apiextensions: prune all GVKs in serializer

This commit is contained in:
Dr. Stefan Schimanski 2019-05-24 18:01:31 +02:00
parent ee4f1847f5
commit d87de1a903

View File

@ -493,6 +493,23 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
statusScopes := map[string]*handlers.RequestScope{} statusScopes := map[string]*handlers.RequestScope{}
scaleScopes := map[string]*handlers.RequestScope{} scaleScopes := map[string]*handlers.RequestScope{}
structuralSchemas := map[string]*structuralschema.Structural{}
for _, v := range crd.Spec.Versions {
val, err := apiextensions.GetSchemaForVersion(crd, v.Name)
if err != nil {
utilruntime.HandleError(err)
return nil, fmt.Errorf("the server could not properly serve the CR schema")
}
if val == nil {
continue
}
structuralSchemas[v.Name], err = structuralschema.NewStructural(val.OpenAPIV3Schema)
if *crd.Spec.PreserveUnknownFields == false && err != nil {
utilruntime.HandleError(err)
return nil, fmt.Errorf("the server could not properly serve the CR schema") // validation should avoid this
}
}
for _, v := range crd.Spec.Versions { for _, v := range crd.Spec.Versions {
safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd) safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd)
if err != nil { if err != nil {
@ -529,14 +546,6 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
return nil, fmt.Errorf("unexpected nil spec.preserveUnknownFields in the CustomResourceDefinition") return nil, fmt.Errorf("unexpected nil spec.preserveUnknownFields in the CustomResourceDefinition")
} }
var structuralSchema *structuralschema.Structural
if validationSchema != nil {
structuralSchema, err = structuralschema.NewStructural(validationSchema.OpenAPIV3Schema)
if *crd.Spec.PreserveUnknownFields == false && err != nil {
return nil, err // validation should avoid this
}
}
var statusSpec *apiextensions.CustomResourceSubresourceStatus var statusSpec *apiextensions.CustomResourceSubresourceStatus
var statusValidator *validate.SchemaValidator var statusValidator *validate.SchemaValidator
subresources, err := apiextensions.GetSubresourcesForVersion(crd, v.Name) subresources, err := apiextensions.GetSubresourcesForVersion(crd, v.Name)
@ -591,7 +600,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
converter: safeConverter, converter: safeConverter,
decoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name}, decoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name},
encoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: storageVersion}, encoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: storageVersion},
structuralSchema: structuralSchema, structuralSchemas: structuralSchemas,
structuralSchemaGK: kind.GroupKind(), structuralSchemaGK: kind.GroupKind(),
preserveUnknownFields: *crd.Spec.PreserveUnknownFields, preserveUnknownFields: *crd.Spec.PreserveUnknownFields,
}, },
@ -619,7 +628,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
typer: typer, typer: typer,
creator: creator, creator: creator,
converter: safeConverter, converter: safeConverter,
structuralSchema: structuralSchema, structuralSchemas: structuralSchemas,
structuralSchemaGK: kind.GroupKind(), structuralSchemaGK: kind.GroupKind(),
preserveUnknownFields: *crd.Spec.PreserveUnknownFields, preserveUnknownFields: *crd.Spec.PreserveUnknownFields,
}, },
@ -676,7 +685,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
statusScope.Serializer = unstructuredNegotiatedSerializer{ statusScope.Serializer = unstructuredNegotiatedSerializer{
typer: typer, creator: creator, typer: typer, creator: creator,
converter: safeConverter, converter: safeConverter,
structuralSchema: structuralSchema, structuralSchemas: structuralSchemas,
structuralSchemaGK: kind.GroupKind(), structuralSchemaGK: kind.GroupKind(),
preserveUnknownFields: *crd.Spec.PreserveUnknownFields, preserveUnknownFields: *crd.Spec.PreserveUnknownFields,
} }
@ -715,7 +724,7 @@ type unstructuredNegotiatedSerializer struct {
creator runtime.ObjectCreater creator runtime.ObjectCreater
converter runtime.ObjectConvertor converter runtime.ObjectConvertor
structuralSchema *structuralschema.Structural structuralSchemas map[string]*structuralschema.Structural // by version
structuralSchemaGK schema.GroupKind structuralSchemaGK schema.GroupKind
preserveUnknownFields bool preserveUnknownFields bool
} }
@ -750,7 +759,7 @@ func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Enco
} }
func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{structuralSchema: s.structuralSchema, structuralSchemaGK: s.structuralSchemaGK, preserveUnknownFields: s.preserveUnknownFields}} d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{structuralSchemas: s.structuralSchemas, structuralSchemaGK: s.structuralSchemaGK, preserveUnknownFields: s.preserveUnknownFields}}
return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv) return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv)
} }
@ -842,7 +851,7 @@ type crdConversionRESTOptionsGetter struct {
converter runtime.ObjectConvertor converter runtime.ObjectConvertor
encoderVersion schema.GroupVersion encoderVersion schema.GroupVersion
decoderVersion schema.GroupVersion decoderVersion schema.GroupVersion
structuralSchema *structuralschema.Structural structuralSchemas map[string]*structuralschema.Structural // by version
structuralSchemaGK schema.GroupKind structuralSchemaGK schema.GroupKind
preserveUnknownFields bool preserveUnknownFields bool
} }
@ -853,12 +862,12 @@ func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupReso
d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{ d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{
// drop invalid fields while decoding old CRs (before we haven't had any ObjectMeta validation) // drop invalid fields while decoding old CRs (before we haven't had any ObjectMeta validation)
dropInvalidMetadata: true, dropInvalidMetadata: true,
structuralSchema: t.structuralSchema, structuralSchemas: t.structuralSchemas,
structuralSchemaGK: t.structuralSchemaGK, structuralSchemaGK: t.structuralSchemaGK,
preserveUnknownFields: t.preserveUnknownFields, preserveUnknownFields: t.preserveUnknownFields,
}} }}
c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{ c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{
structuralSchema: t.structuralSchema, structuralSchemas: t.structuralSchemas,
structuralSchemaGK: t.structuralSchemaGK, structuralSchemaGK: t.structuralSchemaGK,
preserveUnknownFields: t.preserveUnknownFields, preserveUnknownFields: t.preserveUnknownFields,
}} }}
@ -950,7 +959,7 @@ func (v schemaCoercingConverter) ConvertFieldLabel(gvk schema.GroupVersionKind,
type unstructuredSchemaCoercer struct { type unstructuredSchemaCoercer struct {
dropInvalidMetadata bool dropInvalidMetadata bool
structuralSchema *structuralschema.Structural structuralSchemas map[string]*structuralschema.Structural
structuralSchemaGK schema.GroupKind structuralSchemaGK schema.GroupKind
preserveUnknownFields bool preserveUnknownFields bool
} }
@ -976,7 +985,7 @@ func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
return err return err
} }
if !v.preserveUnknownFields && gv.Group == v.structuralSchemaGK.Group && kind == v.structuralSchemaGK.Kind { if !v.preserveUnknownFields && gv.Group == v.structuralSchemaGK.Group && kind == v.structuralSchemaGK.Kind {
structuralpruning.Prune(u.Object, v.structuralSchema) structuralpruning.Prune(u.Object, v.structuralSchemas[gv.Version])
} }
// restore meta fields, starting clean // restore meta fields, starting clean