diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 3b6d275d0ef..6b09aca1aad 100644 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -66,6 +66,7 @@ static="static" storageclass="storageclass" subjectaccessreviews="subjectaccessreviews" thirdpartyresources="thirdpartyresources" +daemonsets="daemonsets" # Stops the running kubectl proxy, if there is one. @@ -2628,6 +2629,22 @@ run_rs_tests() { fi } +run_daemonset_tests() { + kube::log::status "Testing kubectl(v1:daemonsets)" + + ### Create a rolling update DaemonSet + # Pre-condition: no DaemonSet exists + kube::test::get_object_assert daemonsets "{{range.items}}{{$id_field}}:{{end}}" '' + # Command + kubectl apply -f hack/testdata/rollingupdate-daemonset.yaml "${kube_flags[@]}" + # Template Generation should be 1 + kube::test::get_object_assert 'daemonsets bind' "{{${template_generation_field}}}" '1' + kubectl apply -f hack/testdata/rollingupdate-daemonset.yaml "${kube_flags[@]}" + # Template Generation should stay 1 + kube::test::get_object_assert 'daemonsets bind' "{{${template_generation_field}}}" '1' + kubectl delete -f hack/testdata/rollingupdate-daemonset.yaml "${kube_flags[@]}" +} + run_multi_resources_tests() { kube::log::status "Testing kubectl(v1:multiple resources)" @@ -2852,6 +2869,7 @@ runTests() { deployment_second_image_field="(index .spec.template.spec.containers 1).image" change_cause_annotation='.*kubernetes.io/change-cause.*' pdb_min_available=".spec.minAvailable" + template_generation_field=".spec.templateGeneration" # Make sure "default" namespace exists. if kube::test::if_supports_resource "${namespaces}" ; then @@ -3239,6 +3257,14 @@ runTests() { fi + ################## + # DaemonSets # + ################## + + if kube::test::if_supports_resource "${daemonsets}" ; then + run_daemonset_tests + fi + ########################### # Replication controllers # ########################### diff --git a/hack/testdata/rollingupdate-daemonset.yaml b/hack/testdata/rollingupdate-daemonset.yaml new file mode 100644 index 00000000000..c8a9cdca21d --- /dev/null +++ b/hack/testdata/rollingupdate-daemonset.yaml @@ -0,0 +1,27 @@ +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: bind +spec: + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 10% + template: + metadata: + labels: + service: bind + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "service" + operator: "In" + values: ["bind"] + topologyKey: "kubernetes.io/hostname" + namespaces: [] + containers: + - name: kubernetes-pause + image: gcr.io/google-containers/pause:2.0 diff --git a/pkg/apis/extensions/validation/validation_test.go b/pkg/apis/extensions/validation/validation_test.go index 4bf65cd71cd..6bfe9beba89 100644 --- a/pkg/apis/extensions/validation/validation_test.go +++ b/pkg/apis/extensions/validation/validation_test.go @@ -444,6 +444,15 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: validPodSpecAbc, }, } + validPodTemplateAbcSemanticallyEqual := api.PodTemplate{ + Template: api.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: validSelector, + }, + Spec: validPodSpecAbc, + }, + } + validPodTemplateAbcSemanticallyEqual.Template.Spec.ImagePullSecrets = []api.LocalObjectReference{} validPodTemplateNodeSelector := api.PodTemplate{ Template: api.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -618,6 +627,33 @@ func TestValidateDaemonSetUpdate(t *testing.T) { }, }, }, + "unchanged templateGeneration upon semantically equal template update": { + old: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: validSelector}, + TemplateGeneration: 4, + Template: validPodTemplateAbc.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, + }, + }, + update: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: validSelector}, + TemplateGeneration: 4, + Template: validPodTemplateAbcSemanticallyEqual.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.RollingUpdateDaemonSetStrategyType, + RollingUpdate: &extensions.RollingUpdateDaemonSet{ + MaxUnavailable: intstr.FromInt(1), + }, + }, + }, + }, + }, } for testName, successCase := range successCases { // ResourceVersion is required for updates.