From a131a5e491d30a313ba96a5e713597effffb381d Mon Sep 17 00:00:00 2001 From: Paul Morie Date: Wed, 18 Feb 2015 13:02:22 -0500 Subject: [PATCH] Add test for secret RESTStorage --- pkg/registry/registrytest/generic.go | 3 +- pkg/registry/secret/rest.go | 26 +++- pkg/registry/secret/rest_test.go | 212 +++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 pkg/registry/secret/rest_test.go diff --git a/pkg/registry/registrytest/generic.go b/pkg/registry/registrytest/generic.go index d02cd3a484f..820528f4aee 100644 --- a/pkg/registry/registrytest/generic.go +++ b/pkg/registry/registrytest/generic.go @@ -25,8 +25,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" ) -// GenericRegistry knows how to store & list any runtime.Object. Events don't require -// any non-generic features from the storage layer. +// GenericRegistry knows how to store & list any runtime.Object. type GenericRegistry struct { Err error Object runtime.Object diff --git a/pkg/registry/secret/rest.go b/pkg/registry/secret/rest.go index 65f21269e1e..8bdec0de328 100644 --- a/pkg/registry/secret/rest.go +++ b/pkg/registry/secret/rest.go @@ -70,19 +70,19 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err } // Update updates a Secret object. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { secret, ok := obj.(*api.Secret) if !ok { - return nil, fmt.Errorf("not a secret: %#v", obj) + return nil, false, fmt.Errorf("not a secret: %#v", obj) } if !api.ValidNamespace(ctx, &secret.ObjectMeta) { - return nil, errors.NewConflict("secret", secret.Namespace, fmt.Errorf("Secret.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("secret", secret.Namespace, fmt.Errorf("Secret.Namespace does not match the provided context")) } oldObj, err := rs.registry.Get(ctx, secret.Name) if err != nil { - return nil, err + return nil, false, err } editSecret := oldObj.(*api.Secret) @@ -91,16 +91,19 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, err editSecret.Labels = secret.Labels editSecret.ResourceVersion = secret.ResourceVersion editSecret.Annotations = secret.Annotations + editSecret.Data = secret.Data + editSecret.Type = secret.Type if errs := validation.ValidateSecret(editSecret); len(errs) > 0 { - return nil, errors.NewInvalid("secret", editSecret.Name, errs) + return nil, false, errors.NewInvalid("secret", editSecret.Name, errs) } err = rs.registry.UpdateWithName(ctx, editSecret.Name, editSecret) if err != nil { - return nil, err + return nil, false, err } - return rs.registry.Get(ctx, editSecret.Name) + out, err := rs.registry.Get(ctx, editSecret.Name) + return out, false, err } // Delete deletes the Secret with the specified name @@ -131,7 +134,14 @@ func (rs *REST) Get(ctx api.Context, name string) (runtime.Object, error) { } func (rs *REST) getAttrs(obj runtime.Object) (objLabels, objFields labels.Set, err error) { - return labels.Set{}, labels.Set{}, nil + secret, ok := obj.(*api.Secret) + if !ok { + return nil, nil, fmt.Errorf("invalid object type") + } + + return labels.Set{}, labels.Set{ + "type": string(secret.Type), + }, nil } func (rs *REST) List(ctx api.Context, label, field labels.Selector) (runtime.Object, error) { diff --git a/pkg/registry/secret/rest_test.go b/pkg/registry/secret/rest_test.go new file mode 100644 index 00000000000..f905378c2d1 --- /dev/null +++ b/pkg/registry/secret/rest_test.go @@ -0,0 +1,212 @@ +/* +Copyright 2015 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 secret + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" + "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" + "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" +) + +type testRegistry struct { + *registrytest.GenericRegistry +} + +func NewTestREST() (testRegistry, *REST) { + reg := testRegistry{registrytest.NewGeneric(nil)} + return reg, NewREST(reg) +} + +func testSecret(name string) *api.Secret { + return &api.Secret{ + ObjectMeta: api.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Data: map[string][]byte{ + "data-1": []byte("value-1"), + }, + Type: api.SecretTypeOpaque, + } +} + +func TestRESTCreate(t *testing.T) { + table := []struct { + ctx api.Context + secret *api.Secret + valid bool + }{ + { + ctx: api.NewDefaultContext(), + secret: testSecret("foo"), + valid: true, + }, { + ctx: api.NewContext(), + secret: testSecret("bar"), + valid: false, + }, { + ctx: api.WithNamespace(api.NewContext(), "nondefault"), + secret: testSecret("bazzzz"), + valid: false, + }, + } + + for _, item := range table { + _, rest := NewTestREST() + c, err := rest.Create(item.ctx, item.secret) + if !item.valid { + if err == nil { + ctxNS := api.NamespaceValue(item.ctx) + t.Errorf("%v: Unexpected non-error: (%v, %v)", item.secret.Name, ctxNS, item.secret.Namespace) + } + continue + } + if err != nil { + t.Errorf("%v: Unexpected error: %v", item.secret.Name, err) + continue + } + if !api.HasObjectMetaSystemFieldValues(&item.secret.ObjectMeta) { + t.Errorf("storage did not populate object meta field values") + } + if e, a := item.secret, c; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } + // Ensure we implement the interface + _ = apiserver.ResourceWatcher(rest) + } +} + +func TestRESTUpdate(t *testing.T) { + ctx := api.NewDefaultContext() + registry, rest := NewTestREST() + registry.CreateWithName(ctx, "foo", testSecret("foo")) + modifiedSecret := testSecret("foo") + modifiedSecret.Data = map[string][]byte{ + "data-2": []byte("value-2"), + } + + updatedObj, created, err := rest.Update(ctx, modifiedSecret) + if err != nil { + t.Fatalf("Expected no error: %v", err) + } + if updatedObj == nil { + t.Errorf("Expected non-nil object") + } + if created { + t.Errorf("expected not created") + } + updatedSecret := updatedObj.(*api.Secret) + if updatedSecret.Name != "foo" { + t.Errorf("Expected foo, but got %v", updatedSecret.Name) + } +} + +func TestRESTDelete(t *testing.T) { + _, rest := NewTestREST() + secretA := testSecret("foo") + _, err := rest.Create(api.NewDefaultContext(), secretA) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + c, err := rest.Delete(api.NewDefaultContext(), secretA.Name) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if stat := c.(*api.Status); stat.Status != api.StatusSuccess { + t.Errorf("unexpected status: %v", stat) + } +} + +func TestRESTGet(t *testing.T) { + _, rest := NewTestREST() + secretA := testSecret("foo") + _, err := rest.Create(api.NewDefaultContext(), secretA) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + got, err := rest.Get(api.NewDefaultContext(), secretA.Name) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if e, a := secretA, got; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } +} + +func TestRESTgetAttrs(t *testing.T) { + _, rest := NewTestREST() + secretA := testSecret("foo") + label, field, err := rest.getAttrs(secretA) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if e, a := label, (labels.Set{}); !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } + expect := labels.Set{ + "type": string(api.SecretTypeOpaque), + } + if e, a := expect, field; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } +} + +func TestRESTList(t *testing.T) { + reg, rest := NewTestREST() + + var ( + secretA = testSecret("a") + secretB = testSecret("b") + secretC = testSecret("c") + ) + + reg.ObjectList = &api.SecretList{ + Items: []api.Secret{*secretA, *secretB, *secretC}, + } + got, err := rest.List(api.NewContext(), labels.Everything(), labels.Everything()) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + expect := &api.SecretList{ + Items: []api.Secret{*secretA, *secretB, *secretC}, + } + if e, a := expect, got; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } +} + +func TestRESTWatch(t *testing.T) { + secretA := testSecret("a") + reg, rest := NewTestREST() + wi, err := rest.Watch(api.NewContext(), labels.Everything(), labels.Everything(), "0") + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + go func() { + reg.Broadcaster.Action(watch.Added, secretA) + }() + got := <-wi.ResultChan() + if e, a := secretA, got.Object; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } +}