k8s.io/kubernetes@v1.29.3/pkg/registry/apps/controllerrevision/strategy_test.go (about) 1 /* 2 Copyright 2017 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 controllerrevision 18 19 import ( 20 "testing" 21 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 "k8s.io/apimachinery/pkg/runtime" 24 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 25 "k8s.io/kubernetes/pkg/apis/apps" 26 api "k8s.io/kubernetes/pkg/apis/core" 27 ) 28 29 func TestStrategy_NamespaceScoped(t *testing.T) { 30 if !Strategy.NamespaceScoped() { 31 t.Error("ControllerRevision strategy must be namespace scoped") 32 } 33 } 34 35 func TestStrategy_AllowCreateOnUpdate(t *testing.T) { 36 if Strategy.AllowCreateOnUpdate() { 37 t.Error("ControllerRevision should not be created on update") 38 } 39 } 40 41 func TestStrategy_Validate(t *testing.T) { 42 ctx := genericapirequest.NewDefaultContext() 43 var ( 44 valid = newControllerRevision("validname", "validns", newObject(), 0) 45 badRevision = newControllerRevision("validname", "validns", newObject(), -1) 46 emptyName = newControllerRevision("", "validns", newObject(), 0) 47 invalidName = newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", newObject(), 0) 48 emptyNs = newControllerRevision("validname", "", newObject(), 100) 49 invalidNs = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", newObject(), 100) 50 nilData = newControllerRevision("validname", "validns", nil, 0) 51 ) 52 53 tests := map[string]struct { 54 history *apps.ControllerRevision 55 isValid bool 56 }{ 57 "valid": {valid, true}, 58 "negative revision": {badRevision, false}, 59 "empty name": {emptyName, false}, 60 "invalid name": {invalidName, false}, 61 "empty namespace": {emptyNs, false}, 62 "invalid namespace": {invalidNs, false}, 63 "nil data": {nilData, false}, 64 } 65 66 for name, tc := range tests { 67 errs := Strategy.Validate(ctx, tc.history) 68 if tc.isValid && len(errs) > 0 { 69 t.Errorf("%v: unexpected error: %v", name, errs) 70 } 71 if !tc.isValid && len(errs) == 0 { 72 t.Errorf("%v: unexpected non-error", name) 73 } 74 } 75 } 76 77 func TestStrategy_ValidateUpdate(t *testing.T) { 78 ctx := genericapirequest.NewDefaultContext() 79 var ( 80 valid = newControllerRevision("validname", "validns", newObject(), 0) 81 changedData = newControllerRevision("validname", "validns", 82 func() runtime.Object { 83 modified := newObject() 84 ss := modified.(*apps.StatefulSet) 85 ss.Name = "cde" 86 return modified 87 }(), 0) 88 changedRevision = newControllerRevision("validname", "validns", newObject(), 1) 89 ) 90 91 cases := []struct { 92 name string 93 newHistory *apps.ControllerRevision 94 oldHistory *apps.ControllerRevision 95 isValid bool 96 }{ 97 { 98 name: "valid", 99 newHistory: valid, 100 oldHistory: valid, 101 isValid: true, 102 }, 103 { 104 name: "changed data", 105 newHistory: changedData, 106 oldHistory: valid, 107 isValid: false, 108 }, 109 { 110 name: "changed revision", 111 newHistory: changedRevision, 112 oldHistory: valid, 113 isValid: true, 114 }, 115 } 116 117 for _, tc := range cases { 118 errs := Strategy.ValidateUpdate(ctx, tc.newHistory, tc.oldHistory) 119 if tc.isValid && len(errs) > 0 { 120 t.Errorf("%v: unexpected error: %v", tc.name, errs) 121 } 122 if !tc.isValid && len(errs) == 0 { 123 t.Errorf("%v: unexpected non-error", tc.name) 124 } 125 } 126 } 127 128 func newControllerRevision(name, namespace string, data runtime.Object, revision int64) *apps.ControllerRevision { 129 return &apps.ControllerRevision{ 130 ObjectMeta: metav1.ObjectMeta{ 131 Name: name, 132 Namespace: namespace, 133 ResourceVersion: "1", 134 Labels: map[string]string{"foo": "bar"}, 135 }, 136 Data: data, 137 Revision: revision, 138 } 139 } 140 141 func newObject() runtime.Object { 142 return &apps.StatefulSet{ 143 ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, 144 Spec: apps.StatefulSetSpec{ 145 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, 146 Template: api.PodTemplateSpec{ 147 Spec: api.PodSpec{ 148 RestartPolicy: api.RestartPolicyAlways, 149 DNSPolicy: api.DNSClusterFirst, 150 }, 151 ObjectMeta: metav1.ObjectMeta{ 152 Labels: map[string]string{"foo": "bar"}, 153 }, 154 }, 155 }, 156 } 157 }