From 15701ff403b9d25bf79c7df1ef440102f47954dd Mon Sep 17 00:00:00 2001 From: derekwaynecarr Date: Wed, 12 Nov 2014 16:27:10 -0500 Subject: [PATCH] Set uid during object create --- pkg/api/meta.go | 33 +++++++++++++++++++ pkg/api/meta_test.go | 48 ++++++++++++++++++++++++++++ pkg/registry/controller/rest.go | 2 +- pkg/registry/controller/rest_test.go | 3 ++ pkg/registry/endpoint/rest.go | 5 +-- pkg/registry/event/rest.go | 4 +-- pkg/registry/event/rest_test.go | 3 ++ pkg/registry/minion/rest.go | 3 +- pkg/registry/minion/rest_test.go | 3 ++ pkg/registry/pod/rest.go | 3 +- pkg/registry/pod/rest_test.go | 4 ++- pkg/registry/service/rest.go | 3 +- pkg/registry/service/rest_test.go | 3 ++ 13 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 pkg/api/meta.go create mode 100644 pkg/api/meta_test.go diff --git a/pkg/api/meta.go b/pkg/api/meta.go new file mode 100644 index 00000000000..1b7da4d2674 --- /dev/null +++ b/pkg/api/meta.go @@ -0,0 +1,33 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package api + +import ( + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" +) + +// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta. +func FillObjectMetaSystemFields(ctx Context, meta *ObjectMeta) { + meta.CreationTimestamp = util.Now() + meta.UID = util.NewUUID().String() +} + +// HasObjectMetaSystemFieldValues returns true if fields that are managed by the system on ObjectMeta have values. +func HasObjectMetaSystemFieldValues(meta *ObjectMeta) bool { + return !meta.CreationTimestamp.Time.IsZero() || + len(meta.UID) != 0 +} diff --git a/pkg/api/meta_test.go b/pkg/api/meta_test.go new file mode 100644 index 00000000000..d46963654db --- /dev/null +++ b/pkg/api/meta_test.go @@ -0,0 +1,48 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package api_test + +import ( + "testing" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" +) + +// TestFillObjectMetaSystemFields validates that system populated fields are set on an object +func TestFillObjectMetaSystemFields(t *testing.T) { + ctx := api.NewDefaultContext() + resource := api.ObjectMeta{} + api.FillObjectMetaSystemFields(ctx, &resource) + if resource.CreationTimestamp.Time.IsZero() { + t.Errorf("resource.CreationTimestamp is zero") + } else if len(resource.UID) == 0 { + t.Errorf("resource.UID missing") + } +} + +// TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated +func TestHasObjectMetaSystemFieldValues(t *testing.T) { + ctx := api.NewDefaultContext() + resource := api.ObjectMeta{} + if api.HasObjectMetaSystemFieldValues(&resource) { + t.Errorf("the resource does not have all fields yet populated, but incorrectly reports it does") + } + api.FillObjectMetaSystemFields(ctx, &resource) + if !api.HasObjectMetaSystemFieldValues(&resource) { + t.Errorf("the resource does have all fields populated, but incorrectly reports it does not") + } +} diff --git a/pkg/registry/controller/rest.go b/pkg/registry/controller/rest.go index bed047dc0b5..4aba1803402 100644 --- a/pkg/registry/controller/rest.go +++ b/pkg/registry/controller/rest.go @@ -68,7 +68,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE return nil, errors.NewInvalid("replicationController", controller.Name, errs) } - controller.CreationTimestamp = util.Now() + api.FillObjectMetaSystemFields(ctx, &controller.ObjectMeta) return apiserver.MakeAsync(func() (runtime.Object, error) { err := rs.registry.CreateController(ctx, controller) diff --git a/pkg/registry/controller/rest_test.go b/pkg/registry/controller/rest_test.go index 1606d2cc0ea..febe607f25d 100644 --- a/pkg/registry/controller/rest_test.go +++ b/pkg/registry/controller/rest_test.go @@ -264,6 +264,9 @@ func TestCreateController(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } + if !api.HasObjectMetaSystemFieldValues(&controller.ObjectMeta) { + t.Errorf("storage did not populate object meta field values") + } select { case <-channel: diff --git a/pkg/registry/endpoint/rest.go b/pkg/registry/endpoint/rest.go index 49f95f906c9..ac5c2c0e77d 100644 --- a/pkg/registry/endpoint/rest.go +++ b/pkg/registry/endpoint/rest.go @@ -24,7 +24,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" ) @@ -68,7 +67,9 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE if len(endpoints.Name) == 0 { return nil, fmt.Errorf("id is required: %#v", obj) } - endpoints.CreationTimestamp = util.Now() + + api.FillObjectMetaSystemFields(ctx, &endpoints.ObjectMeta) + return apiserver.MakeAsync(func() (runtime.Object, error) { err := rs.registry.UpdateEndpoints(ctx, endpoints) if err != nil { diff --git a/pkg/registry/event/rest.go b/pkg/registry/event/rest.go index 26f4948b6bd..a858a376ec0 100644 --- a/pkg/registry/event/rest.go +++ b/pkg/registry/event/rest.go @@ -24,7 +24,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" ) @@ -46,7 +45,8 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE if !ok { return nil, fmt.Errorf("invalid object type") } - event.CreationTimestamp = util.Now() + + api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta) return apiserver.MakeAsync(func() (runtime.Object, error) { err := rs.registry.Create(ctx, event.Name, event) diff --git a/pkg/registry/event/rest_test.go b/pkg/registry/event/rest_test.go index ae8e68e7cbb..40662e8f53c 100644 --- a/pkg/registry/event/rest_test.go +++ b/pkg/registry/event/rest_test.go @@ -48,6 +48,9 @@ func TestRESTCreate(t *testing.T) { if err != nil { t.Fatalf("Unexpected error %v", err) } + if !api.HasObjectMetaSystemFieldValues(&eventA.ObjectMeta) { + t.Errorf("storage did not populate object meta field values") + } if e, a := eventA, (<-c).Object; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } diff --git a/pkg/registry/minion/rest.go b/pkg/registry/minion/rest.go index 7f668ba7187..842e98b2124 100644 --- a/pkg/registry/minion/rest.go +++ b/pkg/registry/minion/rest.go @@ -29,7 +29,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) // REST implements the RESTStorage interface, backed by a MinionRegistry. @@ -57,7 +56,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE return nil, kerrors.NewInvalid("minion", minion.Name, errs) } - minion.CreationTimestamp = util.Now() + api.FillObjectMetaSystemFields(ctx, &minion.ObjectMeta) return apiserver.MakeAsync(func() (runtime.Object, error) { err := rs.registry.CreateMinion(ctx, minion) diff --git a/pkg/registry/minion/rest_test.go b/pkg/registry/minion/rest_test.go index bb94ec830ab..72baddbef56 100644 --- a/pkg/registry/minion/rest_test.go +++ b/pkg/registry/minion/rest_test.go @@ -43,6 +43,9 @@ func TestMinionREST(t *testing.T) { t.Errorf("insert failed") } obj := <-c + if !api.HasObjectMetaSystemFieldValues(&obj.Object.(*api.Minion).ObjectMeta) { + t.Errorf("storage did not populate object meta field values") + } if m, ok := obj.Object.(*api.Minion); !ok || m.Name != "baz" { t.Errorf("insert return value was weird: %#v", obj) } diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index 3f51d10904e..40d9e70fa09 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -100,7 +100,8 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE if errs := validation.ValidatePod(pod); len(errs) > 0 { return nil, errors.NewInvalid("pod", pod.Name, errs) } - pod.CreationTimestamp = util.Now() + + api.FillObjectMetaSystemFields(ctx, &pod.ObjectMeta) return apiserver.MakeAsync(func() (runtime.Object, error) { if err := rs.registry.CreatePod(ctx, pod); err != nil { diff --git a/pkg/registry/pod/rest_test.go b/pkg/registry/pod/rest_test.go index 8e38b1c6306..8ce317213dc 100644 --- a/pkg/registry/pod/rest_test.go +++ b/pkg/registry/pod/rest_test.go @@ -586,13 +586,15 @@ func TestCreatePod(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - select { case <-channel: // Do nothing, this is expected. case <-time.After(time.Millisecond * 100): t.Error("Unexpected timeout on async channel") } + if !api.HasObjectMetaSystemFieldValues(&podRegistry.Pod.ObjectMeta) { + t.Errorf("Expected ObjectMeta field values were populated") + } } type FakePodInfoGetter struct { diff --git a/pkg/registry/service/rest.go b/pkg/registry/service/rest.go index c20b470d00b..b85123e3ac9 100644 --- a/pkg/registry/service/rest.go +++ b/pkg/registry/service/rest.go @@ -31,7 +31,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/golang/glog" ) @@ -92,7 +91,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE return nil, errors.NewInvalid("service", service.Name, errs) } - service.CreationTimestamp = util.Now() + api.FillObjectMetaSystemFields(ctx, &service.ObjectMeta) if service.Spec.PortalIP == "" { // Allocate next available. diff --git a/pkg/registry/service/rest_test.go b/pkg/registry/service/rest_test.go index 172ebb6b518..874c46b4e4a 100644 --- a/pkg/registry/service/rest_test.go +++ b/pkg/registry/service/rest_test.go @@ -55,6 +55,9 @@ func TestServiceRegistryCreate(t *testing.T) { c, _ := storage.Create(ctx, svc) created_svc := <-c created_service := created_svc.Object.(*api.Service) + if !api.HasObjectMetaSystemFieldValues(&created_service.ObjectMeta) { + t.Errorf("storage did not populate object meta field values") + } if created_service.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service.Name) }