mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
Merge pull request #120368 from Jefftree/openapi-remove-openapiv2-skip-filter
remove SkipFilterSchemaForKubectlOpenAPIV2Validation
This commit is contained in:
commit
ce19650212
@ -89,12 +89,6 @@ type Options struct {
|
||||
// Convert to OpenAPI v2.
|
||||
V2 bool
|
||||
|
||||
// Only takes effect if the flag and V2 and both set to true. If the condition is reached,
|
||||
// publish OpenAPI V2 but skip running the spec through ToStructuralOpenAPIV2
|
||||
// This prevents XPreserveUnknownFields:true fields from being cleared
|
||||
// Used only by server side apply
|
||||
SkipFilterSchemaForKubectlOpenAPIV2Validation bool
|
||||
|
||||
// Strip value validation.
|
||||
StripValueValidation bool
|
||||
|
||||
@ -385,14 +379,14 @@ func (b *builder) buildKubeNative(schema *structuralschema.Structural, opts Opti
|
||||
// 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 || ((opts.V2 && !opts.SkipFilterSchemaForKubectlOpenAPIV2Validation) && (schema.XPreserveUnknownFields || crdPreserveUnknownFields)) {
|
||||
if schema == nil || (opts.V2 && (schema.XPreserveUnknownFields || crdPreserveUnknownFields)) {
|
||||
ret = &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
|
||||
}
|
||||
// no, we cannot add more properties here, not even TypeMeta/ObjectMeta because kubectl will complain about
|
||||
// unknown fields for anything else.
|
||||
} else {
|
||||
if opts.V2 && !opts.SkipFilterSchemaForKubectlOpenAPIV2Validation {
|
||||
if opts.V2 {
|
||||
schema = openapiv2.ToStructuralOpenAPIV2(schema)
|
||||
}
|
||||
|
||||
@ -429,7 +423,7 @@ func addEmbeddedProperties(s *spec.Schema, opts Options) {
|
||||
addEmbeddedProperties(s.AdditionalProperties.Schema, opts)
|
||||
}
|
||||
|
||||
if isTrue, ok := s.VendorExtensible.Extensions.GetBool("x-kubernetes-preserve-unknown-fields"); ok && isTrue && opts.V2 && !opts.SkipFilterSchemaForKubectlOpenAPIV2Validation {
|
||||
if isTrue, ok := s.VendorExtensible.Extensions.GetBool("x-kubernetes-preserve-unknown-fields"); ok && isTrue && opts.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
|
||||
|
@ -44,43 +44,31 @@ func TestNewBuilder(t *testing.T) {
|
||||
wantedSchema string
|
||||
wantedItemsSchema string
|
||||
|
||||
v2 bool // produce OpenAPIv2
|
||||
skipFilterSchemaForKubectlOpenAPIV2Validation bool // produce OpenAPIv2 without going through the ToStructuralOpenAPIV2 path
|
||||
v2 bool // produce OpenAPIv2
|
||||
}{
|
||||
{
|
||||
"nil",
|
||||
"",
|
||||
`{"type":"object","x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`, `{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{"with properties",
|
||||
`{"type":"object","properties":{"spec":{"type":"object"},"status":{"type":"object"}}}`,
|
||||
`{"type":"object","properties":{"apiVersion":{"type":"string"},"kind":{"type":"string"},"metadata":{"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"},"spec":{"type":"object"},"status":{"type":"object"}},"x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`,
|
||||
`{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{"type only",
|
||||
`{"type":"object"}`,
|
||||
`{"type":"object","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"}`,
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{"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,
|
||||
false,
|
||||
},
|
||||
{"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"}`,
|
||||
true,
|
||||
true,
|
||||
},
|
||||
{"with extensions",
|
||||
`
|
||||
@ -184,174 +172,6 @@ func TestNewBuilder(t *testing.T) {
|
||||
}`,
|
||||
`{"$ref":"#/definitions/io.k8s.bar.v1.Foo"}`,
|
||||
true,
|
||||
false,
|
||||
},
|
||||
{"with extensions as v3 schema",
|
||||
`
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"int-or-string-1": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
},
|
||||
"int-or-string-2": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
}, {
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"int-or-string-3": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
],
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"int-or-string-4": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
},
|
||||
"int-or-string-5": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
],
|
||||
"allOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
},
|
||||
"int-or-string-6": {
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"preserve-unknown-fields": {
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"embedded-object": {
|
||||
"x-kubernetes-embedded-resource": true,
|
||||
"x-kubernetes-preserve-unknown-fields": true,
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
`
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"apiVersion": {"type":"string"},
|
||||
"kind": {"type":"string"},
|
||||
"metadata": {"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"},
|
||||
"int-or-string-1": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
},
|
||||
"int-or-string-2": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
}, {
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"int-or-string-3": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
],
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"int-or-string-4": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
}],
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
]
|
||||
},
|
||||
"int-or-string-5": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"minimum": 42.0}
|
||||
],
|
||||
"allOf": [{
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
}, {
|
||||
"minimum": 42.0
|
||||
}]
|
||||
},
|
||||
"int-or-string-6": {
|
||||
"x-kubernetes-int-or-string": true,
|
||||
"anyOf": [
|
||||
{"type":"integer"},
|
||||
{"type":"string"}
|
||||
]
|
||||
},
|
||||
"preserve-unknown-fields": {
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type":"string"
|
||||
},
|
||||
"metadata":{
|
||||
"description":"Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#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"}`,
|
||||
true,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -391,7 +211,7 @@ func TestNewBuilder(t *testing.T) {
|
||||
},
|
||||
Scope: apiextensionsv1.NamespaceScoped,
|
||||
},
|
||||
}, "v1", schema, Options{V2: tt.v2, SkipFilterSchemaForKubectlOpenAPIV2Validation: tt.skipFilterSchemaForKubectlOpenAPIV2Validation})
|
||||
}, "v1", schema, Options{V2: tt.v2})
|
||||
|
||||
var wantedSchema, wantedItemsSchema spec.Schema
|
||||
if err := json.Unmarshal([]byte(tt.wantedSchema), &wantedSchema); err != nil {
|
||||
@ -614,13 +434,6 @@ func TestBuildOpenAPIV2(t *testing.T) {
|
||||
`{"type":"object","properties":{"apiVersion":{"type":"string"},"kind":{"type":"string"},"metadata":{"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"},"foo":{"type":"string"}},"x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`,
|
||||
Options{V2: true},
|
||||
},
|
||||
{
|
||||
"v3",
|
||||
`{"type":"object","properties":{"foo":{"type":"string","oneOf":[{"pattern":"a"},{"pattern":"b"}]}}}`,
|
||||
nil,
|
||||
`{"type":"object","properties":{"apiVersion":{"type":"string"},"kind":{"type":"string"},"metadata":{"$ref":"#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"},"foo":{"type":"string","oneOf":[{"pattern":"a"},{"pattern":"b"}]}},"x-kubernetes-group-version-kind":[{"group":"bar.k8s.io","kind":"Foo","version":"v1"}]}`,
|
||||
Options{V2: true, SkipFilterSchemaForKubectlOpenAPIV2Validation: true},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user