diff --git a/pkg/registry/binding/rest.go b/pkg/registry/binding/rest.go index 52907852c93..42d7970870e 100644 --- a/pkg/registry/binding/rest.go +++ b/pkg/registry/binding/rest.go @@ -18,9 +18,9 @@ package binding import ( "fmt" + "net/http" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) @@ -44,15 +44,13 @@ func (*REST) New() runtime.Object { } // Create attempts to make the assignment indicated by the binding it recieves. -func (b *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (b *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { binding, ok := obj.(*api.Binding) if !ok { return nil, fmt.Errorf("incorrect type: %#v", obj) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := b.registry.ApplyBinding(ctx, binding); err != nil { - return nil, err - } - return &api.Status{Status: api.StatusSuccess}, nil - }), nil + if err := b.registry.ApplyBinding(ctx, binding); err != nil { + return nil, err + } + return &api.Status{Status: api.StatusSuccess, Code: http.StatusCreated}, nil } diff --git a/pkg/registry/binding/rest_test.go b/pkg/registry/binding/rest_test.go index 134d3df5481..5ddac234105 100644 --- a/pkg/registry/binding/rest_test.go +++ b/pkg/registry/binding/rest_test.go @@ -71,22 +71,20 @@ func TestRESTPost(t *testing.T) { } ctx := api.NewContext() b := NewREST(mockRegistry) - resultChan, err := b.Create(ctx, item.b) - if err != nil { + result, err := b.Create(ctx, item.b) + if err != nil && item.err == nil { t.Errorf("Unexpected error %v", err) continue } - var expect *api.Status - if item.err == nil { - expect = &api.Status{Status: api.StatusSuccess} - } else { - expect = &api.Status{ - Status: api.StatusFailure, - Code: http.StatusInternalServerError, - Message: item.err.Error(), - } + if err == nil && item.err != nil { + t.Errorf("Unexpected error %v", err) + continue } - if e, a := expect, (<-resultChan).Object; !reflect.DeepEqual(e, a) { + var expect interface{} + if item.err == nil { + expect = &api.Status{Status: api.StatusSuccess, Code: http.StatusCreated} + } + if e, a := expect, result; !reflect.DeepEqual(e, a) { t.Errorf("%v: expected %#v, got %#v", i, e, a) } } diff --git a/pkg/registry/controller/rest.go b/pkg/registry/controller/rest.go index 94c13664ef1..4ea56e49618 100644 --- a/pkg/registry/controller/rest.go +++ b/pkg/registry/controller/rest.go @@ -50,7 +50,7 @@ func NewREST(registry Registry, podLister PodLister) *REST { } // Create registers the given ReplicationController. -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { controller, ok := obj.(*api.ReplicationController) if !ok { return nil, fmt.Errorf("not a replication controller: %#v", obj) @@ -60,20 +60,16 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE return nil, err } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := rs.registry.CreateController(ctx, controller); err != nil { - err = rest.CheckGeneratedNameError(rest.ReplicationControllers, err, controller) - return apiserver.RESTResult{}, err - } - return rs.registry.GetController(ctx, controller.Name) - }), nil + if err := rs.registry.CreateController(ctx, controller); err != nil { + err = rest.CheckGeneratedNameError(rest.ReplicationControllers, err, controller) + return apiserver.RESTResult{}, err + } + return rs.registry.GetController(ctx, controller.Name) } // Delete asynchronously deletes the ReplicationController specified by its id. -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteController(ctx, id) - }), nil +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { + return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteController(ctx, id) } // Get obtains the ReplicationController specified by its id. @@ -117,24 +113,23 @@ func (*REST) NewList() runtime.Object { // Update replaces a given ReplicationController instance with an existing // instance in storage.registry. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { controller, ok := obj.(*api.ReplicationController) if !ok { - return nil, fmt.Errorf("not a replication controller: %#v", obj) + return nil, false, fmt.Errorf("not a replication controller: %#v", obj) } if !api.ValidNamespace(ctx, &controller.ObjectMeta) { - return nil, errors.NewConflict("controller", controller.Namespace, fmt.Errorf("Controller.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("controller", controller.Namespace, fmt.Errorf("Controller.Namespace does not match the provided context")) } if errs := validation.ValidateReplicationController(controller); len(errs) > 0 { - return nil, errors.NewInvalid("replicationController", controller.Name, errs) + return nil, false, errors.NewInvalid("replicationController", controller.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.UpdateController(ctx, controller) - if err != nil { - return nil, err - } - return rs.registry.GetController(ctx, controller.Name) - }), nil + err := rs.registry.UpdateController(ctx, controller) + if err != nil { + return nil, false, err + } + out, err := rs.registry.GetController(ctx, controller.Name) + return out, false, err } // Watch returns ReplicationController events via a watch.Interface. diff --git a/pkg/registry/controller/rest_test.go b/pkg/registry/controller/rest_test.go index 577b1061415..9616c654210 100644 --- a/pkg/registry/controller/rest_test.go +++ b/pkg/registry/controller/rest_test.go @@ -22,7 +22,6 @@ import ( "io/ioutil" "strings" "testing" - "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" @@ -268,23 +267,17 @@ func TestCreateController(t *testing.T) { }, } ctx := api.NewDefaultContext() - channel, err := storage.Create(ctx, controller) + obj, err := storage.Create(ctx, controller) if err != nil { t.Fatalf("Unexpected error: %v", err) } - if err != nil { - t.Errorf("unexpected error: %v", err) + if obj == nil { + t.Errorf("unexpected object") } if !api.HasObjectMetaSystemFieldValues(&controller.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } - select { - case <-channel: - // expected case - case <-time.After(time.Millisecond * 100): - t.Error("Unexpected timeout from async channel") - } } // TODO: remove, covered by TestCreate @@ -338,9 +331,9 @@ func TestControllerStorageValidatesUpdate(t *testing.T) { } ctx := api.NewDefaultContext() for _, failureCase := range failureCases { - c, err := storage.Update(ctx, &failureCase) - if c != nil { - t.Errorf("Expected nil channel") + c, created, err := storage.Update(ctx, &failureCase) + if c != nil || created { + t.Errorf("Expected nil object and not created") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) @@ -441,9 +434,9 @@ func TestUpdateControllerWithConflictingNamespace(t *testing.T) { } ctx := api.NewDefaultContext() - channel, err := storage.Update(ctx, controller) - if channel != nil { - t.Error("Expected a nil channel, but we got a value") + obj, created, err := storage.Update(ctx, controller) + if obj != nil || created { + t.Error("Expected a nil object, but we got a value or created was true") } if err == nil { t.Errorf("Expected an error, but we didn't get one") diff --git a/pkg/registry/endpoint/rest.go b/pkg/registry/endpoint/rest.go index 40a7831fc23..147a9df248c 100644 --- a/pkg/registry/endpoint/rest.go +++ b/pkg/registry/endpoint/rest.go @@ -21,7 +21,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -59,7 +58,7 @@ func (rs *REST) Watch(ctx api.Context, label, field labels.Selector, resourceVer } // Create satisfies the RESTStorage interface. -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { endpoints, ok := obj.(*api.Endpoints) if !ok { return nil, fmt.Errorf("not an endpoints: %#v", obj) @@ -72,28 +71,25 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } api.FillObjectMetaSystemFields(ctx, &endpoints.ObjectMeta) - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.UpdateEndpoints(ctx, endpoints) - if err != nil { - return nil, err - } - return rs.registry.GetEndpoints(ctx, endpoints.Name) - }), nil + err := rs.registry.UpdateEndpoints(ctx, endpoints) + if err != nil { + return nil, err + } + return rs.registry.GetEndpoints(ctx, endpoints.Name) } // Update satisfies the RESTStorage interface. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { endpoints, ok := obj.(*api.Endpoints) if !ok { - return nil, fmt.Errorf("not an endpoints: %#v", obj) + return nil, false, fmt.Errorf("not an endpoints: %#v", obj) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.UpdateEndpoints(ctx, endpoints) - if err != nil { - return nil, err - } - return rs.registry.GetEndpoints(ctx, endpoints.Name) - }), nil + err := rs.registry.UpdateEndpoints(ctx, endpoints) + if err != nil { + return nil, false, err + } + out, err := rs.registry.GetEndpoints(ctx, endpoints.Name) + return out, false, err } // New implements the RESTStorage interface. diff --git a/pkg/registry/event/rest.go b/pkg/registry/event/rest.go index 216c356d032..c9307eb86d8 100644 --- a/pkg/registry/event/rest.go +++ b/pkg/registry/event/rest.go @@ -22,7 +22,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -42,7 +41,7 @@ func NewREST(registry generic.Registry) *REST { } } -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { event, ok := obj.(*api.Event) if !ok { return nil, fmt.Errorf("invalid object type") @@ -57,41 +56,38 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta) - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Create(ctx, event.Name, event) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, event.Name) - }), nil + err := rs.registry.Create(ctx, event.Name, event) + if err != nil { + return nil, err + } + return rs.registry.Get(ctx, event.Name) } // Update replaces an existing Event instance in storage.registry, with the given instance. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { event, ok := obj.(*api.Event) if !ok { - return nil, fmt.Errorf("not an event object: %#v", obj) + return nil, false, fmt.Errorf("not an event object: %#v", obj) } if api.NamespaceValue(ctx) != "" { if !api.ValidNamespace(ctx, &event.ObjectMeta) { - return nil, errors.NewConflict("event", event.Namespace, fmt.Errorf("event.namespace does not match the provided context")) + return nil, false, errors.NewConflict("event", event.Namespace, fmt.Errorf("event.namespace does not match the provided context")) } } if errs := validation.ValidateEvent(event); len(errs) > 0 { - return nil, errors.NewInvalid("event", event.Name, errs) + return nil, false, errors.NewInvalid("event", event.Name, errs) } api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta) - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Update(ctx, event.Name, event) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, event.Name) - }), nil + err := rs.registry.Update(ctx, event.Name, event) + if err != nil { + return nil, false, err + } + out, err := rs.registry.Get(ctx, event.Name) + return out, false, err } -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { obj, err := rs.registry.Get(ctx, id) if err != nil { return nil, err @@ -100,9 +96,7 @@ func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, if !ok { return nil, fmt.Errorf("invalid object type") } - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, id) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, id) } func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) { diff --git a/pkg/registry/event/rest_test.go b/pkg/registry/event/rest_test.go index 922603dd9b0..cbcce2fbe11 100644 --- a/pkg/registry/event/rest_test.go +++ b/pkg/registry/event/rest_test.go @@ -89,7 +89,7 @@ func TestRESTCreate(t *testing.T) { if !api.HasObjectMetaSystemFieldValues(&item.event.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } - if e, a := item.event, (<-c).Object; !reflect.DeepEqual(e, a) { + if e, a := item.event, c; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } // Ensure we implement the interface @@ -100,11 +100,10 @@ func TestRESTCreate(t *testing.T) { func TestRESTUpdate(t *testing.T) { _, rest := NewTestREST() eventA := testEvent("foo") - c, err := rest.Create(api.NewDefaultContext(), eventA) + _, err := rest.Create(api.NewDefaultContext(), eventA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c got, err := rest.Get(api.NewDefaultContext(), eventA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) @@ -113,11 +112,10 @@ func TestRESTUpdate(t *testing.T) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } eventB := testEvent("bar") - u, err := rest.Update(api.NewDefaultContext(), eventB) + _, _, err = rest.Update(api.NewDefaultContext(), eventB) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-u got2, err := rest.Get(api.NewDefaultContext(), eventB.Name) if err != nil { t.Fatalf("Unexpected error %v", err) @@ -131,16 +129,15 @@ func TestRESTUpdate(t *testing.T) { func TestRESTDelete(t *testing.T) { _, rest := NewTestREST() eventA := testEvent("foo") - c, err := rest.Create(api.NewDefaultContext(), eventA) + _, err := rest.Create(api.NewDefaultContext(), eventA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c - c, err = rest.Delete(api.NewDefaultContext(), eventA.Name) + c, err := rest.Delete(api.NewDefaultContext(), eventA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) } - if stat := (<-c).Object.(*api.Status); stat.Status != api.StatusSuccess { + if stat := c.(*api.Status); stat.Status != api.StatusSuccess { t.Errorf("unexpected status: %v", stat) } } @@ -148,11 +145,10 @@ func TestRESTDelete(t *testing.T) { func TestRESTGet(t *testing.T) { _, rest := NewTestREST() eventA := testEvent("foo") - c, err := rest.Create(api.NewDefaultContext(), eventA) + _, err := rest.Create(api.NewDefaultContext(), eventA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c got, err := rest.Get(api.NewDefaultContext(), eventA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) diff --git a/pkg/registry/limitrange/rest.go b/pkg/registry/limitrange/rest.go index f5eaaa1a71d..878dfc46ebd 100644 --- a/pkg/registry/limitrange/rest.go +++ b/pkg/registry/limitrange/rest.go @@ -22,7 +22,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -44,7 +43,7 @@ func NewREST(registry generic.Registry) *REST { } // Create a LimitRange object -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { limitRange, ok := obj.(*api.LimitRange) if !ok { return nil, fmt.Errorf("invalid object type") @@ -63,29 +62,27 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } api.FillObjectMetaSystemFields(ctx, &limitRange.ObjectMeta) - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Create(ctx, limitRange.Name, limitRange) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, limitRange.Name) - }), nil + err := rs.registry.Create(ctx, limitRange.Name, limitRange) + if err != nil { + return nil, err + } + return rs.registry.Get(ctx, limitRange.Name) } // Update updates a LimitRange object. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { limitRange, ok := obj.(*api.LimitRange) if !ok { - return nil, fmt.Errorf("invalid object type") + return nil, false, fmt.Errorf("invalid object type") } if !api.ValidNamespace(ctx, &limitRange.ObjectMeta) { - return nil, errors.NewConflict("limitRange", limitRange.Namespace, fmt.Errorf("LimitRange.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("limitRange", limitRange.Namespace, fmt.Errorf("LimitRange.Namespace does not match the provided context")) } oldObj, err := rs.registry.Get(ctx, limitRange.Name) if err != nil { - return nil, err + return nil, false, err } editLimitRange := oldObj.(*api.LimitRange) @@ -97,20 +94,18 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE editLimitRange.Spec = limitRange.Spec if errs := validation.ValidateLimitRange(editLimitRange); len(errs) > 0 { - return nil, errors.NewInvalid("limitRange", editLimitRange.Name, errs) + return nil, false, errors.NewInvalid("limitRange", editLimitRange.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Update(ctx, editLimitRange.Name, editLimitRange) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, editLimitRange.Name) - }), nil + if err := rs.registry.Update(ctx, editLimitRange.Name, editLimitRange); err != nil { + return nil, false, err + } + out, err := rs.registry.Get(ctx, editLimitRange.Name) + return out, false, err } // Delete deletes the LimitRange with the specified name -func (rs *REST) Delete(ctx api.Context, name string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, name string) (runtime.Object, error) { obj, err := rs.registry.Get(ctx, name) if err != nil { return nil, err @@ -119,9 +114,7 @@ func (rs *REST) Delete(ctx api.Context, name string) (<-chan apiserver.RESTResul if !ok { return nil, fmt.Errorf("invalid object type") } - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, name) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, name) } // Get gets a LimitRange with the specified name diff --git a/pkg/registry/minion/rest.go b/pkg/registry/minion/rest.go index 5c0ab637383..cd6db1ef475 100644 --- a/pkg/registry/minion/rest.go +++ b/pkg/registry/minion/rest.go @@ -26,7 +26,6 @@ import ( kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -49,7 +48,7 @@ var ErrDoesNotExist = errors.New("The requested resource does not exist.") var ErrNotHealty = errors.New("The requested minion is not healthy.") // Create satisfies the RESTStorage interface. -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { minion, ok := obj.(*api.Node) if !ok { return nil, fmt.Errorf("not a minion: %#v", obj) @@ -59,17 +58,15 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE return nil, err } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := rs.registry.CreateMinion(ctx, minion); err != nil { - err = rest.CheckGeneratedNameError(rest.Nodes, err, minion) - return nil, err - } - return minion, nil - }), nil + if err := rs.registry.CreateMinion(ctx, minion); err != nil { + err = rest.CheckGeneratedNameError(rest.Nodes, err, minion) + return nil, err + } + return minion, nil } // Delete satisfies the RESTStorage interface. -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { minion, err := rs.registry.GetMinion(ctx, id) if minion == nil { return nil, ErrDoesNotExist @@ -77,9 +74,7 @@ func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, if err != nil { return nil, err } - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteMinion(ctx, id) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteMinion(ctx, id) } // Get satisfies the RESTStorage interface. @@ -108,10 +103,10 @@ func (*REST) NewList() runtime.Object { } // Update satisfies the RESTStorage interface. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { minion, ok := obj.(*api.Node) if !ok { - return nil, fmt.Errorf("not a minion: %#v", obj) + return nil, false, fmt.Errorf("not a minion: %#v", obj) } // This is hacky, but minions don't really have a namespace, but kubectl currently automatically // stuffs one in there. Fix it here temporarily until we fix kubectl @@ -123,7 +118,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE oldMinion, err := rs.registry.GetMinion(ctx, minion.Name) if err != nil { - return nil, err + return nil, false, err } // This is hacky, but minion HostIP has been moved from spec to status since v1beta2. When updating @@ -134,16 +129,14 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } if errs := validation.ValidateMinionUpdate(oldMinion, minion); len(errs) > 0 { - return nil, kerrors.NewInvalid("minion", minion.Name, errs) + return nil, false, kerrors.NewInvalid("minion", minion.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.UpdateMinion(ctx, minion) - if err != nil { - return nil, err - } - return rs.registry.GetMinion(ctx, minion.Name) - }), nil + if err := rs.registry.UpdateMinion(ctx, minion); err != nil { + return nil, false, err + } + out, err := rs.registry.GetMinion(ctx, minion.Name) + return out, false, err } // Watch returns Minions events via a watch.Interface. diff --git a/pkg/registry/minion/rest_test.go b/pkg/registry/minion/rest_test.go index 0e3e2c87b83..fe53157e31a 100644 --- a/pkg/registry/minion/rest_test.go +++ b/pkg/registry/minion/rest_test.go @@ -39,27 +39,25 @@ func TestMinionRegistryREST(t *testing.T) { t.Errorf("has unexpected error: %v", err) } - c, err := ms.Create(ctx, &api.Node{ObjectMeta: api.ObjectMeta{Name: "baz"}}) + obj, err := ms.Create(ctx, &api.Node{ObjectMeta: api.ObjectMeta{Name: "baz"}}) if err != nil { t.Fatalf("insert failed: %v", err) } - obj := <-c - if !api.HasObjectMetaSystemFieldValues(&obj.Object.(*api.Node).ObjectMeta) { + if !api.HasObjectMetaSystemFieldValues(&obj.(*api.Node).ObjectMeta) { t.Errorf("storage did not populate object meta field values") } - if m, ok := obj.Object.(*api.Node); !ok || m.Name != "baz" { + if m, ok := obj.(*api.Node); !ok || m.Name != "baz" { t.Errorf("insert return value was weird: %#v", obj) } if obj, err := ms.Get(ctx, "baz"); err != nil || obj.(*api.Node).Name != "baz" { t.Errorf("insert didn't actually insert") } - c, err = ms.Delete(ctx, "bar") + obj, err = ms.Delete(ctx, "bar") if err != nil { t.Fatalf("delete failed") } - obj = <-c - if s, ok := obj.Object.(*api.Status); !ok || s.Status != api.StatusSuccess { + if s, ok := obj.(*api.Status); !ok || s.Status != api.StatusSuccess { t.Errorf("delete return value was weird: %#v", obj) } if _, err := ms.Get(ctx, "bar"); !errors.IsNotFound(err) { @@ -103,7 +101,7 @@ func TestMinionRegistryValidUpdate(t *testing.T) { "foo": "bar", "baz": "home", } - if _, err = storage.Update(ctx, minion); err != nil { + if _, _, err = storage.Update(ctx, minion); err != nil { t.Errorf("Unexpected error: %v", err) } } @@ -136,7 +134,7 @@ func TestMinionRegistryValidatesCreate(t *testing.T) { for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { - t.Errorf("Expected nil channel") + t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) diff --git a/pkg/registry/namespace/rest.go b/pkg/registry/namespace/rest.go index eeaad26519d..21a6a45bf61 100644 --- a/pkg/registry/namespace/rest.go +++ b/pkg/registry/namespace/rest.go @@ -23,7 +23,6 @@ import ( kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -44,48 +43,44 @@ func NewREST(registry generic.Registry) *REST { } // Create creates a Namespace object -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { namespace := obj.(*api.Namespace) if err := rest.BeforeCreate(rest.Namespaces, ctx, obj); err != nil { return nil, err } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := rs.registry.Create(ctx, namespace.Name, namespace); err != nil { - err = rest.CheckGeneratedNameError(rest.Namespaces, err, namespace) - return nil, err - } - return rs.registry.Get(ctx, namespace.Name) - }), nil + if err := rs.registry.Create(ctx, namespace.Name, namespace); err != nil { + err = rest.CheckGeneratedNameError(rest.Namespaces, err, namespace) + return nil, err + } + return rs.registry.Get(ctx, namespace.Name) } // Update updates a Namespace object. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { namespace, ok := obj.(*api.Namespace) if !ok { - return nil, fmt.Errorf("not a namespace: %#v", obj) + return nil, false, fmt.Errorf("not a namespace: %#v", obj) } oldObj, err := rs.registry.Get(ctx, namespace.Name) if err != nil { - return nil, err + return nil, false, err } oldNamespace := oldObj.(*api.Namespace) if errs := validation.ValidateNamespaceUpdate(oldNamespace, namespace); len(errs) > 0 { - return nil, kerrors.NewInvalid("namespace", namespace.Name, errs) + return nil, false, kerrors.NewInvalid("namespace", namespace.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Update(ctx, oldNamespace.Name, oldNamespace) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, oldNamespace.Name) - }), nil + if err := rs.registry.Update(ctx, oldNamespace.Name, oldNamespace); err != nil { + return nil, false, err + } + out, err := rs.registry.Get(ctx, oldNamespace.Name) + return out, false, err } // Delete deletes the Namespace with the specified name -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { obj, err := rs.registry.Get(ctx, id) if err != nil { return nil, err @@ -94,10 +89,7 @@ func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, if !ok { return nil, fmt.Errorf("invalid object type") } - - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, id) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, id) } func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) { diff --git a/pkg/registry/namespace/rest_test.go b/pkg/registry/namespace/rest_test.go index e053e4dd215..9a694984489 100644 --- a/pkg/registry/namespace/rest_test.go +++ b/pkg/registry/namespace/rest_test.go @@ -78,7 +78,7 @@ func TestRESTCreate(t *testing.T) { if !api.HasObjectMetaSystemFieldValues(&item.namespace.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } - if e, a := item.namespace, (<-c).Object; !reflect.DeepEqual(e, a) { + if e, a := item.namespace, c; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } // Ensure we implement the interface @@ -89,11 +89,10 @@ func TestRESTCreate(t *testing.T) { func TestRESTUpdate(t *testing.T) { _, rest := NewTestREST() namespaceA := testNamespace("foo") - c, err := rest.Create(api.NewDefaultContext(), namespaceA) + _, err := rest.Create(api.NewDefaultContext(), namespaceA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c got, err := rest.Get(api.NewDefaultContext(), namespaceA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) @@ -102,11 +101,10 @@ func TestRESTUpdate(t *testing.T) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } namespaceB := testNamespace("foo") - u, err := rest.Update(api.NewDefaultContext(), namespaceB) + _, _, err = rest.Update(api.NewDefaultContext(), namespaceB) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-u got2, err := rest.Get(api.NewDefaultContext(), namespaceB.Name) if err != nil { t.Fatalf("Unexpected error %v", err) @@ -120,16 +118,15 @@ func TestRESTUpdate(t *testing.T) { func TestRESTDelete(t *testing.T) { _, rest := NewTestREST() namespaceA := testNamespace("foo") - c, err := rest.Create(api.NewContext(), namespaceA) + _, err := rest.Create(api.NewContext(), namespaceA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c - c, err = rest.Delete(api.NewContext(), namespaceA.Name) + c, err := rest.Delete(api.NewContext(), namespaceA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) } - if stat := (<-c).Object.(*api.Status); stat.Status != api.StatusSuccess { + if stat := c.(*api.Status); stat.Status != api.StatusSuccess { t.Errorf("unexpected status: %v", stat) } } @@ -137,11 +134,10 @@ func TestRESTDelete(t *testing.T) { func TestRESTGet(t *testing.T) { _, rest := NewTestREST() namespaceA := testNamespace("foo") - c, err := rest.Create(api.NewContext(), namespaceA) + _, err := rest.Create(api.NewContext(), namespaceA) if err != nil { t.Fatalf("Unexpected error %v", err) } - <-c got, err := rest.Get(api.NewContext(), namespaceA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index b27290b1fdb..4e7c995ae69 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -25,7 +25,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -55,32 +54,28 @@ func NewREST(config *RESTConfig) *REST { } } -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { pod := obj.(*api.Pod) if err := rest.BeforeCreate(rest.Pods, ctx, obj); err != nil { return nil, err } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := rs.registry.CreatePod(ctx, pod); err != nil { - err = rest.CheckGeneratedNameError(rest.Pods, err, pod) - return nil, err - } - return rs.registry.GetPod(ctx, pod.Name) - }), nil + if err := rs.registry.CreatePod(ctx, pod); err != nil { + err = rest.CheckGeneratedNameError(rest.Pods, err, pod) + return nil, err + } + return rs.registry.GetPod(ctx, pod.Name) } -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { - return apiserver.MakeAsync(func() (runtime.Object, error) { - namespace, found := api.NamespaceFrom(ctx) - if !found { - return &api.Status{Status: api.StatusFailure}, nil - } - rs.podCache.ClearPodStatus(namespace, id) +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { + namespace, found := api.NamespaceFrom(ctx) + if !found { + return &api.Status{Status: api.StatusFailure}, nil + } + rs.podCache.ClearPodStatus(namespace, id) - return &api.Status{Status: api.StatusSuccess}, rs.registry.DeletePod(ctx, id) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.DeletePod(ctx, id) } func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) { @@ -167,20 +162,19 @@ func (*REST) NewList() runtime.Object { return &api.PodList{} } -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { pod := obj.(*api.Pod) if !api.ValidNamespace(ctx, &pod.ObjectMeta) { - return nil, errors.NewConflict("pod", pod.Namespace, fmt.Errorf("Pod.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("pod", pod.Namespace, fmt.Errorf("Pod.Namespace does not match the provided context")) } if errs := validation.ValidatePod(pod); len(errs) > 0 { - return nil, errors.NewInvalid("pod", pod.Name, errs) + return nil, false, errors.NewInvalid("pod", pod.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := rs.registry.UpdatePod(ctx, pod); err != nil { - return nil, err - } - return rs.registry.GetPod(ctx, pod.Name) - }), nil + if err := rs.registry.UpdatePod(ctx, pod); err != nil { + return nil, false, err + } + out, err := rs.registry.GetPod(ctx, pod.Name) + return out, false, err } // ResourceLocation returns a URL to which one can send traffic for the specified pod. diff --git a/pkg/registry/pod/rest_test.go b/pkg/registry/pod/rest_test.go index e0b2c1c9031..ff133675499 100644 --- a/pkg/registry/pod/rest_test.go +++ b/pkg/registry/pod/rest_test.go @@ -21,7 +21,6 @@ import ( "reflect" "strings" "testing" - "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" @@ -31,6 +30,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) @@ -55,9 +55,8 @@ func (f *fakeCache) ClearPodStatus(namespace, name string) { f.clearedName = name } -func expectApiStatusError(t *testing.T, ch <-chan apiserver.RESTResult, msg string) { - out := <-ch - status, ok := out.Object.(*api.Status) +func expectApiStatusError(t *testing.T, out runtime.Object, msg string) { + status, ok := out.(*api.Status) if !ok { t.Errorf("Expected an api.Status object, was %#v", out) return @@ -67,9 +66,8 @@ func expectApiStatusError(t *testing.T, ch <-chan apiserver.RESTResult, msg stri } } -func expectPod(t *testing.T, ch <-chan apiserver.RESTResult) (*api.Pod, bool) { - out := <-ch - pod, ok := out.Object.(*api.Pod) +func expectPod(t *testing.T, out runtime.Object) (*api.Pod, bool) { + pod, ok := out.(*api.Pod) if !ok || pod == nil { t.Errorf("Expected an api.Pod object, was %#v", out) return nil, false @@ -94,11 +92,10 @@ func TestCreatePodRegistryError(t *testing.T) { }, } ctx := api.NewDefaultContext() - ch, err := storage.Create(ctx, pod) - if err != nil { + _, err := storage.Create(ctx, pod) + if err != podRegistry.Err { t.Fatalf("unexpected error: %v", err) } - expectApiStatusError(t, ch, podRegistry.Err.Error()) } func TestCreatePodSetsIds(t *testing.T) { @@ -118,11 +115,10 @@ func TestCreatePodSetsIds(t *testing.T) { }, } ctx := api.NewDefaultContext() - ch, err := storage.Create(ctx, pod) - if err != nil { + _, err := storage.Create(ctx, pod) + if err != podRegistry.Err { t.Fatalf("unexpected error: %v", err) } - expectApiStatusError(t, ch, podRegistry.Err.Error()) if len(podRegistry.Pod.Name) == 0 { t.Errorf("Expected pod ID to be set, Got %#v", pod) @@ -149,11 +145,10 @@ func TestCreatePodSetsUID(t *testing.T) { }, } ctx := api.NewDefaultContext() - ch, err := storage.Create(ctx, pod) - if err != nil { + _, err := storage.Create(ctx, pod) + if err != podRegistry.Err { t.Fatalf("unexpected error: %v", err) } - expectApiStatusError(t, ch, podRegistry.Err.Error()) if len(podRegistry.Pod.UID) == 0 { t.Errorf("Expected pod UID to be set, Got %#v", pod) @@ -471,15 +466,12 @@ func TestCreatePod(t *testing.T) { } pod.Name = "foo" ctx := api.NewDefaultContext() - channel, err := storage.Create(ctx, pod) + obj, err := storage.Create(ctx, pod) if err != nil { t.Fatalf("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 obj == nil { + t.Fatalf("unexpected object: %#v", obj) } if !api.HasObjectMetaSystemFieldValues(&podRegistry.Pod.ObjectMeta) { t.Errorf("Expected ObjectMeta field values were populated") @@ -520,9 +512,9 @@ func TestUpdatePodWithConflictingNamespace(t *testing.T) { } ctx := api.NewDefaultContext() - channel, err := storage.Update(ctx, pod) - if channel != nil { - t.Error("Expected a nil channel, but we got a value") + obj, created, err := storage.Update(ctx, pod) + if obj != nil || created { + t.Error("Expected a nil channel, but we got a value or created") } if err == nil { t.Errorf("Expected an error, but we didn't get one") @@ -648,19 +640,12 @@ func TestDeletePod(t *testing.T) { podCache: fakeCache, } ctx := api.NewDefaultContext() - channel, err := storage.Delete(ctx, "foo") + result, err := storage.Delete(ctx, "foo") if err != nil { t.Fatalf("unexpected error: %v", err) } - var result apiserver.RESTResult - select { - case result = <-channel: - // Do nothing, this is expected. - case <-time.After(time.Millisecond * 100): - t.Error("Unexpected timeout on async channel") - } if fakeCache.clearedNamespace != "default" || fakeCache.clearedName != "foo" { - t.Errorf("Unexpeceted cache delete: %s %s %#v", fakeCache.clearedName, fakeCache.clearedNamespace, result.Object) + t.Errorf("Unexpeceted cache delete: %s %s %#v", fakeCache.clearedName, fakeCache.clearedNamespace, result) } } diff --git a/pkg/registry/resourcequota/rest.go b/pkg/registry/resourcequota/rest.go index 3f22be18826..e577e0cc516 100644 --- a/pkg/registry/resourcequota/rest.go +++ b/pkg/registry/resourcequota/rest.go @@ -22,7 +22,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -44,7 +43,7 @@ func NewREST(registry generic.Registry) *REST { } // Create a ResourceQuota object -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { resourceQuota, ok := obj.(*api.ResourceQuota) if !ok { return nil, fmt.Errorf("invalid object type") @@ -66,29 +65,27 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } api.FillObjectMetaSystemFields(ctx, &resourceQuota.ObjectMeta) - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Create(ctx, resourceQuota.Name, resourceQuota) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, resourceQuota.Name) - }), nil + err := rs.registry.Create(ctx, resourceQuota.Name, resourceQuota) + if err != nil { + return nil, err + } + return rs.registry.Get(ctx, resourceQuota.Name) } // Update updates a ResourceQuota object. -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { resourceQuota, ok := obj.(*api.ResourceQuota) if !ok { - return nil, fmt.Errorf("invalid object type") + return nil, false, fmt.Errorf("invalid object type") } if !api.ValidNamespace(ctx, &resourceQuota.ObjectMeta) { - return nil, errors.NewConflict("resourceQuota", resourceQuota.Namespace, fmt.Errorf("ResourceQuota.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("resourceQuota", resourceQuota.Namespace, fmt.Errorf("ResourceQuota.Namespace does not match the provided context")) } oldObj, err := rs.registry.Get(ctx, resourceQuota.Name) if err != nil { - return nil, err + return nil, false, err } editResourceQuota := oldObj.(*api.ResourceQuota) @@ -100,20 +97,18 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE editResourceQuota.Spec = resourceQuota.Spec if errs := validation.ValidateResourceQuota(editResourceQuota); len(errs) > 0 { - return nil, errors.NewInvalid("resourceQuota", editResourceQuota.Name, errs) + return nil, false, errors.NewInvalid("resourceQuota", editResourceQuota.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - err := rs.registry.Update(ctx, editResourceQuota.Name, editResourceQuota) - if err != nil { - return nil, err - } - return rs.registry.Get(ctx, editResourceQuota.Name) - }), nil + if err := rs.registry.Update(ctx, editResourceQuota.Name, editResourceQuota); err != nil { + return nil, false, err + } + out, err := rs.registry.Get(ctx, editResourceQuota.Name) + return out, false, err } // Delete deletes the ResourceQuota with the specified name -func (rs *REST) Delete(ctx api.Context, name string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, name string) (runtime.Object, error) { obj, err := rs.registry.Get(ctx, name) if err != nil { return nil, err @@ -122,9 +117,7 @@ func (rs *REST) Delete(ctx api.Context, name string) (<-chan apiserver.RESTResul if !ok { return nil, fmt.Errorf("invalid object type") } - return apiserver.MakeAsync(func() (runtime.Object, error) { - return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, name) - }), nil + return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(ctx, name) } // Get gets a ResourceQuota with the specified name diff --git a/pkg/registry/resourcequotausage/rest.go b/pkg/registry/resourcequotausage/rest.go index cfd63cf4c7a..b2d9a51454e 100644 --- a/pkg/registry/resourcequotausage/rest.go +++ b/pkg/registry/resourcequotausage/rest.go @@ -20,7 +20,6 @@ import ( "fmt" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) @@ -42,15 +41,13 @@ func (*REST) New() runtime.Object { } // Create takes the incoming ResourceQuotaUsage and applies the latest status atomically to a ResourceQuota -func (b *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (b *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { resourceQuotaUsage, ok := obj.(*api.ResourceQuotaUsage) if !ok { return nil, fmt.Errorf("incorrect type: %#v", obj) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - if err := b.registry.ApplyStatus(ctx, resourceQuotaUsage); err != nil { - return nil, err - } - return &api.Status{Status: api.StatusSuccess}, nil - }), nil + if err := b.registry.ApplyStatus(ctx, resourceQuotaUsage); err != nil { + return nil, err + } + return &api.Status{Status: api.StatusSuccess}, nil } diff --git a/pkg/registry/service/rest.go b/pkg/registry/service/rest.go index 638cf592c84..a2906179219 100644 --- a/pkg/registry/service/rest.go +++ b/pkg/registry/service/rest.go @@ -25,7 +25,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" - "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion" @@ -80,7 +79,7 @@ func reloadIPsFromStorage(ipa *ipAllocator, registry Registry) { } } -func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { service := obj.(*api.Service) if err := rest.BeforeCreate(rest.Services, ctx, obj); err != nil { @@ -102,61 +101,59 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE } } - return apiserver.MakeAsync(func() (runtime.Object, error) { - // TODO: Move this to post-creation rectification loop, so that we make/remove external load balancers - // correctly no matter what http operations happen. - if service.Spec.CreateExternalLoadBalancer { - if rs.cloud == nil { - return nil, fmt.Errorf("requested an external service, but no cloud provider supplied.") - } - if service.Spec.Protocol != api.ProtocolTCP { - // TODO: Support UDP here too. - return nil, fmt.Errorf("external load balancers for non TCP services are not currently supported.") - } - balancer, ok := rs.cloud.TCPLoadBalancer() - if !ok { - return nil, fmt.Errorf("the cloud provider does not support external TCP load balancers.") - } - zones, ok := rs.cloud.Zones() - if !ok { - return nil, fmt.Errorf("the cloud provider does not support zone enumeration.") - } - hosts, err := rs.machines.ListMinions(ctx) - if err != nil { - return nil, err - } - zone, err := zones.GetZone() - if err != nil { - return nil, err - } - // TODO: We should be able to rely on valid input, and not do defaulting here. - var affinityType api.AffinityType = service.Spec.SessionAffinity - if affinityType == "" { - affinityType = api.AffinityTypeNone - } - if len(service.Spec.PublicIPs) > 0 { - for _, publicIP := range service.Spec.PublicIPs { - _, err = balancer.CreateTCPLoadBalancer(service.Name, zone.Region, net.ParseIP(publicIP), service.Spec.Port, hostsFromMinionList(hosts), affinityType) - if err != nil { - // TODO: have to roll-back any successful calls. - return nil, err - } - } - } else { - ip, err := balancer.CreateTCPLoadBalancer(service.Name, zone.Region, nil, service.Spec.Port, hostsFromMinionList(hosts), affinityType) - if err != nil { - return nil, err - } - service.Spec.PublicIPs = []string{ip.String()} - } + // TODO: Move this to post-creation rectification loop, so that we make/remove external load balancers + // correctly no matter what http operations happen. + if service.Spec.CreateExternalLoadBalancer { + if rs.cloud == nil { + return nil, fmt.Errorf("requested an external service, but no cloud provider supplied.") } - - if err := rs.registry.CreateService(ctx, service); err != nil { - err = rest.CheckGeneratedNameError(rest.Services, err, service) + if service.Spec.Protocol != api.ProtocolTCP { + // TODO: Support UDP here too. + return nil, fmt.Errorf("external load balancers for non TCP services are not currently supported.") + } + balancer, ok := rs.cloud.TCPLoadBalancer() + if !ok { + return nil, fmt.Errorf("the cloud provider does not support external TCP load balancers.") + } + zones, ok := rs.cloud.Zones() + if !ok { + return nil, fmt.Errorf("the cloud provider does not support zone enumeration.") + } + hosts, err := rs.machines.ListMinions(ctx) + if err != nil { return nil, err } - return rs.registry.GetService(ctx, service.Name) - }), nil + zone, err := zones.GetZone() + if err != nil { + return nil, err + } + // TODO: We should be able to rely on valid input, and not do defaulting here. + var affinityType api.AffinityType = service.Spec.SessionAffinity + if affinityType == "" { + affinityType = api.AffinityTypeNone + } + if len(service.Spec.PublicIPs) > 0 { + for _, publicIP := range service.Spec.PublicIPs { + _, err = balancer.CreateTCPLoadBalancer(service.Name, zone.Region, net.ParseIP(publicIP), service.Spec.Port, hostsFromMinionList(hosts), affinityType) + if err != nil { + // TODO: have to roll-back any successful calls. + return nil, err + } + } + } else { + ip, err := balancer.CreateTCPLoadBalancer(service.Name, zone.Region, nil, service.Spec.Port, hostsFromMinionList(hosts), affinityType) + if err != nil { + return nil, err + } + service.Spec.PublicIPs = []string{ip.String()} + } + } + + if err := rs.registry.CreateService(ctx, service); err != nil { + err = rest.CheckGeneratedNameError(rest.Services, err, service) + return nil, err + } + return rs.registry.GetService(ctx, service.Name) } func hostsFromMinionList(list *api.NodeList) []string { @@ -167,16 +164,14 @@ func hostsFromMinionList(list *api.NodeList) []string { return result } -func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) { service, err := rs.registry.GetService(ctx, id) if err != nil { return nil, err } rs.portalMgr.Release(net.ParseIP(service.Spec.PortalIP)) - return apiserver.MakeAsync(func() (runtime.Object, error) { - rs.deleteExternalLoadBalancer(service) - return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteService(ctx, id) - }), nil + rs.deleteExternalLoadBalancer(service) + return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteService(ctx, id) } func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) { @@ -217,30 +212,29 @@ func (*REST) NewList() runtime.Object { return &api.Service{} } -func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { service := obj.(*api.Service) if !api.ValidNamespace(ctx, &service.ObjectMeta) { - return nil, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context")) + return nil, false, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context")) } oldService, err := rs.registry.GetService(ctx, service.Name) if err != nil { - return nil, err + return nil, false, err } // Copy over non-user fields // TODO: make this a merge function if errs := validation.ValidateServiceUpdate(oldService, service); len(errs) > 0 { - return nil, errors.NewInvalid("service", service.Name, errs) + return nil, false, errors.NewInvalid("service", service.Name, errs) } - return apiserver.MakeAsync(func() (runtime.Object, error) { - // TODO: check to see if external load balancer status changed - err = rs.registry.UpdateService(ctx, service) - if err != nil { - return nil, err - } - return rs.registry.GetService(ctx, service.Name) - }), nil + // TODO: check to see if external load balancer status changed + err = rs.registry.UpdateService(ctx, service) + if err != nil { + return nil, false, err + } + out, err := rs.registry.GetService(ctx, service.Name) + return out, false, err } // ResourceLocation returns a URL to which one can send traffic for the specified service. diff --git a/pkg/registry/service/rest_test.go b/pkg/registry/service/rest_test.go index 8d228844734..60a3096015f 100644 --- a/pkg/registry/service/rest_test.go +++ b/pkg/registry/service/rest_test.go @@ -56,9 +56,8 @@ func TestServiceRegistryCreate(t *testing.T) { }, } ctx := api.NewDefaultContext() - c, _ := storage.Create(ctx, svc) - created_svc := <-c - created_service := created_svc.Object.(*api.Service) + created_svc, _ := storage.Create(ctx, svc) + created_service := created_svc.(*api.Service) if !api.HasObjectMetaSystemFieldValues(&created_service.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } @@ -109,7 +108,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) { for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { - t.Errorf("Expected nil channel") + t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) @@ -129,7 +128,7 @@ func TestServiceRegistryUpdate(t *testing.T) { }, }) storage := NewREST(registry, nil, nil, makeIPNet(t)) - c, err := storage.Update(ctx, &api.Service{ + updated_svc, created, err := storage.Update(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Port: 6502, @@ -141,11 +140,13 @@ func TestServiceRegistryUpdate(t *testing.T) { if err != nil { t.Fatalf("Expected no error: %v", err) } - if c == nil { - t.Errorf("Expected non-nil channel") + if updated_svc == nil { + t.Errorf("Expected non-nil object") } - updated_svc := <-c - updated_service := updated_svc.Object.(*api.Service) + if created { + t.Errorf("expected not created") + } + updated_service := updated_svc.(*api.Service) if updated_service.Name != "foo" { t.Errorf("Expected foo, but got %v", updated_service.Name) } @@ -186,9 +187,9 @@ func TestServiceStorageValidatesUpdate(t *testing.T) { }, } for _, failureCase := range failureCases { - c, err := storage.Update(ctx, &failureCase) - if c != nil { - t.Errorf("Expected nil channel") + c, created, err := storage.Update(ctx, &failureCase) + if c != nil || created { + t.Errorf("Expected nil object or created false") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) @@ -212,8 +213,7 @@ func TestServiceRegistryExternalService(t *testing.T) { SessionAffinity: api.AffinityTypeNone, }, } - c, _ := storage.Create(ctx, svc) - <-c + storage.Create(ctx, svc) if len(fakeCloud.Calls) != 2 || fakeCloud.Calls[0] != "get-zone" || fakeCloud.Calls[1] != "create" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } @@ -244,8 +244,7 @@ func TestServiceRegistryExternalServiceError(t *testing.T) { }, } ctx := api.NewDefaultContext() - c, _ := storage.Create(ctx, svc) - <-c + storage.Create(ctx, svc) if len(fakeCloud.Calls) != 1 || fakeCloud.Calls[0] != "get-zone" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } @@ -269,8 +268,7 @@ func TestServiceRegistryDelete(t *testing.T) { }, } registry.CreateService(ctx, svc) - c, _ := storage.Delete(ctx, svc.Name) - <-c + storage.Delete(ctx, svc.Name) if len(fakeCloud.Calls) != 0 { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } @@ -295,8 +293,7 @@ func TestServiceRegistryDeleteExternal(t *testing.T) { }, } registry.CreateService(ctx, svc) - c, _ := storage.Delete(ctx, svc.Name) - <-c + storage.Delete(ctx, svc.Name) if len(fakeCloud.Calls) != 2 || fakeCloud.Calls[0] != "get-zone" || fakeCloud.Calls[1] != "delete" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } @@ -413,9 +410,8 @@ func TestServiceRegistryIPAllocation(t *testing.T) { }, } ctx := api.NewDefaultContext() - c1, _ := rest.Create(ctx, svc1) - created_svc1 := <-c1 - created_service_1 := created_svc1.Object.(*api.Service) + created_svc1, _ := rest.Create(ctx, svc1) + created_service_1 := created_svc1.(*api.Service) if created_service_1.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service_1.Name) } @@ -432,9 +428,8 @@ func TestServiceRegistryIPAllocation(t *testing.T) { SessionAffinity: api.AffinityTypeNone, }} ctx = api.NewDefaultContext() - c2, _ := rest.Create(ctx, svc2) - created_svc2 := <-c2 - created_service_2 := created_svc2.Object.(*api.Service) + created_svc2, _ := rest.Create(ctx, svc2) + created_service_2 := created_svc2.(*api.Service) if created_service_2.Name != "bar" { t.Errorf("Expected bar, but got %v", created_service_2.Name) } @@ -453,9 +448,8 @@ func TestServiceRegistryIPAllocation(t *testing.T) { }, } ctx = api.NewDefaultContext() - c3, _ := rest.Create(ctx, svc3) - created_svc3 := <-c3 - created_service_3 := created_svc3.Object.(*api.Service) + created_svc3, _ := rest.Create(ctx, svc3) + created_service_3 := created_svc3.(*api.Service) if created_service_3.Spec.PortalIP != "1.2.3.93" { // specific IP t.Errorf("Unexpected PortalIP: %s", created_service_3.Spec.PortalIP) } @@ -478,9 +472,8 @@ func TestServiceRegistryIPReallocation(t *testing.T) { }, } ctx := api.NewDefaultContext() - c1, _ := rest.Create(ctx, svc1) - created_svc1 := <-c1 - created_service_1 := created_svc1.Object.(*api.Service) + created_svc1, _ := rest.Create(ctx, svc1) + created_service_1 := created_svc1.(*api.Service) if created_service_1.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service_1.Name) } @@ -488,8 +481,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) { t.Errorf("Unexpected PortalIP: %s", created_service_1.Spec.PortalIP) } - c, _ := rest.Delete(ctx, created_service_1.Name) - <-c + rest.Delete(ctx, created_service_1.Name) svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "bar"}, @@ -501,9 +493,8 @@ func TestServiceRegistryIPReallocation(t *testing.T) { }, } ctx = api.NewDefaultContext() - c2, _ := rest.Create(ctx, svc2) - created_svc2 := <-c2 - created_service_2 := created_svc2.Object.(*api.Service) + created_svc2, _ := rest.Create(ctx, svc2) + created_service_2 := created_svc2.(*api.Service) if created_service_2.Name != "bar" { t.Errorf("Expected bar, but got %v", created_service_2.Name) } @@ -529,9 +520,8 @@ func TestServiceRegistryIPUpdate(t *testing.T) { }, } ctx := api.NewDefaultContext() - c, _ := rest.Create(ctx, svc) - created_svc := <-c - created_service := created_svc.Object.(*api.Service) + created_svc, _ := rest.Create(ctx, svc) + created_service := created_svc.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } @@ -543,9 +533,8 @@ func TestServiceRegistryIPUpdate(t *testing.T) { *update = *created_service update.Spec.Port = 6503 - c, _ = rest.Update(ctx, update) - updated_svc := <-c - updated_service := updated_svc.Object.(*api.Service) + updated_svc, _, _ := rest.Update(ctx, update) + updated_service := updated_svc.(*api.Service) if updated_service.Spec.Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Port) } @@ -554,7 +543,7 @@ func TestServiceRegistryIPUpdate(t *testing.T) { update.Spec.Port = 6503 update.Spec.PortalIP = "1.2.3.76" // error - _, err := rest.Update(ctx, update) + _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Error("Unexpected error type: %v", err) } @@ -578,9 +567,8 @@ func TestServiceRegistryIPExternalLoadBalancer(t *testing.T) { }, } ctx := api.NewDefaultContext() - c, _ := rest.Create(ctx, svc) - created_svc := <-c - created_service := created_svc.Object.(*api.Service) + created_svc, _ := rest.Create(ctx, svc) + created_service := created_svc.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } @@ -591,7 +579,7 @@ func TestServiceRegistryIPExternalLoadBalancer(t *testing.T) { update := new(api.Service) *update = *created_service - _, err := rest.Update(ctx, update) + _, _, err := rest.Update(ctx, update) if err != nil { t.Errorf("Unexpected error %v", err) } @@ -614,8 +602,7 @@ func TestServiceRegistryIPReloadFromStorage(t *testing.T) { }, } ctx := api.NewDefaultContext() - c, _ := rest1.Create(ctx, svc) - <-c + rest1.Create(ctx, svc) svc = &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ @@ -625,8 +612,7 @@ func TestServiceRegistryIPReloadFromStorage(t *testing.T) { SessionAffinity: api.AffinityTypeNone, }, } - c, _ = rest1.Create(ctx, svc) - <-c + rest1.Create(ctx, svc) // This will reload from storage, finding the previous 2 rest2 := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) @@ -641,9 +627,8 @@ func TestServiceRegistryIPReloadFromStorage(t *testing.T) { SessionAffinity: api.AffinityTypeNone, }, } - c, _ = rest2.Create(ctx, svc) - created_svc := <-c - created_service := created_svc.Object.(*api.Service) + created_svc, _ := rest2.Create(ctx, svc) + created_service := created_svc.(*api.Service) if created_service.Spec.PortalIP != "1.2.3.3" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } @@ -657,9 +642,9 @@ func TestCreateServiceWithConflictingNamespace(t *testing.T) { } ctx := api.NewDefaultContext() - channel, err := storage.Create(ctx, service) - if channel != nil { - t.Error("Expected a nil channel, but we got a value") + obj, err := storage.Create(ctx, service) + if obj != nil { + t.Error("Expected a nil object, but we got a value") } if err == nil { t.Errorf("Expected an error, but we didn't get one") @@ -675,9 +660,9 @@ func TestUpdateServiceWithConflictingNamespace(t *testing.T) { } ctx := api.NewDefaultContext() - channel, err := storage.Update(ctx, service) - if channel != nil { - t.Error("Expected a nil channel, but we got a value") + obj, created, err := storage.Update(ctx, service) + if obj != nil || created { + t.Error("Expected a nil object, but we got a value or created was true") } if err == nil { t.Errorf("Expected an error, but we didn't get one") diff --git a/test/integration/auth_test.go b/test/integration/auth_test.go index 63b66e51a08..4f761589bd9 100644 --- a/test/integration/auth_test.go +++ b/test/integration/auth_test.go @@ -175,6 +175,7 @@ var timeoutFlag = "?timeout=60s" // Requests to try. Each one should be forbidden or not forbidden // depending on the authentication and authorization setup of the master. var code200 = map[int]bool{200: true} +var code201 = map[int]bool{201: true} var code400 = map[int]bool{400: true} var code403 = map[int]bool{403: true} var code404 = map[int]bool{404: true} @@ -197,7 +198,7 @@ func getTestRequests() []struct { }{ // Normal methods on pods {"GET", "/api/v1beta1/pods", "", code200}, - {"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code200}, + {"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code201}, {"PUT", "/api/v1beta1/pods/a" + timeoutFlag, aPod, code200}, {"GET", "/api/v1beta1/pods", "", code200}, {"GET", "/api/v1beta1/pods/a", "", code200}, @@ -217,7 +218,7 @@ func getTestRequests() []struct { // Normal methods on services {"GET", "/api/v1beta1/services", "", code200}, - {"POST", "/api/v1beta1/services" + timeoutFlag, aService, code200}, + {"POST", "/api/v1beta1/services" + timeoutFlag, aService, code201}, {"PUT", "/api/v1beta1/services/a" + timeoutFlag, aService, code200}, {"GET", "/api/v1beta1/services", "", code200}, {"GET", "/api/v1beta1/services/a", "", code200}, @@ -225,7 +226,7 @@ func getTestRequests() []struct { // Normal methods on replicationControllers {"GET", "/api/v1beta1/replicationControllers", "", code200}, - {"POST", "/api/v1beta1/replicationControllers" + timeoutFlag, aRC, code200}, + {"POST", "/api/v1beta1/replicationControllers" + timeoutFlag, aRC, code201}, {"PUT", "/api/v1beta1/replicationControllers/a" + timeoutFlag, aRC, code200}, {"GET", "/api/v1beta1/replicationControllers", "", code200}, {"GET", "/api/v1beta1/replicationControllers/a", "", code200}, @@ -233,7 +234,7 @@ func getTestRequests() []struct { // Normal methods on endpoints {"GET", "/api/v1beta1/endpoints", "", code200}, - {"POST", "/api/v1beta1/endpoints" + timeoutFlag, aEndpoints, code200}, + {"POST", "/api/v1beta1/endpoints" + timeoutFlag, aEndpoints, code201}, {"PUT", "/api/v1beta1/endpoints/a" + timeoutFlag, aEndpoints, code200}, {"GET", "/api/v1beta1/endpoints", "", code200}, {"GET", "/api/v1beta1/endpoints/a", "", code200}, @@ -241,7 +242,7 @@ func getTestRequests() []struct { // Normal methods on minions {"GET", "/api/v1beta1/minions", "", code200}, - {"POST", "/api/v1beta1/minions" + timeoutFlag, aMinion, code200}, + {"POST", "/api/v1beta1/minions" + timeoutFlag, aMinion, code201}, {"PUT", "/api/v1beta1/minions/a" + timeoutFlag, aMinion, code409}, // See #2115 about why 409 {"GET", "/api/v1beta1/minions", "", code200}, {"GET", "/api/v1beta1/minions/a", "", code200}, @@ -249,7 +250,7 @@ func getTestRequests() []struct { // Normal methods on events {"GET", "/api/v1beta1/events", "", code200}, - {"POST", "/api/v1beta1/events" + timeoutFlag, aEvent, code200}, + {"POST", "/api/v1beta1/events" + timeoutFlag, aEvent, code201}, {"PUT", "/api/v1beta1/events/a" + timeoutFlag, aEvent, code200}, {"GET", "/api/v1beta1/events", "", code200}, {"GET", "/api/v1beta1/events", "", code200}, @@ -258,8 +259,8 @@ func getTestRequests() []struct { // Normal methods on bindings {"GET", "/api/v1beta1/bindings", "", code405}, // Bindings are write-only - {"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code200}, // Need a pod to bind or you get a 404 - {"POST", "/api/v1beta1/bindings" + timeoutFlag, aBinding, code200}, + {"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code201}, // Need a pod to bind or you get a 404 + {"POST", "/api/v1beta1/bindings" + timeoutFlag, aBinding, code201}, {"PUT", "/api/v1beta1/bindings/a" + timeoutFlag, aBinding, code404}, {"GET", "/api/v1beta1/bindings", "", code405}, {"GET", "/api/v1beta1/bindings/a", "", code404}, // No bindings instances @@ -727,7 +728,7 @@ func TestNamespaceAuthorization(t *testing.T) { statusCodes map[int]bool // allowed status codes. }{ - {"POST", "/api/v1beta1/pods" + timeoutFlag + "&namespace=foo", "foo", aPod, code200}, + {"POST", "/api/v1beta1/pods" + timeoutFlag + "&namespace=foo", "foo", aPod, code201}, {"GET", "/api/v1beta1/pods?namespace=foo", "foo", "", code200}, {"GET", "/api/v1beta1/pods/a?namespace=foo", "foo", "", code200}, {"DELETE", "/api/v1beta1/pods/a" + timeoutFlag + "&namespace=foo", "foo", "", code200}, @@ -838,7 +839,7 @@ func TestKindAuthorization(t *testing.T) { body string statusCodes map[int]bool // allowed status codes. }{ - {"POST", "/api/v1beta1/services" + timeoutFlag, aService, code200}, + {"POST", "/api/v1beta1/services" + timeoutFlag, aService, code201}, {"GET", "/api/v1beta1/services", "", code200}, {"GET", "/api/v1beta1/services/a", "", code200}, {"DELETE", "/api/v1beta1/services/a" + timeoutFlag, "", code200},