Skip to content

Commit d1940c9

Browse files
Merge pull request kubernetes#17547 from juanvallejo/jvallejo/handle-ds-pod-drain-local-storage
Automatic merge from submit-queue (batch tested with PRs 17547, 18151). UPSTREAM: 56713: Allow oadm drain to continue w ds-managed pods with local storage Fixes openshift/origin#17522 UPSTREAM: kubernetes#56713 Prevents oadm drain from failing if it encounters DaemonSet-managed pods that have local storage, when the option to ignore DaemonSet-managed pods has been specified. Will add tests cc @openshift/cli-review @dustymabe @deads2k Origin-commit: 1c8ec8f29d1fd182c8329d57e1bd22286b8fd7c9
2 parents cf97dae + de3cbf9 commit d1940c9

File tree

2 files changed

+74
-11
lines changed

2 files changed

+74
-11
lines changed

pkg/kubectl/cmd/drain.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []corev
445445

446446
for _, pod := range podList.Items {
447447
podOk := true
448-
for _, filt := range []podFilter{mirrorPodFilter, o.localStorageFilter, o.unreplicatedFilter, o.daemonsetFilter} {
448+
for _, filt := range []podFilter{o.daemonsetFilter, mirrorPodFilter, o.localStorageFilter, o.unreplicatedFilter} {
449449
filterOk, w, f := filt(pod)
450450

451451
podOk = podOk && filterOk
@@ -455,6 +455,13 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []corev
455455
if f != nil {
456456
fs[f.string] = append(fs[f.string], pod.Name)
457457
}
458+
459+
// short-circuit as soon as pod not ok
460+
// at that point, there is no reason to run pod
461+
// through any additional filters
462+
if !podOk {
463+
break
464+
}
458465
}
459466
if podOk {
460467
pods = append(pods, pod)

pkg/kubectl/cmd/drain_test.go

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,34 @@ func TestDrain(t *testing.T) {
304304
},
305305
}
306306

307+
ds_pod_with_emptyDir := corev1.Pod{
308+
ObjectMeta: metav1.ObjectMeta{
309+
Name: "bar",
310+
Namespace: "default",
311+
CreationTimestamp: metav1.Time{Time: time.Now()},
312+
Labels: labels,
313+
SelfLink: testapi.Default.SelfLink("pods", "bar"),
314+
OwnerReferences: []metav1.OwnerReference{
315+
{
316+
APIVersion: "extensions/v1beta1",
317+
Kind: "DaemonSet",
318+
Name: "ds",
319+
BlockOwnerDeletion: boolptr(true),
320+
Controller: boolptr(true),
321+
},
322+
},
323+
},
324+
Spec: corev1.PodSpec{
325+
NodeName: "node",
326+
Volumes: []corev1.Volume{
327+
{
328+
Name: "scratch",
329+
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{Medium: ""}},
330+
},
331+
},
332+
},
333+
}
334+
307335
orphaned_ds_pod := corev1.Pod{
308336
ObjectMeta: metav1.ObjectMeta{
309337
Name: "bar",
@@ -414,15 +442,16 @@ func TestDrain(t *testing.T) {
414442
}
415443

416444
tests := []struct {
417-
description string
418-
node *corev1.Node
419-
expected *corev1.Node
420-
pods []corev1.Pod
421-
rcs []api.ReplicationController
422-
replicaSets []extensions.ReplicaSet
423-
args []string
424-
expectFatal bool
425-
expectDelete bool
445+
description string
446+
node *corev1.Node
447+
expected *corev1.Node
448+
pods []corev1.Pod
449+
rcs []api.ReplicationController
450+
replicaSets []extensions.ReplicaSet
451+
args []string
452+
expectWarning string
453+
expectFatal bool
454+
expectDelete bool
426455
}{
427456
{
428457
description: "RC-managed pod",
@@ -474,6 +503,17 @@ func TestDrain(t *testing.T) {
474503
expectFatal: false,
475504
expectDelete: false,
476505
},
506+
{
507+
description: "DS-managed pod with emptyDir with --ignore-daemonsets",
508+
node: node,
509+
expected: cordoned_node,
510+
pods: []corev1.Pod{ds_pod_with_emptyDir},
511+
rcs: []api.ReplicationController{rc},
512+
args: []string{"node", "--ignore-daemonsets"},
513+
expectWarning: "WARNING: Ignoring DaemonSet-managed pods: bar\n",
514+
expectFatal: false,
515+
expectDelete: false,
516+
},
477517
{
478518
description: "Job-managed pod",
479519
node: node,
@@ -661,21 +701,27 @@ func TestDrain(t *testing.T) {
661701
cmd := NewCmdDrain(f, buf, errBuf)
662702

663703
saw_fatal := false
704+
fatal_msg := ""
664705
func() {
665706
defer func() {
666707
// Recover from the panic below.
667708
_ = recover()
668709
// Restore cmdutil behavior
669710
cmdutil.DefaultBehaviorOnFatal()
670711
}()
671-
cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; panic(e) })
712+
cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; fatal_msg = e; panic(e) })
713+
672714
cmd.SetArgs(test.args)
673715
cmd.Execute()
674716
}()
675717
if test.expectFatal {
676718
if !saw_fatal {
677719
t.Fatalf("%s: unexpected non-error when using %s", test.description, currMethod)
678720
}
721+
} else {
722+
if saw_fatal {
723+
t.Fatalf("%s: unexpected error when using %s: %s", test.description, currMethod, fatal_msg)
724+
}
679725
}
680726

681727
if test.expectDelete {
@@ -693,6 +739,16 @@ func TestDrain(t *testing.T) {
693739
t.Fatalf("%s: unexpected delete when using %s", test.description, currMethod)
694740
}
695741
}
742+
743+
if len(test.expectWarning) > 0 {
744+
if len(errBuf.String()) == 0 {
745+
t.Fatalf("%s: expected warning, but found no stderr output", test.description)
746+
}
747+
748+
if errBuf.String() != test.expectWarning {
749+
t.Fatalf("%s: actual warning message did not match expected warning message.\n Expecting: %s\n Got: %s", test.description, test.expectWarning, errBuf.String())
750+
}
751+
}
696752
}
697753
}
698754
}

0 commit comments

Comments
 (0)