From 0323fe42e23aee176ff14f3385bc15e81216c7bb Mon Sep 17 00:00:00 2001 From: adil ghaffar Date: Thu, 20 Apr 2023 16:16:11 +0300 Subject: [PATCH] adding more callbacks in kubedrain helper --- .../src/k8s.io/kubectl/pkg/cmd/drain/drain.go | 42 ++++++++++++++++--- staging/src/k8s.io/kubectl/pkg/drain/drain.go | 23 +++++++++- .../k8s.io/kubectl/pkg/drain/drain_test.go | 33 +++++++++++++++ 3 files changed, 91 insertions(+), 7 deletions(-) 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 5d9922c6fb0..d8bc03ac034 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go @@ -31,6 +31,7 @@ import ( "k8s.io/cli-runtime/pkg/genericiooptions" "k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/resource" + "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/drain" "k8s.io/kubectl/pkg/scheme" @@ -156,24 +157,53 @@ func NewDrainCmdOptions(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) ChunkSize: cmdutil.DefaultChunkSize, }, } - o.drainer.OnPodDeletedOrEvicted = o.onPodDeletedOrEvicted + o.drainer.OnPodDeletionOrEvictionFinished = o.onPodDeletionOrEvictionFinished + o.drainer.OnPodDeletionOrEvictionStarted = o.onPodDeletionOrEvictionStarted return o } -// onPodDeletedOrEvicted is called by drain.Helper, when the pod has been deleted or evicted -func (o *DrainCmdOptions) onPodDeletedOrEvicted(pod *corev1.Pod, usingEviction bool) { +// onPodDeletionOrEvictionFinished is called by drain.Helper, when eviction/deletetion of the pod is finished +func (o *DrainCmdOptions) onPodDeletionOrEvictionFinished(pod *corev1.Pod, usingEviction bool, err error) { var verbStr string if usingEviction { - verbStr = "evicted" + if err != nil { + verbStr = "eviction failed" + } else { + verbStr = "evicted" + } } else { - verbStr = "deleted" + if err != nil { + verbStr = "deletion failed" + } else { + verbStr = "deleted" + } } printObj, err := o.ToPrinter(verbStr) if err != nil { fmt.Fprintf(o.ErrOut, "error building printer: %v\n", err) fmt.Fprintf(o.Out, "pod %s/%s %s\n", pod.Namespace, pod.Name, verbStr) } else { - printObj(pod, o.Out) + _ = printObj(pod, o.Out) + } +} + +// onPodDeletionOrEvictionStarted is called by drain.Helper, when eviction/deletion of the pod is started +func (o *DrainCmdOptions) onPodDeletionOrEvictionStarted(pod *corev1.Pod, usingEviction bool) { + if !klog.V(2).Enabled() { + return + } + var verbStr string + if usingEviction { + verbStr = "eviction started" + } else { + verbStr = "deletion started" + } + printObj, err := o.ToPrinter(verbStr) + if err != nil { + fmt.Fprintf(o.ErrOut, "error building printer: %v\n", err) + fmt.Fprintf(o.Out, "pod %s/%s %s\n", pod.Namespace, pod.Name, verbStr) + } else { + _ = printObj(pod, o.Out) } } diff --git a/staging/src/k8s.io/kubectl/pkg/drain/drain.go b/staging/src/k8s.io/kubectl/pkg/drain/drain.go index 5a5c9f44d52..1f6502eda6d 100644 --- a/staging/src/k8s.io/kubectl/pkg/drain/drain.go +++ b/staging/src/k8s.io/kubectl/pkg/drain/drain.go @@ -85,7 +85,14 @@ type Helper struct { DryRunStrategy cmdutil.DryRunStrategy // OnPodDeletedOrEvicted is called when a pod is evicted/deleted; for printing progress output + // Deprecated: use OnPodDeletionOrEvictionFinished instead OnPodDeletedOrEvicted func(pod *corev1.Pod, usingEviction bool) + + // OnPodDeletionOrEvictionFinished is called when a pod is eviction/deletetion is failed; for printing progress output + OnPodDeletionOrEvictionFinished func(pod *corev1.Pod, usingEviction bool, err error) + + // OnPodDeletionOrEvictionStarted is called when a pod eviction/deletion is started; for printing progress output + OnPodDeletionOrEvictionStarted func(pod *corev1.Pod, usingEviction bool) } type waitForDeleteParams struct { @@ -96,6 +103,7 @@ type waitForDeleteParams struct { usingEviction bool getPodFn func(string, string) (*corev1.Pod, error) onDoneFn func(pod *corev1.Pod, usingEviction bool) + onFinishFn func(pod *corev1.Pod, usingEviction bool, err error) globalTimeout time.Duration skipWaitForDeleteTimeoutSeconds int out io.Writer @@ -276,6 +284,9 @@ func (d *Helper) evictPods(pods []corev1.Pod, evictionGroupVersion schema.GroupV case cmdutil.DryRunServer: fmt.Fprintf(d.Out, "evicting pod %s/%s (server dry run)\n", pod.Namespace, pod.Name) default: + if d.OnPodDeletionOrEvictionStarted != nil { + d.OnPodDeletionOrEvictionStarted(&pod, true) + } fmt.Fprintf(d.Out, "evicting pod %s/%s\n", pod.Namespace, pod.Name) } select { @@ -334,6 +345,7 @@ func (d *Helper) evictPods(pods []corev1.Pod, evictionGroupVersion schema.GroupV usingEviction: true, getPodFn: getPodFn, onDoneFn: d.OnPodDeletedOrEvicted, + onFinishFn: d.OnPodDeletionOrEvictionFinished, globalTimeout: globalTimeout, skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds, out: d.Out, @@ -377,6 +389,9 @@ func (d *Helper) deletePods(pods []corev1.Pod, getPodFn func(namespace, name str if err != nil && !apierrors.IsNotFound(err) { return err } + if d.OnPodDeletionOrEvictionStarted != nil { + d.OnPodDeletionOrEvictionStarted(&pod, false) + } } ctx := d.getContext() params := waitForDeleteParams{ @@ -387,6 +402,7 @@ func (d *Helper) deletePods(pods []corev1.Pod, getPodFn func(namespace, name str usingEviction: false, getPodFn: getPodFn, onDoneFn: d.OnPodDeletedOrEvicted, + onFinishFn: d.OnPodDeletionOrEvictionFinished, globalTimeout: globalTimeout, skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds, out: d.Out, @@ -402,11 +418,16 @@ func waitForDelete(params waitForDeleteParams) ([]corev1.Pod, error) { for i, pod := range pods { p, err := params.getPodFn(pod.Namespace, pod.Name) if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) { - if params.onDoneFn != nil { + if params.onFinishFn != nil { + params.onFinishFn(&pod, params.usingEviction, nil) + } else if params.onDoneFn != nil { params.onDoneFn(&pod, params.usingEviction) } continue } else if err != nil { + if params.onFinishFn != nil { + params.onFinishFn(&pod, params.usingEviction, err) + } return false, err } else { if shouldSkipPod(*p, params.skipWaitForDeleteTimeoutSeconds) { diff --git a/staging/src/k8s.io/kubectl/pkg/drain/drain_test.go b/staging/src/k8s.io/kubectl/pkg/drain/drain_test.go index 78efab1fdc9..c3cc84869bc 100644 --- a/staging/src/k8s.io/kubectl/pkg/drain/drain_test.go +++ b/staging/src/k8s.io/kubectl/pkg/drain/drain_test.go @@ -331,6 +331,39 @@ func TestDeleteOrEvict(t *testing.T) { h := &Helper{ Out: os.Stdout, GracePeriodSeconds: 10, + OnPodDeletionOrEvictionStarted: func(pod *corev1.Pod, usingEviction bool) { + if tc.evictionSupported && !tc.disableEviction { + if !usingEviction { + t.Errorf("%s: OnPodDeletionOrEvictionStarted callback failed while evicting; actual\n\t%v\nexpected\n\t%v", tc.description, usingEviction, !usingEviction) + } + } else if tc.evictionSupported && tc.disableEviction { + if usingEviction { + t.Errorf("%s: OnPodDeletionOrEvictionStarted callback failed while deleting; actual\n\t%v\nexpected\n\t%v", tc.description, !usingEviction, usingEviction) + } + } + }, + OnPodDeletedOrEvicted: func(pod *corev1.Pod, usingEviction bool) { + if tc.evictionSupported && !tc.disableEviction { + if !usingEviction { + t.Errorf("%s: OnPodDeletedOrEvicted callback failed while evicting; actual\n\t%v\nexpected\n\t%v", tc.description, usingEviction, !usingEviction) + } + } else if tc.evictionSupported && tc.disableEviction { + if usingEviction { + t.Errorf("%s: OnPodDeletedOrEvicted callback failed while deleting; actual\n\t%v\nexpected\n\t%v", tc.description, !usingEviction, usingEviction) + } + } + }, + OnPodDeletionOrEvictionFinished: func(pod *corev1.Pod, usingEviction bool, err error) { + if tc.evictionSupported && !tc.disableEviction { + if !usingEviction { + t.Errorf("%s: OnPodDeletionOrEvictionFinished callback failed while evicting; actual\n\t%v\nexpected\n\t%v", tc.description, usingEviction, !usingEviction) + } + } else if tc.evictionSupported && tc.disableEviction { + if usingEviction { + t.Errorf("%s: OnPodDeletionOrEvictionFinished callback failed while deleting; actual\n\t%v\nexpected\n\t%v", tc.description, !usingEviction, usingEviction) + } + } + }, } // Create 4 pods, and try to remove the first 2