mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #85722 from sttts/sttts-apiextensions-nullable-required
apiextensions: filter required nullable to workaround kubectl validation
This commit is contained in:
commit
1d343c8a0c
@ -73,6 +73,15 @@ func ToStructuralOpenAPIV2(in *structuralschema.Structural) *structuralschema.St
|
||||
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
|
||||
},
|
||||
// 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
|
||||
}
|
||||
|
||||
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),
|
||||
},
|
||||
{
|
||||
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",
|
||||
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 {
|
||||
if i > j {
|
||||
return i
|
||||
|
Loading…
Reference in New Issue
Block a user