mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-03 03:30:19 +00:00
470 lines
19 KiB
Bash
Executable File
470 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Copyright 2018 The Kubernetes Authors.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
set -o errexit
|
|
set -o nounset
|
|
set -o pipefail
|
|
|
|
run_crd_tests() {
|
|
set -o nounset
|
|
set -o errexit
|
|
|
|
create_and_use_new_namespace
|
|
kube::log::status "Testing kubectl crd"
|
|
kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__
|
|
{
|
|
"kind": "CustomResourceDefinition",
|
|
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
|
"metadata": {
|
|
"name": "foos.company.com"
|
|
},
|
|
"spec": {
|
|
"group": "company.com",
|
|
"version": "v1",
|
|
"scope": "Namespaced",
|
|
"names": {
|
|
"plural": "foos",
|
|
"kind": "Foo"
|
|
}
|
|
}
|
|
}
|
|
__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:'
|
|
|
|
kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__
|
|
{
|
|
"kind": "CustomResourceDefinition",
|
|
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
|
"metadata": {
|
|
"name": "bars.company.com"
|
|
},
|
|
"spec": {
|
|
"group": "company.com",
|
|
"version": "v1",
|
|
"scope": "Namespaced",
|
|
"names": {
|
|
"plural": "bars",
|
|
"kind": "Bar"
|
|
}
|
|
}
|
|
}
|
|
__EOF__
|
|
|
|
# Post-Condition: assertion object exist
|
|
kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"foos.company.com\\\" \\\"bars.company.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'bars.company.com:foos.company.com:'
|
|
|
|
# This test ensures that the name printer is able to output a resource
|
|
# in the proper "kind.group/resource_name" format, and that the
|
|
# resource builder is able to resolve a GVK when a kind.group pair is given.
|
|
kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__
|
|
{
|
|
"kind": "CustomResourceDefinition",
|
|
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
|
"metadata": {
|
|
"name": "resources.mygroup.example.com"
|
|
},
|
|
"spec": {
|
|
"group": "mygroup.example.com",
|
|
"version": "v1alpha1",
|
|
"scope": "Namespaced",
|
|
"names": {
|
|
"plural": "resources",
|
|
"singular": "resource",
|
|
"kind": "Kind",
|
|
"listKind": "KindList"
|
|
}
|
|
}
|
|
}
|
|
__EOF__
|
|
|
|
# Post-Condition: assertion crd with non-matching kind and resource exists
|
|
kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"foos.company.com\\\" \\\"bars.company.com\\\" \\\"resources.mygroup.example.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'bars.company.com:foos.company.com:resources.mygroup.example.com:'
|
|
|
|
# This test ensures that we can create complex validation without client-side validation complaining
|
|
kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__
|
|
{
|
|
"kind": "CustomResourceDefinition",
|
|
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
|
"metadata": {
|
|
"name": "validfoos.company.com"
|
|
},
|
|
"spec": {
|
|
"group": "company.com",
|
|
"version": "v1",
|
|
"scope": "Namespaced",
|
|
"names": {
|
|
"plural": "validfoos",
|
|
"kind": "ValidFoo"
|
|
},
|
|
"validation": {
|
|
"openAPIV3Schema": {
|
|
"properties": {
|
|
"spec": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
__EOF__
|
|
|
|
# Post-Condition: assertion crd with non-matching kind and resource exists
|
|
kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"foos.company.com\\\" \\\"bars.company.com\\\" \\\"resources.mygroup.example.com\\\" \\\"validfoos.company.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'bars.company.com:foos.company.com:resources.mygroup.example.com:validfoos.company.com:'
|
|
|
|
run_non_native_resource_tests
|
|
|
|
# teardown
|
|
kubectl delete customresourcedefinitions/foos.company.com "${kube_flags_with_token[@]}"
|
|
kubectl delete customresourcedefinitions/bars.company.com "${kube_flags_with_token[@]}"
|
|
kubectl delete customresourcedefinitions/resources.mygroup.example.com "${kube_flags_with_token[@]}"
|
|
kubectl delete customresourcedefinitions/validfoos.company.com "${kube_flags_with_token[@]}"
|
|
|
|
set +o nounset
|
|
set +o errexit
|
|
}
|
|
|
|
kube::util::non_native_resources() {
|
|
local times
|
|
local wait
|
|
local failed
|
|
times=30
|
|
wait=10
|
|
local i
|
|
for i 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/foos' || failed=true
|
|
kubectl "${kube_flags[@]}" get --raw '/apis/company.com/v1/bars' || failed=true
|
|
|
|
if [ -z "${failed}" ]; then
|
|
return 0
|
|
fi
|
|
sleep ${wait}
|
|
done
|
|
|
|
kube::log::error "Timed out waiting for non-native-resources; tried ${times} waiting ${wait}s between each"
|
|
return 1
|
|
}
|
|
|
|
run_non_native_resource_tests() {
|
|
set -o nounset
|
|
set -o errexit
|
|
|
|
create_and_use_new_namespace
|
|
kube::log::status "Testing kubectl non-native resources"
|
|
kube::util::non_native_resources
|
|
|
|
# Test that we can list this new CustomResource (foos)
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can list this new CustomResource (bars)
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can list this new CustomResource (resources)
|
|
kube::test::get_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can create a new resource of type Kind
|
|
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/resource.yaml "${kube_flags[@]}"
|
|
|
|
# Test that -o name returns kind.group/resourcename
|
|
output_message=$(kubectl "${kube_flags[@]}" get resource/myobj -o name)
|
|
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
|
|
|
output_message=$(kubectl "${kube_flags[@]}" get resources/myobj -o name)
|
|
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
|
|
|
output_message=$(kubectl "${kube_flags[@]}" get kind.mygroup.example.com/myobj -o name)
|
|
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
|
|
|
# Delete the resource with cascade.
|
|
kubectl "${kube_flags[@]}" delete resources myobj --cascade=true
|
|
|
|
# Make sure it's gone
|
|
kube::test::wait_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can create a new resource of type Foo
|
|
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/foo.yaml "${kube_flags[@]}"
|
|
|
|
# Test that we can list this new custom resource
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
|
|
# Test alternate forms
|
|
kube::test::get_object_assert foo "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
kube::test::get_object_assert foos.company.com "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
kube::test::get_object_assert foos.v1.company.com "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
|
|
# Test all printers, with lists and individual items
|
|
kube::log::status "Testing CustomResource printing"
|
|
kubectl "${kube_flags[@]}" get foos
|
|
kubectl "${kube_flags[@]}" get foos/test
|
|
kubectl "${kube_flags[@]}" get foos -o name
|
|
kubectl "${kube_flags[@]}" get foos/test -o name
|
|
kubectl "${kube_flags[@]}" get foos -o wide
|
|
kubectl "${kube_flags[@]}" get foos/test -o wide
|
|
kubectl "${kube_flags[@]}" get foos -o json
|
|
kubectl "${kube_flags[@]}" get foos/test -o json
|
|
kubectl "${kube_flags[@]}" get foos -o yaml
|
|
kubectl "${kube_flags[@]}" get foos/test -o yaml
|
|
kubectl "${kube_flags[@]}" get foos -o "jsonpath={.items[*].someField}" --allow-missing-template-keys=false
|
|
kubectl "${kube_flags[@]}" get foos/test -o "jsonpath={.someField}" --allow-missing-template-keys=false
|
|
kubectl "${kube_flags[@]}" get foos -o "go-template={{range .items}}{{.someField}}{{end}}" --allow-missing-template-keys=false
|
|
kubectl "${kube_flags[@]}" get foos/test -o "go-template={{.someField}}" --allow-missing-template-keys=false
|
|
output_message=$(kubectl "${kube_flags[@]}" get foos/test -o name)
|
|
kube::test::if_has_string "${output_message}" 'foo.company.com/test'
|
|
|
|
# Test patching
|
|
kube::log::status "Testing CustomResource patching"
|
|
kubectl "${kube_flags[@]}" patch foos/test -p '{"patched":"value1"}' --type=merge
|
|
kube::test::get_object_assert foos/test "{{.patched}}" 'value1'
|
|
kubectl "${kube_flags[@]}" patch foos/test -p '{"patched":"value2"}' --type=merge --record
|
|
kube::test::get_object_assert foos/test "{{.patched}}" 'value2'
|
|
kubectl "${kube_flags[@]}" patch foos/test -p '{"patched":null}' --type=merge --record
|
|
kube::test::get_object_assert foos/test "{{.patched}}" '<no value>'
|
|
# Get local version
|
|
CRD_RESOURCE_FILE="${KUBE_TEMP}/crd-foos-test.json"
|
|
kubectl "${kube_flags[@]}" get foos/test -o json > "${CRD_RESOURCE_FILE}"
|
|
# cannot apply strategic patch locally
|
|
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})"
|
|
else
|
|
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
|
|
kubectl "${kube_flags[@]}" patch --local -f "${CRD_RESOURCE_FILE}" -p '{"patched":"value3"}' --type=merge -o json
|
|
# can apply merge patch remotely
|
|
kubectl "${kube_flags[@]}" patch --record -f "${CRD_RESOURCE_FILE}" -p '{"patched":"value3"}' --type=merge -o json
|
|
kube::test::get_object_assert foos/test "{{.patched}}" 'value3'
|
|
rm "${CRD_RESOURCE_FILE}"
|
|
rm "${CRD_PATCH_ERROR_FILE}"
|
|
|
|
# Test labeling
|
|
kube::log::status "Testing CustomResource labeling"
|
|
kubectl "${kube_flags[@]}" label foos --all listlabel=true
|
|
kubectl "${kube_flags[@]}" label foo/test itemlabel=true
|
|
|
|
# Test annotating
|
|
kube::log::status "Testing CustomResource annotating"
|
|
kubectl "${kube_flags[@]}" annotate foos --all listannotation=true
|
|
kubectl "${kube_flags[@]}" annotate foo/test itemannotation=true
|
|
|
|
# Test describing
|
|
kube::log::status "Testing CustomResource describing"
|
|
kubectl "${kube_flags[@]}" describe foos
|
|
kubectl "${kube_flags[@]}" describe foos/test
|
|
kubectl "${kube_flags[@]}" describe foos | grep listlabel=true
|
|
kubectl "${kube_flags[@]}" describe foos | grep itemlabel=true
|
|
|
|
# Delete the resource with cascade.
|
|
kubectl "${kube_flags[@]}" delete foos test --cascade=true
|
|
|
|
# Make sure it's gone
|
|
kube::test::wait_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can create a new resource of type Bar
|
|
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/bar.yaml "${kube_flags[@]}"
|
|
|
|
# Test that we can list this new custom resource
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
|
|
# Test that we can watch the resource.
|
|
# Start watcher in background with process substitution,
|
|
# so we can read from stdout asynchronously.
|
|
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
|
|
|
|
# We can't be sure when the watch gets established,
|
|
# so keep triggering events (in the background) until something comes through.
|
|
local tries=0
|
|
while [ ${tries} -lt 10 ]; do
|
|
tries=$((tries+1))
|
|
kubectl "${kube_flags[@]}" patch bars/test -p "{\"patched\":\"${tries}\"}" --type=merge
|
|
sleep 1
|
|
done &
|
|
local patch_pid=$!
|
|
|
|
# Wait up to 30s for a complete line of output.
|
|
local watch_output
|
|
read <&3 -t 30 watch_output
|
|
# Stop the watcher and the patch loop.
|
|
kill -9 ${watch_pid}
|
|
kill -9 ${patch_pid}
|
|
kube::test::if_has_string "${watch_output}" 'bar.company.com/test'
|
|
|
|
# Delete the resource without cascade.
|
|
kubectl "${kube_flags[@]}" delete bars test --cascade=false
|
|
|
|
# Make sure it's gone
|
|
kube::test::wait_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can create single item via apply
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/foo.yaml
|
|
|
|
# Test that we have create a foo named test
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
|
|
# Test that the field has the expected value
|
|
kube::test::get_object_assert foos/test '{{.someField}}' 'field1'
|
|
|
|
# Test that apply an empty patch doesn't change fields
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/foo.yaml
|
|
|
|
# Test that the field has the same value after re-apply
|
|
kube::test::get_object_assert foos/test '{{.someField}}' 'field1'
|
|
|
|
# Test that apply has updated the subfield
|
|
kube::test::get_object_assert foos/test '{{.nestedField.someSubfield}}' 'subfield1'
|
|
|
|
# Update a subfield and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/foo-updated-subfield.yaml
|
|
|
|
# Test that apply has updated the subfield
|
|
kube::test::get_object_assert foos/test '{{.nestedField.someSubfield}}' 'modifiedSubfield'
|
|
|
|
# Test that the field has the expected value
|
|
kube::test::get_object_assert foos/test '{{.nestedField.otherSubfield}}' 'subfield2'
|
|
|
|
# Delete a subfield and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/foo-deleted-subfield.yaml
|
|
|
|
# Test that apply has deleted the field
|
|
kube::test::get_object_assert foos/test '{{.nestedField.otherSubfield}}' '<no value>'
|
|
|
|
# Test that the field does not exist
|
|
kube::test::get_object_assert foos/test '{{.nestedField.newSubfield}}' '<no value>'
|
|
|
|
# Add a field and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/foo-added-subfield.yaml
|
|
|
|
# Test that apply has added the field
|
|
kube::test::get_object_assert foos/test '{{.nestedField.newSubfield}}' 'subfield3'
|
|
|
|
# Delete the resource
|
|
kubectl "${kube_flags[@]}" delete -f hack/testdata/CRD/foo.yaml
|
|
|
|
# Make sure it's gone
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test that we can create list via apply
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/multi-crd-list.yaml
|
|
|
|
# Test that we have create a foo and a bar from a list
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" 'test-list:'
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" 'test-list:'
|
|
|
|
# Test that the field has the expected value
|
|
kube::test::get_object_assert foos/test-list '{{.someField}}' 'field1'
|
|
kube::test::get_object_assert bars/test-list '{{.someField}}' 'field1'
|
|
|
|
# Test that re-apply an list doesn't change anything
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/multi-crd-list.yaml
|
|
|
|
# Test that the field has the same value after re-apply
|
|
kube::test::get_object_assert foos/test-list '{{.someField}}' 'field1'
|
|
kube::test::get_object_assert bars/test-list '{{.someField}}' 'field1'
|
|
|
|
# Test that the fields have the expected value
|
|
kube::test::get_object_assert foos/test-list '{{.someField}}' 'field1'
|
|
kube::test::get_object_assert bars/test-list '{{.someField}}' 'field1'
|
|
|
|
# Update fields and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/multi-crd-list-updated-field.yaml
|
|
|
|
# Test that apply has updated the fields
|
|
kube::test::get_object_assert foos/test-list '{{.someField}}' 'modifiedField'
|
|
kube::test::get_object_assert bars/test-list '{{.someField}}' 'modifiedField'
|
|
|
|
# Test that the field has the expected value
|
|
kube::test::get_object_assert foos/test-list '{{.otherField}}' 'field2'
|
|
kube::test::get_object_assert bars/test-list '{{.otherField}}' 'field2'
|
|
|
|
# Delete fields and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/multi-crd-list-deleted-field.yaml
|
|
|
|
# Test that apply has deleted the fields
|
|
kube::test::get_object_assert foos/test-list '{{.otherField}}' '<no value>'
|
|
kube::test::get_object_assert bars/test-list '{{.otherField}}' '<no value>'
|
|
|
|
# Test that the fields does not exist
|
|
kube::test::get_object_assert foos/test-list '{{.newField}}' '<no value>'
|
|
kube::test::get_object_assert bars/test-list '{{.newField}}' '<no value>'
|
|
|
|
# Add a field and then apply the change
|
|
kubectl "${kube_flags[@]}" apply -f hack/testdata/CRD/multi-crd-list-added-field.yaml
|
|
|
|
# Test that apply has added the field
|
|
kube::test::get_object_assert foos/test-list '{{.newField}}' 'field3'
|
|
kube::test::get_object_assert bars/test-list '{{.newField}}' 'field3'
|
|
|
|
# Delete the resource
|
|
kubectl "${kube_flags[@]}" delete -f hack/testdata/CRD/multi-crd-list.yaml
|
|
|
|
# Make sure it's gone
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
## kubectl apply --prune
|
|
# Test that no foo or bar exist
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# apply --prune on foo.yaml that has foo/test
|
|
kubectl apply --prune -l pruneGroup=true -f hack/testdata/CRD/foo.yaml "${kube_flags[@]}" --prune-whitelist=company.com/v1/Foo --prune-whitelist=company.com/v1/Bar
|
|
# check right crds exist
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# apply --prune on bar.yaml that has bar/test
|
|
kubectl apply --prune -l pruneGroup=true -f hack/testdata/CRD/bar.yaml "${kube_flags[@]}" --prune-whitelist=company.com/v1/Foo --prune-whitelist=company.com/v1/Bar
|
|
# check right crds exist
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" 'test:'
|
|
|
|
# Delete the resource
|
|
kubectl "${kube_flags[@]}" delete -f hack/testdata/CRD/bar.yaml
|
|
|
|
# Make sure it's gone
|
|
kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
|
|
|
# Test 'kubectl create' with namespace, and namespace cleanup.
|
|
kubectl "${kube_flags[@]}" create namespace non-native-resources
|
|
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/bar.yaml --namespace=non-native-resources
|
|
kube::test::get_object_assert bars '{{len .items}}' '1' --namespace=non-native-resources
|
|
kubectl "${kube_flags[@]}" delete namespace non-native-resources
|
|
# Make sure objects go away.
|
|
kube::test::wait_object_assert bars '{{len .items}}' '0' --namespace=non-native-resources
|
|
# Make sure namespace goes away.
|
|
local tries=0
|
|
while kubectl "${kube_flags[@]}" get namespace non-native-resources && [ ${tries} -lt 10 ]; do
|
|
tries=$((tries+1))
|
|
sleep ${tries}
|
|
done
|
|
|
|
set +o nounset
|
|
set +o errexit
|
|
}
|