func validateRoleBindingSubject(subject kapi.ObjectReference, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(subject.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) } if len(subject.UID) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("uid"), fmt.Sprintf("%v", subject.UID))) } if len(subject.APIVersion) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("apiVersion"), subject.APIVersion)) } if len(subject.ResourceVersion) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("resourceVersion"), subject.ResourceVersion)) } if len(subject.FieldPath) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("fieldPath"), subject.FieldPath)) } switch subject.Kind { case authorizationapi.ServiceAccountKind: if reasons := validation.ValidateServiceAccountName(subject.Name, false); len(subject.Name) > 0 && len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, strings.Join(reasons, ", "))) } if !isNamespaced && len(subject.Namespace) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "Service account subjects for ClusterRoleBindings must have a namespace")) } case authorizationapi.UserKind: if reasons := uservalidation.ValidateUserName(subject.Name, false); len(subject.Name) > 0 && len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, strings.Join(reasons, ", "))) } case authorizationapi.GroupKind: if reasons := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, strings.Join(reasons, ", "))) } case authorizationapi.SystemUserKind: isValidSAName := len(validation.ValidateServiceAccountName(subject.Name, false)) == 0 isValidUserName := len(uservalidation.ValidateUserName(subject.Name, false)) == 0 if isValidSAName || isValidUserName { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "conforms to User.name or ServiceAccount.name restrictions")) } case authorizationapi.SystemGroupKind: if reasons := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && len(reasons) == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "conforms to Group.name restrictions")) } default: allErrs = append(allErrs, field.NotSupported(fldPath.Child("kind"), subject.Kind, []string{authorizationapi.ServiceAccountKind, authorizationapi.UserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.SystemUserKind})) } return allErrs }
func ValidateRoleBindingSubject(subject kapi.ObjectReference, isNamespaced bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(subject.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("name")) } if len(subject.UID) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("uid", subject.UID)) } if len(subject.APIVersion) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("apiVersion", subject.APIVersion)) } if len(subject.ResourceVersion) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("resourceVersion", subject.ResourceVersion)) } if len(subject.FieldPath) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("fieldPath", subject.FieldPath)) } switch subject.Kind { case authorizationapi.ServiceAccountKind: if valid, reason := validation.ValidateServiceAccountName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } if !isNamespaced && len(subject.Namespace) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("namespace")) } case authorizationapi.UserKind: if valid, reason := uservalidation.ValidateUserName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } case authorizationapi.GroupKind: if valid, reason := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } case authorizationapi.SystemUserKind: isValidSAName, _ := validation.ValidateServiceAccountName(subject.Name, false) isValidUserName, _ := uservalidation.ValidateUserName(subject.Name, false) if isValidSAName || isValidUserName { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, "conforms to User.name or ServiceAccount.name restrictions")) } case authorizationapi.SystemGroupKind: if valid, _ := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, "conforms to Group.name restrictions")) } default: allErrs = append(allErrs, fielderrors.NewFieldValueNotSupported("kind", subject.Kind, []string{authorizationapi.ServiceAccountKind, authorizationapi.UserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.SystemUserKind})) } return allErrs }
func ValidateServiceAccountConfig(config api.ServiceAccountConfig, builtInKubernetes bool, fldPath *field.Path) ValidationResults { validationResults := ValidationResults{} managedNames := sets.NewString(config.ManagedNames...) managedNamesPath := fldPath.Child("managedNames") if !managedNames.Has(bootstrappolicy.BuilderServiceAccountName) { validationResults.AddWarnings(field.Invalid(managedNamesPath, "", fmt.Sprintf("missing %q, which will require manual creation in each namespace before builds can run", bootstrappolicy.BuilderServiceAccountName))) } if !managedNames.Has(bootstrappolicy.DeployerServiceAccountName) { validationResults.AddWarnings(field.Invalid(managedNamesPath, "", fmt.Sprintf("missing %q, which will require manual creation in each namespace before deployments can run", bootstrappolicy.DeployerServiceAccountName))) } if builtInKubernetes && !managedNames.Has(bootstrappolicy.DefaultServiceAccountName) { validationResults.AddWarnings(field.Invalid(managedNamesPath, "", fmt.Sprintf("missing %q, which will prevent creation of pods that do not specify a valid service account", bootstrappolicy.DefaultServiceAccountName))) } for i, name := range config.ManagedNames { if reasons := kvalidation.ValidateServiceAccountName(name, false); len(reasons) != 0 { validationResults.AddErrors(field.Invalid(managedNamesPath.Index(i), name, strings.Join(reasons, ", "))) } } if len(config.PrivateKeyFile) > 0 { privateKeyFilePath := fldPath.Child("privateKeyFile") if fileErrs := ValidateFile(config.PrivateKeyFile, privateKeyFilePath); len(fileErrs) > 0 { validationResults.AddErrors(fileErrs...) } else if privateKey, err := serviceaccount.ReadPrivateKey(config.PrivateKeyFile); err != nil { validationResults.AddErrors(field.Invalid(privateKeyFilePath, config.PrivateKeyFile, err.Error())) } else if err := privateKey.Validate(); err != nil { validationResults.AddErrors(field.Invalid(privateKeyFilePath, config.PrivateKeyFile, err.Error())) } } else if builtInKubernetes { validationResults.AddWarnings(field.Invalid(fldPath.Child("privateKeyFile"), "", "no service account tokens will be generated, which could prevent builds and deployments from working")) } if len(config.PublicKeyFiles) == 0 { validationResults.AddWarnings(field.Invalid(fldPath.Child("publicKeyFiles"), "", "no service account tokens will be accepted by the API, which will prevent builds and deployments from working")) } for i, publicKeyFile := range config.PublicKeyFiles { idxPath := fldPath.Child("publicKeyFiles").Index(i) if fileErrs := ValidateFile(publicKeyFile, idxPath); len(fileErrs) > 0 { validationResults.AddErrors(fileErrs...) } else if _, err := serviceaccount.ReadPublicKey(publicKeyFile); err != nil { validationResults.AddErrors(field.Invalid(idxPath, publicKeyFile, err.Error())) } } if len(config.MasterCA) > 0 { validationResults.AddErrors(ValidateFile(config.MasterCA, fldPath.Child("masterCA"))...) } else if builtInKubernetes { validationResults.AddWarnings(field.Invalid(fldPath.Child("masterCA"), "", "master CA information will not be automatically injected into pods, which will prevent verification of the API server from inside a pod")) } return validationResults }
func ValidateClientNameField(value string, fldPath *field.Path) field.ErrorList { if len(value) == 0 { return field.ErrorList{field.Required(fldPath, "")} } else if _, saName, err := serviceaccount.SplitUsername(value); err == nil { if reasons := validation.ValidateServiceAccountName(saName, false); len(reasons) != 0 { return field.ErrorList{field.Invalid(fldPath, value, strings.Join(reasons, ", "))} } } else if reasons := validation.NameIsDNSSubdomain(value, false); len(reasons) != 0 { return field.ErrorList{field.Invalid(fldPath, value, strings.Join(reasons, ", "))} } return field.ErrorList{} }
func ValidateClientNameField(value string, fldPath *field.Path) field.ErrorList { if len(value) == 0 { return field.ErrorList{field.Required(fldPath, "")} } else if _, saName, err := serviceaccount.SplitUsername(value); err == nil { if ok, errString := validation.ValidateServiceAccountName(saName, false); !ok { return field.ErrorList{field.Invalid(fldPath, value, errString)} } } else if ok, msg := validation.NameIsDNSSubdomain(value, false); !ok { return field.ErrorList{field.Invalid(fldPath, value, msg)} } return field.ErrorList{} }
func validateServiceAccountNames(serviceAccountNames []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for i, sa := range serviceAccountNames { idxPath := fldPath.Index(i) switch { case len(sa) == 0: allErrs = append(allErrs, field.Invalid(idxPath, sa, "")) case len(sa) > 0: if reasons := kapivalidation.ValidateServiceAccountName(sa, false); len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(idxPath, sa, strings.Join(reasons, ", "))) } } } return allErrs }
// 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 validateRoleBindingSubject(subject rbac.Subject, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(subject.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) } if len(subject.APIVersion) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("apiVersion"), subject.APIVersion)) } switch subject.Kind { case rbac.ServiceAccountKind: if len(subject.Name) > 0 { for _, msg := range validation.ValidateServiceAccountName(subject.Name, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, msg)) } } if !isNamespaced && len(subject.Namespace) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "")) } case rbac.UserKind: // TODO(ericchiang): What other restrictions on user name are there? if len(subject.Name) == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "user name cannot be empty")) } case rbac.GroupKind: // TODO(ericchiang): What other restrictions on group name are there? if len(subject.Name) == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "group name cannot be empty")) } default: allErrs = append(allErrs, field.NotSupported(fldPath.Child("kind"), subject.Kind, []string{rbac.ServiceAccountKind, rbac.UserKind, rbac.GroupKind})) } return allErrs }
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 }