Merge pull request #17245 from thockin/airplane_validation_pt1

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot
2015-11-23 06:45:28 -08:00
43 changed files with 931 additions and 961 deletions

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
) )
// HTTP Status codes not in the golang http package. // HTTP Status codes not in the golang http package.
@@ -159,10 +159,10 @@ func NewConflict(kind, name string, err error) error {
} }
// NewInvalid returns an error indicating the item is invalid and cannot be processed. // NewInvalid returns an error indicating the item is invalid and cannot be processed.
func NewInvalid(kind, name string, errs fielderrors.ValidationErrorList) error { func NewInvalid(kind, name string, errs validation.ErrorList) error {
causes := make([]unversioned.StatusCause, 0, len(errs)) causes := make([]unversioned.StatusCause, 0, len(errs))
for i := range errs { for i := range errs {
if err, ok := errs[i].(*fielderrors.ValidationError); ok { if err, ok := errs[i].(*validation.Error); ok {
causes = append(causes, unversioned.StatusCause{ causes = append(causes, unversioned.StatusCause{
Type: unversioned.CauseType(err.Type), Type: unversioned.CauseType(err.Type),
Message: err.ErrorBody(), Message: err.ErrorBody(),

View File

@@ -24,7 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
) )
func TestErrorNew(t *testing.T) { func TestErrorNew(t *testing.T) {
@@ -88,11 +88,11 @@ func TestErrorNew(t *testing.T) {
func TestNewInvalid(t *testing.T) { func TestNewInvalid(t *testing.T) {
testCases := []struct { testCases := []struct {
Err *fielderrors.ValidationError Err *validation.Error
Details *unversioned.StatusDetails Details *unversioned.StatusDetails
}{ }{
{ {
fielderrors.NewFieldDuplicate("field[0].name", "bar"), validation.NewFieldDuplicate("field[0].name", "bar"),
&unversioned.StatusDetails{ &unversioned.StatusDetails{
Kind: "kind", Kind: "kind",
Name: "name", Name: "name",
@@ -103,7 +103,7 @@ func TestNewInvalid(t *testing.T) {
}, },
}, },
{ {
fielderrors.NewFieldInvalid("field[0].name", "bar", "detail"), validation.NewFieldInvalid("field[0].name", "bar", "detail"),
&unversioned.StatusDetails{ &unversioned.StatusDetails{
Kind: "kind", Kind: "kind",
Name: "name", Name: "name",
@@ -114,7 +114,7 @@ func TestNewInvalid(t *testing.T) {
}, },
}, },
{ {
fielderrors.NewFieldNotFound("field[0].name", "bar"), validation.NewFieldNotFound("field[0].name", "bar"),
&unversioned.StatusDetails{ &unversioned.StatusDetails{
Kind: "kind", Kind: "kind",
Name: "name", Name: "name",
@@ -125,7 +125,7 @@ func TestNewInvalid(t *testing.T) {
}, },
}, },
{ {
fielderrors.NewFieldValueNotSupported("field[0].name", "bar", nil), validation.NewFieldValueNotSupported("field[0].name", "bar", nil),
&unversioned.StatusDetails{ &unversioned.StatusDetails{
Kind: "kind", Kind: "kind",
Name: "name", Name: "name",
@@ -136,7 +136,7 @@ func TestNewInvalid(t *testing.T) {
}, },
}, },
{ {
fielderrors.NewFieldRequired("field[0].name"), validation.NewFieldRequired("field[0].name"),
&unversioned.StatusDetails{ &unversioned.StatusDetails{
Kind: "kind", Kind: "kind",
Name: "name", Name: "name",
@@ -150,7 +150,7 @@ func TestNewInvalid(t *testing.T) {
for i, testCase := range testCases { for i, testCase := range testCases {
vErr, expected := testCase.Err, testCase.Details vErr, expected := testCase.Err, testCase.Details
expected.Causes[0].Message = vErr.ErrorBody() expected.Causes[0].Message = vErr.ErrorBody()
err := NewInvalid("kind", "name", fielderrors.ValidationErrorList{vErr}) err := NewInvalid("kind", "name", validation.ErrorList{vErr})
status := err.(*StatusError).ErrStatus status := err.(*StatusError).ErrStatus
if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid { if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid {
t.Errorf("%d: unexpected status: %#v", i, status) t.Errorf("%d: unexpected status: %#v", i, status)

View File

@@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// RESTCreateStrategy defines the minimum validation, accepted input, and // RESTCreateStrategy defines the minimum validation, accepted input, and
@@ -42,7 +42,7 @@ type RESTCreateStrategy interface {
PrepareForCreate(obj runtime.Object) PrepareForCreate(obj runtime.Object)
// Validate is invoked after default fields in the object have been filled in before // Validate is invoked after default fields in the object have been filled in before
// the object is persisted. This method should not mutate the object. // the object is persisted. This method should not mutate the object.
Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList
// Canonicalize is invoked after validation has succeeded but before the // Canonicalize is invoked after validation has succeeded but before the
// object has been persisted. This method may mutate the object. // object has been persisted. This method may mutate the object.
Canonicalize(obj runtime.Object) Canonicalize(obj runtime.Object)

View File

@@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// RESTUpdateStrategy defines the minimum validation, accepted input, and // RESTUpdateStrategy defines the minimum validation, accepted input, and
@@ -42,7 +42,7 @@ type RESTUpdateStrategy interface {
// ValidateUpdate is invoked after default fields in the object have been // ValidateUpdate is invoked after default fields in the object have been
// filled in before the object is persisted. This method should not mutate // filled in before the object is persisted. This method should not mutate
// the object. // the object.
ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList
// Canonicalize is invoked after validation has succeeded but before the // Canonicalize is invoked after validation has succeeded but before the
// object has been persisted. This method may mutate the object. // object has been persisted. This method may mutate the object.
Canonicalize(obj runtime.Object) Canonicalize(obj runtime.Object)
@@ -53,8 +53,8 @@ type RESTUpdateStrategy interface {
} }
// TODO: add other common fields that require global validation. // TODO: add other common fields that require global validation.
func validateCommonFields(obj, old runtime.Object) fielderrors.ValidationErrorList { func validateCommonFields(obj, old runtime.Object) utilvalidation.ErrorList {
allErrs := fielderrors.ValidationErrorList{} allErrs := utilvalidation.ErrorList{}
objectMeta, err := api.ObjectMetaFor(obj) objectMeta, err := api.ObjectMetaFor(obj)
if err != nil { if err != nil {
return append(allErrs, errors.NewInternalError(err)) return append(allErrs, errors.NewInternalError(err))

View File

@@ -28,7 +28,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
) )
@@ -42,7 +42,7 @@ func TestCompatibility(
t *testing.T, t *testing.T,
version string, version string,
input []byte, input []byte,
validator func(obj runtime.Object) fielderrors.ValidationErrorList, validator func(obj runtime.Object) validation.ErrorList,
expectedKeys map[string]string, expectedKeys map[string]string,
absentKeys []string, absentKeys []string,
) { ) {

View File

@@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api/testing/compat" "k8s.io/kubernetes/pkg/api/testing/compat"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
func TestCompatibility_v1_PodSecurityContext(t *testing.T) { func TestCompatibility_v1_PodSecurityContext(t *testing.T) {
@@ -217,7 +217,7 @@ func TestCompatibility_v1_PodSecurityContext(t *testing.T) {
}, },
} }
validator := func(obj runtime.Object) fielderrors.ValidationErrorList { validator := func(obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidatePodSpec(&(obj.(*api.Pod).Spec)) return validation.ValidatePodSpec(&(obj.(*api.Pod).Spec))
} }

View File

@@ -18,20 +18,19 @@ package validation
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
errs "k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/validation"
) )
// ValidateEvent makes sure that the event makes sense. // ValidateEvent makes sure that the event makes sense.
func ValidateEvent(event *api.Event) errs.ValidationErrorList { func ValidateEvent(event *api.Event) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
// TODO: There is no namespace required for node. // TODO: There is no namespace required for node.
if event.InvolvedObject.Kind != "Node" && if event.InvolvedObject.Kind != "Node" &&
event.Namespace != event.InvolvedObject.Namespace { event.Namespace != event.InvolvedObject.Namespace {
allErrs = append(allErrs, errs.NewFieldInvalid("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) allErrs = append(allErrs, validation.NewFieldInvalid("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject"))
} }
if !validation.IsDNS1123Subdomain(event.Namespace) { if !validation.IsDNS1123Subdomain(event.Namespace) {
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", event.Namespace, "")) allErrs = append(allErrs, validation.NewFieldInvalid("namespace", event.Namespace, ""))
} }
return allErrs return allErrs
} }

View File

@@ -27,7 +27,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
apiutil "k8s.io/kubernetes/pkg/api/util" apiutil "k8s.io/kubernetes/pkg/api/util"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
errs "k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
"k8s.io/kubernetes/pkg/util/yaml" "k8s.io/kubernetes/pkg/util/yaml"
) )
@@ -70,8 +70,8 @@ func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) {
// validateList unpack a list and validate every item in the list. // validateList unpack a list and validate every item in the list.
// It return nil if every item is ok. // It return nil if every item is ok.
// Otherwise it return an error list contain errors of every item. // Otherwise it return an error list contain errors of every item.
func (s *SwaggerSchema) validateList(obj map[string]interface{}) errs.ValidationErrorList { func (s *SwaggerSchema) validateList(obj map[string]interface{}) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
items, exists := obj["items"] items, exists := obj["items"]
if !exists { if !exists {
return append(allErrs, fmt.Errorf("no items field in %#v", obj)) return append(allErrs, fmt.Errorf("no items field in %#v", obj))
@@ -160,8 +160,8 @@ func (s *SwaggerSchema) ValidateBytes(data []byte) error {
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) errs.ValidationErrorList { func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
models := s.api.Models models := s.api.Models
model, ok := models.At(typeName) model, ok := models.At(typeName)
if !ok { if !ok {
@@ -215,7 +215,7 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName stri
// This matches type name in the swagger spec, such as "v1.Binding". // This matches type name in the swagger spec, such as "v1.Binding".
var versionRegexp = regexp.MustCompile(`^v.+\..*`) var versionRegexp = regexp.MustCompile(`^v.+\..*`)
func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) errs.ValidationErrorList { func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) validation.ErrorList {
// TODO: caesarxuchao: because we have multiple group/versions and objects // TODO: caesarxuchao: because we have multiple group/versions and objects
// may reference objects in other group, the commented out way of checking // 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 // if a filedType is a type defined by us is outdated. We use a hacky way
@@ -229,7 +229,7 @@ func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType st
// if strings.HasPrefix(fieldType, apiVersion) { // if strings.HasPrefix(fieldType, apiVersion) {
return s.ValidateObject(value, fieldName, fieldType) return s.ValidateObject(value, fieldName, fieldType)
} }
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
switch fieldType { switch fieldType {
case "string": case "string":
// Be loose about what we accept for 'string' since we use IntOrString in a couple of places // Be loose about what we accept for 'string' since we use IntOrString in a couple of places

File diff suppressed because it is too large Load Diff

View File

@@ -29,15 +29,14 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/capabilities"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/fielderrors"
errors "k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/validation"
) )
func expectPrefix(t *testing.T, prefix string, errs fielderrors.ValidationErrorList) { func expectPrefix(t *testing.T, prefix string, errs validation.ErrorList) {
for i := range errs { for i := range errs {
if f, p := errs[i].(*errors.ValidationError).Field, prefix; !strings.HasPrefix(f, p) { if f, p := errs[i].(*validation.Error).Field, prefix; !strings.HasPrefix(f, p) {
t.Errorf("expected prefix '%s' for field '%s' (%v)", p, f, errs[i]) t.Errorf("expected prefix '%s' for field '%s' (%v)", p, f, errs[i])
} }
} }
@@ -151,7 +150,7 @@ func TestValidateLabels(t *testing.T) {
if len(errs) != 1 { if len(errs) != 1 {
t.Errorf("case[%d] expected failure", i) t.Errorf("case[%d] expected failure", i)
} else { } else {
detail := errs[0].(*errors.ValidationError).Detail detail := errs[0].(*validation.Error).Detail
if detail != qualifiedNameErrorMsg { if detail != qualifiedNameErrorMsg {
t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg)
} }
@@ -169,7 +168,7 @@ func TestValidateLabels(t *testing.T) {
if len(errs) != 1 { if len(errs) != 1 {
t.Errorf("case[%d] expected failure", i) t.Errorf("case[%d] expected failure", i)
} else { } else {
detail := errs[0].(*errors.ValidationError).Detail detail := errs[0].(*validation.Error).Detail
if detail != labelValueErrorMsg { if detail != labelValueErrorMsg {
t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg) t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg)
} }
@@ -216,7 +215,7 @@ func TestValidateAnnotations(t *testing.T) {
if len(errs) != 1 { if len(errs) != 1 {
t.Errorf("case[%d] expected failure", i) t.Errorf("case[%d] expected failure", i)
} }
detail := errs[0].(*errors.ValidationError).Detail detail := errs[0].(*validation.Error).Detail
if detail != qualifiedNameErrorMsg { if detail != qualifiedNameErrorMsg {
t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg)
} }
@@ -537,30 +536,30 @@ func TestValidateVolumes(t *testing.T) {
slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}} slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}}
errorCases := map[string]struct { errorCases := map[string]struct {
V []api.Volume V []api.Volume
T errors.ValidationErrorType T validation.ErrorType
F string F string
D string D string
}{ }{
"zero-length name": {[]api.Volume{{Name: "", VolumeSource: emptyVS}}, errors.ValidationErrorTypeRequired, "[0].name", ""}, "zero-length name": {[]api.Volume{{Name: "", VolumeSource: emptyVS}}, validation.ErrorTypeRequired, "[0].name", ""},
"name > 63 characters": {[]api.Volume{{Name: strings.Repeat("a", 64), VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""}, "name > 63 characters": {[]api.Volume{{Name: strings.Repeat("a", 64), VolumeSource: emptyVS}}, validation.ErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
"name not a DNS label": {[]api.Volume{{Name: "a.b.c", VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""}, "name not a DNS label": {[]api.Volume{{Name: "a.b.c", VolumeSource: emptyVS}}, validation.ErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
"name not unique": {[]api.Volume{{Name: "abc", VolumeSource: emptyVS}, {Name: "abc", VolumeSource: emptyVS}}, errors.ValidationErrorTypeDuplicate, "[1].name", ""}, "name not unique": {[]api.Volume{{Name: "abc", VolumeSource: emptyVS}, {Name: "abc", VolumeSource: emptyVS}}, validation.ErrorTypeDuplicate, "[1].name", ""},
"empty portal": {[]api.Volume{{Name: "badportal", VolumeSource: emptyPortal}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.targetPortal", ""}, "empty portal": {[]api.Volume{{Name: "badportal", VolumeSource: emptyPortal}}, validation.ErrorTypeRequired, "[0].source.iscsi.targetPortal", ""},
"empty iqn": {[]api.Volume{{Name: "badiqn", VolumeSource: emptyIQN}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.iqn", ""}, "empty iqn": {[]api.Volume{{Name: "badiqn", VolumeSource: emptyIQN}}, validation.ErrorTypeRequired, "[0].source.iscsi.iqn", ""},
"empty hosts": {[]api.Volume{{Name: "badhost", VolumeSource: emptyHosts}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.endpoints", ""}, "empty hosts": {[]api.Volume{{Name: "badhost", VolumeSource: emptyHosts}}, validation.ErrorTypeRequired, "[0].source.glusterfs.endpoints", ""},
"empty path": {[]api.Volume{{Name: "badpath", VolumeSource: emptyPath}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.path", ""}, "empty path": {[]api.Volume{{Name: "badpath", VolumeSource: emptyPath}}, validation.ErrorTypeRequired, "[0].source.glusterfs.path", ""},
"empty datasetName": {[]api.Volume{{Name: "badname", VolumeSource: emptyName}}, errors.ValidationErrorTypeRequired, "[0].source.flocker.datasetName", ""}, "empty datasetName": {[]api.Volume{{Name: "badname", VolumeSource: emptyName}}, validation.ErrorTypeRequired, "[0].source.flocker.datasetName", ""},
"empty mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyMon}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.monitors", ""}, "empty mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyMon}}, validation.ErrorTypeRequired, "[0].source.rbd.monitors", ""},
"empty image": {[]api.Volume{{Name: "badimage", VolumeSource: emptyImage}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.image", ""}, "empty image": {[]api.Volume{{Name: "badimage", VolumeSource: emptyImage}}, validation.ErrorTypeRequired, "[0].source.rbd.image", ""},
"empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, errors.ValidationErrorTypeRequired, "[0].source.cephfs.monitors", ""}, "empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, validation.ErrorTypeRequired, "[0].source.cephfs.monitors", ""},
"empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, errors.ValidationErrorTypeRequired, "[0].source.downwardApi.path", ""}, "empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, validation.ErrorTypeRequired, "[0].source.downwardApi.path", ""},
"absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, errors.ValidationErrorTypeForbidden, "[0].source.downwardApi.path", ""}, "absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, validation.ErrorTypeForbidden, "[0].source.downwardApi.path", ""},
"dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\"."}, "dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\"."},
"dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."}, "dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
"dot dot first level dirent": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."}, "dot dot first level dirent": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
"empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, errors.ValidationErrorTypeRequired, "[0].source.fc.targetWWNs", ""}, "empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, validation.ErrorTypeRequired, "[0].source.fc.targetWWNs", ""},
"empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, errors.ValidationErrorTypeRequired, "[0].source.fc.lun", ""}, "empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, validation.ErrorTypeRequired, "[0].source.fc.lun", ""},
"slash in datasetName": {[]api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, errors.ValidationErrorTypeInvalid, "[0].source.flocker.datasetName", "must not contain '/'"}, "slash in datasetName": {[]api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, validation.ErrorTypeInvalid, "[0].source.flocker.datasetName", "must not contain '/'"},
} }
for k, v := range errorCases { for k, v := range errorCases {
_, errs := validateVolumes(v.V) _, errs := validateVolumes(v.V)
@@ -569,13 +568,13 @@ func TestValidateVolumes(t *testing.T) {
continue continue
} }
for i := range errs { for i := range errs {
if errs[i].(*errors.ValidationError).Type != v.T { if errs[i].(*validation.Error).Type != v.T {
t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i])
} }
if errs[i].(*errors.ValidationError).Field != v.F { if errs[i].(*validation.Error).Field != v.F {
t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i])
} }
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*validation.Error).Detail
if detail != v.D { if detail != v.D {
t.Errorf("%s: expected error detail \"%s\", got \"%s\"", k, v.D, detail) t.Errorf("%s: expected error detail \"%s\", got \"%s\"", k, v.D, detail)
} }
@@ -604,23 +603,23 @@ func TestValidatePorts(t *testing.T) {
errorCases := map[string]struct { errorCases := map[string]struct {
P []api.ContainerPort P []api.ContainerPort
T errors.ValidationErrorType T validation.ErrorType
F string F string
D string D string
}{ }{
"name > 15 characters": {[]api.ContainerPort{{Name: strings.Repeat("a", 16), ContainerPort: 80, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].name", PortNameErrorMsg}, "name > 15 characters": {[]api.ContainerPort{{Name: strings.Repeat("a", 16), ContainerPort: 80, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].name", PortNameErrorMsg},
"name not a IANA svc name ": {[]api.ContainerPort{{Name: "a.b.c", ContainerPort: 80, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].name", PortNameErrorMsg}, "name not a IANA svc name ": {[]api.ContainerPort{{Name: "a.b.c", ContainerPort: 80, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].name", PortNameErrorMsg},
"name not a IANA svc name (i.e. a number)": {[]api.ContainerPort{{Name: "80", ContainerPort: 80, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].name", PortNameErrorMsg}, "name not a IANA svc name (i.e. a number)": {[]api.ContainerPort{{Name: "80", ContainerPort: 80, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].name", PortNameErrorMsg},
"name not unique": {[]api.ContainerPort{ "name not unique": {[]api.ContainerPort{
{Name: "abc", ContainerPort: 80, Protocol: "TCP"}, {Name: "abc", ContainerPort: 80, Protocol: "TCP"},
{Name: "abc", ContainerPort: 81, Protocol: "TCP"}, {Name: "abc", ContainerPort: 81, Protocol: "TCP"},
}, errors.ValidationErrorTypeDuplicate, "[1].name", ""}, }, validation.ErrorTypeDuplicate, "[1].name", ""},
"zero container port": {[]api.ContainerPort{{ContainerPort: 0, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].containerPort", PortRangeErrorMsg}, "zero container port": {[]api.ContainerPort{{ContainerPort: 0, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].containerPort", PortRangeErrorMsg},
"invalid container port": {[]api.ContainerPort{{ContainerPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].containerPort", PortRangeErrorMsg}, "invalid container port": {[]api.ContainerPort{{ContainerPort: 65536, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].containerPort", PortRangeErrorMsg},
"invalid host port": {[]api.ContainerPort{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].hostPort", PortRangeErrorMsg}, "invalid host port": {[]api.ContainerPort{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, validation.ErrorTypeInvalid, "[0].hostPort", PortRangeErrorMsg},
"invalid protocol case": {[]api.ContainerPort{{ContainerPort: 80, Protocol: "tcp"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol", "supported values: TCP, UDP"}, "invalid protocol case": {[]api.ContainerPort{{ContainerPort: 80, Protocol: "tcp"}}, validation.ErrorTypeNotSupported, "[0].protocol", "supported values: TCP, UDP"},
"invalid protocol": {[]api.ContainerPort{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol", "supported values: TCP, UDP"}, "invalid protocol": {[]api.ContainerPort{{ContainerPort: 80, Protocol: "ICMP"}}, validation.ErrorTypeNotSupported, "[0].protocol", "supported values: TCP, UDP"},
"protocol required": {[]api.ContainerPort{{Name: "abc", ContainerPort: 80}}, errors.ValidationErrorTypeRequired, "[0].protocol", ""}, "protocol required": {[]api.ContainerPort{{Name: "abc", ContainerPort: 80}}, validation.ErrorTypeRequired, "[0].protocol", ""},
} }
for k, v := range errorCases { for k, v := range errorCases {
errs := validatePorts(v.P) errs := validatePorts(v.P)
@@ -628,13 +627,13 @@ func TestValidatePorts(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
if errs[i].(*errors.ValidationError).Type != v.T { if errs[i].(*validation.Error).Type != v.T {
t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i])
} }
if errs[i].(*errors.ValidationError).Field != v.F { if errs[i].(*validation.Error).Field != v.F {
t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i])
} }
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*validation.Error).Detail
if detail != v.D { if detail != v.D {
t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail) t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail)
} }
@@ -773,7 +772,7 @@ func TestValidateEnv(t *testing.T) {
t.Errorf("expected failure for %s", tc.name) t.Errorf("expected failure for %s", tc.name)
} else { } else {
for i := range errs { for i := range errs {
str := errs[i].(*errors.ValidationError).Error() str := errs[i].(*validation.Error).Error()
if str != "" && str != tc.expectedError { if str != "" && str != tc.expectedError {
t.Errorf("%s: expected error detail either empty or %s, got %s", tc.name, tc.expectedError, str) t.Errorf("%s: expected error detail either empty or %s, got %s", tc.name, tc.expectedError, str)
} }
@@ -2561,7 +2560,7 @@ func TestValidateReplicationController(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*validation.Error).Field
if !strings.HasPrefix(field, "spec.template.") && if !strings.HasPrefix(field, "spec.template.") &&
field != "metadata.name" && field != "metadata.name" &&
field != "metadata.namespace" && field != "metadata.namespace" &&
@@ -2677,7 +2676,7 @@ func TestValidateNode(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*validation.Error).Field
expectedFields := map[string]bool{ expectedFields := map[string]bool{
"metadata.name": true, "metadata.name": true,
"metadata.labels": true, "metadata.labels": true,
@@ -3009,7 +3008,7 @@ func TestValidateResourceNames(t *testing.T) {
} else if len(err) == 0 && !item.success { } else if len(err) == 0 && !item.success {
t.Errorf("expected failure for input %q", item.input) t.Errorf("expected failure for input %q", item.input)
for i := range err { for i := range err {
detail := err[i].(*errors.ValidationError).Detail detail := err[i].(*validation.Error).Detail
if detail != "" && detail != qualifiedNameErrorMsg { if detail != "" && detail != qualifiedNameErrorMsg {
t.Errorf("%d: expected error detail either empty or %s, got %s", k, qualifiedNameErrorMsg, detail) t.Errorf("%d: expected error detail either empty or %s, got %s", k, qualifiedNameErrorMsg, detail)
} }
@@ -3225,7 +3224,7 @@ func TestValidateLimitRange(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*validation.Error).Detail
if detail != v.D { if detail != v.D {
t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail) t.Errorf("%s: expected error detail either empty or %s, got %s", k, v.D, detail)
} }
@@ -3330,8 +3329,8 @@ func TestValidateResourceQuota(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*validation.Error).Field
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*validation.Error).Detail
if field != "metadata.name" && field != "metadata.namespace" && !api.IsStandardResourceName(field) { if field != "metadata.name" && field != "metadata.namespace" && !api.IsStandardResourceName(field) {
t.Errorf("%s: missing prefix for: %v", k, field) t.Errorf("%s: missing prefix for: %v", k, field)
} }
@@ -3765,7 +3764,7 @@ func TestValidateEndpoints(t *testing.T) {
errorCases := map[string]struct { errorCases := map[string]struct {
endpoints api.Endpoints endpoints api.Endpoints
errorType fielderrors.ValidationErrorType errorType validation.ErrorType
errorDetail string errorDetail string
}{ }{
"missing namespace": { "missing namespace": {
@@ -3938,7 +3937,7 @@ func TestValidateEndpoints(t *testing.T) {
} }
for k, v := range errorCases { for k, v := range errorCases {
if errs := ValidateEndpoints(&v.endpoints); len(errs) == 0 || errs[0].(*errors.ValidationError).Type != v.errorType || !strings.Contains(errs[0].(*errors.ValidationError).Detail, v.errorDetail) { if errs := ValidateEndpoints(&v.endpoints); len(errs) == 0 || errs[0].(*validation.Error).Type != v.errorType || !strings.Contains(errs[0].(*validation.Error).Detail, v.errorDetail) {
t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs) t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs)
} }
} }
@@ -4003,7 +4002,7 @@ func TestValidateSecurityContext(t *testing.T) {
errorCases := map[string]struct { errorCases := map[string]struct {
sc *api.SecurityContext sc *api.SecurityContext
errorType fielderrors.ValidationErrorType errorType validation.ErrorType
errorDetail string errorDetail string
}{ }{
"request privileged when capabilities forbids": { "request privileged when capabilities forbids": {
@@ -4018,7 +4017,7 @@ func TestValidateSecurityContext(t *testing.T) {
}, },
} }
for k, v := range errorCases { for k, v := range errorCases {
if errs := ValidateSecurityContext(v.sc); len(errs) == 0 || errs[0].(*errors.ValidationError).Type != v.errorType || errs[0].(*errors.ValidationError).Detail != v.errorDetail { if errs := ValidateSecurityContext(v.sc); len(errs) == 0 || errs[0].(*validation.Error).Type != v.errorType || errs[0].(*validation.Error).Detail != v.errorDetail {
t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs) t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs)
} }
} }

View File

@@ -27,11 +27,9 @@ import (
apivalidation "k8s.io/kubernetes/pkg/api/validation" apivalidation "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
errs "k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/validation"
utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// ValidateHorizontalPodAutoscaler can be used to check whether the given autoscaler name is valid. // ValidateHorizontalPodAutoscaler can be used to check whether the given autoscaler name is valid.
@@ -41,66 +39,66 @@ func ValidateHorizontalPodAutoscalerName(name string, prefix bool) (bool, string
return apivalidation.ValidateReplicationControllerName(name, prefix) return apivalidation.ValidateReplicationControllerName(name, prefix)
} }
func validateHorizontalPodAutoscalerSpec(autoscaler extensions.HorizontalPodAutoscalerSpec) errs.ValidationErrorList { func validateHorizontalPodAutoscalerSpec(autoscaler extensions.HorizontalPodAutoscalerSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if autoscaler.MinReplicas != nil && *autoscaler.MinReplicas < 1 { if autoscaler.MinReplicas != nil && *autoscaler.MinReplicas < 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("minReplicas", autoscaler.MinReplicas, `must be bigger or equal to 1`)) allErrs = append(allErrs, validation.NewFieldInvalid("minReplicas", autoscaler.MinReplicas, `must be bigger or equal to 1`))
} }
if autoscaler.MaxReplicas < 1 { if autoscaler.MaxReplicas < 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to 1`)) allErrs = append(allErrs, validation.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to 1`))
} }
if autoscaler.MinReplicas != nil && autoscaler.MaxReplicas < *autoscaler.MinReplicas { if autoscaler.MinReplicas != nil && autoscaler.MaxReplicas < *autoscaler.MinReplicas {
allErrs = append(allErrs, errs.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to minReplicas`)) allErrs = append(allErrs, validation.NewFieldInvalid("maxReplicas", autoscaler.MaxReplicas, `must be bigger or equal to minReplicas`))
} }
if autoscaler.CPUUtilization != nil && autoscaler.CPUUtilization.TargetPercentage < 1 { if autoscaler.CPUUtilization != nil && autoscaler.CPUUtilization.TargetPercentage < 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("cpuUtilization.targetPercentage", autoscaler.CPUUtilization.TargetPercentage, `must be bigger or equal to 1`)) allErrs = append(allErrs, validation.NewFieldInvalid("cpuUtilization.targetPercentage", autoscaler.CPUUtilization.TargetPercentage, `must be bigger or equal to 1`))
} }
if refErrs := ValidateSubresourceReference(autoscaler.ScaleRef); len(refErrs) > 0 { if refErrs := ValidateSubresourceReference(autoscaler.ScaleRef); len(refErrs) > 0 {
allErrs = append(allErrs, refErrs.Prefix("scaleRef")...) allErrs = append(allErrs, refErrs.Prefix("scaleRef")...)
} else if autoscaler.ScaleRef.Subresource != "scale" { } else if autoscaler.ScaleRef.Subresource != "scale" {
allErrs = append(allErrs, errs.NewFieldValueNotSupported("scaleRef.subresource", autoscaler.ScaleRef.Subresource, []string{"scale"})) allErrs = append(allErrs, validation.NewFieldValueNotSupported("scaleRef.subresource", autoscaler.ScaleRef.Subresource, []string{"scale"}))
} }
return allErrs return allErrs
} }
func ValidateSubresourceReference(ref extensions.SubresourceReference) errs.ValidationErrorList { func ValidateSubresourceReference(ref extensions.SubresourceReference) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if len(ref.Kind) == 0 { if len(ref.Kind) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("kind")) allErrs = append(allErrs, validation.NewFieldRequired("kind"))
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Kind); !ok { } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Kind); !ok {
allErrs = append(allErrs, errs.NewFieldInvalid("kind", ref.Kind, msg)) allErrs = append(allErrs, validation.NewFieldInvalid("kind", ref.Kind, msg))
} }
if len(ref.Name) == 0 { if len(ref.Name) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("name")) allErrs = append(allErrs, validation.NewFieldRequired("name"))
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Name); !ok { } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Name); !ok {
allErrs = append(allErrs, errs.NewFieldInvalid("name", ref.Name, msg)) allErrs = append(allErrs, validation.NewFieldInvalid("name", ref.Name, msg))
} }
if len(ref.Subresource) == 0 { if len(ref.Subresource) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("subresource")) allErrs = append(allErrs, validation.NewFieldRequired("subresource"))
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Subresource); !ok { } else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Subresource); !ok {
allErrs = append(allErrs, errs.NewFieldInvalid("subresource", ref.Subresource, msg)) allErrs = append(allErrs, validation.NewFieldInvalid("subresource", ref.Subresource, msg))
} }
return allErrs return allErrs
} }
func ValidateHorizontalPodAutoscaler(autoscaler *extensions.HorizontalPodAutoscaler) errs.ValidationErrorList { func ValidateHorizontalPodAutoscaler(autoscaler *extensions.HorizontalPodAutoscaler) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&autoscaler.ObjectMeta, true, ValidateHorizontalPodAutoscalerName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&autoscaler.ObjectMeta, true, ValidateHorizontalPodAutoscalerName).Prefix("metadata")...)
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(autoscaler.Spec)...) allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(autoscaler.Spec)...)
return allErrs return allErrs
} }
func ValidateHorizontalPodAutoscalerUpdate(newAutoscler, oldAutoscaler *extensions.HorizontalPodAutoscaler) errs.ValidationErrorList { func ValidateHorizontalPodAutoscalerUpdate(newAutoscler, oldAutoscaler *extensions.HorizontalPodAutoscaler) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&newAutoscler.ObjectMeta, &oldAutoscaler.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&newAutoscler.ObjectMeta, &oldAutoscaler.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(newAutoscler.Spec)...) allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(newAutoscler.Spec)...)
return allErrs return allErrs
} }
func ValidateHorizontalPodAutoscalerStatusUpdate(controller, oldController *extensions.HorizontalPodAutoscaler) errs.ValidationErrorList { func ValidateHorizontalPodAutoscalerStatusUpdate(controller, oldController *extensions.HorizontalPodAutoscaler) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...)
status := controller.Status status := controller.Status
@@ -109,8 +107,8 @@ func ValidateHorizontalPodAutoscalerStatusUpdate(controller, oldController *exte
return allErrs return allErrs
} }
func ValidateThirdPartyResourceUpdate(update, old *extensions.ThirdPartyResource) errs.ValidationErrorList { func ValidateThirdPartyResourceUpdate(update, old *extensions.ThirdPartyResource) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateThirdPartyResource(update)...) allErrs = append(allErrs, ValidateThirdPartyResource(update)...)
return allErrs return allErrs
@@ -120,18 +118,18 @@ func ValidateThirdPartyResourceName(name string, prefix bool) (bool, string) {
return apivalidation.NameIsDNSSubdomain(name, prefix) return apivalidation.NameIsDNSSubdomain(name, prefix)
} }
func ValidateThirdPartyResource(obj *extensions.ThirdPartyResource) errs.ValidationErrorList { func ValidateThirdPartyResource(obj *extensions.ThirdPartyResource) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateThirdPartyResourceName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateThirdPartyResourceName).Prefix("metadata")...)
versions := sets.String{} versions := sets.String{}
for ix := range obj.Versions { for ix := range obj.Versions {
version := &obj.Versions[ix] version := &obj.Versions[ix]
if len(version.Name) == 0 { if len(version.Name) == 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("name", version, "name can not be empty")) allErrs = append(allErrs, validation.NewFieldInvalid("name", version, "name can not be empty"))
} }
if versions.Has(version.Name) { if versions.Has(version.Name) {
allErrs = append(allErrs, errs.NewFieldDuplicate("version", version)) allErrs = append(allErrs, validation.NewFieldDuplicate("version", version))
} }
versions.Insert(version.Name) versions.Insert(version.Name)
} }
@@ -139,16 +137,16 @@ func ValidateThirdPartyResource(obj *extensions.ThirdPartyResource) errs.Validat
} }
// ValidateDaemonSet tests if required fields in the DaemonSet are set. // ValidateDaemonSet tests if required fields in the DaemonSet are set.
func ValidateDaemonSet(controller *extensions.DaemonSet) errs.ValidationErrorList { func ValidateDaemonSet(controller *extensions.DaemonSet) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&controller.ObjectMeta, true, ValidateDaemonSetName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&controller.ObjectMeta, true, ValidateDaemonSetName).Prefix("metadata")...)
allErrs = append(allErrs, ValidateDaemonSetSpec(&controller.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateDaemonSetSpec(&controller.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
// ValidateDaemonSetUpdate tests if required fields in the DaemonSet are set. // ValidateDaemonSetUpdate tests if required fields in the DaemonSet are set.
func ValidateDaemonSetUpdate(controller, oldController *extensions.DaemonSet) errs.ValidationErrorList { func ValidateDaemonSetUpdate(controller, oldController *extensions.DaemonSet) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateDaemonSetSpec(&controller.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateDaemonSetSpec(&controller.Spec).Prefix("spec")...)
allErrs = append(allErrs, ValidateDaemonSetTemplateUpdate(controller.Spec.Template, oldController.Spec.Template).Prefix("spec.template")...) allErrs = append(allErrs, ValidateDaemonSetTemplateUpdate(controller.Spec.Template, oldController.Spec.Template).Prefix("spec.template")...)
@@ -156,8 +154,8 @@ func ValidateDaemonSetUpdate(controller, oldController *extensions.DaemonSet) er
} }
// validateDaemonSetStatus validates a DaemonSetStatus // validateDaemonSetStatus validates a DaemonSetStatus
func validateDaemonSetStatus(status *extensions.DaemonSetStatus) errs.ValidationErrorList { func validateDaemonSetStatus(status *extensions.DaemonSetStatus) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.CurrentNumberScheduled), "currentNumberScheduled")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.CurrentNumberScheduled), "currentNumberScheduled")...)
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.NumberMisscheduled), "numberMisscheduled")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.NumberMisscheduled), "numberMisscheduled")...)
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.DesiredNumberScheduled), "desiredNumberScheduled")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.DesiredNumberScheduled), "desiredNumberScheduled")...)
@@ -165,16 +163,16 @@ func validateDaemonSetStatus(status *extensions.DaemonSetStatus) errs.Validation
} }
// ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section // ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section
func ValidateDaemonSetStatusUpdate(controller, oldController *extensions.DaemonSet) errs.ValidationErrorList { func ValidateDaemonSetStatusUpdate(controller, oldController *extensions.DaemonSet) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, validateDaemonSetStatus(&controller.Status)...) allErrs = append(allErrs, validateDaemonSetStatus(&controller.Status)...)
return allErrs return allErrs
} }
// ValidateDaemonSetTemplateUpdate tests that certain fields in the daemon set's pod template are not updated. // ValidateDaemonSetTemplateUpdate tests that certain fields in the daemon set's pod template are not updated.
func ValidateDaemonSetTemplateUpdate(podTemplate, oldPodTemplate *api.PodTemplateSpec) errs.ValidationErrorList { func ValidateDaemonSetTemplateUpdate(podTemplate, oldPodTemplate *api.PodTemplateSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
podSpec := podTemplate.Spec podSpec := podTemplate.Spec
// podTemplate.Spec is not a pointer, so we can modify NodeSelector and NodeName directly. // podTemplate.Spec is not a pointer, so we can modify NodeSelector and NodeName directly.
podSpec.NodeSelector = oldPodTemplate.Spec.NodeSelector podSpec.NodeSelector = oldPodTemplate.Spec.NodeSelector
@@ -182,25 +180,25 @@ func ValidateDaemonSetTemplateUpdate(podTemplate, oldPodTemplate *api.PodTemplat
// In particular, we do not allow updates to container images at this point. // In particular, we do not allow updates to container images at this point.
if !api.Semantic.DeepEqual(oldPodTemplate.Spec, podSpec) { if !api.Semantic.DeepEqual(oldPodTemplate.Spec, podSpec) {
// TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff // TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff
allErrs = append(allErrs, errs.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.NewFieldInvalid("spec", "content of spec is not printed out, please refer to the \"details\"", "may not update fields other than spec.nodeSelector"))
} }
return allErrs return allErrs
} }
// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set. // ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set.
func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec) errs.ValidationErrorList { func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, ValidatePodSelector(spec.Selector)...) allErrs = append(allErrs, ValidatePodSelector(spec.Selector)...)
if spec.Template == nil { if spec.Template == nil {
allErrs = append(allErrs, errs.NewFieldRequired("template")) allErrs = append(allErrs, validation.NewFieldRequired("template"))
return allErrs return allErrs
} }
selector, err := extensions.PodSelectorAsSelector(spec.Selector) selector, err := extensions.PodSelectorAsSelector(spec.Selector)
if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) { if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) {
allErrs = append(allErrs, errs.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) allErrs = append(allErrs, validation.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template"))
} }
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template).Prefix("template")...) allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template).Prefix("template")...)
@@ -208,7 +206,7 @@ func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec) errs.ValidationErrorL
allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes).Prefix("template.spec.volumes")...) allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes).Prefix("template.spec.volumes")...)
// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). // RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways {
allErrs = append(allErrs, errs.NewFieldValueNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) allErrs = append(allErrs, validation.NewFieldValueNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)}))
} }
return allErrs return allErrs
@@ -226,11 +224,11 @@ func ValidateDeploymentName(name string, prefix bool) (bool, string) {
return apivalidation.NameIsDNSSubdomain(name, prefix) return apivalidation.NameIsDNSSubdomain(name, prefix)
} }
func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fieldName string) errs.ValidationErrorList { func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fieldName string) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if intOrPercent.Type == intstr.String { if intOrPercent.Type == intstr.String {
if !validation.IsValidPercent(intOrPercent.StrVal) { if !validation.IsValidPercent(intOrPercent.StrVal) {
allErrs = append(allErrs, errs.NewFieldInvalid(fieldName, intOrPercent, "value should be int(5) or percentage(5%)")) allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, intOrPercent, "value should be int(5) or percentage(5%)"))
} }
} else if intOrPercent.Type == intstr.Int { } else if intOrPercent.Type == intstr.Int {
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(intOrPercent.IntVal), fieldName)...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(intOrPercent.IntVal), fieldName)...)
@@ -254,23 +252,23 @@ func getIntOrPercentValue(intOrStringValue intstr.IntOrString) int {
return intOrStringValue.IntVal return intOrStringValue.IntVal
} }
func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fieldName string) errs.ValidationErrorList { func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fieldName string) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
value, isPercent := getPercentValue(intOrStringValue) value, isPercent := getPercentValue(intOrStringValue)
if !isPercent || value <= 100 { if !isPercent || value <= 100 {
return nil return nil
} }
allErrs = append(allErrs, errs.NewFieldInvalid(fieldName, intOrStringValue, "should not be more than 100%")) allErrs = append(allErrs, validation.NewFieldInvalid(fieldName, intOrStringValue, "should not be more than 100%"))
return allErrs return allErrs
} }
func ValidateRollingUpdateDeployment(rollingUpdate *extensions.RollingUpdateDeployment, fieldName string) errs.ValidationErrorList { func ValidateRollingUpdateDeployment(rollingUpdate *extensions.RollingUpdateDeployment, fieldName string) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fieldName+"maxUnavailable")...) allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fieldName+"maxUnavailable")...)
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fieldName+".maxSurge")...) allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fieldName+".maxSurge")...)
if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 && getIntOrPercentValue(rollingUpdate.MaxSurge) == 0 { if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 && getIntOrPercentValue(rollingUpdate.MaxSurge) == 0 {
// Both MaxSurge and MaxUnavailable cannot be zero. // Both MaxSurge and MaxUnavailable cannot be zero.
allErrs = append(allErrs, errs.NewFieldInvalid(fieldName+".maxUnavailable", rollingUpdate.MaxUnavailable, "cannot be 0 when maxSurge is 0 as well")) allErrs = append(allErrs, validation.NewFieldInvalid(fieldName+".maxUnavailable", rollingUpdate.MaxUnavailable, "cannot be 0 when maxSurge is 0 as well"))
} }
// Validate that MaxUnavailable is not more than 100%. // Validate that MaxUnavailable is not more than 100%.
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fieldName+".maxUnavailable")...) allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fieldName+".maxUnavailable")...)
@@ -278,14 +276,14 @@ func ValidateRollingUpdateDeployment(rollingUpdate *extensions.RollingUpdateDepl
return allErrs return allErrs
} }
func ValidateDeploymentStrategy(strategy *extensions.DeploymentStrategy, fieldName string) errs.ValidationErrorList { func ValidateDeploymentStrategy(strategy *extensions.DeploymentStrategy, fieldName string) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if strategy.RollingUpdate == nil { if strategy.RollingUpdate == nil {
return allErrs return allErrs
} }
switch strategy.Type { switch strategy.Type {
case extensions.RecreateDeploymentStrategyType: case extensions.RecreateDeploymentStrategyType:
allErrs = append(allErrs, errs.NewFieldForbidden("rollingUpdate", "rollingUpdate should be nil when strategy type is "+extensions.RecreateDeploymentStrategyType)) allErrs = append(allErrs, validation.NewFieldForbidden("rollingUpdate", "rollingUpdate should be nil when strategy type is "+extensions.RecreateDeploymentStrategyType))
case extensions.RollingUpdateDeploymentStrategyType: case extensions.RollingUpdateDeploymentStrategyType:
allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, "rollingUpdate")...) allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, "rollingUpdate")...)
} }
@@ -293,8 +291,8 @@ func ValidateDeploymentStrategy(strategy *extensions.DeploymentStrategy, fieldNa
} }
// Validates given deployment spec. // Validates given deployment spec.
func ValidateDeploymentSpec(spec *extensions.DeploymentSpec) errs.ValidationErrorList { func ValidateDeploymentSpec(spec *extensions.DeploymentSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateNonEmptySelector(spec.Selector, "selector")...) allErrs = append(allErrs, apivalidation.ValidateNonEmptySelector(spec.Selector, "selector")...)
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(spec.Replicas), "replicas")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(spec.Replicas), "replicas")...)
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpecForRC(&spec.Template, spec.Selector, spec.Replicas, "template")...) allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpecForRC(&spec.Template, spec.Selector, spec.Replicas, "template")...)
@@ -303,42 +301,42 @@ func ValidateDeploymentSpec(spec *extensions.DeploymentSpec) errs.ValidationErro
return allErrs return allErrs
} }
func ValidateDeploymentUpdate(update, old *extensions.Deployment) errs.ValidationErrorList { func ValidateDeploymentUpdate(update, old *extensions.Deployment) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateDeploymentSpec(&update.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateDeploymentSpec(&update.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
func ValidateDeployment(obj *extensions.Deployment) errs.ValidationErrorList { func ValidateDeployment(obj *extensions.Deployment) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateDeploymentName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateDeploymentName).Prefix("metadata")...)
allErrs = append(allErrs, ValidateDeploymentSpec(&obj.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateDeploymentSpec(&obj.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
func ValidateThirdPartyResourceDataUpdate(update, old *extensions.ThirdPartyResourceData) errs.ValidationErrorList { func ValidateThirdPartyResourceDataUpdate(update, old *extensions.ThirdPartyResourceData) validation.ErrorList {
return ValidateThirdPartyResourceData(update) return ValidateThirdPartyResourceData(update)
} }
func ValidateThirdPartyResourceData(obj *extensions.ThirdPartyResourceData) errs.ValidationErrorList { func ValidateThirdPartyResourceData(obj *extensions.ThirdPartyResourceData) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if len(obj.Name) == 0 { if len(obj.Name) == 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("name", obj.Name, "name must be non-empty")) allErrs = append(allErrs, validation.NewFieldInvalid("name", obj.Name, "name must be non-empty"))
} }
return allErrs return allErrs
} }
func ValidateJob(job *extensions.Job) errs.ValidationErrorList { func ValidateJob(job *extensions.Job) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
// Jobs and rcs have the same name validation // Jobs and rcs have the same name validation
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&job.ObjectMeta, true, apivalidation.ValidateReplicationControllerName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&job.ObjectMeta, true, apivalidation.ValidateReplicationControllerName).Prefix("metadata")...)
allErrs = append(allErrs, ValidateJobSpec(&job.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateJobSpec(&job.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
func ValidateJobSpec(spec *extensions.JobSpec) errs.ValidationErrorList { func ValidateJobSpec(spec *extensions.JobSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if spec.Parallelism != nil { if spec.Parallelism != nil {
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Parallelism), "parallelism")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Parallelism), "parallelism")...)
@@ -347,7 +345,7 @@ func ValidateJobSpec(spec *extensions.JobSpec) errs.ValidationErrorList {
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Completions), "completions")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Completions), "completions")...)
} }
if spec.Selector == nil { if spec.Selector == nil {
allErrs = append(allErrs, errs.NewFieldRequired("selector")) allErrs = append(allErrs, validation.NewFieldRequired("selector"))
} else { } else {
allErrs = append(allErrs, ValidatePodSelector(spec.Selector).Prefix("selector")...) allErrs = append(allErrs, ValidatePodSelector(spec.Selector).Prefix("selector")...)
} }
@@ -355,43 +353,43 @@ func ValidateJobSpec(spec *extensions.JobSpec) errs.ValidationErrorList {
if selector, err := extensions.PodSelectorAsSelector(spec.Selector); err == nil { if selector, err := extensions.PodSelectorAsSelector(spec.Selector); err == nil {
labels := labels.Set(spec.Template.Labels) labels := labels.Set(spec.Template.Labels)
if !selector.Matches(labels) { if !selector.Matches(labels) {
allErrs = append(allErrs, errs.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) allErrs = append(allErrs, validation.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template"))
} }
} }
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template).Prefix("template")...) allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template).Prefix("template")...)
if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure &&
spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { spec.Template.Spec.RestartPolicy != api.RestartPolicyNever {
allErrs = append(allErrs, errs.NewFieldValueNotSupported("template.spec.restartPolicy", allErrs = append(allErrs, validation.NewFieldValueNotSupported("template.spec.restartPolicy",
spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)}))
} }
return allErrs return allErrs
} }
func ValidateJobStatus(status *extensions.JobStatus) errs.ValidationErrorList { func ValidateJobStatus(status *extensions.JobStatus) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Active), "active")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Active), "active")...)
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Succeeded), "succeeded")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Succeeded), "succeeded")...)
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Failed), "failed")...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Failed), "failed")...)
return allErrs return allErrs
} }
func ValidateJobUpdate(job, oldJob *extensions.Job) errs.ValidationErrorList { func ValidateJobUpdate(job, oldJob *extensions.Job) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateJobSpecUpdate(job.Spec, oldJob.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateJobSpecUpdate(job.Spec, oldJob.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
func ValidateJobUpdateStatus(job, oldJob *extensions.Job) errs.ValidationErrorList { func ValidateJobUpdateStatus(job, oldJob *extensions.Job) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateJobStatusUpdate(job.Status, oldJob.Status).Prefix("status")...) allErrs = append(allErrs, ValidateJobStatusUpdate(job.Status, oldJob.Status).Prefix("status")...)
return allErrs return allErrs
} }
func ValidateJobSpecUpdate(spec, oldSpec extensions.JobSpec) errs.ValidationErrorList { func ValidateJobSpecUpdate(spec, oldSpec extensions.JobSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, ValidateJobSpec(&spec)...) allErrs = append(allErrs, ValidateJobSpec(&spec)...)
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Completions, oldSpec.Completions, "completions")...) allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Completions, oldSpec.Completions, "completions")...)
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Selector, oldSpec.Selector, "selector")...) allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Selector, oldSpec.Selector, "selector")...)
@@ -399,15 +397,15 @@ func ValidateJobSpecUpdate(spec, oldSpec extensions.JobSpec) errs.ValidationErro
return allErrs return allErrs
} }
func ValidateJobStatusUpdate(status, oldStatus extensions.JobStatus) errs.ValidationErrorList { func ValidateJobStatusUpdate(status, oldStatus extensions.JobStatus) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, ValidateJobStatus(&status)...) allErrs = append(allErrs, ValidateJobStatus(&status)...)
return allErrs return allErrs
} }
// ValidateIngress tests if required fields in the Ingress are set. // ValidateIngress tests if required fields in the Ingress are set.
func ValidateIngress(ingress *extensions.Ingress) errs.ValidationErrorList { func ValidateIngress(ingress *extensions.Ingress) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName).Prefix("metadata")...)
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...)
return allErrs return allErrs
@@ -419,13 +417,13 @@ func ValidateIngressName(name string, prefix bool) (bool, string) {
} }
// ValidateIngressSpec tests if required fields in the IngressSpec are set. // ValidateIngressSpec tests if required fields in the IngressSpec are set.
func ValidateIngressSpec(spec *extensions.IngressSpec) errs.ValidationErrorList { func ValidateIngressSpec(spec *extensions.IngressSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
// TODO: Is a default backend mandatory? // TODO: Is a default backend mandatory?
if spec.Backend != nil { if spec.Backend != nil {
allErrs = append(allErrs, validateIngressBackend(spec.Backend).Prefix("backend")...) allErrs = append(allErrs, validateIngressBackend(spec.Backend).Prefix("backend")...)
} else if len(spec.Rules) == 0 { } else if len(spec.Rules) == 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("rules", spec.Rules, "Either a default backend or a set of host rules are required for ingress.")) allErrs = append(allErrs, validation.NewFieldInvalid("rules", spec.Rules, "Either a default backend or a set of host rules are required for ingress."))
} }
if len(spec.Rules) > 0 { if len(spec.Rules) > 0 {
allErrs = append(allErrs, validateIngressRules(spec.Rules).Prefix("rules")...) allErrs = append(allErrs, validateIngressRules(spec.Rules).Prefix("rules")...)
@@ -434,35 +432,35 @@ func ValidateIngressSpec(spec *extensions.IngressSpec) errs.ValidationErrorList
} }
// ValidateIngressUpdate tests if required fields in the Ingress are set. // ValidateIngressUpdate tests if required fields in the Ingress are set.
func ValidateIngressUpdate(ingress, oldIngress *extensions.Ingress) errs.ValidationErrorList { func ValidateIngressUpdate(ingress, oldIngress *extensions.Ingress) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...) allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...)
return allErrs return allErrs
} }
// ValidateIngressStatusUpdate tests if required fields in the Ingress are set when updating status. // ValidateIngressStatusUpdate tests if required fields in the Ingress are set when updating status.
func ValidateIngressStatusUpdate(ingress, oldIngress *extensions.Ingress) errs.ValidationErrorList { func ValidateIngressStatusUpdate(ingress, oldIngress *extensions.Ingress) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta).Prefix("metadata")...)
allErrs = append(allErrs, apivalidation.ValidateLoadBalancerStatus(&ingress.Status.LoadBalancer).Prefix("status.loadBalancer")...) allErrs = append(allErrs, apivalidation.ValidateLoadBalancerStatus(&ingress.Status.LoadBalancer).Prefix("status.loadBalancer")...)
return allErrs return allErrs
} }
func validateIngressRules(IngressRules []extensions.IngressRule) errs.ValidationErrorList { func validateIngressRules(IngressRules []extensions.IngressRule) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if len(IngressRules) == 0 { if len(IngressRules) == 0 {
return append(allErrs, errs.NewFieldRequired("IngressRules")) return append(allErrs, validation.NewFieldRequired("IngressRules"))
} }
for _, ih := range IngressRules { for _, ih := range IngressRules {
if len(ih.Host) > 0 { if len(ih.Host) > 0 {
// TODO: Ports and ips are allowed in the host part of a url // TODO: Ports and ips are allowed in the host part of a url
// according to RFC 3986, consider allowing them. // according to RFC 3986, consider allowing them.
if valid, errMsg := apivalidation.NameIsDNSSubdomain(ih.Host, false); !valid { if valid, errMsg := apivalidation.NameIsDNSSubdomain(ih.Host, false); !valid {
allErrs = append(allErrs, errs.NewFieldInvalid("host", ih.Host, errMsg)) allErrs = append(allErrs, validation.NewFieldInvalid("host", ih.Host, errMsg))
} }
if isIP := (net.ParseIP(ih.Host) != nil); isIP { if isIP := (net.ParseIP(ih.Host) != nil); isIP {
allErrs = append(allErrs, errs.NewFieldInvalid("host", ih.Host, "Host must be a DNS name, not ip address")) allErrs = append(allErrs, validation.NewFieldInvalid("host", ih.Host, "Host must be a DNS name, not ip address"))
} }
} }
allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue).Prefix("ingressRule")...) allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue).Prefix("ingressRule")...)
@@ -470,23 +468,23 @@ func validateIngressRules(IngressRules []extensions.IngressRule) errs.Validation
return allErrs return allErrs
} }
func validateIngressRuleValue(ingressRule *extensions.IngressRuleValue) errs.ValidationErrorList { func validateIngressRuleValue(ingressRule *extensions.IngressRuleValue) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if ingressRule.HTTP != nil { if ingressRule.HTTP != nil {
allErrs = append(allErrs, validateHTTPIngressRuleValue(ingressRule.HTTP).Prefix("http")...) allErrs = append(allErrs, validateHTTPIngressRuleValue(ingressRule.HTTP).Prefix("http")...)
} }
return allErrs return allErrs
} }
func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRuleValue) errs.ValidationErrorList { func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRuleValue) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if len(httpIngressRuleValue.Paths) == 0 { if len(httpIngressRuleValue.Paths) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("paths")) allErrs = append(allErrs, validation.NewFieldRequired("paths"))
} }
for _, rule := range httpIngressRuleValue.Paths { for _, rule := range httpIngressRuleValue.Paths {
if len(rule.Path) > 0 { if len(rule.Path) > 0 {
if !strings.HasPrefix(rule.Path, "/") { if !strings.HasPrefix(rule.Path, "/") {
allErrs = append(allErrs, errs.NewFieldInvalid("path", rule.Path, "path must begin with /")) allErrs = append(allErrs, validation.NewFieldInvalid("path", rule.Path, "path must begin with /"))
} }
// TODO: More draconian path regex validation. // TODO: More draconian path regex validation.
// Path must be a valid regex. This is the basic requirement. // Path must be a valid regex. This is the basic requirement.
@@ -499,7 +497,7 @@ func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRu
// the user is confusing url regexes with path regexes. // the user is confusing url regexes with path regexes.
_, err := regexp.CompilePOSIX(rule.Path) _, err := regexp.CompilePOSIX(rule.Path)
if err != nil { if err != nil {
allErrs = append(allErrs, errs.NewFieldInvalid("path", rule.Path, "httpIngressRuleValue.path must be a valid regex.")) allErrs = append(allErrs, validation.NewFieldInvalid("path", rule.Path, "httpIngressRuleValue.path must be a valid regex."))
} }
} }
allErrs = append(allErrs, validateIngressBackend(&rule.Backend).Prefix("backend")...) allErrs = append(allErrs, validateIngressBackend(&rule.Backend).Prefix("backend")...)
@@ -508,67 +506,67 @@ func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRu
} }
// validateIngressBackend tests if a given backend is valid. // validateIngressBackend tests if a given backend is valid.
func validateIngressBackend(backend *extensions.IngressBackend) errs.ValidationErrorList { func validateIngressBackend(backend *extensions.IngressBackend) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
// All backends must reference a single local service by name, and a single service port by name or number. // All backends must reference a single local service by name, and a single service port by name or number.
if len(backend.ServiceName) == 0 { if len(backend.ServiceName) == 0 {
return append(allErrs, errs.NewFieldRequired("serviceName")) return append(allErrs, validation.NewFieldRequired("serviceName"))
} else if ok, errMsg := apivalidation.ValidateServiceName(backend.ServiceName, false); !ok { } else if ok, errMsg := apivalidation.ValidateServiceName(backend.ServiceName, false); !ok {
allErrs = append(allErrs, errs.NewFieldInvalid("serviceName", backend.ServiceName, errMsg)) allErrs = append(allErrs, validation.NewFieldInvalid("serviceName", backend.ServiceName, errMsg))
} }
if backend.ServicePort.Type == intstr.String { if backend.ServicePort.Type == intstr.String {
if !utilvalidation.IsDNS1123Label(backend.ServicePort.StrVal) { if !validation.IsDNS1123Label(backend.ServicePort.StrVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.DNS1123LabelErrorMsg)) allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.DNS1123LabelErrorMsg))
} }
if !utilvalidation.IsValidPortName(backend.ServicePort.StrVal) { if !validation.IsValidPortName(backend.ServicePort.StrVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.PortNameErrorMsg)) allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort.StrVal, apivalidation.PortNameErrorMsg))
} }
} else if !utilvalidation.IsValidPortNum(backend.ServicePort.IntVal) { } else if !validation.IsValidPortNum(backend.ServicePort.IntVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("servicePort", backend.ServicePort, apivalidation.PortRangeErrorMsg)) allErrs = append(allErrs, validation.NewFieldInvalid("servicePort", backend.ServicePort, apivalidation.PortRangeErrorMsg))
} }
return allErrs return allErrs
} }
func validateClusterAutoscalerSpec(spec extensions.ClusterAutoscalerSpec) errs.ValidationErrorList { func validateClusterAutoscalerSpec(spec extensions.ClusterAutoscalerSpec) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if spec.MinNodes < 0 { if spec.MinNodes < 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("minNodes", spec.MinNodes, `must be non-negative`)) allErrs = append(allErrs, validation.NewFieldInvalid("minNodes", spec.MinNodes, `must be non-negative`))
} }
if spec.MaxNodes < spec.MinNodes { if spec.MaxNodes < spec.MinNodes {
allErrs = append(allErrs, errs.NewFieldInvalid("maxNodes", spec.MaxNodes, `must be bigger or equal to minNodes`)) allErrs = append(allErrs, validation.NewFieldInvalid("maxNodes", spec.MaxNodes, `must be bigger or equal to minNodes`))
} }
if len(spec.TargetUtilization) == 0 { if len(spec.TargetUtilization) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("targetUtilization")) allErrs = append(allErrs, validation.NewFieldRequired("targetUtilization"))
} }
for _, target := range spec.TargetUtilization { for _, target := range spec.TargetUtilization {
if len(target.Resource) == 0 { if len(target.Resource) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("targetUtilization.resource")) allErrs = append(allErrs, validation.NewFieldRequired("targetUtilization.resource"))
} }
if target.Value <= 0 { if target.Value <= 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("targetUtilization.value", target.Value, "must be greater than 0")) allErrs = append(allErrs, validation.NewFieldInvalid("targetUtilization.value", target.Value, "must be greater than 0"))
} }
if target.Value > 1 { if target.Value > 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("targetUtilization.value", target.Value, "must be less or equal 1")) allErrs = append(allErrs, validation.NewFieldInvalid("targetUtilization.value", target.Value, "must be less or equal 1"))
} }
} }
return allErrs return allErrs
} }
func ValidateClusterAutoscaler(autoscaler *extensions.ClusterAutoscaler) errs.ValidationErrorList { func ValidateClusterAutoscaler(autoscaler *extensions.ClusterAutoscaler) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if autoscaler.Name != "ClusterAutoscaler" { if autoscaler.Name != "ClusterAutoscaler" {
allErrs = append(allErrs, errs.NewFieldInvalid("name", autoscaler.Name, `name must be ClusterAutoscaler`)) allErrs = append(allErrs, validation.NewFieldInvalid("name", autoscaler.Name, `name must be ClusterAutoscaler`))
} }
if autoscaler.Namespace != api.NamespaceDefault { if autoscaler.Namespace != api.NamespaceDefault {
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", autoscaler.Namespace, `namespace must be default`)) allErrs = append(allErrs, validation.NewFieldInvalid("namespace", autoscaler.Namespace, `namespace must be default`))
} }
allErrs = append(allErrs, validateClusterAutoscalerSpec(autoscaler.Spec)...) allErrs = append(allErrs, validateClusterAutoscalerSpec(autoscaler.Spec)...)
return allErrs return allErrs
} }
func ValidatePodSelector(ps *extensions.PodSelector) errs.ValidationErrorList { func ValidatePodSelector(ps *extensions.PodSelector) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
if ps == nil { if ps == nil {
return allErrs return allErrs
} }
@@ -579,30 +577,30 @@ func ValidatePodSelector(ps *extensions.PodSelector) errs.ValidationErrorList {
return allErrs return allErrs
} }
func ValidatePodSelectorRequirement(sr extensions.PodSelectorRequirement) errs.ValidationErrorList { func ValidatePodSelectorRequirement(sr extensions.PodSelectorRequirement) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
switch sr.Operator { switch sr.Operator {
case extensions.PodSelectorOpIn, extensions.PodSelectorOpNotIn: case extensions.PodSelectorOpIn, extensions.PodSelectorOpNotIn:
if len(sr.Values) == 0 { if len(sr.Values) == 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("values", sr.Values, "must be non-empty when operator is In or NotIn")) allErrs = append(allErrs, validation.NewFieldInvalid("values", sr.Values, "must be non-empty when operator is In or NotIn"))
} }
case extensions.PodSelectorOpExists, extensions.PodSelectorOpDoesNotExist: case extensions.PodSelectorOpExists, extensions.PodSelectorOpDoesNotExist:
if len(sr.Values) > 0 { if len(sr.Values) > 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("values", sr.Values, "must be empty when operator is Exists or DoesNotExist")) allErrs = append(allErrs, validation.NewFieldInvalid("values", sr.Values, "must be empty when operator is Exists or DoesNotExist"))
} }
default: default:
allErrs = append(allErrs, errs.NewFieldInvalid("operator", sr.Operator, "not a valid pod selector operator")) allErrs = append(allErrs, validation.NewFieldInvalid("operator", sr.Operator, "not a valid pod selector operator"))
} }
allErrs = append(allErrs, apivalidation.ValidateLabelName(sr.Key, "key")...) allErrs = append(allErrs, apivalidation.ValidateLabelName(sr.Key, "key")...)
return allErrs return allErrs
} }
func ValidateScale(scale *extensions.Scale) errs.ValidationErrorList { func ValidateScale(scale *extensions.Scale) validation.ErrorList {
allErrs := errs.ValidationErrorList{} allErrs := validation.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&scale.ObjectMeta, true, apivalidation.NameIsDNSSubdomain).Prefix("metadata")...) allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&scale.ObjectMeta, true, apivalidation.NameIsDNSSubdomain).Prefix("metadata")...)
if scale.Spec.Replicas < 0 { if scale.Spec.Replicas < 0 {
allErrs = append(allErrs, errs.NewFieldInvalid("spec.replicas", scale.Spec.Replicas, "must be non-negative")) allErrs = append(allErrs, validation.NewFieldInvalid("spec.replicas", scale.Spec.Replicas, "must be non-negative"))
} }
return allErrs return allErrs

View File

@@ -23,8 +23,8 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
errors "k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/validation"
) )
func TestValidateHorizontalPodAutoscaler(t *testing.T) { func TestValidateHorizontalPodAutoscaler(t *testing.T) {
@@ -675,7 +675,7 @@ func TestValidateDaemonSet(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} }
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*validation.Error).Field
if !strings.HasPrefix(field, "spec.template.") && if !strings.HasPrefix(field, "spec.template.") &&
field != "metadata.name" && field != "metadata.name" &&
field != "metadata.namespace" && field != "metadata.namespace" &&
@@ -918,7 +918,7 @@ func TestValidateJob(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} else { } else {
s := strings.Split(k, ":") s := strings.Split(k, ":")
err := errs[0].(*errors.ValidationError) err := errs[0].(*validation.Error)
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { 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", errs[0], k)
} }
@@ -1019,7 +1019,7 @@ func TestValidateIngress(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} else { } else {
s := strings.Split(k, ":") s := strings.Split(k, ":")
err := errs[0].(*errors.ValidationError) err := errs[0].(*validation.Error)
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { 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", errs[0], k)
} }
@@ -1111,7 +1111,7 @@ func TestValidateIngressStatusUpdate(t *testing.T) {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", k)
} else { } else {
s := strings.Split(k, ":") s := strings.Split(k, ":")
err := errs[0].(*errors.ValidationError) err := errs[0].(*validation.Error)
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { 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", errs[0], k)
} }

View File

@@ -31,7 +31,7 @@ import (
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
) )
func TestMerge(t *testing.T) { func TestMerge(t *testing.T) {
@@ -274,15 +274,15 @@ func TestCheckInvalidErr(t *testing.T) {
expected string expected string
}{ }{
{ {
errors.NewInvalid("Invalid1", "invalidation", fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("Cause", "single", "details")}), errors.NewInvalid("Invalid1", "invalidation", validation.ErrorList{validation.NewFieldInvalid("Cause", "single", "details")}),
`Error from server: Invalid1 "invalidation" is invalid: Cause: invalid value 'single', Details: details`, `Error from server: Invalid1 "invalidation" is invalid: Cause: invalid value 'single', Details: details`,
}, },
{ {
errors.NewInvalid("Invalid2", "invalidation", fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("Cause", "multi1", "details"), fielderrors.NewFieldInvalid("Cause", "multi2", "details")}), errors.NewInvalid("Invalid2", "invalidation", validation.ErrorList{validation.NewFieldInvalid("Cause", "multi1", "details"), validation.NewFieldInvalid("Cause", "multi2", "details")}),
`Error from server: Invalid2 "invalidation" is invalid: [Cause: invalid value 'multi1', Details: details, Cause: invalid value 'multi2', Details: details]`, `Error from server: Invalid2 "invalidation" is invalid: [Cause: invalid value 'multi1', Details: details, Cause: invalid value 'multi2', Details: details]`,
}, },
{ {
errors.NewInvalid("Invalid3", "invalidation", fielderrors.ValidationErrorList{}), errors.NewInvalid("Invalid3", "invalidation", validation.ErrorList{}),
`Error from server: Invalid3 "invalidation" is invalid: <nil>`, `Error from server: Invalid3 "invalidation" is invalid: <nil>`,
}, },
} }

View File

@@ -30,8 +30,8 @@ import (
kubeletutil "k8s.io/kubernetes/pkg/kubelet/util" kubeletutil "k8s.io/kubernetes/pkg/kubelet/util"
"k8s.io/kubernetes/pkg/util/config" "k8s.io/kubernetes/pkg/util/config"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// PodConfigNotificationMode describes how changes are sent to the update channel. // PodConfigNotificationMode describes how changes are sent to the update channel.
@@ -318,7 +318,7 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco
} else { } else {
name := kubecontainer.GetPodFullName(pod) name := kubecontainer.GetPodFullName(pod)
if names.Has(name) { if names.Has(name) {
errlist = append(errlist, fielderrors.NewFieldDuplicate("name", pod.Name)) errlist = append(errlist, utilvalidation.NewFieldDuplicate("name", pod.Name))
} else { } else {
names.Insert(name) names.Insert(name)
} }

View File

@@ -22,7 +22,6 @@ import (
"sort" "sort"
"strings" "strings"
"k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/validation"
) )
@@ -702,14 +701,14 @@ const qualifiedNameErrorMsg string = "must match regex [" + validation.DNS1123Su
func validateLabelKey(k string) error { func validateLabelKey(k string) error {
if !validation.IsQualifiedName(k) { if !validation.IsQualifiedName(k) {
return fielderrors.NewFieldInvalid("label key", k, qualifiedNameErrorMsg) return validation.NewFieldInvalid("label key", k, qualifiedNameErrorMsg)
} }
return nil return nil
} }
func validateLabelValue(v string) error { func validateLabelValue(v string) error {
if !validation.IsValidLabelValue(v) { if !validation.IsValidLabelValue(v) {
return fielderrors.NewFieldInvalid("label value", v, qualifiedNameErrorMsg) return validation.NewFieldInvalid("label value", v, qualifiedNameErrorMsg)
} }
return nil return nil
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// rcStrategy implements verification logic for Replication Controllers. // rcStrategy implements verification logic for Replication Controllers.
@@ -76,7 +76,7 @@ func (rcStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new replication controller. // Validate validates a new replication controller.
func (rcStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (rcStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
controller := obj.(*api.ReplicationController) controller := obj.(*api.ReplicationController)
return validation.ValidateReplicationController(controller) return validation.ValidateReplicationController(controller)
} }
@@ -92,7 +92,7 @@ func (rcStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (rcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (rcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
validationErrorList := validation.ValidateReplicationController(obj.(*api.ReplicationController)) validationErrorList := validation.ValidateReplicationController(obj.(*api.ReplicationController))
updateErrorList := validation.ValidateReplicationControllerUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController)) updateErrorList := validation.ValidateReplicationControllerUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController))
return append(validationErrorList, updateErrorList...) return append(validationErrorList, updateErrorList...)
@@ -141,6 +141,6 @@ func (rcStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newRc.Spec = oldRc.Spec newRc.Spec = oldRc.Spec
} }
func (rcStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (rcStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateReplicationControllerStatusUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController)) return validation.ValidateReplicationControllerStatusUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController))
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// daemonSetStrategy implements verification logic for daemon sets. // daemonSetStrategy implements verification logic for daemon sets.
@@ -77,7 +77,7 @@ func (daemonSetStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new daemon set. // Validate validates a new daemon set.
func (daemonSetStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (daemonSetStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
daemonSet := obj.(*extensions.DaemonSet) daemonSet := obj.(*extensions.DaemonSet)
return validation.ValidateDaemonSet(daemonSet) return validation.ValidateDaemonSet(daemonSet)
} }
@@ -93,7 +93,7 @@ func (daemonSetStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (daemonSetStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (daemonSetStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
validationErrorList := validation.ValidateDaemonSet(obj.(*extensions.DaemonSet)) validationErrorList := validation.ValidateDaemonSet(obj.(*extensions.DaemonSet))
updateErrorList := validation.ValidateDaemonSetUpdate(obj.(*extensions.DaemonSet), old.(*extensions.DaemonSet)) updateErrorList := validation.ValidateDaemonSetUpdate(obj.(*extensions.DaemonSet), old.(*extensions.DaemonSet))
return append(validationErrorList, updateErrorList...) return append(validationErrorList, updateErrorList...)
@@ -138,6 +138,6 @@ func (daemonSetStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newDaemonSet.Spec = oldDaemonSet.Spec newDaemonSet.Spec = oldDaemonSet.Spec
} }
func (daemonSetStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (daemonSetStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateDaemonSetStatusUpdate(obj.(*extensions.DaemonSet), old.(*extensions.DaemonSet)) return validation.ValidateDaemonSetStatusUpdate(obj.(*extensions.DaemonSet), old.(*extensions.DaemonSet))
} }

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
errs "k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// deploymentStrategy implements behavior for Deployments. // deploymentStrategy implements behavior for Deployments.
@@ -51,7 +51,7 @@ func (deploymentStrategy) PrepareForCreate(obj runtime.Object) {
} }
// Validate validates a new deployment. // Validate validates a new deployment.
func (deploymentStrategy) Validate(ctx api.Context, obj runtime.Object) errs.ValidationErrorList { func (deploymentStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
deployment := obj.(*extensions.Deployment) deployment := obj.(*extensions.Deployment)
return validation.ValidateDeployment(deployment) return validation.ValidateDeployment(deployment)
} }
@@ -73,7 +73,7 @@ func (deploymentStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (deploymentStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList { func (deploymentStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateDeploymentUpdate(obj.(*extensions.Deployment), old.(*extensions.Deployment)) return validation.ValidateDeploymentUpdate(obj.(*extensions.Deployment), old.(*extensions.Deployment))
} }
@@ -95,7 +95,7 @@ func (deploymentStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user updating status // ValidateUpdate is the default update validation for an end user updating status
func (deploymentStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList { func (deploymentStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateDeploymentUpdate(obj.(*extensions.Deployment), old.(*extensions.Deployment)) return validation.ValidateDeploymentUpdate(obj.(*extensions.Deployment), old.(*extensions.Deployment))
} }

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// endpointsStrategy implements behavior for Endpoints // endpointsStrategy implements behavior for Endpoints
@@ -53,7 +53,7 @@ func (endpointsStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new endpoints. // Validate validates a new endpoints.
func (endpointsStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (endpointsStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidateEndpoints(obj.(*api.Endpoints)) return validation.ValidateEndpoints(obj.(*api.Endpoints))
} }
@@ -69,7 +69,7 @@ func (endpointsStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (endpointsStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (endpointsStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidateEndpoints(obj.(*api.Endpoints)) errorList := validation.ValidateEndpoints(obj.(*api.Endpoints))
return append(errorList, validation.ValidateEndpointsUpdate(obj.(*api.Endpoints), old.(*api.Endpoints))...) return append(errorList, validation.ValidateEndpointsUpdate(obj.(*api.Endpoints), old.(*api.Endpoints))...)
} }

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
type eventStrategy struct { type eventStrategy struct {
@@ -48,7 +48,7 @@ func (eventStrategy) PrepareForCreate(obj runtime.Object) {
func (eventStrategy) PrepareForUpdate(obj, old runtime.Object) { func (eventStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
func (eventStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (eventStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
event := obj.(*api.Event) event := obj.(*api.Event)
return validation.ValidateEvent(event) return validation.ValidateEvent(event)
} }
@@ -61,7 +61,7 @@ func (eventStrategy) AllowCreateOnUpdate() bool {
return true return true
} }
func (eventStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (eventStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
event := obj.(*api.Event) event := obj.(*api.Event)
return validation.ValidateEvent(event) return validation.ValidateEvent(event)
} }

View File

@@ -31,8 +31,8 @@ import (
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest" "k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
storagetesting "k8s.io/kubernetes/pkg/storage/testing" storagetesting "k8s.io/kubernetes/pkg/storage/testing"
"k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/validation"
) )
type testRESTStrategy struct { type testRESTStrategy struct {
@@ -49,10 +49,10 @@ func (t *testRESTStrategy) AllowUnconditionalUpdate() bool { return t.allowUncon
func (t *testRESTStrategy) PrepareForCreate(obj runtime.Object) {} func (t *testRESTStrategy) PrepareForCreate(obj runtime.Object) {}
func (t *testRESTStrategy) PrepareForUpdate(obj, old runtime.Object) {} func (t *testRESTStrategy) PrepareForUpdate(obj, old runtime.Object) {}
func (t *testRESTStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (t *testRESTStrategy) Validate(ctx api.Context, obj runtime.Object) validation.ErrorList {
return nil return nil
} }
func (t *testRESTStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (t *testRESTStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) validation.ErrorList {
return nil return nil
} }
func (t *testRESTStrategy) Canonicalize(obj runtime.Object) {} func (t *testRESTStrategy) Canonicalize(obj runtime.Object) {}

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
errs "k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// autoscalerStrategy implements behavior for HorizontalPodAutoscalers // autoscalerStrategy implements behavior for HorizontalPodAutoscalers
@@ -53,7 +53,7 @@ func (autoscalerStrategy) PrepareForCreate(obj runtime.Object) {
} }
// Validate validates a new autoscaler. // Validate validates a new autoscaler.
func (autoscalerStrategy) Validate(ctx api.Context, obj runtime.Object) errs.ValidationErrorList { func (autoscalerStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
autoscaler := obj.(*extensions.HorizontalPodAutoscaler) autoscaler := obj.(*extensions.HorizontalPodAutoscaler)
return validation.ValidateHorizontalPodAutoscaler(autoscaler) return validation.ValidateHorizontalPodAutoscaler(autoscaler)
} }
@@ -76,7 +76,7 @@ func (autoscalerStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (autoscalerStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList { func (autoscalerStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler)) return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler))
} }
@@ -115,6 +115,6 @@ func (autoscalerStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newAutoscaler.Spec = oldAutoscaler.Spec newAutoscaler.Spec = oldAutoscaler.Spec
} }
func (autoscalerStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList { func (autoscalerStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateHorizontalPodAutoscalerStatusUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler)) return validation.ValidateHorizontalPodAutoscalerStatusUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler))
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// ingressStrategy implements verification logic for Replication Ingresss. // ingressStrategy implements verification logic for Replication Ingresss.
@@ -70,7 +70,7 @@ func (ingressStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new Ingress. // Validate validates a new Ingress.
func (ingressStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (ingressStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
ingress := obj.(*extensions.Ingress) ingress := obj.(*extensions.Ingress)
err := validation.ValidateIngress(ingress) err := validation.ValidateIngress(ingress)
return err return err
@@ -86,7 +86,7 @@ func (ingressStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (ingressStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (ingressStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
validationErrorList := validation.ValidateIngress(obj.(*extensions.Ingress)) validationErrorList := validation.ValidateIngress(obj.(*extensions.Ingress))
updateErrorList := validation.ValidateIngressUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress)) updateErrorList := validation.ValidateIngressUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress))
return append(validationErrorList, updateErrorList...) return append(validationErrorList, updateErrorList...)
@@ -134,6 +134,6 @@ func (ingressStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user updating status // ValidateUpdate is the default update validation for an end user updating status
func (ingressStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (ingressStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateIngressStatusUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress)) return validation.ValidateIngressStatusUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress))
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// jobStrategy implements verification logic for Replication Controllers. // jobStrategy implements verification logic for Replication Controllers.
@@ -58,7 +58,7 @@ func (jobStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new job. // Validate validates a new job.
func (jobStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (jobStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
job := obj.(*extensions.Job) job := obj.(*extensions.Job)
return validation.ValidateJob(job) return validation.ValidateJob(job)
} }
@@ -77,7 +77,7 @@ func (jobStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (jobStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (jobStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
validationErrorList := validation.ValidateJob(obj.(*extensions.Job)) validationErrorList := validation.ValidateJob(obj.(*extensions.Job))
updateErrorList := validation.ValidateJobUpdate(obj.(*extensions.Job), old.(*extensions.Job)) updateErrorList := validation.ValidateJobUpdate(obj.(*extensions.Job), old.(*extensions.Job))
return append(validationErrorList, updateErrorList...) return append(validationErrorList, updateErrorList...)
@@ -95,7 +95,7 @@ func (jobStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newJob.Spec = oldJob.Spec newJob.Spec = oldJob.Spec
} }
func (jobStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (jobStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateJobUpdateStatus(obj.(*extensions.Job), old.(*extensions.Job)) return validation.ValidateJobUpdateStatus(obj.(*extensions.Job), old.(*extensions.Job))
} }

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
type limitrangeStrategy struct { type limitrangeStrategy struct {
@@ -52,7 +52,7 @@ func (limitrangeStrategy) PrepareForCreate(obj runtime.Object) {
func (limitrangeStrategy) PrepareForUpdate(obj, old runtime.Object) { func (limitrangeStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
func (limitrangeStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (limitrangeStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
limitRange := obj.(*api.LimitRange) limitRange := obj.(*api.LimitRange)
return validation.ValidateLimitRange(limitRange) return validation.ValidateLimitRange(limitRange)
} }
@@ -65,7 +65,7 @@ func (limitrangeStrategy) AllowCreateOnUpdate() bool {
return true return true
} }
func (limitrangeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (limitrangeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
limitRange := obj.(*api.LimitRange) limitRange := obj.(*api.LimitRange)
return validation.ValidateLimitRange(limitRange) return validation.ValidateLimitRange(limitRange)
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// namespaceStrategy implements behavior for Namespaces // namespaceStrategy implements behavior for Namespaces
@@ -77,7 +77,7 @@ func (namespaceStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new namespace. // Validate validates a new namespace.
func (namespaceStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (namespaceStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
namespace := obj.(*api.Namespace) namespace := obj.(*api.Namespace)
return validation.ValidateNamespace(namespace) return validation.ValidateNamespace(namespace)
} }
@@ -92,7 +92,7 @@ func (namespaceStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (namespaceStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (namespaceStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidateNamespace(obj.(*api.Namespace)) errorList := validation.ValidateNamespace(obj.(*api.Namespace))
return append(errorList, validation.ValidateNamespaceUpdate(obj.(*api.Namespace), old.(*api.Namespace))...) return append(errorList, validation.ValidateNamespaceUpdate(obj.(*api.Namespace), old.(*api.Namespace))...)
} }
@@ -113,7 +113,7 @@ func (namespaceStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newNamespace.Spec = oldNamespace.Spec newNamespace.Spec = oldNamespace.Spec
} }
func (namespaceStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (namespaceStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateNamespaceStatusUpdate(obj.(*api.Namespace), old.(*api.Namespace)) return validation.ValidateNamespaceStatusUpdate(obj.(*api.Namespace), old.(*api.Namespace))
} }
@@ -123,7 +123,7 @@ type namespaceFinalizeStrategy struct {
var FinalizeStrategy = namespaceFinalizeStrategy{Strategy} var FinalizeStrategy = namespaceFinalizeStrategy{Strategy}
func (namespaceFinalizeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (namespaceFinalizeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateNamespaceFinalizeUpdate(obj.(*api.Namespace), old.(*api.Namespace)) return validation.ValidateNamespaceFinalizeUpdate(obj.(*api.Namespace), old.(*api.Namespace))
} }

View File

@@ -33,8 +33,8 @@ import (
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/fielderrors"
nodeutil "k8s.io/kubernetes/pkg/util/node" nodeutil "k8s.io/kubernetes/pkg/util/node"
utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// nodeStrategy implements behavior for nodes // nodeStrategy implements behavior for nodes
@@ -71,7 +71,7 @@ func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new node. // Validate validates a new node.
func (nodeStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (nodeStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
node := obj.(*api.Node) node := obj.(*api.Node)
return validation.ValidateNode(node) return validation.ValidateNode(node)
} }
@@ -81,7 +81,7 @@ func (nodeStrategy) Canonicalize(obj runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (nodeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (nodeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidateNode(obj.(*api.Node)) errorList := validation.ValidateNode(obj.(*api.Node))
return append(errorList, validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node))...) return append(errorList, validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node))...)
} }
@@ -107,7 +107,7 @@ func (nodeStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newNode.Spec = oldNode.Spec newNode.Spec = oldNode.Spec
} }
func (nodeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (nodeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node)) return validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node))
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// persistentvolumeStrategy implements behavior for PersistentVolume objects // persistentvolumeStrategy implements behavior for PersistentVolume objects
@@ -48,7 +48,7 @@ func (persistentvolumeStrategy) PrepareForCreate(obj runtime.Object) {
pv.Status = api.PersistentVolumeStatus{} pv.Status = api.PersistentVolumeStatus{}
} }
func (persistentvolumeStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
persistentvolume := obj.(*api.PersistentVolume) persistentvolume := obj.(*api.PersistentVolume)
return validation.ValidatePersistentVolume(persistentvolume) return validation.ValidatePersistentVolume(persistentvolume)
} }
@@ -68,7 +68,7 @@ func (persistentvolumeStrategy) PrepareForUpdate(obj, old runtime.Object) {
newPv.Status = oldPv.Status newPv.Status = oldPv.Status
} }
func (persistentvolumeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidatePersistentVolume(obj.(*api.PersistentVolume)) errorList := validation.ValidatePersistentVolume(obj.(*api.PersistentVolume))
return append(errorList, validation.ValidatePersistentVolumeUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))...) return append(errorList, validation.ValidatePersistentVolumeUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))...)
} }
@@ -90,7 +90,7 @@ func (persistentvolumeStatusStrategy) PrepareForUpdate(obj, old runtime.Object)
newPv.Spec = oldPv.Spec newPv.Spec = oldPv.Spec
} }
func (persistentvolumeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume)) return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// persistentvolumeclaimStrategy implements behavior for PersistentVolumeClaim objects // persistentvolumeclaimStrategy implements behavior for PersistentVolumeClaim objects
@@ -48,7 +48,7 @@ func (persistentvolumeclaimStrategy) PrepareForCreate(obj runtime.Object) {
pv.Status = api.PersistentVolumeClaimStatus{} pv.Status = api.PersistentVolumeClaimStatus{}
} }
func (persistentvolumeclaimStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeclaimStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
pvc := obj.(*api.PersistentVolumeClaim) pvc := obj.(*api.PersistentVolumeClaim)
return validation.ValidatePersistentVolumeClaim(pvc) return validation.ValidatePersistentVolumeClaim(pvc)
} }
@@ -68,7 +68,7 @@ func (persistentvolumeclaimStrategy) PrepareForUpdate(obj, old runtime.Object) {
newPvc.Status = oldPvc.Status newPvc.Status = oldPvc.Status
} }
func (persistentvolumeclaimStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeclaimStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidatePersistentVolumeClaim(obj.(*api.PersistentVolumeClaim)) errorList := validation.ValidatePersistentVolumeClaim(obj.(*api.PersistentVolumeClaim))
return append(errorList, validation.ValidatePersistentVolumeClaimUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))...) return append(errorList, validation.ValidatePersistentVolumeClaimUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))...)
} }
@@ -90,7 +90,7 @@ func (persistentvolumeclaimStatusStrategy) PrepareForUpdate(obj, old runtime.Obj
newPv.Spec = oldPv.Spec newPv.Spec = oldPv.Spec
} }
func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim)) return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
} }

View File

@@ -35,7 +35,7 @@ import (
podrest "k8s.io/kubernetes/pkg/registry/pod/rest" podrest "k8s.io/kubernetes/pkg/registry/pod/rest"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage"
"k8s.io/kubernetes/pkg/util/fielderrors" "k8s.io/kubernetes/pkg/util/validation"
) )
// PodStorage includes storage for pods and all sub resources // PodStorage includes storage for pods and all sub resources
@@ -129,10 +129,10 @@ func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.O
binding := obj.(*api.Binding) binding := obj.(*api.Binding)
// TODO: move me to a binding strategy // TODO: move me to a binding strategy
if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" { if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" {
return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("to.kind", binding.Target.Kind, "must be empty or 'Node'")}) return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewFieldInvalid("to.kind", binding.Target.Kind, "must be empty or 'Node'")})
} }
if len(binding.Target.Name) == 0 { if len(binding.Target.Name) == 0 {
return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldRequired("to.name")}) return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewFieldRequired("to.name")})
} }
err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations)
out = &unversioned.Status{Status: unversioned.StatusSuccess} out = &unversioned.Status{Status: unversioned.StatusSuccess}

View File

@@ -33,7 +33,7 @@ import (
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// podStrategy implements behavior for Pods // podStrategy implements behavior for Pods
@@ -67,7 +67,7 @@ func (podStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new pod. // Validate validates a new pod.
func (podStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (podStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
pod := obj.(*api.Pod) pod := obj.(*api.Pod)
return validation.ValidatePod(pod) return validation.ValidatePod(pod)
} }
@@ -82,7 +82,7 @@ func (podStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (podStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (podStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidatePod(obj.(*api.Pod)) errorList := validation.ValidatePod(obj.(*api.Pod))
return append(errorList, validation.ValidatePodUpdate(obj.(*api.Pod), old.(*api.Pod))...) return append(errorList, validation.ValidatePodUpdate(obj.(*api.Pod), old.(*api.Pod))...)
} }
@@ -147,7 +147,7 @@ func (podStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newPod.DeletionTimestamp = nil newPod.DeletionTimestamp = nil
} }
func (podStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (podStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
// TODO: merge valid fields after update // TODO: merge valid fields after update
return validation.ValidatePodStatusUpdate(obj.(*api.Pod), old.(*api.Pod)) return validation.ValidatePodStatusUpdate(obj.(*api.Pod), old.(*api.Pod))
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
errs "k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// podTemplateStrategy implements behavior for PodTemplates // podTemplateStrategy implements behavior for PodTemplates
@@ -49,7 +49,7 @@ func (podTemplateStrategy) PrepareForCreate(obj runtime.Object) {
} }
// Validate validates a new pod template. // Validate validates a new pod template.
func (podTemplateStrategy) Validate(ctx api.Context, obj runtime.Object) errs.ValidationErrorList { func (podTemplateStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
pod := obj.(*api.PodTemplate) pod := obj.(*api.PodTemplate)
return validation.ValidatePodTemplate(pod) return validation.ValidatePodTemplate(pod)
} }
@@ -69,7 +69,7 @@ func (podTemplateStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (podTemplateStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList { func (podTemplateStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidatePodTemplateUpdate(obj.(*api.PodTemplate), old.(*api.PodTemplate)) return validation.ValidatePodTemplateUpdate(obj.(*api.PodTemplate), old.(*api.PodTemplate))
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// resourcequotaStrategy implements behavior for ResourceQuota objects // resourcequotaStrategy implements behavior for ResourceQuota objects
@@ -57,7 +57,7 @@ func (resourcequotaStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new resourcequota. // Validate validates a new resourcequota.
func (resourcequotaStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (resourcequotaStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
resourcequota := obj.(*api.ResourceQuota) resourcequota := obj.(*api.ResourceQuota)
return validation.ValidateResourceQuota(resourcequota) return validation.ValidateResourceQuota(resourcequota)
} }
@@ -72,7 +72,7 @@ func (resourcequotaStrategy) AllowCreateOnUpdate() bool {
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate is the default update validation for an end user.
func (resourcequotaStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (resourcequotaStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
errorList := validation.ValidateResourceQuota(obj.(*api.ResourceQuota)) errorList := validation.ValidateResourceQuota(obj.(*api.ResourceQuota))
return append(errorList, validation.ValidateResourceQuotaUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))...) return append(errorList, validation.ValidateResourceQuotaUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))...)
} }
@@ -93,7 +93,7 @@ func (resourcequotaStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newResourcequota.Spec = oldResourcequota.Spec newResourcequota.Spec = oldResourcequota.Spec
} }
func (resourcequotaStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (resourcequotaStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateResourceQuotaStatusUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota)) return validation.ValidateResourceQuotaStatusUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))
} }

View File

@@ -26,7 +26,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// strategy implements behavior for Secret objects // strategy implements behavior for Secret objects
@@ -50,7 +50,7 @@ func (strategy) NamespaceScoped() bool {
func (strategy) PrepareForCreate(obj runtime.Object) { func (strategy) PrepareForCreate(obj runtime.Object) {
} }
func (strategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (strategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidateSecret(obj.(*api.Secret)) return validation.ValidateSecret(obj.(*api.Secret))
} }
@@ -64,7 +64,7 @@ func (strategy) AllowCreateOnUpdate() bool {
func (strategy) PrepareForUpdate(obj, old runtime.Object) { func (strategy) PrepareForUpdate(obj, old runtime.Object) {
} }
func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateSecretUpdate(obj.(*api.Secret), old.(*api.Secret)) return validation.ValidateSecretUpdate(obj.(*api.Secret), old.(*api.Secret))
} }

View File

@@ -35,7 +35,7 @@ import (
"k8s.io/kubernetes/pkg/registry/service/portallocator" "k8s.io/kubernetes/pkg/registry/service/portallocator"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
) )
@@ -84,7 +84,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
// Allocate next available. // Allocate next available.
ip, err := rs.serviceIPs.AllocateNext() ip, err := rs.serviceIPs.AllocateNext()
if err != nil { if err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())} el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())}
return nil, errors.NewInvalid("Service", service.Name, el) return nil, errors.NewInvalid("Service", service.Name, el)
} }
service.Spec.ClusterIP = ip.String() 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) { } else if api.IsServiceIPSet(service) {
// Try to respect the requested IP. // Try to respect the requested IP.
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil { if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())} el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("spec.clusterIP", service.Spec.ClusterIP, err.Error())}
return nil, errors.NewInvalid("Service", service.Name, el) return nil, errors.NewInvalid("Service", service.Name, el)
} }
releaseServiceIP = true releaseServiceIP = true
@@ -104,13 +104,13 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
if servicePort.NodePort != 0 { if servicePort.NodePort != 0 {
err := nodePortOp.Allocate(servicePort.NodePort) err := nodePortOp.Allocate(servicePort.NodePort)
if err != nil { if err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports")
return nil, errors.NewInvalid("Service", service.Name, el) return nil, errors.NewInvalid("Service", service.Name, el)
} }
} else if assignNodePorts { } else if assignNodePorts {
nodePort, err := nodePortOp.AllocateNext() nodePort, err := nodePortOp.AllocateNext()
if err != nil { if err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", servicePort.NodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports")
return nil, errors.NewInvalid("Service", service.Name, el) return nil, errors.NewInvalid("Service", service.Name, el)
} }
servicePort.NodePort = nodePort servicePort.NodePort = nodePort
@@ -223,14 +223,14 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
if !contains(oldNodePorts, nodePort) { if !contains(oldNodePorts, nodePort) {
err := nodePortOp.Allocate(nodePort) err := nodePortOp.Allocate(nodePort)
if err != nil { if err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports")
return nil, false, errors.NewInvalid("Service", service.Name, el) return nil, false, errors.NewInvalid("Service", service.Name, el)
} }
} }
} else { } else {
nodePort, err = nodePortOp.AllocateNext() nodePort, err = nodePortOp.AllocateNext()
if err != nil { if err != nil {
el := fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports") el := utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("nodePort", nodePort, err.Error())}.PrefixIndex(i).Prefix("spec.ports")
return nil, false, errors.NewInvalid("Service", service.Name, el) return nil, false, errors.NewInvalid("Service", service.Name, el)
} }
servicePort.NodePort = nodePort servicePort.NodePort = nodePort

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// svcStrategy implements behavior for Services // svcStrategy implements behavior for Services
@@ -58,7 +58,7 @@ func (svcStrategy) PrepareForUpdate(obj, old runtime.Object) {
} }
// Validate validates a new service. // Validate validates a new service.
func (svcStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (svcStrategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
service := obj.(*api.Service) service := obj.(*api.Service)
return validation.ValidateService(service) return validation.ValidateService(service)
} }
@@ -71,7 +71,7 @@ func (svcStrategy) AllowCreateOnUpdate() bool {
return true return true
} }
func (svcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (svcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateServiceUpdate(obj.(*api.Service), old.(*api.Service)) return validation.ValidateServiceUpdate(obj.(*api.Service), old.(*api.Service))
} }

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// strategy implements behavior for ServiceAccount objects // strategy implements behavior for ServiceAccount objects
@@ -46,7 +46,7 @@ func (strategy) PrepareForCreate(obj runtime.Object) {
cleanSecretReferences(obj.(*api.ServiceAccount)) cleanSecretReferences(obj.(*api.ServiceAccount))
} }
func (strategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (strategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidateServiceAccount(obj.(*api.ServiceAccount)) return validation.ValidateServiceAccount(obj.(*api.ServiceAccount))
} }
@@ -68,7 +68,7 @@ func cleanSecretReferences(serviceAccount *api.ServiceAccount) {
} }
} }
func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateServiceAccountUpdate(obj.(*api.ServiceAccount), old.(*api.ServiceAccount)) return validation.ValidateServiceAccountUpdate(obj.(*api.ServiceAccount), old.(*api.ServiceAccount))
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// strategy implements behavior for ThirdPartyResource objects // strategy implements behavior for ThirdPartyResource objects
@@ -51,7 +51,7 @@ func (strategy) NamespaceScoped() bool {
func (strategy) PrepareForCreate(obj runtime.Object) { func (strategy) PrepareForCreate(obj runtime.Object) {
} }
func (strategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (strategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidateThirdPartyResource(obj.(*extensions.ThirdPartyResource)) return validation.ValidateThirdPartyResource(obj.(*extensions.ThirdPartyResource))
} }
@@ -66,7 +66,7 @@ func (strategy) AllowCreateOnUpdate() bool {
func (strategy) PrepareForUpdate(obj, old runtime.Object) { func (strategy) PrepareForUpdate(obj, old runtime.Object) {
} }
func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateThirdPartyResourceUpdate(obj.(*extensions.ThirdPartyResource), old.(*extensions.ThirdPartyResource)) return validation.ValidateThirdPartyResourceUpdate(obj.(*extensions.ThirdPartyResource), old.(*extensions.ThirdPartyResource))
} }

View File

@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
// strategy implements behavior for ThirdPartyResource objects // strategy implements behavior for ThirdPartyResource objects
@@ -51,7 +51,7 @@ func (strategy) NamespaceScoped() bool {
func (strategy) PrepareForCreate(obj runtime.Object) { func (strategy) PrepareForCreate(obj runtime.Object) {
} }
func (strategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList { func (strategy) Validate(ctx api.Context, obj runtime.Object) utilvalidation.ErrorList {
return validation.ValidateThirdPartyResourceData(obj.(*extensions.ThirdPartyResourceData)) return validation.ValidateThirdPartyResourceData(obj.(*extensions.ThirdPartyResourceData))
} }
@@ -66,7 +66,7 @@ func (strategy) AllowCreateOnUpdate() bool {
func (strategy) PrepareForUpdate(obj, old runtime.Object) { func (strategy) PrepareForUpdate(obj, old runtime.Object) {
} }
func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList { func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList {
return validation.ValidateThirdPartyResourceDataUpdate(obj.(*extensions.ThirdPartyResourceData), old.(*extensions.ThirdPartyResourceData)) return validation.ValidateThirdPartyResourceDataUpdate(obj.(*extensions.ThirdPartyResourceData), old.(*extensions.ThirdPartyResourceData))
} }

View File

@@ -24,7 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/fielderrors" utilvalidation "k8s.io/kubernetes/pkg/util/validation"
) )
type SimpleUpdateFunc func(runtime.Object) (runtime.Object, error) type SimpleUpdateFunc func(runtime.Object) (runtime.Object, error)
@@ -47,8 +47,8 @@ func ParseWatchResourceVersion(resourceVersion, kind string) (uint64, error) {
} }
version, err := strconv.ParseUint(resourceVersion, 10, 64) version, err := strconv.ParseUint(resourceVersion, 10, 64)
if err != nil { if err != nil {
// TODO: Does this need to be a ValidationErrorList? I can't convince myself it does. // TODO: Does this need to be a ErrorList? I can't convince myself it does.
return 0, errors.NewInvalid(kind, "", fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("resourceVersion", resourceVersion, err.Error())}) return 0, errors.NewInvalid(kind, "", utilvalidation.ErrorList{utilvalidation.NewFieldInvalid("resourceVersion", resourceVersion, err.Error())})
} }
return version + 1, nil return version + 1, nil
} }

View File

@@ -1,207 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fielderrors
import (
"fmt"
"strings"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"github.com/davecgh/go-spew/spew"
)
// ValidationErrorType is a machine readable value providing more detail about why
// a field is invalid. These values are expected to match 1-1 with
// CauseType in api/types.go.
type ValidationErrorType string
// TODO: These values are duplicated in api/types.go, but there's a circular dep. Fix it.
const (
// ValidationErrorTypeNotFound is used to report failure to find a requested value
// (e.g. looking up an ID).
ValidationErrorTypeNotFound ValidationErrorType = "FieldValueNotFound"
// ValidationErrorTypeRequired is used to report required values that are not
// provided (e.g. empty strings, null values, or empty arrays).
ValidationErrorTypeRequired ValidationErrorType = "FieldValueRequired"
// ValidationErrorTypeDuplicate is used to report collisions of values that must be
// unique (e.g. unique IDs).
ValidationErrorTypeDuplicate ValidationErrorType = "FieldValueDuplicate"
// ValidationErrorTypeInvalid is used to report malformed values (e.g. failed regex
// match).
ValidationErrorTypeInvalid ValidationErrorType = "FieldValueInvalid"
// ValidationErrorTypeNotSupported is used to report valid (as per formatting rules)
// values that can not be handled (e.g. an enumerated string).
ValidationErrorTypeNotSupported ValidationErrorType = "FieldValueNotSupported"
// ValidationErrorTypeForbidden is used to report valid (as per formatting rules)
// values which would be accepted by some api instances, but which would invoke behavior
// not permitted by this api instance (such as due to stricter security policy).
ValidationErrorTypeForbidden ValidationErrorType = "FieldValueForbidden"
// ValidationErrorTypeTooLong is used to report that given value is too long.
ValidationErrorTypeTooLong ValidationErrorType = "FieldValueTooLong"
)
// String converts a ValidationErrorType into its corresponding error message.
func (t ValidationErrorType) String() string {
switch t {
case ValidationErrorTypeNotFound:
return "not found"
case ValidationErrorTypeRequired:
return "required value"
case ValidationErrorTypeDuplicate:
return "duplicate value"
case ValidationErrorTypeInvalid:
return "invalid value"
case ValidationErrorTypeNotSupported:
return "unsupported value"
case ValidationErrorTypeForbidden:
return "forbidden"
case ValidationErrorTypeTooLong:
return "too long"
default:
panic(fmt.Sprintf("unrecognized validation type: %#v", t))
return ""
}
}
// ValidationError is an implementation of the 'error' interface, which represents an error of validation.
type ValidationError struct {
Type ValidationErrorType
Field string
BadValue interface{}
Detail string
}
var _ error = &ValidationError{}
func (v *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
}
func (v *ValidationError) ErrorBody() string {
var s string
switch v.Type {
case ValidationErrorTypeRequired, ValidationErrorTypeTooLong:
s = spew.Sprintf("%s", v.Type)
default:
s = spew.Sprintf("%s '%+v'", v.Type, v.BadValue)
}
if len(v.Detail) != 0 {
s += fmt.Sprintf(", Details: %s", v.Detail)
}
return s
}
// NewFieldRequired returns a *ValidationError indicating "value required"
func NewFieldRequired(field string) *ValidationError {
return &ValidationError{ValidationErrorTypeRequired, field, "", ""}
}
// NewFieldInvalid returns a *ValidationError indicating "invalid value"
func NewFieldInvalid(field string, value interface{}, detail string) *ValidationError {
return &ValidationError{ValidationErrorTypeInvalid, field, value, detail}
}
// NewFieldValueNotSupported returns a *ValidationError indicating "unsupported value"
func NewFieldValueNotSupported(field string, value interface{}, validValues []string) *ValidationError {
detail := ""
if validValues != nil && len(validValues) > 0 {
detail = "supported values: " + strings.Join(validValues, ", ")
}
return &ValidationError{ValidationErrorTypeNotSupported, field, value, detail}
}
// NewFieldForbidden returns a *ValidationError indicating "forbidden"
func NewFieldForbidden(field string, value interface{}) *ValidationError {
return &ValidationError{ValidationErrorTypeForbidden, field, value, ""}
}
// NewFieldDuplicate returns a *ValidationError indicating "duplicate value"
func NewFieldDuplicate(field string, value interface{}) *ValidationError {
return &ValidationError{ValidationErrorTypeDuplicate, field, value, ""}
}
// NewFieldNotFound returns a *ValidationError indicating "value not found"
func NewFieldNotFound(field string, value interface{}) *ValidationError {
return &ValidationError{ValidationErrorTypeNotFound, field, value, ""}
}
func NewFieldTooLong(field string, value interface{}, maxLength int) *ValidationError {
return &ValidationError{ValidationErrorTypeTooLong, field, value, fmt.Sprintf("must have at most %d characters", maxLength)}
}
type ValidationErrorList []error
// Prefix adds a prefix to the Field of every ValidationError in the list.
// Returns the list for convenience.
func (list ValidationErrorList) Prefix(prefix string) ValidationErrorList {
for i := range list {
if err, ok := list[i].(*ValidationError); 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
} else {
panic(fmt.Sprintf("Programmer error: ValidationErrorList holds non-ValidationError: %#v", list[i]))
}
}
return list
}
// PrefixIndex adds an index to the Field of every ValidationError in the list.
// Returns the list for convenience.
func (list ValidationErrorList) PrefixIndex(index int) ValidationErrorList {
return list.Prefix(fmt.Sprintf("[%d]", index))
}
// NewValidationErrorFieldPrefixMatcher returns an errors.Matcher that returns true
// if the provided error is a ValidationError and has the provided ValidationErrorType.
func NewValidationErrorTypeMatcher(t ValidationErrorType) utilerrors.Matcher {
return func(err error) bool {
if e, ok := err.(*ValidationError); ok {
return e.Type == t
}
return false
}
}
// NewValidationErrorFieldPrefixMatcher returns an errors.Matcher that returns true
// if the provided error is a ValidationError and has a field with the provided
// prefix.
func NewValidationErrorFieldPrefixMatcher(prefix string) utilerrors.Matcher {
return func(err error) bool {
if e, ok := err.(*ValidationError); ok {
return strings.HasPrefix(e.Field, prefix)
}
return false
}
}
// Filter removes items from the ValidationErrorList that match the provided fns.
func (list ValidationErrorList) Filter(fns ...utilerrors.Matcher) ValidationErrorList {
err := utilerrors.FilterOut(utilerrors.NewAggregate(list), fns...)
if err == nil {
return nil
}
// FilterOut that takes an Aggregate returns an Aggregate
agg := err.(utilerrors.Aggregate)
return ValidationErrorList(agg.Errors())
}

View File

@@ -0,0 +1,195 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"fmt"
"strings"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"github.com/davecgh/go-spew/spew"
)
// ErrorType is a machine readable value providing more detail about why
// a field is invalid. These values are expected to match 1-1 with
// CauseType in api/types.go.
type ErrorType string
// TODO: These values are duplicated in api/types.go, but there's a circular dep. Fix it.
const (
// ErrorType is used to report failure to find a requested value
// (e.g. looking up an ID).
ErrorTypeNotFound ErrorType = "FieldValueNotFound"
// ErrorTypeRequired is used to report required values that are not
// provided (e.g. empty strings, null values, or empty arrays).
ErrorTypeRequired ErrorType = "FieldValueRequired"
// ErrorTypeDuplicate is used to report collisions of values that must be
// unique (e.g. unique IDs).
ErrorTypeDuplicate ErrorType = "FieldValueDuplicate"
// ErrorTypeInvalid is used to report malformed values (e.g. failed regex
// match).
ErrorTypeInvalid ErrorType = "FieldValueInvalid"
// ErrorTypeNotSupported is used to report valid (as per formatting rules)
// values that can not be handled (e.g. an enumerated string).
ErrorTypeNotSupported ErrorType = "FieldValueNotSupported"
// ErrorTypeForbidden is used to report valid (as per formatting rules)
// values which would be accepted by some api instances, but which would invoke behavior
// not permitted by this api instance (such as due to stricter security policy).
ErrorTypeForbidden ErrorType = "FieldValueForbidden"
// ErrorTypeTooLong is used to report that given value is too long.
ErrorTypeTooLong ErrorType = "FieldValueTooLong"
)
// String converts a ErrorType into its corresponding error message.
func (t ErrorType) String() string {
switch t {
case ErrorTypeNotFound:
return "not found"
case ErrorTypeRequired:
return "required value"
case ErrorTypeDuplicate:
return "duplicate value"
case ErrorTypeInvalid:
return "invalid value"
case ErrorTypeNotSupported:
return "unsupported value"
case ErrorTypeForbidden:
return "forbidden"
case ErrorTypeTooLong:
return "too long"
default:
panic(fmt.Sprintf("unrecognized validation type: %#v", t))
return ""
}
}
// Error is an implementation of the 'error' interface, which represents an error of validation.
type Error struct {
Type ErrorType
Field string
BadValue interface{}
Detail string
}
var _ error = &Error{}
func (v *Error) Error() string {
return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
}
func (v *Error) ErrorBody() string {
var s string
switch v.Type {
case ErrorTypeRequired, ErrorTypeTooLong:
s = spew.Sprintf("%s", v.Type)
default:
s = spew.Sprintf("%s '%+v'", v.Type, v.BadValue)
}
if len(v.Detail) != 0 {
s += fmt.Sprintf(", Details: %s", v.Detail)
}
return s
}
// NewFieldRequired returns a *Error indicating "value required"
func NewFieldRequired(field string) *Error {
return &Error{ErrorTypeRequired, field, "", ""}
}
// NewFieldInvalid returns a *Error indicating "invalid value"
func NewFieldInvalid(field string, value interface{}, detail string) *Error {
return &Error{ErrorTypeInvalid, field, value, detail}
}
// NewFieldValueNotSupported returns a *Error indicating "unsupported value"
func NewFieldValueNotSupported(field string, value interface{}, validValues []string) *Error {
detail := ""
if validValues != nil && len(validValues) > 0 {
detail = "supported values: " + strings.Join(validValues, ", ")
}
return &Error{ErrorTypeNotSupported, field, value, detail}
}
// NewFieldForbidden returns a *Error indicating "forbidden"
func NewFieldForbidden(field string, value interface{}) *Error {
return &Error{ErrorTypeForbidden, field, value, ""}
}
// NewFieldDuplicate returns a *Error indicating "duplicate value"
func NewFieldDuplicate(field string, value interface{}) *Error {
return &Error{ErrorTypeDuplicate, field, value, ""}
}
// NewFieldNotFound returns a *Error indicating "value not found"
func NewFieldNotFound(field string, value interface{}) *Error {
return &Error{ErrorTypeNotFound, field, value, ""}
}
func NewFieldTooLong(field string, value interface{}, maxLength int) *Error {
return &Error{ErrorTypeTooLong, field, value, fmt.Sprintf("must have at most %d characters", maxLength)}
}
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
} else {
panic(fmt.Sprintf("Programmer error: ErrorList holds non-Error: %#v", list[i]))
}
}
return list
}
// PrefixIndex adds an index to the Field of every Error in the list.
// Returns the list for convenience.
func (list ErrorList) PrefixIndex(index int) ErrorList {
return list.Prefix(fmt.Sprintf("[%d]", index))
}
// NewErrorTypeMatcher returns an errors.Matcher that returns true
// if the provided error is a Error and has the provided ErrorType.
func NewErrorTypeMatcher(t ErrorType) utilerrors.Matcher {
return func(err error) bool {
if e, ok := err.(*Error); ok {
return e.Type == t
}
return false
}
}
// 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...)
if err == nil {
return nil
}
// FilterOut that takes an Aggregate returns an Aggregate
agg := err.(utilerrors.Aggregate)
return ErrorList(agg.Errors())
}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package fielderrors package validation
import ( import (
"strings" "strings"
@@ -23,28 +23,28 @@ import (
func TestMakeFuncs(t *testing.T) { func TestMakeFuncs(t *testing.T) {
testCases := []struct { testCases := []struct {
fn func() *ValidationError fn func() *Error
expected ValidationErrorType expected ErrorType
}{ }{
{ {
func() *ValidationError { return NewFieldInvalid("f", "v", "d") }, func() *Error { return NewFieldInvalid("f", "v", "d") },
ValidationErrorTypeInvalid, ErrorTypeInvalid,
}, },
{ {
func() *ValidationError { return NewFieldValueNotSupported("f", "v", nil) }, func() *Error { return NewFieldValueNotSupported("f", "v", nil) },
ValidationErrorTypeNotSupported, ErrorTypeNotSupported,
}, },
{ {
func() *ValidationError { return NewFieldDuplicate("f", "v") }, func() *Error { return NewFieldDuplicate("f", "v") },
ValidationErrorTypeDuplicate, ErrorTypeDuplicate,
}, },
{ {
func() *ValidationError { return NewFieldNotFound("f", "v") }, func() *Error { return NewFieldNotFound("f", "v") },
ValidationErrorTypeNotFound, ErrorTypeNotFound,
}, },
{ {
func() *ValidationError { return NewFieldRequired("f") }, func() *Error { return NewFieldRequired("f") },
ValidationErrorTypeRequired, ErrorTypeRequired,
}, },
} }
@@ -56,10 +56,10 @@ func TestMakeFuncs(t *testing.T) {
} }
} }
func TestValidationErrorUsefulMessage(t *testing.T) { func TestErrorUsefulMessage(t *testing.T) {
s := NewFieldInvalid("foo", "bar", "deet").Error() s := NewFieldInvalid("foo", "bar", "deet").Error()
t.Logf("message: %v", s) t.Logf("message: %v", s)
for _, part := range []string{"foo", "bar", "deet", ValidationErrorTypeInvalid.String()} { for _, part := range []string{"foo", "bar", "deet", ErrorTypeInvalid.String()} {
if !strings.Contains(s, part) { if !strings.Contains(s, part) {
t.Errorf("error message did not contain expected part '%v'", part) t.Errorf("error message did not contain expected part '%v'", part)
} }
@@ -83,7 +83,7 @@ func TestValidationErrorUsefulMessage(t *testing.T) {
).Error() ).Error()
t.Logf("message: %v", s) t.Logf("message: %v", s)
for _, part := range []string{ for _, part := range []string{
"foo", ValidationErrorTypeInvalid.String(), "foo", ErrorTypeInvalid.String(),
"Baz", "Qux", "Inner", "KV", "detail", "Baz", "Qux", "Inner", "KV", "detail",
"1", "aoeu", "asdf", "Billy", "2", "1", "aoeu", "asdf", "Billy", "2",
} { } {
@@ -94,34 +94,22 @@ func TestValidationErrorUsefulMessage(t *testing.T) {
} }
func TestErrListFilter(t *testing.T) { func TestErrListFilter(t *testing.T) {
list := ValidationErrorList{ list := ErrorList{
NewFieldInvalid("test.field", "", ""), NewFieldInvalid("test.field", "", ""),
NewFieldInvalid("field.test", "", ""), NewFieldInvalid("field.test", "", ""),
NewFieldDuplicate("test", "value"), NewFieldDuplicate("test", "value"),
} }
if len(list.Filter(NewValidationErrorTypeMatcher(ValidationErrorTypeDuplicate))) != 2 { if len(list.Filter(NewErrorTypeMatcher(ErrorTypeDuplicate))) != 2 {
t.Errorf("should not filter") t.Errorf("should not filter")
} }
if len(list.Filter(NewValidationErrorTypeMatcher(ValidationErrorTypeInvalid))) != 1 { if len(list.Filter(NewErrorTypeMatcher(ErrorTypeInvalid))) != 1 {
t.Errorf("should filter")
}
if len(list.Filter(NewValidationErrorFieldPrefixMatcher("test"))) != 1 {
t.Errorf("should filter")
}
if len(list.Filter(NewValidationErrorFieldPrefixMatcher("test."))) != 2 {
t.Errorf("should filter")
}
if len(list.Filter(NewValidationErrorFieldPrefixMatcher(""))) != 0 {
t.Errorf("should filter")
}
if len(list.Filter(NewValidationErrorFieldPrefixMatcher("field."), NewValidationErrorTypeMatcher(ValidationErrorTypeDuplicate))) != 1 {
t.Errorf("should filter") t.Errorf("should filter")
} }
} }
func TestErrListPrefix(t *testing.T) { func TestErrListPrefix(t *testing.T) {
testCases := []struct { testCases := []struct {
Err *ValidationError Err *Error
Expected string Expected string
}{ }{
{ {
@@ -138,12 +126,12 @@ func TestErrListPrefix(t *testing.T) {
}, },
} }
for _, testCase := range testCases { for _, testCase := range testCases {
errList := ValidationErrorList{testCase.Err} errList := ErrorList{testCase.Err}
prefix := errList.Prefix("foo") prefix := errList.Prefix("foo")
if prefix == nil || len(prefix) != len(errList) { if prefix == nil || len(prefix) != len(errList) {
t.Errorf("Prefix should return self") t.Errorf("Prefix should return self")
} }
if e, a := testCase.Expected, errList[0].(*ValidationError).Field; e != a { if e, a := testCase.Expected, errList[0].(*Error).Field; e != a {
t.Errorf("expected %s, got %s", e, a) t.Errorf("expected %s, got %s", e, a)
} }
} }
@@ -151,7 +139,7 @@ func TestErrListPrefix(t *testing.T) {
func TestErrListPrefixIndex(t *testing.T) { func TestErrListPrefixIndex(t *testing.T) {
testCases := []struct { testCases := []struct {
Err *ValidationError Err *Error
Expected string Expected string
}{ }{
{ {
@@ -168,12 +156,12 @@ func TestErrListPrefixIndex(t *testing.T) {
}, },
} }
for _, testCase := range testCases { for _, testCase := range testCases {
errList := ValidationErrorList{testCase.Err} errList := ErrorList{testCase.Err}
prefix := errList.PrefixIndex(1) prefix := errList.PrefixIndex(1)
if prefix == nil || len(prefix) != len(errList) { if prefix == nil || len(prefix) != len(errList) {
t.Errorf("PrefixIndex should return self") t.Errorf("PrefixIndex should return self")
} }
if e, a := testCase.Expected, errList[0].(*ValidationError).Field; e != a { if e, a := testCase.Expected, errList[0].(*Error).Field; e != a {
t.Errorf("expected %s, got %s", e, a) t.Errorf("expected %s, got %s", e, a)
} }
} }