mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-20 01:01:22 +00:00
allow CEL and additionalProperties used in allof
additionalProperties makes sense to use in a NestedValueValidation, but it is currently forbidden. This change makes the treatment of additionalProperties more in line with the treatment of `items` or `properties` - so users can specify additional value validations for schemas which use `additionalProperties` structurally. This change also move XValidations so that it is allowed to be used inside an allOf in a CRD schema
This commit is contained in:
parent
0aa01be424
commit
bf7770f92f
@ -122,10 +122,10 @@ func Compile(s *schema.Structural, declType *apiservercel.DeclType, perCallLimit
|
|||||||
metrics.Metrics.ObserveCompilation(time.Since(t))
|
metrics.Metrics.ObserveCompilation(time.Since(t))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if len(s.Extensions.XValidations) == 0 {
|
if len(s.XValidations) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
celRules := s.Extensions.XValidations
|
celRules := s.XValidations
|
||||||
|
|
||||||
oldSelfEnvSet, optionalOldSelfEnvSet, err := prepareEnvSet(baseEnvSet, declType)
|
oldSelfEnvSet, optionalOldSelfEnvSet, err := prepareEnvSet(baseEnvSet, declType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -168,7 +168,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "self >= oldSelf.value()", OptionalOldSelf: ptr.To(true)},
|
{Rule: "self >= oldSelf.value()", OptionalOldSelf: ptr.To(true)},
|
||||||
{Rule: "self >= oldSelf.orValue(1)", OptionalOldSelf: ptr.To(true)},
|
{Rule: "self >= oldSelf.orValue(1)", OptionalOldSelf: ptr.To(true)},
|
||||||
@ -216,7 +216,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "self.i >= oldSelf.i.value()", OptionalOldSelf: ptr.To(true)},
|
{Rule: "self.i >= oldSelf.i.value()", OptionalOldSelf: ptr.To(true)},
|
||||||
{Rule: "self.s == oldSelf.s.value()", OptionalOldSelf: ptr.To(true)},
|
{Rule: "self.s == oldSelf.s.value()", OptionalOldSelf: ptr.To(true)},
|
||||||
@ -266,7 +266,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self.minReplicas < self.maxReplicas",
|
Rule: "self.minReplicas < self.maxReplicas",
|
||||||
@ -285,7 +285,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "string",
|
Type: "string",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self.startsWith('s')",
|
Rule: "self.startsWith('s')",
|
||||||
@ -307,7 +307,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
Format: "byte",
|
Format: "byte",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "string(self).endsWith('s')",
|
Rule: "string(self).endsWith('s')",
|
||||||
@ -326,7 +326,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "boolean",
|
Type: "boolean",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self == true",
|
Rule: "self == true",
|
||||||
@ -345,7 +345,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self > 0",
|
Rule: "self > 0",
|
||||||
@ -364,7 +364,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "number",
|
Type: "number",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self > 1.0",
|
Rule: "self > 1.0",
|
||||||
@ -400,7 +400,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self.nestedObj.val == 10",
|
Rule: "self.nestedObj.val == 10",
|
||||||
@ -436,7 +436,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self.nestedObj[0]) == 10",
|
Rule: "size(self.nestedObj[0]) == 10",
|
||||||
@ -470,7 +470,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self[0][0]) == 10",
|
Rule: "size(self[0][0]) == 10",
|
||||||
@ -511,7 +511,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self[0].nestedObj.val == 10",
|
Rule: "self[0].nestedObj.val == 10",
|
||||||
@ -529,17 +529,17 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
input: schema.Structural{
|
input: schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Bool: true,
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Structural: &schema.Structural{
|
Bool: true,
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "boolean",
|
Generic: schema.Generic{
|
||||||
Nullable: false,
|
Type: "boolean",
|
||||||
},
|
Nullable: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self) > 0",
|
Rule: "size(self) > 0",
|
||||||
@ -558,7 +558,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "number",
|
Type: "number",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self) == 10",
|
Rule: "size(self) == 10",
|
||||||
@ -577,7 +577,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self) == 10",
|
Rule: "size(self) == 10",
|
||||||
@ -623,7 +623,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self.__namespace__[0]) == 10",
|
Rule: "size(self.__namespace__[0]) == 10",
|
||||||
@ -677,7 +677,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "size(self.namespace[0]) == 10",
|
Rule: "size(self.namespace[0]) == 10",
|
||||||
@ -704,7 +704,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "self > 0"},
|
{Rule: "self > 0"},
|
||||||
{Rule: "self >= oldSelf"},
|
{Rule: "self >= oldSelf"},
|
||||||
@ -722,7 +722,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: " \t"},
|
{Rule: " \t"},
|
||||||
},
|
},
|
||||||
@ -745,7 +745,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "42"},
|
{Rule: "42"},
|
||||||
},
|
},
|
||||||
@ -761,7 +761,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "string",
|
Type: "string",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self.startsWith('s')",
|
Rule: "self.startsWith('s')",
|
||||||
@ -780,7 +780,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self == 5",
|
Rule: "self == 5",
|
||||||
@ -799,7 +799,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "number",
|
Type: "number",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: "self < 32.0",
|
Rule: "self < 32.0",
|
||||||
@ -818,7 +818,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "fakeFunction('abc') == 'ABC'"},
|
{Rule: "fakeFunction('abc') == 'ABC'"},
|
||||||
},
|
},
|
||||||
@ -835,7 +835,7 @@ func TestCelCompilation(t *testing.T) {
|
|||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{Rule: "fakeFunction('abc') == 'ABC'"},
|
{Rule: "fakeFunction('abc') == 'ABC'"},
|
||||||
},
|
},
|
||||||
@ -917,7 +917,7 @@ func genArrayWithRule(arrayType, rule string) func(maxItems *int64) *schema.Stru
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxItems: maxItems,
|
MaxItems: maxItems,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -947,7 +947,7 @@ func genArrayOfArraysWithRule(arrayType, rule string) func(maxItems *int64) *sch
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxItems: maxItems,
|
MaxItems: maxItems,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -987,7 +987,7 @@ func genObjectArrayWithRule(rule string) func(maxItems *int64) *schema.Structura
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxItems: maxItems,
|
MaxItems: maxItems,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1007,17 +1007,17 @@ func getMapArrayWithRule(mapType, rule string) func(maxItems *int64) *schema.Str
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: mapType,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: mapType,
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxItems: maxItems,
|
MaxItems: maxItems,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1034,22 +1034,22 @@ func genMapWithRule(mapType, rule string) func(maxProperties *int64) *schema.Str
|
|||||||
return &schema.Structural{
|
return &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: passedType,
|
|
||||||
},
|
|
||||||
ValueValidation: &schema.ValueValidation{
|
|
||||||
Format: passedFormat,
|
|
||||||
},
|
|
||||||
Extensions: schema.Extensions{
|
|
||||||
XIntOrString: xIntString,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: passedType,
|
||||||
|
},
|
||||||
|
ValueValidation: &schema.ValueValidation{
|
||||||
|
Format: passedFormat,
|
||||||
|
},
|
||||||
|
Extensions: schema.Extensions{
|
||||||
|
XIntOrString: xIntString,
|
||||||
|
},
|
||||||
|
}},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxProperties: maxProperties,
|
MaxProperties: maxProperties,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1069,7 +1069,7 @@ func genStringWithRule(rule string) func(maxLength *int64) *schema.Structural {
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxLength: maxLength,
|
MaxLength: maxLength,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1098,7 +1098,7 @@ func genEnumWithRuleAndValues(rule string, values ...string) func(maxLength *int
|
|||||||
MaxLength: maxLength,
|
MaxLength: maxLength,
|
||||||
Enum: enums,
|
Enum: enums,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1119,7 +1119,7 @@ func genBytesWithRule(rule string) func(maxLength *int64) *schema.Structural {
|
|||||||
MaxLength: maxLength,
|
MaxLength: maxLength,
|
||||||
Format: "byte",
|
Format: "byte",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1135,19 +1135,19 @@ func genNestedSpecWithRule(rule string) func(maxLength *int64) *schema.Structura
|
|||||||
return &schema.Structural{
|
return &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
ValueValidation: &schema.ValueValidation{
|
|
||||||
MaxLength: maxLength,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
ValueValidation: &schema.ValueValidation{
|
||||||
|
MaxLength: maxLength,
|
||||||
|
},
|
||||||
|
}},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxProperties: maxLength,
|
MaxProperties: maxLength,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1167,28 +1167,28 @@ func genAllMaxNestedSpecWithRootRule(rule string) func(maxLength *int64) *schema
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "object",
|
|
||||||
},
|
|
||||||
ValueValidation: &schema.ValueValidation{
|
|
||||||
Required: []string{"required"},
|
|
||||||
MaxProperties: maxLength,
|
|
||||||
},
|
|
||||||
Properties: map[string]schema.Structural{
|
|
||||||
"required": {
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "object",
|
||||||
|
},
|
||||||
|
ValueValidation: &schema.ValueValidation{
|
||||||
|
Required: []string{"required"},
|
||||||
|
MaxProperties: maxLength,
|
||||||
|
},
|
||||||
|
Properties: map[string]schema.Structural{
|
||||||
|
"required": {
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxProperties: maxLength,
|
MaxProperties: maxLength,
|
||||||
},
|
},
|
||||||
@ -1196,7 +1196,7 @@ func genAllMaxNestedSpecWithRootRule(rule string) func(maxLength *int64) *schema
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxItems: maxLength,
|
MaxItems: maxLength,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1216,32 +1216,32 @@ func genOneMaxNestedSpecWithRootRule(rule string) func(maxLength *int64) *schema
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "object",
|
|
||||||
},
|
|
||||||
ValueValidation: &schema.ValueValidation{
|
|
||||||
Required: []string{"required"},
|
|
||||||
},
|
|
||||||
Properties: map[string]schema.Structural{
|
|
||||||
"required": {
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "object",
|
||||||
|
},
|
||||||
|
ValueValidation: &schema.ValueValidation{
|
||||||
|
Required: []string{"required"},
|
||||||
|
},
|
||||||
|
Properties: map[string]schema.Structural{
|
||||||
|
"required": {
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxProperties: maxLength,
|
MaxProperties: maxLength,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
@ -1292,12 +1292,12 @@ func genMapForMap() *schema.Structural {
|
|||||||
return &schema.Structural{
|
return &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "number",
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "number",
|
||||||
|
},
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1305,13 +1305,13 @@ func genMapWithCustomItemRule(item *schema.Structural, rule string) func(maxProp
|
|||||||
return func(maxProperties *int64) *schema.Structural {
|
return func(maxProperties *int64) *schema.Structural {
|
||||||
return &schema.Structural{
|
return &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: item},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: item},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
MaxProperties: maxProperties,
|
MaxProperties: maxProperties,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
|
@ -279,11 +279,18 @@ func nestedValueValidationToStructural(nvv *schema.NestedValueValidation) *Struc
|
|||||||
newProperties[k] = *nestedValueValidationToStructural(&v).Structural
|
newProperties[k] = *nestedValueValidationToStructural(&v).Structural
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newAdditionalProperties *schema.StructuralOrBool
|
||||||
|
if nvv.AdditionalProperties != nil {
|
||||||
|
newAdditionalProperties = &schema.StructuralOrBool{Structural: nestedValueValidationToStructural(nvv.AdditionalProperties).Structural}
|
||||||
|
}
|
||||||
|
|
||||||
return &Structural{
|
return &Structural{
|
||||||
Structural: &schema.Structural{
|
Structural: &schema.Structural{
|
||||||
Items: newItems,
|
Items: newItems,
|
||||||
Properties: newProperties,
|
Properties: newProperties,
|
||||||
ValueValidation: &nvv.ValueValidation,
|
AdditionalProperties: newAdditionalProperties,
|
||||||
|
ValueValidation: &nvv.ValueValidation,
|
||||||
|
ValidationExtensions: nvv.ValidationExtensions,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,11 @@ func WithTypeAndObjectMeta(s *schema.Structural) *schema.Structural {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
result := &schema.Structural{
|
result := &schema.Structural{
|
||||||
Generic: s.Generic,
|
AdditionalProperties: s.AdditionalProperties,
|
||||||
Extensions: s.Extensions,
|
Generic: s.Generic,
|
||||||
ValueValidation: s.ValueValidation,
|
Extensions: s.Extensions,
|
||||||
|
ValueValidation: s.ValueValidation,
|
||||||
|
ValidationExtensions: s.ValidationExtensions,
|
||||||
}
|
}
|
||||||
props := make(map[string]schema.Structural, len(s.Properties))
|
props := make(map[string]schema.Structural, len(s.Properties))
|
||||||
for k, prop := range s.Properties {
|
for k, prop := range s.Properties {
|
||||||
|
@ -199,11 +199,11 @@ func testSchema() *schema.Structural {
|
|||||||
"flags": {
|
"flags": {
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "boolean",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "boolean",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -317,12 +317,12 @@ func TestEstimateMaxLengthJSON(t *testing.T) {
|
|||||||
InputSchema: &schema.Structural{
|
InputSchema: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
// expected JSON is {"":"","":"",...} so our length should be (3000000 - 2) / 6
|
// expected JSON is {"":"","":"",...} so our length should be (3000000 - 2) / 6
|
||||||
ExpectedMaxElements: 393215,
|
ExpectedMaxElements: 393215,
|
||||||
@ -382,12 +382,12 @@ func TestEstimateMaxLengthJSON(t *testing.T) {
|
|||||||
InputSchema: &schema.Structural{
|
InputSchema: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
}},
|
||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
Format: "string",
|
Format: "string",
|
||||||
MaxProperties: maxPtr(15),
|
MaxProperties: maxPtr(15),
|
||||||
@ -519,15 +519,15 @@ func genNestedSchema(depth int) *schema.Structural {
|
|||||||
generator = func(d int) schema.Structural {
|
generator = func(d int) schema.Structural {
|
||||||
nodeTemplate := schema.Structural{
|
nodeTemplate := schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{},
|
||||||
}
|
}
|
||||||
if d == 1 {
|
if d == 1 {
|
||||||
return nodeTemplate
|
return nodeTemplate
|
||||||
} else {
|
} else {
|
||||||
mapType := generator(d - 1)
|
mapType := generator(d - 1)
|
||||||
nodeTemplate.Generic.AdditionalProperties.Structural = &mapType
|
nodeTemplate.AdditionalProperties.Structural = &mapType
|
||||||
return nodeTemplate
|
return nodeTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2787,7 +2787,7 @@ func TestReasonAndFldPath(t *testing.T) {
|
|||||||
"field2": stringType,
|
"field2": stringType,
|
||||||
"field3": stringType,
|
"field3": stringType,
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: apiextensions.ValidationRules{
|
XValidations: apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: `self.field2 != "value2"`,
|
Rule: `self.field2 != "value2"`,
|
||||||
@ -2852,16 +2852,16 @@ func TestValidateFieldPath(t *testing.T) {
|
|||||||
"foo": {
|
"foo": {
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "object",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "object",
|
||||||
Properties: map[string]schema.Structural{
|
},
|
||||||
"subAdd": {
|
Properties: map[string]schema.Structural{
|
||||||
Generic: schema.Generic{
|
"subAdd": {
|
||||||
Type: "number",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "number",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4387,7 +4387,7 @@ func BenchmarkCELValidationWithAndWithoutOldSelfReference(b *testing.B) {
|
|||||||
ValueValidation: &schema.ValueValidation{
|
ValueValidation: &schema.ValueValidation{
|
||||||
Format: "date-time",
|
Format: "date-time",
|
||||||
},
|
},
|
||||||
Extensions: schema.Extensions{
|
ValidationExtensions: schema.ValidationExtensions{
|
||||||
XValidations: []apiextensions.ValidationRule{
|
XValidations: []apiextensions.ValidationRule{
|
||||||
{Rule: rule},
|
{Rule: rule},
|
||||||
},
|
},
|
||||||
@ -4520,9 +4520,9 @@ func objectTypePtr(props map[string]schema.Structural) *schema.Structural {
|
|||||||
func mapType(valSchema *schema.Structural) schema.Structural {
|
func mapType(valSchema *schema.Structural) schema.Structural {
|
||||||
result := schema.Structural{
|
result := schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{Bool: true, Structural: valSchema},
|
|
||||||
},
|
},
|
||||||
|
AdditionalProperties: &schema.StructuralOrBool{Bool: true, Structural: valSchema},
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -4541,7 +4541,7 @@ func intOrStringType() schema.Structural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withRule(s schema.Structural, rule string) schema.Structural {
|
func withRule(s schema.Structural, rule string) schema.Structural {
|
||||||
s.Extensions.XValidations = apiextensions.ValidationRules{
|
s.XValidations = apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
},
|
},
|
||||||
@ -4550,7 +4550,7 @@ func withRule(s schema.Structural, rule string) schema.Structural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withRuleMessageAndMessageExpression(s schema.Structural, rule, message, messageExpression string) schema.Structural {
|
func withRuleMessageAndMessageExpression(s schema.Structural, rule, message, messageExpression string) schema.Structural {
|
||||||
s.Extensions.XValidations = apiextensions.ValidationRules{
|
s.XValidations = apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
Message: message,
|
Message: message,
|
||||||
@ -4561,7 +4561,7 @@ func withRuleMessageAndMessageExpression(s schema.Structural, rule, message, mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withReasonAndFldPath(s schema.Structural, rule, jsonPath string, reason *apiextensions.FieldValueErrorReason) schema.Structural {
|
func withReasonAndFldPath(s schema.Structural, rule, jsonPath string, reason *apiextensions.FieldValueErrorReason) schema.Structural {
|
||||||
s.Extensions.XValidations = apiextensions.ValidationRules{
|
s.XValidations = apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
FieldPath: jsonPath,
|
FieldPath: jsonPath,
|
||||||
@ -4572,7 +4572,7 @@ func withReasonAndFldPath(s schema.Structural, rule, jsonPath string, reason *ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withRuleAndMessageExpression(s schema.Structural, rule, messageExpression string) schema.Structural {
|
func withRuleAndMessageExpression(s schema.Structural, rule, messageExpression string) schema.Structural {
|
||||||
s.Extensions.XValidations = apiextensions.ValidationRules{
|
s.XValidations = apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
MessageExpression: messageExpression,
|
MessageExpression: messageExpression,
|
||||||
@ -4582,7 +4582,7 @@ func withRuleAndMessageExpression(s schema.Structural, rule, messageExpression s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withRulePtr(s *schema.Structural, rule string) *schema.Structural {
|
func withRulePtr(s *schema.Structural, rule string) *schema.Structural {
|
||||||
s.Extensions.XValidations = apiextensions.ValidationRules{
|
s.XValidations = apiextensions.ValidationRules{
|
||||||
{
|
{
|
||||||
Rule: rule,
|
Rule: rule,
|
||||||
},
|
},
|
||||||
|
@ -100,10 +100,10 @@ var (
|
|||||||
mapSchema = schema.Structural{
|
mapSchema = schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Bool: true,
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Structural: &stringSchema,
|
Bool: true,
|
||||||
},
|
Structural: &stringSchema,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -18,6 +18,7 @@ package schema
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
)
|
)
|
||||||
@ -62,10 +63,16 @@ func NewStructural(s *apiextensions.JSONSchemaProps) (*Structural, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vx, err := newValidationExtensions(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
ss := &Structural{
|
ss := &Structural{
|
||||||
Generic: *g,
|
Generic: *g,
|
||||||
Extensions: *x,
|
Extensions: *x,
|
||||||
ValueValidation: vv,
|
ValueValidation: vv,
|
||||||
|
ValidationExtensions: *vx,
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Items != nil {
|
if s.Items != nil {
|
||||||
@ -91,6 +98,18 @@ func NewStructural(s *apiextensions.JSONSchemaProps) (*Structural, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.AdditionalProperties != nil {
|
||||||
|
if s.AdditionalProperties.Schema != nil {
|
||||||
|
additionalPropertiesSchema, err := NewStructural(s.AdditionalProperties.Schema)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ss.AdditionalProperties = &StructuralOrBool{Structural: additionalPropertiesSchema, Bool: true}
|
||||||
|
} else {
|
||||||
|
ss.AdditionalProperties = &StructuralOrBool{Bool: s.AdditionalProperties.Allows}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ss, nil
|
return ss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,18 +127,6 @@ func newGenerics(s *apiextensions.JSONSchemaProps) (*Generic, error) {
|
|||||||
g.Default = JSON{interface{}(*s.Default)}
|
g.Default = JSON{interface{}(*s.Default)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.AdditionalProperties != nil {
|
|
||||||
if s.AdditionalProperties.Schema != nil {
|
|
||||||
ss, err := NewStructural(s.AdditionalProperties.Schema)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
g.AdditionalProperties = &StructuralOrBool{Structural: ss, Bool: true}
|
|
||||||
} else {
|
|
||||||
g.AdditionalProperties = &StructuralOrBool{Bool: s.AdditionalProperties.Allows}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,10 +212,16 @@ func newNestedValueValidation(s *apiextensions.JSONSchemaProps) (*NestedValueVal
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vx, err := newValidationExtensions(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
v := &NestedValueValidation{
|
v := &NestedValueValidation{
|
||||||
ValueValidation: *vv,
|
ValueValidation: *vv,
|
||||||
ForbiddenGenerics: *g,
|
ValidationExtensions: *vx,
|
||||||
ForbiddenExtensions: *x,
|
ForbiddenGenerics: *g,
|
||||||
|
ForbiddenExtensions: *x,
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Items != nil {
|
if s.Items != nil {
|
||||||
@ -232,6 +245,18 @@ func newNestedValueValidation(s *apiextensions.JSONSchemaProps) (*NestedValueVal
|
|||||||
v.Properties[k] = *nvv
|
v.Properties[k] = *nvv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if s.AdditionalProperties != nil {
|
||||||
|
if s.AdditionalProperties.Schema != nil {
|
||||||
|
additionalPropertiesSchema, err := newNestedValueValidation(s.AdditionalProperties.Schema)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
v.AdditionalProperties = additionalPropertiesSchema
|
||||||
|
} else if s.AdditionalProperties.Allows {
|
||||||
|
v.AdditionalProperties = &NestedValueValidation{}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
@ -248,9 +273,6 @@ func newExtensions(s *apiextensions.JSONSchemaProps) (*Extensions, error) {
|
|||||||
XListType: s.XListType,
|
XListType: s.XListType,
|
||||||
XMapType: s.XMapType,
|
XMapType: s.XMapType,
|
||||||
}
|
}
|
||||||
if err := apiextensionsv1.Convert_apiextensions_ValidationRules_To_v1_ValidationRules(&s.XValidations, &ret.XValidations, nil); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.XPreserveUnknownFields != nil {
|
if s.XPreserveUnknownFields != nil {
|
||||||
if !*s.XPreserveUnknownFields {
|
if !*s.XPreserveUnknownFields {
|
||||||
@ -262,6 +284,19 @@ func newExtensions(s *apiextensions.JSONSchemaProps) (*Extensions, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newValidationExtensions(s *apiextensions.JSONSchemaProps) (*ValidationExtensions, error) {
|
||||||
|
if s == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &ValidationExtensions{}
|
||||||
|
if err := apiextensionsv1.Convert_apiextensions_ValidationRules_To_v1_ValidationRules(&s.XValidations, &ret.XValidations, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
// validateUnsupportedFields checks that those fields rejected by validation are actually unset.
|
// validateUnsupportedFields checks that those fields rejected by validation are actually unset.
|
||||||
func validateUnsupportedFields(s *apiextensions.JSONSchemaProps) error {
|
func validateUnsupportedFields(s *apiextensions.JSONSchemaProps) error {
|
||||||
if len(s.ID) > 0 {
|
if len(s.ID) > 0 {
|
||||||
|
@ -99,19 +99,17 @@ func TestDefault(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Structural: &structuralschema.Structural{
|
||||||
Structural: &structuralschema.Structural{
|
Properties: map[string]structuralschema.Structural{
|
||||||
Properties: map[string]structuralschema.Structural{
|
"a": {
|
||||||
"a": {
|
Generic: structuralschema.Generic{
|
||||||
Generic: structuralschema.Generic{
|
Default: structuralschema.JSON{Object: "alpha"},
|
||||||
Default: structuralschema.JSON{Object: "alpha"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"b": {
|
},
|
||||||
Generic: structuralschema.Generic{
|
"b": {
|
||||||
Default: structuralschema.JSON{Object: "beta"},
|
Generic: structuralschema.Generic{
|
||||||
},
|
Default: structuralschema.JSON{Object: "beta"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -182,34 +180,28 @@ func TestDefault(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, `{"a": "A"}`},
|
}, `{"a": "A"}`},
|
||||||
{"null in nullable object with additionalProperties", `{"a": null}`, &structuralschema.Structural{
|
{"null in nullable object with additionalProperties", `{"a": null}`, &structuralschema.Structural{
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Structural: &structuralschema.Structural{
|
||||||
Structural: &structuralschema.Structural{
|
Generic: structuralschema.Generic{
|
||||||
Generic: structuralschema.Generic{
|
Nullable: true,
|
||||||
Nullable: true,
|
Default: structuralschema.JSON{Object: "A"},
|
||||||
Default: structuralschema.JSON{Object: "A"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, `{"a": null}`},
|
}, `{"a": null}`},
|
||||||
{"null in non-nullable object with additionalProperties", `{"a": null}`, &structuralschema.Structural{
|
{"null in non-nullable object with additionalProperties", `{"a": null}`, &structuralschema.Structural{
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Structural: &structuralschema.Structural{
|
||||||
Structural: &structuralschema.Structural{
|
Generic: structuralschema.Generic{
|
||||||
Generic: structuralschema.Generic{
|
Nullable: false,
|
||||||
Nullable: false,
|
Default: structuralschema.JSON{Object: "A"},
|
||||||
Default: structuralschema.JSON{Object: "A"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, `{"a": "A"}`},
|
}, `{"a": "A"}`},
|
||||||
{"null unknown field", `{"a": null}`, &structuralschema.Structural{
|
{"null unknown field", `{"a": null}`, &structuralschema.Structural{
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Bool: true,
|
||||||
Bool: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, `{"a": null}`},
|
}, `{"a": null}`},
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,16 @@ func (s *Structural) ToKubeOpenAPI() *spec.Schema {
|
|||||||
ret.Properties[k] = *v.ToKubeOpenAPI()
|
ret.Properties[k] = *v.ToKubeOpenAPI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if s.AdditionalProperties != nil {
|
||||||
|
ret.AdditionalProperties = &spec.SchemaOrBool{
|
||||||
|
Allows: s.AdditionalProperties.Bool,
|
||||||
|
Schema: s.AdditionalProperties.Structural.ToKubeOpenAPI(),
|
||||||
|
}
|
||||||
|
}
|
||||||
s.Generic.toKubeOpenAPI(ret)
|
s.Generic.toKubeOpenAPI(ret)
|
||||||
s.Extensions.toKubeOpenAPI(ret)
|
s.Extensions.toKubeOpenAPI(ret)
|
||||||
s.ValueValidation.toKubeOpenAPI(ret)
|
s.ValueValidation.toKubeOpenAPI(ret)
|
||||||
|
s.ValidationExtensions.toKubeOpenAPI(ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,12 +59,6 @@ func (g *Generic) toKubeOpenAPI(ret *spec.Schema) {
|
|||||||
ret.Type = spec.StringOrArray{g.Type}
|
ret.Type = spec.StringOrArray{g.Type}
|
||||||
}
|
}
|
||||||
ret.Nullable = g.Nullable
|
ret.Nullable = g.Nullable
|
||||||
if g.AdditionalProperties != nil {
|
|
||||||
ret.AdditionalProperties = &spec.SchemaOrBool{
|
|
||||||
Allows: g.AdditionalProperties.Bool,
|
|
||||||
Schema: g.AdditionalProperties.Structural.ToKubeOpenAPI(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret.Description = g.Description
|
ret.Description = g.Description
|
||||||
ret.Title = g.Title
|
ret.Title = g.Title
|
||||||
ret.Default = g.Default.Object
|
ret.Default = g.Default.Object
|
||||||
@ -87,6 +87,13 @@ func (x *Extensions) toKubeOpenAPI(ret *spec.Schema) {
|
|||||||
if x.XMapType != nil {
|
if x.XMapType != nil {
|
||||||
ret.VendorExtensible.AddExtension("x-kubernetes-map-type", *x.XMapType)
|
ret.VendorExtensible.AddExtension("x-kubernetes-map-type", *x.XMapType)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ValidationExtensions) toKubeOpenAPI(ret *spec.Schema) {
|
||||||
|
if x == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(x.XValidations) > 0 {
|
if len(x.XValidations) > 0 {
|
||||||
ret.VendorExtensible.AddExtension("x-kubernetes-validations", x.XValidations)
|
ret.VendorExtensible.AddExtension("x-kubernetes-validations", x.XValidations)
|
||||||
}
|
}
|
||||||
@ -138,6 +145,7 @@ func (vv *NestedValueValidation) toKubeOpenAPI() *spec.Schema {
|
|||||||
ret := &spec.Schema{}
|
ret := &spec.Schema{}
|
||||||
|
|
||||||
vv.ValueValidation.toKubeOpenAPI(ret)
|
vv.ValueValidation.toKubeOpenAPI(ret)
|
||||||
|
vv.ValidationExtensions.toKubeOpenAPI(ret)
|
||||||
if vv.Items != nil {
|
if vv.Items != nil {
|
||||||
ret.Items = &spec.SchemaOrArray{Schema: vv.Items.toKubeOpenAPI()}
|
ret.Items = &spec.SchemaOrArray{Schema: vv.Items.toKubeOpenAPI()}
|
||||||
}
|
}
|
||||||
@ -149,6 +157,5 @@ func (vv *NestedValueValidation) toKubeOpenAPI() *spec.Schema {
|
|||||||
}
|
}
|
||||||
vv.ForbiddenGenerics.toKubeOpenAPI(ret) // normally empty. Exception: int-or-string
|
vv.ForbiddenGenerics.toKubeOpenAPI(ret) // normally empty. Exception: int-or-string
|
||||||
vv.ForbiddenExtensions.toKubeOpenAPI(ret) // shouldn't do anything
|
vv.ForbiddenExtensions.toKubeOpenAPI(ret) // shouldn't do anything
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -202,18 +202,18 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
schema: &schema.Structural{
|
schema: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
|
Structural: &schema.Structural{
|
||||||
|
Generic: schema.Generic{
|
||||||
|
Type: "array",
|
||||||
|
},
|
||||||
|
Extensions: schema.Extensions{
|
||||||
|
XListType: strPtr("set"),
|
||||||
|
},
|
||||||
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "array",
|
Type: "string",
|
||||||
},
|
|
||||||
Extensions: schema.Extensions{
|
|
||||||
XListType: strPtr("set"),
|
|
||||||
},
|
|
||||||
Items: &schema.Structural{
|
|
||||||
Generic: schema.Generic{
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -387,11 +387,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -407,11 +407,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -427,12 +427,12 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
Nullable: true,
|
Type: "string",
|
||||||
},
|
Nullable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -485,11 +485,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -670,11 +670,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -691,11 +691,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -712,11 +712,11 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
},
|
Type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -733,12 +733,12 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
Nullable: true,
|
Type: "string",
|
||||||
},
|
Nullable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -856,12 +856,12 @@ func TestValidateListSetsAndMaps(t *testing.T) {
|
|||||||
Items: &schema.Structural{
|
Items: &schema.Structural{
|
||||||
Generic: schema.Generic{
|
Generic: schema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &schema.StructuralOrBool{
|
},
|
||||||
Structural: &schema.Structural{
|
AdditionalProperties: &schema.StructuralOrBool{
|
||||||
Generic: schema.Generic{
|
Structural: &schema.Structural{
|
||||||
Type: "string",
|
Generic: schema.Generic{
|
||||||
Nullable: true,
|
Type: "string",
|
||||||
},
|
Nullable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -171,11 +171,9 @@ func TestValidate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Structural: &structuralschema.Structural{
|
||||||
Structural: &structuralschema.Structural{
|
Extensions: structuralschema.Extensions{XEmbeddedResource: true},
|
||||||
Extensions: structuralschema.Extensions{XEmbeddedResource: true},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -146,12 +146,12 @@ func TestPrune(t *testing.T) {
|
|||||||
Extensions: structuralschema.Extensions{XPreserveUnknownFields: true},
|
Extensions: structuralschema.Extensions{XPreserveUnknownFields: true},
|
||||||
Generic: structuralschema.Generic{
|
Generic: structuralschema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
},
|
||||||
Structural: &structuralschema.Structural{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
Generic: structuralschema.Generic{Type: "object"},
|
Structural: &structuralschema.Structural{
|
||||||
Properties: map[string]structuralschema.Structural{
|
Generic: structuralschema.Generic{Type: "object"},
|
||||||
"specified": {Generic: structuralschema.Generic{Type: "object"}},
|
Properties: map[string]structuralschema.Structural{
|
||||||
},
|
"specified": {Generic: structuralschema.Generic{Type: "object"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -159,12 +159,12 @@ func TestPrune(t *testing.T) {
|
|||||||
"preservingAdditionalPropertiesKeyPruneValues": {
|
"preservingAdditionalPropertiesKeyPruneValues": {
|
||||||
Generic: structuralschema.Generic{
|
Generic: structuralschema.Generic{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
},
|
||||||
Structural: &structuralschema.Structural{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
Generic: structuralschema.Generic{Type: "object"},
|
Structural: &structuralschema.Structural{
|
||||||
Properties: map[string]structuralschema.Structural{
|
Generic: structuralschema.Generic{Type: "object"},
|
||||||
"specified": {Generic: structuralschema.Generic{Type: "object"}},
|
Properties: map[string]structuralschema.Structural{
|
||||||
},
|
"specified": {Generic: structuralschema.Generic{Type: "object"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -203,12 +203,10 @@ func TestPrune(t *testing.T) {
|
|||||||
Properties: map[string]structuralschema.Structural{
|
Properties: map[string]structuralschema.Structural{
|
||||||
"a": {},
|
"a": {},
|
||||||
"c": {
|
"c": {
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Structural: &structuralschema.Structural{
|
||||||
Structural: &structuralschema.Structural{
|
Generic: structuralschema.Generic{
|
||||||
Generic: structuralschema.Generic{
|
Type: "integer",
|
||||||
Type: "integer",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -220,10 +218,8 @@ func TestPrune(t *testing.T) {
|
|||||||
Properties: map[string]structuralschema.Structural{
|
Properties: map[string]structuralschema.Structural{
|
||||||
"a": {},
|
"a": {},
|
||||||
"c": {
|
"c": {
|
||||||
Generic: structuralschema.Generic{
|
AdditionalProperties: &structuralschema.StructuralOrBool{
|
||||||
AdditionalProperties: &structuralschema.StructuralOrBool{
|
Bool: false,
|
||||||
Bool: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,11 +25,13 @@ import (
|
|||||||
|
|
||||||
// Structural represents a structural schema.
|
// Structural represents a structural schema.
|
||||||
type Structural struct {
|
type Structural struct {
|
||||||
Items *Structural
|
Items *Structural
|
||||||
Properties map[string]Structural
|
Properties map[string]Structural
|
||||||
|
AdditionalProperties *StructuralOrBool
|
||||||
|
|
||||||
Generic
|
Generic
|
||||||
Extensions
|
Extensions
|
||||||
|
ValidationExtensions
|
||||||
|
|
||||||
ValueValidation *ValueValidation
|
ValueValidation *ValueValidation
|
||||||
}
|
}
|
||||||
@ -51,11 +53,10 @@ type Generic struct {
|
|||||||
// It can be object, array, number, integer, boolean, string.
|
// It can be object, array, number, integer, boolean, string.
|
||||||
// It is optional only if x-kubernetes-preserve-unknown-fields
|
// It is optional only if x-kubernetes-preserve-unknown-fields
|
||||||
// or x-kubernetes-int-or-string is true.
|
// or x-kubernetes-int-or-string is true.
|
||||||
Type string
|
Type string
|
||||||
Title string
|
Title string
|
||||||
Default JSON
|
Default JSON
|
||||||
AdditionalProperties *StructuralOrBool
|
Nullable bool
|
||||||
Nullable bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
@ -128,7 +129,13 @@ type Extensions struct {
|
|||||||
// Atomic maps will be entirely replaced when updated.
|
// Atomic maps will be entirely replaced when updated.
|
||||||
// +optional
|
// +optional
|
||||||
XMapType *string
|
XMapType *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// ValidationExtensions contains the Kubernetes OpenAPI v3 extensions that are
|
||||||
|
// used for validation rather than structure.
|
||||||
|
type ValidationExtensions struct {
|
||||||
// x-kubernetes-validations describes a list of validation rules for expression validation.
|
// x-kubernetes-validations describes a list of validation rules for expression validation.
|
||||||
// Use the v1 struct since this gets serialized as an extension.
|
// Use the v1 struct since this gets serialized as an extension.
|
||||||
XValidations apiextensionsv1.ValidationRules
|
XValidations apiextensionsv1.ValidationRules
|
||||||
@ -166,9 +173,11 @@ type ValueValidation struct {
|
|||||||
// under a logical junctor, and catch all structs for generic and vendor extensions schema fields.
|
// under a logical junctor, and catch all structs for generic and vendor extensions schema fields.
|
||||||
type NestedValueValidation struct {
|
type NestedValueValidation struct {
|
||||||
ValueValidation
|
ValueValidation
|
||||||
|
ValidationExtensions
|
||||||
|
|
||||||
Items *NestedValueValidation
|
Items *NestedValueValidation
|
||||||
Properties map[string]NestedValueValidation
|
Properties map[string]NestedValueValidation
|
||||||
|
AdditionalProperties *NestedValueValidation
|
||||||
|
|
||||||
// Anything set in the following will make the scheme
|
// Anything set in the following will make the scheme
|
||||||
// non-structural, with the exception of these two patterns if
|
// non-structural, with the exception of these two patterns if
|
||||||
|
@ -91,6 +91,16 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path)
|
|||||||
for k, v := range s.Properties {
|
for k, v := range s.Properties {
|
||||||
allErrs = append(allErrs, validateStructuralInvariants(&v, fieldLevel, fldPath.Child("properties").Key(k))...)
|
allErrs = append(allErrs, validateStructuralInvariants(&v, fieldLevel, fldPath.Child("properties").Key(k))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.AdditionalProperties != nil {
|
||||||
|
if lvl == rootLevel {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "must not be used at the root"))
|
||||||
|
}
|
||||||
|
if s.AdditionalProperties.Structural != nil {
|
||||||
|
allErrs = append(allErrs, validateStructuralInvariants(s.AdditionalProperties.Structural, fieldLevel, fldPath.Child("additionalProperties"))...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allErrs = append(allErrs, validateGeneric(&s.Generic, lvl, fldPath)...)
|
allErrs = append(allErrs, validateGeneric(&s.Generic, lvl, fldPath)...)
|
||||||
allErrs = append(allErrs, validateExtensions(&s.Extensions, fldPath)...)
|
allErrs = append(allErrs, validateExtensions(&s.Extensions, fldPath)...)
|
||||||
|
|
||||||
@ -207,18 +217,7 @@ func validateGeneric(g *Generic, lvl level, fldPath *field.Path) field.ErrorList
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
allErrs := field.ErrorList{}
|
return nil
|
||||||
|
|
||||||
if g.AdditionalProperties != nil {
|
|
||||||
if lvl == rootLevel {
|
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "must not be used at the root"))
|
|
||||||
}
|
|
||||||
if g.AdditionalProperties.Structural != nil {
|
|
||||||
allErrs = append(allErrs, validateStructuralInvariants(g.AdditionalProperties.Structural, fieldLevel, fldPath.Child("additionalProperties"))...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allErrs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateExtensions checks Kubernetes vendor extensions of a structural schema.
|
// validateExtensions checks Kubernetes vendor extensions of a structural schema.
|
||||||
@ -282,6 +281,7 @@ func validateNestedValueValidation(v *NestedValueValidation, skipAnyOf, skipAllO
|
|||||||
|
|
||||||
allErrs = append(allErrs, validateValueValidation(&v.ValueValidation, skipAnyOf, skipAllOfAnyOf, lvl, fldPath)...)
|
allErrs = append(allErrs, validateValueValidation(&v.ValueValidation, skipAnyOf, skipAllOfAnyOf, lvl, fldPath)...)
|
||||||
allErrs = append(allErrs, validateNestedValueValidation(v.Items, false, false, lvl, fldPath.Child("items"))...)
|
allErrs = append(allErrs, validateNestedValueValidation(v.Items, false, false, lvl, fldPath.Child("items"))...)
|
||||||
|
allErrs = append(allErrs, validateNestedValueValidation(v.AdditionalProperties, false, false, lvl, fldPath.Child("additionalProperties"))...)
|
||||||
|
|
||||||
for k, fld := range v.Properties {
|
for k, fld := range v.Properties {
|
||||||
allErrs = append(allErrs, validateNestedValueValidation(&fld, false, false, fieldLevel, fldPath.Child("properties").Key(k))...)
|
allErrs = append(allErrs, validateNestedValueValidation(&fld, false, false, fieldLevel, fldPath.Child("properties").Key(k))...)
|
||||||
@ -290,9 +290,6 @@ func validateNestedValueValidation(v *NestedValueValidation, skipAnyOf, skipAllO
|
|||||||
if len(v.ForbiddenGenerics.Type) > 0 {
|
if len(v.ForbiddenGenerics.Type) > 0 {
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("type"), "must be empty to be structural"))
|
allErrs = append(allErrs, field.Forbidden(fldPath.Child("type"), "must be empty to be structural"))
|
||||||
}
|
}
|
||||||
if v.ForbiddenGenerics.AdditionalProperties != nil {
|
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "must be undefined to be structural"))
|
|
||||||
}
|
|
||||||
if v.ForbiddenGenerics.Default.Object != nil {
|
if v.ForbiddenGenerics.Default.Object != nil {
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("default"), "must be undefined to be structural"))
|
allErrs = append(allErrs, field.Forbidden(fldPath.Child("default"), "must be undefined to be structural"))
|
||||||
}
|
}
|
||||||
@ -324,9 +321,6 @@ func validateNestedValueValidation(v *NestedValueValidation, skipAnyOf, skipAllO
|
|||||||
if v.ForbiddenExtensions.XMapType != nil {
|
if v.ForbiddenExtensions.XMapType != nil {
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("x-kubernetes-map-type"), "must be undefined to be structural"))
|
allErrs = append(allErrs, field.Forbidden(fldPath.Child("x-kubernetes-map-type"), "must be undefined to be structural"))
|
||||||
}
|
}
|
||||||
if len(v.ForbiddenExtensions.XValidations) > 0 {
|
|
||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("x-kubernetes-validations"), "must be empty to be structural"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// forbid reasoning about metadata because it can lead to metadata restriction we don't want
|
// forbid reasoning about metadata because it can lead to metadata restriction we don't want
|
||||||
if _, found := v.Properties["metadata"]; found {
|
if _, found := v.Properties["metadata"]; found {
|
||||||
|
@ -50,8 +50,8 @@ func (m *Visitor) visitStructural(s *Structural) bool {
|
|||||||
s.Properties[k] = v
|
s.Properties[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Generic.AdditionalProperties != nil && s.Generic.AdditionalProperties.Structural != nil {
|
if s.AdditionalProperties != nil && s.AdditionalProperties.Structural != nil {
|
||||||
m.visitStructural(s.Generic.AdditionalProperties.Structural)
|
m.visitStructural(s.AdditionalProperties.Structural)
|
||||||
}
|
}
|
||||||
if s.ValueValidation != nil {
|
if s.ValueValidation != nil {
|
||||||
for i := range s.ValueValidation.AllOf {
|
for i := range s.ValueValidation.AllOf {
|
||||||
@ -86,8 +86,8 @@ func (m *Visitor) visitNestedValueValidation(vv *NestedValueValidation) bool {
|
|||||||
vv.Properties[k] = v
|
vv.Properties[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vv.ForbiddenGenerics.AdditionalProperties != nil && vv.ForbiddenGenerics.AdditionalProperties.Structural != nil {
|
if vv.AdditionalProperties != nil {
|
||||||
m.visitStructural(vv.ForbiddenGenerics.AdditionalProperties.Structural)
|
m.visitNestedValueValidation(vv.AdditionalProperties)
|
||||||
}
|
}
|
||||||
for i := range vv.ValueValidation.AllOf {
|
for i := range vv.ValueValidation.AllOf {
|
||||||
m.visitNestedValueValidation(&vv.ValueValidation.AllOf[i])
|
m.visitNestedValueValidation(&vv.ValueValidation.AllOf[i])
|
||||||
|
Loading…
Reference in New Issue
Block a user