@@ -17,14 +17,17 @@ limitations under the License.
1717package disruption
1818
1919import (
20+ "bytes"
2021 "context"
2122 "fmt"
23+ "path"
2224 "reflect"
2325 "testing"
2426 "time"
2527
2628 "github.com/google/go-cmp/cmp"
2729 "github.com/google/go-cmp/cmp/cmpopts"
30+ clientv3 "go.etcd.io/etcd/client/v3"
2831 v1 "k8s.io/api/core/v1"
2932 policyv1 "k8s.io/api/policy/v1"
3033 "k8s.io/api/policy/v1beta1"
@@ -34,9 +37,12 @@ import (
3437 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3538 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3639 "k8s.io/apimachinery/pkg/runtime/schema"
40+ "k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
3741 "k8s.io/apimachinery/pkg/types"
3842 "k8s.io/apimachinery/pkg/util/intstr"
3943 "k8s.io/apimachinery/pkg/util/wait"
44+ genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
45+ "k8s.io/apiserver/pkg/registry/rest"
4046 cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
4147 "k8s.io/client-go/dynamic"
4248 "k8s.io/client-go/informers"
@@ -46,6 +52,7 @@ import (
4652 "k8s.io/client-go/scale"
4753 "k8s.io/client-go/tools/cache"
4854 kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
55+ "k8s.io/kubernetes/pkg/api/legacyscheme"
4956 "k8s.io/kubernetes/pkg/controller/disruption"
5057 "k8s.io/kubernetes/test/integration/etcd"
5158 "k8s.io/kubernetes/test/integration/framework"
@@ -201,12 +208,12 @@ func TestPDBWithScaleSubresource(t *testing.T) {
201208func TestEmptySelector (t * testing.T ) {
202209 testcases := []struct {
203210 name string
204- createPDBFunc func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error
211+ createPDBFunc func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error
205212 expectedCurrentHealthy int32
206213 }{
207214 {
208215 name : "v1beta1 should not target any pods" ,
209- createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error {
216+ createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error {
210217 pdb := & v1beta1.PodDisruptionBudget {
211218 ObjectMeta : metav1.ObjectMeta {
212219 Name : name ,
@@ -216,14 +223,13 @@ func TestEmptySelector(t *testing.T) {
216223 Selector : & metav1.LabelSelector {},
217224 },
218225 }
219- _ , err := clientSet .PolicyV1beta1 ().PodDisruptionBudgets (nsName ).Create (ctx , pdb , metav1.CreateOptions {})
220- return err
226+ return createPDBUsingRemovedAPI (ctx , etcdClient , etcdStoragePrefix , nsName , pdb )
221227 },
222228 expectedCurrentHealthy : 0 ,
223229 },
224230 {
225231 name : "v1 should target all pods" ,
226- createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error {
232+ createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error {
227233 pdb := & policyv1.PodDisruptionBudget {
228234 ObjectMeta : metav1.ObjectMeta {
229235 Name : name ,
@@ -266,7 +272,7 @@ func TestEmptySelector(t *testing.T) {
266272 waitToObservePods (t , informers .Core ().V1 ().Pods ().Informer (), 4 , v1 .PodRunning )
267273
268274 pdbName := "test-pdb"
269- if err := tc .createPDBFunc (ctx , clientSet , pdbName , nsName , minAvailable ); err != nil {
275+ if err := tc .createPDBFunc (ctx , clientSet , s . EtcdClient , s . EtcdStoragePrefix , pdbName , nsName , minAvailable ); err != nil {
270276 t .Errorf ("Error creating PodDisruptionBudget: %v" , err )
271277 }
272278
@@ -287,12 +293,12 @@ func TestEmptySelector(t *testing.T) {
287293func TestSelectorsForPodsWithoutLabels (t * testing.T ) {
288294 testcases := []struct {
289295 name string
290- createPDBFunc func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error
296+ createPDBFunc func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error
291297 expectedCurrentHealthy int32
292298 }{
293299 {
294300 name : "pods with no labels can be targeted by v1 PDBs with empty selector" ,
295- createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error {
301+ createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error {
296302 pdb := & policyv1.PodDisruptionBudget {
297303 ObjectMeta : metav1.ObjectMeta {
298304 Name : name ,
@@ -309,7 +315,7 @@ func TestSelectorsForPodsWithoutLabels(t *testing.T) {
309315 },
310316 {
311317 name : "pods with no labels can be targeted by v1 PDBs with DoesNotExist selector" ,
312- createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error {
318+ createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error {
313319 pdb := & policyv1.PodDisruptionBudget {
314320 ObjectMeta : metav1.ObjectMeta {
315321 Name : name ,
@@ -333,7 +339,7 @@ func TestSelectorsForPodsWithoutLabels(t *testing.T) {
333339 },
334340 {
335341 name : "pods with no labels can be targeted by v1beta1 PDBs with DoesNotExist selector" ,
336- createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , name , nsName string , minAvailable intstr.IntOrString ) error {
342+ createPDBFunc : func (ctx context.Context , clientSet clientset.Interface , etcdClient * clientv3. Client , etcdStoragePrefix , name , nsName string , minAvailable intstr.IntOrString ) error {
337343 pdb := & v1beta1.PodDisruptionBudget {
338344 ObjectMeta : metav1.ObjectMeta {
339345 Name : name ,
@@ -350,8 +356,7 @@ func TestSelectorsForPodsWithoutLabels(t *testing.T) {
350356 },
351357 },
352358 }
353- _ , err := clientSet .PolicyV1beta1 ().PodDisruptionBudgets (nsName ).Create (ctx , pdb , metav1.CreateOptions {})
354- return err
359+ return createPDBUsingRemovedAPI (ctx , etcdClient , etcdStoragePrefix , nsName , pdb )
355360 },
356361 expectedCurrentHealthy : 1 ,
357362 },
@@ -376,7 +381,7 @@ func TestSelectorsForPodsWithoutLabels(t *testing.T) {
376381
377382 // Create the PDB first and wait for it to settle.
378383 pdbName := "test-pdb"
379- if err := tc .createPDBFunc (ctx , clientSet , pdbName , nsName , minAvailable ); err != nil {
384+ if err := tc .createPDBFunc (ctx , clientSet , s . EtcdClient , s . EtcdStoragePrefix , pdbName , nsName , minAvailable ); err != nil {
380385 t .Errorf ("Error creating PodDisruptionBudget: %v" , err )
381386 }
382387 waitPDBStable (ctx , t , clientSet , 0 , nsName , pdbName )
@@ -513,6 +518,26 @@ func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podN
513518 }
514519}
515520
521+ // createPDBUsingRemovedAPI creates a PDB directly using etcd. This is must *ONLY* be used for checks of compatibility
522+ // with removed data. Do not use this just because you don't want to update your test to use v1. Only use this
523+ // when it actually matters.
524+ func createPDBUsingRemovedAPI (ctx context.Context , etcdClient * clientv3.Client , etcdStoragePrefix , nsName string , betaPDB * v1beta1.PodDisruptionBudget ) error {
525+ betaPDB .APIVersion = v1beta1 .SchemeGroupVersion .Group + "/" + v1beta1 .SchemeGroupVersion .Version
526+ betaPDB .Kind = "PodDisruptionBudget"
527+ betaPDB .Namespace = nsName
528+ betaPDB .Generation = 1
529+ rest .FillObjectMetaSystemFields (betaPDB )
530+ ctx = genericapirequest .WithNamespace (ctx , nsName )
531+ key := path .Join ("/" , etcdStoragePrefix , "poddisruptionbudgets" , nsName , betaPDB .Name )
532+ protoSerializer := protobuf .NewSerializer (legacyscheme .Scheme , legacyscheme .Scheme )
533+ buffer := bytes .NewBuffer (nil )
534+ if err := protoSerializer .Encode (betaPDB , buffer ); err != nil {
535+ return err
536+ }
537+ _ , err := etcdClient .Put (ctx , key , buffer .String ())
538+ return err
539+ }
540+
516541func TestPatchCompatibility (t * testing.T ) {
517542 ctx , cancel := context .WithCancel (context .Background ())
518543
@@ -533,17 +558,6 @@ func TestPatchCompatibility(t *testing.T) {
533558 fieldManager string
534559 expectSelector * metav1.LabelSelector
535560 }{
536- {
537- name : "v1beta1-smp" ,
538- version : "v1beta1" ,
539- patchType : types .StrategicMergePatchType ,
540- patch : `{"spec":{"selector":{"matchLabels":{"patchmatch":"true"},"matchExpressions":[{"key":"patchexpression","operator":"In","values":["true"]}]}}}` ,
541- // matchLabels portion is merged, matchExpressions portion is replaced (because it's a list with no patchStrategy defined)
542- expectSelector : & metav1.LabelSelector {
543- MatchLabels : map [string ]string {"basematch" : "true" , "patchmatch" : "true" },
544- MatchExpressions : []metav1.LabelSelectorRequirement {{Key : "patchexpression" , Operator : "In" , Values : []string {"true" }}},
545- },
546- },
547561 {
548562 name : "v1-smp" ,
549563 version : "v1" ,
@@ -555,18 +569,6 @@ func TestPatchCompatibility(t *testing.T) {
555569 MatchExpressions : []metav1.LabelSelectorRequirement {{Key : "patchexpression" , Operator : "In" , Values : []string {"true" }}},
556570 },
557571 },
558-
559- {
560- name : "v1beta1-mergepatch" ,
561- version : "v1beta1" ,
562- patchType : types .MergePatchType ,
563- patch : `{"spec":{"selector":{"matchLabels":{"patchmatch":"true"},"matchExpressions":[{"key":"patchexpression","operator":"In","values":["true"]}]}}}` ,
564- // matchLabels portion is merged, matchExpressions portion is replaced (because it's a list)
565- expectSelector : & metav1.LabelSelector {
566- MatchLabels : map [string ]string {"basematch" : "true" , "patchmatch" : "true" },
567- MatchExpressions : []metav1.LabelSelectorRequirement {{Key : "patchexpression" , Operator : "In" , Values : []string {"true" }}},
568- },
569- },
570572 {
571573 name : "v1-mergepatch" ,
572574 version : "v1" ,
@@ -578,20 +580,6 @@ func TestPatchCompatibility(t *testing.T) {
578580 MatchExpressions : []metav1.LabelSelectorRequirement {{Key : "patchexpression" , Operator : "In" , Values : []string {"true" }}},
579581 },
580582 },
581-
582- {
583- name : "v1beta1-apply" ,
584- version : "v1beta1" ,
585- patchType : types .ApplyPatchType ,
586- patch : `{"apiVersion":"policy/v1beta1","kind":"PodDisruptionBudget","spec":{"selector":{"matchLabels":{"patchmatch":"true"},"matchExpressions":[{"key":"patchexpression","operator":"In","values":["true"]}]}}}` ,
587- force : pointer .Bool (true ),
588- fieldManager : "test" ,
589- // entire selector is replaced (because structType=atomic)
590- expectSelector : & metav1.LabelSelector {
591- MatchLabels : map [string ]string {"patchmatch" : "true" },
592- MatchExpressions : []metav1.LabelSelectorRequirement {{Key : "patchexpression" , Operator : "In" , Values : []string {"true" }}},
593- },
594- },
595583 {
596584 name : "v1-apply" ,
597585 version : "v1" ,
@@ -641,12 +629,6 @@ func TestPatchCompatibility(t *testing.T) {
641629 t .Fatal (err )
642630 }
643631 resultSelector = result .Spec .Selector
644- case "v1beta1" :
645- result , err := clientSet .PolicyV1beta1 ().PodDisruptionBudgets (ns ).Patch (context .TODO (), pdb .Name , tc .patchType , []byte (tc .patch ), metav1.PatchOptions {Force : tc .force , FieldManager : tc .fieldManager })
646- if err != nil {
647- t .Fatal (err )
648- }
649- resultSelector = result .Spec .Selector
650632 default :
651633 t .Error ("unknown version" )
652634 }
0 commit comments