@@ -26,6 +26,7 @@ import (
26
26
"github.com/go-openapi/spec"
27
27
28
28
v1 "k8s.io/api/autoscaling/v1"
29
+ structuralschema "k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
29
30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
31
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
31
32
"k8s.io/apimachinery/pkg/runtime"
@@ -58,22 +59,24 @@ var namer *openapi.DefinitionNamer
58
59
59
60
// BuildSwagger builds swagger for the given crd in the given version
60
61
func BuildSwagger (crd * apiextensions.CustomResourceDefinition , version string ) (* spec.Swagger , error ) {
61
- var schema * spec. Schema
62
+ var schema * structuralschema. Structural
62
63
s , err := apiextensions .GetSchemaForVersion (crd , version )
63
64
if err != nil {
64
65
return nil , err
65
66
}
66
67
if s != nil && s .OpenAPIV3Schema != nil {
67
- schema , err = ConvertJSONSchemaPropsToOpenAPIv2Schema (s .OpenAPIV3Schema )
68
- if err != nil {
69
- return nil , err
68
+ ss , err := structuralschema .NewStructural (s .OpenAPIV3Schema )
69
+ if err == nil && len (structuralschema .ValidateStructural (ss , nil )) == 0 {
70
+ // skip non-structural schemas
71
+ schema = ss .Unfold ()
70
72
}
71
73
}
74
+
72
75
// TODO(roycaihw): remove the WebService templating below. The following logic
73
76
// comes from function registerResourceHandlers() in k8s.io/apiserver.
74
77
// Alternatives are either (ideally) refactoring registerResourceHandlers() to
75
78
// reuse the code, or faking an APIInstaller for CR to feed to registerResourceHandlers().
76
- b := newBuilder (crd , version , schema )
79
+ b := newBuilder (crd , version , schema , true )
77
80
78
81
// Sample response types for building web service
79
82
sample := & CRDCanonicalTypeNamer {
@@ -288,31 +291,35 @@ func (b *builder) buildRoute(root, path, action, verb string, sample interface{}
288
291
289
292
// buildKubeNative builds input schema with Kubernetes' native object meta, type meta and
290
293
// extensions
291
- func (b * builder ) buildKubeNative (schema * spec. Schema ) * spec.Schema {
294
+ func (b * builder ) buildKubeNative (schema * structuralschema. Structural , v2 bool ) ( ret * spec.Schema ) {
292
295
// only add properties if we have a schema. Otherwise, kubectl would (wrongly) assume additionalProperties=false
293
296
// and forbid anything outside of apiVersion, kind and metadata. We have to fix kubectl to stop doing this, e.g. by
294
297
// adding additionalProperties=true support to explicitly allow additional fields.
295
298
// TODO: fix kubectl to understand additionalProperties=true
296
299
if schema == nil {
297
- schema = & spec.Schema {
300
+ ret = & spec.Schema {
298
301
SchemaProps : spec.SchemaProps {Type : []string {"object" }},
299
302
}
300
303
// no, we cannot add more properties here, not even TypeMeta/ObjectMeta because kubectl will complain about
301
304
// unknown fields for anything else.
302
305
} else {
303
- schema .SetProperty ("metadata" , * spec .RefSchema (objectMetaSchemaRef ).
306
+ if v2 {
307
+ schema = ToStructuralOpenAPIV2 (schema )
308
+ }
309
+ ret = schema .ToGoOpenAPI ()
310
+ ret .SetProperty ("metadata" , * spec .RefSchema (objectMetaSchemaRef ).
304
311
WithDescription (swaggerPartialObjectMetadataDescriptions ["metadata" ]))
305
- addTypeMetaProperties (schema )
312
+ addTypeMetaProperties (ret )
306
313
}
307
- schema .AddExtension (endpoints .ROUTE_META_GVK , []interface {}{
314
+ ret .AddExtension (endpoints .ROUTE_META_GVK , []interface {}{
308
315
map [string ]interface {}{
309
316
"group" : b .group ,
310
317
"version" : b .version ,
311
318
"kind" : b .kind ,
312
319
},
313
320
})
314
321
315
- return schema
322
+ return ret
316
323
}
317
324
318
325
// getDefinition gets definition for given Kubernetes type. This function is extracted from
@@ -391,7 +398,7 @@ func (b *builder) getOpenAPIConfig() *common.Config {
391
398
}
392
399
}
393
400
394
- func newBuilder (crd * apiextensions.CustomResourceDefinition , version string , schema * spec. Schema ) * builder {
401
+ func newBuilder (crd * apiextensions.CustomResourceDefinition , version string , schema * structuralschema. Structural , v2 bool ) * builder {
395
402
b := & builder {
396
403
schema : & spec.Schema {
397
404
SchemaProps : spec.SchemaProps {Type : []string {"object" }},
@@ -410,7 +417,7 @@ func newBuilder(crd *apiextensions.CustomResourceDefinition, version string, sch
410
417
}
411
418
412
419
// Pre-build schema with Kubernetes native properties
413
- b .schema = b .buildKubeNative (schema )
420
+ b .schema = b .buildKubeNative (schema , v2 )
414
421
b .listSchema = b .buildListSchema ()
415
422
416
423
return b
0 commit comments