// TestTypes will try to roundtrip all OpenShift and Kubernetes stable api types func TestTypes(t *testing.T) { for kind, reflectType := range kapi.Scheme.KnownTypes(osapi.SchemeGroupVersion) { if !strings.Contains(reflectType.PkgPath(), "/origin/") && reflectType.PkgPath() != "k8s.io/kubernetes/pkg/api" { continue } if nonInternalRoundTrippableTypes.Has(kind) { continue } // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { item, err := kapi.Scheme.New(osapi.SchemeGroupVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } seed := rand.Int63() if versions, ok := skipStandardVersions[kind]; ok { for _, v := range versions { t.Logf("About to test %v with %q", kind, v) fuzzInternalObject(t, v, item, seed) roundTrip(t, kapi.Codecs.LegacyCodec(v), item) } continue } t.Logf(`About to test %v with "v1"`, kind) fuzzInternalObject(t, v1.SchemeGroupVersion, item, seed) roundTrip(t, kapi.Codecs.LegacyCodec(v1.SchemeGroupVersion), item) } } }
func TestTypes(t *testing.T) { for kind, reflectType := range api.Scheme.KnownTypes("") { if !strings.Contains(reflectType.PkgPath(), "/origin/") { continue } t.Logf("About to test %v", reflectType) // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { item, err := api.Scheme.New("", kind) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } seed := rand.Int63() if versions, ok := skipStandardVersions[kind]; ok { for _, v := range versions { fuzzInternalObject(t, "", item, seed) roundTrip(t, runtime.CodecFor(api.Scheme, v), item) } continue } fuzzInternalObject(t, "", item, seed) roundTrip(t, osapi.Codec, item) fuzzInternalObject(t, "v1beta3", item, seed) roundTrip(t, v1beta3.Codec, item) fuzzInternalObject(t, "v1", item, seed) roundTrip(t, v1.Codec, item) } } }
func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)).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 doRoundTripTest(kind string, t *testing.T) { item, err := api.Scheme.New("", kind) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } roundTripSame(t, item, nonRoundTrippableTypesByVersion[kind]...) if !nonInternalRoundTrippableTypes.Has(kind) { roundTrip(t, api.Codec, fuzzInternalObject(t, "", item, rand.Int63())) } }
func TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` APIVersion string `json:"apiVersion,omitempty"` Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"` Finalizers []string `json:"finalizers,omitempty"` } j := struct{ TypeMeta }{TypeMeta{APIVersion: "a", Kind: "b"}} typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }
func doRoundTripTest(group testapi.TestGroup, kind string, t *testing.T) { item, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } if api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTripSame(t, group, item, nonRoundTrippableTypesByVersion[kind]...) } if !nonInternalRoundTrippableTypes.Has(kind) && api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTrip(t, group.Codec(), fuzzInternalObject(t, group.InternalGroupVersion(), item, rand.Int63())) } }
// TestTypes will try to roundtrip all OpenShift and Kubernetes stable api types func TestTypes(t *testing.T) { for kind := range configapi.Scheme.KnownTypes(configapi.SchemeGroupVersion) { // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { item, err := configapi.Scheme.New(configapi.SchemeGroupVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } seed := rand.Int63() fuzzInternalObject(t, configapiv1.SchemeGroupVersion, item, seed) roundTrip(t, serializer.NewCodecFactory(configapi.Scheme).LegacyCodec(configapiv1.SchemeGroupVersion), item) } } }
// TestTypes will try to roundtrip all OpenShift and Kubernetes stable api types func TestTypes(t *testing.T) { internalVersionToExternalVersions := map[unversioned.GroupVersion][]unversioned.GroupVersion{ osapi.SchemeGroupVersion: {v1.SchemeGroupVersion}, quotaapi.SchemeGroupVersion: {quotaapiv1.SchemeGroupVersion}, } for internalVersion, externalVersions := range internalVersionToExternalVersions { for kind, reflectType := range kapi.Scheme.KnownTypes(internalVersion) { if !strings.Contains(reflectType.PkgPath(), "github.com/openshift/origin/") && reflectType.PkgPath() != "github.com/openshift/origin/vendor/k8s.io/kubernetes/pkg/api" { continue } if nonInternalRoundTrippableTypes.Has(kind) { continue } for _, externalVersion := range externalVersions { // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { item, err := kapi.Scheme.New(internalVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } seed := rand.Int63() if versions, ok := skipStandardVersions[kind]; ok { for _, v := range versions { fuzzInternalObject(t, v, item, seed) roundTrip(t, kapi.Codecs.LegacyCodec(v), item) } continue } fuzzInternalObject(t, externalVersion, item, seed) roundTripWithAllCodecs(t, externalVersion, item) } } } } }
func fuzzImageSignature(t *testing.T, signature *api.ImageSignature, seed int64) *api.ImageSignature { f := apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(seed)) f.Funcs( func(j *api.ImageSignature, c fuzz.Continue) { c.FuzzNoCustom(j) j.Annotations = make(map[string]string) j.Labels = make(map[string]string) j.Conditions = []api.SignatureCondition{} j.SignedClaims = make(map[string]string) j.Content = []byte(c.RandString()) for i := 0; i < c.Rand.Intn(3)+2; i++ { j.Labels[c.RandString()] = c.RandString() j.Annotations[c.RandString()] = c.RandString() j.SignedClaims[c.RandString()] = c.RandString() } for i := 0; i < c.Rand.Intn(3)+2; i++ { cond := api.SignatureCondition{} c.Fuzz(&cond) j.Conditions = append(j.Conditions, cond) } }, ) updated := api.ImageSignature{} f.Fuzz(&updated) updated.Namespace = signature.Namespace updated.Name = signature.Name j, err := meta.TypeAccessor(signature) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, signature) } j.SetKind("") j.SetAPIVersion("") return &updated }
func fuzzImage(t *testing.T, image *api.Image, seed int64) *api.Image { f := apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(seed)) f.Funcs( func(j *api.Image, c fuzz.Continue) { c.FuzzNoCustom(j) j.Annotations = make(map[string]string) j.Labels = make(map[string]string) j.Signatures = make([]api.ImageSignature, c.Rand.Intn(3)+2) for i := range j.Signatures { sign := &j.Signatures[i] c.Fuzz(sign) sign.Conditions = make([]api.SignatureCondition, c.Rand.Intn(3)+2) for ci := range sign.Conditions { cond := &sign.Conditions[ci] c.Fuzz(cond) } } for i := 0; i < c.Rand.Intn(3)+2; i++ { j.Labels[c.RandString()] = c.RandString() j.Annotations[c.RandString()] = c.RandString() } }, ) updated := api.Image{} f.Fuzz(&updated) updated.Namespace = image.Namespace updated.Name = image.Name j, err := meta.TypeAccessor(image) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, image) } j.SetKind("") j.SetAPIVersion("") return &updated }
func TestRoundTripTypes(t *testing.T) { // api.Scheme.Log(t) // defer api.Scheme.Log(nil) for kind := range api.Scheme.KnownTypes("") { if nonRoundTrippableTypes.Has(kind) { continue } // Try a few times, since runTest uses random values. for i := 0; i < *fuzzIters; i++ { item, err := api.Scheme.New("", kind) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } roundTripSame(t, item, nonRoundTrippableTypesByVersion[kind]...) if !nonInternalRoundTrippableTypes.Has(kind) { roundTrip(t, api.Codec, fuzzInternalObject(t, "", item, rand.Int63())) } } } }
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 }
func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { f := fuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // these follow defaulting rules func(obj *configapi.MasterConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.APILevels) == 0 { obj.APILevels = configapi.DefaultOpenShiftAPILevels } if len(obj.Controllers) == 0 { obj.Controllers = configapi.ControllersAll } if obj.ServingInfo.RequestTimeoutSeconds == 0 { obj.ServingInfo.RequestTimeoutSeconds = 60 * 60 } if obj.ServingInfo.MaxRequestsInFlight == 0 { obj.ServingInfo.MaxRequestsInFlight = 500 } if len(obj.PolicyConfig.OpenShiftInfrastructureNamespace) == 0 { obj.PolicyConfig.OpenShiftInfrastructureNamespace = bootstrappolicy.DefaultOpenShiftInfraNamespace } if len(obj.RoutingConfig.Subdomain) == 0 { obj.RoutingConfig.Subdomain = "router.default.svc.cluster.local" } // Populate the new NetworkConfig.ServiceNetworkCIDR field from the KubernetesMasterConfig.ServicesSubnet field if needed if len(obj.NetworkConfig.ServiceNetworkCIDR) == 0 { if obj.KubernetesMasterConfig != nil && len(obj.KubernetesMasterConfig.ServicesSubnet) > 0 { // if a subnet is set in the kubernetes master config, use that obj.NetworkConfig.ServiceNetworkCIDR = obj.KubernetesMasterConfig.ServicesSubnet } else { // default ServiceClusterIPRange used by kubernetes if nothing is specified obj.NetworkConfig.ServiceNetworkCIDR = "10.0.0.0/24" } } // Historically, the clientCA was incorrectly used as the master's server cert CA bundle // If missing from the config, migrate the ClientCA into that field if obj.OAuthConfig != nil && obj.OAuthConfig.MasterCA == nil { s := obj.ServingInfo.ClientCA // The final value of OAuthConfig.MasterCA should never be nil obj.OAuthConfig.MasterCA = &s } }, func(obj *configapi.KubernetesMasterConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.MasterCount == 0 { obj.MasterCount = 1 } if len(obj.ServicesNodePortRange) == 0 { obj.ServicesNodePortRange = "30000-32767" } if len(obj.PodEvictionTimeout) == 0 { obj.PodEvictionTimeout = "5m" } }, func(obj *configapi.JenkinsPipelineConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.Enabled == nil { v := c.RandBool() obj.Enabled = &v } if len(obj.TemplateNamespace) == 0 { obj.TemplateNamespace = "value" } if len(obj.TemplateName) == 0 { obj.TemplateName = "anothervalue" } if len(obj.ServiceName) == 0 { obj.ServiceName = "thirdvalue" } }, func(obj *configapi.NodeConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) // Defaults/migrations for NetworkConfig if len(obj.NetworkConfig.NetworkPluginName) == 0 { obj.NetworkConfig.NetworkPluginName = "plugin-name" } if obj.NetworkConfig.MTU == 0 { obj.NetworkConfig.MTU = 1450 } if len(obj.IPTablesSyncPeriod) == 0 { obj.IPTablesSyncPeriod = "5s" } // Auth cache defaults if len(obj.AuthConfig.AuthenticationCacheTTL) == 0 { obj.AuthConfig.AuthenticationCacheTTL = "5m" } if obj.AuthConfig.AuthenticationCacheSize == 0 { obj.AuthConfig.AuthenticationCacheSize = 1000 } if len(obj.AuthConfig.AuthorizationCacheTTL) == 0 { obj.AuthConfig.AuthorizationCacheTTL = "5m" } if obj.AuthConfig.AuthorizationCacheSize == 0 { obj.AuthConfig.AuthorizationCacheSize = 1000 } }, func(obj *configapi.EtcdStorageConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.KubernetesStorageVersion) == 0 { obj.KubernetesStorageVersion = "v1" } if len(obj.KubernetesStoragePrefix) == 0 { obj.KubernetesStoragePrefix = "kubernetes.io" } if len(obj.OpenShiftStorageVersion) == 0 { obj.OpenShiftStorageVersion = configapi.DefaultOpenShiftStorageVersionLevel } if len(obj.OpenShiftStoragePrefix) == 0 { obj.OpenShiftStoragePrefix = "openshift.io" } }, func(obj *configapi.DockerConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.ExecHandlerName) == 0 { obj.ExecHandlerName = configapi.DockerExecHandlerNative } }, func(obj *configapi.ServingInfo, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.BindNetwork) == 0 { obj.BindNetwork = "tcp4" } }, func(obj *configapi.ImagePolicyConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.MaxImagesBulkImportedPerRepository == 0 { obj.MaxImagesBulkImportedPerRepository = 5 } if obj.MaxScheduledImageImportsPerMinute == 0 { obj.MaxScheduledImageImportsPerMinute = 60 } if obj.ScheduledImageImportMinimumIntervalSeconds == 0 { obj.ScheduledImageImportMinimumIntervalSeconds = 15 * 60 } }, func(obj *configapi.DNSConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.BindNetwork) == 0 { obj.BindNetwork = "tcp4" } }, func(obj *configapi.SecurityAllocator, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.UIDAllocatorRange) == 0 { obj.UIDAllocatorRange = "1000000000-1999999999/10000" } if len(obj.MCSAllocatorRange) == 0 { obj.MCSAllocatorRange = "s0:/2" } if obj.MCSLabelsPerProject == 0 { obj.MCSLabelsPerProject = 5 } }, func(obj *configapi.IdentityProvider, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.MappingMethod) == 0 { // By default, only let one identity provider authenticate a particular user // If multiple identity providers collide, the second one in will fail to auth // The admin can set this to "add" if they want to allow new identities to join existing users obj.MappingMethod = "claim" } }, func(s *configapi.StringSource, c fuzz.Continue) { if c.RandBool() { c.Fuzz(&s.Value) } else { c.Fuzz(&s.StringSourceSpec) } }, func(obj *podnodeapi.PodNodeConstraintsConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.NodeSelectorLabelBlacklist == nil { obj.NodeSelectorLabelBlacklist = []string{"kubernetes.io/hostname"} } }, func(obj *configapi.GrantConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.ServiceAccountMethod) == 0 { obj.ServiceAccountMethod = "prompt" } }, ) 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 }
// Dequeueing an event from eventQueue, updating graph, populating dirty_queue. func (p *Propagator) processEvent() { key, quit := p.eventQueue.Get() if quit { return } defer p.eventQueue.Done(key) event, ok := key.(event) if !ok { utilruntime.HandleError(fmt.Errorf("expect an event, got %v", key)) return } obj := event.obj accessor, err := meta.Accessor(obj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access obj: %v", err)) return } typeAccessor, err := meta.TypeAccessor(obj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access obj: %v", err)) return } glog.V(6).Infof("Propagator process object: %s/%s, namespace %s, name %s, event type %s", typeAccessor.GetAPIVersion(), typeAccessor.GetKind(), accessor.GetNamespace(), accessor.GetName(), event.eventType) // Check if the node already exsits existingNode, found := p.uidToNode.Read(accessor.GetUID()) switch { case (event.eventType == addEvent || event.eventType == updateEvent) && !found: newNode := &node{ identity: objectReference{ OwnerReference: metatypes.OwnerReference{ APIVersion: typeAccessor.GetAPIVersion(), Kind: typeAccessor.GetKind(), UID: accessor.GetUID(), Name: accessor.GetName(), }, Namespace: accessor.GetNamespace(), }, dependentsLock: &sync.RWMutex{}, dependents: make(map[*node]struct{}), owners: accessor.GetOwnerReferences(), } p.insertNode(newNode) // the underlying delta_fifo may combine a creation and deletion into one event if shouldOrphanDependents(event, accessor) { glog.V(6).Infof("add %s to the orphanQueue", newNode.identity) p.gc.orphanQueue.Add(newNode) } case (event.eventType == addEvent || event.eventType == updateEvent) && found: // caveat: if GC observes the creation of the dependents later than the // deletion of the owner, then the orphaning finalizer won't be effective. if shouldOrphanDependents(event, accessor) { glog.V(6).Infof("add %s to the orphanQueue", existingNode.identity) p.gc.orphanQueue.Add(existingNode) } // add/remove owner refs added, removed := referencesDiffs(existingNode.owners, accessor.GetOwnerReferences()) if len(added) == 0 && len(removed) == 0 { glog.V(6).Infof("The updateEvent %#v doesn't change node references, ignore", event) return } // update the node itself existingNode.owners = accessor.GetOwnerReferences() // Add the node to its new owners' dependent lists. p.addDependentToOwners(existingNode, added) // remove the node from the dependent list of node that are no long in // the node's owners list. p.removeDependentFromOwners(existingNode, removed) case event.eventType == deleteEvent: if !found { glog.V(6).Infof("%v doesn't exist in the graph, this shouldn't happen", accessor.GetUID()) return } p.removeNode(existingNode) existingNode.dependentsLock.RLock() defer existingNode.dependentsLock.RUnlock() for dep := range existingNode.dependents { p.gc.dirtyQueue.Add(dep) } } }
func TestGenericListMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` APIVersion string `json:"apiVersion,omitempty"` } type ListMeta struct { SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` } type Object struct { TypeMeta `json:",inline"` ListMeta `json:"metadata"` } j := Object{ TypeMeta{ APIVersion: "a", Kind: "b", }, ListMeta{ ResourceVersion: "1", SelfLink: "some/place/only/we/know", }, } accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetName("bar") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") // Prove that accessor changes the original object. if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } }
func TestGenericObjectMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` APIVersion string `json:"apiVersion,omitempty"` } type ObjectMeta struct { Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` Finalizers []string `json:"finalizers,omitempty"` OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"` } type Object struct { TypeMeta `json:",inline"` ObjectMeta `json:"metadata"` } j := Object{ TypeMeta{ APIVersion: "a", Kind: "b", }, ObjectMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"a": "b"}, Finalizers: []string{ "finalizer.1", "finalizer.2", }, }, } accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, len(accessor.GetLabels()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, len(accessor.GetAnnotations()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetLabels(map[string]string{"other": "label"}) accessor.SetAnnotations(map[string]string{"c": "d"}) accessor.SetFinalizers([]string{"finalizer.3"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "other", j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := map[string]string{"other": "label"}, j.Labels; !reflect.DeepEqual(e, a) { t.Errorf("expected %#v, got %#v", e, a) } if e, a := map[string]string{"c": "d"}, j.Annotations; !reflect.DeepEqual(e, a) { t.Errorf("expected %#v, got %#v", e, a) } if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } }
func TestAPIObjectMeta(t *testing.T) { j := &api.Pod{ TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, ObjectMeta: api.ObjectMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"x": "y"}, Finalizers: []string{ "finalizer.1", "finalizer.2", }, }, } var _ meta.Object = &j.ObjectMeta var _ meta.ObjectMetaAccessor = j accessor, err := meta.Accessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if accessor != meta.Object(&j.ObjectMeta) { t.Fatalf("should have returned the same pointer: %#v %#v", accessor, j) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetFinalizers([]string{"finalizer.3"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := types.UID("other"), j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }
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 := fuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // these follow defaulting rules func(obj *configapi.MasterConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.APILevels) == 0 { obj.APILevels = configapi.DefaultOpenShiftAPILevels } if len(obj.Controllers) == 0 { obj.Controllers = configapi.ControllersAll } if obj.ServingInfo.RequestTimeoutSeconds == 0 { obj.ServingInfo.RequestTimeoutSeconds = 60 * 60 } if obj.ServingInfo.MaxRequestsInFlight == 0 { obj.ServingInfo.MaxRequestsInFlight = 500 } if len(obj.PolicyConfig.OpenShiftInfrastructureNamespace) == 0 { obj.PolicyConfig.OpenShiftInfrastructureNamespace = bootstrappolicy.DefaultOpenShiftInfraNamespace } if len(obj.RoutingConfig.Subdomain) == 0 { obj.RoutingConfig.Subdomain = "router.default.svc.cluster.local" } if obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides == nil { obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides = &configapi.ClientConnectionOverrides{ AcceptContentTypes: "test/second", ContentType: "test/first", } } if obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.QPS <= 0 { obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.QPS = 2.0 } if obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.Burst <= 0 { obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.Burst = 2 } if len(obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.AcceptContentTypes) == 0 { obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.AcceptContentTypes = "test/fourth" } if len(obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.ContentType) == 0 { obj.MasterClients.OpenShiftLoopbackClientConnectionOverrides.ContentType = "test/fifth" } if obj.MasterClients.ExternalKubernetesClientConnectionOverrides == nil { obj.MasterClients.ExternalKubernetesClientConnectionOverrides = &configapi.ClientConnectionOverrides{ AcceptContentTypes: "test/other", ContentType: "test/third", } } if obj.MasterClients.ExternalKubernetesClientConnectionOverrides.QPS <= 0 { obj.MasterClients.ExternalKubernetesClientConnectionOverrides.QPS = 2.0 } if obj.MasterClients.ExternalKubernetesClientConnectionOverrides.Burst <= 0 { obj.MasterClients.ExternalKubernetesClientConnectionOverrides.Burst = 2 } if len(obj.MasterClients.ExternalKubernetesClientConnectionOverrides.AcceptContentTypes) == 0 { obj.MasterClients.ExternalKubernetesClientConnectionOverrides.AcceptContentTypes = "test/fourth" } if len(obj.MasterClients.ExternalKubernetesClientConnectionOverrides.ContentType) == 0 { obj.MasterClients.ExternalKubernetesClientConnectionOverrides.ContentType = "test/fifth" } // Populate the new NetworkConfig.ServiceNetworkCIDR field from the KubernetesMasterConfig.ServicesSubnet field if needed if len(obj.NetworkConfig.ServiceNetworkCIDR) == 0 { if obj.KubernetesMasterConfig != nil && len(obj.KubernetesMasterConfig.ServicesSubnet) > 0 { // if a subnet is set in the kubernetes master config, use that obj.NetworkConfig.ServiceNetworkCIDR = obj.KubernetesMasterConfig.ServicesSubnet } else { // default ServiceClusterIPRange used by kubernetes if nothing is specified obj.NetworkConfig.ServiceNetworkCIDR = "10.0.0.0/24" } } // TODO stop duplicating the conversion in the test. kubeConfig := obj.KubernetesMasterConfig noCloudProvider := kubeConfig != nil && (len(kubeConfig.ControllerArguments["cloud-provider"]) == 0 || kubeConfig.ControllerArguments["cloud-provider"][0] == "") if noCloudProvider && len(obj.NetworkConfig.IngressIPNetworkCIDR) == 0 { cidr := "172.46.0.0/16" if !(configapi.CIDRsOverlap(cidr, obj.NetworkConfig.ClusterNetworkCIDR) || configapi.CIDRsOverlap(cidr, obj.NetworkConfig.ServiceNetworkCIDR)) { obj.NetworkConfig.IngressIPNetworkCIDR = cidr } } // Historically, the clientCA was incorrectly used as the master's server cert CA bundle // If missing from the config, migrate the ClientCA into that field if obj.OAuthConfig != nil && obj.OAuthConfig.MasterCA == nil { s := obj.ServingInfo.ClientCA // The final value of OAuthConfig.MasterCA should never be nil obj.OAuthConfig.MasterCA = &s } // test an admission plugin nested for round tripping if c.RandBool() { obj.AdmissionConfig.PluginConfig = map[string]configapi.AdmissionPluginConfig{ "abc": { Location: "test", Configuration: &configapi.LDAPSyncConfig{ URL: "ldap://*****:*****@server:8080/test", }, }, } } // test a Kubernetes admission plugin nested for round tripping if obj.KubernetesMasterConfig != nil && c.RandBool() { obj.KubernetesMasterConfig.AdmissionConfig.PluginConfig = map[string]configapi.AdmissionPluginConfig{ "abc": { Location: "test", Configuration: &configapi.LDAPSyncConfig{ URL: "ldap://*****:*****@server:8080/test", }, }, } } if obj.OAuthConfig != nil && c.RandBool() { obj.OAuthConfig.IdentityProviders = []configapi.IdentityProvider{ { MappingMethod: "claim", Provider: &configapi.LDAPSyncConfig{ URL: "ldap://*****:*****@server:8080/test", }, }, } } }, func(obj *configapi.KubernetesMasterConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.MasterCount == 0 { obj.MasterCount = 1 } if len(obj.ServicesNodePortRange) == 0 { obj.ServicesNodePortRange = "30000-32767" } if len(obj.PodEvictionTimeout) == 0 { obj.PodEvictionTimeout = "5m" } }, func(obj *configapi.JenkinsPipelineConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.AutoProvisionEnabled == nil { v := c.RandBool() obj.AutoProvisionEnabled = &v } if len(obj.TemplateNamespace) == 0 { obj.TemplateNamespace = "value" } if len(obj.TemplateName) == 0 { obj.TemplateName = "anothervalue" } if len(obj.ServiceName) == 0 { obj.ServiceName = "thirdvalue" } }, func(obj *configapi.NodeConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) // Defaults/migrations for NetworkConfig if len(obj.NetworkConfig.NetworkPluginName) == 0 { obj.NetworkConfig.NetworkPluginName = "plugin-name" } if obj.NetworkConfig.MTU == 0 { obj.NetworkConfig.MTU = 1450 } if len(obj.IPTablesSyncPeriod) == 0 { obj.IPTablesSyncPeriod = "5s" } if obj.MasterClientConnectionOverrides == nil { obj.MasterClientConnectionOverrides = &configapi.ClientConnectionOverrides{ QPS: 1.0, Burst: 1, AcceptContentTypes: "test/other", ContentType: "test/third", } } if len(obj.MasterClientConnectionOverrides.AcceptContentTypes) == 0 { obj.MasterClientConnectionOverrides.AcceptContentTypes = "test/fourth" } if len(obj.MasterClientConnectionOverrides.ContentType) == 0 { obj.MasterClientConnectionOverrides.ContentType = "test/fifth" } // Auth cache defaults if len(obj.AuthConfig.AuthenticationCacheTTL) == 0 { obj.AuthConfig.AuthenticationCacheTTL = "5m" } if obj.AuthConfig.AuthenticationCacheSize == 0 { obj.AuthConfig.AuthenticationCacheSize = 1000 } if len(obj.AuthConfig.AuthorizationCacheTTL) == 0 { obj.AuthConfig.AuthorizationCacheTTL = "5m" } if obj.AuthConfig.AuthorizationCacheSize == 0 { obj.AuthConfig.AuthorizationCacheSize = 1000 } }, func(obj *configapi.EtcdStorageConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.KubernetesStorageVersion) == 0 { obj.KubernetesStorageVersion = "v1" } if len(obj.KubernetesStoragePrefix) == 0 { obj.KubernetesStoragePrefix = "kubernetes.io" } if len(obj.OpenShiftStorageVersion) == 0 { obj.OpenShiftStorageVersion = configapi.DefaultOpenShiftStorageVersionLevel } if len(obj.OpenShiftStoragePrefix) == 0 { obj.OpenShiftStoragePrefix = "openshift.io" } }, func(obj *configapi.DockerConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.ExecHandlerName) == 0 { obj.ExecHandlerName = configapi.DockerExecHandlerNative } }, func(obj *configapi.ServingInfo, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.BindNetwork) == 0 { obj.BindNetwork = "tcp4" } }, func(obj *configapi.ImagePolicyConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.MaxImagesBulkImportedPerRepository == 0 { obj.MaxImagesBulkImportedPerRepository = 5 } if obj.MaxScheduledImageImportsPerMinute == 0 { obj.MaxScheduledImageImportsPerMinute = 60 } if obj.ScheduledImageImportMinimumIntervalSeconds == 0 { obj.ScheduledImageImportMinimumIntervalSeconds = 15 * 60 } }, func(obj *configapi.DNSConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.BindNetwork) == 0 { obj.BindNetwork = "tcp4" } }, func(obj *configapi.SecurityAllocator, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.UIDAllocatorRange) == 0 { obj.UIDAllocatorRange = "1000000000-1999999999/10000" } if len(obj.MCSAllocatorRange) == 0 { obj.MCSAllocatorRange = "s0:/2" } if obj.MCSLabelsPerProject == 0 { obj.MCSLabelsPerProject = 5 } }, func(obj *configapi.IdentityProvider, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.MappingMethod) == 0 { // By default, only let one identity provider authenticate a particular user // If multiple identity providers collide, the second one in will fail to auth // The admin can set this to "add" if they want to allow new identities to join existing users obj.MappingMethod = "claim" } }, func(s *configapi.StringSource, c fuzz.Continue) { if c.RandBool() { c.Fuzz(&s.Value) } else { c.Fuzz(&s.StringSourceSpec) } }, func(obj *podnodeapi.PodNodeConstraintsConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if obj.NodeSelectorLabelBlacklist == nil { obj.NodeSelectorLabelBlacklist = []string{"kubernetes.io/hostname"} } }, func(obj *labels.Selector, c fuzz.Continue) { }, func(obj *imagepolicyapi.ImagePolicyConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) for i := range obj.ExecutionRules { if len(obj.ExecutionRules[i].OnResources) == 0 { obj.ExecutionRules[i].OnResources = []unversioned.GroupResource{{Resource: "pods"}} } obj.ExecutionRules[i].MatchImageLabelSelectors = nil } if len(obj.ResolveImages) == 0 { obj.ResolveImages = imagepolicyapi.Attempt } }, func(obj *configapi.GrantConfig, c fuzz.Continue) { c.FuzzNoCustom(obj) if len(obj.ServiceAccountMethod) == 0 { obj.ServiceAccountMethod = "prompt" } }, ) 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 TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` APIVersion string `json:"apiVersion,omitempty"` Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` } type Object struct { TypeMeta `json:",inline"` } j := Object{ TypeMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", APIVersion: "a", Kind: "b", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"x": "y"}, }, } accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "other", j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }