Initialize UID earlier in the Create process
Before: Create() BeginCreate() BeforeCreate() init UID <--------------------- strategy code After: Create() init UID <------------------------- BeginCreate() BeforeCreate() strategy code This also wipes UID early (suggested by David) and asserts it is set in BeforeCreate(). Kubernetes-commit: 5615de51f9e768dd01d7fe49a48e8db756bd8ac8
This commit is contained in:
parent
010d9e3ada
commit
970b3ee9bb
|
@ -163,8 +163,10 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int
|
||||||
|
|
||||||
userInfo, _ := request.UserFrom(ctx)
|
userInfo, _ := request.UserFrom(ctx)
|
||||||
|
|
||||||
// if this object supports namespace info
|
|
||||||
if objectMeta, err := meta.Accessor(obj); err == nil {
|
if objectMeta, err := meta.Accessor(obj); err == nil {
|
||||||
|
// Wipe fields which cannot take user-provided values
|
||||||
|
rest.WipeObjectMetaSystemFields(objectMeta)
|
||||||
|
|
||||||
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
||||||
if err := rest.EnsureObjectNamespaceMatchesRequestNamespace(rest.ExpectedNamespaceForResource(namespace, scope.Resource), objectMeta); err != nil {
|
if err := rest.EnsureObjectNamespaceMatchesRequestNamespace(rest.ExpectedNamespaceForResource(namespace, scope.Resource), objectMeta); err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
|
|
|
@ -382,6 +382,13 @@ func finishNothing(context.Context, bool) {}
|
||||||
func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||||
var finishCreate FinishFunc = finishNothing
|
var finishCreate FinishFunc = finishNothing
|
||||||
|
|
||||||
|
// Init metadata as early as possible.
|
||||||
|
if objectMeta, err := meta.Accessor(obj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
rest.FillObjectMetaSystemFields(objectMeta)
|
||||||
|
}
|
||||||
|
|
||||||
if e.BeginCreate != nil {
|
if e.BeginCreate != nil {
|
||||||
fn, err := e.BeginCreate(ctx, obj, options)
|
fn, err := e.BeginCreate(ctx, obj, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -558,6 +565,13 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||||
doUnconditionalUpdate := newResourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
|
doUnconditionalUpdate := newResourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
|
||||||
|
|
||||||
if existingResourceVersion == 0 {
|
if existingResourceVersion == 0 {
|
||||||
|
// Init metadata as early as possible.
|
||||||
|
if objectMeta, err := meta.Accessor(obj); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
} else {
|
||||||
|
rest.FillObjectMetaSystemFields(objectMeta)
|
||||||
|
}
|
||||||
|
|
||||||
var finishCreate FinishFunc = finishNothing
|
var finishCreate FinishFunc = finishNothing
|
||||||
|
|
||||||
if e.BeginCreate != nil {
|
if e.BeginCreate != nil {
|
||||||
|
|
|
@ -100,6 +100,11 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||||
return kerr
|
return kerr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure that system-critical metadata has been populated
|
||||||
|
if !metav1.HasObjectMetaSystemFieldValues(objectMeta) {
|
||||||
|
return errors.NewInternalError(fmt.Errorf("system metadata was not initialized"))
|
||||||
|
}
|
||||||
|
|
||||||
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
||||||
requestNamespace, ok := genericapirequest.NamespaceFrom(ctx)
|
requestNamespace, ok := genericapirequest.NamespaceFrom(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -109,10 +114,7 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
objectMeta.SetDeletionTimestamp(nil)
|
|
||||||
objectMeta.SetDeletionGracePeriodSeconds(nil)
|
|
||||||
strategy.PrepareForCreate(ctx, obj)
|
strategy.PrepareForCreate(ctx, obj)
|
||||||
FillObjectMetaSystemFields(objectMeta)
|
|
||||||
|
|
||||||
if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
|
if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
|
||||||
objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName()))
|
objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName()))
|
||||||
|
|
|
@ -23,11 +23,19 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WipeObjectMetaSystemFields erases fields that are managed by the system on ObjectMeta.
|
||||||
|
func WipeObjectMetaSystemFields(meta metav1.Object) {
|
||||||
|
meta.SetCreationTimestamp(metav1.Time{})
|
||||||
|
meta.SetUID("")
|
||||||
|
meta.SetDeletionTimestamp(nil)
|
||||||
|
meta.SetDeletionGracePeriodSeconds(nil)
|
||||||
|
meta.SetSelfLink("")
|
||||||
|
}
|
||||||
|
|
||||||
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
|
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
|
||||||
func FillObjectMetaSystemFields(meta metav1.Object) {
|
func FillObjectMetaSystemFields(meta metav1.Object) {
|
||||||
meta.SetCreationTimestamp(metav1.Now())
|
meta.SetCreationTimestamp(metav1.Now())
|
||||||
meta.SetUID(uuid.NewUUID())
|
meta.SetUID(uuid.NewUUID())
|
||||||
meta.SetSelfLink("")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureObjectNamespaceMatchesRequestNamespace returns an error if obj.Namespace and requestNamespace
|
// EnsureObjectNamespaceMatchesRequestNamespace returns an error if obj.Namespace and requestNamespace
|
||||||
|
|
|
@ -23,14 +23,33 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestWipeObjectMetaSystemFields validates that system populated fields are set on an object
|
||||||
|
func TestWipeObjectMetaSystemFields(t *testing.T) {
|
||||||
|
resource := metav1.ObjectMeta{}
|
||||||
|
WipeObjectMetaSystemFields(&resource)
|
||||||
|
if !resource.CreationTimestamp.Time.IsZero() {
|
||||||
|
t.Errorf("resource.CreationTimestamp is set")
|
||||||
|
}
|
||||||
|
if len(resource.UID) != 0 {
|
||||||
|
t.Errorf("resource.UID is set")
|
||||||
|
}
|
||||||
|
if resource.DeletionTimestamp != nil {
|
||||||
|
t.Errorf("resource.DeletionTimestamp is set")
|
||||||
|
}
|
||||||
|
if resource.DeletionGracePeriodSeconds != nil {
|
||||||
|
t.Errorf("resource.DeletionGracePeriodSeconds is set")
|
||||||
|
}
|
||||||
|
if len(resource.SelfLink) != 0 {
|
||||||
|
t.Errorf("resource.SelfLink is set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestFillObjectMetaSystemFields validates that system populated fields are set on an object
|
// TestFillObjectMetaSystemFields validates that system populated fields are set on an object
|
||||||
func TestFillObjectMetaSystemFields(t *testing.T) {
|
func TestFillObjectMetaSystemFields(t *testing.T) {
|
||||||
resource := metav1.ObjectMeta{}
|
resource := metav1.ObjectMeta{}
|
||||||
FillObjectMetaSystemFields(&resource)
|
FillObjectMetaSystemFields(&resource)
|
||||||
if resource.CreationTimestamp.Time.IsZero() {
|
if resource.CreationTimestamp.Time.IsZero() {
|
||||||
t.Errorf("resource.CreationTimestamp is zero")
|
t.Errorf("resource.CreationTimestamp is zero")
|
||||||
} else if len(resource.UID) == 0 {
|
|
||||||
t.Errorf("resource.UID missing")
|
|
||||||
}
|
}
|
||||||
if len(resource.UID) == 0 {
|
if len(resource.UID) == 0 {
|
||||||
t.Errorf("resource.UID missing")
|
t.Errorf("resource.UID missing")
|
||||||
|
|
Loading…
Reference in New Issue