diff --git a/examples/examples_test.go b/examples/examples_test.go index c175f1e76be26..22b9906e91b15 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -86,6 +86,8 @@ func validateObject(obj runtime.Object) (errors []error) { errors = validation.ValidateEndpoints(t) case *api.Namespace: errors = validation.ValidateNamespace(t) + case *api.Tenant: + errors = validation.ValidateTenant(t) case *api.Secret: if t.Namespace == "" { t.Namespace = api.NamespaceDefault @@ -219,6 +221,8 @@ func TestExampleObjectSchemas(t *testing.T) { }, "../docs/user-guide": { "multi-pod": nil, + "ns": &api.Namespace{}, + "te": &api.Tenant{}, "pod": &api.Pod{}, "replication": &api.ReplicationController{}, "job": &experimental.Job{}, diff --git a/pkg/api/meta/meta_test.go b/pkg/api/meta/meta_test.go index 37cedb2be6748..ba0d0a1e529ed 100644 --- a/pkg/api/meta/meta_test.go +++ b/pkg/api/meta/meta_test.go @@ -28,6 +28,7 @@ func TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` + Tenant string `json:"tenant,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` @@ -44,6 +45,7 @@ func TestGenericTypeMeta(t *testing.T) { j := Object{ TypeMeta{ Namespace: "bar", + Tenant: "hah", Name: "foo", GenerateName: "prefix", UID: "uid", @@ -62,6 +64,9 @@ func TestGenericTypeMeta(t *testing.T) { if e, a := "bar", accessor.Namespace(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := "hah", accessor.Tenant(); e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := "foo", accessor.Name(); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -96,6 +101,7 @@ func TestGenericTypeMeta(t *testing.T) { } accessor.SetNamespace("baz") + accessor.SetTenant("uau") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") @@ -108,6 +114,9 @@ func TestGenericTypeMeta(t *testing.T) { if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := "uau", j.Tenant; e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } @@ -143,6 +152,7 @@ func TestGenericTypeMeta(t *testing.T) { type InternalTypeMeta struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` + Tenant string `json:"tenant,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` @@ -163,6 +173,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) { j := &InternalObject{ InternalTypeMeta{ Namespace: "bar", + Tenant: "hah", Name: "foo", GenerateName: "prefix", UID: "uid", @@ -182,6 +193,13 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if e, a := "bar", namespace; e != a { t.Errorf("expected %v, got %v", e, a) } + tenant, err := accessor.Tenant(j) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if e, a := "hah", tenant; e != a { + t.Errorf("expected %v, got %v", e, a) + } name, err := accessor.Name(j) if err != nil { t.Errorf("unexpected error: %v", err) @@ -249,6 +267,9 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if err := accessor.SetNamespace(j, "baz"); err != nil { t.Errorf("unexpected error: %v", err) } + if err := accessor.SetTenant(j, "uau"); err != nil { + t.Errorf("unexpected error: %v", err) + } if err := accessor.SetName(j, "bar"); err != nil { t.Errorf("unexpected error: %v", err) } @@ -282,6 +303,9 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if e, a := "baz", j.TypeMeta.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := "uau", j.TypeMeta.Tenant; e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := "bar", j.TypeMeta.Name; e != a { t.Errorf("expected %v, got %v", e, a) } @@ -318,6 +342,7 @@ func TestGenericObjectMeta(t *testing.T) { } type ObjectMeta struct { Namespace string `json:"namespace,omitempty"` + Tenant string `json:"tenant,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` @@ -338,6 +363,7 @@ func TestGenericObjectMeta(t *testing.T) { }, ObjectMeta{ Namespace: "bar", + Tenant: "hah", Name: "foo", GenerateName: "prefix", UID: "uid", @@ -354,6 +380,9 @@ func TestGenericObjectMeta(t *testing.T) { if e, a := "bar", accessor.Namespace(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := "hah", accessor.Tenant(); e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := "foo", accessor.Name(); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -383,6 +412,7 @@ func TestGenericObjectMeta(t *testing.T) { } accessor.SetNamespace("baz") + accessor.SetTenant("uau") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") @@ -397,6 +427,9 @@ func TestGenericObjectMeta(t *testing.T) { if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := "uau", j.Tenant; e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index aa88da1ceb400..d7c5263bf24c0 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -1798,15 +1798,34 @@ func ValidateResourceQuotaStatusUpdate(newResourceQuota, oldResourceQuota *api.R // fake functions for 'tenant' validatation func ValidateTenant(tenant *api.Tenant) errs.ValidationErrorList { - return nil + allErrs := errs.ValidationErrorList{} + allErrs = append(allErrs, ValidateObjectMeta(&tenant.ObjectMeta, false, ValidateTenantName).Prefix("metadata")...) + + return allErrs } func ValidateTenantUpdate(newTenant *api.Tenant, oldTenant *api.Tenant) errs.ValidationErrorList { - return nil + allErrs := errs.ValidationErrorList{} + allErrs = append(allErrs, ValidateObjectMetaUpdate(&newTenant.ObjectMeta, &oldTenant.ObjectMeta).Prefix("metadata")...) + newTenant.Spec = oldTenant.Spec + newTenant.Status = oldTenant.Status + return allErrs } func ValidateTenantStatusUpdate(newTenant, oldTenant *api.Tenant) errs.ValidationErrorList { - return nil + allErrs := errs.ValidationErrorList{} + allErrs = append(allErrs, ValidateObjectMetaUpdate(&newTenant.ObjectMeta, &oldTenant.ObjectMeta).Prefix("metadata")...) + newTenant.Spec = oldTenant.Spec + if newTenant.DeletionTimestamp.IsZero() { + if newTenant.Status.Phase != api.TenantActive { + allErrs = append(allErrs, errs.NewFieldInvalid("Status.Phase", newTenant.Status.Phase, "A tenant may only be in active status if it does not have a deletion timestamp.")) + } + } else { + if newTenant.Status.Phase != api.TenantTerminating { + allErrs = append(allErrs, errs.NewFieldInvalid("Status.Phase", newTenant.Status.Phase, "A tenant may only be in terminating status if it has a deletion timestamp.")) + } + } + return allErrs } // ValidateNamespace tests if required fields are set. diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 6cce29831b60b..77d046a06fe4d 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -460,7 +460,7 @@ func TestValidateVolumes(t *testing.T) { {Name: "glusterfs", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host1", Path: "path", ReadOnly: false}}}, {Name: "flocker", VolumeSource: api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "datasetName"}}}, {Name: "rbd", VolumeSource: api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "bar", FSType: "ext4"}}}, - {Name: "cinder", VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{"29ea5088-4f60-4757-962e-dba678767887", "ext4", false}}}, + {Name: "cinder", VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{"29ea5088-4f60-4757-962e-dba678767887", "ext4", false, false}}}, {Name: "cephfs", VolumeSource: api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{"foo"}}}}, {Name: "downwardapi", VolumeSource: api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{ {Path: "labels", FieldRef: api.ObjectFieldSelector{ diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 8663ec6c91938..f37006fdae730 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -2250,13 +2250,19 @@ type setTestSelfLinker struct { expectedSet string name string namespace string + tenant string called bool err error } func (s *setTestSelfLinker) Namespace(runtime.Object) (string, error) { return s.namespace, s.err } -func (s *setTestSelfLinker) Name(runtime.Object) (string, error) { return s.name, s.err } -func (s *setTestSelfLinker) SelfLink(runtime.Object) (string, error) { return "", s.err } +func (s *setTestSelfLinker) Tenant(runtime.Object) (string, error) { return s.tenant, s.err } +func (s *setTestSelfLinker) SetTenant(obj runtime.Object, tenant string) error { + s.tenant = tenant + return s.err +} +func (s *setTestSelfLinker) Name(runtime.Object) (string, error) { return s.name, s.err } +func (s *setTestSelfLinker) SelfLink(runtime.Object) (string, error) { return "", s.err } func (s *setTestSelfLinker) SetSelfLink(obj runtime.Object, selfLink string) error { if e, a := s.expectedSet, selfLink; e != a { s.t.Errorf("expected '%v', got '%v'", e, a) diff --git a/pkg/apiserver/authz_test.go b/pkg/apiserver/authz_test.go index 72d33802ae1e5..6580976d97c05 100644 --- a/pkg/apiserver/authz_test.go +++ b/pkg/apiserver/authz_test.go @@ -24,7 +24,7 @@ import ( // and always return nil. func TestNewAlwaysAllowAuthorizer(t *testing.T) { aaa := NewAlwaysAllowAuthorizer() - if result := aaa.Authorize(nil); result != nil { + if _, result := aaa.Authorize(nil); result != nil { t.Errorf("AlwaysAllowAuthorizer.Authorize did not return nil. (%s)", result) } } @@ -33,7 +33,7 @@ func TestNewAlwaysAllowAuthorizer(t *testing.T) { // and always return an error as everything is forbidden. func TestNewAlwaysDenyAuthorizer(t *testing.T) { ada := NewAlwaysDenyAuthorizer() - if result := ada.Authorize(nil); result == nil { + if _, result := ada.Authorize(nil); result == nil { t.Errorf("AlwaysDenyAuthorizer.Authorize returned nil instead of error.") } } @@ -41,31 +41,43 @@ func TestNewAlwaysDenyAuthorizer(t *testing.T) { // NewAuthorizerFromAuthorizationConfig has multiple return possibilities. This test // validates that errors are returned only when proper. func TestNewAuthorizerFromAuthorizationConfig(t *testing.T) { + testConfig := AuthorizerConfig{ + AuthorizationModes: []string{}, + AuthorizationPolicyFile: "", + KeystonAuthURL: "", + } // Unknown modes should return errors - if _, err := NewAuthorizerFromAuthorizationConfig([]string{"DoesNotExist"}, ""); err == nil { + testConfig.AuthorizationModes = []string{"DoesNotExist"} + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err == nil { t.Errorf("NewAuthorizerFromAuthorizationConfig using a fake mode should have returned an error") } // ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile // but error if one is given - if _, err := NewAuthorizerFromAuthorizationConfig([]string{ModeAlwaysAllow, ModeAlwaysDeny}, ""); err != nil { + testConfig.AuthorizationModes = []string{ModeAlwaysAllow, ModeAlwaysDeny} + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err != nil { t.Errorf("NewAuthorizerFromAuthorizationConfig returned an error: %s", err) } // ModeABAC requires a policy file - if _, err := NewAuthorizerFromAuthorizationConfig([]string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC}, ""); err == nil { + testConfig.AuthorizationModes = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC} + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err == nil { t.Errorf("NewAuthorizerFromAuthorizationConfig using a fake mode should have returned an error") } // ModeABAC should not error if a valid policy path is provided - if _, err := NewAuthorizerFromAuthorizationConfig([]string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC}, "../auth/authorizer/abac/example_policy_file.jsonl"); err != nil { + testConfig.AuthorizationModes = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC} + testConfig.AuthorizationPolicyFile = "../auth/authorizer/abac/example_policy_file.jsonl" + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err != nil { t.Errorf("NewAuthorizerFromAuthorizationConfig errored while using a valid policy file: %s", err) } // Authorization Policy file cannot be used without ModeABAC - if _, err := NewAuthorizerFromAuthorizationConfig([]string{ModeAlwaysAllow, ModeAlwaysDeny}, "../auth/authorizer/abac/example_policy_file.jsonl"); err == nil { + testConfig.AuthorizationModes = []string{ModeAlwaysAllow, ModeAlwaysDeny} + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err == nil { t.Errorf("NewAuthorizerFromAuthorizationConfig should have errored when Authorization Policy File is used without ModeABAC") } // Atleast one authorizationMode is necessary - if _, err := NewAuthorizerFromAuthorizationConfig([]string{}, "../auth/authorizer/abac/example_policy_file.jsonl"); err == nil { + testConfig.AuthorizationModes = []string{} + if _, err := NewAuthorizerFromAuthorizationConfig(testConfig); err == nil { t.Errorf("NewAuthorizerFromAuthorizationConfig should have errored when no authorization modes are passed") } } diff --git a/pkg/apiserver/resthandler_test.go b/pkg/apiserver/resthandler_test.go index 18fdddd933a00..2995f2ad71c1e 100644 --- a/pkg/apiserver/resthandler_test.go +++ b/pkg/apiserver/resthandler_test.go @@ -96,6 +96,7 @@ func (p *testPatcher) Get(ctx api.Context, name string) (runtime.Object, error) type testNamer struct { namespace string name string + tenant string } func (p *testNamer) Namespace(req *restful.Request) (namespace string, err error) { @@ -114,6 +115,15 @@ func (p *testNamer) ObjectName(obj runtime.Object) (namespace, name string, err return p.namespace, p.name, nil } +func (p *testNamer) ObjectTenant(obj runtime.Object) (tenant string, err error) { + return p.tenant, nil +} + +func (p *testNamer) SetTenant(obj runtime.Object, tenant string) (err error) { + p.tenant = tenant + return nil +} + // SetSelfLink sets the provided URL onto the object. The method should return nil if the object // does not support selfLinks. func (p *testNamer) SetSelfLink(obj runtime.Object, url string) error { @@ -151,6 +161,7 @@ func (tc *patchTestCase) Run(t *testing.T) { namespace := tc.startingPod.Namespace name := tc.startingPod.Name + tenant := tc.startingPod.Tenant codec := latest.GroupOrDie("").Codec @@ -161,7 +172,7 @@ func (tc *patchTestCase) Run(t *testing.T) { ctx := api.NewDefaultContext() ctx = api.WithNamespace(ctx, namespace) - namer := &testNamer{namespace, name} + namer := &testNamer{namespace, name, tenant} versionedObj, err := api.Scheme.ConvertToVersion(&api.Pod{}, "v1") if err != nil { diff --git a/pkg/auth/authorizer/abac/abac_test.go b/pkg/auth/authorizer/abac/abac_test.go index ef42ade6ca958..9a968ff350df8 100644 --- a/pkg/auth/authorizer/abac/abac_test.go +++ b/pkg/auth/authorizer/abac/abac_test.go @@ -122,7 +122,7 @@ func TestNotAuthorized(t *testing.T) { Namespace: tc.NS, } t.Logf("tc: %v -> attr %v", tc, attr) - err := a.Authorize(attr) + _, err := a.Authorize(attr) actualAllow := bool(err == nil) if tc.ExpectAllow != actualAllow { t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v", diff --git a/pkg/auth/authorizer/union/union_test.go b/pkg/auth/authorizer/union/union_test.go index 1a01676af6cd1..588238eef7517 100644 --- a/pkg/auth/authorizer/union/union_test.go +++ b/pkg/auth/authorizer/union/union_test.go @@ -28,14 +28,14 @@ type mockAuthzHandler struct { err error } -func (mock *mockAuthzHandler) Authorize(a authorizer.Attributes) error { +func (mock *mockAuthzHandler) Authorize(a authorizer.Attributes) (string, error) { if mock.err != nil { - return mock.err + return "", mock.err } if !mock.isAuthorized { - return errors.New("Request unauthorized") + return "", errors.New("Request unauthorized") } else { - return nil + return "", nil } } @@ -44,7 +44,7 @@ func TestAuthorizationSecondPasses(t *testing.T) { handler2 := &mockAuthzHandler{isAuthorized: true} authzHandler := New(handler1, handler2) - err := authzHandler.Authorize(nil) + _, err := authzHandler.Authorize(nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -55,7 +55,7 @@ func TestAuthorizationFirstPasses(t *testing.T) { handler2 := &mockAuthzHandler{isAuthorized: false} authzHandler := New(handler1, handler2) - err := authzHandler.Authorize(nil) + _, err := authzHandler.Authorize(nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -66,7 +66,7 @@ func TestAuthorizationNonePasses(t *testing.T) { handler2 := &mockAuthzHandler{isAuthorized: false} authzHandler := New(handler1, handler2) - err := authzHandler.Authorize(nil) + _, err := authzHandler.Authorize(nil) if err == nil { t.Errorf("Expected error: %v", err) } diff --git a/pkg/client/record/event_test.go b/pkg/client/record/event_test.go index 33fc1f3a0103c..de7283a36b180 100644 --- a/pkg/client/record/event_test.go +++ b/pkg/client/record/event_test.go @@ -110,7 +110,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { @@ -135,7 +135,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): reason: 'Killed' some other verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): reason: 'Killed' some other verbose message: 1`, expectUpdate: false, }, { @@ -161,7 +161,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 2, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { @@ -187,7 +187,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { @@ -213,7 +213,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 3, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { @@ -239,7 +239,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: false, }, { @@ -265,7 +265,7 @@ func TestEventf(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 2, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: true, }, } @@ -523,7 +523,7 @@ func TestEventfNoNamespace(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, } @@ -627,7 +627,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { @@ -652,7 +652,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): reason: 'Killed' some other verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): reason: 'Killed' some other verbose message: 1`, expectUpdate: false, }, { @@ -678,7 +678,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 2, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { @@ -704,7 +704,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { @@ -730,7 +730,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 3, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { @@ -756,7 +756,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 1, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: false, }, { @@ -782,7 +782,7 @@ func TestMultiSinkCache(t *testing.T) { Source: api.EventSource{Component: "eventTest"}, Count: 2, }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Tenant:"", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: true, }, } diff --git a/pkg/client/unversioned/testclient/fake_tenants.go b/pkg/client/unversioned/testclient/fake_tenants.go new file mode 100644 index 0000000000000..3f98c8c71b0a6 --- /dev/null +++ b/pkg/client/unversioned/testclient/fake_tenants.go @@ -0,0 +1,105 @@ +/* +Copyright 2014 The Kubernetes Authors 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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/fields" + "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeTenants implements TenantsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeTenants struct { + Fake *Fake +} + +func (c *FakeTenants) Get(name string) (*api.Tenant, error) { + obj, err := c.Fake.Invokes(NewRootGetAction("tenants", name), &api.Tenant{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Tenant), err +} + +func (c *FakeTenants) List(label labels.Selector, field fields.Selector) (*api.TenantList, error) { + obj, err := c.Fake.Invokes(NewRootListAction("tenants", label, field), &api.TenantList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.TenantList), err +} + +func (c *FakeTenants) Create(tenant *api.Tenant) (*api.Tenant, error) { + obj, err := c.Fake.Invokes(NewRootCreateAction("tenants", tenant), tenant) + if obj == nil { + return nil, err + } + + return obj.(*api.Tenant), err +} + +func (c *FakeTenants) Update(tenant *api.Tenant) (*api.Tenant, error) { + obj, err := c.Fake.Invokes(NewRootUpdateAction("tenants", tenant), tenant) + if obj == nil { + return nil, err + } + + return obj.(*api.Tenant), err +} + +func (c *FakeTenants) Delete(name string) error { + _, err := c.Fake.Invokes(NewRootDeleteAction("tenants", name), &api.Tenant{}) + return err +} + +func (c *FakeTenants) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewRootWatchAction("tenants", label, field, resourceVersion)) +} + +func (c *FakeTenants) Finalize(tenant *api.Tenant) (*api.Tenant, error) { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "tenants" + action.Subresource = "finalize" + action.Object = tenant + + obj, err := c.Fake.Invokes(action, tenant) + if obj == nil { + return nil, err + } + + return obj.(*api.Tenant), err +} + +func (c *FakeTenants) Status(tenant *api.Tenant) (*api.Tenant, error) { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "tenants" + action.Subresource = "status" + action.Object = tenant + + obj, err := c.Fake.Invokes(action, tenant) + if obj == nil { + return nil, err + } + + return obj.(*api.Tenant), err +} diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index 0ab34ee328cf0..127f24ae674fe 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -267,6 +267,10 @@ func (c *Fake) Namespaces() client.NamespaceInterface { return &FakeNamespaces{Fake: c} } +func (c *Fake) Tenants() client.TenantInterface { + return &FakeTenants{Fake: c} +} + func (c *Fake) Networks() client.NetworkInterface { return &FakeNetworks{Fake: c} } diff --git a/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go b/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go index 352b44aa5b59b..d79386713df67 100644 --- a/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go +++ b/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go @@ -403,6 +403,10 @@ func (r *mockRecycler) GetPath() string { return r.path } +func (r *mockRecycler) GetMetaData() map[string]interface{} { + return nil +} + func (r *mockRecycler) Recycle() error { // return nil means recycle passed return nil diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 2058b2645cfc3..e553cf1d722a2 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -110,9 +110,9 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, args []string) (err error if err != nil { return err } - tenant, enforceTenant, errT := f.DefaultTenant() - if errT != nil { - return errT + tenant, enforceTenant, err := f.DefaultTenant() + if err != nil { + return err } // retrieves resource and annotation args from args diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index d518846bc3f49..ae63e1cda72f7 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -99,7 +99,7 @@ func TestValidateAnnotationOverwrites(t *testing.T) { func TestParseAnnotations(t *testing.T) { testURL := "https://test.com/index.htm?id=123#u=user-name" - testJSON := `'{"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"default","name":"my-nginx","uid":"c544ee78-2665-11e5-8051-42010af0c213","apiVersion":"v1","resourceVersion":"61368"}}'` + testJSON := `'{"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"default","tenant":"default", "name":"my-nginx","uid":"c544ee78-2665-11e5-8051-42010af0c213","apiVersion":"v1","resourceVersion":"61368"}}'` tests := []struct { annotations []string expected map[string]string @@ -392,6 +392,7 @@ func TestAnnotateErrors(t *testing.T) { f, tf, _ := NewAPIFactory() tf.Printer = &testPrinter{} tf.Namespace = "test" + tf.Tenant = "test" tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} buf := bytes.NewBuffer([]byte{}) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index 8049734a74ee6..014d4c8fd034d 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -138,6 +138,7 @@ type testFactory struct { Printer kubectl.ResourcePrinter Validator validation.Schema Namespace string + Tenant string ClientConfig *client.Config Err error } @@ -168,6 +169,9 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { DefaultNamespace: func() (string, bool, error) { return t.Namespace, false, t.Err }, + DefaultTenant: func() (string, bool, error) { + return t.Tenant, false, t.Err + }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err }, @@ -225,6 +229,9 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { DefaultNamespace: func() (string, bool, error) { return t.Namespace, false, t.Err }, + DefaultTenant: func() (string, bool, error) { + return t.Tenant, false, t.Err + }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err }, diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index aa2337175310d..bf61a2a7698c8 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -498,6 +498,10 @@ func (f *stubVolume) GetPath() string { return f.path } +func (f *stubVolume) GetMetaData() map[string]interface{} { + return nil +} + func TestMakeVolumeMounts(t *testing.T) { container := api.Container{ VolumeMounts: []api.VolumeMount{ diff --git a/pkg/master/controller_test.go b/pkg/master/controller_test.go index e7a4acf8483c1..f01f93d5225a0 100644 --- a/pkg/master/controller_test.go +++ b/pkg/master/controller_test.go @@ -28,7 +28,7 @@ import ( func TestSetEndpoints(t *testing.T) { ns := api.NamespaceDefault om := func(name string) api.ObjectMeta { - return api.ObjectMeta{Namespace: ns, Name: name} + return api.ObjectMeta{Namespace: ns, Tenant: api.TenantDefault, Name: name} } tests := []struct { testName string diff --git a/pkg/probe/http/http_test.go b/pkg/probe/http/http_test.go index 65cd039828210..1277b8c3e92fd 100644 --- a/pkg/probe/http/http_test.go +++ b/pkg/probe/http/http_test.go @@ -72,7 +72,7 @@ func TestHTTPProbeChecker(t *testing.T) { probe.Failure, []string{ "use of closed network connection", - "request canceled (Client.Timeout exceeded while awaiting headers)", + "Client.Timeout exceeded while awaiting headers", }, }, } diff --git a/pkg/registry/network/etcd/etcd_test.go b/pkg/registry/network/etcd/etcd_test.go index 053cddf53be72..c935965c365e5 100644 --- a/pkg/registry/network/etcd/etcd_test.go +++ b/pkg/registry/network/etcd/etcd_test.go @@ -21,12 +21,12 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/registry/network" "k8s.io/kubernetes/pkg/registry/registrytest" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/tools" "k8s.io/kubernetes/pkg/tools/etcdtest" - "k8s.io/kubernetes/pkg/util" ) func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) { @@ -121,7 +121,7 @@ func TestDeleteNetwork(t *testing.T) { storage, fakeClient := newStorage(t) key := etcdtest.AddPrefix("networks/foo") ctx := api.NewContext() - now := util.Now() + now := unversioned.Now() net := &api.Network{ ObjectMeta: api.ObjectMeta{ Name: "foo", diff --git a/pkg/registry/network/rest_test.go b/pkg/registry/network/rest_test.go index a972b82c26cd2..b69cb9827ca6a 100644 --- a/pkg/registry/network/rest_test.go +++ b/pkg/registry/network/rest_test.go @@ -20,7 +20,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/api/unversioned" ) func TestNetworkStrategy(t *testing.T) { @@ -60,7 +60,7 @@ func TestNetworkStatusStrategy(t *testing.T) { if StatusStrategy.AllowCreateOnUpdate() { t.Errorf("Networks should not allow create on update") } - now := util.Now() + now := unversioned.Now() oldNetwork := &api.Network{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, Spec: api.NetworkSpec{ diff --git a/pkg/registry/tenant/etcd/etcd_test.go b/pkg/registry/tenant/etcd/etcd_test.go index eaa001dc223d6..aa46dc2f03083 100644 --- a/pkg/registry/tenant/etcd/etcd_test.go +++ b/pkg/registry/tenant/etcd/etcd_test.go @@ -32,7 +32,7 @@ import ( func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) { etcdStorage, fakeClient := registrytest.NewEtcdStorage(t, "") - storage, _, _ := NewREST(etcdStorage) + storage, _ := NewREST(etcdStorage) return storage, fakeClient } @@ -125,7 +125,7 @@ func TestWatch(t *testing.T) { ) } -func TestDeleteTenantWithIncompleteFinalizers(t *testing.T) { +func TestDeleteTenant(t *testing.T) { storage, fakeClient := newStorage(t) key := etcdtest.AddPrefix("tenants/foo") ctx := api.NewContext() @@ -135,32 +135,7 @@ func TestDeleteTenantWithIncompleteFinalizers(t *testing.T) { Name: "foo", DeletionTimestamp: &now, }, - Spec: api.TenantSpec{ - Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, - }, - Status: api.TenantStatus{Phase: api.TenantActive}, - } - if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), tenant), 0); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if _, err := storage.Delete(ctx, "foo", nil); err == nil { - t.Errorf("unexpected error: %v", err) - } -} - -func TestDeleteTenantWithCompleteFinalizers(t *testing.T) { - storage, fakeClient := newStorage(t) - key := etcdtest.AddPrefix("tenants/foo") - ctx := api.NewContext() - now := unversioned.Now() - tenant := &api.Tenant{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - DeletionTimestamp: &now, - }, - Spec: api.TenantSpec{ - Finalizers: []api.FinalizerName{}, - }, + Spec: api.TenantSpec{}, Status: api.TenantStatus{Phase: api.TenantActive}, } if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), tenant), 0); err != nil { diff --git a/pkg/registry/tenant/strategy.go b/pkg/registry/tenant/strategy.go index 2abe8fca36a34..233914957834c 100644 --- a/pkg/registry/tenant/strategy.go +++ b/pkg/registry/tenant/strategy.go @@ -56,6 +56,7 @@ func (tenantStrategy) PrepareForCreate(obj runtime.Object) { func (tenantStrategy) PrepareForUpdate(obj, old runtime.Object) { newTenant := obj.(*api.Tenant) oldTenant := old.(*api.Tenant) + newTenant.Spec.Namespaces = oldTenant.Spec.Namespaces newTenant.Status = oldTenant.Status } diff --git a/pkg/registry/tenant/strategy_test.go b/pkg/registry/tenant/strategy_test.go index b028aa50a2276..dbd4798d8766c 100644 --- a/pkg/registry/tenant/strategy_test.go +++ b/pkg/registry/tenant/strategy_test.go @@ -25,9 +25,6 @@ import ( func TestTenantStrategy(t *testing.T) { ctx := api.NewDefaultContext() - if Strategy.TenantScoped() { - t.Errorf("Tenants should not be tenant scoped") - } if Strategy.AllowCreateOnUpdate() { t.Errorf("Tenants should not allow create on update") } @@ -39,9 +36,6 @@ func TestTenantStrategy(t *testing.T) { if tenant.Status.Phase != api.TenantActive { t.Errorf("Tenants do not allow setting phase on create") } - if len(tenant.Spec.Finalizers) != 1 || tenant.Spec.Finalizers[0] != api.FinalizerKubernetes { - t.Errorf("Prepare For Create should have added kubernetes finalizer") - } errs := Strategy.Validate(ctx, tenant) if len(errs) != 0 { t.Errorf("Unexpected error validating %v", errs) @@ -51,9 +45,6 @@ func TestTenantStrategy(t *testing.T) { } // ensure we copy spec.finalizers from old to new Strategy.PrepareForUpdate(invalidTenant, tenant) - if len(invalidTenant.Spec.Finalizers) != 1 || invalidTenant.Spec.Finalizers[0] != api.FinalizerKubernetes { - t.Errorf("PrepareForUpdate should have preserved old.spec.finalizers") - } errs = Strategy.ValidateUpdate(ctx, invalidTenant, tenant) if len(errs) == 0 { t.Errorf("Expected a validation error") @@ -65,16 +56,13 @@ func TestTenantStrategy(t *testing.T) { func TestTenantStatusStrategy(t *testing.T) { ctx := api.NewDefaultContext() - if StatusStrategy.TenantScoped() { - t.Errorf("Tenants should not be tenant scoped") - } if StatusStrategy.AllowCreateOnUpdate() { t.Errorf("Tenants should not allow create on update") } now := unversioned.Now() oldTenant := &api.Tenant{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, - Spec: api.TenantSpec{Finalizers: []api.FinalizerName{"kubernetes"}}, + Spec: api.TenantSpec{}, Status: api.TenantStatus{Phase: api.TenantActive}, } tenant := &api.Tenant{ @@ -85,43 +73,6 @@ func TestTenantStatusStrategy(t *testing.T) { if tenant.Status.Phase != api.TenantTerminating { t.Errorf("Tenant status updates should allow change of phase: %v", tenant.Status.Phase) } - if len(tenant.Spec.Finalizers) != 1 || tenant.Spec.Finalizers[0] != api.FinalizerKubernetes { - t.Errorf("PrepareForUpdate should have preserved old finalizers") - } - errs := StatusStrategy.ValidateUpdate(ctx, tenant, oldTenant) - if len(errs) != 0 { - t.Errorf("Unexpected error %v", errs) - } - if tenant.ResourceVersion != "9" { - t.Errorf("Incoming resource version on update should not be mutated") - } -} - -func TestTenantFinalizeStrategy(t *testing.T) { - ctx := api.NewDefaultContext() - if FinalizeStrategy.TenantScoped() { - t.Errorf("Tenants should not be tenant scoped") - } - if FinalizeStrategy.AllowCreateOnUpdate() { - t.Errorf("Tenants should not allow create on update") - } - oldTenant := &api.Tenant{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, - Spec: api.TenantSpec{Finalizers: []api.FinalizerName{"kubernetes", "example.com/org"}}, - Status: api.TenantStatus{Phase: api.TenantActive}, - } - tenant := &api.Tenant{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "9"}, - Spec: api.TenantSpec{Finalizers: []api.FinalizerName{"example.com/foo"}}, - Status: api.TenantStatus{Phase: api.TenantTerminating}, - } - FinalizeStrategy.PrepareForUpdate(tenant, oldTenant) - if tenant.Status.Phase != api.TenantActive { - t.Errorf("finalize updates should not allow change of phase: %v", tenant.Status.Phase) - } - if len(tenant.Spec.Finalizers) != 1 || string(tenant.Spec.Finalizers[0]) != "example.com/foo" { - t.Errorf("PrepareForUpdate should have modified finalizers") - } errs := StatusStrategy.ValidateUpdate(ctx, tenant, oldTenant) if len(errs) != 0 { t.Errorf("Unexpected error %v", errs) diff --git a/pkg/volume/cinder/cinder_test.go b/pkg/volume/cinder/cinder_test.go index 5cf6dcec0bf41..bcac96a3b20db 100644 --- a/pkg/volume/cinder/cinder_test.go +++ b/pkg/volume/cinder/cinder_test.go @@ -83,7 +83,7 @@ func TestPlugin(t *testing.T) { }, }, } - builder, err := plug.(*cinderPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) + builder, err := plug.(*cinderPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}, false) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -114,7 +114,7 @@ func TestPlugin(t *testing.T) { } } - cleaner, err := plug.(*cinderPlugin).newCleanerInternal("vol1", types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) + cleaner, err := plug.(*cinderPlugin).newCleanerInternal("vol1", types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}, false) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index 594d6fb707c73..59e35dd64db1d 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -98,6 +98,10 @@ func (r *mockRecycler) GetPath() string { return r.path } +func (r *mockRecycler) GetMetaData() map[string]interface{} { + return nil +} + func (r *mockRecycler) Recycle() error { // return nil means recycle passed return nil