1
16
17 package proto_test
18
19 import (
20 "path/filepath"
21
22 openapi_v3 "github.com/google/gnostic-models/openapiv3"
23 . "github.com/onsi/ginkgo/v2"
24 . "github.com/onsi/gomega"
25
26 "k8s.io/kube-openapi/pkg/util/proto"
27 "k8s.io/kube-openapi/pkg/util/proto/testing"
28 )
29
30 var fakeSchema = testing.Fake{Path: filepath.Join("testdata", "swagger.json")}
31 var fakeSchemaNext = testing.Fake{Path: filepath.Join("testdata", "swagger_next.json")}
32 var fakeSchemaV300 = testing.FakeV3{Path: filepath.Join("testdata", "openapi_v3_0_0")}
33
34 var _ = Describe("Reading apps/v1beta1/Deployment from v1.8 openAPIData", func() {
35 var models proto.Models
36 BeforeEach(func() {
37 s, err := fakeSchema.OpenAPISchema()
38 Expect(err).To(BeNil())
39 models, err = proto.NewOpenAPIData(s)
40 Expect(err).To(BeNil())
41 })
42
43 model := "io.k8s.api.apps.v1beta1.Deployment"
44 var schema proto.Schema
45 It("should lookup the Schema by its model name", func() {
46 schema = models.LookupModel(model)
47 Expect(schema).ToNot(BeNil())
48 })
49
50 var deployment *proto.Kind
51 It("should be a Kind", func() {
52 deployment = schema.(*proto.Kind)
53 Expect(deployment).ToNot(BeNil())
54 })
55
56 It("should have a path", func() {
57 Expect(deployment.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment"}))
58 })
59
60 It("should have a kind key of type string", func() {
61 Expect(deployment.Fields).To(HaveKey("kind"))
62 key := deployment.Fields["kind"].(*proto.Primitive)
63 Expect(key).ToNot(BeNil())
64 Expect(key.Type).To(Equal("string"))
65 Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".kind"}))
66 })
67
68 It("should have a apiVersion key of type string", func() {
69 Expect(deployment.Fields).To(HaveKey("apiVersion"))
70 key := deployment.Fields["apiVersion"].(*proto.Primitive)
71 Expect(key).ToNot(BeNil())
72 Expect(key.Type).To(Equal("string"))
73 Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".apiVersion"}))
74 })
75
76 It("should have a metadata key of type Reference", func() {
77 Expect(deployment.Fields).To(HaveKey("metadata"))
78 key := deployment.Fields["metadata"].(proto.Reference)
79 Expect(key).ToNot(BeNil())
80 Expect(key.Reference()).To(Equal("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"))
81 subSchema := key.SubSchema().(*proto.Kind)
82 Expect(subSchema).ToNot(BeNil())
83 })
84
85 var status *proto.Kind
86 It("should have a status key of type Reference", func() {
87 Expect(deployment.Fields).To(HaveKey("status"))
88 key := deployment.Fields["status"].(proto.Reference)
89 Expect(key).ToNot(BeNil())
90 Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentStatus"))
91 status = key.SubSchema().(*proto.Kind)
92 Expect(status).ToNot(BeNil())
93 })
94
95 It("should have a valid DeploymentStatus", func() {
96 By("having availableReplicas key")
97 Expect(status.Fields).To(HaveKey("availableReplicas"))
98 replicas := status.Fields["availableReplicas"].(*proto.Primitive)
99 Expect(replicas).ToNot(BeNil())
100 Expect(replicas.Type).To(Equal("integer"))
101
102 By("having conditions key")
103 Expect(status.Fields).To(HaveKey("conditions"))
104 conditions := status.Fields["conditions"].(*proto.Array)
105 Expect(conditions).ToNot(BeNil())
106 Expect(conditions.GetName()).To(Equal(`Array of Reference to "io.k8s.api.apps.v1beta1.DeploymentCondition"`))
107 Expect(conditions.GetExtensions()).To(Equal(map[string]interface{}{
108 "x-kubernetes-patch-merge-key": "type",
109 "x-kubernetes-patch-strategy": "merge",
110 }))
111 condition := conditions.SubType.(proto.Reference)
112 Expect(condition.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentCondition"))
113 })
114
115 var spec *proto.Kind
116 It("should have a spec key of type Reference", func() {
117 Expect(deployment.Fields).To(HaveKey("spec"))
118 key := deployment.Fields["spec"].(proto.Reference)
119 Expect(key).ToNot(BeNil())
120 Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentSpec"))
121 spec = key.SubSchema().(*proto.Kind)
122 Expect(spec).ToNot(BeNil())
123 })
124
125 It("should have a spec with no gvk", func() {
126 _, found := spec.GetExtensions()["x-kubernetes-group-version-kind"]
127 Expect(found).To(BeFalse())
128 })
129
130 It("should have a spec with a PodTemplateSpec sub-field", func() {
131 Expect(spec.Fields).To(HaveKey("template"))
132 key := spec.Fields["template"].(proto.Reference)
133 Expect(key).ToNot(BeNil())
134 Expect(key.Reference()).To(Equal("io.k8s.api.core.v1.PodTemplateSpec"))
135 })
136 })
137
138 var _ = Describe("Reading apps/v1beta1/Deployment from v1.11 openAPIData", func() {
139 var models proto.Models
140 BeforeEach(func() {
141 s, err := fakeSchemaNext.OpenAPISchema()
142 Expect(err).To(BeNil())
143 models, err = proto.NewOpenAPIData(s)
144 Expect(err).To(BeNil())
145 })
146
147 model := "io.k8s.api.apps.v1beta1.Deployment"
148 var schema proto.Schema
149 It("should lookup the Schema by its model name", func() {
150 schema = models.LookupModel(model)
151 Expect(schema).ToNot(BeNil())
152 })
153
154 var deployment *proto.Kind
155 It("should be a Kind", func() {
156 deployment = schema.(*proto.Kind)
157 Expect(deployment).ToNot(BeNil())
158 })
159 })
160
161 var _ = Describe("Reading apps/v1beta1/ControllerRevision from v1.11 openAPIData", func() {
162 var models proto.Models
163 BeforeEach(func() {
164 s, err := fakeSchemaNext.OpenAPISchema()
165 Expect(err).To(BeNil())
166 models, err = proto.NewOpenAPIData(s)
167 Expect(err).To(BeNil())
168 })
169
170 model := "io.k8s.api.apps.v1beta1.ControllerRevision"
171 var schema proto.Schema
172 It("should lookup the Schema by its model name", func() {
173 schema = models.LookupModel(model)
174 Expect(schema).ToNot(BeNil())
175 })
176
177 var cr *proto.Kind
178 It("data property should be map[string]Arbitrary", func() {
179 cr = schema.(*proto.Kind)
180 Expect(cr).ToNot(BeNil())
181 Expect(cr.Fields).To(HaveKey("data"))
182
183 data := cr.Fields["data"].(*proto.Map)
184 Expect(data).ToNot(BeNil())
185 Expect(data.GetName()).To(Equal("Map of Arbitrary value (primitive, object or array)"))
186 Expect(data.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"}))
187
188 arbitrary := data.SubType.(*proto.Arbitrary)
189 Expect(arbitrary).ToNot(BeNil())
190 Expect(arbitrary.GetName()).To(Equal("Arbitrary value (primitive, object or array)"))
191 Expect(arbitrary.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"}))
192 })
193 })
194
195 var _ = Describe("Reading authorization.k8s.io/v1/SubjectAccessReview from openAPIData", func() {
196 var models proto.Models
197 BeforeEach(func() {
198 s, err := fakeSchema.OpenAPISchema()
199 Expect(err).To(BeNil())
200 models, err = proto.NewOpenAPIData(s)
201 Expect(err).To(BeNil())
202 })
203
204 model := "io.k8s.api.authorization.v1.LocalSubjectAccessReview"
205 var schema proto.Schema
206 It("should lookup the Schema by its model", func() {
207 schema = models.LookupModel(model)
208 Expect(schema).ToNot(BeNil())
209 })
210
211 var sarspec *proto.Kind
212 It("should be a Kind and have a spec", func() {
213 sar := schema.(*proto.Kind)
214 Expect(sar).ToNot(BeNil())
215 Expect(sar.Fields).To(HaveKey("spec"))
216 specRef := sar.Fields["spec"].(proto.Reference)
217 Expect(specRef).ToNot(BeNil())
218 Expect(specRef.Reference()).To(Equal("io.k8s.api.authorization.v1.SubjectAccessReviewSpec"))
219 sarspec = specRef.SubSchema().(*proto.Kind)
220 Expect(sarspec).ToNot(BeNil())
221 })
222
223 It("should have a valid SubjectAccessReviewSpec", func() {
224 Expect(sarspec.Fields).To(HaveKey("extra"))
225 extra := sarspec.Fields["extra"].(*proto.Map)
226 Expect(extra).ToNot(BeNil())
227 Expect(extra.GetName()).To(Equal("Map of Array of string"))
228 Expect(extra.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
229 array := extra.SubType.(*proto.Array)
230 Expect(array).ToNot(BeNil())
231 Expect(array.GetName()).To(Equal("Array of string"))
232 Expect(array.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
233 str := array.SubType.(*proto.Primitive)
234 Expect(str).ToNot(BeNil())
235 Expect(str.Type).To(Equal("string"))
236 Expect(str.GetName()).To(Equal("string"))
237 Expect(str.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
238 })
239 })
240
241 var _ = Describe("Path", func() {
242 It("can be created by NewPath", func() {
243 path := proto.NewPath("key")
244 Expect(path.String()).To(Equal("key"))
245 })
246 It("can create and print complex paths", func() {
247 key := proto.NewPath("key")
248 array := key.ArrayPath(12)
249 field := array.FieldPath("subKey")
250
251 Expect(field.String()).To(Equal("key[12].subKey"))
252 })
253 It("has a length", func() {
254 key := proto.NewPath("key")
255 array := key.ArrayPath(12)
256 field := array.FieldPath("subKey")
257
258 Expect(field.Len()).To(Equal(3))
259 })
260 It("can look like an array", func() {
261 key := proto.NewPath("key")
262 array := key.ArrayPath(12)
263 field := array.FieldPath("subKey")
264
265 Expect(field.Get()).To(Equal([]string{"key", "[12]", ".subKey"}))
266 })
267 })
268
269 var _ = Describe("Reading apps/v1/Deployment from v3.0.0 openAPIData", func() {
270 var deployment *proto.Kind
271 BeforeEach(func() {
272 var models proto.Models
273 s, schemaErr := fakeSchemaV300.OpenAPIV3Schema("apps/v1")
274 models, modelsErr := proto.NewOpenAPIV3Data(s)
275
276 Expect(schemaErr).To(BeNil())
277 Expect(modelsErr).To(BeNil())
278
279 model := "io.k8s.api.apps.v1.Deployment"
280 schema := models.LookupModel(model)
281 Expect(schema).ToNot(BeNil())
282
283 deployment = schema.(*proto.Kind)
284 Expect(deployment).ToNot(BeNil())
285 })
286
287 It("should have a path", func() {
288 Expect(deployment.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1.Deployment"}))
289 })
290
291 It("should have a kind key of type string", func() {
292 Expect(deployment.Fields).To(HaveKey("kind"))
293 key := deployment.Fields["kind"].(*proto.Primitive)
294 Expect(key).ToNot(BeNil())
295 Expect(key.Type).To(Equal("string"))
296 Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1.Deployment", ".kind"}))
297 })
298
299 It("should have a apiVersion key of type string", func() {
300 Expect(deployment.Fields).To(HaveKey("apiVersion"))
301 key := deployment.Fields["apiVersion"].(*proto.Primitive)
302 Expect(key).ToNot(BeNil())
303 Expect(key.Type).To(Equal("string"))
304 Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1.Deployment", ".apiVersion"}))
305 })
306
307 It("should have a metadata key of type Reference", func() {
308 Expect(deployment.Fields).To(HaveKey("metadata"))
309 key := deployment.Fields["metadata"].(proto.Reference)
310 Expect(key).ToNot(BeNil())
311 Expect(key.Reference()).To(Equal("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"))
312 subSchema := key.SubSchema().(*proto.Kind)
313 Expect(subSchema).ToNot(BeNil())
314 })
315
316 Describe("status", func() {
317 var status *proto.Kind
318 BeforeEach(func() {
319 Expect(deployment.Fields).To(HaveKey("status"))
320 key := deployment.Fields["status"].(proto.Reference)
321 Expect(key).ToNot(BeNil())
322 Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1.DeploymentStatus"))
323 status = key.SubSchema().(*proto.Kind)
324 Expect(status).ToNot(BeNil())
325 })
326
327 It("should have a valid DeploymentStatus", func() {
328 By("having availableReplicas key")
329 Expect(status.Fields).To(HaveKey("availableReplicas"))
330 replicas := status.Fields["availableReplicas"].(*proto.Primitive)
331 Expect(replicas).ToNot(BeNil())
332 Expect(replicas.Type).To(Equal("integer"))
333
334 By("having conditions key")
335 Expect(status.Fields).To(HaveKey("conditions"))
336 conditions := status.Fields["conditions"].(*proto.Array)
337 Expect(conditions).ToNot(BeNil())
338 Expect(conditions.GetName()).To(Equal(`Array of Reference to "io.k8s.api.apps.v1.DeploymentCondition"`))
339 Expect(conditions.GetExtensions()).To(Equal(map[string]interface{}{
340 "x-kubernetes-patch-merge-key": "type",
341 "x-kubernetes-patch-strategy": "merge",
342 }))
343 condition := conditions.SubType.(proto.Reference)
344 Expect(condition.Reference()).To(Equal("io.k8s.api.apps.v1.DeploymentCondition"))
345 })
346 })
347
348 Describe("spec subschema", func() {
349 var spec *proto.Kind
350 BeforeEach(func() {
351 Expect(deployment.Fields).To(HaveKey("spec"))
352 key, _ := deployment.Fields["spec"].(proto.Reference)
353 Expect(key).ToNot(BeNil())
354 Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1.DeploymentSpec"))
355 spec = key.SubSchema().(*proto.Kind)
356 Expect(spec).ToNot(BeNil())
357 })
358
359 It("should have a spec with no gvk", func() {
360 _, found := spec.GetExtensions()["x-kubernetes-group-version-kind"]
361 Expect(found).To(BeFalse())
362 })
363
364 It("should have a spec with a PodTemplateSpec sub-field", func() {
365 Expect(spec.Fields).To(HaveKey("template"))
366 key := spec.Fields["template"].(proto.Reference)
367 Expect(key).ToNot(BeNil())
368 Expect(key.Reference()).To(Equal("io.k8s.api.core.v1.PodTemplateSpec"))
369 })
370 })
371 })
372
373 var _ = Describe("Reading v3 OpenAPI spec with x-kubernetes-group-version-kind", func() {
374 spec := []byte(`{
375 "openapi": "3.0.0",
376 "info": {
377 "title": "Kubernetes",
378 "version": "v1.24.0"
379 },
380 "paths": {
381 "/foo": {
382 "get": {
383 "responses": {
384 "200": {
385 "description": "OK",
386 "content": {
387 "application/json": {
388 "schema": {
389 "$ref": "#/components/schemas/Foo"
390 }
391 }
392 }
393 }
394 }
395 }
396 }
397 },
398 "components": {
399 "schemas": {
400 "Foo": {
401 "type": "object",
402 "properties": {},
403 "x-kubernetes-group-version-kind": [
404 {
405 "group": "foo",
406 "kind": "Foo",
407 "version": "v1"
408 }
409 ]
410 }
411 }
412 }
413 }`)
414 var schema proto.Schema
415
416 BeforeEach(func() {
417 document, err := openapi_v3.ParseDocument(spec)
418 Expect(err).To(BeNil())
419
420 models, modelsErr := proto.NewOpenAPIV3Data(document)
421 Expect(modelsErr).To(BeNil())
422
423 model := "Foo"
424 schema = models.LookupModel(model)
425 Expect(schema).ToNot(BeNil())
426 })
427
428 It("should have an extension with gvk", func() {
429 _, found := schema.GetExtensions()["x-kubernetes-group-version-kind"]
430 Expect(found).To(BeTrue())
431 })
432
433 It("should convert to proto.Kind type", func() {
434 foo, ok := schema.(*proto.Kind)
435 Expect(ok).To(BeTrue())
436 Expect(foo).ToNot(BeNil())
437 })
438 })
439
View as plain text