diff --git a/hack/.shellcheck_failures b/hack/.shellcheck_failures index 8cab139e4f2..5c2afb9dd5f 100644 --- a/hack/.shellcheck_failures +++ b/hack/.shellcheck_failures @@ -28,11 +28,6 @@ ./hack/update-vendor.sh ./hack/verify-no-vendor-cycles.sh ./hack/verify-test-featuregates.sh -./test/cmd/batch.sh -./test/cmd/certificate.sh -./test/cmd/core.sh -./test/cmd/crd.sh -./test/cmd/create.sh ./test/cmd/diff.sh ./test/cmd/discovery.sh ./test/cmd/generic-resources.sh diff --git a/test/cmd/batch.sh b/test/cmd/batch.sh index 5b50848a7b4..5b4ba2b0a42 100755 --- a/test/cmd/batch.sh +++ b/test/cmd/batch.sh @@ -27,14 +27,14 @@ run_job_tests() { ### Create a new namespace # Pre-condition: the test-jobs namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-jobs\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"${id_field:?}"' \"test-jobs\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace test-jobs # Post-condition: namespace 'test-jobs' is created. kube::test::get_object_assert 'namespaces/test-jobs' "{{$id_field}}" 'test-jobs' ### Create a cronjob in a specific namespace - kubectl run pi --schedule="59 23 31 2 *" --namespace=test-jobs --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" + kubectl run pi --schedule="59 23 31 2 *" --namespace=test-jobs --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]:?}" # Post-Condition: assertion object exists kube::test::get_object_assert 'cronjob/pi --namespace=test-jobs' "{{$id_field}}" 'pi' kubectl get cronjob/pi --namespace=test-jobs diff --git a/test/cmd/certificate.sh b/test/cmd/certificate.sh index 443b00e10b4..d09958f939e 100755 --- a/test/cmd/certificate.sh +++ b/test/cmd/certificate.sh @@ -25,13 +25,13 @@ run_certificates_tests() { kube::log::status "Testing certificates" # approve - kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" + kubectl create -f hack/testdata/csr.yml "${kube_flags[@]:?}" kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' kubectl certificate approve foo "${kube_flags[@]}" kubectl get csr "${kube_flags[@]}" -o json kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' 'Approved' kubectl delete -f hack/testdata/csr.yml "${kube_flags[@]}" - kube::test::get_object_assert csr "{{range.items}}{{$id_field}}{{end}}" '' + kube::test::get_object_assert csr "{{range.items}}{{${id_field:?}}}{{end}}" '' kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' diff --git a/test/cmd/core.sh b/test/cmd/core.sh index 7b551f7b18d..4878e7dd639 100755 --- a/test/cmd/core.sh +++ b/test/cmd/core.sh @@ -25,12 +25,12 @@ run_configmap_tests() { create_and_use_new_namespace kube::log::status "Testing configmaps" kubectl create -f test/fixtures/doc-yaml/user-guide/configmap/configmap.yaml - kube::test::get_object_assert 'configmap/test-configmap' "{{$id_field}}" 'test-configmap' - kubectl delete configmap test-configmap "${kube_flags[@]}" + kube::test::get_object_assert 'configmap/test-configmap' "{{${id_field:?}}}" 'test-configmap' + kubectl delete configmap test-configmap "${kube_flags[@]:?}" ### Create a new namespace # Pre-condition: the test-configmaps namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-configmaps\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"$id_field"' \"test-configmaps\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace test-configmaps # Post-condition: namespace 'test-configmaps' is created. @@ -38,8 +38,8 @@ run_configmap_tests() { ### Create a generic configmap in a specific namespace # Pre-condition: configmap test-configmap and test-binary-configmap does not exist - kube::test::get_object_assert 'configmaps' '{{range.items}}{{ if eq $id_field \"test-configmap\" }}found{{end}}{{end}}:' ':' - kube::test::get_object_assert 'configmaps' '{{range.items}}{{ if eq $id_field \"test-binary-configmap\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'configmaps' '{{range.items}}{{ if eq '"$id_field"' \"test-configmap\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'configmaps' '{{range.items}}{{ if eq '"$id_field"' \"test-binary-configmap\" }}found{{end}}{{end}}:' ':' # Command kubectl create configmap test-configmap --from-literal=key1=value1 --namespace=test-configmaps @@ -47,8 +47,8 @@ run_configmap_tests() { # Post-condition: configmap exists and has expected values kube::test::get_object_assert 'configmap/test-configmap --namespace=test-configmaps' "{{$id_field}}" 'test-configmap' kube::test::get_object_assert 'configmap/test-binary-configmap --namespace=test-configmaps' "{{$id_field}}" 'test-binary-configmap' - [[ "$(kubectl get configmap/test-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}" | grep 'key1: value1')" ]] - [[ "$(kubectl get configmap/test-binary-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}" | grep 'binaryData')" ]] + grep -q "key1: value1" <<< "$(kubectl get configmap/test-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}")" + grep -q "binaryData" <<< "$(kubectl get configmap/test-binary-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}")" # Clean-up kubectl delete configmap test-configmap --namespace=test-configmaps kubectl delete configmap test-binary-configmap --namespace=test-configmaps @@ -159,11 +159,11 @@ run_pod_tests() { ### Delete POD valid-pod with label # Pre-condition: valid-pod POD exists - kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' 'valid-pod:' + kube::test::get_object_assert "pods -l'name in (valid-pod)'" "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' # Command kubectl delete pods -l'name in (valid-pod)' "${kube_flags[@]}" --grace-period=0 --force # Post-condition: valid-pod POD doesn't exist - kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' '' + kube::test::get_object_assert "pods -l'name in (valid-pod)'" "{{range.items}}{{$id_field}}:{{end}}" '' ### Create POD valid-pod from YAML # Pre-condition: no POD exists @@ -203,12 +203,12 @@ run_pod_tests() { # Command kubectl delete --all pods "${kube_flags[@]}" --grace-period=0 --force # --all remove all the pods # Post-condition: no POD exists - kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' '' + kube::test::get_object_assert "pods -l'name in (valid-pod)'" "{{range.items}}{{$id_field}}:{{end}}" '' # Detailed tests for describe pod output ### Create a new namespace # Pre-condition: the test-secrets namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-kubectl-describe-pod\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"$id_field"' \"test-kubectl-describe-pod\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace test-kubectl-describe-pod # Post-condition: namespace 'test-secrets' is created. @@ -221,12 +221,12 @@ run_pod_tests() { kubectl create secret generic test-secret --from-literal=key-1=value1 --type=test-type --namespace=test-kubectl-describe-pod # Post-condition: secret exists and has expected values kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{$id_field}}" 'test-secret' - kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{$secret_type}}" 'test-type' + kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{${secret_type:?}}}" 'test-type' ### Create a generic configmap # Pre-condition: CONFIGMAP test-configmap does not exist #kube::test::get_object_assert 'configmap/test-configmap --namespace=test-kubectl-describe-pod' "{{$id_field}}" '' - kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' '{{range.items}}{{ if eq $id_field \"test-configmap\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' '{{range.items}}{{ if eq '"$id_field"' \"test-configmap\" }}found{{end}}{{end}}:' ':' #kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" '' # Command @@ -238,7 +238,7 @@ run_pod_tests() { # Command kubectl create pdb test-pdb-1 --selector=app=rails --min-available=2 --namespace=test-kubectl-describe-pod # Post-condition: pdb exists and has expected values - kube::test::get_object_assert 'pdb/test-pdb-1 --namespace=test-kubectl-describe-pod' "{{$pdb_min_available}}" '2' + kube::test::get_object_assert 'pdb/test-pdb-1 --namespace=test-kubectl-describe-pod' "{{${pdb_min_available:?}}}" '2' # Command kubectl create pdb test-pdb-2 --selector=app=rails --min-available=50% --namespace=test-kubectl-describe-pod # Post-condition: pdb exists and has expected values @@ -248,7 +248,7 @@ run_pod_tests() { # Command kubectl create pdb test-pdb-3 --selector=app=rails --max-unavailable=2 --namespace=test-kubectl-describe-pod # Post-condition: pdb exists and has expected values - kube::test::get_object_assert 'pdb/test-pdb-3 --namespace=test-kubectl-describe-pod' "{{$pdb_max_unavailable}}" '2' + kube::test::get_object_assert 'pdb/test-pdb-3 --namespace=test-kubectl-describe-pod' "{{${pdb_max_unavailable:?}}}" '2' # Command kubectl create pdb test-pdb-4 --selector=app=rails --max-unavailable=50% --namespace=test-kubectl-describe-pod # Post-condition: pdb exists and has expected values @@ -301,7 +301,7 @@ run_pod_tests() { ### Label the valid-pod POD # Pre-condition: valid-pod is not labelled - kube::test::get_object_assert 'pod valid-pod' "{{range$labels_field}}{{.}}:{{end}}" 'valid-pod:' + kube::test::get_object_assert 'pod valid-pod' "{{range${labels_field:?}}}{{.}}:{{end}}" 'valid-pod:' # Command kubectl label pods valid-pod new-name=new-valid-pod "${kube_flags[@]}" # Post-condition: valid-pod is labelled @@ -317,7 +317,7 @@ run_pod_tests() { ### Annotate the valid-pod POD with empty annotation value # Pre-condition: valid-pod does not have annotation "emptyannotation" - kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field}.emptyannotation}}" '' + kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field:?}.emptyannotation}}" '' # Command kubectl annotate pods valid-pod emptyannotation="" "${kube_flags[@]}" # Post-condition: valid pod contains "emptyannotation" with no value @@ -387,7 +387,7 @@ run_pod_tests() { # Command output_message=$(kubectl annotate --local -f hack/testdata/pod.yaml annotatekey=localvalue -o yaml "${kube_flags[@]}") - echo $output_message + echo "$output_message" # Post-condition: annotationkey is still annotationvalue in the live pod, but command output is the new value kube::test::get_object_assert 'pod test-pod' "{{${annotations_field}.annotatekey}}" 'annotatevalue' @@ -402,8 +402,8 @@ run_pod_tests() { kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" '' ## kubectl create --edit can update the label filed of multiple resources. tmp-editor.sh is a fake editor TEMP=$(mktemp /tmp/tmp-editor-XXXXXXXX.sh) - echo -e "#!/usr/bin/env bash\n${SED} -i \"s/mock/modified/g\" \$1" > ${TEMP} - chmod +x ${TEMP} + echo -e "#!/usr/bin/env bash\n${SED} -i \"s/mock/modified/g\" \$1" > "${TEMP}" + chmod +x "${TEMP}" # Command EDITOR=${TEMP} kubectl create --edit -f hack/testdata/multi-resource-json.json "${kube_flags[@]}" # Post-condition: service named modified and rc named modified are created @@ -422,12 +422,12 @@ run_pod_tests() { kube::test::get_object_assert service "{{range.items}}{{$id_field}}:{{end}}" 'modified:' kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'modified:' # Clean up - rm ${TEMP} + rm "${TEMP}" kubectl delete service/modified "${kube_flags[@]}" kubectl delete rc/modified "${kube_flags[@]}" ## kubectl create --edit won't create anything if user makes no changes - [ "$(EDITOR=cat kubectl create --edit -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json 2>&1 | grep 'Edit cancelled')" ] + grep -q 'Edit cancelled' <<< "$(EDITOR="cat" kubectl create --edit -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json 2>&1)" ## Create valid-pod POD # Pre-condition: no POD exists @@ -452,9 +452,9 @@ run_pod_tests() { # Command kubectl patch "${kube_flags[@]}" pod valid-pod --record -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}' # Post-condition: valid-pod POD has image nginx - kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:' + kube::test::get_object_assert pods "{{range.items}}{{${image_field:?}}}:{{end}}" 'nginx:' # Post-condition: valid-pod has the record annotation - kube::test::get_object_assert pods "{{range.items}}{{$annotations_field}}:{{end}}" "${change_cause_annotation}" + kube::test::get_object_assert pods "{{range.items}}{{$annotations_field}}:{{end}}" "${change_cause_annotation:?}" # prove that patch can use different types kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx2"}]' # Post-condition: valid-pod POD has image nginx @@ -481,9 +481,9 @@ run_pod_tests() { # Needs to retry because other party may change the resource. for count in {0..3}; do resourceVersion=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .metadata.resourceVersion }}') - kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'$resourceVersion'"}}' 2> "${ERROR_FILE}" || true + kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'"${resourceVersion}"'"}}' 2> "${ERROR_FILE}" || true if grep -q "the object has been modified" "${ERROR_FILE}"; then - kube::log::status "retry $1, error: $(cat ${ERROR_FILE})" + kube::log::status "retry $1, error: $(cat "${ERROR_FILE}")" rm "${ERROR_FILE}" sleep $((2**count)) else @@ -500,9 +500,9 @@ run_pod_tests() { kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'$resourceVersion'"}}' 2> "${ERROR_FILE}" || true # Post-condition: should get an error reporting the conflict if grep -q "please apply your changes to the latest version and try again" "${ERROR_FILE}"; then - kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns error as expected: $(cat ${ERROR_FILE})" + kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns error as expected: $(cat "${ERROR_FILE}")" else - kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns unexpected error or non-error: $(cat ${ERROR_FILE})" + kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns unexpected error or non-error: $(cat "${ERROR_FILE}")" exit 1 fi rm "${ERROR_FILE}" @@ -557,25 +557,25 @@ __EOF__ chmod +x /tmp/tmp-editor.sh # Pre-condition: valid-pod POD has image nginx kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:' - [[ "$(EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod --output-patch=true | grep Patch:)" ]] + grep -q 'Patch:' <<< "$(EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod --output-patch=true)" # Post-condition: valid-pod POD has image k8s.gcr.io/serve_hostname kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'k8s.gcr.io/serve_hostname:' # cleaning rm /tmp/tmp-editor.sh ## kubectl edit should work on Windows - [ "$(EDITOR=cat kubectl edit pod/valid-pod 2>&1 | grep 'Edit cancelled')" ] - [ "$(EDITOR=cat kubectl edit pod/valid-pod | grep 'name: valid-pod')" ] - [ "$(EDITOR=cat kubectl edit --windows-line-endings pod/valid-pod | file - | grep CRLF)" ] - [ ! "$(EDITOR=cat kubectl edit --windows-line-endings=false pod/valid-pod | file - | grep CRLF)" ] - [ "$(EDITOR=cat kubectl edit ns | grep 'kind: List')" ] + grep -q 'Edit cancelled' <<< "$(EDITOR="cat" kubectl edit pod/valid-pod 2>&1)" + grep -q 'name: valid-pod' <<< "$(EDITOR="cat" kubectl edit pod/valid-pod)" + grep -q CRLF <<< "$(EDITOR="cat" kubectl edit --windows-line-endings pod/valid-pod | file - )" + ! grep -q CRLF <<< "$(EDITOR="cat" kubectl edit --windows-line-endings=false pod/valid-pod | file - )" + grep -q 'kind: List' <<< "$(EDITOR="cat" kubectl edit ns)" ### Label POD YAML file locally without effecting the live pod. # Pre-condition: name is valid-pod kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod' # Command output_message=$(kubectl label --local --overwrite -f hack/testdata/pod.yaml name=localonlyvalue -o yaml "${kube_flags[@]}") - echo $output_message + echo "$output_message" # Post-condition: name is still valid-pod in the live pod, but command output is the new value kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod' kube::test::if_has_string "${output_message}" "localonlyvalue" @@ -631,7 +631,7 @@ __EOF__ # Post-Condition: pod "test-pod" is created kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label' # Post-Condition: pod "test-pod" doesn't have configuration annotation - ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] + ! grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" )" ## 2. kubectl replace doesn't set the annotation kubectl get pods test-pod -o yaml "${kube_flags[@]}" | ${SED} 's/test-pod-label/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml # Command: replace the pod "test-pod" @@ -639,14 +639,14 @@ __EOF__ # Post-Condition: pod "test-pod" is replaced kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced' # Post-Condition: pod "test-pod" doesn't have configuration annotation - ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] + ! grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}")" ## 3. kubectl apply does set the annotation # Command: apply the pod "test-pod" kubectl apply -f hack/testdata/pod-apply.yaml "${kube_flags[@]}" # Post-Condition: pod "test-pod" is applied kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-applied' # Post-Condition: pod "test-pod" has configuration annotation - [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] + grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}")" kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration ## 4. kubectl replace updates an existing annotation kubectl get pods test-pod -o yaml "${kube_flags[@]}" | ${SED} 's/test-pod-applied/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml @@ -655,7 +655,7 @@ __EOF__ # Post-Condition: pod "test-pod" is replaced kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced' # Post-Condition: pod "test-pod" has configuration annotation, and it's updated (different from the annotation when it's applied) - [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] + grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" )" kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration-replaced ! [[ $(diff -q "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced > /dev/null) ]] # Clean up @@ -710,7 +710,7 @@ run_secrets_test() { ### Create a new namespace # Pre-condition: the test-secrets namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-secrets\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"$id_field"' \"test-secrets\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace test-secrets # Post-condition: namespace 'test-secrets' is created. @@ -724,7 +724,7 @@ run_secrets_test() { # Post-condition: secret exists and has expected values kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret' kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'test-type' - [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep 'key1: dmFsdWUx')" ]] + grep -q 'key1: dmFsdWUx' <<< "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}")" # Clean-up kubectl delete secret test-secret --namespace=test-secrets @@ -739,7 +739,7 @@ run_secrets_test() { # Post-condition: secret exists and has expected values kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret' kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockerconfigjson' - [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep '.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ0ZXN0LXVzZXIiLCJwYXNzd29yZCI6InRlc3QtcGFzc3dvcmQiLCJlbWFpbCI6InRlc3QtdXNlckB0ZXN0LmNvbSIsImF1dGgiOiJkR1Z6ZEMxMWMyVnlPblJsYzNRdGNHRnpjM2R2Y21RPSJ9fX0=')" ]] + grep -q '.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ0ZXN0LXVzZXIiLCJwYXNzd29yZCI6InRlc3QtcGFzc3dvcmQiLCJlbWFpbCI6InRlc3QtdXNlckB0ZXN0LmNvbSIsImF1dGgiOiJkR1Z6ZEMxMWMyVnlPblJsYzNRdGNHRnpjM2R2Y21RPSJ9fX0=' <<< "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}")" # Clean-up kubectl delete secret test-secret --namespace=test-secrets @@ -794,7 +794,7 @@ __EOF__ # Pre-condition: no secret exists kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" '' # Command - [[ "$(kubectl create secret generic test-secret --namespace=test-secrets --from-literal=key1=value1 --output=go-template --template=\"{{.metadata.name}}:\" | grep 'test-secret:')" ]] + grep -q 'test-secret:' <<< "$(kubectl create secret generic test-secret --namespace=test-secrets --from-literal=key1=value1 --output=go-template --template="{{.metadata.name}}:")" ## Clean-up kubectl delete secret test-secret --namespace=test-secrets # Clean up @@ -813,7 +813,7 @@ run_service_accounts_tests() { ### Create a new namespace # Pre-condition: the test-service-accounts namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-service-accounts\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"$id_field"' \"test-service-accounts\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace test-service-accounts # Post-condition: namespace 'test-service-accounts' is created. @@ -867,7 +867,7 @@ run_service_tests() { ### set selector # prove role=master - kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:" + kube::test::get_object_assert 'services redis-master' "{{range${service_selector_field:?}}}{{.}}:{{end}}" "redis:master:backend:" # Set selector of a local file without talking to the server kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan --local -o yaml "${kube_flags[@]}" @@ -1064,7 +1064,7 @@ run_rc_tests() { ### Scale replication controller frontend with current-replicas and replicas # Pre-condition: 3 replicas - kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3' + kube::test::get_object_assert 'rc frontend' "{{${rc_replicas_field:?}}}" '3' # Command kubectl scale --current-replicas=3 --replicas=2 replicationcontrollers frontend "${kube_flags[@]}" # Post-condition: 2 replicas @@ -1112,7 +1112,7 @@ run_rc_tests() { # Command kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment # Post-condition: 1 replica for nginx-deployment - kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '1' + kube::test::get_object_assert 'deployment nginx-deployment' "{{${deployment_replicas:?}}}" '1' # Clean-up kubectl delete deployment/nginx-deployment "${kube_flags[@]}" @@ -1151,7 +1151,7 @@ run_rc_tests() { # Command kubectl expose deployment/nginx-deployment # Post-condition: service exists and exposes deployment port (80) - kube::test::get_object_assert 'service nginx-deployment' "{{$port_field}}" '80' + kube::test::get_object_assert 'service nginx-deployment' "{{${port_field:?}}}" '80' # Clean-up kubectl delete deployment/nginx-deployment service/nginx-deployment "${kube_flags[@]}" @@ -1162,7 +1162,7 @@ run_rc_tests() { # Command kubectl expose rc frontend --port=80 "${kube_flags[@]}" # Post-condition: service exists and the port is unnamed - kube::test::get_object_assert 'service frontend' "{{$port_name}} {{$port_field}}" ' 80' + kube::test::get_object_assert 'service frontend' "{{${port_name:?}}} {{$port_field}}" ' 80' # Command kubectl expose service frontend --port=443 --name=frontend-2 "${kube_flags[@]}" # Post-condition: service exists and the port is unnamed @@ -1210,7 +1210,7 @@ run_rc_tests() { kube::test::if_has_string "${output_message}" 'etcd-server exposed' # Post-condition: generated service has both ports from the exposed pod kube::test::get_object_assert 'service etcd-server' "{{$port_name}} {{$port_field}}" 'port-1 2380' - kube::test::get_object_assert 'service etcd-server' "{{$second_port_name}} {{$second_port_field}}" 'port-2 2379' + kube::test::get_object_assert 'service etcd-server' "{{${second_port_name:?}}} {{${second_port_field:?}}}" 'port-2 2379' # Clean-up kubectl delete svc etcd-server "${kube_flags[@]}" @@ -1247,7 +1247,7 @@ run_rc_tests() { kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:' # autoscale 1~2 pods, CPU utilization 70%, rc specified by file kubectl autoscale -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}" --max=2 --cpu-percent=70 - kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 70' + kube::test::get_object_assert 'hpa frontend' "{{${hpa_min_field:?}}} {{${hpa_max_field:?}}} {{${hpa_cpu_field:?}}}" '1 2 70' kubectl delete hpa frontend "${kube_flags[@]}" # autoscale 2~3 pods, no CPU utilization specified, rc specified by name kubectl autoscale rc frontend "${kube_flags[@]}" --min=2 --max=3 @@ -1267,8 +1267,8 @@ run_rc_tests() { # Create a deployment kubectl create -f hack/testdata/deployment-multicontainer-resources.yaml "${kube_flags[@]}" kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment-resources:' - kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:" - kube::test::get_object_assert deployment "{{range.items}}{{$image_field1}}:{{end}}" "${IMAGE_PERL}:" + kube::test::get_object_assert deployment "{{range.items}}{{${image_field0:?}}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:" + kube::test::get_object_assert deployment "{{range.items}}{{${image_field1:?}}}:{{end}}" "${IMAGE_PERL}:" # Set the deployment's cpu limits kubectl set resources deployment nginx-deployment-resources --limits=cpu=100m "${kube_flags[@]}" kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 0).resources.limits.cpu}}:{{end}}" "100m:" @@ -1327,10 +1327,10 @@ run_namespace_tests() { # Pods in Namespaces # ###################### - if kube::test::if_supports_resource "${pods}" ; then + if kube::test::if_supports_resource "${pods:?}" ; then ### Create a new namespace # Pre-condition: the other namespace does not exist - kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"other\" }}found{{end}}{{end}}:' ':' + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq '"$id_field"' \"other\" }}found{{end}}{{end}}:' ':' # Command kubectl create namespace other # Post-condition: namespace 'other' is created. @@ -1424,7 +1424,7 @@ run_pod_templates_tests() { ### Printing pod templates works kubectl get podtemplates "${kube_flags[@]}" - [[ "$(kubectl get podtemplates -o yaml "${kube_flags[@]}" | grep nginx)" ]] + grep -q nginx <<< "$(kubectl get podtemplates -o yaml "${kube_flags[@]}")" ### Delete nginx pod template by name # Pre-condition: nginx pod template is available diff --git a/test/cmd/crd.sh b/test/cmd/crd.sh index 7fafafffc04..9c54c63a993 100755 --- a/test/cmd/crd.sh +++ b/test/cmd/crd.sh @@ -24,7 +24,7 @@ run_crd_tests() { create_and_use_new_namespace kube::log::status "Testing kubectl crd" - kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__ + kubectl "${kube_flags_with_token[@]:?}" create -f - << __EOF__ { "kind": "CustomResourceDefinition", "apiVersion": "apiextensions.k8s.io/v1beta1", @@ -44,7 +44,7 @@ run_crd_tests() { __EOF__ # Post-Condition: assertion object exist - kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"foos.company.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'foos.company.com:' + kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \\\"foos.company.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'foos.company.com:' kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__ { @@ -148,10 +148,9 @@ kube::util::non_native_resources() { local failed times=30 wait=10 - local i - for i in $(seq 1 $times); do + for _ in $(seq 1 $times); do failed="" - kubectl "${kube_flags[@]}" get --raw '/apis/company.com/v1' || failed=true + kubectl "${kube_flags[@]:?}" get --raw '/apis/company.com/v1' || failed=true kubectl "${kube_flags[@]}" get --raw '/apis/company.com/v1/foos' || failed=true kubectl "${kube_flags[@]}" get --raw '/apis/company.com/v1/bars' || failed=true @@ -246,9 +245,9 @@ run_non_native_resource_tests() { CRD_PATCH_ERROR_FILE="${KUBE_TEMP}/crd-foos-test-error" ! kubectl "${kube_flags[@]}" patch --local -f "${CRD_RESOURCE_FILE}" -p '{"patched":"value3"}' 2> "${CRD_PATCH_ERROR_FILE}" if grep -q "try --type merge" "${CRD_PATCH_ERROR_FILE}"; then - kube::log::status "\"kubectl patch --local\" returns error as expected for CustomResource: $(cat ${CRD_PATCH_ERROR_FILE})" + kube::log::status "\"kubectl patch --local\" returns error as expected for CustomResource: $(cat "${CRD_PATCH_ERROR_FILE}")" else - kube::log::status "\"kubectl patch --local\" returns unexpected error or non-error: $(cat ${CRD_PATCH_ERROR_FILE})" + kube::log::status "\"kubectl patch --local\" returns unexpected error or non-error: $(cat "${CRD_PATCH_ERROR_FILE}")" exit 1 fi # can apply merge patch locally @@ -294,7 +293,7 @@ run_non_native_resource_tests() { kube::log::status "Testing CustomResource watching" exec 3< <(kubectl "${kube_flags[@]}" get bars --request-timeout=1m --watch-only -o name & echo $! ; wait) local watch_pid - read <&3 watch_pid + read -r <&3 watch_pid # We can't be sure when the watch gets established, # so keep triggering events (in the background) until something comes through. @@ -308,10 +307,10 @@ run_non_native_resource_tests() { # Wait up to 30s for a complete line of output. local watch_output - read <&3 -t 30 watch_output + read -r <&3 -t 30 watch_output # Stop the watcher and the patch loop. - kill -9 ${watch_pid} - kill -9 ${patch_pid} + kill -9 "${watch_pid}" + kill -9 "${patch_pid}" kube::test::if_has_string "${watch_output}" 'bar.company.com/test' # Delete the resource without cascade. diff --git a/test/cmd/create.sh b/test/cmd/create.sh index e21b04d8cfb..8ffa71b21bd 100755 --- a/test/cmd/create.sh +++ b/test/cmd/create.sh @@ -27,11 +27,11 @@ run_kubectl_create_filter_tests() { kube::log::status "Testing kubectl create filter" ## kubectl create -f with label selector should only create matching objects # Pre-Condition: no POD exists - kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" '' + kube::test::get_object_assert pods "{{range.items}}{{${id_field:?}}}:{{end}}" '' # create - kubectl create -l unique-label=bingbang -f hack/testdata/filter "${kube_flags[@]}" + kubectl create -l unique-label=bingbang -f hack/testdata/filter "${kube_flags[@]:?}" # check right pod exists - kube::test::get_object_assert 'pods selector-test-pod' "{{${labels_field}.name}}" 'selector-test-pod' + kube::test::get_object_assert 'pods selector-test-pod' "{{${labels_field:?}.name}}" 'selector-test-pod' # check wrong pod doesn't exist output_message=$(! kubectl get pods selector-test-pod-dont-apply 2>&1 "${kube_flags[@]}") kube::test::if_has_string "${output_message}" 'pods "selector-test-pod-dont-apply" not found' @@ -57,17 +57,17 @@ run_kubectl_create_error_tests() { kubectl create -f hack/testdata/invalid-rc-with-empty-args.yaml "${kube_flags[@]}" 2> "${ERROR_FILE}" || true # Post-condition: should get an error reporting the empty string if grep -q "unknown object type \"nil\" in ReplicationController" "${ERROR_FILE}"; then - kube::log::status "\"kubectl create with empty string list returns error as expected: $(cat ${ERROR_FILE})" + kube::log::status "\"kubectl create with empty string list returns error as expected: $(cat "${ERROR_FILE}")" else - kube::log::status "\"kubectl create with empty string list returns unexpected error or non-error: $(cat ${ERROR_FILE})" + kube::log::status "\"kubectl create with empty string list returns unexpected error or non-error: $(cat "${ERROR_FILE}")" exit 1 fi rm "${ERROR_FILE}" # Posting a pod to namespaces should fail. Also tests --raw forcing the post location - [ "$( kubectl convert -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f - --v=8 2>&1 | grep 'cannot be handled as a Namespace: converting (v1.Pod)')" ] + grep -q "cannot be handled as a Namespace: converting (v1.Pod)" <<< "$( kubectl convert -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f - --v=8 2>&1 )" - [ "$( kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --edit 2>&1 | grep 'raw and --edit are mutually exclusive')" ] + grep -q "raw and --edit are mutually exclusive" <<< "$( kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --edit 2>&1 )" set +o nounset set +o errexit @@ -83,13 +83,13 @@ run_create_job_tests() { # Test kubectl create job kubectl create job test-job --image=k8s.gcr.io/nginx:test-cmd # Post-Condition: job nginx is created - kube::test::get_object_assert 'job test-job' "{{$image_field0}}" 'k8s.gcr.io/nginx:test-cmd' + kube::test::get_object_assert 'job test-job' "{{${image_field0:?}}}" 'k8s.gcr.io/nginx:test-cmd' # Clean up kubectl delete job test-job "${kube_flags[@]}" # Test kubectl create job with command kubectl create job test-job-pi "--image=$IMAGE_PERL" -- perl -Mbignum=bpi -wle 'print bpi(20)' - kube::test::get_object_assert 'job test-job-pi' "{{$image_field0}}" $IMAGE_PERL + kube::test::get_object_assert 'job test-job-pi' "{{$image_field0}}" "$IMAGE_PERL" # Clean up kubectl delete job test-job-pi @@ -132,4 +132,4 @@ run_kubectl_create_kustomization_directory_tests() { set +o nounset set +o errexit -} \ No newline at end of file +}