k8s.io/kubernetes@v1.29.3/pkg/registry/apps/daemonset/strategy_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 daemonset 18 19 import ( 20 "reflect" 21 "testing" 22 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/util/validation/field" 25 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 26 "k8s.io/kubernetes/pkg/apis/apps" 27 api "k8s.io/kubernetes/pkg/apis/core" 28 ) 29 30 const ( 31 fakeImageName = "fake-name" 32 fakeImage = "fakeimage" 33 daemonsetName = "test-daemonset" 34 namespace = "test-namespace" 35 ) 36 37 func TestSelectorImmutability(t *testing.T) { 38 tests := []struct { 39 requestInfo genericapirequest.RequestInfo 40 oldSelectorLabels map[string]string 41 newSelectorLabels map[string]string 42 expectedErrorList field.ErrorList 43 }{ 44 { 45 genericapirequest.RequestInfo{ 46 APIGroup: "apps", 47 APIVersion: "v1", 48 Resource: "daemonsets", 49 }, 50 map[string]string{"a": "b"}, 51 map[string]string{"c": "d"}, 52 field.ErrorList{ 53 &field.Error{ 54 Type: field.ErrorTypeInvalid, 55 Field: field.NewPath("spec").Child("selector").String(), 56 BadValue: &metav1.LabelSelector{ 57 MatchLabels: map[string]string{"c": "d"}, 58 MatchExpressions: []metav1.LabelSelectorRequirement{}, 59 }, 60 Detail: "field is immutable", 61 }, 62 }, 63 }, 64 { 65 genericapirequest.RequestInfo{ 66 APIGroup: "apps", 67 APIVersion: "v1beta2", 68 Resource: "daemonsets", 69 }, 70 map[string]string{"a": "b"}, 71 map[string]string{"c": "d"}, 72 field.ErrorList{ 73 &field.Error{ 74 Type: field.ErrorTypeInvalid, 75 Field: field.NewPath("spec").Child("selector").String(), 76 BadValue: &metav1.LabelSelector{ 77 MatchLabels: map[string]string{"c": "d"}, 78 MatchExpressions: []metav1.LabelSelectorRequirement{}, 79 }, 80 Detail: "field is immutable", 81 }, 82 }, 83 }, 84 { 85 genericapirequest.RequestInfo{ 86 APIGroup: "extensions", 87 APIVersion: "v1beta1", 88 Resource: "daemonsets", 89 }, 90 map[string]string{"a": "b"}, 91 map[string]string{"c": "d"}, 92 nil, 93 }, 94 } 95 96 for _, test := range tests { 97 oldDaemonSet := newDaemonSetWithSelectorLabels(test.oldSelectorLabels, 1) 98 newDaemonSet := newDaemonSetWithSelectorLabels(test.newSelectorLabels, 2) 99 context := genericapirequest.NewContext() 100 context = genericapirequest.WithRequestInfo(context, &test.requestInfo) 101 errorList := daemonSetStrategy{}.ValidateUpdate(context, newDaemonSet, oldDaemonSet) 102 if !reflect.DeepEqual(test.expectedErrorList, errorList) { 103 t.Errorf("Unexpected error list, expected: %v, actual: %v", test.expectedErrorList, errorList) 104 } 105 } 106 } 107 108 func TestValidateToleratingBadLabels(t *testing.T) { 109 oldObj := newDaemonSetWithSelectorLabels(map[string]string{"a": "b"}, 1) 110 oldObj.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{{Key: "key", Operator: metav1.LabelSelectorOpNotIn, Values: []string{"bad value"}}} 111 newObj := newDaemonSetWithSelectorLabels(map[string]string{"a": "b"}, 1) 112 newObj.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{{Key: "key", Operator: metav1.LabelSelectorOpNotIn, Values: []string{"bad value"}}} 113 114 context := genericapirequest.NewContext() 115 errorList := daemonSetStrategy{}.ValidateUpdate(context, newObj, oldObj) 116 if len(errorList) > 0 { 117 t.Errorf("Unexpected error list with no-op update of bad object: %v", errorList) 118 } 119 } 120 121 func newDaemonSetWithSelectorLabels(selectorLabels map[string]string, templateGeneration int64) *apps.DaemonSet { 122 return &apps.DaemonSet{ 123 ObjectMeta: metav1.ObjectMeta{ 124 Name: daemonsetName, 125 Namespace: namespace, 126 ResourceVersion: "1", 127 }, 128 Spec: apps.DaemonSetSpec{ 129 Selector: &metav1.LabelSelector{ 130 MatchLabels: selectorLabels, 131 MatchExpressions: []metav1.LabelSelectorRequirement{}, 132 }, 133 UpdateStrategy: apps.DaemonSetUpdateStrategy{ 134 Type: apps.OnDeleteDaemonSetStrategyType, 135 }, 136 TemplateGeneration: templateGeneration, 137 Template: api.PodTemplateSpec{ 138 ObjectMeta: metav1.ObjectMeta{ 139 Labels: selectorLabels, 140 }, 141 Spec: api.PodSpec{ 142 RestartPolicy: api.RestartPolicyAlways, 143 DNSPolicy: api.DNSClusterFirst, 144 Containers: []api.Container{{Name: fakeImageName, Image: fakeImage, ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: api.TerminationMessageReadFile}}, 145 }, 146 }, 147 }, 148 } 149 }