From f9590a33fde93176653d8805cbe7435d78cd3463 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Wed, 19 Aug 2015 22:18:59 -0400 Subject: [PATCH] Enable graceful deletion by enabling pods --- pkg/registry/pod/etcd/etcd_test.go | 13 ++++++++++- pkg/registry/pod/strategy.go | 36 +++++++++++++++++++++++++++++- test/e2e/pods.go | 7 +++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/pkg/registry/pod/etcd/etcd_test.go b/pkg/registry/pod/etcd/etcd_test.go index 38c05e8c8d2..9d129ba2cd6 100644 --- a/pkg/registry/pod/etcd/etcd_test.go +++ b/pkg/registry/pod/etcd/etcd_test.go @@ -143,8 +143,10 @@ func TestDelete(t *testing.T) { key = etcdtest.AddPrefix(key) test := resttest.New(t, storage, fakeClient.SetError) + expectedNode := "some-node" createFn := func() runtime.Object { pod := validChangedPod() + pod.Spec.NodeName = expectedNode fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ @@ -159,8 +161,17 @@ func TestDelete(t *testing.T) { if fakeClient.Data[key].R.Node == nil { return false } - return fakeClient.Data[key].R.Node.TTL == 30 + obj, err := testapi.Codec().Decode([]byte(fakeClient.Data[key].R.Node.Value)) + if err != nil { + return false + } + pod := obj.(*api.Pod) + t.Logf("found object %#v", pod.ObjectMeta) + return pod.DeletionTimestamp != nil && pod.DeletionGracePeriodSeconds != nil && *pod.DeletionGracePeriodSeconds != 0 } + test.TestDeleteGraceful(createFn, 30, gracefulSetFn) + + expectedNode = "" test.TestDelete(createFn, gracefulSetFn) } diff --git a/pkg/registry/pod/strategy.go b/pkg/registry/pod/strategy.go index ef10127e658..622c689bdba 100644 --- a/pkg/registry/pod/strategy.go +++ b/pkg/registry/pod/strategy.go @@ -81,15 +81,49 @@ func (podStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fiel return append(errorList, validation.ValidatePodUpdate(obj.(*api.Pod), old.(*api.Pod))...) } +// AllowUnconditionalUpdate allows pods to be overwritten func (podStrategy) AllowUnconditionalUpdate() bool { return true } -// CheckGracefulDelete allows a pod to be gracefully deleted. +// CheckGracefulDelete allows a pod to be gracefully deleted. It updates the DeleteOptions to +// reflect the desired grace value. func (podStrategy) CheckGracefulDelete(obj runtime.Object, options *api.DeleteOptions) bool { + if options == nil { + return false + } + pod := obj.(*api.Pod) + period := int64(0) + // user has specified a value + if options.GracePeriodSeconds != nil { + period = *options.GracePeriodSeconds + } else { + // use the default value if set, or deletes the pod immediately (0) + if pod.Spec.TerminationGracePeriodSeconds != nil { + period = *pod.Spec.TerminationGracePeriodSeconds + } + } + // if the pod is not scheduled, delete immediately + if len(pod.Spec.NodeName) == 0 { + period = 0 + } + // ensure the options and the pod are in sync + options.GracePeriodSeconds = &period + return true +} + +type podStrategyWithoutGraceful struct { + podStrategy +} + +// CheckGracefulDelete prohibits graceful deletion. +func (podStrategyWithoutGraceful) CheckGracefulDelete(obj runtime.Object, options *api.DeleteOptions) bool { return false } +// StrategyWithoutGraceful implements the legacy instant delele behavior. +var StrategyWithoutGraceful = podStrategyWithoutGraceful{Strategy} + type podStatusStrategy struct { podStrategy } diff --git a/test/e2e/pods.go b/test/e2e/pods.go index de881d1e567..4b9623d9f7b 100644 --- a/test/e2e/pods.go +++ b/test/e2e/pods.go @@ -255,7 +255,7 @@ var _ = Describe("Pods", func() { Fail("Timeout while waiting for pod creation") } - By("deleting the pod") + By("deleting the pod gracefully") if err := podClient.Delete(pod.Name, nil); err != nil { Failf("Failed to delete pod: %v", err) } @@ -263,11 +263,13 @@ var _ = Describe("Pods", func() { By("verifying pod deletion was observed") deleted := false timeout := false + var lastPod *api.Pod timer := time.After(podStartTimeout) for !deleted && !timeout { select { case event, _ := <-w.ResultChan(): if event.Type == watch.Deleted { + lastPod = event.Object.(*api.Pod) deleted = true } case <-timer: @@ -278,6 +280,9 @@ var _ = Describe("Pods", func() { Fail("Failed to observe pod deletion") } + Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) + Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) + pods, err = podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value})), fields.Everything()) if err != nil { Fail(fmt.Sprintf("Failed to list pods to verify deletion: %v", err))