Fix publishing x-kubernetes-preserve-unknown-fields working with kubectl

This commit is contained in:
Jordan Liggitt 2019-07-01 23:11:18 -04:00
parent 8756e2c5e4
commit 66453d9372
3 changed files with 32 additions and 22 deletions

View File

@ -297,7 +297,7 @@ func (b *builder) buildKubeNative(schema *structuralschema.Structural, v2 bool)
// and forbid anything outside of apiVersion, kind and metadata. We have to fix kubectl to stop doing this, e.g. by
// adding additionalProperties=true support to explicitly allow additional fields.
// TODO: fix kubectl to understand additionalProperties=true
if schema == nil {
if schema == nil || (v2 && schema.XPreserveUnknownFields) {
ret = &spec.Schema{
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
}
@ -311,7 +311,7 @@ func (b *builder) buildKubeNative(schema *structuralschema.Structural, v2 bool)
ret.SetProperty("metadata", *spec.RefSchema(objectMetaSchemaRef).
WithDescription(swaggerPartialObjectMetadataDescriptions["metadata"]))
addTypeMetaProperties(ret)
addEmbeddedProperties(ret)
addEmbeddedProperties(ret, v2)
}
ret.AddExtension(endpoints.ROUTE_META_GVK, []interface{}{
map[string]interface{}{
@ -324,23 +324,28 @@ func (b *builder) buildKubeNative(schema *structuralschema.Structural, v2 bool)
return ret
}
func addEmbeddedProperties(s *spec.Schema) {
func addEmbeddedProperties(s *spec.Schema, v2 bool) {
if s == nil {
return
}
for k := range s.Properties {
v := s.Properties[k]
addEmbeddedProperties(&v)
addEmbeddedProperties(&v, v2)
s.Properties[k] = v
}
if s.Items != nil {
addEmbeddedProperties(s.Items.Schema)
addEmbeddedProperties(s.Items.Schema, v2)
}
if s.AdditionalProperties != nil {
addEmbeddedProperties(s.AdditionalProperties.Schema)
addEmbeddedProperties(s.AdditionalProperties.Schema, v2)
}
if isTrue, ok := s.VendorExtensible.Extensions.GetBool("x-kubernetes-preserve-unknown-fields"); ok && isTrue && v2 {
// don't add metadata properties if we're publishing to openapi v2 and are allowing unknown fields.
// adding these metadata properties makes kubectl refuse to validate unknown fields.
return
}
if isTrue, ok := s.VendorExtensible.Extensions.GetBool("x-kubernetes-embedded-resource"); ok && isTrue {
s.SetProperty("apiVersion", withDescription(getDefinition(typeMetaType).SchemaProps.Properties["apiVersion"],
"apiVersion defines the versioned schema of this representation of an object. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",

View File

@ -59,6 +59,18 @@ func TestNewBuilder(t *testing.T) {
`{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
true,
},
{"preserve unknown at root v2",
`{"type":"object","x-kubernetes-preserve-unknown-fields":true}`,
`{"type":"object","x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`,
`{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
true,
},
{"preserve unknown at root v3",
`{"type":"object","x-kubernetes-preserve-unknown-fields":true}`,
`{"type":"object","x-kubernetes-preserve-unknown-fields":true,"properties":{"apiVersion":{"type":"string"},"kind":{"type":"string"},"metadata":{"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"}},"x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`,
`{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
false,
},
{"with extensions",
`
{
@ -155,22 +167,7 @@ func TestNewBuilder(t *testing.T) {
"embedded-object": {
"x-kubernetes-embedded-resource": true,
"x-kubernetes-preserve-unknown-fields": true,
"type": "object",
"required":["kind","apiVersion"],
"properties":{
"apiVersion":{
"description":"apiVersion defines the versioned schema of this representation of an object. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type":"string"
},
"kind":{
"description":"kind is a string value representing the type of this object. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type":"string"
},
"metadata":{
"description":"Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
}
}
"type":"object"
}
},
"x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]

View File

@ -65,6 +65,14 @@ func ToStructuralOpenAPIV2(in *structuralschema.Structural) *structuralschema.St
changed = true
}
if s.XPreserveUnknownFields {
// unknown fields break if items or properties are set in kubectl
s.Items = nil
s.Properties = nil
changed = true
}
return changed
},
// we drop all junctors above, and hence, never reach nested value validations