Merge pull request #4539 from pmorie/secret_resource

Add test for secret RESTStorage
This commit is contained in:
Eric Tune 2015-02-18 10:20:59 -08:00
commit afefa85b26
3 changed files with 231 additions and 10 deletions

View File

@ -25,8 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
) )
// GenericRegistry knows how to store & list any runtime.Object. Events don't require // GenericRegistry knows how to store & list any runtime.Object.
// any non-generic features from the storage layer.
type GenericRegistry struct { type GenericRegistry struct {
Err error Err error
Object runtime.Object Object runtime.Object

View File

@ -70,19 +70,19 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
} }
// Update updates a Secret object. // 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) secret, ok := obj.(*api.Secret)
if !ok { 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) { 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) oldObj, err := rs.registry.Get(ctx, secret.Name)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
editSecret := oldObj.(*api.Secret) 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.Labels = secret.Labels
editSecret.ResourceVersion = secret.ResourceVersion editSecret.ResourceVersion = secret.ResourceVersion
editSecret.Annotations = secret.Annotations editSecret.Annotations = secret.Annotations
editSecret.Data = secret.Data
editSecret.Type = secret.Type
if errs := validation.ValidateSecret(editSecret); len(errs) > 0 { 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) err = rs.registry.UpdateWithName(ctx, editSecret.Name, editSecret)
if err != nil { 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 // 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) { 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) { func (rs *REST) List(ctx api.Context, label, field labels.Selector) (runtime.Object, error) {

View File

@ -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))
}
}