From 682f2a5a795a4e3a4f76f23ceb03b818af0d69a5 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 3 Nov 2015 16:08:20 -0800 Subject: [PATCH 1/2] Stronger typing for validation ErrorList --- examples/examples_test.go | 5 +- pkg/api/errors/errors.go | 16 +++--- pkg/api/rest/update.go | 4 +- pkg/api/validation/schema.go | 15 +++-- pkg/api/validation/validation.go | 4 +- pkg/api/validation/validation_test.go | 43 +++++++------- .../extensions/validation/validation_test.go | 15 +++-- pkg/kubectl/cmd/log.go | 3 +- pkg/kubelet/config/config.go | 5 +- pkg/kubelet/config/http_test.go | 3 +- pkg/util/validation/errors.go | 57 +++++++++++++------ pkg/util/validation/errors_test.go | 30 +++++++++- 12 files changed, 122 insertions(+), 78 deletions(-) diff --git a/examples/examples_test.go b/examples/examples_test.go index f75f9d604e6..c8ae44e8463 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -33,12 +33,13 @@ import ( expvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" "k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/runtime" + utilvalidation "k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/yaml" schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api" schedulerapilatest "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest" ) -func validateObject(obj runtime.Object) (errors []error) { +func validateObject(obj runtime.Object) (errors utilvalidation.ErrorList) { switch t := obj.(type) { case *api.ReplicationController: if t.Namespace == "" { @@ -122,7 +123,7 @@ func validateObject(obj runtime.Object) (errors []error) { } errors = expvalidation.ValidateDaemonSet(t) default: - return []error{fmt.Errorf("no validation defined for %#v", obj)} + return utilvalidation.ErrorList{utilvalidation.NewInternalError("", fmt.Errorf("no validation defined for %#v", obj))} } return errors } diff --git a/pkg/api/errors/errors.go b/pkg/api/errors/errors.go index 0935ed88fb8..ea62742c3ef 100644 --- a/pkg/api/errors/errors.go +++ b/pkg/api/errors/errors.go @@ -24,7 +24,6 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" - utilerrors "k8s.io/kubernetes/pkg/util/errors" "k8s.io/kubernetes/pkg/util/validation" ) @@ -162,13 +161,12 @@ func NewConflict(kind, name string, err error) error { func NewInvalid(kind, name string, errs validation.ErrorList) error { causes := make([]unversioned.StatusCause, 0, len(errs)) for i := range errs { - if err, ok := errs[i].(*validation.Error); ok { - causes = append(causes, unversioned.StatusCause{ - Type: unversioned.CauseType(err.Type), - Message: err.ErrorBody(), - Field: err.Field, - }) - } + err := errs[i] + causes = append(causes, unversioned.StatusCause{ + Type: unversioned.CauseType(err.Type), + Message: err.ErrorBody(), + Field: err.Field, + }) } return &StatusError{unversioned.Status{ Status: unversioned.StatusFailure, @@ -179,7 +177,7 @@ func NewInvalid(kind, name string, errs validation.ErrorList) error { Name: name, Causes: causes, }, - Message: fmt.Sprintf("%s %q is invalid: %v", kind, name, utilerrors.NewAggregate(errs)), + Message: fmt.Sprintf("%s %q is invalid: %v", kind, name, errs.ToAggregate()), }} } diff --git a/pkg/api/rest/update.go b/pkg/api/rest/update.go index 7a2e9da1b0a..c8e9e30d784 100644 --- a/pkg/api/rest/update.go +++ b/pkg/api/rest/update.go @@ -57,11 +57,11 @@ func validateCommonFields(obj, old runtime.Object) utilvalidation.ErrorList { allErrs := utilvalidation.ErrorList{} objectMeta, err := api.ObjectMetaFor(obj) if err != nil { - return append(allErrs, errors.NewInternalError(err)) + return append(allErrs, utilvalidation.NewInternalError("metadata", err)) } oldObjectMeta, err := api.ObjectMetaFor(old) if err != nil { - return append(allErrs, errors.NewInternalError(err)) + return append(allErrs, utilvalidation.NewInternalError("metadata", err)) } allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta)...) diff --git a/pkg/api/validation/schema.go b/pkg/api/validation/schema.go index 57755cd64d6..24c1e26199f 100644 --- a/pkg/api/validation/schema.go +++ b/pkg/api/validation/schema.go @@ -27,7 +27,6 @@ import ( "github.com/golang/glog" apiutil "k8s.io/kubernetes/pkg/api/util" utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/yaml" ) @@ -67,11 +66,11 @@ func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) { return schema, nil } -// validateList unpack a list and validate every item in the list. +// validateList unpacks a list and validate every item in the list. // It return nil if every item is ok. // Otherwise it return an error list contain errors of every item. -func (s *SwaggerSchema) validateList(obj map[string]interface{}) validation.ErrorList { - allErrs := validation.ErrorList{} +func (s *SwaggerSchema) validateList(obj map[string]interface{}) []error { + allErrs := []error{} items, exists := obj["items"] if !exists { return append(allErrs, fmt.Errorf("no items field in %#v", obj)) @@ -160,8 +159,8 @@ func (s *SwaggerSchema) ValidateBytes(data []byte) error { return utilerrors.NewAggregate(allErrs) } -func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) validation.ErrorList { - allErrs := validation.ErrorList{} +func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) []error { + allErrs := []error{} models := s.api.Models model, ok := models.At(typeName) if !ok { @@ -215,7 +214,7 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName stri // This matches type name in the swagger spec, such as "v1.Binding". var versionRegexp = regexp.MustCompile(`^v.+\..*`) -func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) validation.ErrorList { +func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) []error { // TODO: caesarxuchao: because we have multiple group/versions and objects // may reference objects in other group, the commented out way of checking // if a filedType is a type defined by us is outdated. We use a hacky way @@ -229,7 +228,7 @@ func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType st // if strings.HasPrefix(fieldType, apiVersion) { return s.ValidateObject(value, fieldName, fieldType) } - allErrs := validation.ErrorList{} + allErrs := []error{} switch fieldType { case "string": // Be loose about what we accept for 'string' since we use IntOrString in a couple of places diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 3224e4ef0fb..47469208b9f 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -1480,7 +1480,7 @@ func ValidateNodeUpdate(node, oldNode *api.Node) validation.ErrorList { addresses := make(map[api.NodeAddress]bool) for _, address := range node.Status.Addresses { if _, ok := addresses[address]; ok { - allErrs = append(allErrs, fmt.Errorf("duplicate node addresses found")) + allErrs = append(allErrs, validation.NewFieldDuplicate("addresses", address)) } addresses[address] = true } @@ -1500,7 +1500,7 @@ func ValidateNodeUpdate(node, oldNode *api.Node) validation.ErrorList { // TODO: Add a 'real' error type for this error and provide print actual diffs. if !api.Semantic.DeepEqual(oldNode, node) { glog.V(4).Infof("Update failed validation %#v vs %#v", oldNode, node) - allErrs = append(allErrs, fmt.Errorf("update contains more than labels or capacity changes")) + allErrs = append(allErrs, validation.NewFieldForbidden("", "update contains more than labels or capacity changes")) } return allErrs diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 21c20ec0bbe..71b39eae611 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -28,7 +28,6 @@ import ( "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/capabilities" - utilerrors "k8s.io/kubernetes/pkg/util/errors" "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/validation" @@ -36,7 +35,7 @@ import ( func expectPrefix(t *testing.T, prefix string, errs validation.ErrorList) { for i := range errs { - if f, p := errs[i].(*validation.Error).Field, prefix; !strings.HasPrefix(f, p) { + if f, p := errs[i].Field, prefix; !strings.HasPrefix(f, p) { t.Errorf("expected prefix '%s' for field '%s' (%v)", p, f, errs[i]) } } @@ -150,7 +149,7 @@ func TestValidateLabels(t *testing.T) { if len(errs) != 1 { t.Errorf("case[%d] expected failure", i) } else { - detail := errs[0].(*validation.Error).Detail + detail := errs[0].Detail if detail != qualifiedNameErrorMsg { t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) } @@ -168,7 +167,7 @@ func TestValidateLabels(t *testing.T) { if len(errs) != 1 { t.Errorf("case[%d] expected failure", i) } else { - detail := errs[0].(*validation.Error).Detail + detail := errs[0].Detail if detail != labelValueErrorMsg { t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg) } @@ -215,7 +214,7 @@ func TestValidateAnnotations(t *testing.T) { if len(errs) != 1 { t.Errorf("case[%d] expected failure", i) } - detail := errs[0].(*validation.Error).Detail + detail := errs[0].Detail if detail != qualifiedNameErrorMsg { t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) } @@ -568,13 +567,13 @@ func TestValidateVolumes(t *testing.T) { continue } for i := range errs { - if errs[i].(*validation.Error).Type != v.T { + if errs[i].Type != v.T { t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) } - if errs[i].(*validation.Error).Field != v.F { + if errs[i].Field != v.F { t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) } - detail := errs[i].(*validation.Error).Detail + detail := errs[i].Detail if detail != v.D { t.Errorf("%s: expected error detail \"%s\", got \"%s\"", k, v.D, detail) } @@ -627,13 +626,13 @@ func TestValidatePorts(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - if errs[i].(*validation.Error).Type != v.T { + if errs[i].Type != v.T { t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) } - if errs[i].(*validation.Error).Field != v.F { + if errs[i].Field != v.F { t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) } - detail := errs[i].(*validation.Error).Detail + detail := errs[i].Detail if detail != v.D { t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail) } @@ -772,7 +771,7 @@ func TestValidateEnv(t *testing.T) { t.Errorf("expected failure for %s", tc.name) } else { for i := range errs { - str := errs[i].(*validation.Error).Error() + str := errs[i].Error() if str != "" && str != tc.expectedError { t.Errorf("%s: expected error detail either empty or %s, got %s", tc.name, tc.expectedError, str) } @@ -2108,7 +2107,7 @@ func TestValidateService(t *testing.T) { tc.tweakSvc(&svc) errs := ValidateService(&svc) if len(errs) != tc.numErrs { - t.Errorf("Unexpected error list for case %q: %v", tc.name, utilerrors.NewAggregate(errs)) + t.Errorf("Unexpected error list for case %q: %v", tc.name, errs.ToAggregate()) } } } @@ -2560,7 +2559,7 @@ func TestValidateReplicationController(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - field := errs[i].(*validation.Error).Field + field := errs[i].Field if !strings.HasPrefix(field, "spec.template.") && field != "metadata.name" && field != "metadata.namespace" && @@ -2676,7 +2675,7 @@ func TestValidateNode(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - field := errs[i].(*validation.Error).Field + field := errs[i].Field expectedFields := map[string]bool{ "metadata.name": true, "metadata.labels": true, @@ -2974,7 +2973,7 @@ func TestValidateServiceUpdate(t *testing.T) { tc.tweakSvc(&oldSvc, &newSvc) errs := ValidateServiceUpdate(&newSvc, &oldSvc) if len(errs) != tc.numErrs { - t.Errorf("Unexpected error list for case %q: %v", tc.name, utilerrors.NewAggregate(errs)) + t.Errorf("Unexpected error list for case %q: %v", tc.name, errs.ToAggregate()) } } } @@ -3008,7 +3007,7 @@ func TestValidateResourceNames(t *testing.T) { } else if len(err) == 0 && !item.success { t.Errorf("expected failure for input %q", item.input) for i := range err { - detail := err[i].(*validation.Error).Detail + detail := err[i].Detail if detail != "" && detail != qualifiedNameErrorMsg { t.Errorf("%d: expected error detail either empty or %s, got %s", k, qualifiedNameErrorMsg, detail) } @@ -3224,7 +3223,7 @@ func TestValidateLimitRange(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - detail := errs[i].(*validation.Error).Detail + detail := errs[i].Detail if detail != v.D { t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail) } @@ -3329,8 +3328,8 @@ func TestValidateResourceQuota(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - field := errs[i].(*validation.Error).Field - detail := errs[i].(*validation.Error).Detail + field := errs[i].Field + detail := errs[i].Detail if field != "metadata.name" && field != "metadata.namespace" && !api.IsStandardResourceName(field) { t.Errorf("%s: missing prefix for: %v", k, field) } @@ -3937,7 +3936,7 @@ func TestValidateEndpoints(t *testing.T) { } for k, v := range errorCases { - if errs := ValidateEndpoints(&v.endpoints); len(errs) == 0 || errs[0].(*validation.Error).Type != v.errorType || !strings.Contains(errs[0].(*validation.Error).Detail, v.errorDetail) { + if errs := ValidateEndpoints(&v.endpoints); len(errs) == 0 || errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs) } } @@ -4017,7 +4016,7 @@ func TestValidateSecurityContext(t *testing.T) { }, } for k, v := range errorCases { - if errs := ValidateSecurityContext(v.sc); len(errs) == 0 || errs[0].(*validation.Error).Type != v.errorType || errs[0].(*validation.Error).Detail != v.errorDetail { + if errs := ValidateSecurityContext(v.sc); len(errs) == 0 || errs[0].Type != v.errorType || errs[0].Detail != v.errorDetail { t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs) } } diff --git a/pkg/apis/extensions/validation/validation_test.go b/pkg/apis/extensions/validation/validation_test.go index 94d74de2fe7..497e88e88fc 100644 --- a/pkg/apis/extensions/validation/validation_test.go +++ b/pkg/apis/extensions/validation/validation_test.go @@ -24,7 +24,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/util/intstr" - "k8s.io/kubernetes/pkg/util/validation" ) func TestValidateHorizontalPodAutoscaler(t *testing.T) { @@ -675,7 +674,7 @@ func TestValidateDaemonSet(t *testing.T) { t.Errorf("expected failure for %s", k) } for i := range errs { - field := errs[i].(*validation.Error).Field + field := errs[i].Field if !strings.HasPrefix(field, "spec.template.") && field != "metadata.name" && field != "metadata.namespace" && @@ -918,9 +917,9 @@ func TestValidateJob(t *testing.T) { t.Errorf("expected failure for %s", k) } else { s := strings.Split(k, ":") - err := errs[0].(*validation.Error) + err := errs[0] if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %v, expected: %s", errs[0], k) + t.Errorf("unexpected error: %v, expected: %s", err, k) } } } @@ -1019,9 +1018,9 @@ func TestValidateIngress(t *testing.T) { t.Errorf("expected failure for %s", k) } else { s := strings.Split(k, ":") - err := errs[0].(*validation.Error) + err := errs[0] if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %v, expected: %s", errs[0], k) + t.Errorf("unexpected error: %v, expected: %s", err, k) } } } @@ -1111,9 +1110,9 @@ func TestValidateIngressStatusUpdate(t *testing.T) { t.Errorf("expected failure for %s", k) } else { s := strings.Split(k, ":") - err := errs[0].(*validation.Error) + err := errs[0] if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %v, expected: %s", errs[0], k) + t.Errorf("unexpected error: %v, expected: %s", err, k) } } } diff --git a/pkg/kubectl/cmd/log.go b/pkg/kubectl/cmd/log.go index 722b1f10166..430511d6b30 100644 --- a/pkg/kubectl/cmd/log.go +++ b/pkg/kubectl/cmd/log.go @@ -32,7 +32,6 @@ import ( cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/runtime" - kerrors "k8s.io/kubernetes/pkg/util/errors" ) const ( @@ -169,7 +168,7 @@ func (o LogsOptions) Validate() error { return errors.New("unexpected log options object") } if errs := validation.ValidatePodLogOptions(logOptions); len(errs) > 0 { - return kerrors.NewAggregate(errs) + return errs.ToAggregate() } return nil diff --git a/pkg/kubelet/config/config.go b/pkg/kubelet/config/config.go index ff0bd1a0459..737c6aa7425 100644 --- a/pkg/kubelet/config/config.go +++ b/pkg/kubelet/config/config.go @@ -29,7 +29,6 @@ import ( kubetypes "k8s.io/kubernetes/pkg/kubelet/types" kubeletutil "k8s.io/kubernetes/pkg/kubelet/util" "k8s.io/kubernetes/pkg/util/config" - utilerrors "k8s.io/kubernetes/pkg/util/errors" "k8s.io/kubernetes/pkg/util/sets" utilvalidation "k8s.io/kubernetes/pkg/util/validation" ) @@ -310,7 +309,7 @@ func (s *podStorage) seenSources(sources ...string) bool { func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventRecorder) (filtered []*api.Pod) { names := sets.String{} for i, pod := range pods { - var errlist []error + var errlist utilvalidation.ErrorList if errs := validation.ValidatePod(pod); len(errs) != 0 { errlist = append(errlist, errs...) // If validation fails, don't trust it any further - @@ -325,7 +324,7 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco } if len(errlist) > 0 { name := bestPodIdentString(pod) - err := utilerrors.NewAggregate(errlist) + err := errlist.ToAggregate() glog.Warningf("Pod[%d] (%s) from %s failed validation, ignoring: %v", i+1, name, source, err) recorder.Eventf(pod, kubecontainer.FailedValidation, "Error validating pod %s from %s, ignoring: %v", name, source, err) continue diff --git a/pkg/kubelet/config/http_test.go b/pkg/kubelet/config/http_test.go index 84115a4cc7f..f257bc3fc68 100644 --- a/pkg/kubelet/config/http_test.go +++ b/pkg/kubelet/config/http_test.go @@ -30,7 +30,6 @@ import ( kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" - utilerrors "k8s.io/kubernetes/pkg/util/errors" ) func TestURLErrorNotExistNoUpdate(t *testing.T) { @@ -286,7 +285,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { } for _, pod := range update.Pods { if errs := validation.ValidatePod(pod); len(errs) != 0 { - t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, pod, utilerrors.NewAggregate(errs)) + t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, pod, errs.ToAggregate()) } } } diff --git a/pkg/util/validation/errors.go b/pkg/util/validation/errors.go index 17d5e4630f4..56d39cf89b6 100644 --- a/pkg/util/validation/errors.go +++ b/pkg/util/validation/errors.go @@ -46,7 +46,7 @@ func (v *Error) Error() string { func (v *Error) ErrorBody() string { var s string switch v.Type { - case ErrorTypeRequired, ErrorTypeTooLong: + case ErrorTypeRequired, ErrorTypeTooLong, ErrorTypeInternal: s = spew.Sprintf("%s", v.Type) default: s = spew.Sprintf("%s '%+v'", v.Type, v.BadValue) @@ -89,6 +89,9 @@ const ( // This is similar to ErrorTypeInvalid, but the error will not include the // too-long value. See NewFieldTooLong. ErrorTypeTooLong ErrorType = "FieldValueTooLong" + // ErrorTypeInternal is used to report other errors that are not related + // to user input. + ErrorTypeInternal ErrorType = "InternalError" ) // String converts a ErrorType into its corresponding canonical error message. @@ -108,6 +111,8 @@ func (t ErrorType) String() string { return "forbidden" case ErrorTypeTooLong: return "too long" + case ErrorTypeInternal: + return "internal error" default: panic(fmt.Sprintf("unrecognized validation error: %q", t)) return "" @@ -166,24 +171,27 @@ func NewFieldTooLong(field string, value interface{}, maxLength int) *Error { return &Error{ErrorTypeTooLong, field, value, fmt.Sprintf("must have at most %d characters", maxLength)} } +// NewInternalError returns a *Error indicating "internal error". This is used +// to signal that an error was found that was not directly related to user +// input. The err argument must be non-nil. +func NewInternalError(field string, err error) *Error { + return &Error{ErrorTypeInternal, field, nil, err.Error()} +} + // ErrorList holds a set of errors. -type ErrorList []error +type ErrorList []*Error // Prefix adds a prefix to the Field of every Error in the list. // Returns the list for convenience. func (list ErrorList) Prefix(prefix string) ErrorList { for i := range list { - if err, ok := list[i].(*Error); ok { - if strings.HasPrefix(err.Field, "[") { - err.Field = prefix + err.Field - } else if len(err.Field) != 0 { - err.Field = prefix + "." + err.Field - } else { - err.Field = prefix - } - list[i] = err + err := list[i] + if strings.HasPrefix(err.Field, "[") { + err.Field = prefix + err.Field + } else if len(err.Field) != 0 { + err.Field = prefix + "." + err.Field } else { - panic(fmt.Sprintf("Programmer error: ErrorList holds non-Error: %#v", list[i])) + err.Field = prefix } } return list @@ -206,13 +214,30 @@ func NewErrorTypeMatcher(t ErrorType) utilerrors.Matcher { } } +// ToAggregate converts the ErrorList into an errors.Aggregate. +func (list ErrorList) ToAggregate() utilerrors.Aggregate { + errs := make([]error, len(list)) + for i := range list { + errs[i] = list[i] + } + return utilerrors.NewAggregate(errs) +} + +func fromAggregate(agg utilerrors.Aggregate) ErrorList { + errs := agg.Errors() + list := make(ErrorList, len(errs)) + for i := range errs { + list[i] = errs[i].(*Error) + } + return list +} + // Filter removes items from the ErrorList that match the provided fns. func (list ErrorList) Filter(fns ...utilerrors.Matcher) ErrorList { - err := utilerrors.FilterOut(utilerrors.NewAggregate(list), fns...) + err := utilerrors.FilterOut(list.ToAggregate(), fns...) if err == nil { return nil } - // FilterOut that takes an Aggregate returns an Aggregate - agg := err.(utilerrors.Aggregate) - return ErrorList(agg.Errors()) + // FilterOut takes an Aggregate and returns an Aggregate + return fromAggregate(err.(utilerrors.Aggregate)) } diff --git a/pkg/util/validation/errors_test.go b/pkg/util/validation/errors_test.go index 777c9abcb3e..d4fb1884295 100644 --- a/pkg/util/validation/errors_test.go +++ b/pkg/util/validation/errors_test.go @@ -17,6 +17,7 @@ limitations under the License. package validation import ( + "fmt" "strings" "testing" ) @@ -46,6 +47,10 @@ func TestMakeFuncs(t *testing.T) { func() *Error { return NewFieldRequired("f") }, ErrorTypeRequired, }, + { + func() *Error { return NewInternalError("f", fmt.Errorf("e")) }, + ErrorTypeInternal, + }, } for _, testCase := range testCases { @@ -93,6 +98,27 @@ func TestErrorUsefulMessage(t *testing.T) { } } +func TestToAggregate(t *testing.T) { + testCases := []ErrorList{ + nil, + {}, + {NewFieldInvalid("f", "v", "d")}, + {NewFieldInvalid("f", "v", "d"), NewInternalError("", fmt.Errorf("e"))}, + } + for i, tc := range testCases { + agg := tc.ToAggregate() + if len(tc) == 0 { + if agg != nil { + t.Errorf("[%d] Expected nil, got %#v", i, agg) + } + } else if agg == nil { + t.Errorf("[%d] Expected non-nil", i) + } else if len(tc) != len(agg.Errors()) { + t.Errorf("[%d] Expected %d, got %d", i, len(tc), len(agg.Errors())) + } + } +} + func TestErrListFilter(t *testing.T) { list := ErrorList{ NewFieldInvalid("test.field", "", ""), @@ -131,7 +157,7 @@ func TestErrListPrefix(t *testing.T) { if prefix == nil || len(prefix) != len(errList) { t.Errorf("Prefix should return self") } - if e, a := testCase.Expected, errList[0].(*Error).Field; e != a { + if e, a := testCase.Expected, errList[0].Field; e != a { t.Errorf("expected %s, got %s", e, a) } } @@ -161,7 +187,7 @@ func TestErrListPrefixIndex(t *testing.T) { if prefix == nil || len(prefix) != len(errList) { t.Errorf("PrefixIndex should return self") } - if e, a := testCase.Expected, errList[0].(*Error).Field; e != a { + if e, a := testCase.Expected, errList[0].Field; e != a { t.Errorf("expected %s, got %s", e, a) } } From ceee678b29278c946e0e065579f3e994893629a4 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 3 Nov 2015 16:17:48 -0800 Subject: [PATCH 2/2] Rename validation 'New' funcs --- pkg/api/errors/errors_test.go | 10 +- pkg/api/validation/events.go | 4 +- pkg/api/validation/validation.go | 374 +++++++++---------- pkg/apis/extensions/validation/validation.go | 98 ++--- pkg/kubectl/cmd/util/helpers_test.go | 4 +- pkg/kubelet/config/config.go | 2 +- pkg/labels/selector.go | 4 +- pkg/registry/pod/etcd/etcd.go | 4 +- pkg/registry/service/rest.go | 12 +- pkg/storage/util.go | 2 +- pkg/util/validation/errors.go | 44 +-- pkg/util/validation/errors_test.go | 36 +- 12 files changed, 297 insertions(+), 297 deletions(-) diff --git a/pkg/api/errors/errors_test.go b/pkg/api/errors/errors_test.go index 0f49524de01..182093f6f0e 100644 --- a/pkg/api/errors/errors_test.go +++ b/pkg/api/errors/errors_test.go @@ -92,7 +92,7 @@ func TestNewInvalid(t *testing.T) { Details *unversioned.StatusDetails }{ { - validation.NewFieldDuplicate("field[0].name", "bar"), + validation.NewDuplicateError("field[0].name", "bar"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", @@ -103,7 +103,7 @@ func TestNewInvalid(t *testing.T) { }, }, { - validation.NewFieldInvalid("field[0].name", "bar", "detail"), + validation.NewInvalidError("field[0].name", "bar", "detail"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", @@ -114,7 +114,7 @@ func TestNewInvalid(t *testing.T) { }, }, { - validation.NewFieldNotFound("field[0].name", "bar"), + validation.NewNotFoundError("field[0].name", "bar"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", @@ -125,7 +125,7 @@ func TestNewInvalid(t *testing.T) { }, }, { - validation.NewFieldNotSupported("field[0].name", "bar", nil), + validation.NewNotSupportedError("field[0].name", "bar", nil), &unversioned.StatusDetails{ Kind: "kind", Name: "name", @@ -136,7 +136,7 @@ func TestNewInvalid(t *testing.T) { }, }, { - validation.NewFieldRequired("field[0].name"), + validation.NewRequiredError("field[0].name"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", diff --git a/pkg/api/validation/events.go b/pkg/api/validation/events.go index e52340a791f..fef1e62dd1c 100644 --- a/pkg/api/validation/events.go +++ b/pkg/api/validation/events.go @@ -27,10 +27,10 @@ func ValidateEvent(event *api.Event) validation.ErrorList { // TODO: There is no namespace required for node. if event.InvolvedObject.Kind != "Node" && event.Namespace != event.InvolvedObject.Namespace { - allErrs = append(allErrs, validation.NewFieldInvalid("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) + allErrs = append(allErrs, validation.NewInvalidError("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) } if !validation.IsDNS1123Subdomain(event.Namespace) { - allErrs = append(allErrs, validation.NewFieldInvalid("namespace", event.Namespace, "")) + allErrs = append(allErrs, validation.NewInvalidError("namespace", event.Namespace, "")) } return allErrs } diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 47469208b9f..af9e85c96d2 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -64,7 +64,7 @@ const totalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB func ValidateLabelName(labelName, fieldName string) validation.ErrorList { allErrs := validation.ErrorList{} if !validation.IsQualifiedName(labelName) { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, labelName, qualifiedNameErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, labelName, qualifiedNameErrorMsg)) } return allErrs } @@ -75,7 +75,7 @@ func ValidateLabels(labels map[string]string, field string) validation.ErrorList for k, v := range labels { allErrs = append(allErrs, ValidateLabelName(k, field)...) if !validation.IsValidLabelValue(v) { - allErrs = append(allErrs, validation.NewFieldInvalid(field, v, labelValueErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(field, v, labelValueErrorMsg)) } } return allErrs @@ -87,12 +87,12 @@ func ValidateAnnotations(annotations map[string]string, field string) validation var totalSize int64 for k, v := range annotations { if !validation.IsQualifiedName(strings.ToLower(k)) { - allErrs = append(allErrs, validation.NewFieldInvalid(field, k, qualifiedNameErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(field, k, qualifiedNameErrorMsg)) } totalSize += (int64)(len(k)) + (int64)(len(v)) } if totalSize > (int64)(totalAnnotationSizeLimitB) { - allErrs = append(allErrs, validation.NewFieldTooLong(field, "", totalAnnotationSizeLimitB)) + allErrs = append(allErrs, validation.NewTooLongError(field, "", totalAnnotationSizeLimitB)) } return allErrs } @@ -220,7 +220,7 @@ func NameIsDNS952Label(name string, prefix bool) (bool, string) { func ValidatePositiveField(value int64, fieldName string) validation.ErrorList { allErrs := validation.ErrorList{} if value < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, value, isNegativeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, value, isNegativeErrorMsg)) } return allErrs } @@ -229,7 +229,7 @@ func ValidatePositiveField(value int64, fieldName string) validation.ErrorList { func ValidatePositiveQuantity(value resource.Quantity, fieldName string) validation.ErrorList { allErrs := validation.ErrorList{} if value.Cmp(resource.Quantity{}) < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, value.String(), isNegativeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, value.String(), isNegativeErrorMsg)) } return allErrs } @@ -237,7 +237,7 @@ func ValidatePositiveQuantity(value resource.Quantity, fieldName string) validat func ValidateImmutableField(new, old interface{}, fieldName string) validation.ErrorList { allErrs := validation.ErrorList{} if !api.Semantic.DeepEqual(old, new) { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, new, fieldImmutableErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, new, fieldImmutableErrorMsg)) } return allErrs } @@ -251,31 +251,31 @@ func ValidateObjectMeta(meta *api.ObjectMeta, requiresNamespace bool, nameFn Val if len(meta.GenerateName) != 0 { if ok, qualifier := nameFn(meta.GenerateName, true); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("generateName", meta.GenerateName, qualifier)) + allErrs = append(allErrs, validation.NewInvalidError("generateName", meta.GenerateName, qualifier)) } } // If the generated name validates, but the calculated value does not, it's a problem with generation, and we // report it here. This may confuse users, but indicates a programming bug and still must be validated. // If there are multiple fields out of which one is required then add a or as a separator if len(meta.Name) == 0 { - requiredErr := validation.NewFieldRequired("name") + requiredErr := validation.NewRequiredError("name") requiredErr.Detail = "name or generateName is required" allErrs = append(allErrs, requiredErr) } else { if ok, qualifier := nameFn(meta.Name, false); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("name", meta.Name, qualifier)) + allErrs = append(allErrs, validation.NewInvalidError("name", meta.Name, qualifier)) } } allErrs = append(allErrs, ValidatePositiveField(meta.Generation, "generation")...) if requiresNamespace { if len(meta.Namespace) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("namespace")) + allErrs = append(allErrs, validation.NewRequiredError("namespace")) } else if ok, _ := ValidateNamespaceName(meta.Namespace, false); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("namespace", meta.Namespace, DNS1123LabelErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("namespace", meta.Namespace, DNS1123LabelErrorMsg)) } } else { if len(meta.Namespace) != 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("namespace", meta.Namespace, "namespace is not allowed on this type")) + allErrs = append(allErrs, validation.NewInvalidError("namespace", meta.Namespace, "namespace is not allowed on this type")) } } allErrs = append(allErrs, ValidateLabels(meta.Labels, "labels")...) @@ -289,7 +289,7 @@ func ValidateObjectMetaUpdate(new, old *api.ObjectMeta) validation.ErrorList { allErrs := validation.ErrorList{} if !RepairMalformedUpdates && new.UID != old.UID { - allErrs = append(allErrs, validation.NewFieldInvalid("uid", new.UID, "field is immutable")) + allErrs = append(allErrs, validation.NewInvalidError("uid", new.UID, "field is immutable")) } // in the event it is left empty, set it, to allow clients more flexibility // TODO: remove the following code that repairs the update request when we retire the clients that modify the immutable fields. @@ -315,12 +315,12 @@ func ValidateObjectMetaUpdate(new, old *api.ObjectMeta) validation.ErrorList { // TODO: needs to check if new==nil && old !=nil after the repair logic is removed. if new.DeletionGracePeriodSeconds != nil && old.DeletionGracePeriodSeconds != nil && *new.DeletionGracePeriodSeconds != *old.DeletionGracePeriodSeconds { - allErrs = append(allErrs, validation.NewFieldInvalid("deletionGracePeriodSeconds", new.DeletionGracePeriodSeconds, "field is immutable; may only be changed via deletion")) + allErrs = append(allErrs, validation.NewInvalidError("deletionGracePeriodSeconds", new.DeletionGracePeriodSeconds, "field is immutable; may only be changed via deletion")) } // Reject updates that don't specify a resource version if new.ResourceVersion == "" { - allErrs = append(allErrs, validation.NewFieldInvalid("resourceVersion", new.ResourceVersion, "resourceVersion must be specified for an update")) + allErrs = append(allErrs, validation.NewInvalidError("resourceVersion", new.ResourceVersion, "resourceVersion must be specified for an update")) } allErrs = append(allErrs, ValidateImmutableField(new.Name, old.Name, "name")...) @@ -341,11 +341,11 @@ func validateVolumes(volumes []api.Volume) (sets.String, validation.ErrorList) { for i, vol := range volumes { el := validateSource(&vol.VolumeSource).Prefix("source") if len(vol.Name) == 0 { - el = append(el, validation.NewFieldRequired("name")) + el = append(el, validation.NewRequiredError("name")) } else if !validation.IsDNS1123Label(vol.Name) { - el = append(el, validation.NewFieldInvalid("name", vol.Name, DNS1123LabelErrorMsg)) + el = append(el, validation.NewInvalidError("name", vol.Name, DNS1123LabelErrorMsg)) } else if allNames.Has(vol.Name) { - el = append(el, validation.NewFieldDuplicate("name", vol.Name)) + el = append(el, validation.NewDuplicateError("name", vol.Name)) } if len(el) == 0 { allNames.Insert(vol.Name) @@ -424,7 +424,7 @@ func validateSource(source *api.VolumeSource) validation.ErrorList { allErrs = append(allErrs, validateFCVolumeSource(source.FC).Prefix("fc")...) } if numVolumes != 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("", source, "exactly 1 volume type is required")) + allErrs = append(allErrs, validation.NewInvalidError("", source, "exactly 1 volume type is required")) } return allErrs @@ -433,7 +433,7 @@ func validateSource(source *api.VolumeSource) validation.ErrorList { func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if hostPath.Path == "" { - allErrs = append(allErrs, validation.NewFieldRequired("path")) + allErrs = append(allErrs, validation.NewRequiredError("path")) } return allErrs } @@ -441,7 +441,7 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource) validation func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if gitRepo.Repository == "" { - allErrs = append(allErrs, validation.NewFieldRequired("repository")) + allErrs = append(allErrs, validation.NewRequiredError("repository")) } return allErrs } @@ -449,16 +449,16 @@ func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) validation.Er func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if iscsi.TargetPortal == "" { - allErrs = append(allErrs, validation.NewFieldRequired("targetPortal")) + allErrs = append(allErrs, validation.NewRequiredError("targetPortal")) } if iscsi.IQN == "" { - allErrs = append(allErrs, validation.NewFieldRequired("iqn")) + allErrs = append(allErrs, validation.NewRequiredError("iqn")) } if iscsi.FSType == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fsType")) + allErrs = append(allErrs, validation.NewRequiredError("fsType")) } if iscsi.Lun < 0 || iscsi.Lun > 255 { - allErrs = append(allErrs, validation.NewFieldInvalid("lun", iscsi.Lun, "")) + allErrs = append(allErrs, validation.NewInvalidError("lun", iscsi.Lun, "")) } return allErrs } @@ -466,17 +466,17 @@ func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource) validation.ErrorLis func validateFCVolumeSource(fc *api.FCVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if len(fc.TargetWWNs) < 1 { - allErrs = append(allErrs, validation.NewFieldRequired("targetWWNs")) + allErrs = append(allErrs, validation.NewRequiredError("targetWWNs")) } if fc.FSType == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fsType")) + allErrs = append(allErrs, validation.NewRequiredError("fsType")) } if fc.Lun == nil { - allErrs = append(allErrs, validation.NewFieldRequired("lun")) + allErrs = append(allErrs, validation.NewRequiredError("lun")) } else { if *fc.Lun < 0 || *fc.Lun > 255 { - allErrs = append(allErrs, validation.NewFieldInvalid("lun", fc.Lun, "")) + allErrs = append(allErrs, validation.NewInvalidError("lun", fc.Lun, "")) } } return allErrs @@ -485,13 +485,13 @@ func validateFCVolumeSource(fc *api.FCVolumeSource) validation.ErrorList { func validateGCEPersistentDiskVolumeSource(PD *api.GCEPersistentDiskVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if PD.PDName == "" { - allErrs = append(allErrs, validation.NewFieldRequired("pdName")) + allErrs = append(allErrs, validation.NewRequiredError("pdName")) } if PD.FSType == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fsType")) + allErrs = append(allErrs, validation.NewRequiredError("fsType")) } if PD.Partition < 0 || PD.Partition > 255 { - allErrs = append(allErrs, validation.NewFieldInvalid("partition", PD.Partition, pdPartitionErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("partition", PD.Partition, pdPartitionErrorMsg)) } return allErrs } @@ -499,13 +499,13 @@ func validateGCEPersistentDiskVolumeSource(PD *api.GCEPersistentDiskVolumeSource func validateAWSElasticBlockStoreVolumeSource(PD *api.AWSElasticBlockStoreVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if PD.VolumeID == "" { - allErrs = append(allErrs, validation.NewFieldRequired("volumeID")) + allErrs = append(allErrs, validation.NewRequiredError("volumeID")) } if PD.FSType == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fsType")) + allErrs = append(allErrs, validation.NewRequiredError("fsType")) } if PD.Partition < 0 || PD.Partition > 255 { - allErrs = append(allErrs, validation.NewFieldInvalid("partition", PD.Partition, pdPartitionErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("partition", PD.Partition, pdPartitionErrorMsg)) } return allErrs } @@ -513,7 +513,7 @@ func validateAWSElasticBlockStoreVolumeSource(PD *api.AWSElasticBlockStoreVolume func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if secretSource.SecretName == "" { - allErrs = append(allErrs, validation.NewFieldRequired("secretName")) + allErrs = append(allErrs, validation.NewRequiredError("secretName")) } return allErrs } @@ -521,7 +521,7 @@ func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) validation func validatePersistentClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if claim.ClaimName == "" { - allErrs = append(allErrs, validation.NewFieldRequired("claimName")) + allErrs = append(allErrs, validation.NewRequiredError("claimName")) } return allErrs } @@ -529,13 +529,13 @@ func validatePersistentClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeS func validateNFS(nfs *api.NFSVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if nfs.Server == "" { - allErrs = append(allErrs, validation.NewFieldRequired("server")) + allErrs = append(allErrs, validation.NewRequiredError("server")) } if nfs.Path == "" { - allErrs = append(allErrs, validation.NewFieldRequired("path")) + allErrs = append(allErrs, validation.NewRequiredError("path")) } if !path.IsAbs(nfs.Path) { - allErrs = append(allErrs, validation.NewFieldInvalid("path", nfs.Path, "must be an absolute path")) + allErrs = append(allErrs, validation.NewInvalidError("path", nfs.Path, "must be an absolute path")) } return allErrs } @@ -543,10 +543,10 @@ func validateNFS(nfs *api.NFSVolumeSource) validation.ErrorList { func validateGlusterfs(glusterfs *api.GlusterfsVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if glusterfs.EndpointsName == "" { - allErrs = append(allErrs, validation.NewFieldRequired("endpoints")) + allErrs = append(allErrs, validation.NewRequiredError("endpoints")) } if glusterfs.Path == "" { - allErrs = append(allErrs, validation.NewFieldRequired("path")) + allErrs = append(allErrs, validation.NewRequiredError("path")) } return allErrs } @@ -554,10 +554,10 @@ func validateGlusterfs(glusterfs *api.GlusterfsVolumeSource) validation.ErrorLis func validateFlocker(flocker *api.FlockerVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if flocker.DatasetName == "" { - allErrs = append(allErrs, validation.NewFieldRequired("datasetName")) + allErrs = append(allErrs, validation.NewRequiredError("datasetName")) } if strings.Contains(flocker.DatasetName, "/") { - allErrs = append(allErrs, validation.NewFieldInvalid("datasetName", flocker.DatasetName, "must not contain '/'")) + allErrs = append(allErrs, validation.NewInvalidError("datasetName", flocker.DatasetName, "must not contain '/'")) } return allErrs } @@ -568,19 +568,19 @@ func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSou allErrs := validation.ErrorList{} for _, downwardAPIVolumeFile := range downwardAPIVolume.Items { if len(downwardAPIVolumeFile.Path) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("path")) + allErrs = append(allErrs, validation.NewRequiredError("path")) } if path.IsAbs(downwardAPIVolumeFile.Path) { - allErrs = append(allErrs, validation.NewFieldForbidden("path", "must not be an absolute path")) + allErrs = append(allErrs, validation.NewForbiddenError("path", "must not be an absolute path")) } items := strings.Split(downwardAPIVolumeFile.Path, string(os.PathSeparator)) for _, item := range items { if item == ".." { - allErrs = append(allErrs, validation.NewFieldInvalid("path", downwardAPIVolumeFile.Path, "must not contain \"..\".")) + allErrs = append(allErrs, validation.NewInvalidError("path", downwardAPIVolumeFile.Path, "must not contain \"..\".")) } } if strings.HasPrefix(items[0], "..") && len(items[0]) > 2 { - allErrs = append(allErrs, validation.NewFieldInvalid("path", downwardAPIVolumeFile.Path, "must not start with \"..\".")) + allErrs = append(allErrs, validation.NewInvalidError("path", downwardAPIVolumeFile.Path, "must not start with \"..\".")) } allErrs = append(allErrs, validateObjectFieldSelector(&downwardAPIVolumeFile.FieldRef, &validDownwardAPIFieldPathExpressions).Prefix("FieldRef")...) } @@ -590,13 +590,13 @@ func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSou func validateRBD(rbd *api.RBDVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if len(rbd.CephMonitors) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("monitors")) + allErrs = append(allErrs, validation.NewRequiredError("monitors")) } if rbd.RBDImage == "" { - allErrs = append(allErrs, validation.NewFieldRequired("image")) + allErrs = append(allErrs, validation.NewRequiredError("image")) } if rbd.FSType == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fsType")) + allErrs = append(allErrs, validation.NewRequiredError("fsType")) } return allErrs } @@ -604,10 +604,10 @@ func validateRBD(rbd *api.RBDVolumeSource) validation.ErrorList { func validateCinderVolumeSource(cd *api.CinderVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if cd.VolumeID == "" { - allErrs = append(allErrs, validation.NewFieldRequired("volumeID")) + allErrs = append(allErrs, validation.NewRequiredError("volumeID")) } if cd.FSType == "" || (cd.FSType != "ext3" && cd.FSType != "ext4") { - allErrs = append(allErrs, validation.NewFieldRequired("fsType required and should be of type ext3 or ext4")) + allErrs = append(allErrs, validation.NewRequiredError("fsType required and should be of type ext3 or ext4")) } return allErrs } @@ -615,7 +615,7 @@ func validateCinderVolumeSource(cd *api.CinderVolumeSource) validation.ErrorList func validateCephFS(cephfs *api.CephFSVolumeSource) validation.ErrorList { allErrs := validation.ErrorList{} if len(cephfs.Monitors) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("monitors")) + allErrs = append(allErrs, validation.NewRequiredError("monitors")) } return allErrs } @@ -629,21 +629,21 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) validation.ErrorList { allErrs = append(allErrs, ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName).Prefix("metadata")...) if len(pv.Spec.AccessModes) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("persistentVolume.AccessModes")) + allErrs = append(allErrs, validation.NewRequiredError("persistentVolume.AccessModes")) } for _, mode := range pv.Spec.AccessModes { if mode != api.ReadWriteOnce && mode != api.ReadOnlyMany && mode != api.ReadWriteMany { - allErrs = append(allErrs, validation.NewFieldInvalid("persistentVolume.Spec.AccessModes", mode, fmt.Sprintf("only %s, %s, and %s are valid", api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany))) + allErrs = append(allErrs, validation.NewInvalidError("persistentVolume.Spec.AccessModes", mode, fmt.Sprintf("only %s, %s, and %s are valid", api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany))) } } if len(pv.Spec.Capacity) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("persistentVolume.Capacity")) + allErrs = append(allErrs, validation.NewRequiredError("persistentVolume.Capacity")) } if _, ok := pv.Spec.Capacity[api.ResourceStorage]; !ok || len(pv.Spec.Capacity) > 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("", pv.Spec.Capacity, fmt.Sprintf("only %s is expected", api.ResourceStorage))) + allErrs = append(allErrs, validation.NewInvalidError("", pv.Spec.Capacity, fmt.Sprintf("only %s is expected", api.ResourceStorage))) } for _, qty := range pv.Spec.Capacity { @@ -696,7 +696,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) validation.ErrorList { allErrs = append(allErrs, validateFCVolumeSource(pv.Spec.FC).Prefix("fc")...) } if numVolumes != 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("", pv.Spec.PersistentVolumeSource, "exactly 1 volume type is required")) + allErrs = append(allErrs, validation.NewInvalidError("", pv.Spec.PersistentVolumeSource, "exactly 1 volume type is required")) } return allErrs } @@ -716,7 +716,7 @@ func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *api.PersistentVolume) va allErrs := validation.ErrorList{} allErrs = append(allErrs, ValidateObjectMetaUpdate(&newPv.ObjectMeta, &oldPv.ObjectMeta).Prefix("metadata")...) if newPv.ResourceVersion == "" { - allErrs = append(allErrs, validation.NewFieldRequired("resourceVersion")) + allErrs = append(allErrs, validation.NewRequiredError("resourceVersion")) } newPv.Spec = oldPv.Spec return allErrs @@ -725,15 +725,15 @@ func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *api.PersistentVolume) va func ValidatePersistentVolumeClaim(pvc *api.PersistentVolumeClaim) validation.ErrorList { allErrs := ValidateObjectMeta(&pvc.ObjectMeta, true, ValidatePersistentVolumeName) if len(pvc.Spec.AccessModes) == 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("persistentVolumeClaim.Spec.AccessModes", pvc.Spec.AccessModes, "at least 1 PersistentVolumeAccessMode is required")) + allErrs = append(allErrs, validation.NewInvalidError("persistentVolumeClaim.Spec.AccessModes", pvc.Spec.AccessModes, "at least 1 PersistentVolumeAccessMode is required")) } for _, mode := range pvc.Spec.AccessModes { if mode != api.ReadWriteOnce && mode != api.ReadOnlyMany && mode != api.ReadWriteMany { - allErrs = append(allErrs, validation.NewFieldInvalid("persistentVolumeClaim.Spec.AccessModes", mode, fmt.Sprintf("only %s, %s, and %s are valid", api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany))) + allErrs = append(allErrs, validation.NewInvalidError("persistentVolumeClaim.Spec.AccessModes", mode, fmt.Sprintf("only %s, %s, and %s are valid", api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany))) } } if _, ok := pvc.Spec.Resources.Requests[api.ResourceStorage]; !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("persistentVolumeClaim.Spec.Resources.Requests", pvc.Spec.Resources.Requests, "No Storage size specified")) + allErrs = append(allErrs, validation.NewInvalidError("persistentVolumeClaim.Spec.Resources.Requests", pvc.Spec.Resources.Requests, "No Storage size specified")) } return allErrs } @@ -749,10 +749,10 @@ func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *api.PersistentVol allErrs := validation.ErrorList{} allErrs = append(allErrs, ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta).Prefix("metadata")...) if newPvc.ResourceVersion == "" { - allErrs = append(allErrs, validation.NewFieldRequired("resourceVersion")) + allErrs = append(allErrs, validation.NewRequiredError("resourceVersion")) } if len(newPvc.Spec.AccessModes) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("persistentVolume.AccessModes")) + allErrs = append(allErrs, validation.NewRequiredError("persistentVolume.AccessModes")) } for _, qty := range newPvc.Status.Capacity { allErrs = append(allErrs, validateBasicResource(qty)...) @@ -771,25 +771,25 @@ func validatePorts(ports []api.ContainerPort) validation.ErrorList { pErrs := validation.ErrorList{} if len(port.Name) > 0 { if !validation.IsValidPortName(port.Name) { - pErrs = append(pErrs, validation.NewFieldInvalid("name", port.Name, PortNameErrorMsg)) + pErrs = append(pErrs, validation.NewInvalidError("name", port.Name, PortNameErrorMsg)) } else if allNames.Has(port.Name) { - pErrs = append(pErrs, validation.NewFieldDuplicate("name", port.Name)) + pErrs = append(pErrs, validation.NewDuplicateError("name", port.Name)) } else { allNames.Insert(port.Name) } } if port.ContainerPort == 0 { - pErrs = append(pErrs, validation.NewFieldInvalid("containerPort", port.ContainerPort, PortRangeErrorMsg)) + pErrs = append(pErrs, validation.NewInvalidError("containerPort", port.ContainerPort, PortRangeErrorMsg)) } else if !validation.IsValidPortNum(port.ContainerPort) { - pErrs = append(pErrs, validation.NewFieldInvalid("containerPort", port.ContainerPort, PortRangeErrorMsg)) + pErrs = append(pErrs, validation.NewInvalidError("containerPort", port.ContainerPort, PortRangeErrorMsg)) } if port.HostPort != 0 && !validation.IsValidPortNum(port.HostPort) { - pErrs = append(pErrs, validation.NewFieldInvalid("hostPort", port.HostPort, PortRangeErrorMsg)) + pErrs = append(pErrs, validation.NewInvalidError("hostPort", port.HostPort, PortRangeErrorMsg)) } if len(port.Protocol) == 0 { - pErrs = append(pErrs, validation.NewFieldRequired("protocol")) + pErrs = append(pErrs, validation.NewRequiredError("protocol")) } else if !supportedPortProtocols.Has(string(port.Protocol)) { - pErrs = append(pErrs, validation.NewFieldNotSupported("protocol", port.Protocol, supportedPortProtocols.List())) + pErrs = append(pErrs, validation.NewNotSupportedError("protocol", port.Protocol, supportedPortProtocols.List())) } allErrs = append(allErrs, pErrs.PrefixIndex(i)...) } @@ -802,9 +802,9 @@ func validateEnv(vars []api.EnvVar) validation.ErrorList { for i, ev := range vars { vErrs := validation.ErrorList{} if len(ev.Name) == 0 { - vErrs = append(vErrs, validation.NewFieldRequired("name")) + vErrs = append(vErrs, validation.NewRequiredError("name")) } else if !validation.IsCIdentifier(ev.Name) { - vErrs = append(vErrs, validation.NewFieldInvalid("name", ev.Name, cIdentifierErrorMsg)) + vErrs = append(vErrs, validation.NewInvalidError("name", ev.Name, cIdentifierErrorMsg)) } vErrs = append(vErrs, validateEnvVarValueFrom(ev).Prefix("valueFrom")...) allErrs = append(allErrs, vErrs.PrefixIndex(i)...) @@ -830,7 +830,7 @@ func validateEnvVarValueFrom(ev api.EnvVar) validation.ErrorList { } if ev.Value != "" && numSources != 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("", "", "sources cannot be specified when value is not empty")) + allErrs = append(allErrs, validation.NewInvalidError("", "", "sources cannot be specified when value is not empty")) } return allErrs @@ -840,15 +840,15 @@ func validateObjectFieldSelector(fs *api.ObjectFieldSelector, expressions *sets. allErrs := validation.ErrorList{} if fs.APIVersion == "" { - allErrs = append(allErrs, validation.NewFieldRequired("apiVersion")) + allErrs = append(allErrs, validation.NewRequiredError("apiVersion")) } else if fs.FieldPath == "" { - allErrs = append(allErrs, validation.NewFieldRequired("fieldPath")) + allErrs = append(allErrs, validation.NewRequiredError("fieldPath")) } else { internalFieldPath, _, err := api.Scheme.ConvertFieldLabel(fs.APIVersion, "Pod", fs.FieldPath, "") if err != nil { - allErrs = append(allErrs, validation.NewFieldInvalid("fieldPath", fs.FieldPath, "error converting fieldPath")) + allErrs = append(allErrs, validation.NewInvalidError("fieldPath", fs.FieldPath, "error converting fieldPath")) } else if !expressions.Has(internalFieldPath) { - allErrs = append(allErrs, validation.NewFieldNotSupported("fieldPath", internalFieldPath, expressions.List())) + allErrs = append(allErrs, validation.NewNotSupportedError("fieldPath", internalFieldPath, expressions.List())) } } @@ -861,12 +861,12 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes sets.String) validat for i, mnt := range mounts { mErrs := validation.ErrorList{} if len(mnt.Name) == 0 { - mErrs = append(mErrs, validation.NewFieldRequired("name")) + mErrs = append(mErrs, validation.NewRequiredError("name")) } else if !volumes.Has(mnt.Name) { - mErrs = append(mErrs, validation.NewFieldNotFound("name", mnt.Name)) + mErrs = append(mErrs, validation.NewNotFoundError("name", mnt.Name)) } if len(mnt.MountPath) == 0 { - mErrs = append(mErrs, validation.NewFieldRequired("mountPath")) + mErrs = append(mErrs, validation.NewRequiredError("mountPath")) } allErrs = append(allErrs, mErrs.PrefixIndex(i)...) } @@ -902,7 +902,7 @@ func AccumulateUniqueHostPorts(containers []api.Container, accumulator *sets.Str } str := fmt.Sprintf("%d/%s", port, ctr.Ports[pi].Protocol) if accumulator.Has(str) { - cErrs = append(cErrs, validation.NewFieldDuplicate("port", str)) + cErrs = append(cErrs, validation.NewDuplicateError("port", str)) } else { accumulator.Insert(str) } @@ -922,7 +922,7 @@ func checkHostPortConflicts(containers []api.Container) validation.ErrorList { func validateExecAction(exec *api.ExecAction) validation.ErrorList { allErrors := validation.ErrorList{} if len(exec.Command) == 0 { - allErrors = append(allErrors, validation.NewFieldRequired("command")) + allErrors = append(allErrors, validation.NewRequiredError("command")) } return allErrors } @@ -930,16 +930,16 @@ func validateExecAction(exec *api.ExecAction) validation.ErrorList { func validateHTTPGetAction(http *api.HTTPGetAction) validation.ErrorList { allErrors := validation.ErrorList{} if len(http.Path) == 0 { - allErrors = append(allErrors, validation.NewFieldRequired("path")) + allErrors = append(allErrors, validation.NewRequiredError("path")) } if http.Port.Type == intstr.Int && !validation.IsValidPortNum(http.Port.IntVal) { - allErrors = append(allErrors, validation.NewFieldInvalid("port", http.Port, PortRangeErrorMsg)) + allErrors = append(allErrors, validation.NewInvalidError("port", http.Port, PortRangeErrorMsg)) } else if http.Port.Type == intstr.String && !validation.IsValidPortName(http.Port.StrVal) { - allErrors = append(allErrors, validation.NewFieldInvalid("port", http.Port.StrVal, PortNameErrorMsg)) + allErrors = append(allErrors, validation.NewInvalidError("port", http.Port.StrVal, PortNameErrorMsg)) } supportedSchemes := sets.NewString(string(api.URISchemeHTTP), string(api.URISchemeHTTPS)) if !supportedSchemes.Has(string(http.Scheme)) { - allErrors = append(allErrors, validation.NewFieldInvalid("scheme", http.Scheme, fmt.Sprintf("must be one of %v", supportedSchemes.List()))) + allErrors = append(allErrors, validation.NewInvalidError("scheme", http.Scheme, fmt.Sprintf("must be one of %v", supportedSchemes.List()))) } return allErrors } @@ -947,9 +947,9 @@ func validateHTTPGetAction(http *api.HTTPGetAction) validation.ErrorList { func validateTCPSocketAction(tcp *api.TCPSocketAction) validation.ErrorList { allErrors := validation.ErrorList{} if tcp.Port.Type == intstr.Int && !validation.IsValidPortNum(tcp.Port.IntVal) { - allErrors = append(allErrors, validation.NewFieldInvalid("port", tcp.Port, PortRangeErrorMsg)) + allErrors = append(allErrors, validation.NewInvalidError("port", tcp.Port, PortRangeErrorMsg)) } else if tcp.Port.Type == intstr.String && !validation.IsValidPortName(tcp.Port.StrVal) { - allErrors = append(allErrors, validation.NewFieldInvalid("port", tcp.Port.StrVal, PortNameErrorMsg)) + allErrors = append(allErrors, validation.NewInvalidError("port", tcp.Port.StrVal, PortNameErrorMsg)) } return allErrors } @@ -970,7 +970,7 @@ func validateHandler(handler *api.Handler) validation.ErrorList { allErrors = append(allErrors, validateTCPSocketAction(handler.TCPSocket).Prefix("tcpSocket")...) } if numHandlers != 1 { - allErrors = append(allErrors, validation.NewFieldInvalid("", handler, "exactly 1 handler type is required")) + allErrors = append(allErrors, validation.NewInvalidError("", handler, "exactly 1 handler type is required")) } return allErrors } @@ -993,10 +993,10 @@ func validatePullPolicy(ctr *api.Container) validation.ErrorList { case api.PullAlways, api.PullIfNotPresent, api.PullNever: break case "": - allErrors = append(allErrors, validation.NewFieldRequired("")) + allErrors = append(allErrors, validation.NewRequiredError("")) default: validValues := []string{string(api.PullAlways), string(api.PullIfNotPresent), string(api.PullNever)} - allErrors = append(allErrors, validation.NewFieldNotSupported("", ctr.ImagePullPolicy, validValues)) + allErrors = append(allErrors, validation.NewNotSupportedError("", ctr.ImagePullPolicy, validValues)) } return allErrors @@ -1006,23 +1006,23 @@ func validateContainers(containers []api.Container, volumes sets.String) validat allErrs := validation.ErrorList{} if len(containers) == 0 { - return append(allErrs, validation.NewFieldRequired("")) + return append(allErrs, validation.NewRequiredError("")) } allNames := sets.String{} for i, ctr := range containers { cErrs := validation.ErrorList{} if len(ctr.Name) == 0 { - cErrs = append(cErrs, validation.NewFieldRequired("name")) + cErrs = append(cErrs, validation.NewRequiredError("name")) } else if !validation.IsDNS1123Label(ctr.Name) { - cErrs = append(cErrs, validation.NewFieldInvalid("name", ctr.Name, DNS1123LabelErrorMsg)) + cErrs = append(cErrs, validation.NewInvalidError("name", ctr.Name, DNS1123LabelErrorMsg)) } else if allNames.Has(ctr.Name) { - cErrs = append(cErrs, validation.NewFieldDuplicate("name", ctr.Name)) + cErrs = append(cErrs, validation.NewDuplicateError("name", ctr.Name)) } else { allNames.Insert(ctr.Name) } if len(ctr.Image) == 0 { - cErrs = append(cErrs, validation.NewFieldRequired("image")) + cErrs = append(cErrs, validation.NewRequiredError("image")) } if ctr.Lifecycle != nil { cErrs = append(cErrs, validateLifecycle(ctr.Lifecycle).Prefix("lifecycle")...) @@ -1030,7 +1030,7 @@ func validateContainers(containers []api.Container, volumes sets.String) validat cErrs = append(cErrs, validateProbe(ctr.LivenessProbe).Prefix("livenessProbe")...) // Liveness-specific validation if ctr.LivenessProbe != nil && ctr.LivenessProbe.SuccessThreshold != 1 { - allErrs = append(allErrs, validation.NewFieldForbidden("livenessProbe.successThreshold", "must be 1")) + allErrs = append(allErrs, validation.NewForbiddenError("livenessProbe.successThreshold", "must be 1")) } cErrs = append(cErrs, validateProbe(ctr.ReadinessProbe).Prefix("readinessProbe")...) @@ -1054,10 +1054,10 @@ func validateRestartPolicy(restartPolicy *api.RestartPolicy) validation.ErrorLis case api.RestartPolicyAlways, api.RestartPolicyOnFailure, api.RestartPolicyNever: break case "": - allErrors = append(allErrors, validation.NewFieldRequired("")) + allErrors = append(allErrors, validation.NewRequiredError("")) default: validValues := []string{string(api.RestartPolicyAlways), string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)} - allErrors = append(allErrors, validation.NewFieldNotSupported("", *restartPolicy, validValues)) + allErrors = append(allErrors, validation.NewNotSupportedError("", *restartPolicy, validValues)) } return allErrors @@ -1069,10 +1069,10 @@ func validateDNSPolicy(dnsPolicy *api.DNSPolicy) validation.ErrorList { case api.DNSClusterFirst, api.DNSDefault: break case "": - allErrors = append(allErrors, validation.NewFieldRequired("")) + allErrors = append(allErrors, validation.NewRequiredError("")) default: validValues := []string{string(api.DNSClusterFirst), string(api.DNSDefault)} - allErrors = append(allErrors, validation.NewFieldNotSupported("", dnsPolicy, validValues)) + allErrors = append(allErrors, validation.NewNotSupportedError("", dnsPolicy, validValues)) } return allErrors } @@ -1083,7 +1083,7 @@ func validateHostNetwork(hostNetwork bool, containers []api.Container) validatio for _, container := range containers { for _, port := range container.Ports { if port.HostPort != port.ContainerPort { - allErrors = append(allErrors, validation.NewFieldInvalid("containerPort", port.ContainerPort, "containerPort must match hostPort if hostNetwork is set to true")) + allErrors = append(allErrors, validation.NewInvalidError("containerPort", port.ContainerPort, "containerPort must match hostPort if hostNetwork is set to true")) } } } @@ -1099,7 +1099,7 @@ func validateImagePullSecrets(imagePullSecrets []api.LocalObjectReference) valid strippedRef := api.LocalObjectReference{Name: currPullSecret.Name} if !reflect.DeepEqual(strippedRef, currPullSecret) { - allErrors = append(allErrors, validation.NewFieldInvalid(fmt.Sprintf("[%d]", i), currPullSecret, "only name may be set")) + allErrors = append(allErrors, validation.NewInvalidError(fmt.Sprintf("[%d]", i), currPullSecret, "only name may be set")) } } return allErrors @@ -1131,13 +1131,13 @@ func ValidatePodSpec(spec *api.PodSpec) validation.ErrorList { allErrs = append(allErrs, validateImagePullSecrets(spec.ImagePullSecrets).Prefix("imagePullSecrets")...) if len(spec.ServiceAccountName) > 0 { if ok, msg := ValidateServiceAccountName(spec.ServiceAccountName, false); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("serviceAccountName", spec.ServiceAccountName, msg)) + allErrs = append(allErrs, validation.NewInvalidError("serviceAccountName", spec.ServiceAccountName, msg)) } } if spec.ActiveDeadlineSeconds != nil { if *spec.ActiveDeadlineSeconds <= 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("activeDeadlineSeconds", spec.ActiveDeadlineSeconds, "activeDeadlineSeconds must be a positive integer greater than 0")) + allErrs = append(allErrs, validation.NewInvalidError("activeDeadlineSeconds", spec.ActiveDeadlineSeconds, "activeDeadlineSeconds must be a positive integer greater than 0")) } } return allErrs @@ -1163,7 +1163,7 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) validation.ErrorList { if len(newPod.Spec.Containers) != len(oldPod.Spec.Containers) { //TODO: Pinpoint the specific container that causes the invalid error after we have strategic merge diff - allErrs = append(allErrs, validation.NewFieldInvalid("spec.containers", "content of spec.containers is not printed out, please refer to the \"details\"", "may not add or remove containers")) + allErrs = append(allErrs, validation.NewInvalidError("spec.containers", "content of spec.containers is not printed out, please refer to the \"details\"", "may not add or remove containers")) return allErrs } pod := *newPod @@ -1176,7 +1176,7 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) validation.ErrorList { pod.Spec.Containers = newContainers if !api.Semantic.DeepEqual(pod.Spec, oldPod.Spec) { //TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff - allErrs = append(allErrs, validation.NewFieldInvalid("spec", "content of spec is not printed out, please refer to the \"details\"", "may not update fields other than container.image")) + allErrs = append(allErrs, validation.NewInvalidError("spec", "content of spec is not printed out, please refer to the \"details\"", "may not update fields other than container.image")) } newPod.Status = oldPod.Status @@ -1192,7 +1192,7 @@ func ValidatePodStatusUpdate(newPod, oldPod *api.Pod) validation.ErrorList { // TODO: allow change when bindings are properly decoupled from pods if newPod.Spec.NodeName != oldPod.Spec.NodeName { - allErrs = append(allErrs, validation.NewFieldInvalid("status.nodeName", newPod.Spec.NodeName, "pod nodename cannot be changed directly")) + allErrs = append(allErrs, validation.NewInvalidError("status.nodeName", newPod.Spec.NodeName, "pod nodename cannot be changed directly")) } // For status update we ignore changes to pod spec. @@ -1228,13 +1228,13 @@ func ValidateService(service *api.Service) validation.ErrorList { allErrs = append(allErrs, ValidateObjectMeta(&service.ObjectMeta, true, ValidateServiceName).Prefix("metadata")...) if len(service.Spec.Ports) == 0 && service.Spec.ClusterIP != api.ClusterIPNone { - allErrs = append(allErrs, validation.NewFieldRequired("spec.ports")) + allErrs = append(allErrs, validation.NewRequiredError("spec.ports")) } if service.Spec.Type == api.ServiceTypeLoadBalancer { for ix := range service.Spec.Ports { port := &service.Spec.Ports[ix] if port.Port == 10250 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.ports[%d].port", ix), port.Port, "can not expose port 10250 externally since it is used by kubelet")) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.ports[%d].port", ix), port.Port, "can not expose port 10250 externally since it is used by kubelet")) } } } @@ -1248,34 +1248,34 @@ func ValidateService(service *api.Service) validation.ErrorList { } if service.Spec.SessionAffinity == "" { - allErrs = append(allErrs, validation.NewFieldRequired("spec.sessionAffinity")) + allErrs = append(allErrs, validation.NewRequiredError("spec.sessionAffinity")) } else if !supportedSessionAffinityType.Has(string(service.Spec.SessionAffinity)) { - allErrs = append(allErrs, validation.NewFieldNotSupported("spec.sessionAffinity", service.Spec.SessionAffinity, supportedSessionAffinityType.List())) + allErrs = append(allErrs, validation.NewNotSupportedError("spec.sessionAffinity", service.Spec.SessionAffinity, supportedSessionAffinityType.List())) } if api.IsServiceIPSet(service) { if ip := net.ParseIP(service.Spec.ClusterIP); ip == nil { - allErrs = append(allErrs, validation.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, "clusterIP should be empty, 'None', or a valid IP address")) + allErrs = append(allErrs, validation.NewInvalidError("spec.clusterIP", service.Spec.ClusterIP, "clusterIP should be empty, 'None', or a valid IP address")) } } for _, ip := range service.Spec.ExternalIPs { if ip == "0.0.0.0" { - allErrs = append(allErrs, validation.NewFieldInvalid("spec.externalIPs", ip, "is not an IP address")) + allErrs = append(allErrs, validation.NewInvalidError("spec.externalIPs", ip, "is not an IP address")) } allErrs = append(allErrs, validateIpIsNotLinkLocalOrLoopback(ip, "spec.externalIPs")...) } if service.Spec.Type == "" { - allErrs = append(allErrs, validation.NewFieldRequired("spec.type")) + allErrs = append(allErrs, validation.NewRequiredError("spec.type")) } else if !supportedServiceType.Has(string(service.Spec.Type)) { - allErrs = append(allErrs, validation.NewFieldNotSupported("spec.type", service.Spec.Type, supportedServiceType.List())) + allErrs = append(allErrs, validation.NewNotSupportedError("spec.type", service.Spec.Type, supportedServiceType.List())) } if service.Spec.Type == api.ServiceTypeLoadBalancer { for i := range service.Spec.Ports { if service.Spec.Ports[i].Protocol != api.ProtocolTCP { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.ports[%d].protocol", i), service.Spec.Ports[i].Protocol, "cannot create an external load balancer with non-TCP ports")) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.ports[%d].protocol", i), service.Spec.Ports[i].Protocol, "cannot create an external load balancer with non-TCP ports")) } } } @@ -1283,7 +1283,7 @@ func ValidateService(service *api.Service) validation.ErrorList { if service.Spec.Type == api.ServiceTypeClusterIP { for i := range service.Spec.Ports { if service.Spec.Ports[i].NodePort != 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.ports[%d].nodePort", i), service.Spec.Ports[i].NodePort, "cannot specify a node port with services of type ClusterIP")) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.ports[%d].nodePort", i), service.Spec.Ports[i].NodePort, "cannot specify a node port with services of type ClusterIP")) } } } @@ -1300,7 +1300,7 @@ func ValidateService(service *api.Service) validation.ErrorList { key.NodePort = port.NodePort _, found := nodePorts[key] if found { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.ports[%d].nodePort", i), port.NodePort, "duplicate nodePort specified")) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.ports[%d].nodePort", i), port.NodePort, "duplicate nodePort specified")) } nodePorts[key] = true } @@ -1312,32 +1312,32 @@ func validateServicePort(sp *api.ServicePort, requireName bool, allNames *sets.S allErrs := validation.ErrorList{} if requireName && sp.Name == "" { - allErrs = append(allErrs, validation.NewFieldRequired("name")) + allErrs = append(allErrs, validation.NewRequiredError("name")) } else if sp.Name != "" { if !validation.IsDNS1123Label(sp.Name) { - allErrs = append(allErrs, validation.NewFieldInvalid("name", sp.Name, DNS1123LabelErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("name", sp.Name, DNS1123LabelErrorMsg)) } else if allNames.Has(sp.Name) { - allErrs = append(allErrs, validation.NewFieldDuplicate("name", sp.Name)) + allErrs = append(allErrs, validation.NewDuplicateError("name", sp.Name)) } else { allNames.Insert(sp.Name) } } if !validation.IsValidPortNum(sp.Port) { - allErrs = append(allErrs, validation.NewFieldInvalid("port", sp.Port, PortRangeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("port", sp.Port, PortRangeErrorMsg)) } if len(sp.Protocol) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("protocol")) + allErrs = append(allErrs, validation.NewRequiredError("protocol")) } else if !supportedPortProtocols.Has(string(sp.Protocol)) { - allErrs = append(allErrs, validation.NewFieldNotSupported("protocol", sp.Protocol, supportedPortProtocols.List())) + allErrs = append(allErrs, validation.NewNotSupportedError("protocol", sp.Protocol, supportedPortProtocols.List())) } if sp.TargetPort.Type == intstr.Int && !validation.IsValidPortNum(sp.TargetPort.IntVal) { - allErrs = append(allErrs, validation.NewFieldInvalid("targetPort", sp.TargetPort, PortRangeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("targetPort", sp.TargetPort, PortRangeErrorMsg)) } if sp.TargetPort.Type == intstr.String && !validation.IsValidPortName(sp.TargetPort.StrVal) { - allErrs = append(allErrs, validation.NewFieldInvalid("targetPort", sp.TargetPort, PortNameErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("targetPort", sp.TargetPort, PortNameErrorMsg)) } return allErrs @@ -1386,7 +1386,7 @@ func ValidateNonEmptySelector(selectorMap map[string]string, fieldName string) v allErrs := validation.ErrorList{} selector := labels.Set(selectorMap).AsSelector() if selector.Empty() { - allErrs = append(allErrs, validation.NewFieldRequired(fieldName)) + allErrs = append(allErrs, validation.NewRequiredError(fieldName)) } return allErrs } @@ -1395,14 +1395,14 @@ func ValidateNonEmptySelector(selectorMap map[string]string, fieldName string) v func ValidatePodTemplateSpecForRC(template *api.PodTemplateSpec, selectorMap map[string]string, replicas int, fieldName string) validation.ErrorList { allErrs := validation.ErrorList{} if template == nil { - allErrs = append(allErrs, validation.NewFieldRequired(fieldName)) + allErrs = append(allErrs, validation.NewRequiredError(fieldName)) } else { selector := labels.Set(selectorMap).AsSelector() if !selector.Empty() { // Verify that the RC selector matches the labels in template. labels := labels.Set(template.Labels) if !selector.Matches(labels) { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName+".metadata.labels", template.Labels, "selector does not match labels in "+fieldName)) + allErrs = append(allErrs, validation.NewInvalidError(fieldName+".metadata.labels", template.Labels, "selector does not match labels in "+fieldName)) } } allErrs = append(allErrs, ValidatePodTemplateSpec(template).Prefix(fieldName)...) @@ -1411,7 +1411,7 @@ func ValidatePodTemplateSpecForRC(template *api.PodTemplateSpec, selectorMap map } // RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). if template.Spec.RestartPolicy != api.RestartPolicyAlways { - allErrs = append(allErrs, validation.NewFieldNotSupported(fieldName+".spec.restartPolicy", template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) + allErrs = append(allErrs, validation.NewNotSupportedError(fieldName+".spec.restartPolicy", template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } } return allErrs @@ -1441,7 +1441,7 @@ func ValidateReadOnlyPersistentDisks(volumes []api.Volume) validation.ErrorList for _, vol := range volumes { if vol.GCEPersistentDisk != nil { if vol.GCEPersistentDisk.ReadOnly == false { - allErrs = append(allErrs, validation.NewFieldInvalid("GCEPersistentDisk.ReadOnly", false, "ReadOnly must be true for replicated pods > 1, as GCE PD can only be mounted on multiple machines if it is read-only.")) + allErrs = append(allErrs, validation.NewInvalidError("GCEPersistentDisk.ReadOnly", false, "ReadOnly must be true for replicated pods > 1, as GCE PD can only be mounted on multiple machines if it is read-only.")) } } // TODO: What to do for AWS? It doesn't support replicas @@ -1458,7 +1458,7 @@ func ValidateNode(node *api.Node) validation.ErrorList { // external ID is required. if len(node.Spec.ExternalID) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("spec.ExternalID")) + allErrs = append(allErrs, validation.NewRequiredError("spec.ExternalID")) } // TODO(rjnagal): Ignore PodCIDR till its completely implemented. @@ -1473,14 +1473,14 @@ func ValidateNodeUpdate(node, oldNode *api.Node) validation.ErrorList { // TODO: Enable the code once we have better api object.status update model. Currently, // anyone can update node status. // if !api.Semantic.DeepEqual(node.Status, api.NodeStatus{}) { - // allErrs = append(allErrs, validation.NewFieldInvalid("status", node.Status, "status must be empty")) + // allErrs = append(allErrs, validation.NewInvalidError("status", node.Status, "status must be empty")) // } // Validte no duplicate addresses in node status. addresses := make(map[api.NodeAddress]bool) for _, address := range node.Status.Addresses { if _, ok := addresses[address]; ok { - allErrs = append(allErrs, validation.NewFieldDuplicate("addresses", address)) + allErrs = append(allErrs, validation.NewDuplicateError("addresses", address)) } addresses[address] = true } @@ -1500,7 +1500,7 @@ func ValidateNodeUpdate(node, oldNode *api.Node) validation.ErrorList { // TODO: Add a 'real' error type for this error and provide print actual diffs. if !api.Semantic.DeepEqual(oldNode, node) { glog.V(4).Infof("Update failed validation %#v vs %#v", oldNode, node) - allErrs = append(allErrs, validation.NewFieldForbidden("", "update contains more than labels or capacity changes")) + allErrs = append(allErrs, validation.NewForbiddenError("", "update contains more than labels or capacity changes")) } return allErrs @@ -1511,12 +1511,12 @@ func ValidateNodeUpdate(node, oldNode *api.Node) validation.ErrorList { func validateResourceName(value string, field string) validation.ErrorList { allErrs := validation.ErrorList{} if !validation.IsQualifiedName(value) { - return append(allErrs, validation.NewFieldInvalid(field, value, "resource typename: "+qualifiedNameErrorMsg)) + return append(allErrs, validation.NewInvalidError(field, value, "resource typename: "+qualifiedNameErrorMsg)) } if len(strings.Split(value, "/")) == 1 { if !api.IsStandardResourceName(value) { - return append(allErrs, validation.NewFieldInvalid(field, value, "is neither a standard resource type nor is fully qualified")) + return append(allErrs, validation.NewInvalidError(field, value, "is neither a standard resource type nor is fully qualified")) } } @@ -1534,7 +1534,7 @@ func ValidateLimitRange(limitRange *api.LimitRange) validation.ErrorList { limit := limitRange.Spec.Limits[i] _, found := limitTypeSet[limit.Type] if found { - allErrs = append(allErrs, validation.NewFieldDuplicate(fmt.Sprintf("spec.limits[%d].type", i), limit.Type)) + allErrs = append(allErrs, validation.NewDuplicateError(fmt.Sprintf("spec.limits[%d].type", i), limit.Type)) } limitTypeSet[limit.Type] = true @@ -1558,10 +1558,10 @@ func ValidateLimitRange(limitRange *api.LimitRange) validation.ErrorList { if limit.Type == api.LimitTypePod { if len(limit.Default) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("spec.limits[%d].default", limit.Default, "Default is not supported when limit type is Pod")) + allErrs = append(allErrs, validation.NewInvalidError("spec.limits[%d].default", limit.Default, "Default is not supported when limit type is Pod")) } if len(limit.DefaultRequest) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("spec.limits[%d].defaultRequest", limit.DefaultRequest, "DefaultRequest is not supported when limit type is Pod")) + allErrs = append(allErrs, validation.NewInvalidError("spec.limits[%d].defaultRequest", limit.DefaultRequest, "DefaultRequest is not supported when limit type is Pod")) } } else { for k, q := range limit.Default { @@ -1590,30 +1590,30 @@ func ValidateLimitRange(limitRange *api.LimitRange) validation.ErrorList { maxRatio, maxRatioFound := maxLimitRequestRatios[k] if minQuantityFound && maxQuantityFound && minQuantity.Cmp(maxQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].min[%s]", i, k), minQuantity, fmt.Sprintf("min value %s is greater than max value %s", minQuantity.String(), maxQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].min[%s]", i, k), minQuantity, fmt.Sprintf("min value %s is greater than max value %s", minQuantity.String(), maxQuantity.String()))) } if defaultRequestQuantityFound && minQuantityFound && minQuantity.Cmp(defaultRequestQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("min value %s is greater than default request value %s", minQuantity.String(), defaultRequestQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("min value %s is greater than default request value %s", minQuantity.String(), defaultRequestQuantity.String()))) } if defaultRequestQuantityFound && maxQuantityFound && defaultRequestQuantity.Cmp(maxQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("default request value %s is greater than max value %s", defaultRequestQuantity.String(), maxQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("default request value %s is greater than max value %s", defaultRequestQuantity.String(), maxQuantity.String()))) } if defaultRequestQuantityFound && defaultQuantityFound && defaultRequestQuantity.Cmp(defaultQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("default request value %s is greater than default limit value %s", defaultRequestQuantity.String(), defaultQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].defaultRequest[%s]", i, k), defaultRequestQuantity, fmt.Sprintf("default request value %s is greater than default limit value %s", defaultRequestQuantity.String(), defaultQuantity.String()))) } if defaultQuantityFound && minQuantityFound && minQuantity.Cmp(defaultQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].default[%s]", i, k), minQuantity, fmt.Sprintf("min value %s is greater than default value %s", minQuantity.String(), defaultQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].default[%s]", i, k), minQuantity, fmt.Sprintf("min value %s is greater than default value %s", minQuantity.String(), defaultQuantity.String()))) } if defaultQuantityFound && maxQuantityFound && defaultQuantity.Cmp(maxQuantity) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].default[%s]", i, k), maxQuantity, fmt.Sprintf("default value %s is greater than max value %s", defaultQuantity.String(), maxQuantity.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].default[%s]", i, k), maxQuantity, fmt.Sprintf("default value %s is greater than max value %s", defaultQuantity.String(), maxQuantity.String()))) } if maxRatioFound && maxRatio.Cmp(*resource.NewQuantity(1, resource.DecimalSI)) < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].maxLimitRequestRatio[%s]", i, k), maxRatio, fmt.Sprintf("maxLimitRequestRatio %s is less than 1", maxRatio.String()))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].maxLimitRequestRatio[%s]", i, k), maxRatio, fmt.Sprintf("maxLimitRequestRatio %s is less than 1", maxRatio.String()))) } if maxRatioFound && minQuantityFound && maxQuantityFound { maxRatioValue := float64(maxRatio.Value()) @@ -1626,7 +1626,7 @@ func ValidateLimitRange(limitRange *api.LimitRange) validation.ErrorList { } maxRatioLimit := float64(maxQuantityValue) / float64(minQuantityValue) if maxRatioValue > maxRatioLimit { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("spec.limits[%d].maxLimitRequestRatio[%s]", i, k), maxRatio, fmt.Sprintf("maxLimitRequestRatio %s is greater than max/min = %f", maxRatio.String(), maxRatioLimit))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("spec.limits[%d].maxLimitRequestRatio[%s]", i, k), maxRatio, fmt.Sprintf("maxLimitRequestRatio %s is greater than max/min = %f", maxRatio.String(), maxRatioLimit))) } } } @@ -1668,14 +1668,14 @@ func ValidateSecret(secret *api.Secret) validation.ErrorList { totalSize := 0 for key, value := range secret.Data { if !IsSecretKey(key) { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, fmt.Sprintf("must have at most %d characters and match regex %s", validation.DNS1123SubdomainMaxLength, SecretKeyFmt))) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("data[%s]", key), key, fmt.Sprintf("must have at most %d characters and match regex %s", validation.DNS1123SubdomainMaxLength, SecretKeyFmt))) } totalSize += len(value) } if totalSize > api.MaxSecretSize { - allErrs = append(allErrs, validation.NewFieldForbidden("data", "Maximum secret size exceeded")) + allErrs = append(allErrs, validation.NewForbiddenError("data", "Maximum secret size exceeded")) } switch secret.Type { @@ -1683,20 +1683,20 @@ func ValidateSecret(secret *api.Secret) validation.ErrorList { // Only require Annotations[kubernetes.io/service-account.name] // Additional fields (like Annotations[kubernetes.io/service-account.uid] and Data[token]) might be contributed later by a controller loop if value := secret.Annotations[api.ServiceAccountNameKey]; len(value) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired(fmt.Sprintf("metadata.annotations[%s]", api.ServiceAccountNameKey))) + allErrs = append(allErrs, validation.NewRequiredError(fmt.Sprintf("metadata.annotations[%s]", api.ServiceAccountNameKey))) } case api.SecretTypeOpaque, "": // no-op case api.SecretTypeDockercfg: dockercfgBytes, exists := secret.Data[api.DockerConfigKey] if !exists { - allErrs = append(allErrs, validation.NewFieldRequired(fmt.Sprintf("data[%s]", api.DockerConfigKey))) + allErrs = append(allErrs, validation.NewRequiredError(fmt.Sprintf("data[%s]", api.DockerConfigKey))) break } // make sure that the content is well-formed json. if err := json.Unmarshal(dockercfgBytes, &map[string]interface{}{}); err != nil { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("data[%s]", api.DockerConfigKey), "", err.Error())) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("data[%s]", api.DockerConfigKey), "", err.Error())) } default: @@ -1723,7 +1723,7 @@ func ValidateSecretUpdate(newSecret, oldSecret *api.Secret) validation.ErrorList func validateBasicResource(quantity resource.Quantity) validation.ErrorList { if quantity.Value() < 0 { - return validation.ErrorList{validation.NewFieldInvalid("", quantity.Value(), "must be a valid resource quantity")} + return validation.ErrorList{validation.NewInvalidError("", quantity.Value(), "must be a valid resource quantity")} } return validation.ErrorList{} } @@ -1749,7 +1749,7 @@ func ValidateResourceRequirements(requirements *api.ResourceRequirements) valida limitValue = quantity.MilliValue() } if limitValue < requestValue { - allErrs = append(allErrs, validation.NewFieldInvalid(fmt.Sprintf("resources.limits[%s]", resourceName), quantity.String(), "limit cannot be smaller than request")) + allErrs = append(allErrs, validation.NewInvalidError(fmt.Sprintf("resources.limits[%s]", resourceName), quantity.String(), "limit cannot be smaller than request")) } } } @@ -1789,7 +1789,7 @@ func validateResourceQuantityValue(resource string, value resource.Quantity) val allErrs = append(allErrs, ValidatePositiveQuantity(value, resource)...) if api.IsIntegerResourceName(resource) { if value.MilliValue()%int64(1000) != int64(0) { - allErrs = append(allErrs, validation.NewFieldInvalid(resource, value, isNotIntegerErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError(resource, value, isNotIntegerErrorMsg)) } } return allErrs @@ -1814,7 +1814,7 @@ func ValidateResourceQuotaStatusUpdate(newResourceQuota, oldResourceQuota *api.R allErrs := validation.ErrorList{} allErrs = append(allErrs, ValidateObjectMetaUpdate(&newResourceQuota.ObjectMeta, &oldResourceQuota.ObjectMeta).Prefix("metadata")...) if newResourceQuota.ResourceVersion == "" { - allErrs = append(allErrs, validation.NewFieldRequired("resourceVersion")) + allErrs = append(allErrs, validation.NewRequiredError("resourceVersion")) } for k, v := range newResourceQuota.Status.Hard { allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...) @@ -1842,12 +1842,12 @@ func ValidateNamespace(namespace *api.Namespace) validation.ErrorList { func validateFinalizerName(stringValue string) validation.ErrorList { allErrs := validation.ErrorList{} if !validation.IsQualifiedName(stringValue) { - return append(allErrs, validation.NewFieldInvalid("spec.finalizers", stringValue, qualifiedNameErrorMsg)) + return append(allErrs, validation.NewInvalidError("spec.finalizers", stringValue, qualifiedNameErrorMsg)) } if len(strings.Split(stringValue, "/")) == 1 { if !api.IsStandardFinalizerName(stringValue) { - return append(allErrs, validation.NewFieldInvalid("spec.finalizers", stringValue, fmt.Sprintf("finalizer name is neither a standard finalizer name nor is it fully qualified"))) + return append(allErrs, validation.NewInvalidError("spec.finalizers", stringValue, fmt.Sprintf("finalizer name is neither a standard finalizer name nor is it fully qualified"))) } } @@ -1872,11 +1872,11 @@ func ValidateNamespaceStatusUpdate(newNamespace, oldNamespace *api.Namespace) va newNamespace.Spec = oldNamespace.Spec if newNamespace.DeletionTimestamp.IsZero() { if newNamespace.Status.Phase != api.NamespaceActive { - allErrs = append(allErrs, validation.NewFieldInvalid("Status.Phase", newNamespace.Status.Phase, "A namespace may only be in active status if it does not have a deletion timestamp.")) + allErrs = append(allErrs, validation.NewInvalidError("Status.Phase", newNamespace.Status.Phase, "A namespace may only be in active status if it does not have a deletion timestamp.")) } } else { if newNamespace.Status.Phase != api.NamespaceTerminating { - allErrs = append(allErrs, validation.NewFieldInvalid("Status.Phase", newNamespace.Status.Phase, "A namespace may only be in terminating status if it has a deletion timestamp.")) + allErrs = append(allErrs, validation.NewInvalidError("Status.Phase", newNamespace.Status.Phase, "A namespace may only be in terminating status if it has a deletion timestamp.")) } } return allErrs @@ -1911,10 +1911,10 @@ func validateEndpointSubsets(subsets []api.EndpointSubset) validation.ErrorList ssErrs := validation.ErrorList{} if len(ss.Addresses) == 0 && len(ss.NotReadyAddresses) == 0 { - ssErrs = append(ssErrs, validation.NewFieldRequired("addresses or notReadyAddresses")) + ssErrs = append(ssErrs, validation.NewRequiredError("addresses or notReadyAddresses")) } if len(ss.Ports) == 0 { - ssErrs = append(ssErrs, validation.NewFieldRequired("ports")) + ssErrs = append(ssErrs, validation.NewRequiredError("ports")) } for addr := range ss.Addresses { ssErrs = append(ssErrs, validateEndpointAddress(&ss.Addresses[addr]).PrefixIndex(addr).Prefix("addresses")...) @@ -1932,7 +1932,7 @@ func validateEndpointSubsets(subsets []api.EndpointSubset) validation.ErrorList func validateEndpointAddress(address *api.EndpointAddress) validation.ErrorList { allErrs := validation.ErrorList{} if !validation.IsValidIPv4(address.IP) { - allErrs = append(allErrs, validation.NewFieldInvalid("ip", address.IP, "invalid IPv4 address")) + allErrs = append(allErrs, validation.NewInvalidError("ip", address.IP, "invalid IPv4 address")) return allErrs } return validateIpIsNotLinkLocalOrLoopback(address.IP, "ip") @@ -1944,17 +1944,17 @@ func validateIpIsNotLinkLocalOrLoopback(ipAddress, fieldName string) validation. allErrs := validation.ErrorList{} ip := net.ParseIP(ipAddress) if ip == nil { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, ipAddress, "not a valid IP address")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, ipAddress, "not a valid IP address")) return allErrs } if ip.IsLoopback() { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, ipAddress, "may not be in the loopback range (127.0.0.0/8)")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, ipAddress, "may not be in the loopback range (127.0.0.0/8)")) } if ip.IsLinkLocalUnicast() { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, ipAddress, "may not be in the link-local range (169.254.0.0/16)")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, ipAddress, "may not be in the link-local range (169.254.0.0/16)")) } if ip.IsLinkLocalMulticast() { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, ipAddress, "may not be in the link-local multicast range (224.0.0.0/24)")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, ipAddress, "may not be in the link-local multicast range (224.0.0.0/24)")) } return allErrs } @@ -1962,19 +1962,19 @@ func validateIpIsNotLinkLocalOrLoopback(ipAddress, fieldName string) validation. func validateEndpointPort(port *api.EndpointPort, requireName bool) validation.ErrorList { allErrs := validation.ErrorList{} if requireName && port.Name == "" { - allErrs = append(allErrs, validation.NewFieldRequired("name")) + allErrs = append(allErrs, validation.NewRequiredError("name")) } else if port.Name != "" { if !validation.IsDNS1123Label(port.Name) { - allErrs = append(allErrs, validation.NewFieldInvalid("name", port.Name, DNS1123LabelErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("name", port.Name, DNS1123LabelErrorMsg)) } } if !validation.IsValidPortNum(port.Port) { - allErrs = append(allErrs, validation.NewFieldInvalid("port", port.Port, PortRangeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("port", port.Port, PortRangeErrorMsg)) } if len(port.Protocol) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("protocol")) + allErrs = append(allErrs, validation.NewRequiredError("protocol")) } else if !supportedPortProtocols.Has(string(port.Protocol)) { - allErrs = append(allErrs, validation.NewFieldNotSupported("protocol", port.Protocol, supportedPortProtocols.List())) + allErrs = append(allErrs, validation.NewNotSupportedError("protocol", port.Protocol, supportedPortProtocols.List())) } return allErrs } @@ -1997,13 +1997,13 @@ func ValidateSecurityContext(sc *api.SecurityContext) validation.ErrorList { if sc.Privileged != nil { if *sc.Privileged && !capabilities.Get().AllowPrivileged { - allErrs = append(allErrs, validation.NewFieldForbidden("privileged", sc.Privileged)) + allErrs = append(allErrs, validation.NewForbiddenError("privileged", sc.Privileged)) } } if sc.RunAsUser != nil { if *sc.RunAsUser < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("runAsUser", *sc.RunAsUser, "runAsUser cannot be negative")) + allErrs = append(allErrs, validation.NewInvalidError("runAsUser", *sc.RunAsUser, "runAsUser cannot be negative")) } } return allErrs @@ -2012,18 +2012,18 @@ func ValidateSecurityContext(sc *api.SecurityContext) validation.ErrorList { func ValidatePodLogOptions(opts *api.PodLogOptions) validation.ErrorList { allErrs := validation.ErrorList{} if opts.TailLines != nil && *opts.TailLines < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("tailLines", *opts.TailLines, "tailLines must be a non-negative integer or nil")) + allErrs = append(allErrs, validation.NewInvalidError("tailLines", *opts.TailLines, "tailLines must be a non-negative integer or nil")) } if opts.LimitBytes != nil && *opts.LimitBytes < 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("limitBytes", *opts.LimitBytes, "limitBytes must be a positive integer or nil")) + allErrs = append(allErrs, validation.NewInvalidError("limitBytes", *opts.LimitBytes, "limitBytes must be a positive integer or nil")) } switch { case opts.SinceSeconds != nil && opts.SinceTime != nil: - allErrs = append(allErrs, validation.NewFieldInvalid("sinceSeconds", *opts.SinceSeconds, "only one of sinceTime or sinceSeconds can be provided")) - allErrs = append(allErrs, validation.NewFieldInvalid("sinceTime", *opts.SinceTime, "only one of sinceTime or sinceSeconds can be provided")) + allErrs = append(allErrs, validation.NewInvalidError("sinceSeconds", *opts.SinceSeconds, "only one of sinceTime or sinceSeconds can be provided")) + allErrs = append(allErrs, validation.NewInvalidError("sinceTime", *opts.SinceTime, "only one of sinceTime or sinceSeconds can be provided")) case opts.SinceSeconds != nil: if *opts.SinceSeconds < 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("sinceSeconds", *opts.SinceSeconds, "sinceSeconds must be a positive integer")) + allErrs = append(allErrs, validation.NewInvalidError("sinceSeconds", *opts.SinceSeconds, "sinceSeconds must be a positive integer")) } } return allErrs @@ -2035,15 +2035,15 @@ func ValidateLoadBalancerStatus(status *api.LoadBalancerStatus) validation.Error for _, ingress := range status.Ingress { if len(ingress.IP) > 0 { if isIP := (net.ParseIP(ingress.IP) != nil); !isIP { - allErrs = append(allErrs, validation.NewFieldInvalid("ingress.ip", ingress.IP, "must be an IP address")) + allErrs = append(allErrs, validation.NewInvalidError("ingress.ip", ingress.IP, "must be an IP address")) } } if len(ingress.Hostname) > 0 { if valid, errMsg := NameIsDNSSubdomain(ingress.Hostname, false); !valid { - allErrs = append(allErrs, validation.NewFieldInvalid("ingress.hostname", ingress.Hostname, errMsg)) + allErrs = append(allErrs, validation.NewInvalidError("ingress.hostname", ingress.Hostname, errMsg)) } if isIP := (net.ParseIP(ingress.Hostname) != nil); isIP { - allErrs = append(allErrs, validation.NewFieldInvalid("ingress.hostname", ingress.Hostname, "must be a DNS name, not an IP address")) + allErrs = append(allErrs, validation.NewInvalidError("ingress.hostname", ingress.Hostname, "must be a DNS name, not an IP address")) } } } diff --git a/pkg/apis/extensions/validation/validation.go b/pkg/apis/extensions/validation/validation.go index 7971898e0b4..e89279b94d2 100644 --- a/pkg/apis/extensions/validation/validation.go +++ b/pkg/apis/extensions/validation/validation.go @@ -42,21 +42,21 @@ func ValidateHorizontalPodAutoscalerName(name string, prefix bool) (bool, string func validateHorizontalPodAutoscalerSpec(autoscaler extensions.HorizontalPodAutoscalerSpec) validation.ErrorList { allErrs := validation.ErrorList{} if autoscaler.MinReplicas != nil && *autoscaler.MinReplicas < 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("minReplicas", autoscaler.MinReplicas, `must be bigger or equal to 1`)) + allErrs = append(allErrs, validation.NewInvalidError("minReplicas", autoscaler.MinReplicas, `must be bigger or equal to 1`)) } if autoscaler.MaxReplicas < 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to 1`)) + allErrs = append(allErrs, validation.NewInvalidError("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to 1`)) } if autoscaler.MinReplicas != nil && autoscaler.MaxReplicas < *autoscaler.MinReplicas { - allErrs = append(allErrs, validation.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to minReplicas`)) + allErrs = append(allErrs, validation.NewInvalidError("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to minReplicas`)) } if autoscaler.CPUUtilization != nil && autoscaler.CPUUtilization.TargetPercentage < 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("cpuUtilization.targetPercentage", autoscaler.CPUUtilization.TargetPercentage, `must be bigger or equal to 1`)) + allErrs = append(allErrs, validation.NewInvalidError("cpuUtilization.targetPercentage", autoscaler.CPUUtilization.TargetPercentage, `must be bigger or equal to 1`)) } if refErrs := ValidateSubresourceReference(autoscaler.ScaleRef); len(refErrs) > 0 { allErrs = append(allErrs, refErrs.Prefix("scaleRef")...) } else if autoscaler.ScaleRef.Subresource != "scale" { - allErrs = append(allErrs, validation.NewFieldNotSupported("scaleRef.subresource", autoscaler.ScaleRef.Subresource, []string{"scale"})) + allErrs = append(allErrs, validation.NewNotSupportedError("scaleRef.subresource", autoscaler.ScaleRef.Subresource, []string{"scale"})) } return allErrs } @@ -64,21 +64,21 @@ func validateHorizontalPodAutoscalerSpec(autoscaler extensions.HorizontalPodAuto func ValidateSubresourceReference(ref extensions.SubresourceReference) validation.ErrorList { allErrs := validation.ErrorList{} if len(ref.Kind) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("kind")) + allErrs = append(allErrs, validation.NewRequiredError("kind")) } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Kind); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("kind", ref.Kind, msg)) + allErrs = append(allErrs, validation.NewInvalidError("kind", ref.Kind, msg)) } if len(ref.Name) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("name")) + allErrs = append(allErrs, validation.NewRequiredError("name")) } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Name); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("name", ref.Name, msg)) + allErrs = append(allErrs, validation.NewInvalidError("name", ref.Name, msg)) } if len(ref.Subresource) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("subresource")) + allErrs = append(allErrs, validation.NewRequiredError("subresource")) } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Subresource); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("subresource", ref.Subresource, msg)) + allErrs = append(allErrs, validation.NewInvalidError("subresource", ref.Subresource, msg)) } return allErrs } @@ -126,10 +126,10 @@ func ValidateThirdPartyResource(obj *extensions.ThirdPartyResource) validation.E for ix := range obj.Versions { version := &obj.Versions[ix] if len(version.Name) == 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("name", version, "name can not be empty")) + allErrs = append(allErrs, validation.NewInvalidError("name", version, "name can not be empty")) } if versions.Has(version.Name) { - allErrs = append(allErrs, validation.NewFieldDuplicate("version", version)) + allErrs = append(allErrs, validation.NewDuplicateError("version", version)) } versions.Insert(version.Name) } @@ -180,7 +180,7 @@ func ValidateDaemonSetTemplateUpdate(podTemplate, oldPodTemplate *api.PodTemplat // In particular, we do not allow updates to container images at this point. if !api.Semantic.DeepEqual(oldPodTemplate.Spec, podSpec) { // TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff - allErrs = append(allErrs, validation.NewFieldInvalid("spec", "content of spec is not printed out, please refer to the \"details\"", "may not update fields other than spec.nodeSelector")) + allErrs = append(allErrs, validation.NewInvalidError("spec", "content of spec is not printed out, please refer to the \"details\"", "may not update fields other than spec.nodeSelector")) } return allErrs } @@ -192,13 +192,13 @@ func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec) validation.ErrorList allErrs = append(allErrs, ValidatePodSelector(spec.Selector)...) if spec.Template == nil { - allErrs = append(allErrs, validation.NewFieldRequired("template")) + allErrs = append(allErrs, validation.NewRequiredError("template")) return allErrs } selector, err := extensions.PodSelectorAsSelector(spec.Selector) if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) { - allErrs = append(allErrs, validation.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) + allErrs = append(allErrs, validation.NewInvalidError("template.metadata.labels", spec.Template.Labels, "selector does not match template")) } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template).Prefix("template")...) @@ -206,7 +206,7 @@ func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec) validation.ErrorList allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes).Prefix("template.spec.volumes")...) // RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { - allErrs = append(allErrs, validation.NewFieldNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) + allErrs = append(allErrs, validation.NewNotSupportedError("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } return allErrs @@ -228,7 +228,7 @@ func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fieldName str allErrs := validation.ErrorList{} if intOrPercent.Type == intstr.String { if !validation.IsValidPercent(intOrPercent.StrVal) { - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, intOrPercent, "value should be int(5) or percentage(5%)")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, intOrPercent, "value should be int(5) or percentage(5%)")) } } else if intOrPercent.Type == intstr.Int { allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(intOrPercent.IntVal), fieldName)...) @@ -258,7 +258,7 @@ func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fieldName stri if !isPercent || value <= 100 { return nil } - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, intOrStringValue, "should not be more than 100%")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName, intOrStringValue, "should not be more than 100%")) return allErrs } @@ -268,7 +268,7 @@ func ValidateRollingUpdateDeployment(rollingUpdate *extensions.RollingUpdateDepl allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fieldName+".maxSurge")...) if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 && getIntOrPercentValue(rollingUpdate.MaxSurge) == 0 { // Both MaxSurge and MaxUnavailable cannot be zero. - allErrs = append(allErrs, validation.NewFieldInvalid(fieldName+".maxUnavailable", rollingUpdate.MaxUnavailable, "cannot be 0 when maxSurge is 0 as well")) + allErrs = append(allErrs, validation.NewInvalidError(fieldName+".maxUnavailable", rollingUpdate.MaxUnavailable, "cannot be 0 when maxSurge is 0 as well")) } // Validate that MaxUnavailable is not more than 100%. allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fieldName+".maxUnavailable")...) @@ -283,7 +283,7 @@ func ValidateDeploymentStrategy(strategy *extensions.DeploymentStrategy, fieldNa } switch strategy.Type { case extensions.RecreateDeploymentStrategyType: - allErrs = append(allErrs, validation.NewFieldForbidden("rollingUpdate", "rollingUpdate should be nil when strategy type is "+extensions.RecreateDeploymentStrategyType)) + allErrs = append(allErrs, validation.NewForbiddenError("rollingUpdate", "rollingUpdate should be nil when strategy type is "+extensions.RecreateDeploymentStrategyType)) case extensions.RollingUpdateDeploymentStrategyType: allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, "rollingUpdate")...) } @@ -322,7 +322,7 @@ func ValidateThirdPartyResourceDataUpdate(update, old *extensions.ThirdPartyReso func ValidateThirdPartyResourceData(obj *extensions.ThirdPartyResourceData) validation.ErrorList { allErrs := validation.ErrorList{} if len(obj.Name) == 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("name", obj.Name, "name must be non-empty")) + allErrs = append(allErrs, validation.NewInvalidError("name", obj.Name, "name must be non-empty")) } return allErrs } @@ -345,7 +345,7 @@ func ValidateJobSpec(spec *extensions.JobSpec) validation.ErrorList { allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Completions), "completions")...) } if spec.Selector == nil { - allErrs = append(allErrs, validation.NewFieldRequired("selector")) + allErrs = append(allErrs, validation.NewRequiredError("selector")) } else { allErrs = append(allErrs, ValidatePodSelector(spec.Selector).Prefix("selector")...) } @@ -353,14 +353,14 @@ func ValidateJobSpec(spec *extensions.JobSpec) validation.ErrorList { if selector, err := extensions.PodSelectorAsSelector(spec.Selector); err == nil { labels := labels.Set(spec.Template.Labels) if !selector.Matches(labels) { - allErrs = append(allErrs, validation.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) + allErrs = append(allErrs, validation.NewInvalidError("template.metadata.labels", spec.Template.Labels, "selector does not match template")) } } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template).Prefix("template")...) if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { - allErrs = append(allErrs, validation.NewFieldNotSupported("template.spec.restartPolicy", + allErrs = append(allErrs, validation.NewNotSupportedError("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) } return allErrs @@ -423,7 +423,7 @@ func ValidateIngressSpec(spec *extensions.IngressSpec) validation.ErrorList { if spec.Backend != nil { allErrs = append(allErrs, validateIngressBackend(spec.Backend).Prefix("backend")...) } else if len(spec.Rules) == 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("rules", spec.Rules, "Either a default backend or a set of host rules are required for ingress.")) + allErrs = append(allErrs, validation.NewInvalidError("rules", spec.Rules, "Either a default backend or a set of host rules are required for ingress.")) } if len(spec.Rules) > 0 { allErrs = append(allErrs, validateIngressRules(spec.Rules).Prefix("rules")...) @@ -450,17 +450,17 @@ func ValidateIngressStatusUpdate(ingress, oldIngress *extensions.Ingress) valida func validateIngressRules(IngressRules []extensions.IngressRule) validation.ErrorList { allErrs := validation.ErrorList{} if len(IngressRules) == 0 { - return append(allErrs, validation.NewFieldRequired("IngressRules")) + return append(allErrs, validation.NewRequiredError("IngressRules")) } for _, ih := range IngressRules { if len(ih.Host) > 0 { // TODO: Ports and ips are allowed in the host part of a url // according to RFC 3986, consider allowing them. if valid, errMsg := apivalidation.NameIsDNSSubdomain(ih.Host, false); !valid { - allErrs = append(allErrs, validation.NewFieldInvalid("host", ih.Host, errMsg)) + allErrs = append(allErrs, validation.NewInvalidError("host", ih.Host, errMsg)) } if isIP := (net.ParseIP(ih.Host) != nil); isIP { - allErrs = append(allErrs, validation.NewFieldInvalid("host", ih.Host, "Host must be a DNS name, not ip address")) + allErrs = append(allErrs, validation.NewInvalidError("host", ih.Host, "Host must be a DNS name, not ip address")) } } allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue).Prefix("ingressRule")...) @@ -479,12 +479,12 @@ func validateIngressRuleValue(ingressRule *extensions.IngressRuleValue) validati func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRuleValue) validation.ErrorList { allErrs := validation.ErrorList{} if len(httpIngressRuleValue.Paths) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("paths")) + allErrs = append(allErrs, validation.NewRequiredError("paths")) } for _, rule := range httpIngressRuleValue.Paths { if len(rule.Path) > 0 { if !strings.HasPrefix(rule.Path, "/") { - allErrs = append(allErrs, validation.NewFieldInvalid("path", rule.Path, "path must begin with /")) + allErrs = append(allErrs, validation.NewInvalidError("path", rule.Path, "path must begin with /")) } // TODO: More draconian path regex validation. // Path must be a valid regex. This is the basic requirement. @@ -497,7 +497,7 @@ func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRu // the user is confusing url regexes with path regexes. _, err := regexp.CompilePOSIX(rule.Path) if err != nil { - allErrs = append(allErrs, validation.NewFieldInvalid("path", rule.Path, "httpIngressRuleValue.path must be a valid regex.")) + allErrs = append(allErrs, validation.NewInvalidError("path", rule.Path, "httpIngressRuleValue.path must be a valid regex.")) } } allErrs = append(allErrs, validateIngressBackend(&rule.Backend).Prefix("backend")...) @@ -511,19 +511,19 @@ func validateIngressBackend(backend *extensions.IngressBackend) validation.Error // All backends must reference a single local service by name, and a single service port by name or number. if len(backend.ServiceName) == 0 { - return append(allErrs, validation.NewFieldRequired("serviceName")) + return append(allErrs, validation.NewRequiredError("serviceName")) } else if ok, errMsg := apivalidation.ValidateServiceName(backend.ServiceName, false); !ok { - allErrs = append(allErrs, validation.NewFieldInvalid("serviceName", backend.ServiceName, errMsg)) + allErrs = append(allErrs, validation.NewInvalidError("serviceName", backend.ServiceName, errMsg)) } if backend.ServicePort.Type == intstr.String { if !validation.IsDNS1123Label(backend.ServicePort.StrVal) { - allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.DNS1123LabelErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("servicePort", backend.ServicePort.StrVal, apivalidation.DNS1123LabelErrorMsg)) } if !validation.IsValidPortName(backend.ServicePort.StrVal) { - allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.PortNameErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("servicePort", backend.ServicePort.StrVal, apivalidation.PortNameErrorMsg)) } } else if !validation.IsValidPortNum(backend.ServicePort.IntVal) { - allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort, apivalidation.PortRangeErrorMsg)) + allErrs = append(allErrs, validation.NewInvalidError("servicePort", backend.ServicePort, apivalidation.PortRangeErrorMsg)) } return allErrs } @@ -531,23 +531,23 @@ func validateIngressBackend(backend *extensions.IngressBackend) validation.Error func validateClusterAutoscalerSpec(spec extensions.ClusterAutoscalerSpec) validation.ErrorList { allErrs := validation.ErrorList{} if spec.MinNodes < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("minNodes", spec.MinNodes, `must be non-negative`)) + allErrs = append(allErrs, validation.NewInvalidError("minNodes", spec.MinNodes, `must be non-negative`)) } if spec.MaxNodes < spec.MinNodes { - allErrs = append(allErrs, validation.NewFieldInvalid("maxNodes", spec.MaxNodes, `must be bigger or equal to minNodes`)) + allErrs = append(allErrs, validation.NewInvalidError("maxNodes", spec.MaxNodes, `must be bigger or equal to minNodes`)) } if len(spec.TargetUtilization) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("targetUtilization")) + allErrs = append(allErrs, validation.NewRequiredError("targetUtilization")) } for _, target := range spec.TargetUtilization { if len(target.Resource) == 0 { - allErrs = append(allErrs, validation.NewFieldRequired("targetUtilization.resource")) + allErrs = append(allErrs, validation.NewRequiredError("targetUtilization.resource")) } if target.Value <= 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("targetUtilization.value", target.Value, "must be greater than 0")) + allErrs = append(allErrs, validation.NewInvalidError("targetUtilization.value", target.Value, "must be greater than 0")) } if target.Value > 1 { - allErrs = append(allErrs, validation.NewFieldInvalid("targetUtilization.value", target.Value, "must be less or equal 1")) + allErrs = append(allErrs, validation.NewInvalidError("targetUtilization.value", target.Value, "must be less or equal 1")) } } return allErrs @@ -556,10 +556,10 @@ func validateClusterAutoscalerSpec(spec extensions.ClusterAutoscalerSpec) valida func ValidateClusterAutoscaler(autoscaler *extensions.ClusterAutoscaler) validation.ErrorList { allErrs := validation.ErrorList{} if autoscaler.Name != "ClusterAutoscaler" { - allErrs = append(allErrs, validation.NewFieldInvalid("name", autoscaler.Name, `name must be ClusterAutoscaler`)) + allErrs = append(allErrs, validation.NewInvalidError("name", autoscaler.Name, `name must be ClusterAutoscaler`)) } if autoscaler.Namespace != api.NamespaceDefault { - allErrs = append(allErrs, validation.NewFieldInvalid("namespace", autoscaler.Namespace, `namespace must be default`)) + allErrs = append(allErrs, validation.NewInvalidError("namespace", autoscaler.Namespace, `namespace must be default`)) } allErrs = append(allErrs, validateClusterAutoscalerSpec(autoscaler.Spec)...) return allErrs @@ -582,14 +582,14 @@ func ValidatePodSelectorRequirement(sr extensions.PodSelectorRequirement) valida switch sr.Operator { case extensions.PodSelectorOpIn, extensions.PodSelectorOpNotIn: if len(sr.Values) == 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("values", sr.Values, "must be non-empty when operator is In or NotIn")) + allErrs = append(allErrs, validation.NewInvalidError("values", sr.Values, "must be non-empty when operator is In or NotIn")) } case extensions.PodSelectorOpExists, extensions.PodSelectorOpDoesNotExist: if len(sr.Values) > 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("values", sr.Values, "must be empty when operator is Exists or DoesNotExist")) + allErrs = append(allErrs, validation.NewInvalidError("values", sr.Values, "must be empty when operator is Exists or DoesNotExist")) } default: - allErrs = append(allErrs, validation.NewFieldInvalid("operator", sr.Operator, "not a valid pod selector operator")) + allErrs = append(allErrs, validation.NewInvalidError("operator", sr.Operator, "not a valid pod selector operator")) } allErrs = append(allErrs, apivalidation.ValidateLabelName(sr.Key, "key")...) return allErrs @@ -600,7 +600,7 @@ func ValidateScale(scale *extensions.Scale) validation.ErrorList { allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&scale.ObjectMeta, true, apivalidation.NameIsDNSSubdomain).Prefix("metadata")...) if scale.Spec.Replicas < 0 { - allErrs = append(allErrs, validation.NewFieldInvalid("spec.replicas", scale.Spec.Replicas, "must be non-negative")) + allErrs = append(allErrs, validation.NewInvalidError("spec.replicas", scale.Spec.Replicas, "must be non-negative")) } return allErrs diff --git a/pkg/kubectl/cmd/util/helpers_test.go b/pkg/kubectl/cmd/util/helpers_test.go index a142b121cec..72db1ff9225 100644 --- a/pkg/kubectl/cmd/util/helpers_test.go +++ b/pkg/kubectl/cmd/util/helpers_test.go @@ -274,11 +274,11 @@ func TestCheckInvalidErr(t *testing.T) { expected string }{ { - errors.NewInvalid("Invalid1", "invalidation", validation.ErrorList{validation.NewFieldInvalid("Cause", "single", "details")}), + errors.NewInvalid("Invalid1", "invalidation", validation.ErrorList{validation.NewInvalidError("Cause", "single", "details")}), `Error from server: Invalid1 "invalidation" is invalid: Cause: invalid value 'single', Details: details`, }, { - errors.NewInvalid("Invalid2", "invalidation", validation.ErrorList{validation.NewFieldInvalid("Cause", "multi1", "details"), validation.NewFieldInvalid("Cause", "multi2", "details")}), + errors.NewInvalid("Invalid2", "invalidation", validation.ErrorList{validation.NewInvalidError("Cause", "multi1", "details"), validation.NewInvalidError("Cause", "multi2", "details")}), `Error from server: Invalid2 "invalidation" is invalid: [Cause: invalid value 'multi1', Details: details, Cause: invalid value 'multi2', Details: details]`, }, { diff --git a/pkg/kubelet/config/config.go b/pkg/kubelet/config/config.go index 737c6aa7425..cbc5970d015 100644 --- a/pkg/kubelet/config/config.go +++ b/pkg/kubelet/config/config.go @@ -317,7 +317,7 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco } else { name := kubecontainer.GetPodFullName(pod) if names.Has(name) { - errlist = append(errlist, utilvalidation.NewFieldDuplicate("name", pod.Name)) + errlist = append(errlist, utilvalidation.NewDuplicateError("name", pod.Name)) } else { names.Insert(name) } diff --git a/pkg/labels/selector.go b/pkg/labels/selector.go index c3e70b56cb4..bc80dcb9cbe 100644 --- a/pkg/labels/selector.go +++ b/pkg/labels/selector.go @@ -701,14 +701,14 @@ const qualifiedNameErrorMsg string = "must match regex [" + validation.DNS1123Su func validateLabelKey(k string) error { if !validation.IsQualifiedName(k) { - return validation.NewFieldInvalid("label key", k, qualifiedNameErrorMsg) + return validation.NewInvalidError("label key", k, qualifiedNameErrorMsg) } return nil } func validateLabelValue(v string) error { if !validation.IsValidLabelValue(v) { - return validation.NewFieldInvalid("label value", v, qualifiedNameErrorMsg) + return validation.NewInvalidError("label value", v, qualifiedNameErrorMsg) } return nil } diff --git a/pkg/registry/pod/etcd/etcd.go b/pkg/registry/pod/etcd/etcd.go index c9d233821bd..8a8c3b91674 100644 --- a/pkg/registry/pod/etcd/etcd.go +++ b/pkg/registry/pod/etcd/etcd.go @@ -129,10 +129,10 @@ func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.O binding := obj.(*api.Binding) // TODO: move me to a binding strategy if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" { - return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewFieldInvalid("to.kind", binding.Target.Kind, "must be empty or 'Node'")}) + return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewInvalidError("to.kind", binding.Target.Kind, "must be empty or 'Node'")}) } if len(binding.Target.Name) == 0 { - return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewFieldRequired("to.name")}) + return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewRequiredError("to.name")}) } err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) out = &unversioned.Status{Status: unversioned.StatusSuccess} diff --git a/pkg/registry/service/rest.go b/pkg/registry/service/rest.go index b632ee33571..931e2820e1d 100644 --- a/pkg/registry/service/rest.go +++ b/pkg/registry/service/rest.go @@ -84,7 +84,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err // Allocate next available. ip, err := rs.serviceIPs.AllocateNext() if err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())} + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("spec.clusterIP", service.Spec.ClusterIP, err.Error())} return nil, errors.NewInvalid("Service", service.Name, el) } service.Spec.ClusterIP = ip.String() @@ -92,7 +92,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err } else if api.IsServiceIPSet(service) { // Try to respect the requested IP. if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())} + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("spec.clusterIP", service.Spec.ClusterIP, err.Error())} return nil, errors.NewInvalid("Service", service.Name, el) } releaseServiceIP = true @@ -104,13 +104,13 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err if servicePort.NodePort != 0 { err := nodePortOp.Allocate(servicePort.NodePort) if err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") return nil, errors.NewInvalid("Service", service.Name, el) } } else if assignNodePorts { nodePort, err := nodePortOp.AllocateNext() if err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") return nil, errors.NewInvalid("Service", service.Name, el) } servicePort.NodePort = nodePort @@ -223,14 +223,14 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo if !contains(oldNodePorts, nodePort) { err := nodePortOp.Allocate(nodePort) if err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") return nil, false, errors.NewInvalid("Service", service.Name, el) } } } else { nodePort, err = nodePortOp.AllocateNext() if err != nil { - el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") + el := utilvalidation.ErrorList{utilvalidation.NewInvalidError("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") return nil, false, errors.NewInvalid("Service", service.Name, el) } servicePort.NodePort = nodePort diff --git a/pkg/storage/util.go b/pkg/storage/util.go index 01c29cdf202..8f8aa5277df 100644 --- a/pkg/storage/util.go +++ b/pkg/storage/util.go @@ -48,7 +48,7 @@ func ParseWatchResourceVersion(resourceVersion, kind string) (uint64, error) { version, err := strconv.ParseUint(resourceVersion, 10, 64) if err != nil { // TODO: Does this need to be a ErrorList? I can't convince myself it does. - return 0, errors.NewInvalid(kind, "", utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("resourceVersion", resourceVersion, err.Error())}) + return 0, errors.NewInvalid(kind, "", utilvalidation.ErrorList{utilvalidation.NewInvalidError("resourceVersion", resourceVersion, err.Error())}) } return version + 1, nil } diff --git a/pkg/util/validation/errors.go b/pkg/util/validation/errors.go index 56d39cf89b6..bb6bfd56164 100644 --- a/pkg/util/validation/errors.go +++ b/pkg/util/validation/errors.go @@ -65,29 +65,29 @@ type ErrorType string // TODO: These values are duplicated in api/types.go, but there's a circular dep. Fix it. const ( // ErrorTypeNotFound is used to report failure to find a requested value - // (e.g. looking up an ID). See NewFieldNotFound. + // (e.g. looking up an ID). See NewNotFoundError. ErrorTypeNotFound ErrorType = "FieldValueNotFound" // ErrorTypeRequired is used to report required values that are not // provided (e.g. empty strings, null values, or empty arrays). See - // NewFieldRequired. + // NewRequiredError. ErrorTypeRequired ErrorType = "FieldValueRequired" // ErrorTypeDuplicate is used to report collisions of values that must be - // unique (e.g. unique IDs). See NewFieldDuplicate. + // unique (e.g. unique IDs). See NewDuplicateError. ErrorTypeDuplicate ErrorType = "FieldValueDuplicate" // ErrorTypeInvalid is used to report malformed values (e.g. failed regex - // match, too long, out of bounds). See NewFieldInvalid. + // match, too long, out of bounds). See NewInvalidError. ErrorTypeInvalid ErrorType = "FieldValueInvalid" // ErrorTypeNotSupported is used to report unknown values for enumerated - // fields (e.g. a list of valid values). See NewFieldNotSupported. + // fields (e.g. a list of valid values). See NewNotSupportedError. ErrorTypeNotSupported ErrorType = "FieldValueNotSupported" // ErrorTypeForbidden is used to report valid (as per formatting rules) // values which would be accepted under some conditions, but which are not // permitted by the current conditions (such as security policy). See - // NewFieldForbidden. + // NewForbiddenError. ErrorTypeForbidden ErrorType = "FieldValueForbidden" // ErrorTypeTooLong is used to report that the given value is too long. // This is similar to ErrorTypeInvalid, but the error will not include the - // too-long value. See NewFieldTooLong. + // too-long value. See NewTooLongError. ErrorTypeTooLong ErrorType = "FieldValueTooLong" // ErrorTypeInternal is used to report other errors that are not related // to user input. @@ -119,35 +119,35 @@ func (t ErrorType) String() string { } } -// NewFieldNotFound returns a *Error indicating "value not found". This is +// NewNotFoundError returns a *Error indicating "value not found". This is // used to report failure to find a requested value (e.g. looking up an ID). -func NewFieldNotFound(field string, value interface{}) *Error { +func NewNotFoundError(field string, value interface{}) *Error { return &Error{ErrorTypeNotFound, field, value, ""} } -// NewFieldRequired returns a *Error indicating "value required". This is used +// NewRequiredError returns a *Error indicating "value required". This is used // to report required values that are not provided (e.g. empty strings, null // values, or empty arrays). -func NewFieldRequired(field string) *Error { +func NewRequiredError(field string) *Error { return &Error{ErrorTypeRequired, field, "", ""} } -// NewFieldDuplicate returns a *Error indicating "duplicate value". This is +// NewDuplicateError returns a *Error indicating "duplicate value". This is // used to report collisions of values that must be unique (e.g. names or IDs). -func NewFieldDuplicate(field string, value interface{}) *Error { +func NewDuplicateError(field string, value interface{}) *Error { return &Error{ErrorTypeDuplicate, field, value, ""} } -// NewFieldInvalid returns a *Error indicating "invalid value". This is used +// NewInvalidError returns a *Error indicating "invalid value". This is used // to report malformed values (e.g. failed regex match, too long, out of bounds). -func NewFieldInvalid(field string, value interface{}, detail string) *Error { +func NewInvalidError(field string, value interface{}, detail string) *Error { return &Error{ErrorTypeInvalid, field, value, detail} } -// NewFieldNotSupported returns a *Error indicating "unsupported value". +// NewNotSupportedError returns a *Error indicating "unsupported value". // This is used to report unknown values for enumerated fields (e.g. a list of // valid values). -func NewFieldNotSupported(field string, value interface{}, validValues []string) *Error { +func NewNotSupportedError(field string, value interface{}, validValues []string) *Error { detail := "" if validValues != nil && len(validValues) > 0 { detail = "supported values: " + strings.Join(validValues, ", ") @@ -155,19 +155,19 @@ func NewFieldNotSupported(field string, value interface{}, validValues []string) return &Error{ErrorTypeNotSupported, field, value, detail} } -// NewFieldForbidden returns a *Error indicating "forbidden". This is used to +// NewForbiddenError returns a *Error indicating "forbidden". This is used to // report valid (as per formatting rules) values which would be accepted under // some conditions, but which are not permitted by current conditions (e.g. // security policy). -func NewFieldForbidden(field string, value interface{}) *Error { +func NewForbiddenError(field string, value interface{}) *Error { return &Error{ErrorTypeForbidden, field, value, ""} } -// NewFieldTooLong returns a *Error indicating "too long". This is used to +// NewTooLongError returns a *Error indicating "too long". This is used to // report that the given value is too long. This is similar to -// NewFieldInvalid, but the returned error will not include the too-long +// NewInvalidError, but the returned error will not include the too-long // value. -func NewFieldTooLong(field string, value interface{}, maxLength int) *Error { +func NewTooLongError(field string, value interface{}, maxLength int) *Error { return &Error{ErrorTypeTooLong, field, value, fmt.Sprintf("must have at most %d characters", maxLength)} } diff --git a/pkg/util/validation/errors_test.go b/pkg/util/validation/errors_test.go index d4fb1884295..993e3a38d6b 100644 --- a/pkg/util/validation/errors_test.go +++ b/pkg/util/validation/errors_test.go @@ -28,23 +28,23 @@ func TestMakeFuncs(t *testing.T) { expected ErrorType }{ { - func() *Error { return NewFieldInvalid("f", "v", "d") }, + func() *Error { return NewInvalidError("f", "v", "d") }, ErrorTypeInvalid, }, { - func() *Error { return NewFieldNotSupported("f", "v", nil) }, + func() *Error { return NewNotSupportedError("f", "v", nil) }, ErrorTypeNotSupported, }, { - func() *Error { return NewFieldDuplicate("f", "v") }, + func() *Error { return NewDuplicateError("f", "v") }, ErrorTypeDuplicate, }, { - func() *Error { return NewFieldNotFound("f", "v") }, + func() *Error { return NewNotFoundError("f", "v") }, ErrorTypeNotFound, }, { - func() *Error { return NewFieldRequired("f") }, + func() *Error { return NewRequiredError("f") }, ErrorTypeRequired, }, { @@ -62,7 +62,7 @@ func TestMakeFuncs(t *testing.T) { } func TestErrorUsefulMessage(t *testing.T) { - s := NewFieldInvalid("foo", "bar", "deet").Error() + s := NewInvalidError("foo", "bar", "deet").Error() t.Logf("message: %v", s) for _, part := range []string{"foo", "bar", "deet", ErrorTypeInvalid.String()} { if !strings.Contains(s, part) { @@ -76,7 +76,7 @@ func TestErrorUsefulMessage(t *testing.T) { Inner interface{} KV map[string]int } - s = NewFieldInvalid( + s = NewInvalidError( "foo", &complicated{ Baz: 1, @@ -102,8 +102,8 @@ func TestToAggregate(t *testing.T) { testCases := []ErrorList{ nil, {}, - {NewFieldInvalid("f", "v", "d")}, - {NewFieldInvalid("f", "v", "d"), NewInternalError("", fmt.Errorf("e"))}, + {NewInvalidError("f", "v", "d")}, + {NewInvalidError("f", "v", "d"), NewInternalError("", fmt.Errorf("e"))}, } for i, tc := range testCases { agg := tc.ToAggregate() @@ -121,9 +121,9 @@ func TestToAggregate(t *testing.T) { func TestErrListFilter(t *testing.T) { list := ErrorList{ - NewFieldInvalid("test.field", "", ""), - NewFieldInvalid("field.test", "", ""), - NewFieldDuplicate("test", "value"), + NewInvalidError("test.field", "", ""), + NewInvalidError("field.test", "", ""), + NewDuplicateError("test", "value"), } if len(list.Filter(NewErrorTypeMatcher(ErrorTypeDuplicate))) != 2 { t.Errorf("should not filter") @@ -139,15 +139,15 @@ func TestErrListPrefix(t *testing.T) { Expected string }{ { - NewFieldNotFound("[0].bar", "value"), + NewNotFoundError("[0].bar", "value"), "foo[0].bar", }, { - NewFieldInvalid("field", "value", ""), + NewInvalidError("field", "value", ""), "foo.field", }, { - NewFieldDuplicate("", "value"), + NewDuplicateError("", "value"), "foo", }, } @@ -169,15 +169,15 @@ func TestErrListPrefixIndex(t *testing.T) { Expected string }{ { - NewFieldNotFound("[0].bar", "value"), + NewNotFoundError("[0].bar", "value"), "[1][0].bar", }, { - NewFieldInvalid("field", "value", ""), + NewInvalidError("field", "value", ""), "[1].field", }, { - NewFieldDuplicate("", "value"), + NewDuplicateError("", "value"), "[1]", }, }