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

View File

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

View File

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

View File

@ -31,6 +31,7 @@ import (
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "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/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version" "github.com/GoogleCloudPlatform/kubernetes/pkg/version"
@ -331,7 +332,7 @@ func TestGet(t *testing.T) {
func TestGetMissing(t *testing.T) { func TestGetMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]RESTStorage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"get": NewNotFoundErr("simple", "id")}, errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")},
} }
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version") handler := Handle(storage, codec, "/prefix/version")
@ -371,7 +372,7 @@ func TestDeleteMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]RESTStorage{}
ID := "id" ID := "id"
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"delete": NewNotFoundErr("simple", ID)}, errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)},
} }
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version") handler := Handle(storage, codec, "/prefix/version")
@ -421,7 +422,7 @@ func TestUpdateMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]RESTStorage{}
ID := "id" ID := "id"
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"update": NewNotFoundErr("simple", ID)}, errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)},
} }
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
handler := Handle(storage, codec, "/prefix/version") handler := Handle(storage, codec, "/prefix/version")
@ -490,7 +491,7 @@ func TestCreateNotFound(t *testing.T) {
"simple": &SimpleRESTStorage{ "simple": &SimpleRESTStorage{
// storage.Create can fail with not found error in theory. // storage.Create can fail with not found error in theory.
// See https://github.com/GoogleCloudPlatform/kubernetes/pull/486#discussion_r15037092. // 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") }, codec, "/prefix/version")
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
@ -597,41 +598,10 @@ func expectApiStatus(t *testing.T, method, url string, data []byte, code int) *a
return &status 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) { func TestAsyncDelayReturnsError(t *testing.T) {
storage := SimpleRESTStorage{ storage := SimpleRESTStorage{
injectedFunction: func(obj interface{}) (interface{}, error) { 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") handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version")
@ -649,7 +619,7 @@ func TestAsyncCreateError(t *testing.T) {
storage := SimpleRESTStorage{ storage := SimpleRESTStorage{
injectedFunction: func(obj interface{}) (interface{}, error) { injectedFunction: func(obj interface{}) (interface{}, error) {
<-ch <-ch
return nil, NewAlreadyExistsErr("foo", "bar") return nil, apierrs.NewAlreadyExists("foo", "bar")
}, },
} }
handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version") handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version")
@ -673,7 +643,7 @@ func TestAsyncCreateError(t *testing.T) {
time.Sleep(time.Millisecond) 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) 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{ expectedStatus := &api.Status{
Status: api.StatusFailure, Status: api.StatusFailure,
Code: http.StatusConflict, Code: http.StatusConflict,

View File

@ -21,120 +21,19 @@ import (
"net/http" "net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
) )
// apiServerError is an error intended for consumption by a REST API server. // statusError is an object that can be converted into an api.Status
type apiServerError struct { type statusError interface {
api.Status Status() 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
} }
// errToAPIStatus converts an error to an api.Status object. // errToAPIStatus converts an error to an api.Status object.
func errToAPIStatus(err error) *api.Status { func errToAPIStatus(err error) *api.Status {
switch t := err.(type) { switch t := err.(type) {
case *apiServerError: case statusError:
status := t.Status status := t.Status()
status.Status = api.StatusFailure status.Status = api.StatusFailure
//TODO: check for invalid responses //TODO: check for invalid responses
return &status return &status

View File

@ -17,126 +17,50 @@ limitations under the License.
package apiserver package apiserver
import ( import (
"errors" stderrs "errors"
"fmt" "net/http"
"reflect" "reflect"
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "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) { func Test_errToAPIStatus(t *testing.T) {
err := &apiServerError{} err := errors.NewNotFound("foo", "bar")
status := errToAPIStatus(err) 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) t.Errorf("unexpected status object: %#v", status)
} }
} }
func Test_reasonForError(t *testing.T) { func TestErrorsToAPIStatus(t *testing.T) {
if e, a := api.StatusReasonUnknown, reasonForError(nil); e != a { cases := map[error]api.Status{
t.Errorf("unexpected reason type: %#v", a) 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 { for i := range pods {
var errors []error var errors []error
if names.Has(pods[i].Name) { 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 { } else {
names.Insert(pods[i].Name) names.Insert(pods[i].Name)
} }

View File

@ -24,7 +24,7 @@ import (
func ValidatePod(pod *Pod) (errors []error) { func ValidatePod(pod *Pod) (errors []error) {
if !util.IsDNSSubdomain(pod.Name) { 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 { if errs := validation.ValidateManifest(&pod.Manifest); len(errs) != 0 {
errors = append(errors, errs...) errors = append(errors, errs...)

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "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. // List returns an error because bindings are write-only objects.
func (*BindingStorage) List(selector labels.Selector) (interface{}, error) { 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. // Get returns an error because bindings are write-only objects.
func (*BindingStorage) Get(id string) (interface{}, error) { 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. // Delete returns an error because bindings are write-only objects.
func (*BindingStorage) Delete(id string) (<-chan interface{}, error) { 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. // New returns a new binding object fit for having data unmarshalled into it.

View File

@ -21,6 +21,7 @@ import (
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "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/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "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 // Pod Manifest ID should be assigned by the pod API
controller.DesiredState.PodTemplate.DesiredState.Manifest.ID = "" controller.DesiredState.PodTemplate.DesiredState.Manifest.ID = ""
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 { 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() 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) return nil, fmt.Errorf("not a replication controller: %#v", obj)
} }
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 { 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) { return apiserver.MakeAsync(func() (interface{}, error) {
err := rs.registry.UpdateController(*controller) err := rs.registry.UpdateController(*controller)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,6 +23,7 @@ import (
"strings" "strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "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/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" "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) { func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service) srv := obj.(*api.Service)
if errs := validation.ValidateService(srv); len(errs) > 0 { 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() 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) { func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service) srv := obj.(*api.Service)
if errs := validation.ValidateService(srv); len(errs) > 0 { 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) { return apiserver.MakeAsync(func() (interface{}, error) {
// TODO: check to see if external load balancer status changed // TODO: check to see if external load balancer status changed

View File

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