Add support for waiting by label selector or on all resources

Add test for multiple deletions in kubectl watch
pull/564/head
Rasmus Jönsson 2018-12-05 12:24:50 +01:00
parent 0c2613c71a
commit 4c31e9855d
4 changed files with 116 additions and 4 deletions

View File

@ -90,6 +90,8 @@ func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams g
PrintFlags: genericclioptions.NewPrintFlags("condition met"),
ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags().
WithLabelSelector("").
WithFieldSelector("").
WithAll(false).
WithAllNamespaces(false).
WithAll(false).
WithLatest(),
@ -105,11 +107,12 @@ func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams gen
flags := NewWaitFlags(restClientGetter, streams)
cmd := &cobra.Command{
Use: "wait resource.group/name [--for=delete|--for condition=available]",
DisableFlagsInUseLine: true,
Use: "wait ([-f FILENAME] | resource.group/resource.name | resource.group [(-l label | --all)]) [--for=delete|--for condition=available]",
Short: "Experimental: Wait for a specific condition on one or many resources.",
Long: waitLong,
Example: waitExample,
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
o, err := flags.ToOptions(args)
cmdutil.CheckErr(err)

View File

@ -310,6 +310,58 @@ func TestWaitForDeletion(t *testing.T) {
}
},
},
{
name: "handles watch delete multiple",
infos: []*resource.Info{
{
Mapping: &meta.RESTMapping{
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource-1"},
},
Name: "name-foo-1",
Namespace: "ns-foo",
},
{
Mapping: &meta.RESTMapping{
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource-2"},
},
Name: "name-foo-2",
Namespace: "ns-foo",
},
},
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme)
fakeClient.PrependReactor("get", "theresource-1", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo-1"), nil
})
fakeClient.PrependReactor("get", "theresource-2", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo-2"), nil
})
fakeClient.PrependWatchReactor("theresource-1", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
fakeWatch := watch.NewRaceFreeFake()
fakeWatch.Action(watch.Deleted, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo-1"))
return true, fakeWatch, nil
})
fakeClient.PrependWatchReactor("theresource-2", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
fakeWatch := watch.NewRaceFreeFake()
fakeWatch.Action(watch.Deleted, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo-2"))
return true, fakeWatch, nil
})
return fakeClient
},
timeout: 10 * time.Second,
validateActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) != 2 {
t.Fatal(spew.Sdump(actions))
}
if !actions[0].Matches("list", "theresource-1") {
t.Error(spew.Sdump(actions))
}
if !actions[1].Matches("list", "theresource-2") {
t.Error(spew.Sdump(actions))
}
},
},
{
name: "ignores watch error",
infos: []*resource.Info{

View File

@ -51,6 +51,7 @@ source "${KUBE_ROOT}/test/cmd/save-config.sh"
source "${KUBE_ROOT}/test/cmd/storage.sh"
source "${KUBE_ROOT}/test/cmd/template-output.sh"
source "${KUBE_ROOT}/test/cmd/version.sh"
source "${KUBE_ROOT}/test/cmd/wait.sh"
ETCD_HOST=${ETCD_HOST:-127.0.0.1}
@ -832,6 +833,12 @@ runTests() {
#################
record_command run_impersonation_tests
####################
# kubectl wait #
####################
record_command run_wait_tests
kube::test::clear_all
if [[ -n "${foundError}" ]]; then

50
test/cmd/wait.sh Normal file
View File

@ -0,0 +1,50 @@
#!/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_wait_tests() {
set -o nounset
set -o errexit
kube::log::status "Testing kubectl wait"
create_and_use_new_namespace
### Wait for deletion using --all flag
# create test data
kubectl create deployment test-1 --image=busybox
kubectl create deployment test-2 --image=busybox
# Post-Condition: deployments exists
kube::test::get_object_assert "deployments" "{{range .items}}{{.metadata.name}},{{end}}" 'test-1,test-2,'
# Delete all deployments async to kubectl wait
( sleep 2 && kubectl delete deployment --all ) &
# Command: Wait for all deployments to be deleted
output_message=$(kubectl wait deployment --for=delete --all)
# Post-Condition: Wait was successful
kube::test::if_has_string "${output_message}" 'test-1 condition met'
kube::test::if_has_string "${output_message}" 'test-2 condition met'
set +o nounset
set +o errexit
}