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  }