From 029acfc8aaf03c8c5c6b491a7cf2e47ab54d9830 Mon Sep 17 00:00:00 2001 From: derekwaynecarr Date: Sat, 7 May 2016 09:23:15 -0400 Subject: [PATCH] Allow handlers earlier in a request flow to inject a UID for an object --- pkg/api/context.go | 25 +++++++++++++++++++++---- pkg/api/meta.go | 8 +++++++- pkg/api/meta_test.go | 9 +++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/pkg/api/context.go b/pkg/api/context.go index 7e86395712..fcb6de7e57 100644 --- a/pkg/api/context.go +++ b/pkg/api/context.go @@ -22,6 +22,7 @@ import ( "golang.org/x/net/context" "k8s.io/kubernetes/pkg/auth/user" + "k8s.io/kubernetes/pkg/types" ) // Context carries values across API boundaries. @@ -49,11 +50,16 @@ type Context interface { // The key type is unexported to prevent collisions type key int -// namespaceKey is the context key for the request namespace. -const namespaceKey key = 0 +const ( + // namespaceKey is the context key for the request namespace. + namespaceKey key = iota -// userKey is the context key for the request user. -const userKey key = 1 + // userKey is the context key for the request user. + userKey + + // uidKey is the context key for the uid to assign to an object on create. + uidKey +) // NewContext instantiates a base context object for request flows. func NewContext() Context { @@ -119,3 +125,14 @@ func UserFrom(ctx Context) (user.Info, bool) { user, ok := ctx.Value(userKey).(user.Info) return user, ok } + +// WithUID returns a copy of parent in which the uid value is set +func WithUID(parent Context, uid types.UID) Context { + return WithValue(parent, uidKey, uid) +} + +// UIDFrom returns the value of the uid key on the ctx +func UIDFrom(ctx Context) (types.UID, bool) { + uid, ok := ctx.Value(uidKey).(types.UID) + return uid, ok +} diff --git a/pkg/api/meta.go b/pkg/api/meta.go index 9d5dae2c59..9f7a01b030 100644 --- a/pkg/api/meta.go +++ b/pkg/api/meta.go @@ -29,7 +29,13 @@ import ( // FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta. func FillObjectMetaSystemFields(ctx Context, meta *ObjectMeta) { meta.CreationTimestamp = unversioned.Now() - meta.UID = util.NewUUID() + // allows admission controllers to assign a UID earlier in the request processing + // to support tracking resources pending creation. + uid, found := UIDFrom(ctx) + if !found { + uid = util.NewUUID() + } + meta.UID = uid meta.SelfLink = "" } diff --git a/pkg/api/meta_test.go b/pkg/api/meta_test.go index bd8b5f9862..d3e08607e4 100644 --- a/pkg/api/meta_test.go +++ b/pkg/api/meta_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util" ) var _ meta.Object = &api.ObjectMeta{} @@ -42,6 +43,14 @@ func TestFillObjectMetaSystemFields(t *testing.T) { } else if len(resource.UID) == 0 { t.Errorf("resource.UID missing") } + // verify we can inject a UID + uid := util.NewUUID() + ctx = api.WithUID(ctx, uid) + resource = api.ObjectMeta{} + api.FillObjectMetaSystemFields(ctx, &resource) + if resource.UID != uid { + t.Errorf("resource.UID expected: %v, actual: %v", uid, resource.UID) + } } // TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated