mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
apiextensions: filter required nullable to workaround kubectl validation
This commit is contained in:
parent
be1658e08c
commit
ae72e19ab6
@ -73,6 +73,15 @@ func ToStructuralOpenAPIV2(in *structuralschema.Structural) *structuralschema.St
|
|||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for f, fs := range s.Properties {
|
||||||
|
if fs.Nullable {
|
||||||
|
s.ValueValidation.Required, changed = filterOut(s.ValueValidation.Required, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.AdditionalProperties != nil && s.AdditionalProperties.Structural != nil && s.AdditionalProperties.Structural.Nullable {
|
||||||
|
s.ValueValidation.Required, changed = nil, true
|
||||||
|
}
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
},
|
},
|
||||||
// we drop all junctors above, and hence, never reach nested value validations
|
// we drop all junctors above, and hence, never reach nested value validations
|
||||||
@ -82,3 +91,24 @@ func ToStructuralOpenAPIV2(in *structuralschema.Structural) *structuralschema.St
|
|||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterOut(ss []string, x string) ([]string, bool) {
|
||||||
|
var filtered []string
|
||||||
|
for i, s := range ss {
|
||||||
|
if s == x {
|
||||||
|
if filtered == nil {
|
||||||
|
filtered = make([]string, i, len(ss))
|
||||||
|
copy(filtered, ss[:i])
|
||||||
|
}
|
||||||
|
} else if filtered != nil {
|
||||||
|
filtered = append(filtered, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filtered != nil {
|
||||||
|
if len(filtered) == 0 {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
return filtered, true
|
||||||
|
}
|
||||||
|
return ss, false
|
||||||
|
}
|
||||||
|
@ -172,6 +172,63 @@ func Test_ConvertJSONSchemaPropsToOpenAPIv2SchemaByType(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: new(spec.Schema),
|
expected: new(spec.Schema),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "nullable required",
|
||||||
|
in: &apiextensions.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||||
|
"a": {
|
||||||
|
Nullable: true,
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
Nullable: true,
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"a", "c"},
|
||||||
|
},
|
||||||
|
expected: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Type: []string{"object"},
|
||||||
|
Properties: map[string]spec.Schema{
|
||||||
|
"a": {},
|
||||||
|
"b": {},
|
||||||
|
"c": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Type: []string{"string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"c"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nullable required additionalProperties",
|
||||||
|
in: &apiextensions.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextensions.JSONSchemaProps{
|
||||||
|
Nullable: true,
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"a", "c"},
|
||||||
|
},
|
||||||
|
expected: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Type: []string{"object"},
|
||||||
|
AdditionalProperties: &spec.SchemaOrBool{
|
||||||
|
Allows: true,
|
||||||
|
Schema: &spec.Schema{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "title",
|
name: "title",
|
||||||
in: &apiextensions.JSONSchemaProps{
|
in: &apiextensions.JSONSchemaProps{
|
||||||
@ -829,6 +886,34 @@ func fuzzFuncs(f *fuzz.Fuzzer, refFunc func(ref *spec.Ref, c fuzz.Continue, visi
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterOut(t *testing.T) {
|
||||||
|
type Test struct {
|
||||||
|
name string
|
||||||
|
input []string
|
||||||
|
x string
|
||||||
|
expected []string
|
||||||
|
expectedChanged bool
|
||||||
|
}
|
||||||
|
for _, tt := range []Test{
|
||||||
|
{"nil", nil, "foo", nil, false},
|
||||||
|
{"empty", []string{}, "foo", []string{}, false},
|
||||||
|
{"foo", []string{"foo"}, "foo", nil, true},
|
||||||
|
{"aaa", []string{"a", "a", "a"}, "a", nil, true},
|
||||||
|
{"abc", []string{"a", "b", "c"}, "c", []string{"a", "b"}, true},
|
||||||
|
{"abbbcc", []string{"a", "b", "b", "b", "c", "c"}, "b", []string{"a", "c", "c"}, true},
|
||||||
|
} {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, gotChanged := filterOut(tt.input, tt.x)
|
||||||
|
if !reflect.DeepEqual(tt.expected, got) {
|
||||||
|
t.Errorf("expected slice %v, got %v", tt.expected, got)
|
||||||
|
}
|
||||||
|
if tt.expectedChanged != gotChanged {
|
||||||
|
t.Errorf("expected changed %v, got %v", tt.expected, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func max(i, j int) int {
|
func max(i, j int) int {
|
||||||
if i > j {
|
if i > j {
|
||||||
return i
|
return i
|
||||||
|
Loading…
Reference in New Issue
Block a user