Merge pull request #85571 from mgugino-upstream-stage/drain-ignore-pdbs

kubectl/drain: add disable-eviction option
This commit is contained in:
Kubernetes Prow Robot 2019-12-04 12:11:00 -08:00 committed by GitHub
commit b42f21982c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 80 deletions

View File

@ -192,6 +192,7 @@ func NewCmdDrain(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr
cmd.Flags().DurationVar(&o.drainer.Timeout, "timeout", o.drainer.Timeout, "The length of time to wait before giving up, zero means infinite")
cmd.Flags().StringVarP(&o.drainer.Selector, "selector", "l", o.drainer.Selector, "Selector (label query) to filter on")
cmd.Flags().StringVarP(&o.drainer.PodSelector, "pod-selector", "", o.drainer.PodSelector, "Label selector to filter pods on the node")
cmd.Flags().BoolVar(&o.drainer.DisableEviction, "disable-eviction", o.drainer.DisableEviction, "Force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets, use with caution.")
cmdutil.AddDryRunFlag(cmd)
return cmd

View File

@ -52,6 +52,10 @@ type Helper struct {
DeleteLocalData bool
Selector string
PodSelector string
// DisableEviction forces drain to use delete rather than evict
DisableEviction bool
Out io.Writer
ErrOut io.Writer
@ -179,18 +183,21 @@ func (d *Helper) DeleteOrEvictPods(pods []corev1.Pod) error {
return nil
}
// TODO(justinsb): unnecessary?
getPodFn := func(namespace, name string) (*corev1.Pod, error) {
return d.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
}
if !d.DisableEviction {
policyGroupVersion, err := CheckEvictionSupport(d.Client)
if err != nil {
return err
}
// TODO(justinsb): unnecessary?
getPodFn := func(namespace, name string) (*corev1.Pod, error) {
return d.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
}
if len(policyGroupVersion) > 0 {
return d.evictPods(pods, policyGroupVersion, getPodFn)
}
}
return d.deletePods(pods, getPodFn)
}

View File

@ -245,10 +245,34 @@ func TestCheckEvictionSupport(t *testing.T) {
}
func TestDeleteOrEvict(t *testing.T) {
for _, evictionSupported := range []bool{true, false} {
evictionSupported := evictionSupported
t.Run(fmt.Sprintf("evictionSupported=%v", evictionSupported),
func(t *testing.T) {
tests := []struct {
description string
evictionSupported bool
disableEviction bool
}{
{
description: "eviction supported/enabled",
evictionSupported: true,
disableEviction: false,
},
{
description: "eviction unsupported/disabled",
evictionSupported: false,
disableEviction: false,
},
{
description: "eviction supported/disabled",
evictionSupported: true,
disableEviction: true,
},
{
description: "eviction unsupported/disabled",
evictionSupported: false,
disableEviction: false,
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
h := &Helper{
Out: os.Stdout,
GracePeriodSeconds: 10,
@ -267,7 +291,7 @@ func TestDeleteOrEvict(t *testing.T) {
if i <= 2 {
deletePods = append(deletePods, *pod)
if evictionSupported {
if tc.evictionSupported && !tc.disableEviction {
eviction := policyv1beta1.Eviction{}
eviction.Kind = "Eviction"
eviction.APIVersion = "policy/v1"
@ -286,11 +310,11 @@ func TestDeleteOrEvict(t *testing.T) {
// Build the fake client
k := fake.NewSimpleClientset(create...)
if evictionSupported {
if tc.evictionSupported {
addEvictionSupport(t, k)
}
h.Client = k
h.DisableEviction = tc.disableEviction
// Do the eviction
if err := h.DeleteOrEvictPods(deletePods); err != nil {
t.Fatalf("error from DeleteOrEvictPods: %v", err)
@ -311,7 +335,7 @@ func TestDeleteOrEvict(t *testing.T) {
}
expected := []string{"default/mypod-3", "default/mypod-4"}
if !reflect.DeepEqual(remainingPods, expected) {
t.Errorf("unexpected remaining pods after DeleteOrEvictPods; actual %v; expected %v", remainingPods, expected)
t.Errorf("%s: unexpected remaining pods after DeleteOrEvictPods; actual %v; expected %v", tc.description, remainingPods, expected)
}
// Test that pods were evicted as expected
@ -327,7 +351,7 @@ func TestDeleteOrEvict(t *testing.T) {
return actualEvictions[i].Name < actualEvictions[j].Name
})
if !reflect.DeepEqual(actualEvictions, expectedEvictions) {
t.Errorf("unexpected evictions; actual %v; expected %v", actualEvictions, expectedEvictions)
t.Errorf("%s: unexpected evictions; actual %v; expected %v", tc.description, actualEvictions, expectedEvictions)
}
})
}