Commit 6acd9215 authored by Dr. Stefan Schimanski's avatar Dr. Stefan Schimanski

apiextensions: add structural schema extension unfolding

parent 4f28fa89
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package schema
// Unfold expands vendor extensions of a structural schema.
// It mutates the receiver.
func (s *Structural) Unfold() *Structural {
if s == nil {
return nil
}
mapper := Visitor{
Structural: func(s *Structural) bool {
if !s.XIntOrString {
return false
}
skipAnyOf := isIntOrStringAnyOfPattern(s)
skipFirstAllOfAnyOf := isIntOrStringAllOfPattern(s)
if skipAnyOf || skipFirstAllOfAnyOf {
return false
}
if s.AnyOf == nil {
s.AnyOf = []NestedValueValidation{
{ForbiddenGenerics: Generic{Type: "integer"}},
{ForbiddenGenerics: Generic{Type: "string"}},
}
} else {
s.AllOf = append([]NestedValueValidation{
{
ValueValidation: ValueValidation{
AnyOf: []NestedValueValidation{
{ForbiddenGenerics: Generic{Type: "integer"}},
{ForbiddenGenerics: Generic{Type: "string"}},
},
},
},
}, s.AllOf...)
}
return true
},
NestedValueValidation: nil, // x-kubernetes-int-or-string cannot be set in nested value validation
}
mapper.Visit(s)
return s
}
...@@ -97,15 +97,8 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path) ...@@ -97,15 +97,8 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path)
// - type: integer // - type: integer
// - type: string // - type: string
// - ... zero or more // - ... zero or more
skipAnyOf := false skipAnyOf := isIntOrStringAnyOfPattern(s)
skipFirstAllOfAnyOf := false skipFirstAllOfAnyOf := isIntOrStringAllOfPattern(s)
if s.XIntOrString && s.ValueValidation != nil {
if len(s.ValueValidation.AnyOf) == 2 && reflect.DeepEqual(s.ValueValidation.AnyOf, intOrStringAnyOf) {
skipAnyOf = true
} else if len(s.ValueValidation.AllOf) >= 1 && len(s.ValueValidation.AllOf[0].AnyOf) == 2 && reflect.DeepEqual(s.ValueValidation.AllOf[0].AnyOf, intOrStringAnyOf) {
skipFirstAllOfAnyOf = true
}
}
allErrs = append(allErrs, validateValueValidation(s.ValueValidation, skipAnyOf, skipFirstAllOfAnyOf, lvl, fldPath)...) allErrs = append(allErrs, validateValueValidation(s.ValueValidation, skipAnyOf, skipFirstAllOfAnyOf, lvl, fldPath)...)
...@@ -157,6 +150,20 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path) ...@@ -157,6 +150,20 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path)
return allErrs return allErrs
} }
func isIntOrStringAnyOfPattern(s *Structural) bool {
if s == nil || s.ValueValidation == nil {
return false
}
return len(s.ValueValidation.AnyOf) == 2 && reflect.DeepEqual(s.ValueValidation.AnyOf, intOrStringAnyOf)
}
func isIntOrStringAllOfPattern(s *Structural) bool {
if s == nil || s.ValueValidation == nil {
return false
}
return len(s.ValueValidation.AllOf) >= 1 && len(s.ValueValidation.AllOf[0].AnyOf) == 2 && reflect.DeepEqual(s.ValueValidation.AllOf[0].AnyOf, intOrStringAnyOf)
}
// validateGeneric checks the generic fields of a structural schema. // validateGeneric checks the generic fields of a structural schema.
func validateGeneric(g *Generic, lvl level, fldPath *field.Path) field.ErrorList { func validateGeneric(g *Generic, lvl level, fldPath *field.Path) field.ErrorList {
if g == nil { if g == nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment