// ValidateImageStreamMapping tests required fields for an ImageStreamMapping. func ValidateImageStreamMapping(mapping *api.ImageStreamMapping) field.ErrorList { result := validation.ValidateObjectMeta(&mapping.ObjectMeta, true, oapi.MinimalNameRequirements, field.NewPath("metadata")) hasRepository := len(mapping.DockerImageRepository) != 0 hasName := len(mapping.Name) != 0 switch { case hasRepository: if _, err := api.ParseDockerImageReference(mapping.DockerImageRepository); err != nil { result = append(result, field.Invalid(field.NewPath("dockerImageRepository"), mapping.DockerImageRepository, err.Error())) } case hasName: default: result = append(result, field.Required(field.NewPath("name"), "")) result = append(result, field.Required(field.NewPath("dockerImageRepository"), "")) } if ok, msg := validation.ValidateNamespaceName(mapping.Namespace, false); !ok { result = append(result, field.Invalid(field.NewPath("metadata", "namespace"), mapping.Namespace, msg)) } if len(mapping.Tag) == 0 { result = append(result, field.Required(field.NewPath("tag"), "")) } if errs := validateImage(&mapping.Image, field.NewPath("image")); len(errs) != 0 { result = append(result, errs...) } return result }
func validateRoleBinding(roleBinding *rbac.RoleBinding, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, isNamespaced, minimalNameRequirements, fldPath.Child("metadata"))...) // roleRef namespace is empty when referring to global policy. if len(roleBinding.RoleRef.Namespace) > 0 { if ok, reason := validation.ValidateNamespaceName(roleBinding.RoleRef.Namespace, false); !ok { allErrs = append(allErrs, field.Invalid(fldPath.Child("roleRef", "namespace"), roleBinding.RoleRef.Namespace, reason)) } } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("roleRef", "name"), "")) } else { if valid, err := minimalNameRequirements(roleBinding.RoleRef.Name, false); !valid { allErrs = append(allErrs, field.Invalid(fldPath.Child("roleRef", "name"), roleBinding.RoleRef.Name, err)) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { allErrs = append(allErrs, validateRoleBindingSubject(subject, isNamespaced, subjectsPath.Index(i))...) } return allErrs }
func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...) // roleRef namespace is empty when referring to global policy. if len(roleBinding.RoleRef.Namespace) > 0 { for _, msg := range validation.ValidateNamespaceName(roleBinding.RoleRef.Namespace, false) { allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "namespace"), roleBinding.RoleRef.Namespace, msg)) } } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), "")) } else { for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) { allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg)) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { allErrs = append(allErrs, validateRoleBindingSubject(subject, false, subjectsPath.Index(i))...) } return allErrs }
func ValidateNamespace(namespace, field string) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(namespace) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired(field)) } else if ok, _ := kvalidation.ValidateNamespaceName(namespace, false); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid(field, namespace, "must be a valid namespace")) } return allErrs }
func ValidateNamespace(namespace string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(namespace) == 0 { allErrs = append(allErrs, field.Required(fldPath, "")) } else if reasons := kvalidation.ValidateNamespaceName(namespace, false); len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(fldPath, namespace, "must be a valid namespace")) } return allErrs }
func PodMetricsUrl(namespace string, name string) (string, error) { errs := validation.ValidateNamespaceName(namespace, false) if len(errs) > 0 { message := fmt.Sprintf("invalid namespace: %s - %v", namespace, errs) return "", errors.New(message) } if len(name) > 0 { errs = validation.ValidatePodName(name, false) if len(errs) > 0 { message := fmt.Sprintf("invalid pod name: %s - %v", name, errs) return "", errors.New(message) } } return fmt.Sprintf("%s/namespaces/%s/pods/%s", MetricsRoot, namespace, name), nil }
func ValidateProjectName(name string, prefix bool) (bool, string) { if ok, reason := oapi.MinimalNameRequirements(name, prefix); !ok { return ok, reason } if len(name) < 2 { return false, "must be at least 2 characters long" } if ok, msg := validation.ValidateNamespaceName(name, false); !ok { return ok, msg } return true, "" }
func ValidateProjectName(name string, prefix bool) []string { if reasons := path.ValidatePathSegmentName(name, prefix); len(reasons) != 0 { return reasons } if len(name) < 2 { return []string{"must be at least 2 characters long"} } if reasons := validation.ValidateNamespaceName(name, false); len(reasons) != 0 { return reasons } return nil }
func ValidateProjectName(name string, prefix bool) []string { if reasons := oapi.MinimalNameRequirements(name, prefix); len(reasons) != 0 { return reasons } if len(name) < 2 { return []string{"must be at least 2 characters long"} } if reasons := validation.ValidateNamespaceName(name, false); len(reasons) != 0 { return reasons } return nil }
// SplitUsername returns the namespace and ServiceAccount name embedded in the given username, // or an error if the username is not a valid name produced by MakeUsername func SplitUsername(username string) (string, string, error) { if !strings.HasPrefix(username, ServiceAccountUsernamePrefix) { return "", "", invalidUsernameErr } trimmed := strings.TrimPrefix(username, ServiceAccountUsernamePrefix) parts := strings.Split(trimmed, ServiceAccountUsernameSeparator) if len(parts) != 2 { return "", "", invalidUsernameErr } namespace, name := parts[0], parts[1] if len(validation.ValidateNamespaceName(namespace, false)) != 0 { return "", "", invalidUsernameErr } if len(validation.ValidateServiceAccountName(name, false)) != 0 { return "", "", invalidUsernameErr } return namespace, name, nil }
func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.Role) }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.ClusterRole) }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageImportSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To == nil { // To is defaulted to be not nil j.To = &api.LocalObjectReference{} } }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } if j.Tags == nil { j.Tags = make(map[string]image.TagReference) } }, func(j *image.ImageStreamStatus, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.To = api.ObjectReference{ Kind: "Service", Name: j.To.Name, } }, func(j *route.TLSConfig, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Termination) == 0 && len(j.DestinationCACertificate) == 0 { j.Termination = route.TLSTerminationEdge } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} if forVersion == "v1beta3" { // v1beta3 does not contain the PodSecurityContext type. For this API version, only fuzz // the host namespace fields. The fields set to nil here are the other fields of the // PodSecurityContext that will not roundtrip correctly from internal->v1beta3->internal. j.Spec.Template.Spec.SecurityContext.SELinuxOptions = nil j.Spec.Template.Spec.SecurityContext.RunAsUser = nil j.Spec.Template.Spec.SecurityContext.RunAsNonRoot = nil j.Spec.Template.Spec.SecurityContext.SupplementalGroups = nil j.Spec.Template.Spec.SecurityContext.FSGroup = nil } }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) strategyTypes := []deploy.DeploymentStrategyType{deploy.DeploymentStrategyTypeRecreate, deploy.DeploymentStrategyTypeRolling, deploy.DeploymentStrategyTypeCustom} j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] switch j.Type { case deploy.DeploymentStrategyTypeRolling: params := &deploy.RollingDeploymentStrategyParams{} randInt64 := func() *int64 { p := int64(c.RandUint64()) return &p } params.TimeoutSeconds = randInt64() params.IntervalSeconds = randInt64() params.UpdatePeriodSeconds = randInt64() policyTypes := []deploy.LifecycleHookFailurePolicy{ deploy.LifecycleHookFailurePolicyRetry, deploy.LifecycleHookFailurePolicyAbort, deploy.LifecycleHookFailurePolicyIgnore, } if c.RandBool() { params.Pre = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.Post = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.MaxUnavailable = util.NewIntOrStringFromInt(int(c.RandUint64())) params.MaxSurge = util.NewIntOrStringFromInt(int(c.RandUint64())) } else { params.MaxSurge = util.NewIntOrStringFromString(fmt.Sprintf("%d%%", c.RandUint64())) params.MaxUnavailable = util.NewIntOrStringFromString(fmt.Sprintf("%d%%", c.RandUint64())) } j.RollingParams = params default: j.RollingParams = nil } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"stuff", "other"} j.From.Name = specs[c.Intn(len(specs))] if len(j.From.Name) > 0 { j.From.Name = image.JoinImageStreamTag(j.From.Name, tags[c.Intn(len(tags))]) } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] }, func(j *runtime.EmbeddedObject, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { c.FuzzNoCustom(j) if j.Roles != nil { j.Roles = make(map[string]*authorizationapi.Role) } for k, v := range j.Roles { if v == nil { delete(j.Roles, k) } } }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { c.FuzzNoCustom(j) if j.RoleBindings == nil { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) } for k, v := range j.RoleBindings { if v == nil { delete(j.RoleBindings, k) } } }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { c.FuzzNoCustom(j) if j.Roles == nil { j.Roles = make(map[string]*authorizationapi.ClusterRole) } for k, v := range j.Roles { if v == nil { delete(j.Roles, k) } } }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateUserName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateGroupName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if len(validation.ValidateNamespaceName(j.Subjects[i].Namespace, false)) != 0 { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if len(validation.ValidateServiceAccountName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.PolicyRule, c fuzz.Continue) { c.FuzzNoCustom(j) // if no groups are found, then we assume "". This matches defaulting if len(j.APIGroups) == 0 { j.APIGroups = []string{""} } switch c.Intn(3) { case 0: j.AttributeRestrictions = &authorizationapi.IsPersonalSubjectAccessReview{} case 1: j.AttributeRestrictions = &runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "Type", APIVersion: "other"}, ContentType: "application/json", Raw: []byte(`{"apiVersion":"other","kind":"Type"}`)} default: j.AttributeRestrictions = nil } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateUserName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateGroupName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if len(validation.ValidateNamespaceName(j.Subjects[i].Namespace, false)) != 0 { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if len(validation.ValidateServiceAccountName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) c.Fuzz(&j.Signatures) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageSignature, c fuzz.Continue) { c.FuzzNoCustom(j) j.Conditions = nil j.ImageIdentity = "" j.SignedClaims = nil j.Created = nil j.IssuedBy = nil j.IssuedTo = nil }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageImportSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To == nil { // To is defaulted to be not nil j.To = &kapi.LocalObjectReference{} } }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } if j.Tags == nil { j.Tags = make(map[string]image.TagReference) } for k, v := range j.Tags { v.Name = k j.Tags[k] = v } }, func(j *image.ImageStreamStatus, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.BuildConfigSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.RunPolicy = build.BuildRunPolicySerial }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteTargetReference, c fuzz.Continue) { c.FuzzNoCustom(j) j.Kind = "Service" j.Weight = new(int32) *j.Weight = 100 }, func(j *route.TLSConfig, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Termination) == 0 && len(j.DestinationCACertificate) == 0 { j.Termination = route.TLSTerminationEdge } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} if j.Spec.Template != nil && len(j.Spec.Template.Spec.Containers) == 1 { containerName := j.Spec.Template.Spec.Containers[0].Name if p := j.Spec.Strategy.RecreateParams; p != nil { defaultHookContainerName(p.Pre, containerName) defaultHookContainerName(p.Mid, containerName) defaultHookContainerName(p.Post, containerName) } if p := j.Spec.Strategy.RollingParams; p != nil { defaultHookContainerName(p.Pre, containerName) defaultHookContainerName(p.Post, containerName) } } }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.RecreateParams, j.RollingParams, j.CustomParams = nil, nil, nil strategyTypes := []deploy.DeploymentStrategyType{deploy.DeploymentStrategyTypeRecreate, deploy.DeploymentStrategyTypeRolling, deploy.DeploymentStrategyTypeCustom} j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] switch j.Type { case deploy.DeploymentStrategyTypeRecreate: params := &deploy.RecreateDeploymentStrategyParams{} c.Fuzz(params) if params.TimeoutSeconds == nil { s := int64(120) params.TimeoutSeconds = &s } j.RecreateParams = params case deploy.DeploymentStrategyTypeRolling: params := &deploy.RollingDeploymentStrategyParams{} randInt64 := func() *int64 { p := int64(c.RandUint64()) return &p } params.TimeoutSeconds = randInt64() params.IntervalSeconds = randInt64() params.UpdatePeriodSeconds = randInt64() policyTypes := []deploy.LifecycleHookFailurePolicy{ deploy.LifecycleHookFailurePolicyRetry, deploy.LifecycleHookFailurePolicyAbort, deploy.LifecycleHookFailurePolicyIgnore, } if c.RandBool() { params.Pre = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.Post = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.MaxUnavailable = intstr.FromInt(int(c.RandUint64())) params.MaxSurge = intstr.FromInt(int(c.RandUint64())) } else { params.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64())) params.MaxUnavailable = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64())) } j.RollingParams = params } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"stuff", "other"} j.From.Name = specs[c.Intn(len(specs))] if len(j.From.Name) > 0 { j.From.Name = image.JoinImageStreamTag(j.From.Name, tags[c.Intn(len(tags))]) } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] }, // TODO: uncomment when round tripping for init containers is available (the annotation is // not supported on security context review for now) func(j *securityapi.PodSecurityPolicyReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil for i := range j.Status.AllowedServiceAccounts { j.Status.AllowedServiceAccounts[i].Template.Spec.InitContainers = nil } }, func(j *securityapi.PodSecurityPolicySelfSubjectReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil j.Status.Template.Spec.InitContainers = nil }, func(j *securityapi.PodSecurityPolicySubjectReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil j.Status.Template.Spec.InitContainers = nil }, func(j *oauthapi.OAuthAuthorizeToken, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.CodeChallenge) > 0 && len(j.CodeChallengeMethod) == 0 { j.CodeChallengeMethod = "plain" } }, func(j *oauthapi.OAuthClientAuthorization, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Scopes) == 0 { j.Scopes = append(j.Scopes, "user:full") } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.WildcardPolicy) == 0 { j.WildcardPolicy = route.WildcardPolicyNone } }, func(j *route.RouteIngress, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.WildcardPolicy) == 0 { j.WildcardPolicy = route.WildcardPolicyNone } }, func(j *runtime.Object, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.Role) }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.ClusterRole) }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.To = api.ObjectReference{ Kind: "Service", Name: j.To.Name, } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) mkintp := func(i int) *int64 { v := int64(i) return &v } switch c.Intn(3) { case 0: // TODO: we should not have to set defaults, instead we should be able // to detect defaults were applied. j.Type = deploy.DeploymentStrategyTypeRolling j.RollingParams = &deploy.RollingDeploymentStrategyParams{ IntervalSeconds: mkintp(1), UpdatePeriodSeconds: mkintp(1), TimeoutSeconds: mkintp(120), } case 1: j.Type = deploy.DeploymentStrategyTypeRecreate j.RollingParams = nil case 2: j.Type = deploy.DeploymentStrategyTypeCustom j.RollingParams = nil } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"", "stuff", "other"} j.RepositoryName = specs[c.Intn(len(specs))] if len(j.RepositoryName) > 0 { j.Tag = tags[c.Intn(len(tags))] } else { j.Tag = "" } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] if ref, err := image.ParseDockerImageReference(j.From.Name); err == nil { j.Tag = ref.Tag ref.Tag, ref.ID = "", "" j.RepositoryName = ref.String() } }, func(j *runtime.EmbeddedObject, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }