1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package apiextensions 18 19 // FieldValueErrorReason is a machine-readable value providing more detail about why a field failed the validation. 20 // +enum 21 type FieldValueErrorReason string 22 23 const ( 24 // FieldValueRequired is used to report required values that are not 25 // provided (e.g. empty strings, null values, or empty arrays). 26 FieldValueRequired FieldValueErrorReason = "FieldValueRequired" 27 // FieldValueDuplicate is used to report collisions of values that must be 28 // unique (e.g. unique IDs). 29 FieldValueDuplicate FieldValueErrorReason = "FieldValueDuplicate" 30 // FieldValueInvalid is used to report malformed values (e.g. failed regex 31 // match, too long, out of bounds). 32 FieldValueInvalid FieldValueErrorReason = "FieldValueInvalid" 33 // FieldValueForbidden is used to report valid (as per formatting rules) 34 // values which would be accepted under some conditions, but which are not 35 // permitted by the current conditions (such as security policy). 36 FieldValueForbidden FieldValueErrorReason = "FieldValueForbidden" 37 ) 38 39 // JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/). 40 type JSONSchemaProps struct { 41 ID string 42 Schema JSONSchemaURL 43 Ref *string 44 Description string 45 Type string 46 Nullable bool 47 Format string 48 Title string 49 Default *JSON 50 Maximum *float64 51 ExclusiveMaximum bool 52 Minimum *float64 53 ExclusiveMinimum bool 54 MaxLength *int64 55 MinLength *int64 56 Pattern string 57 MaxItems *int64 58 MinItems *int64 59 UniqueItems bool 60 MultipleOf *float64 61 Enum []JSON 62 MaxProperties *int64 63 MinProperties *int64 64 Required []string 65 Items *JSONSchemaPropsOrArray 66 AllOf []JSONSchemaProps 67 OneOf []JSONSchemaProps 68 AnyOf []JSONSchemaProps 69 Not *JSONSchemaProps 70 Properties map[string]JSONSchemaProps 71 AdditionalProperties *JSONSchemaPropsOrBool 72 PatternProperties map[string]JSONSchemaProps 73 Dependencies JSONSchemaDependencies 74 AdditionalItems *JSONSchemaPropsOrBool 75 Definitions JSONSchemaDefinitions 76 ExternalDocs *ExternalDocumentation 77 Example *JSON 78 79 // x-kubernetes-preserve-unknown-fields stops the API server 80 // decoding step from pruning fields which are not specified 81 // in the validation schema. This affects fields recursively, 82 // but switches back to normal pruning behaviour if nested 83 // properties or additionalProperties are specified in the schema. 84 // This can either be true or undefined. False is forbidden. 85 XPreserveUnknownFields *bool 86 87 // x-kubernetes-embedded-resource defines that the value is an 88 // embedded Kubernetes runtime.Object, with TypeMeta and 89 // ObjectMeta. The type must be object. It is allowed to further 90 // restrict the embedded object. Both ObjectMeta and TypeMeta 91 // are validated automatically. x-kubernetes-preserve-unknown-fields 92 // must be true. 93 XEmbeddedResource bool 94 95 // x-kubernetes-int-or-string specifies that this value is 96 // either an integer or a string. If this is true, an empty 97 // type is allowed and type as child of anyOf is permitted 98 // if following one of the following patterns: 99 // 100 // 1) anyOf: 101 // - type: integer 102 // - type: string 103 // 2) allOf: 104 // - anyOf: 105 // - type: integer 106 // - type: string 107 // - ... zero or more 108 XIntOrString bool 109 110 // x-kubernetes-list-map-keys annotates an array with the x-kubernetes-list-type `map` by specifying the keys used 111 // as the index of the map. 112 // 113 // This tag MUST only be used on lists that have the "x-kubernetes-list-type" 114 // extension set to "map". Also, the values specified for this attribute must 115 // be a scalar typed field of the child structure (no nesting is supported). 116 XListMapKeys []string 117 118 // x-kubernetes-list-type annotates an array to further describe its topology. 119 // This extension must only be used on lists and may have 3 possible values: 120 // 121 // 1) `atomic`: the list is treated as a single entity, like a scalar. 122 // Atomic lists will be entirely replaced when updated. This extension 123 // may be used on any type of list (struct, scalar, ...). 124 // 2) `set`: 125 // Sets are lists that must not have multiple items with the same value. Each 126 // value must be a scalar, an object with x-kubernetes-map-type `atomic` or an 127 // array with x-kubernetes-list-type `atomic`. 128 // 3) `map`: 129 // These lists are like maps in that their elements have a non-index key 130 // used to identify them. Order is preserved upon merge. The map tag 131 // must only be used on a list with elements of type object. 132 XListType *string 133 134 // x-kubernetes-map-type annotates an object to further describe its topology. 135 // This extension must only be used when type is object and may have 2 possible values: 136 // 137 // 1) `granular`: 138 // These maps are actual maps (key-value pairs) and each fields are independent 139 // from each other (they can each be manipulated by separate actors). This is 140 // the default behaviour for all maps. 141 // 2) `atomic`: the list is treated as a single entity, like a scalar. 142 // Atomic maps will be entirely replaced when updated. 143 // +optional 144 XMapType *string 145 146 // x-kubernetes-validations -kubernetes-validations describes a list of validation rules written in the CEL expression language. 147 // This field is an alpha-level. Using this field requires the feature gate `CustomResourceValidationExpressions` to be enabled. 148 // +patchMergeKey=rule 149 // +patchStrategy=merge 150 // +listType=map 151 // +listMapKey=rule 152 XValidations ValidationRules 153 } 154 155 // ValidationRules describes a list of validation rules written in the CEL expression language. 156 type ValidationRules []ValidationRule 157 158 // ValidationRule describes a validation rule written in the CEL expression language. 159 type ValidationRule struct { 160 // Rule represents the expression which will be evaluated by CEL. 161 // ref: https://github.com/google/cel-spec 162 // The Rule is scoped to the location of the x-kubernetes-validations extension in the schema. 163 // The `self` variable in the CEL expression is bound to the scoped value. 164 // Example: 165 // - Rule scoped to the root of a resource with a status subresource: {"rule": "self.status.actual <= self.spec.maxDesired"} 166 // 167 // If the Rule is scoped to an object with properties, the accessible properties of the object are field selectable 168 // via `self.field` and field presence can be checked via `has(self.field)`. Null valued fields are treated as 169 // absent fields in CEL expressions. 170 // If the Rule is scoped to an object with additionalProperties (i.e. a map) the value of the map 171 // are accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the map 172 // are accessible via CEL macros and functions such as `self.all(...)`. 173 // If the Rule is scoped to an array, the elements of the array are accessible via `self[i]` and also by macros and 174 // functions. 175 // If the Rule is scoped to a scalar, `self` is bound to the scalar value. 176 // Examples: 177 // - Rule scoped to a map of objects: {"rule": "self.components['Widget'].priority < 10"} 178 // - Rule scoped to a list of integers: {"rule": "self.values.all(value, value >= 0 && value < 100)"} 179 // - Rule scoped to a string value: {"rule": "self.startsWith('kube')"} 180 // 181 // The `apiVersion`, `kind`, `metadata.name` and `metadata.generateName` are always accessible from the root of the 182 // object and from any x-kubernetes-embedded-resource annotated objects. No other metadata properties are accessible. 183 // 184 // Unknown data preserved in custom resources via x-kubernetes-preserve-unknown-fields is not accessible in CEL 185 // expressions. This includes: 186 // - Unknown field values that are preserved by object schemas with x-kubernetes-preserve-unknown-fields. 187 // - Object properties where the property schema is of an "unknown type". An "unknown type" is recursively defined as: 188 // - A schema with no type and x-kubernetes-preserve-unknown-fields set to true 189 // - An array where the items schema is of an "unknown type" 190 // - An object where the additionalProperties schema is of an "unknown type" 191 // 192 // Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible. 193 // Accessible property names are escaped according to the following rules when accessed in the expression: 194 // - '__' escapes to '__underscores__' 195 // - '.' escapes to '__dot__' 196 // - '-' escapes to '__dash__' 197 // - '/' escapes to '__slash__' 198 // - Property names that exactly match a CEL RESERVED keyword escape to '__{keyword}__'. The keywords are: 199 // "true", "false", "null", "in", "as", "break", "const", "continue", "else", "for", "function", "if", 200 // "import", "let", "loop", "package", "namespace", "return". 201 // Examples: 202 // - Rule accessing a property named "namespace": {"rule": "self.__namespace__ > 0"} 203 // - Rule accessing a property named "x-prop": {"rule": "self.x__dash__prop > 0"} 204 // - Rule accessing a property named "redact__d": {"rule": "self.redact__underscores__d > 0"} 205 // 206 // Equality on arrays with x-kubernetes-list-type of 'set' or 'map' ignores element order, i.e. [1, 2] == [2, 1]. 207 // Concatenation on arrays with x-kubernetes-list-type use the semantics of the list type: 208 // - 'set': `X + Y` performs a union where the array positions of all elements in `X` are preserved and 209 // non-intersecting elements in `Y` are appended, retaining their partial order. 210 // - 'map': `X + Y` performs a merge where the array positions of all keys in `X` are preserved but the values 211 // are overwritten by values in `Y` when the key sets of `X` and `Y` intersect. Elements in `Y` with 212 // non-intersecting keys are appended, retaining their partial order. 213 // 214 // If `rule` makes use of the `oldSelf` variable it is implicitly a 215 // `transition rule`. 216 // 217 // By default, the `oldSelf` variable is the same type as `self`. 218 // When `optionalOldSelf` is true, the `oldSelf` variable is a CEL optional 219 // variable whose value() is the same type as `self`. 220 // See the documentation for the `optionalOldSelf` field for details. 221 // 222 // Transition rules by default are applied only on UPDATE requests and are 223 // skipped if an old value could not be found. You can opt a transition 224 // rule into unconditional evaluation by setting `optionalOldSelf` to true. 225 // 226 Rule string 227 // Message represents the message displayed when validation fails. The message is required if the Rule contains 228 // line breaks. The message must not contain line breaks. 229 // If unset, the message is "failed rule: {Rule}". 230 // e.g. "must be a URL with the host matching spec.host" 231 Message string 232 // MessageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. 233 // Since messageExpression is used as a failure message, it must evaluate to a string. 234 // If both message and messageExpression are present on a rule, then messageExpression will be used if validation 235 // fails. If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced 236 // as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string 237 // that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and 238 // the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. 239 // messageExpression has access to all the same variables as the rule; the only difference is the return type. 240 // Example: 241 // "x must be less than max ("+string(self.max)+")" 242 // +optional 243 MessageExpression string 244 // reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule. 245 // The HTTP status code returned to the caller will match the reason of the reason of the first failed validation rule. 246 // The currently supported reasons are: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate". 247 // If not set, default to use "FieldValueInvalid". 248 // All future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid. 249 // +optional 250 Reason *FieldValueErrorReason 251 // fieldPath represents the field path returned when the validation fails. 252 // 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. 253 // e.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo` 254 // If the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList` 255 // It does not support list numeric index. 256 // 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. 257 // Numeric index of array is not supported. 258 // For field name which contains special characters, use `['specialName']` to refer the field name. 259 // e.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']` 260 // +optional 261 FieldPath string 262 263 // optionalOldSelf is used to opt a transition rule into evaluation 264 // even when the object is first created, or if the old object is 265 // missing the value. 266 // 267 // When enabled `oldSelf` will be a CEL optional whose value will be 268 // `None` if there is no old value, or when the object is initially created. 269 // 270 // You may check for presence of oldSelf using `oldSelf.hasValue()` and 271 // unwrap it after checking using `oldSelf.value()`. Check the CEL 272 // documentation for Optional types for more information: 273 // https://pkg.go.dev/github.com/google/cel-go/cel#OptionalTypes 274 // 275 // May not be set unless `oldSelf` is used in `rule`. 276 // 277 // +featureGate=CRDValidationRatcheting 278 // +optional 279 OptionalOldSelf *bool 280 } 281 282 // JSON represents any valid JSON value. 283 // These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil. 284 type JSON interface{} 285 286 // JSONSchemaURL represents a schema url. 287 type JSONSchemaURL string 288 289 // JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps 290 // or an array of JSONSchemaProps. Mainly here for serialization purposes. 291 type JSONSchemaPropsOrArray struct { 292 Schema *JSONSchemaProps 293 JSONSchemas []JSONSchemaProps 294 } 295 296 // JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value. 297 // Defaults to true for the boolean property. 298 type JSONSchemaPropsOrBool struct { 299 Allows bool 300 Schema *JSONSchemaProps 301 } 302 303 // JSONSchemaDependencies represent a dependencies property. 304 type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray 305 306 // JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array. 307 type JSONSchemaPropsOrStringArray struct { 308 Schema *JSONSchemaProps 309 Property []string 310 } 311 312 // JSONSchemaDefinitions contains the models explicitly defined in this spec. 313 type JSONSchemaDefinitions map[string]JSONSchemaProps 314 315 // ExternalDocumentation allows referencing an external resource for extended documentation. 316 type ExternalDocumentation struct { 317 Description string 318 URL string 319 } 320