Commit 4c31e985 authored by Rasmus Jönsson's avatar Rasmus Jönsson

Add support for waiting by label selector or on all resources

Add test for multiple deletions in kubectl watch
parent 0c2613c7
...@@ -90,6 +90,8 @@ func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams g ...@@ -90,6 +90,8 @@ func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams g
PrintFlags: genericclioptions.NewPrintFlags("condition met"), PrintFlags: genericclioptions.NewPrintFlags("condition met"),
ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags().
WithLabelSelector(""). WithLabelSelector("").
WithFieldSelector("").
WithAll(false).
WithAllNamespaces(false). WithAllNamespaces(false).
WithAll(false). WithAll(false).
WithLatest(), WithLatest(),
...@@ -105,11 +107,12 @@ func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams gen ...@@ -105,11 +107,12 @@ func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams gen
flags := NewWaitFlags(restClientGetter, streams) flags := NewWaitFlags(restClientGetter, streams)
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "wait resource.group/name [--for=delete|--for condition=available]", Use: "wait ([-f FILENAME] | resource.group/resource.name | resource.group [(-l label | --all)]) [--for=delete|--for condition=available]",
DisableFlagsInUseLine: true,
Short: "Experimental: Wait for a specific condition on one or many resources.", Short: "Experimental: Wait for a specific condition on one or many resources.",
Long: waitLong, Long: waitLong,
Example: waitExample, Example: waitExample,
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
o, err := flags.ToOptions(args) o, err := flags.ToOptions(args)
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
......
...@@ -311,6 +311,58 @@ func TestWaitForDeletion(t *testing.T) { ...@@ -311,6 +311,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", name: "ignores watch error",
infos: []*resource.Info{ infos: []*resource.Info{
{ {
......
...@@ -51,6 +51,7 @@ source "${KUBE_ROOT}/test/cmd/save-config.sh" ...@@ -51,6 +51,7 @@ source "${KUBE_ROOT}/test/cmd/save-config.sh"
source "${KUBE_ROOT}/test/cmd/storage.sh" source "${KUBE_ROOT}/test/cmd/storage.sh"
source "${KUBE_ROOT}/test/cmd/template-output.sh" source "${KUBE_ROOT}/test/cmd/template-output.sh"
source "${KUBE_ROOT}/test/cmd/version.sh" source "${KUBE_ROOT}/test/cmd/version.sh"
source "${KUBE_ROOT}/test/cmd/wait.sh"
ETCD_HOST=${ETCD_HOST:-127.0.0.1} ETCD_HOST=${ETCD_HOST:-127.0.0.1}
...@@ -832,6 +833,12 @@ runTests() { ...@@ -832,6 +833,12 @@ runTests() {
################# #################
record_command run_impersonation_tests record_command run_impersonation_tests
####################
# kubectl wait #
####################
record_command run_wait_tests
kube::test::clear_all kube::test::clear_all
if [[ -n "${foundError}" ]]; then if [[ -n "${foundError}" ]]; then
......
#!/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
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment