Add TerminationGracePeriodSeconds to API
Set defaulting for pod spec
This commit is contained in:
@@ -59,6 +59,8 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx api.Context, obj runtime.Obje
|
||||
} else {
|
||||
objectMeta.Namespace = api.NamespaceNone
|
||||
}
|
||||
objectMeta.DeletionTimestamp = nil
|
||||
objectMeta.DeletionGracePeriodSeconds = nil
|
||||
strategy.PrepareForCreate(obj)
|
||||
api.FillObjectMetaSystemFields(ctx, objectMeta)
|
||||
api.GenerateName(strategy, objectMeta)
|
||||
|
@@ -17,8 +17,11 @@ limitations under the License.
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
// RESTDeleteStrategy defines deletion behavior on an object that follows Kubernetes
|
||||
@@ -40,12 +43,41 @@ func BeforeDelete(strategy RESTDeleteStrategy, ctx api.Context, obj runtime.Obje
|
||||
if strategy == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
_, _, kerr := objectMetaAndKind(strategy, obj)
|
||||
objectMeta, _, kerr := objectMetaAndKind(strategy, obj)
|
||||
if kerr != nil {
|
||||
return false, false, kerr
|
||||
}
|
||||
|
||||
// if the object is already being deleted
|
||||
if objectMeta.DeletionTimestamp != nil {
|
||||
// if we are already being deleted, we may only shorten the deletion grace period
|
||||
// this means the object was gracefully deleted previously but deletionGracePeriodSeconds was not set,
|
||||
// so we force deletion immediately
|
||||
if objectMeta.DeletionGracePeriodSeconds == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
// only a shorter grace period may be provided by a user
|
||||
if options.GracePeriodSeconds != nil {
|
||||
period := int64(*options.GracePeriodSeconds)
|
||||
if period > *objectMeta.DeletionGracePeriodSeconds {
|
||||
return false, true, nil
|
||||
}
|
||||
now := util.NewTime(util.Now().Add(time.Second * time.Duration(*options.GracePeriodSeconds)))
|
||||
objectMeta.DeletionTimestamp = &now
|
||||
objectMeta.DeletionGracePeriodSeconds = &period
|
||||
options.GracePeriodSeconds = &period
|
||||
return true, false, nil
|
||||
}
|
||||
// graceful deletion is pending, do nothing
|
||||
options.GracePeriodSeconds = objectMeta.DeletionGracePeriodSeconds
|
||||
return false, true, nil
|
||||
}
|
||||
|
||||
if !strategy.CheckGracefulDelete(obj, options) {
|
||||
return false, false, nil
|
||||
}
|
||||
now := util.NewTime(util.Now().Add(time.Second * time.Duration(*options.GracePeriodSeconds)))
|
||||
objectMeta.DeletionTimestamp = &now
|
||||
objectMeta.DeletionGracePeriodSeconds = options.GracePeriodSeconds
|
||||
return true, false, nil
|
||||
}
|
||||
|
@@ -123,9 +123,9 @@ func (t *Tester) TestUpdate(valid runtime.Object, existing, older runtime.Object
|
||||
// Test deleting an object.
|
||||
// TODO(wojtek-t): Change it to use AssignFunc instead.
|
||||
func (t *Tester) TestDelete(createFn func() runtime.Object, wasGracefulFn func() bool, invalid ...runtime.Object) {
|
||||
t.testDeleteNonExist(createFn)
|
||||
t.testDeleteNoGraceful(createFn, wasGracefulFn)
|
||||
t.testDeleteInvokesValidation(invalid...)
|
||||
t.TestDeleteNonExist(createFn)
|
||||
t.TestDeleteNoGraceful(createFn, wasGracefulFn)
|
||||
t.TestDeleteInvokesValidation(invalid...)
|
||||
// TODO: Test delete namespace mismatch rejection
|
||||
// once #5684 is fixed.
|
||||
}
|
||||
@@ -133,8 +133,11 @@ func (t *Tester) TestDelete(createFn func() runtime.Object, wasGracefulFn func()
|
||||
// Test graceful deletion.
|
||||
// TODO(wojtek-t): Change it to use AssignFunc instead.
|
||||
func (t *Tester) TestDeleteGraceful(createFn func() runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
t.testDeleteGracefulHasDefault(createFn(), expectedGrace, wasGracefulFn)
|
||||
t.testDeleteGracefulUsesZeroOnNil(createFn(), 0)
|
||||
t.TestDeleteGracefulHasDefault(createFn(), expectedGrace, wasGracefulFn)
|
||||
t.TestDeleteGracefulWithValue(createFn(), expectedGrace, wasGracefulFn)
|
||||
t.TestDeleteGracefulUsesZeroOnNil(createFn(), 0)
|
||||
t.TestDeleteGracefulExtend(createFn(), expectedGrace, wasGracefulFn)
|
||||
t.TestDeleteGracefulImmediate(createFn(), expectedGrace, wasGracefulFn)
|
||||
}
|
||||
|
||||
// Test getting object.
|
||||
@@ -316,7 +319,7 @@ func (t *Tester) testUpdateFailsOnVersion(older runtime.Object) {
|
||||
// =============================================================================
|
||||
// Deletion tests.
|
||||
|
||||
func (t *Tester) testDeleteInvokesValidation(invalid ...runtime.Object) {
|
||||
func (t *Tester) TestDeleteInvokesValidation(invalid ...runtime.Object) {
|
||||
for i, obj := range invalid {
|
||||
objectMeta := t.getObjectMetaOrFail(obj)
|
||||
ctx := t.TestContext()
|
||||
@@ -327,7 +330,7 @@ func (t *Tester) testDeleteInvokesValidation(invalid ...runtime.Object) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tester) testDeleteNonExist(createFn func() runtime.Object) {
|
||||
func (t *Tester) TestDeleteNonExist(createFn func() runtime.Object) {
|
||||
existing := createFn()
|
||||
objectMeta := t.getObjectMetaOrFail(existing)
|
||||
context := t.TestContext()
|
||||
@@ -340,7 +343,10 @@ func (t *Tester) testDeleteNonExist(createFn func() runtime.Object) {
|
||||
})
|
||||
}
|
||||
|
||||
func (t *Tester) testDeleteNoGraceful(createFn func() runtime.Object, wasGracefulFn func() bool) {
|
||||
// =============================================================================
|
||||
// Graceful Deletion tests.
|
||||
|
||||
func (t *Tester) TestDeleteNoGraceful(createFn func() runtime.Object, wasGracefulFn func() bool) {
|
||||
existing := createFn()
|
||||
objectMeta := t.getObjectMetaOrFail(existing)
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
@@ -356,25 +362,142 @@ func (t *Tester) testDeleteNoGraceful(createFn func() runtime.Object, wasGracefu
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Graceful Deletion tests.
|
||||
|
||||
func (t *Tester) testDeleteGracefulHasDefault(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
func (t *Tester) TestDeleteGracefulHasDefault(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
objectMeta := t.getObjectMetaOrFail(existing)
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); err != nil {
|
||||
if !wasGracefulFn() {
|
||||
t.Errorf("did not gracefully delete resource")
|
||||
return
|
||||
}
|
||||
object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error, object should exist: %v", err)
|
||||
return
|
||||
}
|
||||
objectMeta, err = api.ObjectMetaFor(object)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, object)
|
||||
}
|
||||
if objectMeta.DeletionTimestamp == nil {
|
||||
t.Errorf("did not set deletion timestamp")
|
||||
}
|
||||
if objectMeta.DeletionGracePeriodSeconds == nil {
|
||||
t.Fatalf("did not set deletion grace period seconds")
|
||||
}
|
||||
if *objectMeta.DeletionGracePeriodSeconds != expectedGrace {
|
||||
t.Errorf("actual grace period does not match expected: %d", *objectMeta.DeletionGracePeriodSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tester) TestDeleteGracefulWithValue(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
objectMeta, err := api.ObjectMetaFor(existing)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing)
|
||||
}
|
||||
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !wasGracefulFn() {
|
||||
t.Errorf("did not gracefully delete resource")
|
||||
}
|
||||
object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error, object should exist: %v", err)
|
||||
}
|
||||
objectMeta, err = api.ObjectMetaFor(object)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, object)
|
||||
}
|
||||
if objectMeta.DeletionTimestamp == nil {
|
||||
t.Errorf("did not set deletion timestamp")
|
||||
}
|
||||
if objectMeta.DeletionGracePeriodSeconds == nil {
|
||||
t.Fatalf("did not set deletion grace period seconds")
|
||||
}
|
||||
if *objectMeta.DeletionGracePeriodSeconds != expectedGrace+2 {
|
||||
t.Errorf("actual grace period does not match expected: %d", *objectMeta.DeletionGracePeriodSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tester) testDeleteGracefulUsesZeroOnNil(existing runtime.Object, expectedGrace int64) {
|
||||
func (t *Tester) TestDeleteGracefulExtend(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
objectMeta, err := api.ObjectMetaFor(existing)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing)
|
||||
}
|
||||
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !wasGracefulFn() {
|
||||
t.Errorf("did not gracefully delete resource")
|
||||
}
|
||||
// second delete duration is ignored
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error, object should exist: %v", err)
|
||||
}
|
||||
objectMeta, err = api.ObjectMetaFor(object)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, object)
|
||||
}
|
||||
if objectMeta.DeletionTimestamp == nil {
|
||||
t.Errorf("did not set deletion timestamp")
|
||||
}
|
||||
if objectMeta.DeletionGracePeriodSeconds == nil {
|
||||
t.Fatalf("did not set deletion grace period seconds")
|
||||
}
|
||||
if *objectMeta.DeletionGracePeriodSeconds != expectedGrace {
|
||||
t.Errorf("actual grace period does not match expected: %d", *objectMeta.DeletionGracePeriodSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tester) TestDeleteGracefulImmediate(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
|
||||
objectMeta, err := api.ObjectMetaFor(existing)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing)
|
||||
}
|
||||
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !wasGracefulFn() {
|
||||
t.Errorf("did not gracefully delete resource")
|
||||
}
|
||||
// second delete is immediate, resource is deleted
|
||||
out, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(0))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
_, err = t.storage.(rest.Getter).Get(ctx, objectMeta.Name)
|
||||
if !errors.IsNotFound(err) {
|
||||
t.Errorf("unexpected error, object should be deleted immediately: %v", err)
|
||||
}
|
||||
objectMeta, err = api.ObjectMetaFor(out)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != 0 {
|
||||
t.Errorf("unexpected deleted meta: %#v", objectMeta)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tester) TestDeleteGracefulUsesZeroOnNil(existing runtime.Object, expectedGrace int64) {
|
||||
objectMeta := t.getObjectMetaOrFail(existing)
|
||||
ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace)
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil)
|
||||
@@ -382,7 +505,7 @@ func (t *Tester) testDeleteGracefulUsesZeroOnNil(existing runtime.Object, expect
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) {
|
||||
t.Errorf("unexpected error, object should exist: %v", err)
|
||||
t.Errorf("unexpected error, object should not exist: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user