k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/registry/policy/poddisruptionbudget/storage/storage_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package storage 18 19 import ( 20 "testing" 21 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 "k8s.io/apimachinery/pkg/fields" 24 "k8s.io/apimachinery/pkg/labels" 25 "k8s.io/apimachinery/pkg/util/intstr" 26 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 27 "k8s.io/apiserver/pkg/registry/generic" 28 genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" 29 "k8s.io/apiserver/pkg/registry/rest" 30 etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" 31 "k8s.io/kubernetes/pkg/apis/policy" 32 "k8s.io/kubernetes/pkg/registry/registrytest" 33 ) 34 35 func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) { 36 etcdStorage, server := registrytest.NewEtcdStorage(t, policy.GroupName) 37 restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "poddisruptionbudgets"} 38 podDisruptionBudgetStorage, statusStorage, err := NewREST(restOptions) 39 if err != nil { 40 t.Fatalf("unexpected error from REST storage: %v", err) 41 } 42 return podDisruptionBudgetStorage, statusStorage, server 43 } 44 45 func validNewPodDisruptionBudget() *policy.PodDisruptionBudget { 46 minAvailable := intstr.FromInt32(7) 47 return &policy.PodDisruptionBudget{ 48 ObjectMeta: metav1.ObjectMeta{ 49 Name: "foo", 50 Namespace: metav1.NamespaceDefault, 51 Labels: map[string]string{"a": "b"}, 52 }, 53 Spec: policy.PodDisruptionBudgetSpec{ 54 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}}, 55 MinAvailable: &minAvailable, 56 }, 57 Status: policy.PodDisruptionBudgetStatus{}, 58 } 59 } 60 61 func TestCreate(t *testing.T) { 62 storage, _, server := newStorage(t) 63 defer server.Terminate(t) 64 defer storage.Store.DestroyFunc() 65 test := genericregistrytest.New(t, storage.Store) 66 pdb := validNewPodDisruptionBudget() 67 pdb.ObjectMeta = metav1.ObjectMeta{} 68 test.TestCreate( 69 // valid 70 pdb, 71 // TODO: Add an invalid case when we have validation. 72 ) 73 } 74 75 // TODO: Test updates to spec when we allow them. 76 77 func TestStatusUpdate(t *testing.T) { 78 storage, statusStorage, server := newStorage(t) 79 defer server.Terminate(t) 80 defer storage.Store.DestroyFunc() 81 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) 82 key := "/poddisruptionbudgets/" + metav1.NamespaceDefault + "/foo" 83 validPodDisruptionBudget := validNewPodDisruptionBudget() 84 if err := storage.Storage.Create(ctx, key, validPodDisruptionBudget, nil, 0, false); err != nil { 85 t.Fatalf("unexpected error: %v", err) 86 } 87 88 obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 89 if err != nil { 90 t.Fatalf("failed to get pdb: %v", err) 91 } 92 obtainedPdb := obj.(*policy.PodDisruptionBudget) 93 94 minAvailable := intstr.FromInt32(8) 95 update := policy.PodDisruptionBudget{ 96 ObjectMeta: obtainedPdb.ObjectMeta, 97 Spec: policy.PodDisruptionBudgetSpec{ 98 MinAvailable: &minAvailable, 99 }, 100 Status: policy.PodDisruptionBudgetStatus{ 101 ExpectedPods: 8, 102 }, 103 } 104 105 if _, _, err := statusStorage.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 106 t.Fatalf("unexpected error: %v", err) 107 } 108 obj, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 109 if err != nil { 110 t.Fatalf("unexpected error: %v", err) 111 } 112 113 pdb := obj.(*policy.PodDisruptionBudget) 114 if pdb.Spec.MinAvailable.IntValue() != 7 { 115 t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", pdb.Spec.MinAvailable) 116 } 117 if pdb.Status.ExpectedPods != 8 { 118 t.Errorf("we expected .status.replicas to be updated to %d but it was %v", 7, pdb.Status.ExpectedPods) 119 } 120 } 121 122 func TestGet(t *testing.T) { 123 storage, _, server := newStorage(t) 124 defer server.Terminate(t) 125 defer storage.Store.DestroyFunc() 126 test := genericregistrytest.New(t, storage.Store) 127 test.TestGet(validNewPodDisruptionBudget()) 128 } 129 130 func TestList(t *testing.T) { 131 storage, _, server := newStorage(t) 132 defer server.Terminate(t) 133 defer storage.Store.DestroyFunc() 134 test := genericregistrytest.New(t, storage.Store) 135 test.TestList(validNewPodDisruptionBudget()) 136 } 137 138 func TestDelete(t *testing.T) { 139 storage, _, server := newStorage(t) 140 defer server.Terminate(t) 141 defer storage.Store.DestroyFunc() 142 test := genericregistrytest.New(t, storage.Store) 143 test.TestDelete(validNewPodDisruptionBudget()) 144 } 145 146 func TestWatch(t *testing.T) { 147 storage, _, server := newStorage(t) 148 defer server.Terminate(t) 149 defer storage.Store.DestroyFunc() 150 test := genericregistrytest.New(t, storage.Store) 151 test.TestWatch( 152 validNewPodDisruptionBudget(), 153 // matching labels 154 []labels.Set{ 155 {"a": "b"}, 156 }, 157 // not matching labels 158 []labels.Set{ 159 {"a": "c"}, 160 {"foo": "bar"}, 161 }, 162 163 // matching fields 164 []fields.Set{ 165 {"metadata.name": "foo"}, 166 }, 167 // not matching fields 168 []fields.Set{ 169 {"metadata.name": "bar"}, 170 }, 171 ) 172 } 173 174 // TODO: Test generation number.