Skip to content

Commit bc86aeb

Browse files
committed
apiextensions: switch OpenAPI pubilshing to structural schema
1 parent 6acd921 commit bc86aeb

File tree

5 files changed

+526
-309
lines changed

5 files changed

+526
-309
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/controller/openapi/builder.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/go-openapi/spec"
2727

2828
v1 "k8s.io/api/autoscaling/v1"
29+
structuralschema "k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
3132
"k8s.io/apimachinery/pkg/runtime"
@@ -58,22 +59,24 @@ var namer *openapi.DefinitionNamer
5859

5960
// BuildSwagger builds swagger for the given crd in the given version
6061
func BuildSwagger(crd *apiextensions.CustomResourceDefinition, version string) (*spec.Swagger, error) {
61-
var schema *spec.Schema
62+
var schema *structuralschema.Structural
6263
s, err := apiextensions.GetSchemaForVersion(crd, version)
6364
if err != nil {
6465
return nil, err
6566
}
6667
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()
7072
}
7173
}
74+
7275
// TODO(roycaihw): remove the WebService templating below. The following logic
7376
// comes from function registerResourceHandlers() in k8s.io/apiserver.
7477
// Alternatives are either (ideally) refactoring registerResourceHandlers() to
7578
// 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)
7780

7881
// Sample response types for building web service
7982
sample := &CRDCanonicalTypeNamer{
@@ -288,31 +291,35 @@ func (b *builder) buildRoute(root, path, action, verb string, sample interface{}
288291

289292
// buildKubeNative builds input schema with Kubernetes' native object meta, type meta and
290293
// extensions
291-
func (b *builder) buildKubeNative(schema *spec.Schema) *spec.Schema {
294+
func (b *builder) buildKubeNative(schema *structuralschema.Structural, v2 bool) (ret *spec.Schema) {
292295
// only add properties if we have a schema. Otherwise, kubectl would (wrongly) assume additionalProperties=false
293296
// and forbid anything outside of apiVersion, kind and metadata. We have to fix kubectl to stop doing this, e.g. by
294297
// adding additionalProperties=true support to explicitly allow additional fields.
295298
// TODO: fix kubectl to understand additionalProperties=true
296299
if schema == nil {
297-
schema = &spec.Schema{
300+
ret = &spec.Schema{
298301
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
299302
}
300303
// no, we cannot add more properties here, not even TypeMeta/ObjectMeta because kubectl will complain about
301304
// unknown fields for anything else.
302305
} 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).
304311
WithDescription(swaggerPartialObjectMetadataDescriptions["metadata"]))
305-
addTypeMetaProperties(schema)
312+
addTypeMetaProperties(ret)
306313
}
307-
schema.AddExtension(endpoints.ROUTE_META_GVK, []interface{}{
314+
ret.AddExtension(endpoints.ROUTE_META_GVK, []interface{}{
308315
map[string]interface{}{
309316
"group": b.group,
310317
"version": b.version,
311318
"kind": b.kind,
312319
},
313320
})
314321

315-
return schema
322+
return ret
316323
}
317324

318325
// getDefinition gets definition for given Kubernetes type. This function is extracted from
@@ -391,7 +398,7 @@ func (b *builder) getOpenAPIConfig() *common.Config {
391398
}
392399
}
393400

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 {
395402
b := &builder{
396403
schema: &spec.Schema{
397404
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
@@ -410,7 +417,7 @@ func newBuilder(crd *apiextensions.CustomResourceDefinition, version string, sch
410417
}
411418

412419
// Pre-build schema with Kubernetes native properties
413-
b.schema = b.buildKubeNative(schema)
420+
b.schema = b.buildKubeNative(schema, v2)
414421
b.listSchema = b.buildListSchema()
415422

416423
return b

0 commit comments

Comments
 (0)