fuzzer.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package testing
  14. import (
  15. "fmt"
  16. "math/rand"
  17. "reflect"
  18. "strconv"
  19. "testing"
  20. "k8s.io/kubernetes/pkg/api"
  21. "k8s.io/kubernetes/pkg/api/resource"
  22. "k8s.io/kubernetes/pkg/api/testapi"
  23. "k8s.io/kubernetes/pkg/api/unversioned"
  24. "k8s.io/kubernetes/pkg/apis/autoscaling"
  25. "k8s.io/kubernetes/pkg/apis/batch"
  26. "k8s.io/kubernetes/pkg/apis/extensions"
  27. "k8s.io/kubernetes/pkg/fields"
  28. "k8s.io/kubernetes/pkg/labels"
  29. "k8s.io/kubernetes/pkg/runtime"
  30. "k8s.io/kubernetes/pkg/types"
  31. "k8s.io/kubernetes/pkg/util/intstr"
  32. "github.com/google/gofuzz"
  33. )
  34. // FuzzerFor can randomly populate api objects that are destined for version.
  35. func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source) *fuzz.Fuzzer {
  36. f := fuzz.New().NilChance(.5).NumElements(1, 1)
  37. if src != nil {
  38. f.RandSource(src)
  39. }
  40. f.Funcs(
  41. func(j *int, c fuzz.Continue) {
  42. *j = int(c.Int31())
  43. },
  44. func(j **int, c fuzz.Continue) {
  45. if c.RandBool() {
  46. i := int(c.Int31())
  47. *j = &i
  48. } else {
  49. *j = nil
  50. }
  51. },
  52. func(q *resource.Quantity, c fuzz.Continue) {
  53. *q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
  54. },
  55. func(j *runtime.TypeMeta, c fuzz.Continue) {
  56. // We have to customize the randomization of TypeMetas because their
  57. // APIVersion and Kind must remain blank in memory.
  58. j.APIVersion = ""
  59. j.Kind = ""
  60. },
  61. func(j *unversioned.TypeMeta, c fuzz.Continue) {
  62. // We have to customize the randomization of TypeMetas because their
  63. // APIVersion and Kind must remain blank in memory.
  64. j.APIVersion = ""
  65. j.Kind = ""
  66. },
  67. func(j *api.ObjectMeta, c fuzz.Continue) {
  68. j.Name = c.RandString()
  69. j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
  70. j.SelfLink = c.RandString()
  71. j.UID = types.UID(c.RandString())
  72. j.GenerateName = c.RandString()
  73. var sec, nsec int64
  74. c.Fuzz(&sec)
  75. c.Fuzz(&nsec)
  76. j.CreationTimestamp = unversioned.Unix(sec, nsec).Rfc3339Copy()
  77. },
  78. func(j *api.ObjectReference, c fuzz.Continue) {
  79. // We have to customize the randomization of TypeMetas because their
  80. // APIVersion and Kind must remain blank in memory.
  81. j.APIVersion = c.RandString()
  82. j.Kind = c.RandString()
  83. j.Namespace = c.RandString()
  84. j.Name = c.RandString()
  85. j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
  86. j.FieldPath = c.RandString()
  87. },
  88. func(j *unversioned.ListMeta, c fuzz.Continue) {
  89. j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
  90. j.SelfLink = c.RandString()
  91. },
  92. func(j *api.ListOptions, c fuzz.Continue) {
  93. label, _ := labels.Parse("a=b")
  94. j.LabelSelector = label
  95. field, _ := fields.ParseSelector("a=b")
  96. j.FieldSelector = field
  97. },
  98. func(j *api.PodExecOptions, c fuzz.Continue) {
  99. j.Stdout = true
  100. j.Stderr = true
  101. },
  102. func(j *api.PodAttachOptions, c fuzz.Continue) {
  103. j.Stdout = true
  104. j.Stderr = true
  105. },
  106. func(s *api.PodSpec, c fuzz.Continue) {
  107. c.FuzzNoCustom(s)
  108. // has a default value
  109. ttl := int64(30)
  110. if c.RandBool() {
  111. ttl = int64(c.Uint32())
  112. }
  113. s.TerminationGracePeriodSeconds = &ttl
  114. c.Fuzz(s.SecurityContext)
  115. if s.SecurityContext == nil {
  116. s.SecurityContext = new(api.PodSecurityContext)
  117. }
  118. },
  119. func(j *api.PodPhase, c fuzz.Continue) {
  120. statuses := []api.PodPhase{api.PodPending, api.PodRunning, api.PodFailed, api.PodUnknown}
  121. *j = statuses[c.Rand.Intn(len(statuses))]
  122. },
  123. func(j *api.Binding, c fuzz.Continue) {
  124. c.Fuzz(&j.ObjectMeta)
  125. j.Target.Name = c.RandString()
  126. },
  127. func(j *api.ReplicationControllerSpec, c fuzz.Continue) {
  128. c.FuzzNoCustom(j) // fuzz self without calling this function again
  129. //j.TemplateRef = nil // this is required for round trip
  130. },
  131. func(j *extensions.DeploymentStrategy, c fuzz.Continue) {
  132. c.FuzzNoCustom(j) // fuzz self without calling this function again
  133. // Ensure that strategyType is one of valid values.
  134. strategyTypes := []extensions.DeploymentStrategyType{extensions.RecreateDeploymentStrategyType, extensions.RollingUpdateDeploymentStrategyType}
  135. j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))]
  136. if j.Type != extensions.RollingUpdateDeploymentStrategyType {
  137. j.RollingUpdate = nil
  138. } else {
  139. rollingUpdate := extensions.RollingUpdateDeployment{}
  140. if c.RandBool() {
  141. rollingUpdate.MaxUnavailable = intstr.FromInt(int(c.RandUint64()))
  142. rollingUpdate.MaxSurge = intstr.FromInt(int(c.RandUint64()))
  143. } else {
  144. rollingUpdate.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64()))
  145. }
  146. j.RollingUpdate = &rollingUpdate
  147. }
  148. },
  149. func(j *batch.JobSpec, c fuzz.Continue) {
  150. c.FuzzNoCustom(j) // fuzz self without calling this function again
  151. completions := int32(c.Rand.Int31())
  152. parallelism := int32(c.Rand.Int31())
  153. j.Completions = &completions
  154. j.Parallelism = &parallelism
  155. if c.Rand.Int31()%2 == 0 {
  156. j.ManualSelector = newBool(true)
  157. } else {
  158. j.ManualSelector = nil
  159. }
  160. },
  161. func(sj *batch.ScheduledJobSpec, c fuzz.Continue) {
  162. c.FuzzNoCustom(sj)
  163. suspend := c.RandBool()
  164. sj.Suspend = &suspend
  165. sds := int64(c.RandUint64())
  166. sj.StartingDeadlineSeconds = &sds
  167. sj.Schedule = c.RandString()
  168. },
  169. func(cp *batch.ConcurrencyPolicy, c fuzz.Continue) {
  170. policies := []batch.ConcurrencyPolicy{batch.AllowConcurrent, batch.ForbidConcurrent, batch.ReplaceConcurrent}
  171. *cp = policies[c.Rand.Intn(len(policies))]
  172. },
  173. func(j *api.List, c fuzz.Continue) {
  174. c.FuzzNoCustom(j) // fuzz self without calling this function again
  175. // TODO: uncomment when round trip starts from a versioned object
  176. if false { //j.Items == nil {
  177. j.Items = []runtime.Object{}
  178. }
  179. },
  180. func(j *runtime.Object, c fuzz.Continue) {
  181. // TODO: uncomment when round trip starts from a versioned object
  182. if true { //c.RandBool() {
  183. *j = &runtime.Unknown{
  184. // We do not set TypeMeta here because it is not carried through a round trip
  185. Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
  186. ContentType: runtime.ContentTypeJSON,
  187. }
  188. } else {
  189. types := []runtime.Object{&api.Pod{}, &api.ReplicationController{}}
  190. t := types[c.Rand.Intn(len(types))]
  191. c.Fuzz(t)
  192. *j = t
  193. }
  194. },
  195. func(q *api.ResourceRequirements, c fuzz.Continue) {
  196. randomQuantity := func() resource.Quantity {
  197. var q resource.Quantity
  198. c.Fuzz(&q)
  199. // precalc the string for benchmarking purposes
  200. _ = q.String()
  201. return q
  202. }
  203. q.Limits = make(api.ResourceList)
  204. q.Requests = make(api.ResourceList)
  205. cpuLimit := randomQuantity()
  206. q.Limits[api.ResourceCPU] = *cpuLimit.Copy()
  207. q.Requests[api.ResourceCPU] = *cpuLimit.Copy()
  208. memoryLimit := randomQuantity()
  209. q.Limits[api.ResourceMemory] = *memoryLimit.Copy()
  210. q.Requests[api.ResourceMemory] = *memoryLimit.Copy()
  211. storageLimit := randomQuantity()
  212. q.Limits[api.ResourceStorage] = *storageLimit.Copy()
  213. q.Requests[api.ResourceStorage] = *storageLimit.Copy()
  214. },
  215. func(q *api.LimitRangeItem, c fuzz.Continue) {
  216. var cpuLimit resource.Quantity
  217. c.Fuzz(&cpuLimit)
  218. q.Type = api.LimitTypeContainer
  219. q.Default = make(api.ResourceList)
  220. q.Default[api.ResourceCPU] = *(cpuLimit.Copy())
  221. q.DefaultRequest = make(api.ResourceList)
  222. q.DefaultRequest[api.ResourceCPU] = *(cpuLimit.Copy())
  223. q.Max = make(api.ResourceList)
  224. q.Max[api.ResourceCPU] = *(cpuLimit.Copy())
  225. q.Min = make(api.ResourceList)
  226. q.Min[api.ResourceCPU] = *(cpuLimit.Copy())
  227. q.MaxLimitRequestRatio = make(api.ResourceList)
  228. q.MaxLimitRequestRatio[api.ResourceCPU] = resource.MustParse("10")
  229. },
  230. func(p *api.PullPolicy, c fuzz.Continue) {
  231. policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent}
  232. *p = policies[c.Rand.Intn(len(policies))]
  233. },
  234. func(rp *api.RestartPolicy, c fuzz.Continue) {
  235. policies := []api.RestartPolicy{api.RestartPolicyAlways, api.RestartPolicyNever, api.RestartPolicyOnFailure}
  236. *rp = policies[c.Rand.Intn(len(policies))]
  237. },
  238. // api.DownwardAPIVolumeFile needs to have a specific func since FieldRef has to be
  239. // defaulted to a version otherwise roundtrip will fail
  240. func(m *api.DownwardAPIVolumeFile, c fuzz.Continue) {
  241. m.Path = c.RandString()
  242. versions := []string{"v1"}
  243. m.FieldRef = &api.ObjectFieldSelector{}
  244. m.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))]
  245. m.FieldRef.FieldPath = c.RandString()
  246. c.Fuzz(m.Mode)
  247. if m.Mode != nil {
  248. *m.Mode &= 0777
  249. }
  250. },
  251. func(s *api.SecretVolumeSource, c fuzz.Continue) {
  252. c.FuzzNoCustom(s) // fuzz self without calling this function again
  253. // DefaultMode should always be set, it has a default
  254. // value and it is expected to be between 0 and 0777
  255. var mode int32
  256. c.Fuzz(&mode)
  257. mode &= 0777
  258. s.DefaultMode = &mode
  259. },
  260. func(cm *api.ConfigMapVolumeSource, c fuzz.Continue) {
  261. c.FuzzNoCustom(cm) // fuzz self without calling this function again
  262. // DefaultMode should always be set, it has a default
  263. // value and it is expected to be between 0 and 0777
  264. var mode int32
  265. c.Fuzz(&mode)
  266. mode &= 0777
  267. cm.DefaultMode = &mode
  268. },
  269. func(d *api.DownwardAPIVolumeSource, c fuzz.Continue) {
  270. c.FuzzNoCustom(d) // fuzz self without calling this function again
  271. // DefaultMode should always be set, it has a default
  272. // value and it is expected to be between 0 and 0777
  273. var mode int32
  274. c.Fuzz(&mode)
  275. mode &= 0777
  276. d.DefaultMode = &mode
  277. },
  278. func(k *api.KeyToPath, c fuzz.Continue) {
  279. c.FuzzNoCustom(k) // fuzz self without calling this function again
  280. k.Key = c.RandString()
  281. k.Path = c.RandString()
  282. // Mode is not mandatory, but if it is set, it should be
  283. // a value between 0 and 0777
  284. if k.Mode != nil {
  285. *k.Mode &= 0777
  286. }
  287. },
  288. func(vs *api.VolumeSource, c fuzz.Continue) {
  289. // Exactly one of the fields must be set.
  290. v := reflect.ValueOf(vs).Elem()
  291. i := int(c.RandUint64() % uint64(v.NumField()))
  292. t := v.Field(i).Addr()
  293. for v.Field(i).IsNil() {
  294. c.Fuzz(t.Interface())
  295. }
  296. },
  297. func(i *api.ISCSIVolumeSource, c fuzz.Continue) {
  298. i.ISCSIInterface = c.RandString()
  299. if i.ISCSIInterface == "" {
  300. i.ISCSIInterface = "default"
  301. }
  302. },
  303. func(d *api.DNSPolicy, c fuzz.Continue) {
  304. policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault}
  305. *d = policies[c.Rand.Intn(len(policies))]
  306. },
  307. func(p *api.Protocol, c fuzz.Continue) {
  308. protocols := []api.Protocol{api.ProtocolTCP, api.ProtocolUDP}
  309. *p = protocols[c.Rand.Intn(len(protocols))]
  310. },
  311. func(p *api.ServiceAffinity, c fuzz.Continue) {
  312. types := []api.ServiceAffinity{api.ServiceAffinityClientIP, api.ServiceAffinityNone}
  313. *p = types[c.Rand.Intn(len(types))]
  314. },
  315. func(p *api.ServiceType, c fuzz.Continue) {
  316. types := []api.ServiceType{api.ServiceTypeClusterIP, api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer}
  317. *p = types[c.Rand.Intn(len(types))]
  318. },
  319. func(ct *api.Container, c fuzz.Continue) {
  320. c.FuzzNoCustom(ct) // fuzz self without calling this function again
  321. ct.TerminationMessagePath = "/" + ct.TerminationMessagePath // Must be non-empty
  322. },
  323. func(p *api.Probe, c fuzz.Continue) {
  324. c.FuzzNoCustom(p)
  325. // These fields have default values.
  326. intFieldsWithDefaults := [...]string{"TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"}
  327. v := reflect.ValueOf(p).Elem()
  328. for _, field := range intFieldsWithDefaults {
  329. f := v.FieldByName(field)
  330. if f.Int() == 0 {
  331. f.SetInt(1)
  332. }
  333. }
  334. },
  335. func(ev *api.EnvVar, c fuzz.Continue) {
  336. ev.Name = c.RandString()
  337. if c.RandBool() {
  338. ev.Value = c.RandString()
  339. } else {
  340. ev.ValueFrom = &api.EnvVarSource{}
  341. ev.ValueFrom.FieldRef = &api.ObjectFieldSelector{}
  342. var versions []unversioned.GroupVersion
  343. for _, testGroup := range testapi.Groups {
  344. versions = append(versions, *testGroup.GroupVersion())
  345. }
  346. ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))].String()
  347. ev.ValueFrom.FieldRef.FieldPath = c.RandString()
  348. }
  349. },
  350. func(sc *api.SecurityContext, c fuzz.Continue) {
  351. c.FuzzNoCustom(sc) // fuzz self without calling this function again
  352. if c.RandBool() {
  353. priv := c.RandBool()
  354. sc.Privileged = &priv
  355. }
  356. if c.RandBool() {
  357. sc.Capabilities = &api.Capabilities{
  358. Add: make([]api.Capability, 0),
  359. Drop: make([]api.Capability, 0),
  360. }
  361. c.Fuzz(&sc.Capabilities.Add)
  362. c.Fuzz(&sc.Capabilities.Drop)
  363. }
  364. },
  365. func(s *api.Secret, c fuzz.Continue) {
  366. c.FuzzNoCustom(s) // fuzz self without calling this function again
  367. s.Type = api.SecretTypeOpaque
  368. },
  369. func(r *api.RBDVolumeSource, c fuzz.Continue) {
  370. r.RBDPool = c.RandString()
  371. if r.RBDPool == "" {
  372. r.RBDPool = "rbd"
  373. }
  374. r.RadosUser = c.RandString()
  375. if r.RadosUser == "" {
  376. r.RadosUser = "admin"
  377. }
  378. r.Keyring = c.RandString()
  379. if r.Keyring == "" {
  380. r.Keyring = "/etc/ceph/keyring"
  381. }
  382. },
  383. func(pv *api.PersistentVolume, c fuzz.Continue) {
  384. c.FuzzNoCustom(pv) // fuzz self without calling this function again
  385. types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed}
  386. pv.Status.Phase = types[c.Rand.Intn(len(types))]
  387. pv.Status.Message = c.RandString()
  388. reclamationPolicies := []api.PersistentVolumeReclaimPolicy{api.PersistentVolumeReclaimRecycle, api.PersistentVolumeReclaimRetain}
  389. pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
  390. },
  391. func(pvc *api.PersistentVolumeClaim, c fuzz.Continue) {
  392. c.FuzzNoCustom(pvc) // fuzz self without calling this function again
  393. types := []api.PersistentVolumeClaimPhase{api.ClaimBound, api.ClaimPending, api.ClaimLost}
  394. pvc.Status.Phase = types[c.Rand.Intn(len(types))]
  395. },
  396. func(obj *api.AzureDiskVolumeSource, c fuzz.Continue) {
  397. if obj.CachingMode == nil {
  398. obj.CachingMode = new(api.AzureDataDiskCachingMode)
  399. *obj.CachingMode = api.AzureDataDiskCachingNone
  400. }
  401. if obj.FSType == nil {
  402. obj.FSType = new(string)
  403. *obj.FSType = "ext4"
  404. }
  405. if obj.ReadOnly == nil {
  406. obj.ReadOnly = new(bool)
  407. *obj.ReadOnly = false
  408. }
  409. },
  410. func(s *api.NamespaceSpec, c fuzz.Continue) {
  411. s.Finalizers = []api.FinalizerName{api.FinalizerKubernetes}
  412. },
  413. func(s *api.NamespaceStatus, c fuzz.Continue) {
  414. s.Phase = api.NamespaceActive
  415. },
  416. func(http *api.HTTPGetAction, c fuzz.Continue) {
  417. c.FuzzNoCustom(http) // fuzz self without calling this function again
  418. http.Path = "/" + http.Path // can't be blank
  419. http.Scheme = "x" + http.Scheme // can't be blank
  420. },
  421. func(ss *api.ServiceSpec, c fuzz.Continue) {
  422. c.FuzzNoCustom(ss) // fuzz self without calling this function again
  423. if len(ss.Ports) == 0 {
  424. // There must be at least 1 port.
  425. ss.Ports = append(ss.Ports, api.ServicePort{})
  426. c.Fuzz(&ss.Ports[0])
  427. }
  428. for i := range ss.Ports {
  429. switch ss.Ports[i].TargetPort.Type {
  430. case intstr.Int:
  431. ss.Ports[i].TargetPort.IntVal = 1 + ss.Ports[i].TargetPort.IntVal%65535 // non-zero
  432. case intstr.String:
  433. ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty
  434. }
  435. }
  436. },
  437. func(n *api.Node, c fuzz.Continue) {
  438. c.FuzzNoCustom(n)
  439. n.Spec.ExternalID = "external"
  440. },
  441. func(s *api.NodeStatus, c fuzz.Continue) {
  442. c.FuzzNoCustom(s)
  443. s.Allocatable = s.Capacity
  444. },
  445. func(s *autoscaling.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
  446. c.FuzzNoCustom(s) // fuzz self without calling this function again
  447. minReplicas := int32(c.Rand.Int31())
  448. s.MinReplicas = &minReplicas
  449. targetCpu := int32(c.RandUint64())
  450. s.TargetCPUUtilizationPercentage = &targetCpu
  451. },
  452. func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
  453. c.FuzzNoCustom(psp) // fuzz self without calling this function again
  454. runAsUserRules := []extensions.RunAsUserStrategy{extensions.RunAsUserStrategyMustRunAsNonRoot, extensions.RunAsUserStrategyMustRunAs, extensions.RunAsUserStrategyRunAsAny}
  455. psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))]
  456. seLinuxRules := []extensions.SELinuxStrategy{extensions.SELinuxStrategyRunAsAny, extensions.SELinuxStrategyMustRunAs}
  457. psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))]
  458. },
  459. func(s *extensions.Scale, c fuzz.Continue) {
  460. c.FuzzNoCustom(s) // fuzz self without calling this function again
  461. // TODO: Implement a fuzzer to generate valid keys, values and operators for
  462. // selector requirements.
  463. if s.Status.Selector != nil {
  464. s.Status.Selector = &unversioned.LabelSelector{
  465. MatchLabels: map[string]string{
  466. "testlabelkey": "testlabelval",
  467. },
  468. MatchExpressions: []unversioned.LabelSelectorRequirement{
  469. {
  470. Key: "testkey",
  471. Operator: unversioned.LabelSelectorOpIn,
  472. Values: []string{"val1", "val2", "val3"},
  473. },
  474. },
  475. }
  476. }
  477. },
  478. func(r *runtime.RawExtension, c fuzz.Continue) {
  479. // Pick an arbitrary type and fuzz it
  480. types := []runtime.Object{&api.Pod{}, &extensions.Deployment{}, &api.Service{}}
  481. obj := types[c.Rand.Intn(len(types))]
  482. c.Fuzz(obj)
  483. // Find a codec for converting the object to raw bytes. This is necessary for the
  484. // api version and kind to be correctly set be serialization.
  485. var codec runtime.Codec
  486. switch obj.(type) {
  487. case *api.Pod:
  488. codec = testapi.Default.Codec()
  489. case *extensions.Deployment:
  490. codec = testapi.Extensions.Codec()
  491. case *api.Service:
  492. codec = testapi.Default.Codec()
  493. default:
  494. t.Errorf("Failed to find codec for object type: %T", obj)
  495. return
  496. }
  497. // Convert the object to raw bytes
  498. bytes, err := runtime.Encode(codec, obj)
  499. if err != nil {
  500. t.Errorf("Failed to encode object: %v", err)
  501. return
  502. }
  503. // Set the bytes field on the RawExtension
  504. r.Raw = bytes
  505. },
  506. )
  507. return f
  508. }
  509. func newBool(val bool) *bool {
  510. p := new(bool)
  511. *p = val
  512. return p
  513. }