Errors should be part of api/errors, not apiserver

Renames constructor methods to be errors.New<name> which changed a few
places.
This commit is contained in:
Clayton Coleman 2014-09-03 17:16:00 -04:00
parent 6dd4831de8
commit 34c40e4e48
20 changed files with 407 additions and 342 deletions

134
pkg/api/errors/errors.go Normal file
View File

@ -0,0 +1,134 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package errors
import (
"fmt"
"net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)
// statusError is an error intended for consumption by a REST API server.
type statusError struct {
status api.Status
}
// Error implements the Error interface.
func (e *statusError) Error() string {
return e.status.Message
}
// Status converts this error into an api.Status object.
func (e *statusError) Status() api.Status {
return e.status
}
// NewNotFound returns a new error which indicates that the resource of the kind and the name was not found.
func NewNotFound(kind, name string) error {
return &statusError{api.Status{
Status: api.StatusFailure,
Code: http.StatusNotFound,
Reason: api.StatusReasonNotFound,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q not found", kind, name),
}}
}
// NewAlreadyExists returns an error indicating the item requested exists by that identifier.
func NewAlreadyExists(kind, name string) error {
return &statusError{api.Status{
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: api.StatusReasonAlreadyExists,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q already exists", kind, name),
}}
}
// NewConflict returns an error indicating the item can't be updated as provided.
func NewConflict(kind, name string, err error) error {
return &statusError{api.Status{
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: api.StatusReasonConflict,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q cannot be updated: %s", kind, name, err),
}}
}
// NewInvalid returns an error indicating the item is invalid and cannot be processed.
func NewInvalid(kind, name string, errs ErrorList) error {
causes := make([]api.StatusCause, 0, len(errs))
for i := range errs {
if err, ok := errs[i].(ValidationError); ok {
causes = append(causes, api.StatusCause{
Type: api.CauseType(err.Type),
Message: err.Error(),
Field: err.Field,
})
}
}
return &statusError{api.Status{
Status: api.StatusFailure,
Code: 422, // RFC 4918
Reason: api.StatusReasonInvalid,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
Causes: causes,
},
Message: fmt.Sprintf("%s %q is invalid: %s", kind, name, errs.ToError()),
}}
}
// IsNotFound returns true if the specified error was created by NewNotFoundErr.
func IsNotFound(err error) bool {
return reasonForError(err) == api.StatusReasonNotFound
}
// IsAlreadyExists determines if the err is an error which indicates that a specified resource already exists.
func IsAlreadyExists(err error) bool {
return reasonForError(err) == api.StatusReasonAlreadyExists
}
// IsConflict determines if the err is an error which indicates the provided update conflicts.
func IsConflict(err error) bool {
return reasonForError(err) == api.StatusReasonConflict
}
// IsInvalid determines if the err is an error which indicates the provided resource is not valid.
func IsInvalid(err error) bool {
return reasonForError(err) == api.StatusReasonInvalid
}
func reasonForError(err error) api.StatusReason {
switch t := err.(type) {
case *statusError:
return t.status.Reason
}
return api.StatusReasonUnknown
}

View File

@ -0,0 +1,133 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package errors
import (
"errors"
"fmt"
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)
func TestErrorNew(t *testing.T) {
err := NewAlreadyExists("test", "1")
if !IsAlreadyExists(err) {
t.Errorf("expected to be already_exists")
}
if IsConflict(err) {
t.Errorf("expected to not be confict")
}
if IsNotFound(err) {
t.Errorf(fmt.Sprintf("expected to not be %s", api.StatusReasonNotFound))
}
if IsInvalid(err) {
t.Errorf("expected to not be invalid")
}
if !IsConflict(NewConflict("test", "2", errors.New("message"))) {
t.Errorf("expected to be conflict")
}
if !IsNotFound(NewNotFound("test", "3")) {
t.Errorf("expected to be not found")
}
if !IsInvalid(NewInvalid("test", "2", nil)) {
t.Errorf("expected to be invalid")
}
}
func TestNewInvalid(t *testing.T) {
testCases := []struct {
Err ValidationError
Details *api.StatusDetails
}{
{
NewFieldDuplicate("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueDuplicate,
Field: "field[0].name",
}},
},
},
{
NewFieldInvalid("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueInvalid,
Field: "field[0].name",
}},
},
},
{
NewFieldNotFound("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueNotFound,
Field: "field[0].name",
}},
},
},
{
NewFieldNotSupported("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueNotSupported,
Field: "field[0].name",
}},
},
},
{
NewFieldRequired("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueRequired,
Field: "field[0].name",
}},
},
},
}
for i, testCase := range testCases {
vErr, expected := testCase.Err, testCase.Details
expected.Causes[0].Message = vErr.Error()
err := NewInvalid("kind", "name", ErrorList{vErr})
status := err.(*statusError).Status()
if status.Code != 422 || status.Reason != api.StatusReasonInvalid {
t.Errorf("%d: unexpected status: %#v", i, status)
}
if !reflect.DeepEqual(expected, status.Details) {
t.Errorf("%d: expected %#v, got %#v", expected, status.Details)
}
}
}
func Test_reasonForError(t *testing.T) {
if e, a := api.StatusReasonUnknown, reasonForError(nil); e != a {
t.Errorf("unexpected reason type: %#v", a)
}
}

View File

@ -75,28 +75,28 @@ func (v ValidationError) Error() string {
return fmt.Sprintf("%s: %v '%v'", v.Field, ValueOf(v.Type), v.BadValue)
}
// NewInvalid returns a ValidationError indicating "value required"
func NewRequired(field string, value interface{}) ValidationError {
// NewFieldRequired returns a ValidationError indicating "value required"
func NewFieldRequired(field string, value interface{}) ValidationError {
return ValidationError{ValidationErrorTypeRequired, field, value}
}
// NewInvalid returns a ValidationError indicating "invalid value"
func NewInvalid(field string, value interface{}) ValidationError {
// NewFieldInvalid returns a ValidationError indicating "invalid value"
func NewFieldInvalid(field string, value interface{}) ValidationError {
return ValidationError{ValidationErrorTypeInvalid, field, value}
}
// NewNotSupported returns a ValidationError indicating "unsupported value"
func NewNotSupported(field string, value interface{}) ValidationError {
// NewFieldNotSupported returns a ValidationError indicating "unsupported value"
func NewFieldNotSupported(field string, value interface{}) ValidationError {
return ValidationError{ValidationErrorTypeNotSupported, field, value}
}
// NewDuplicate returns a ValidationError indicating "duplicate value"
func NewDuplicate(field string, value interface{}) ValidationError {
// NewFieldDuplicate returns a ValidationError indicating "duplicate value"
func NewFieldDuplicate(field string, value interface{}) ValidationError {
return ValidationError{ValidationErrorTypeDuplicate, field, value}
}
// NewNotFound returns a ValidationError indicating "value not found"
func NewNotFound(field string, value interface{}) ValidationError {
// NewFieldNotFound returns a ValidationError indicating "value not found"
func NewFieldNotFound(field string, value interface{}) ValidationError {
return ValidationError{ValidationErrorTypeNotFound, field, value}
}

View File

@ -28,23 +28,23 @@ func TestMakeFuncs(t *testing.T) {
expected ValidationErrorType
}{
{
func() ValidationError { return NewInvalid("f", "v") },
func() ValidationError { return NewFieldInvalid("f", "v") },
ValidationErrorTypeInvalid,
},
{
func() ValidationError { return NewNotSupported("f", "v") },
func() ValidationError { return NewFieldNotSupported("f", "v") },
ValidationErrorTypeNotSupported,
},
{
func() ValidationError { return NewDuplicate("f", "v") },
func() ValidationError { return NewFieldDuplicate("f", "v") },
ValidationErrorTypeDuplicate,
},
{
func() ValidationError { return NewNotFound("f", "v") },
func() ValidationError { return NewFieldNotFound("f", "v") },
ValidationErrorTypeNotFound,
},
{
func() ValidationError { return NewRequired("f", "v") },
func() ValidationError { return NewFieldRequired("f", "v") },
ValidationErrorTypeRequired,
},
}
@ -58,7 +58,7 @@ func TestMakeFuncs(t *testing.T) {
}
func TestValidationError(t *testing.T) {
s := NewInvalid("foo", "bar").Error()
s := NewFieldInvalid("foo", "bar").Error()
if !strings.Contains(s, "foo") || !strings.Contains(s, "bar") || !strings.Contains(s, ValueOf(ValidationErrorTypeInvalid)) {
t.Errorf("error message did not contain expected values, got %s", s)
}
@ -72,7 +72,7 @@ func TestErrorList(t *testing.T) {
if a := errorListInternal(errList).Error(); a != "" {
t.Errorf("expected empty string, got %v", a)
}
errList = append(errList, NewInvalid("field", "value"))
errList = append(errList, NewFieldInvalid("field", "value"))
// The fact that this compiles is the test.
}
@ -108,15 +108,15 @@ func TestErrListPrefix(t *testing.T) {
Expected string
}{
{
NewNotFound("[0].bar", "value"),
NewFieldNotFound("[0].bar", "value"),
"foo[0].bar",
},
{
NewInvalid("field", "value"),
NewFieldInvalid("field", "value"),
"foo.field",
},
{
NewDuplicate("", "value"),
NewFieldDuplicate("", "value"),
"foo",
},
}
@ -138,15 +138,15 @@ func TestErrListPrefixIndex(t *testing.T) {
Expected string
}{
{
NewNotFound("[0].bar", "value"),
NewFieldNotFound("[0].bar", "value"),
"[1][0].bar",
},
{
NewInvalid("field", "value"),
NewFieldInvalid("field", "value"),
"[1].field",
},
{
NewDuplicate("", "value"),
NewFieldDuplicate("", "value"),
"[1]",
},
}

View File

@ -37,11 +37,11 @@ func validateVolumes(volumes []api.Volume) (util.StringSet, errs.ErrorList) {
el = validateSource(vol.Source).Prefix("source")
}
if len(vol.Name) == 0 {
el = append(el, errs.NewRequired("name", vol.Name))
el = append(el, errs.NewFieldRequired("name", vol.Name))
} else if !util.IsDNSLabel(vol.Name) {
el = append(el, errs.NewInvalid("name", vol.Name))
el = append(el, errs.NewFieldInvalid("name", vol.Name))
} else if allNames.Has(vol.Name) {
el = append(el, errs.NewDuplicate("name", vol.Name))
el = append(el, errs.NewFieldDuplicate("name", vol.Name))
}
if len(el) == 0 {
allNames.Insert(vol.Name)
@ -64,7 +64,7 @@ func validateSource(source *api.VolumeSource) errs.ErrorList {
//EmptyDirs have nothing to validate
}
if numVolumes != 1 {
allErrs = append(allErrs, errs.NewInvalid("", source))
allErrs = append(allErrs, errs.NewFieldInvalid("", source))
}
return allErrs
}
@ -88,25 +88,25 @@ func validatePorts(ports []api.Port) errs.ErrorList {
port := &ports[i] // so we can set default values
if len(port.Name) > 0 {
if len(port.Name) > 63 || !util.IsDNSLabel(port.Name) {
pErrs = append(pErrs, errs.NewInvalid("name", port.Name))
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name))
} else if allNames.Has(port.Name) {
pErrs = append(pErrs, errs.NewDuplicate("name", port.Name))
pErrs = append(pErrs, errs.NewFieldDuplicate("name", port.Name))
} else {
allNames.Insert(port.Name)
}
}
if port.ContainerPort == 0 {
pErrs = append(pErrs, errs.NewRequired("containerPort", port.ContainerPort))
pErrs = append(pErrs, errs.NewFieldRequired("containerPort", port.ContainerPort))
} else if !util.IsValidPortNum(port.ContainerPort) {
pErrs = append(pErrs, errs.NewInvalid("containerPort", port.ContainerPort))
pErrs = append(pErrs, errs.NewFieldInvalid("containerPort", port.ContainerPort))
}
if port.HostPort != 0 && !util.IsValidPortNum(port.HostPort) {
pErrs = append(pErrs, errs.NewInvalid("hostPort", port.HostPort))
pErrs = append(pErrs, errs.NewFieldInvalid("hostPort", port.HostPort))
}
if len(port.Protocol) == 0 {
port.Protocol = "TCP"
} else if !supportedPortProtocols.Has(strings.ToUpper(port.Protocol)) {
pErrs = append(pErrs, errs.NewNotSupported("protocol", port.Protocol))
pErrs = append(pErrs, errs.NewFieldNotSupported("protocol", port.Protocol))
}
allErrs = append(allErrs, pErrs.PrefixIndex(i)...)
}
@ -120,10 +120,10 @@ func validateEnv(vars []api.EnvVar) errs.ErrorList {
vErrs := errs.ErrorList{}
ev := &vars[i] // so we can set default values
if len(ev.Name) == 0 {
vErrs = append(vErrs, errs.NewRequired("name", ev.Name))
vErrs = append(vErrs, errs.NewFieldRequired("name", ev.Name))
}
if !util.IsCIdentifier(ev.Name) {
vErrs = append(vErrs, errs.NewInvalid("name", ev.Name))
vErrs = append(vErrs, errs.NewFieldInvalid("name", ev.Name))
}
allErrs = append(allErrs, vErrs.PrefixIndex(i)...)
}
@ -137,12 +137,12 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs
mErrs := errs.ErrorList{}
mnt := &mounts[i] // so we can set default values
if len(mnt.Name) == 0 {
mErrs = append(mErrs, errs.NewRequired("name", mnt.Name))
mErrs = append(mErrs, errs.NewFieldRequired("name", mnt.Name))
} else if !volumes.Has(mnt.Name) {
mErrs = append(mErrs, errs.NewNotFound("name", mnt.Name))
}
if len(mnt.MountPath) == 0 {
mErrs = append(mErrs, errs.NewRequired("mountPath", mnt.MountPath))
mErrs = append(mErrs, errs.NewFieldRequired("mountPath", mnt.MountPath))
}
allErrs = append(allErrs, mErrs.PrefixIndex(i)...)
}
@ -163,7 +163,7 @@ func AccumulateUniquePorts(containers []api.Container, accumulator map[int]bool,
continue
}
if accumulator[port] {
cErrs = append(cErrs, errs.NewDuplicate("Port", port))
cErrs = append(cErrs, errs.NewFieldDuplicate("Port", port))
} else {
accumulator[port] = true
}
@ -188,16 +188,16 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
cErrs := errs.ErrorList{}
ctr := &containers[i] // so we can set default values
if len(ctr.Name) == 0 {
cErrs = append(cErrs, errs.NewRequired("name", ctr.Name))
cErrs = append(cErrs, errs.NewFieldRequired("name", ctr.Name))
} else if !util.IsDNSLabel(ctr.Name) {
cErrs = append(cErrs, errs.NewInvalid("name", ctr.Name))
cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name))
} else if allNames.Has(ctr.Name) {
cErrs = append(cErrs, errs.NewDuplicate("name", ctr.Name))
cErrs = append(cErrs, errs.NewFieldDuplicate("name", ctr.Name))
} else {
allNames.Insert(ctr.Name)
}
if len(ctr.Image) == 0 {
cErrs = append(cErrs, errs.NewRequired("image", ctr.Image))
cErrs = append(cErrs, errs.NewFieldRequired("image", ctr.Image))
}
cErrs = append(cErrs, validatePorts(ctr.Ports).Prefix("ports")...)
cErrs = append(cErrs, validateEnv(ctr.Env).Prefix("env")...)
@ -224,9 +224,9 @@ func ValidateManifest(manifest *api.ContainerManifest) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(manifest.Version) == 0 {
allErrs = append(allErrs, errs.NewRequired("version", manifest.Version))
allErrs = append(allErrs, errs.NewFieldRequired("version", manifest.Version))
} else if !supportedManifestVersions.Has(strings.ToLower(manifest.Version)) {
allErrs = append(allErrs, errs.NewNotSupported("version", manifest.Version))
allErrs = append(allErrs, errs.NewFieldNotSupported("version", manifest.Version))
}
allVolumes, errs := validateVolumes(manifest.Volumes)
allErrs = append(allErrs, errs.Prefix("volumes")...)
@ -241,7 +241,7 @@ func ValidatePodState(podState *api.PodState) errs.ErrorList {
} else if podState.RestartPolicy.Type != api.RestartAlways &&
podState.RestartPolicy.Type != api.RestartOnFailure &&
podState.RestartPolicy.Type != api.RestartNever {
allErrs = append(allErrs, errs.NewNotSupported("restartPolicy.type", podState.RestartPolicy.Type))
allErrs = append(allErrs, errs.NewFieldNotSupported("restartPolicy.type", podState.RestartPolicy.Type))
}
return allErrs
@ -251,7 +251,7 @@ func ValidatePodState(podState *api.PodState) errs.ErrorList {
func ValidatePod(pod *api.Pod) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(pod.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", pod.ID))
allErrs = append(allErrs, errs.NewFieldRequired("id", pod.ID))
}
allErrs = append(allErrs, ValidatePodState(&pod.DesiredState).Prefix("desiredState")...)
return allErrs
@ -261,15 +261,15 @@ func ValidatePod(pod *api.Pod) errs.ErrorList {
func ValidateService(service *api.Service) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(service.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", service.ID))
allErrs = append(allErrs, errs.NewFieldRequired("id", service.ID))
} else if !util.IsDNS952Label(service.ID) {
allErrs = append(allErrs, errs.NewInvalid("id", service.ID))
allErrs = append(allErrs, errs.NewFieldInvalid("id", service.ID))
}
if !util.IsValidPortNum(service.Port) {
allErrs = append(allErrs, errs.NewInvalid("Service.Port", service.Port))
allErrs = append(allErrs, errs.NewFieldInvalid("Service.Port", service.Port))
}
if labels.Set(service.Selector).AsSelector().Empty() {
allErrs = append(allErrs, errs.NewRequired("selector", service.Selector))
allErrs = append(allErrs, errs.NewFieldRequired("selector", service.Selector))
}
return allErrs
}
@ -278,18 +278,18 @@ func ValidateService(service *api.Service) errs.ErrorList {
func ValidateReplicationController(controller *api.ReplicationController) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(controller.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", controller.ID))
allErrs = append(allErrs, errs.NewFieldRequired("id", controller.ID))
}
if labels.Set(controller.DesiredState.ReplicaSelector).AsSelector().Empty() {
allErrs = append(allErrs, errs.NewRequired("desiredState.replicaSelector", controller.DesiredState.ReplicaSelector))
allErrs = append(allErrs, errs.NewFieldRequired("desiredState.replicaSelector", controller.DesiredState.ReplicaSelector))
}
selector := labels.Set(controller.DesiredState.ReplicaSelector).AsSelector()
labels := labels.Set(controller.DesiredState.PodTemplate.Labels)
if !selector.Matches(labels) {
allErrs = append(allErrs, errs.NewInvalid("desiredState.podTemplate.labels", controller.DesiredState.PodTemplate))
allErrs = append(allErrs, errs.NewFieldInvalid("desiredState.podTemplate.labels", controller.DesiredState.PodTemplate))
}
if controller.DesiredState.Replicas < 0 {
allErrs = append(allErrs, errs.NewInvalid("desiredState.replicas", controller.DesiredState.Replicas))
allErrs = append(allErrs, errs.NewFieldInvalid("desiredState.replicas", controller.DesiredState.Replicas))
}
allErrs = append(allErrs, ValidateManifest(&controller.DesiredState.PodTemplate.DesiredState.Manifest).Prefix("desiredState.podTemplate.desiredState.manifest")...)
return allErrs

View File

@ -31,6 +31,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
@ -331,7 +332,7 @@ func TestGet(t *testing.T) {
func TestGetMissing(t *testing.T) {
storage := map[string]RESTStorage{}
simpleStorage := SimpleRESTStorage{
errors: map[string]error{"get": NewNotFoundErr("simple", "id")},
errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")},
}
storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version")
@ -371,7 +372,7 @@ func TestDeleteMissing(t *testing.T) {
storage := map[string]RESTStorage{}
ID := "id"
simpleStorage := SimpleRESTStorage{
errors: map[string]error{"delete": NewNotFoundErr("simple", ID)},
errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)},
}
storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version")
@ -421,7 +422,7 @@ func TestUpdateMissing(t *testing.T) {
storage := map[string]RESTStorage{}
ID := "id"
simpleStorage := SimpleRESTStorage{
errors: map[string]error{"update": NewNotFoundErr("simple", ID)},
errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)},
}
storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version")
@ -490,7 +491,7 @@ func TestCreateNotFound(t *testing.T) {
"simple": &SimpleRESTStorage{
// storage.Create can fail with not found error in theory.
// See https://github.com/GoogleCloudPlatform/kubernetes/pull/486#discussion_r15037092.
errors: map[string]error{"create": NewNotFoundErr("simple", "id")},
errors: map[string]error{"create": apierrs.NewNotFound("simple", "id")},
},
}, codec, "/prefix/version")
server := httptest.NewServer(handler)
@ -597,41 +598,10 @@ func expectApiStatus(t *testing.T, method, url string, data []byte, code int) *a
return &status
}
func TestErrorsToAPIStatus(t *testing.T) {
cases := map[error]api.Status{
NewAlreadyExistsErr("foo", "bar"): {
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: "already_exists",
Message: "foo \"bar\" already exists",
Details: &api.StatusDetails{
Kind: "foo",
ID: "bar",
},
},
NewConflictErr("foo", "bar", errors.New("failure")): {
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: "conflict",
Message: "foo \"bar\" cannot be updated: failure",
Details: &api.StatusDetails{
Kind: "foo",
ID: "bar",
},
},
}
for k, v := range cases {
actual := errToAPIStatus(k)
if !reflect.DeepEqual(actual, &v) {
t.Errorf("Expected %#v, Got %#v", v, actual)
}
}
}
func TestAsyncDelayReturnsError(t *testing.T) {
storage := SimpleRESTStorage{
injectedFunction: func(obj interface{}) (interface{}, error) {
return nil, NewAlreadyExistsErr("foo", "bar")
return nil, apierrs.NewAlreadyExists("foo", "bar")
},
}
handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version")
@ -649,7 +619,7 @@ func TestAsyncCreateError(t *testing.T) {
storage := SimpleRESTStorage{
injectedFunction: func(obj interface{}) (interface{}, error) {
<-ch
return nil, NewAlreadyExistsErr("foo", "bar")
return nil, apierrs.NewAlreadyExists("foo", "bar")
},
}
handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version")
@ -673,7 +643,7 @@ func TestAsyncCreateError(t *testing.T) {
time.Sleep(time.Millisecond)
finalStatus := expectApiStatus(t, "GET", fmt.Sprintf("%s/prefix/version/operations/%s?after=1", server.URL, status.Details.ID), []byte{}, http.StatusOK)
expectedErr := NewAlreadyExistsErr("foo", "bar")
expectedErr := apierrs.NewAlreadyExists("foo", "bar")
expectedStatus := &api.Status{
Status: api.StatusFailure,
Code: http.StatusConflict,

View File

@ -21,120 +21,19 @@ import (
"net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
)
// apiServerError is an error intended for consumption by a REST API server.
type apiServerError struct {
api.Status
}
// Error implements the Error interface.
func (e *apiServerError) Error() string {
return e.Status.Message
}
// NewNotFoundErr returns a new error which indicates that the resource of the kind and the name was not found.
func NewNotFoundErr(kind, name string) error {
return &apiServerError{api.Status{
Status: api.StatusFailure,
Code: http.StatusNotFound,
Reason: api.StatusReasonNotFound,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q not found", kind, name),
}}
}
// NewAlreadyExistsErr returns an error indicating the item requested exists by that identifier.
func NewAlreadyExistsErr(kind, name string) error {
return &apiServerError{api.Status{
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: api.StatusReasonAlreadyExists,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q already exists", kind, name),
}}
}
// NewConflictErr returns an error indicating the item can't be updated as provided.
func NewConflictErr(kind, name string, err error) error {
return &apiServerError{api.Status{
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: api.StatusReasonConflict,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
},
Message: fmt.Sprintf("%s %q cannot be updated: %s", kind, name, err),
}}
}
// NewInvalidErr returns an error indicating the item is invalid and cannot be processed.
func NewInvalidErr(kind, name string, errs errors.ErrorList) error {
causes := make([]api.StatusCause, 0, len(errs))
for i := range errs {
if err, ok := errs[i].(errors.ValidationError); ok {
causes = append(causes, api.StatusCause{
Type: api.CauseType(err.Type),
Message: err.Error(),
Field: err.Field,
})
}
}
return &apiServerError{api.Status{
Status: api.StatusFailure,
Code: 422, // RFC 4918
Reason: api.StatusReasonInvalid,
Details: &api.StatusDetails{
Kind: kind,
ID: name,
Causes: causes,
},
Message: fmt.Sprintf("%s %q is invalid: %s", kind, name, errs.ToError()),
}}
}
// IsNotFound returns true if the specified error was created by NewNotFoundErr.
func IsNotFound(err error) bool {
return reasonForError(err) == api.StatusReasonNotFound
}
// IsAlreadyExists determines if the err is an error which indicates that a specified resource already exists.
func IsAlreadyExists(err error) bool {
return reasonForError(err) == api.StatusReasonAlreadyExists
}
// IsConflict determines if the err is an error which indicates the provided update conflicts.
func IsConflict(err error) bool {
return reasonForError(err) == api.StatusReasonConflict
}
// IsInvalid determines if the err is an error which indicates the provided resource is not valid.
func IsInvalid(err error) bool {
return reasonForError(err) == api.StatusReasonInvalid
}
func reasonForError(err error) api.StatusReason {
switch t := err.(type) {
case *apiServerError:
return t.Status.Reason
}
return api.StatusReasonUnknown
// statusError is an object that can be converted into an api.Status
type statusError interface {
Status() api.Status
}
// errToAPIStatus converts an error to an api.Status object.
func errToAPIStatus(err error) *api.Status {
switch t := err.(type) {
case *apiServerError:
status := t.Status
case statusError:
status := t.Status()
status.Status = api.StatusFailure
//TODO: check for invalid responses
return &status

View File

@ -17,126 +17,50 @@ limitations under the License.
package apiserver
import (
"errors"
"fmt"
stderrs "errors"
"net/http"
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
)
func TestErrorNew(t *testing.T) {
err := NewAlreadyExistsErr("test", "1")
if !IsAlreadyExists(err) {
t.Errorf("expected to be already_exists")
}
if IsConflict(err) {
t.Errorf("expected to not be confict")
}
if IsNotFound(err) {
t.Errorf(fmt.Sprintf("expected to not be %s", api.StatusReasonNotFound))
}
if IsInvalid(err) {
t.Errorf("expected to not be invalid")
}
if !IsConflict(NewConflictErr("test", "2", errors.New("message"))) {
t.Errorf("expected to be conflict")
}
if !IsNotFound(NewNotFoundErr("test", "3")) {
t.Errorf("expected to be not found")
}
if !IsInvalid(NewInvalidErr("test", "2", nil)) {
t.Errorf("expected to be invalid")
}
}
func TestNewInvalidErr(t *testing.T) {
testCases := []struct {
Err apierrors.ValidationError
Details *api.StatusDetails
}{
{
apierrors.NewDuplicate("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueDuplicate,
Field: "field[0].name",
}},
},
},
{
apierrors.NewInvalid("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueInvalid,
Field: "field[0].name",
}},
},
},
{
apierrors.NewNotFound("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueNotFound,
Field: "field[0].name",
}},
},
},
{
apierrors.NewNotSupported("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueNotSupported,
Field: "field[0].name",
}},
},
},
{
apierrors.NewRequired("field[0].name", "bar"),
&api.StatusDetails{
Kind: "kind",
ID: "name",
Causes: []api.StatusCause{{
Type: api.CauseTypeFieldValueRequired,
Field: "field[0].name",
}},
},
},
}
for i := range testCases {
vErr, expected := testCases[i].Err, testCases[i].Details
expected.Causes[0].Message = vErr.Error()
err := NewInvalidErr("kind", "name", apierrors.ErrorList{vErr})
status := errToAPIStatus(err)
if status.Code != 422 || status.Reason != api.StatusReasonInvalid {
t.Errorf("unexpected status: %#v", status)
}
if !reflect.DeepEqual(expected, status.Details) {
t.Errorf("expected %#v, got %#v", expected, status.Details)
}
}
}
func Test_errToAPIStatus(t *testing.T) {
err := &apiServerError{}
err := errors.NewNotFound("foo", "bar")
status := errToAPIStatus(err)
if status.Reason != api.StatusReasonUnknown || status.Status != api.StatusFailure {
if status.Reason != api.StatusReasonNotFound || status.Status != api.StatusFailure {
t.Errorf("unexpected status object: %#v", status)
}
}
func Test_reasonForError(t *testing.T) {
if e, a := api.StatusReasonUnknown, reasonForError(nil); e != a {
t.Errorf("unexpected reason type: %#v", a)
func TestErrorsToAPIStatus(t *testing.T) {
cases := map[error]api.Status{
errors.NewAlreadyExists("foo", "bar"): {
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: "already_exists",
Message: "foo \"bar\" already exists",
Details: &api.StatusDetails{
Kind: "foo",
ID: "bar",
},
},
errors.NewConflict("foo", "bar", stderrs.New("failure")): {
Status: api.StatusFailure,
Code: http.StatusConflict,
Reason: "conflict",
Message: "foo \"bar\" cannot be updated: failure",
Details: &api.StatusDetails{
Kind: "foo",
ID: "bar",
},
},
}
for k, v := range cases {
actual := errToAPIStatus(k)
if !reflect.DeepEqual(actual, &v) {
t.Errorf("%s: Expected %#v, Got %#v", k, v, actual)
}
}
}

View File

@ -251,7 +251,7 @@ func filterInvalidPods(pods []kubelet.Pod, source string) (filtered []*kubelet.P
for i := range pods {
var errors []error
if names.Has(pods[i].Name) {
errors = append(errors, apierrs.NewDuplicate("Pod.Name", pods[i].Name))
errors = append(errors, apierrs.NewFieldDuplicate("name", pods[i].Name))
} else {
names.Insert(pods[i].Name)
}

View File

@ -24,7 +24,7 @@ import (
func ValidatePod(pod *Pod) (errors []error) {
if !util.IsDNSSubdomain(pod.Name) {
errors = append(errors, apierrs.NewInvalid("Pod.Name", pod.Name))
errors = append(errors, apierrs.NewFieldInvalid("name", pod.Name))
}
if errs := validation.ValidateManifest(&pod.Manifest); len(errs) != 0 {
errors = append(errors, errs...)

View File

@ -20,6 +20,7 @@ import (
"fmt"
"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"
)
@ -40,17 +41,17 @@ func NewBindingStorage(bindingRegistry Registry) *BindingStorage {
// List returns an error because bindings are write-only objects.
func (*BindingStorage) List(selector labels.Selector) (interface{}, error) {
return nil, apiserver.NewNotFoundErr("binding", "list")
return nil, errors.NewNotFound("binding", "list")
}
// Get returns an error because bindings are write-only objects.
func (*BindingStorage) Get(id string) (interface{}, error) {
return nil, apiserver.NewNotFoundErr("binding", id)
return nil, errors.NewNotFound("binding", id)
}
// Delete returns an error because bindings are write-only objects.
func (*BindingStorage) Delete(id string) (<-chan interface{}, error) {
return nil, apiserver.NewNotFoundErr("binding", id)
return nil, errors.NewNotFound("binding", id)
}
// New returns a new binding object fit for having data unmarshalled into it.

View File

@ -21,6 +21,7 @@ import (
"time"
"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"
@ -61,7 +62,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
// Pod Manifest ID should be assigned by the pod API
controller.DesiredState.PodTemplate.DesiredState.Manifest.ID = ""
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("replicationController", controller.ID, errs)
return nil, errors.NewInvalid("replicationController", controller.ID, errs)
}
controller.CreationTimestamp = util.Now()
@ -120,7 +121,7 @@ func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
return nil, fmt.Errorf("not a replication controller: %#v", obj)
}
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("replicationController", controller.ID, errs)
return nil, errors.NewInvalid("replicationController", controller.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {
err := rs.registry.UpdateController(*controller)

View File

@ -25,7 +25,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -280,7 +280,7 @@ func TestControllerStorageValidatesCreate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}
@ -310,7 +310,7 @@ func TestControllerStorageValidatesUpdate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}

View File

@ -21,7 +21,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
)
@ -45,13 +45,13 @@ func TestGetEndpoints(t *testing.T) {
func TestGetEndpointsMissingService(t *testing.T) {
registry := &registrytest.ServiceRegistry{
Err: apiserver.NewNotFoundErr("service", "foo"),
Err: errors.NewNotFound("service", "foo"),
}
storage := NewStorage(registry)
// returns service not found
_, err := storage.Get("foo")
if !apiserver.IsNotFound(err) || !reflect.DeepEqual(err, apiserver.NewNotFoundErr("service", "foo")) {
if !errors.IsNotFound(err) || !reflect.DeepEqual(err, errors.NewNotFound("service", "foo")) {
t.Errorf("expected NotFound error, got %#v", err)
}

View File

@ -20,7 +20,7 @@ import (
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/constraint"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -184,7 +184,7 @@ func (r *Registry) DeletePod(podID string) error {
podKey := makePodKey(podID)
err := r.ExtractObj(podKey, &pod, false)
if tools.IsEtcdNotFound(err) {
return apiserver.NewNotFoundErr("pod", podID)
return errors.NewNotFound("pod", podID)
}
if err != nil {
return err
@ -193,7 +193,7 @@ func (r *Registry) DeletePod(podID string) error {
// machine and attempt to put it somewhere.
err = r.Delete(podKey, true)
if tools.IsEtcdNotFound(err) {
return apiserver.NewNotFoundErr("pod", podID)
return errors.NewNotFound("pod", podID)
}
if err != nil {
return err
@ -249,7 +249,7 @@ func (r *Registry) GetController(controllerID string) (*api.ReplicationControlle
key := makeControllerKey(controllerID)
err := r.ExtractObj(key, &controller, false)
if tools.IsEtcdNotFound(err) {
return nil, apiserver.NewNotFoundErr("replicationController", controllerID)
return nil, errors.NewNotFound("replicationController", controllerID)
}
if err != nil {
return nil, err
@ -261,7 +261,7 @@ func (r *Registry) GetController(controllerID string) (*api.ReplicationControlle
func (r *Registry) CreateController(controller api.ReplicationController) error {
err := r.CreateObj(makeControllerKey(controller.ID), controller)
if tools.IsEtcdNodeExist(err) {
return apiserver.NewAlreadyExistsErr("replicationController", controller.ID)
return errors.NewAlreadyExists("replicationController", controller.ID)
}
return err
}
@ -276,7 +276,7 @@ func (r *Registry) DeleteController(controllerID string) error {
key := makeControllerKey(controllerID)
err := r.Delete(key, false)
if tools.IsEtcdNotFound(err) {
return apiserver.NewNotFoundErr("replicationController", controllerID)
return errors.NewNotFound("replicationController", controllerID)
}
return err
}
@ -296,7 +296,7 @@ func (r *Registry) ListServices() (*api.ServiceList, error) {
func (r *Registry) CreateService(svc api.Service) error {
err := r.CreateObj(makeServiceKey(svc.ID), svc)
if tools.IsEtcdNodeExist(err) {
return apiserver.NewAlreadyExistsErr("service", svc.ID)
return errors.NewAlreadyExists("service", svc.ID)
}
return err
}
@ -307,7 +307,7 @@ func (r *Registry) GetService(name string) (*api.Service, error) {
var svc api.Service
err := r.ExtractObj(key, &svc, false)
if tools.IsEtcdNotFound(err) {
return nil, apiserver.NewNotFoundErr("service", name)
return nil, errors.NewNotFound("service", name)
}
if err != nil {
return nil, err
@ -321,7 +321,7 @@ func (r *Registry) GetEndpoints(name string) (*api.Endpoints, error) {
var endpoints api.Endpoints
err := r.ExtractObj(key, &endpoints, false)
if tools.IsEtcdNotFound(err) {
return nil, apiserver.NewNotFoundErr("endpoints", name)
return nil, errors.NewNotFound("endpoints", name)
}
if err != nil {
return nil, err
@ -338,7 +338,7 @@ func (r *Registry) DeleteService(name string) error {
key := makeServiceKey(name)
err := r.Delete(key, true)
if tools.IsEtcdNotFound(err) {
return apiserver.NewNotFoundErr("service", name)
return errors.NewNotFound("service", name)
}
if err != nil {
return err

View File

@ -21,8 +21,8 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -627,7 +627,7 @@ func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
ID: "foo",
},
})
if !apiserver.IsAlreadyExists(err) {
if !errors.IsAlreadyExists(err) {
t.Errorf("expected already exists err, got %#v", err)
}
}
@ -716,7 +716,7 @@ func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
err := registry.CreateService(api.Service{
JSONBase: api.JSONBase{ID: "foo"},
})
if !apiserver.IsAlreadyExists(err) {
if !errors.IsAlreadyExists(err) {
t.Errorf("expected already exists err, got %#v", err)
}
}

View File

@ -23,6 +23,7 @@ import (
"time"
"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/client"
@ -70,7 +71,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
}
pod.DesiredState.Manifest.ID = pod.ID
if errs := validation.ValidatePod(pod); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("pod", pod.ID, errs)
return nil, errors.NewInvalid("pod", pod.ID, errs)
}
pod.CreationTimestamp = util.Now()
@ -137,7 +138,7 @@ func (rs RegistryStorage) New() interface{} {
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
pod := obj.(*api.Pod)
if errs := validation.ValidatePod(pod); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("pod", pod.ID, errs)
return nil, errors.NewInvalid("pod", pod.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {
if err := rs.registry.UpdatePod(*pod); err != nil {

View File

@ -23,7 +23,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
@ -337,7 +337,7 @@ func TestPodStorageValidatesCreate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}
@ -353,7 +353,7 @@ func TestPodStorageValidatesUpdate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}

View File

@ -23,6 +23,7 @@ import (
"strings"
"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/cloudprovider"
@ -51,7 +52,7 @@ func NewRegistryStorage(registry Registry, cloud cloudprovider.Interface, machin
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service)
if errs := validation.ValidateService(srv); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("service", srv.ID, errs)
return nil, errors.NewInvalid("service", srv.ID, errs)
}
srv.CreationTimestamp = util.Now()
@ -157,7 +158,7 @@ func GetServiceEnvironmentVariables(registry Registry, machine string) ([]api.En
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service)
if errs := validation.ValidateService(srv); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("service", srv.ID, errs)
return nil, errors.NewInvalid("service", srv.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {
// TODO: check to see if external load balancer status changed

View File

@ -21,6 +21,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
cloud "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -79,7 +80,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
@ -140,7 +141,7 @@ func TestServiceStorageValidatesUpdate(t *testing.T) {
if c != nil {
t.Errorf("Expected nil channel")
}
if !apiserver.IsInvalid(err) {
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}