k8s.io/kubernetes@v1.29.3/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go (about) 1 /* 2 Copyright 2015 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 "github.com/google/go-cmp/cmp" 23 apiequality "k8s.io/apimachinery/pkg/api/equality" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/kubernetes/pkg/apis/autoscaling" 26 api "k8s.io/kubernetes/pkg/apis/core" 27 28 // Ensure that autoscaling/v1 package is initialized. 29 _ "k8s.io/api/autoscaling/v1" 30 "k8s.io/apimachinery/pkg/fields" 31 "k8s.io/apimachinery/pkg/labels" 32 "k8s.io/apimachinery/pkg/runtime" 33 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 34 "k8s.io/apiserver/pkg/registry/generic" 35 genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" 36 "k8s.io/apiserver/pkg/registry/rest" 37 etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" 38 "k8s.io/kubernetes/pkg/registry/registrytest" 39 ) 40 41 func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) { 42 etcdStorage, server := registrytest.NewEtcdStorage(t, autoscaling.GroupName) 43 restOptions := generic.RESTOptions{ 44 StorageConfig: etcdStorage, 45 Decorator: generic.UndecoratedStorage, 46 DeleteCollectionWorkers: 1, 47 ResourcePrefix: "horizontalpodautoscalers", 48 } 49 horizontalPodAutoscalerStorage, statusStorage, err := NewREST(restOptions) 50 if err != nil { 51 t.Fatalf("unexpected error from REST storage: %v", err) 52 } 53 return horizontalPodAutoscalerStorage, statusStorage, server 54 } 55 56 func validNewHorizontalPodAutoscaler(name string) *autoscaling.HorizontalPodAutoscaler { 57 cpu := int32(70) 58 return &autoscaling.HorizontalPodAutoscaler{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: name, 61 Namespace: metav1.NamespaceDefault, 62 }, 63 Spec: autoscaling.HorizontalPodAutoscalerSpec{ 64 ScaleTargetRef: autoscaling.CrossVersionObjectReference{ 65 Kind: "ReplicationController", 66 Name: "myrc", 67 }, 68 MaxReplicas: 5, 69 Metrics: []autoscaling.MetricSpec{ 70 { 71 Type: autoscaling.ResourceMetricSourceType, 72 Resource: &autoscaling.ResourceMetricSource{ 73 Name: api.ResourceCPU, 74 Target: autoscaling.MetricTarget{ 75 Type: autoscaling.UtilizationMetricType, 76 AverageUtilization: &cpu, 77 }, 78 }, 79 }, 80 }, 81 }, 82 } 83 } 84 85 func TestCreate(t *testing.T) { 86 storage, _, server := newStorage(t) 87 defer server.Terminate(t) 88 defer storage.Store.DestroyFunc() 89 test := genericregistrytest.New(t, storage.Store) 90 autoscaler := validNewHorizontalPodAutoscaler("foo") 91 autoscaler.ObjectMeta = metav1.ObjectMeta{} 92 test.TestCreate( 93 // valid 94 autoscaler, 95 // invalid 96 &autoscaling.HorizontalPodAutoscaler{}, 97 ) 98 } 99 100 func TestUpdate(t *testing.T) { 101 storage, _, server := newStorage(t) 102 defer server.Terminate(t) 103 defer storage.Store.DestroyFunc() 104 test := genericregistrytest.New(t, storage.Store) 105 test.TestUpdate( 106 // valid 107 validNewHorizontalPodAutoscaler("foo"), 108 // updateFunc 109 func(obj runtime.Object) runtime.Object { 110 object := obj.(*autoscaling.HorizontalPodAutoscaler) 111 object.Spec.MaxReplicas = object.Spec.MaxReplicas + 1 112 return object 113 }, 114 ) 115 } 116 117 func TestDelete(t *testing.T) { 118 storage, _, server := newStorage(t) 119 defer server.Terminate(t) 120 defer storage.Store.DestroyFunc() 121 test := genericregistrytest.New(t, storage.Store) 122 test.TestDelete(validNewHorizontalPodAutoscaler("foo")) 123 } 124 125 func TestGet(t *testing.T) { 126 storage, _, server := newStorage(t) 127 defer server.Terminate(t) 128 defer storage.Store.DestroyFunc() 129 test := genericregistrytest.New(t, storage.Store) 130 test.TestGet(validNewHorizontalPodAutoscaler("foo")) 131 } 132 133 func TestList(t *testing.T) { 134 storage, _, server := newStorage(t) 135 defer server.Terminate(t) 136 defer storage.Store.DestroyFunc() 137 test := genericregistrytest.New(t, storage.Store) 138 test.TestList(validNewHorizontalPodAutoscaler("foo")) 139 } 140 141 func TestWatch(t *testing.T) { 142 storage, _, server := newStorage(t) 143 defer server.Terminate(t) 144 defer storage.Store.DestroyFunc() 145 test := genericregistrytest.New(t, storage.Store) 146 test.TestWatch( 147 validNewHorizontalPodAutoscaler("foo"), 148 // matching labels 149 []labels.Set{}, 150 // not matching labels 151 []labels.Set{ 152 {"foo": "bar"}, 153 }, 154 // matching fields 155 []fields.Set{}, 156 // not matching fields 157 []fields.Set{ 158 {"metadata.name": "bar"}, 159 {"name": "foo"}, 160 }, 161 ) 162 } 163 164 func TestShortNames(t *testing.T) { 165 storage, _, server := newStorage(t) 166 defer server.Terminate(t) 167 defer storage.Store.DestroyFunc() 168 expected := []string{"hpa"} 169 registrytest.AssertShortNames(t, storage, expected) 170 } 171 172 func TestCategories(t *testing.T) { 173 storage, _, server := newStorage(t) 174 defer server.Terminate(t) 175 defer storage.Store.DestroyFunc() 176 expected := []string{"all"} 177 registrytest.AssertCategories(t, storage, expected) 178 } 179 180 func TestUpdateStatus(t *testing.T) { 181 storage, statusStorage, server := newStorage(t) 182 defer server.Terminate(t) 183 defer storage.Store.DestroyFunc() 184 ctx := genericapirequest.NewDefaultContext() 185 key, _ := storage.KeyFunc(ctx, "foo") 186 autoscalerStart := validNewHorizontalPodAutoscaler("foo") 187 err := storage.Storage.Create(ctx, key, autoscalerStart, nil, 0, false) 188 if err != nil { 189 t.Errorf("unexpected error: %v", err) 190 } 191 192 autoscalerIn := &autoscaling.HorizontalPodAutoscaler{ 193 ObjectMeta: metav1.ObjectMeta{ 194 Name: "foo", 195 Namespace: metav1.NamespaceDefault, 196 }, 197 Status: autoscaling.HorizontalPodAutoscalerStatus{ 198 Conditions: []autoscaling.HorizontalPodAutoscalerCondition{ 199 {Status: "True"}, 200 }, 201 }, 202 } 203 204 _, _, err = statusStorage.Update(ctx, autoscalerIn.Name, rest.DefaultUpdatedObjectInfo(autoscalerIn), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}) 205 if err != nil { 206 t.Fatalf("Unexpected error: %v", err) 207 } 208 obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 209 if err != nil { 210 t.Fatalf("Unexpected error: %v", err) 211 } 212 autoscalerOut := obj.(*autoscaling.HorizontalPodAutoscaler) 213 // only compare the meaningful update b/c we can't compare due to metadata 214 if !apiequality.Semantic.DeepEqual(autoscalerIn.Status, autoscalerOut.Status) { 215 t.Errorf("unexpected object: %s", cmp.Diff(autoscalerIn, autoscalerOut)) 216 } 217 }