func validateOutput(output *buildapi.BuildOutput) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} // TODO: make part of a generic ValidateObjectReference method upstream. if output.To != nil { kind, name, namespace := output.To.Kind, output.To.Name, output.To.Namespace if len(kind) == 0 { kind = "ImageStream" output.To.Kind = kind } if kind != "ImageStream" { allErrs = append(allErrs, fielderrors.NewFieldInvalid("to.kind", kind, "the target of build output must be 'ImageStream'")) } if len(name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("to.name")) } else if !util.IsDNS1123Subdomain(name) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("to.name", name, "name must be a valid subdomain")) } if len(namespace) != 0 && !util.IsDNS1123Subdomain(namespace) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("to.namespace", namespace, "namespace must be a valid subdomain")) } } allErrs = append(allErrs, validateSecretRef(output.PushSecret).Prefix("pushSecret")...) if len(output.DockerImageReference) != 0 { if _, err := imageapi.ParseDockerImageReference(output.DockerImageReference); err != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("dockerImageReference", output.DockerImageReference, err.Error())) } } return allErrs }
func validateImageChangeParams(params *deployapi.DeploymentTriggerImageChangeParams) fielderrors.ValidationErrorList { errs := fielderrors.ValidationErrorList{} if len(params.From.Name) != 0 { if len(params.From.Kind) == 0 { params.From.Kind = "ImageStream" } kinds := util.NewStringSet("ImageRepository", "ImageStream", "ImageStreamTag") if !kinds.Has(params.From.Kind) { msg := fmt.Sprintf("kind must be one of: %s", strings.Join(kinds.List(), ", ")) errs = append(errs, fielderrors.NewFieldInvalid("from.kind", params.From.Kind, msg)) } if !util.IsDNS1123Subdomain(params.From.Name) { errs = append(errs, fielderrors.NewFieldInvalid("from.name", params.From.Name, "name must be a valid subdomain")) } if len(params.From.Namespace) != 0 && !util.IsDNS1123Subdomain(params.From.Namespace) { errs = append(errs, fielderrors.NewFieldInvalid("from.namespace", params.From.Namespace, "namespace must be a valid subdomain")) } if len(params.RepositoryName) != 0 { errs = append(errs, fielderrors.NewFieldInvalid("repositoryName", params.RepositoryName, "only one of 'from', 'repository' name may be specified")) } } else { if len(params.RepositoryName) == 0 { errs = append(errs, fielderrors.NewFieldRequired("from")) } } if len(params.ContainerNames) == 0 { errs = append(errs, fielderrors.NewFieldRequired("containerNames")) } return errs }
func validateToImageReference(reference *kapi.ObjectReference) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} kind, name, namespace := reference.Kind, reference.Name, reference.Namespace switch kind { case "ImageStreamTag": if len(name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("name")) } else if _, _, ok := imageapi.SplitImageStreamTag(name); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", name, "ImageStreamTag object references must be in the form <name>:<tag>")) } if len(namespace) != 0 && !util.IsDNS1123Subdomain(namespace) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("namespace", namespace, "namespace must be a valid subdomain")) } case "DockerImage": if len(namespace) != 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("namespace", namespace, "namespace is not valid when used with a 'DockerImage'")) } if _, err := imageapi.ParseDockerImageReference(name); err != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", name, fmt.Sprintf("name is not a valid Docker pull specification: %v", err))) } case "": allErrs = append(allErrs, fielderrors.NewFieldRequired("kind")) default: allErrs = append(allErrs, fielderrors.NewFieldInvalid("kind", kind, "the target of build output must be an 'ImageStreamTag' or 'DockerImage'")) } return allErrs }
// ValidateRoute tests if required fields in the route are set. func ValidateRoute(route *routeapi.Route) fielderrors.ValidationErrorList { result := fielderrors.ValidationErrorList{} //ensure meta is set properly result = append(result, kval.ValidateObjectMeta(&route.ObjectMeta, true, oapi.GetNameValidationFunc(kval.ValidatePodName)).Prefix("metadata")...) //host is not required but if it is set ensure it meets DNS requirements if len(route.Host) > 0 { if !util.IsDNS1123Subdomain(route.Host) { result = append(result, fielderrors.NewFieldInvalid("host", route.Host, "host must conform to DNS 952 subdomain conventions")) } } if len(route.Path) > 0 && !strings.HasPrefix(route.Path, "/") { result = append(result, fielderrors.NewFieldInvalid("path", route.Path, "path must begin with /")) } if len(route.ServiceName) == 0 { result = append(result, fielderrors.NewFieldRequired("serviceName")) } if errs := validateTLS(route); len(errs) != 0 { result = append(result, errs.Prefix("tls")...) } return result }
// ValidateObjectMeta validates an object's metadata on creation. It expects that name generation has already // been performed. func ValidateObjectMeta(meta *api.ObjectMeta, requiresNamespace bool, nameFn ValidateNameFunc) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if len(meta.GenerateName) != 0 { if ok, qualifier := nameFn(meta.GenerateName, true); !ok { allErrs = append(allErrs, errs.NewFieldInvalid("generateName", meta.GenerateName, qualifier)) } } // if the generated name validates, but the calculated value does not, it's a problem with generation, and we // report it here. This may confuse users, but indicates a programming bug and still must be validated. if len(meta.Name) == 0 { allErrs = append(allErrs, errs.NewFieldRequired("name")) } else { if ok, qualifier := nameFn(meta.Name, false); !ok { allErrs = append(allErrs, errs.NewFieldInvalid("name", meta.Name, qualifier)) } } if requiresNamespace { if len(meta.Namespace) == 0 { allErrs = append(allErrs, errs.NewFieldRequired("namespace")) } else if !util.IsDNS1123Subdomain(meta.Namespace) { allErrs = append(allErrs, errs.NewFieldInvalid("namespace", meta.Namespace, dnsSubdomainErrorMsg)) } } else { if len(meta.Namespace) != 0 { allErrs = append(allErrs, errs.NewFieldInvalid("namespace", meta.Namespace, "namespace is not allowed on this type")) } } allErrs = append(allErrs, ValidateLabels(meta.Labels, "labels")...) allErrs = append(allErrs, ValidateAnnotations(meta.Annotations, "annotations")...) return allErrs }
// nameIsDNSSubdomain is a ValidateNameFunc for names that must be a DNS subdomain. func nameIsDNSSubdomain(name string, prefix bool) (bool, string) { if prefix { name = maskTrailingDash(name) } if util.IsDNS1123Subdomain(name) { return true, "" } return false, dnsSubdomainErrorMsg }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, errs.NewFieldInvalid("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) } if !util.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, errs.NewFieldInvalid("namespace", event.Namespace, "")) } return allErrs }
func ValidateRoutingConfig(config api.RoutingConfig) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(config.Subdomain) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("subdomain")) } else if !util.IsDNS1123Subdomain(config.Subdomain) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("subdomain", config.Subdomain, "must be a valid subdomain")) } return allErrs }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} // TODO: There is no namespace required for minion if event.InvolvedObject.Kind != "Node" && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, errs.NewFieldInvalid("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) } if !util.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, errs.NewFieldInvalid("namespace", event.Namespace, "")) } return allErrs }
// NewSimpleAllocationPlugin creates a new SimpleAllocationPlugin. func NewSimpleAllocationPlugin(suffix string) (*SimpleAllocationPlugin, error) { if len(suffix) == 0 { suffix = defaultDNSSuffix } glog.V(4).Infof("Route plugin initialized with suffix=%s", suffix) // Check that the DNS suffix is valid. if !util.IsDNS1123Subdomain(suffix) { return nil, fmt.Errorf("invalid DNS suffix: %s", suffix) } return &SimpleAllocationPlugin{DNSSuffix: suffix}, nil }
func ValidateRoleBinding(roleBinding *authorizationapi.RoleBinding, isNamespaced bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, isNamespaced, oapi.MinimalNameRequirements).Prefix("metadata")...) // roleRef namespace is empty when referring to global policy. if (len(roleBinding.RoleRef.Namespace) > 0) && !util.IsDNS1123Subdomain(roleBinding.RoleRef.Namespace) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleRef.namespace", roleBinding.RoleRef.Namespace, "roleRef.namespace must be a valid subdomain")) } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("roleRef.name")) } else { if valid, err := oapi.MinimalNameRequirements(roleBinding.RoleRef.Name, false); !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleRef.name", roleBinding.RoleRef.Name, err)) } } return allErrs }
// ValidateSecret tests if required fields in the Secret are set. func ValidateSecret(secret *api.Secret) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} allErrs = append(allErrs, ValidateObjectMeta(&secret.ObjectMeta, true, ValidateSecretName).Prefix("metadata")...) totalSize := 0 for key, value := range secret.Data { if !util.IsDNS1123Subdomain(key) { allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, cIdentifierErrorMsg)) } totalSize += len(value) } if totalSize > api.MaxSecretSize { allErrs = append(allErrs, errs.NewFieldForbidden("data", "Maximum secret size exceeded")) } return allErrs }
func TestSimpleAllocationPlugin(t *testing.T) { tests := []struct { name string route *api.Route }{ { name: "No Name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "namespace", }, ServiceName: "service", }, }, { name: "No namespace", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", }, ServiceName: "nonamespace", }, }, { name: "No service name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, }, }, { name: "Valid route", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Host: "www.example.com", ServiceName: "myservice", }, }, { name: "No host", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, ServiceName: "myservice", }, }, } plugin, err := NewSimpleAllocationPlugin("www.example.org") if err != nil { t.Errorf("Error creating SimpleAllocationPlugin got %s", err) return } for _, tc := range tests { shard, _ := plugin.Allocate(tc.route) name := plugin.GenerateHostname(tc.route, shard) if len(name) <= 0 { t.Errorf("Test case %s got %d length name.", tc.name, len(name)) } if !util.IsDNS1123Subdomain(name) { t.Errorf("Test case %s got %s - invalid DNS name.", tc.name, name) } } }
func TestSimpleAllocationPluginViaController(t *testing.T) { tests := []struct { name string route *api.Route }{ { name: "No Name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "namespace", }, ServiceName: "service", }, }, { name: "No namespace", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", }, ServiceName: "nonamespace", }, }, { name: "No service name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, }, }, { name: "Valid route", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Host: "www.example.com", ServiceName: "s3", }, }, } plugin, _ := NewSimpleAllocationPlugin("www.example.org") fac := &rac.RouteAllocationControllerFactory{nil, nil} sac := fac.Create(plugin) for _, tc := range tests { shard, err := sac.AllocateRouterShard(tc.route) if err != nil { t.Errorf("Test case %s got an error %s", tc.name, err) } name := sac.GenerateHostname(tc.route, shard) if len(name) <= 0 { t.Errorf("Test case %s got %d length name", tc.name, len(name)) } if !util.IsDNS1123Subdomain(name) { t.Errorf("Test case %s got %s - invalid DNS name.", tc.name, name) } } }