k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/cmd/diff.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  # Copyright 2018 The Kubernetes Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  set -o errexit
    18  set -o nounset
    19  set -o pipefail
    20  
    21  # Runs tests for kubectl diff
    22  run_kubectl_diff_tests() {
    23      set -o nounset
    24      set -o errexit
    25  
    26      create_and_use_new_namespace
    27      kube::log::status "Testing kubectl diff"
    28  
    29      # Test that it works when the live object doesn't exist
    30      output_message=$(! kubectl diff -f hack/testdata/pod.yaml)
    31      kube::test::if_has_string "${output_message}" 'test-pod'
    32      # Ensure diff only dry-runs and doesn't persist change
    33      kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \"test-pod\" }}found{{end}}{{end}}:" ':'
    34  
    35      kubectl apply -f hack/testdata/pod.yaml
    36      kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \"test-pod\" }}found{{end}}{{end}}:" 'found:'
    37      initialResourceVersion=$(kubectl get "${kube_flags[@]:?}" -f hack/testdata/pod.yaml -o go-template='{{ .metadata.resourceVersion }}')
    38  
    39      # Make sure that diffing the resource right after returns nothing (0 exit code).
    40      kubectl diff -f hack/testdata/pod.yaml
    41  
    42      # Ensure diff only dry-runs and doesn't persist change
    43      resourceVersion=$(kubectl get "${kube_flags[@]:?}" -f hack/testdata/pod.yaml -o go-template='{{ .metadata.resourceVersion }}')
    44      kube::test::if_has_string "${resourceVersion}" "${initialResourceVersion}"
    45  
    46      # Make sure that:
    47      # 1. the exit code for diff is 1 because it found a difference
    48      # 2. the difference contains the changed image
    49      # 3. the output doesn't indicate this is an error
    50      output_message=$(kubectl diff -f hack/testdata/pod-changed.yaml 2>&1 || test $? -eq 1)
    51      kube::test::if_has_string "${output_message}" 'registry.k8s.io/pause:3.4'
    52      kube::test::if_has_not_string "${output_message}" 'exit status 1'
    53  
    54      # Ensure diff only dry-runs and doesn't persist change
    55      resourceVersion=$(kubectl get "${kube_flags[@]:?}" -f hack/testdata/pod.yaml -o go-template='{{ .metadata.resourceVersion }}')
    56      kube::test::if_has_string "${resourceVersion}" "${initialResourceVersion}"
    57  
    58      # Test found diff with server-side apply
    59      output_message=$(kubectl diff -f hack/testdata/pod-changed.yaml --server-side || test $? -eq 1)
    60      kube::test::if_has_string "${output_message}" 'registry.k8s.io/pause:3.4'
    61  
    62      # Ensure diff --server-side only dry-runs and doesn't persist change
    63      resourceVersion=$(kubectl get "${kube_flags[@]:?}" -f hack/testdata/pod.yaml -o go-template='{{ .metadata.resourceVersion }}')
    64      kube::test::if_has_string "${resourceVersion}" "${initialResourceVersion}"
    65  
    66      # Test that we have a return code bigger than 1 if there is an error when diffing
    67      kubectl diff -f hack/testdata/invalid-pod.yaml || test $? -gt 1
    68  
    69      # Cleanup
    70      kubectl delete -f hack/testdata/pod.yaml
    71  
    72      kube::log::status "Testing kubectl diff with server-side apply"
    73  
    74      # Test that kubectl diff --server-side works when the live object doesn't exist
    75      output_message=$(! kubectl diff --server-side -f hack/testdata/pod.yaml)
    76      kube::test::if_has_string "${output_message}" 'test-pod'
    77      # Ensure diff --server-side only dry-runs and doesn't persist change
    78      kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \"test-pod\" }}found{{end}}{{end}}:" ':'
    79  
    80      # Server-side apply the Pod
    81      kubectl apply --server-side -f hack/testdata/pod.yaml
    82      kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \"test-pod\" }}found{{end}}{{end}}:" 'found:'
    83  
    84      # Make sure that --server-side diffing the resource right after returns nothing (0 exit code).
    85      kubectl diff --server-side -f hack/testdata/pod.yaml
    86  
    87      # Make sure that for kubectl diff --server-side:
    88      # 1. the exit code for diff is 1 because it found a difference
    89      # 2. the difference contains the changed image
    90      output_message=$(kubectl diff --server-side -f hack/testdata/pod-changed.yaml || test $? -eq 1)
    91      kube::test::if_has_string "${output_message}" 'registry.k8s.io/pause:3.4'
    92  
    93      ## kubectl diff --prune
    94      kubectl create ns nsb
    95      kubectl apply --namespace nsb -l prune-group=true -f hack/testdata/prune/a.yaml
    96      kube::test::get_object_assert 'pods a -n nsb' "{{${id_field:?}}}" 'a'
    97      # Make sure that kubectl diff does not return pod 'a' without prune flag
    98      output_message=$(kubectl diff -l prune-group=true -f hack/testdata/prune/b.yaml || test $? -eq 1)
    99      kube::test::if_has_not_string "${output_message}" "name: a"
   100      # Make sure that for kubectl diff --prune:
   101      # 1. the exit code for diff is 1 because it found a difference
   102      # 2. the difference contains the pruned pod
   103      output_message=$(kubectl diff --prune -l prune-group=true -f hack/testdata/prune/b.yaml || test $? -eq 1)
   104      # pod 'a' should be in output, it is pruned
   105      kube::test::if_has_string "${output_message}" 'name: a'
   106      # apply b with namespace
   107      kubectl apply --prune --namespace nsb -l prune-group=true -f hack/testdata/prune/b.yaml
   108      # check right pod exists and wrong pod doesn't exist
   109      kube::test::wait_object_assert 'pods -n nsb' "{{range.items}}{{${id_field:?}}}:{{end}}" 'b:'
   110      # Make sure that diff --prune returns nothing (0 exit code) for 'b'.
   111      kubectl diff --prune -l prune-group=true -f hack/testdata/prune/b.yaml
   112  
   113      # Cleanup
   114      kubectl delete -f hack/testdata/pod.yaml
   115      kubectl delete -f hack/testdata/prune/b.yaml
   116      kubectl delete namespace nsb
   117  
   118      ## kubectl diff --prune with label selector
   119      kubectl create ns nsbprune
   120      kubectl apply --namespace nsbprune -f - <<EOF
   121  apiVersion: v1
   122  kind: Pod
   123  metadata:
   124    name: a
   125    namespace: nsbprune
   126    labels:
   127      prune-group: "true"
   128  spec:
   129    containers:
   130    - name: kubernetes-pause
   131      image: registry.k8s.io/pause:3.9
   132  ---
   133  apiVersion: v1
   134  kind: Pod
   135  metadata:
   136    name: b
   137    namespace: nsbprune
   138    labels:
   139      prune-group: "true"
   140  spec:
   141    containers:
   142      - name: kubernetes-pause
   143        image: registry.k8s.io/pause:3.9
   144  ---
   145  apiVersion: v1
   146  kind: Pod
   147  metadata:
   148    name: c
   149    namespace: nsbprune
   150    labels:
   151      prune-group: "false"
   152  spec:
   153    containers:
   154      - name: kubernetes-pause
   155        image: registry.k8s.io/pause:3.9
   156  EOF
   157      kube::test::get_object_assert 'pods a -n nsbprune' "{{${id_field:?}}}" 'a'
   158      kube::test::get_object_assert 'pods b -n nsbprune' "{{${id_field:?}}}" 'b'
   159      kube::test::get_object_assert 'pods c -n nsbprune' "{{${id_field:?}}}" 'c'
   160      # Make sure that kubectl diff does not return either pod 'b' or pod 'c' without prune flag
   161      PRUNE=$(cat <<EOF
   162  apiVersion: v1
   163  kind: Pod
   164  metadata:
   165    name: a
   166    namespace: nsbprune
   167    labels:
   168      prune-group: "true"
   169  spec:
   170    containers:
   171    - name: kubernetes-pause
   172      image: registry.k8s.io/pause:3.9
   173  ---
   174  apiVersion: v1
   175  kind: Pod
   176  metadata:
   177    name: c
   178    namespace: nsbprune
   179    labels:
   180      prune-group: "false"
   181  spec:
   182    containers:
   183      - name: kubernetes-pause
   184        image: registry.k8s.io/pause:3.9
   185  EOF
   186  )
   187      output_message=$(echo "${PRUNE}" | kubectl diff -l prune-group=true -f -)
   188      kube::test::if_has_not_string "${output_message}" "name: b"
   189      kube::test::if_has_not_string "${output_message}" "name: c"
   190      # the exit code for diff is 1 because pod 'b' is found in the given label selector but not 'c'
   191      output_message=$(echo "${PRUNE}" | kubectl diff --prune -l prune-group=true -f - || test $? -eq 1)
   192      # pod 'b' should be in output, it is pruned. On the other hand, 'c' should not be, it's label selector is different
   193      kube::test::if_has_string "${output_message}" 'name: b'
   194      kube::test::if_has_not_string "${output_message}" "name: c"
   195  
   196      # Cleanup
   197      kubectl delete namespace nsbprune
   198  
   199  
   200      set +o nounset
   201      set +o errexit
   202  }
   203  
   204  run_kubectl_diff_same_names() {
   205      set -o nounset
   206      set -o errexit
   207  
   208      create_and_use_new_namespace
   209      kube::log::status "Test kubectl diff with multiple resources with the same name"
   210  
   211      output_message=$(KUBECTL_EXTERNAL_DIFF="find" kubectl diff -Rf hack/testdata/diff/)
   212      kube::test::if_has_string "${output_message}" 'v1\.Pod\..*\.test'
   213      kube::test::if_has_string "${output_message}" 'apps\.v1\.Deployment\..*\.test'
   214      kube::test::if_has_string "${output_message}" 'v1\.ConfigMap\..*\.test'
   215      kube::test::if_has_string "${output_message}" 'v1\.Secret\..*\.test'
   216  
   217      set +o nounset
   218      set +o errexit
   219  }