diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go b/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go index f14a4627a7d..319658453e2 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go @@ -297,17 +297,18 @@ func (o *DrainCmdOptions) RunDrain() error { return err } - printObj, err := o.ToPrinter("drained") - if err != nil { - return err - } - drainedNodes := sets.NewString() var fatal error for _, info := range o.nodeInfos { if err := o.deleteOrEvictPodsSimple(info); err == nil { drainedNodes.Insert(info.Name) + + printObj, err := o.ToPrinter("drained") + if err != nil { + return err + } + printObj(info.Object, o.Out) } else { if o.drainer.IgnoreErrors && len(o.nodeInfos) > 1 { diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain_test.go index eacef7fd300..9a8fb6fdb93 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain_test.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain_test.go @@ -546,16 +546,18 @@ func TestDrain(t *testing.T) { expectWarning string expectFatal bool expectDelete bool + expectOutputToContain string }{ { - description: "RC-managed pod", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{rcPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, + description: "RC-managed pod", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{rcPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { description: "DS-managed pod", @@ -568,14 +570,15 @@ func TestDrain(t *testing.T) { expectDelete: false, }, { - description: "DS-managed terminated pod", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{dsTerminatedPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, + description: "DS-managed terminated pod", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{dsTerminatedPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { description: "orphaned DS-managed pod", @@ -588,76 +591,83 @@ func TestDrain(t *testing.T) { expectDelete: false, }, { - description: "orphaned DS-managed pod with --force", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{orphanedDsPod}, - rcs: []corev1.ReplicationController{}, - args: []string{"node", "--force"}, - expectFatal: false, - expectDelete: true, - expectWarning: "WARNING: deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: default/bar", + description: "orphaned DS-managed pod with --force", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{orphanedDsPod}, + rcs: []corev1.ReplicationController{}, + args: []string{"node", "--force"}, + expectFatal: false, + expectDelete: true, + expectWarning: "WARNING: deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: default/bar", + expectOutputToContain: "node/node drained", }, { - description: "DS-managed pod with --ignore-daemonsets", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{dsPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node", "--ignore-daemonsets"}, - expectFatal: false, - expectDelete: false, + description: "DS-managed pod with --ignore-daemonsets", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{dsPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node", "--ignore-daemonsets"}, + expectFatal: false, + expectDelete: false, + expectOutputToContain: "node/node drained", }, { - description: "DS-managed pod with emptyDir with --ignore-daemonsets", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{dsPodWithEmptyDir}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node", "--ignore-daemonsets"}, - expectWarning: "WARNING: ignoring DaemonSet-managed Pods: default/bar", - expectFatal: false, - expectDelete: false, + description: "DS-managed pod with emptyDir with --ignore-daemonsets", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{dsPodWithEmptyDir}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node", "--ignore-daemonsets"}, + expectWarning: "WARNING: ignoring DaemonSet-managed Pods: default/bar", + expectFatal: false, + expectDelete: false, + expectOutputToContain: "node/node drained", }, { - description: "Job-managed pod with local storage", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{jobPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node", "--force", "--delete-emptydir-data=true"}, - expectFatal: false, - expectDelete: true, + description: "Job-managed pod with local storage", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{jobPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node", "--force", "--delete-emptydir-data=true"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { - description: "Ensure compatibility for --delete-local-data until fully deprecated", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{jobPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node", "--force", "--delete-local-data=true"}, - expectFatal: false, - expectDelete: true, + description: "Ensure compatibility for --delete-local-data until fully deprecated", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{jobPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node", "--force", "--delete-local-data=true"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { - description: "Job-managed terminated pod", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{terminatedJobPodWithLocalStorage}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, + description: "Job-managed terminated pod", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{terminatedJobPodWithLocalStorage}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { - description: "RS-managed pod", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{rsPod}, - replicaSets: []appsv1.ReplicaSet{rs}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, + description: "RS-managed pod", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{rsPod}, + replicaSets: []appsv1.ReplicaSet{rs}, + args: []string{"node"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { description: "naked pod", @@ -670,14 +680,15 @@ func TestDrain(t *testing.T) { expectDelete: false, }, { - description: "naked pod with --force", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{nakedPod}, - rcs: []corev1.ReplicationController{}, - args: []string{"node", "--force"}, - expectFatal: false, - expectDelete: true, + description: "naked pod with --force", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{nakedPod}, + rcs: []corev1.ReplicationController{}, + args: []string{"node", "--force"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { description: "pod with EmptyDir", @@ -689,33 +700,36 @@ func TestDrain(t *testing.T) { expectDelete: false, }, { - description: "terminated pod with emptyDir", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{emptydirTerminatedPod}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, + description: "terminated pod with emptyDir", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{emptydirTerminatedPod}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { - description: "pod with EmptyDir and --delete-emptydir-data", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{emptydirPod}, - args: []string{"node", "--force", "--delete-emptydir-data=true"}, - expectFatal: false, - expectDelete: true, + description: "pod with EmptyDir and --delete-emptydir-data", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{emptydirPod}, + args: []string{"node", "--force", "--delete-emptydir-data=true"}, + expectFatal: false, + expectDelete: true, + expectOutputToContain: "node/node drained", }, { - description: "empty node", - node: node, - expected: cordonedNode, - pods: []corev1.Pod{}, - rcs: []corev1.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: false, + description: "empty node", + node: node, + expected: cordonedNode, + pods: []corev1.Pod{}, + rcs: []corev1.ReplicationController{rc}, + args: []string{"node"}, + expectFatal: false, + expectDelete: false, + expectOutputToContain: "node/node drained", }, { description: "fail to list pods", @@ -859,7 +873,7 @@ func TestDrain(t *testing.T) { } tf.ClientConfigVal = cmdtesting.DefaultClientConfig() - ioStreams, _, _, errBuf := genericclioptions.NewTestIOStreams() + ioStreams, _, outBuf, errBuf := genericclioptions.NewTestIOStreams() cmd := NewCmdDrain(tf, ioStreams) var recovered interface{} @@ -925,6 +939,13 @@ func TestDrain(t *testing.T) { t.Fatalf("%s: actual warning message did not match expected warning message.\n Expecting:\n%v\n Got:\n%v", test.description, e, a) } } + + if len(test.expectOutputToContain) > 0 { + out := outBuf.String() + if !strings.Contains(out, test.expectOutputToContain) { + t.Fatalf("%s: expected output to contain: %s\nGot:\n%s", test.description, test.expectOutputToContain, out) + } + } }) } }