...
1
16
17 package fuzzer
18
19 import (
20 "reflect"
21 "strings"
22
23 fuzz "github.com/google/gofuzz"
24
25 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
28 "k8s.io/utils/pointer"
29 )
30
31 var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
32
33
34 func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
35 return []interface{}{
36 func(obj *apiextensions.CustomResourceDefinitionSpec, c fuzz.Continue) {
37 c.FuzzNoCustom(obj)
38
39
40 if len(obj.Scope) == 0 {
41 obj.Scope = apiextensions.NamespaceScoped
42 }
43 if len(obj.Names.Singular) == 0 {
44 obj.Names.Singular = strings.ToLower(obj.Names.Kind)
45 }
46 if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
47 obj.Names.ListKind = obj.Names.Kind + "List"
48 }
49 if len(obj.Versions) == 0 && len(obj.Version) == 0 {
50
51 obj.Version = "v1"
52 }
53 if len(obj.Versions) == 0 && len(obj.Version) != 0 {
54 obj.Versions = []apiextensions.CustomResourceDefinitionVersion{
55 {
56 Name: obj.Version,
57 Served: true,
58 Storage: true,
59 },
60 }
61 } else if len(obj.Versions) != 0 {
62 obj.Version = obj.Versions[0].Name
63 }
64 if len(obj.AdditionalPrinterColumns) == 0 {
65 obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{
66 {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
67 }
68 }
69 c.Fuzz(&obj.SelectableFields)
70 if obj.Conversion == nil {
71 obj.Conversion = &apiextensions.CustomResourceConversion{
72 Strategy: apiextensions.NoneConverter,
73 }
74 }
75 if obj.Conversion.Strategy == apiextensions.WebhookConverter && len(obj.Conversion.ConversionReviewVersions) == 0 {
76 obj.Conversion.ConversionReviewVersions = []string{"v1beta1"}
77 }
78 if obj.PreserveUnknownFields == nil {
79 obj.PreserveUnknownFields = pointer.BoolPtr(true)
80 }
81
82
83
84 if len(obj.Versions) == 1 {
85 if obj.Versions[0].Schema != nil {
86 obj.Validation = obj.Versions[0].Schema
87 obj.Versions[0].Schema = nil
88 }
89 if obj.Versions[0].AdditionalPrinterColumns != nil {
90 obj.AdditionalPrinterColumns = obj.Versions[0].AdditionalPrinterColumns
91 obj.Versions[0].AdditionalPrinterColumns = nil
92 }
93 if obj.Versions[0].SelectableFields != nil {
94 obj.SelectableFields = obj.Versions[0].SelectableFields
95 obj.Versions[0].SelectableFields = nil
96 }
97 if obj.Versions[0].Subresources != nil {
98 obj.Subresources = obj.Versions[0].Subresources
99 obj.Versions[0].Subresources = nil
100 }
101 }
102 },
103 func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) {
104 c.FuzzNoCustom(obj)
105
106 if len(obj.Status.StoredVersions) == 0 {
107 for _, v := range obj.Spec.Versions {
108 if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) {
109 obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
110 }
111 }
112 }
113 },
114 func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) {
115
116 vobj := reflect.ValueOf(obj).Elem()
117 tobj := reflect.TypeOf(obj).Elem()
118 for i := 0; i < tobj.NumField(); i++ {
119 field := tobj.Field(i)
120 switch field.Name {
121 case "Default", "Enum", "Example", "Ref":
122 continue
123 default:
124 isValue := true
125 switch field.Type.Kind() {
126 case reflect.Interface, reflect.Map, reflect.Slice, reflect.Pointer:
127 isValue = false
128 }
129 if isValue || c.Intn(10) == 0 {
130 c.Fuzz(vobj.Field(i).Addr().Interface())
131 }
132 }
133 }
134 if c.RandBool() {
135 validJSON := apiextensions.JSON(`{"some": {"json": "test"}, "string": 42}`)
136 obj.Default = &validJSON
137 }
138 if c.RandBool() {
139 obj.Enum = []apiextensions.JSON{c.Float64(), c.RandString(), c.RandBool()}
140 }
141 if c.RandBool() {
142 validJSON := apiextensions.JSON(`"foobarbaz"`)
143 obj.Example = &validJSON
144 }
145 if c.RandBool() {
146 validRef := "validRef"
147 obj.Ref = &validRef
148 }
149 if len(obj.Type) == 0 {
150 obj.Nullable = false
151 }
152 if obj.XIntOrString {
153 obj.Type = ""
154 }
155 },
156 func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) {
157 if c.RandBool() {
158 obj.Allows = true
159 obj.Schema = &apiextensions.JSONSchemaProps{}
160 c.Fuzz(obj.Schema)
161 } else {
162 obj.Allows = c.RandBool()
163 }
164 },
165 func(obj *apiextensions.JSONSchemaPropsOrArray, c fuzz.Continue) {
166
167 if c.RandBool() {
168 obj.Schema = &apiextensions.JSONSchemaProps{}
169 c.Fuzz(obj.Schema)
170 } else {
171 obj.JSONSchemas = make([]apiextensions.JSONSchemaProps, c.Intn(3)+1)
172 for i := range obj.JSONSchemas {
173 c.Fuzz(&obj.JSONSchemas[i])
174 }
175 }
176 },
177 func(obj *apiextensions.JSONSchemaPropsOrStringArray, c fuzz.Continue) {
178 if c.RandBool() {
179 obj.Schema = &apiextensions.JSONSchemaProps{}
180 c.Fuzz(obj.Schema)
181 } else {
182 c.Fuzz(&obj.Property)
183 }
184 },
185 func(obj *int64, c fuzz.Continue) {
186
187 *obj = int64(c.Uint64()) & ((int64(1) << 53) - 1)
188 },
189 func(obj *apiextensions.ValidationRule, c fuzz.Continue) {
190 c.FuzzNoCustom(obj)
191 if obj.Reason != nil && *(obj.Reason) == "" {
192 obj.Reason = nil
193 }
194 },
195 }
196 }
197
View as plain text