diff --git a/api/v1beta1/clusterclass_types.go b/api/v1beta1/clusterclass_types.go index 14322c4a4eee..4313f7ea736b 100644 --- a/api/v1beta1/clusterclass_types.go +++ b/api/v1beta1/clusterclass_types.go @@ -549,12 +549,12 @@ type JSONSchemaProps struct { // XValidations describes a list of validation rules written in the CEL expression language. // See: https://github.com/kubernetes/apiextensions-apiserver/blob/v0.28.5/pkg/apis/apiextensions/v1/types_jsonschema.go#L191. // +optional - // +listType=map - // +listMapKey=rule XValidations ValidationRules `json:"x-kubernetes-validations,omitempty"` } // ValidationRules describes a list of validation rules written in the CEL expression language. +// +listType=map +// +listMapKey=rule type ValidationRules []ValidationRule // ValidationRule describes a validation rule written in the CEL expression language. diff --git a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml index e463e06b06f3..0609a5055b96 100644 --- a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml +++ b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml @@ -1148,26 +1148,21 @@ spec: except if nested properties or additionalProperties are specified in the schema. type: boolean x-kubernetes-validations: - description: XValidations describes a list of validation - rules written in the CEL expression language. + description: |- + XValidations describes a list of validation rules written in the CEL expression language. + See: https://github.com/kubernetes/apiextensions-apiserver/blob/v0.28.5/pkg/apis/apiextensions/v1/types_jsonschema.go#L191. items: description: ValidationRule describes a validation rule written in the CEL expression language. properties: FieldValueRequired: default: FieldValueInvalid - description: 'Reason provides a machine-readable - validation failure reason that is returned to - the caller when a request fails this validation - rule. The HTTP status code returned to the caller - will match the reason of the reason of the first - failed validation rule. The currently supported - reasons are: "FieldValueInvalid", "FieldValueForbidden", - "FieldValueRequired", "FieldValueDuplicate". + description: |- + Reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule. + The HTTP status code returned to the caller will match the reason of the reason of the first failed validation rule. + The currently supported reasons are: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate". If not set, default to use "FieldValueInvalid". - All future added reasons must be accepted by - clients when reading this value and unknown - reasons should be treated as FieldValueInvalid.' + All future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid. enum: - FieldValueInvalid - FieldValueForbidden @@ -1175,133 +1170,116 @@ spec: - FieldValueDuplicate type: string fieldPath: - description: 'FieldPath represents the field path - returned when the validation fails. It must - be a relative JSON path (i.e. with array notation) - scoped to the location of this x-kubernetes-validations - extension in the schema and refer to an existing - field. e.g. when validation checks if a specific - attribute `foo` under a map `testMap`, the fieldPath - could be set to `.testMap.foo` If the validation - checks two lists must have unique attributes, - the fieldPath could be set to either of the - list: e.g. `.testList` It does not support list - numeric index. It supports child operation to - refer to an existing field currently. Refer - to [JSONPath support in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) - for more info. Numeric index of array is not - supported. For field name which contains special - characters, use `[''specialName'']` to refer - the field name. e.g. for attribute `foo.34$` - appears in a list `testList`, the fieldPath - could be set to `.testList[''foo.34$'']`' + description: |- + FieldPath represents the field path returned when the validation fails. + It must be a relative JSON path (i.e. with array notation) scoped to the location of this x-kubernetes-validations extension in the schema and refer to an existing field. + e.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo` + If the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList` + It does not support list numeric index. + It supports child operation to refer to an existing field currently. Refer to [JSONPath support in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) for more info. + Numeric index of array is not supported. + For field name which contains special characters, use `['specialName']` to refer the field name. + e.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']` type: string message: - description: 'Message represents the message displayed - when validation fails. The message is required - if the Rule contains line breaks. The message - must not contain line breaks. If unset, the - message is "failed rule: {Rule}". e.g. "must - be a URL with the host matching spec.host"' + description: |- + Message represents the message displayed when validation fails. The message is required if the Rule contains + line breaks. The message must not contain line breaks. + If unset, the message is "failed rule: {Rule}". + e.g. "must be a URL with the host matching spec.host" type: string messageExpression: - description: 'MessageExpression declares a CEL - expression that evaluates to the validation - failure message that is returned when this rule - fails. Since messageExpression is used as a - failure message, it must evaluate to a string. - If both message and messageExpression are present - on a rule, then messageExpression will be used - if validation fails. If messageExpression results - in a runtime error, the runtime error is logged, - and the validation failure message is produced - as if the messageExpression field were unset. - If messageExpression evaluates to an empty string, - a string with only spaces, or a string that - contains line breaks, then the validation failure - message will also be produced as if the messageExpression - field were unset, and the fact that messageExpression - produced an empty string/string with only spaces/string - with line breaks will be logged. messageExpression - has access to all the same variables as the - rule; the only difference is the return type. - Example: "x must be less than max ("+string(self.max)+")"' + description: |- + MessageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. + Since messageExpression is used as a failure message, it must evaluate to a string. + If both message and messageExpression are present on a rule, then messageExpression will be used if validation + fails. If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced + as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string + that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and + the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. + messageExpression has access to all the same variables as the rule; the only difference is the return type. + Example: + "x must be less than max ("+string(self.max)+")" type: string rule: description: "Rule represents the expression which - will be evaluated by CEL. ref: https://github.com/google/cel-spec - The Rule is scoped to the location of the x-kubernetes-validations - extension in the schema. The `self` variable + will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nThe + Rule is scoped to the location of the x-kubernetes-validations + extension in the schema.\nThe `self` variable in the CEL expression is bound to the scoped - value. If the Rule is scoped to an object with + value.\nIf the Rule is scoped to an object with properties, the accessible properties of the - object are field selectable via `self.field` + object are field selectable\nvia `self.field` and field presence can be checked via `has(self.field)`. - Null valued fields are treated as absent fields - in CEL expressions. If the Rule is scoped to + Null valued fields are treated as\nabsent fields + in CEL expressions.\nIf the Rule is scoped to an object with additionalProperties (i.e. a - map) the value of the map are accessible via + map) the value of the map\nare accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the - map are accessible via CEL macros and functions - such as `self.all(...)`. If the Rule is scoped + map\nare accessible via CEL macros and functions + such as `self.all(...)`.\nIf the Rule is scoped to an array, the elements of the array are accessible - via `self[i]` and also by macros and functions. - If the Rule is scoped to a scalar, `self` is - bound to the scalar value. Examples: - Rule - scoped to a map of objects: {\"rule\": \"self.components['Widget'].priority - < 10\"} - Rule scoped to a list of integers: + via `self[i]` and also by macros and\nfunctions.\nIf + the Rule is scoped to a scalar, `self` is bound + to the scalar value.\nExamples:\n- Rule scoped + to a map of objects: {\"rule\": \"self.components['Widget'].priority + < 10\"}\n- Rule scoped to a list of integers: {\"rule\": \"self.values.all(value, value >= - 0 && value < 100)\"} - Rule scoped to a string - value: {\"rule\": \"self.startsWith('kube')\"} - \n Unknown data preserved in custom resources - via x-kubernetes-preserve-unknown-fields is - not accessible in CEL expressions. This includes: - - Unknown field values that are preserved by - object schemas with x-kubernetes-preserve-unknown-fields. - - Object properties where the property schema + 0 && value < 100)\"}\n- Rule scoped to a string + value: {\"rule\": \"self.startsWith('kube')\"}\n\n\nUnknown + data preserved in custom resources via x-kubernetes-preserve-unknown-fields + is not accessible in CEL\nexpressions. This + includes:\n- Unknown field values that are preserved + by object schemas with x-kubernetes-preserve-unknown-fields.\n- + Object properties where the property schema is of an \"unknown type\". An \"unknown type\" - is recursively defined as: - A schema with no - type and x-kubernetes-preserve-unknown-fields - set to true - An array where the items schema - is of an \"unknown type\" - An object where + is recursively defined as:\n - A schema with + no type and x-kubernetes-preserve-unknown-fields + set to true\n - An array where the items schema + is of an \"unknown type\"\n - An object where the additionalProperties schema is of an \"unknown - type\" \n Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible. Accessible property names are - escaped according to the following rules when - accessed in the expression: - '__' escapes to - '__underscores__' - '.' escapes to '__dot__' - - '-' escapes to '__dash__' - '/' escapes to - '__slash__' - Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are: \"true\", \"false\", \"null\", - \"in\", \"as\", \"break\", \"const\", \"continue\", - \"else\", \"for\", \"function\", \"if\", \"import\", - \"let\", \"loop\", \"package\", \"namespace\", - \"return\". Examples: - Rule accessing a property - named \"namespace\": {\"rule\": \"self.__namespace__ - > 0\"} - Rule accessing a property named \"x-prop\": - {\"rule\": \"self.x__dash__prop > 0\"} - Rule - accessing a property named \"redact__d\": {\"rule\": - \"self.redact__underscores__d > 0\"} \n Equality + type\"\n\n\nOnly property names of the form + `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.\nAccessible + property names are escaped according to the + following rules when accessed in the expression:\n- + '__' escapes to '__underscores__'\n- '.' escapes + to '__dot__'\n- '-' escapes to '__dash__'\n- + '/' escapes to '__slash__'\n- Property names + that exactly match a CEL RESERVED keyword escape + to '__{keyword}__'. The keywords are:\n\t \"true\", + \"false\", \"null\", \"in\", \"as\", \"break\", + \"const\", \"continue\", \"else\", \"for\", + \"function\", \"if\",\n\t \"import\", \"let\", + \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n + \ - Rule accessing a property named \"namespace\": + {\"rule\": \"self.__namespace__ > 0\"}\n - + Rule accessing a property named \"x-prop\": + {\"rule\": \"self.x__dash__prop > 0\"}\n - + Rule accessing a property named \"redact__d\": + {\"rule\": \"self.redact__underscores__d > 0\"}\n\n\nEquality on arrays with x-kubernetes-list-type of 'set' or 'map' ignores element order, i.e. [1, 2] - == [2, 1]. Concatenation on arrays with x-kubernetes-list-type - use the semantics of the list type: - 'set': + == [2, 1].\nConcatenation on arrays with x-kubernetes-list-type + use the semantics of the list type:\n - 'set': `X + Y` performs a union where the array positions - of all elements in `X` are preserved and non-intersecting + of all elements in `X` are preserved and\n non-intersecting elements in `Y` are appended, retaining their - partial order. - 'map': `X + Y` performs a merge - where the array positions of all keys in `X` - are preserved but the values are overwritten - by values in `Y` when the key sets of `X` and - `Y` intersect. Elements in `Y` with non-intersecting - keys are appended, retaining their partial order." + partial order.\n - 'map': `X + Y` performs + a merge where the array positions of all keys + in `X` are preserved but the values\n are + overwritten by values in `Y` when the key sets + of `X` and `Y` intersect. Elements in `Y` with\n + \ non-intersecting keys are appended, retaining + their partial order." type: string required: - rule type: object type: array + x-kubernetes-list-map-keys: + - rule + x-kubernetes-list-type: map required: - type type: object @@ -2158,28 +2136,21 @@ spec: except if nested properties or additionalProperties are specified in the schema. type: boolean x-kubernetes-validations: - description: XValidations describes a list of - validation rules written in the CEL expression - language. + description: |- + XValidations describes a list of validation rules written in the CEL expression language. + See: https://github.com/kubernetes/apiextensions-apiserver/blob/v0.28.5/pkg/apis/apiextensions/v1/types_jsonschema.go#L191. items: description: ValidationRule describes a validation rule written in the CEL expression language. properties: FieldValueRequired: default: FieldValueInvalid - description: 'Reason provides a machine-readable - validation failure reason that is returned - to the caller when a request fails this - validation rule. The HTTP status code - returned to the caller will match the - reason of the reason of the first failed - validation rule. The currently supported - reasons are: "FieldValueInvalid", "FieldValueForbidden", - "FieldValueRequired", "FieldValueDuplicate". + description: |- + Reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule. + The HTTP status code returned to the caller will match the reason of the reason of the first failed validation rule. + The currently supported reasons are: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate". If not set, default to use "FieldValueInvalid". - All future added reasons must be accepted - by clients when reading this value and - unknown reasons should be treated as FieldValueInvalid.' + All future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid. enum: - FieldValueInvalid - FieldValueForbidden @@ -2187,152 +2158,127 @@ spec: - FieldValueDuplicate type: string fieldPath: - description: 'FieldPath represents the field - path returned when the validation fails. - It must be a relative JSON path (i.e. - with array notation) scoped to the location - of this x-kubernetes-validations extension - in the schema and refer to an existing - field. e.g. when validation checks if - a specific attribute `foo` under a map - `testMap`, the fieldPath could be set - to `.testMap.foo` If the validation checks - two lists must have unique attributes, - the fieldPath could be set to either of - the list: e.g. `.testList` It does not - support list numeric index. It supports - child operation to refer to an existing - field currently. Refer to [JSONPath support - in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) - for more info. Numeric index of array - is not supported. For field name which - contains special characters, use `[''specialName'']` - to refer the field name. e.g. for attribute - `foo.34$` appears in a list `testList`, - the fieldPath could be set to `.testList[''foo.34$'']`' + description: |- + FieldPath represents the field path returned when the validation fails. + It must be a relative JSON path (i.e. with array notation) scoped to the location of this x-kubernetes-validations extension in the schema and refer to an existing field. + e.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo` + If the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList` + It does not support list numeric index. + It supports child operation to refer to an existing field currently. Refer to [JSONPath support in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) for more info. + Numeric index of array is not supported. + For field name which contains special characters, use `['specialName']` to refer the field name. + e.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']` type: string message: - description: 'Message represents the message - displayed when validation fails. The message - is required if the Rule contains line - breaks. The message must not contain line - breaks. If unset, the message is "failed - rule: {Rule}". e.g. "must be a URL with - the host matching spec.host"' + description: |- + Message represents the message displayed when validation fails. The message is required if the Rule contains + line breaks. The message must not contain line breaks. + If unset, the message is "failed rule: {Rule}". + e.g. "must be a URL with the host matching spec.host" type: string messageExpression: - description: 'MessageExpression declares - a CEL expression that evaluates to the - validation failure message that is returned - when this rule fails. Since messageExpression - is used as a failure message, it must - evaluate to a string. If both message - and messageExpression are present on a - rule, then messageExpression will be used - if validation fails. If messageExpression - results in a runtime error, the runtime - error is logged, and the validation failure - message is produced as if the messageExpression - field were unset. If messageExpression - evaluates to an empty string, a string - with only spaces, or a string that contains - line breaks, then the validation failure - message will also be produced as if the - messageExpression field were unset, and - the fact that messageExpression produced - an empty string/string with only spaces/string - with line breaks will be logged. messageExpression - has access to all the same variables as - the rule; the only difference is the return - type. Example: "x must be less than max - ("+string(self.max)+")"' + description: |- + MessageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. + Since messageExpression is used as a failure message, it must evaluate to a string. + If both message and messageExpression are present on a rule, then messageExpression will be used if validation + fails. If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced + as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string + that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and + the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. + messageExpression has access to all the same variables as the rule; the only difference is the return type. + Example: + "x must be less than max ("+string(self.max)+")" type: string rule: description: "Rule represents the expression - which will be evaluated by CEL. ref: https://github.com/google/cel-spec - The Rule is scoped to the location of - the x-kubernetes-validations extension - in the schema. The `self` variable in - the CEL expression is bound to the scoped - value. If the Rule is scoped to an object + which will be evaluated by CEL.\nref: + https://github.com/google/cel-spec\nThe + Rule is scoped to the location of the + x-kubernetes-validations extension in + the schema.\nThe `self` variable in the + CEL expression is bound to the scoped + value.\nIf the Rule is scoped to an object with properties, the accessible properties - of the object are field selectable via + of the object are field selectable\nvia `self.field` and field presence can be checked via `has(self.field)`. Null valued - fields are treated as absent fields in - CEL expressions. If the Rule is scoped + fields are treated as\nabsent fields in + CEL expressions.\nIf the Rule is scoped to an object with additionalProperties - (i.e. a map) the value of the map are + (i.e. a map) the value of the map\nare accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and - all entries of the map are accessible - via CEL macros and functions such as `self.all(...)`. - If the Rule is scoped to an array, the - elements of the array are accessible via - `self[i]` and also by macros and functions. - If the Rule is scoped to a scalar, `self` - is bound to the scalar value. Examples: - - Rule scoped to a map of objects: {\"rule\": + all entries of the map\nare accessible + via CEL macros and functions such as `self.all(...)`.\nIf + the Rule is scoped to an array, the elements + of the array are accessible via `self[i]` + and also by macros and\nfunctions.\nIf + the Rule is scoped to a scalar, `self` + is bound to the scalar value.\nExamples:\n- + Rule scoped to a map of objects: {\"rule\": \"self.components['Widget'].priority < - 10\"} - Rule scoped to a list of integers: + 10\"}\n- Rule scoped to a list of integers: {\"rule\": \"self.values.all(value, value - >= 0 && value < 100)\"} - Rule scoped - to a string value: {\"rule\": \"self.startsWith('kube')\"} - \n Unknown data preserved in custom resources - via x-kubernetes-preserve-unknown-fields - is not accessible in CEL expressions. - This includes: - Unknown field values - that are preserved by object schemas with - x-kubernetes-preserve-unknown-fields. - - Object properties where the property - schema is of an \"unknown type\". An \"unknown - type\" is recursively defined as: - A - schema with no type and x-kubernetes-preserve-unknown-fields - set to true - An array where the items - schema is of an \"unknown type\" - An - object where the additionalProperties - schema is of an \"unknown type\" \n Only + >= 0 && value < 100)\"}\n- Rule scoped + to a string value: {\"rule\": \"self.startsWith('kube')\"}\n\n\nUnknown + data preserved in custom resources via + x-kubernetes-preserve-unknown-fields is + not accessible in CEL\nexpressions. This + includes:\n- Unknown field values that + are preserved by object schemas with x-kubernetes-preserve-unknown-fields.\n- + Object properties where the property schema + is of an \"unknown type\". An \"unknown + type\" is recursively defined as:\n - + A schema with no type and x-kubernetes-preserve-unknown-fields + set to true\n - An array where the items + schema is of an \"unknown type\"\n - + An object where the additionalProperties + schema is of an \"unknown type\"\n\n\nOnly property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible. Accessible property names + are accessible.\nAccessible property names are escaped according to the following - rules when accessed in the expression: - - '__' escapes to '__underscores__' - - '.' escapes to '__dot__' - '-' escapes - to '__dash__' - '/' escapes to '__slash__' - - Property names that exactly match a - CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are: \"true\", \"false\", + rules when accessed in the expression:\n- + '__' escapes to '__underscores__'\n- '.' + escapes to '__dot__'\n- '-' escapes to + '__dash__'\n- '/' escapes to '__slash__'\n- + Property names that exactly match a CEL + RESERVED keyword escape to '__{keyword}__'. + The keywords are:\n\t \"true\", \"false\", \"null\", \"in\", \"as\", \"break\", \"const\", \"continue\", \"else\", \"for\", \"function\", - \"if\", \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\". - Examples: - Rule accessing a property - named \"namespace\": {\"rule\": \"self.__namespace__ - > 0\"} - Rule accessing a property named - \"x-prop\": {\"rule\": \"self.x__dash__prop - > 0\"} - Rule accessing a property named - \"redact__d\": {\"rule\": \"self.redact__underscores__d - > 0\"} \n Equality on arrays with x-kubernetes-list-type + \"if\",\n\t \"import\", \"let\", \"loop\", + \"package\", \"namespace\", \"return\".\nExamples:\n + \ - Rule accessing a property named \"namespace\": + {\"rule\": \"self.__namespace__ > 0\"}\n + \ - Rule accessing a property named \"x-prop\": + {\"rule\": \"self.x__dash__prop > 0\"}\n + \ - Rule accessing a property named \"redact__d\": + {\"rule\": \"self.redact__underscores__d + > 0\"}\n\n\nEquality on arrays with x-kubernetes-list-type of 'set' or 'map' ignores element order, - i.e. [1, 2] == [2, 1]. Concatenation on - arrays with x-kubernetes-list-type use - the semantics of the list type: - 'set': - `X + Y` performs a union where the array - positions of all elements in `X` are preserved - and non-intersecting elements in `Y` are - appended, retaining their partial order. - - 'map': `X + Y` performs a merge where - the array positions of all keys in `X` - are preserved but the values are overwritten - by values in `Y` when the key sets of - `X` and `Y` intersect. Elements in `Y` - with non-intersecting keys are appended, - retaining their partial order." + i.e. [1, 2] == [2, 1].\nConcatenation + on arrays with x-kubernetes-list-type + use the semantics of the list type:\n + \ - 'set': `X + Y` performs a union where + the array positions of all elements in + `X` are preserved and\n non-intersecting + elements in `Y` are appended, retaining + their partial order.\n - 'map': `X + + Y` performs a merge where the array positions + of all keys in `X` are preserved but the + values\n are overwritten by values + in `Y` when the key sets of `X` and `Y` + intersect. Elements in `Y` with\n non-intersecting + keys are appended, retaining their partial + order." type: string required: - rule type: object type: array + x-kubernetes-list-map-keys: + - rule + x-kubernetes-list-type: map required: - type type: object diff --git a/internal/topology/variables/cluster_variable_validation.go b/internal/topology/variables/cluster_variable_validation.go index 1e287d7319d2..c30afa18cc42 100644 --- a/internal/topology/variables/cluster_variable_validation.go +++ b/internal/topology/variables/cluster_variable_validation.go @@ -66,7 +66,8 @@ func validateClusterVariables(values, oldValues []clusterv1.ClusterVariable, def // Get a map of old ClusterVariable values, assume they are all valid and not duplicate names, etc. oldValuesMap := make(map[string]*clusterv1.ClusterVariable, len(oldValues)) - for _, v := range oldValues { + for idx := range oldValues { + v := oldValues[idx] oldValuesMap[v.Name] = &v } @@ -188,7 +189,7 @@ func ValidateClusterVariable(value, oldValue *clusterv1.ClusterVariable, definit fmt.Errorf("failed to create structural schema for variable %q; ClusterClass should be checked: %v", value.Name, err))} // TODO: consider if to add ClusterClass name } - if err := validateUnknownFields(fldPath, definition.Name, wrappedVariable, variableValue, ss); err != nil { + if err := validateUnknownFields(fldPath, definition.Name, wrappedVariable, ss); err != nil { return err } @@ -221,7 +222,7 @@ func ValidateClusterVariable(value, oldValue *clusterv1.ClusterVariable, definit // validateUnknownFields validates the given variableValue for unknown fields. // This func returns an error if there are variable fields in variableValue that are not defined in // variableSchema and if x-kubernetes-preserve-unknown-fields is not set. -func validateUnknownFields(fldPath *field.Path, variableName string, wrappedVariable map[string]interface{}, variableValue interface{}, ss *structuralschema.Structural) field.ErrorList { +func validateUnknownFields(fldPath *field.Path, variableName string, wrappedVariable map[string]interface{}, ss *structuralschema.Structural) field.ErrorList { // Run Prune to check if it would drop any unknown fields. opts := structuralschema.UnknownFieldPathOptions{ // TrackUnknownFieldPaths has to be true so PruneWithOptions returns the unknown fields.