adding more callbacks in kubedrain helper

This commit is contained in:
adil ghaffar 2023-04-20 16:16:11 +03:00
parent 6e0cb243d5
commit 0323fe42e2
No known key found for this signature in database
GPG Key ID: DE3A415A4279FB36
3 changed files with 91 additions and 7 deletions

View File

@ -31,6 +31,7 @@ import (
"k8s.io/cli-runtime/pkg/genericiooptions" "k8s.io/cli-runtime/pkg/genericiooptions"
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/klog/v2"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/drain" "k8s.io/kubectl/pkg/drain"
"k8s.io/kubectl/pkg/scheme" "k8s.io/kubectl/pkg/scheme"
@ -156,24 +157,53 @@ func NewDrainCmdOptions(f cmdutil.Factory, ioStreams genericiooptions.IOStreams)
ChunkSize: cmdutil.DefaultChunkSize, ChunkSize: cmdutil.DefaultChunkSize,
}, },
} }
o.drainer.OnPodDeletedOrEvicted = o.onPodDeletedOrEvicted o.drainer.OnPodDeletionOrEvictionFinished = o.onPodDeletionOrEvictionFinished
o.drainer.OnPodDeletionOrEvictionStarted = o.onPodDeletionOrEvictionStarted
return o return o
} }
// onPodDeletedOrEvicted is called by drain.Helper, when the pod has been deleted or evicted // onPodDeletionOrEvictionFinished is called by drain.Helper, when eviction/deletetion of the pod is finished
func (o *DrainCmdOptions) onPodDeletedOrEvicted(pod *corev1.Pod, usingEviction bool) { func (o *DrainCmdOptions) onPodDeletionOrEvictionFinished(pod *corev1.Pod, usingEviction bool, err error) {
var verbStr string var verbStr string
if usingEviction { if usingEviction {
verbStr = "evicted" if err != nil {
verbStr = "eviction failed"
} else {
verbStr = "evicted"
}
} else { } else {
verbStr = "deleted" if err != nil {
verbStr = "deletion failed"
} else {
verbStr = "deleted"
}
} }
printObj, err := o.ToPrinter(verbStr) printObj, err := o.ToPrinter(verbStr)
if err != nil { if err != nil {
fmt.Fprintf(o.ErrOut, "error building printer: %v\n", err) fmt.Fprintf(o.ErrOut, "error building printer: %v\n", err)
fmt.Fprintf(o.Out, "pod %s/%s %s\n", pod.Namespace, pod.Name, verbStr) fmt.Fprintf(o.Out, "pod %s/%s %s\n", pod.Namespace, pod.Name, verbStr)
} else { } 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)
} }
} }

View File

@ -85,7 +85,14 @@ type Helper struct {
DryRunStrategy cmdutil.DryRunStrategy DryRunStrategy cmdutil.DryRunStrategy
// OnPodDeletedOrEvicted is called when a pod is evicted/deleted; for printing progress output // OnPodDeletedOrEvicted is called when a pod is evicted/deleted; for printing progress output
// Deprecated: use OnPodDeletionOrEvictionFinished instead
OnPodDeletedOrEvicted func(pod *corev1.Pod, usingEviction bool) 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 { type waitForDeleteParams struct {
@ -96,6 +103,7 @@ type waitForDeleteParams struct {
usingEviction bool usingEviction bool
getPodFn func(string, string) (*corev1.Pod, error) getPodFn func(string, string) (*corev1.Pod, error)
onDoneFn func(pod *corev1.Pod, usingEviction bool) onDoneFn func(pod *corev1.Pod, usingEviction bool)
onFinishFn func(pod *corev1.Pod, usingEviction bool, err error)
globalTimeout time.Duration globalTimeout time.Duration
skipWaitForDeleteTimeoutSeconds int skipWaitForDeleteTimeoutSeconds int
out io.Writer out io.Writer
@ -276,6 +284,9 @@ func (d *Helper) evictPods(pods []corev1.Pod, evictionGroupVersion schema.GroupV
case cmdutil.DryRunServer: case cmdutil.DryRunServer:
fmt.Fprintf(d.Out, "evicting pod %s/%s (server dry run)\n", pod.Namespace, pod.Name) fmt.Fprintf(d.Out, "evicting pod %s/%s (server dry run)\n", pod.Namespace, pod.Name)
default: default:
if d.OnPodDeletionOrEvictionStarted != nil {
d.OnPodDeletionOrEvictionStarted(&pod, true)
}
fmt.Fprintf(d.Out, "evicting pod %s/%s\n", pod.Namespace, pod.Name) fmt.Fprintf(d.Out, "evicting pod %s/%s\n", pod.Namespace, pod.Name)
} }
select { select {
@ -334,6 +345,7 @@ func (d *Helper) evictPods(pods []corev1.Pod, evictionGroupVersion schema.GroupV
usingEviction: true, usingEviction: true,
getPodFn: getPodFn, getPodFn: getPodFn,
onDoneFn: d.OnPodDeletedOrEvicted, onDoneFn: d.OnPodDeletedOrEvicted,
onFinishFn: d.OnPodDeletionOrEvictionFinished,
globalTimeout: globalTimeout, globalTimeout: globalTimeout,
skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds, skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds,
out: d.Out, 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) { if err != nil && !apierrors.IsNotFound(err) {
return err return err
} }
if d.OnPodDeletionOrEvictionStarted != nil {
d.OnPodDeletionOrEvictionStarted(&pod, false)
}
} }
ctx := d.getContext() ctx := d.getContext()
params := waitForDeleteParams{ params := waitForDeleteParams{
@ -387,6 +402,7 @@ func (d *Helper) deletePods(pods []corev1.Pod, getPodFn func(namespace, name str
usingEviction: false, usingEviction: false,
getPodFn: getPodFn, getPodFn: getPodFn,
onDoneFn: d.OnPodDeletedOrEvicted, onDoneFn: d.OnPodDeletedOrEvicted,
onFinishFn: d.OnPodDeletionOrEvictionFinished,
globalTimeout: globalTimeout, globalTimeout: globalTimeout,
skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds, skipWaitForDeleteTimeoutSeconds: d.SkipWaitForDeleteTimeoutSeconds,
out: d.Out, out: d.Out,
@ -402,11 +418,16 @@ func waitForDelete(params waitForDeleteParams) ([]corev1.Pod, error) {
for i, pod := range pods { for i, pod := range pods {
p, err := params.getPodFn(pod.Namespace, pod.Name) p, err := params.getPodFn(pod.Namespace, pod.Name)
if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) { 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) params.onDoneFn(&pod, params.usingEviction)
} }
continue continue
} else if err != nil { } else if err != nil {
if params.onFinishFn != nil {
params.onFinishFn(&pod, params.usingEviction, err)
}
return false, err return false, err
} else { } else {
if shouldSkipPod(*p, params.skipWaitForDeleteTimeoutSeconds) { if shouldSkipPod(*p, params.skipWaitForDeleteTimeoutSeconds) {

View File

@ -331,6 +331,39 @@ func TestDeleteOrEvict(t *testing.T) {
h := &Helper{ h := &Helper{
Out: os.Stdout, Out: os.Stdout,
GracePeriodSeconds: 10, 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 // Create 4 pods, and try to remove the first 2