diff --git a/GUIDELINES.md b/GUIDELINES.md index 30d5487fbe3..f316b5f4437 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -19,6 +19,7 @@ followed for Istio APIs. - [Proto Guidelines](#proto-guidelines) - [Style](#style) - [Basic Proto Versioning](#basic-proto-ersioning) +- [Validation Guidelines](#validation-guidelines) - [CRD Guidelines](#crd-guidelines) - [Style](#crd-style) - [Basic CRD Versioning](#basic-crd-versioning) @@ -214,6 +215,75 @@ protos. - Loosening validation is permitted. As a result, it is recommended to err on the side of stricter validation. +## Validation Guidelines + +All types should have as strict validation specified on it as possible to rule out invalid states. +These are ultimately compiled to Kubernetes CustomResourceDefinitions, which use OpenAPI validation with some Kubernetes extras. +This is handled by our own custom [protoc-gen-crd](https://github.com/istio/tools/tree/master/cmd/protoc-gen-crd) which compiles our +protobuf definitions down to CRDs. + +There are a few types of validations: +* Automatic ones, based on the protobuf type. For example, a UInt32Value automatically has a validation to check the number between `0` and `MaxUint32` +* Protobuf `field_behavior`. Currently only `[(google.api.field_behavior) = REQUIRED]` is implemented. +* Comment driven validations (see below). + +Most validation is driven by comments on fields and messages. +All validations in [KubeBuilder](https://book.kubebuilder.io/reference/markers/crd-validation) are supported, as well as some extras: + +* `+protoc-gen-crd:map-value-validation`: apply the validation to each *value* in a map. + Note it's not possible to apply validations to each key. You can, however, validate the entire map together with a CEL rule. +* `+protoc-gen-crd:list-value-validation`: apply the validation to each value in a list. +* `+protoc-gen-crd:duration-validation:none`: exclude the default requirement that a duration field is non-zero. +* `+protoc-gen-crd:validation:XIntOrString`: marks a field as accepting integers or strings. +* `+protoc-gen-crd:validation:IgnoreSubValidation`: if referencing a message in a field, and that message has some validation on it already, exclude the listed validations. + This is uncommon, but can be used when referencing a message in a certain context has different rules than others. + +The most common validations are: +* Sizes: `MaxLength` (strings), `MaxItems` (lists), `MaxProperties` (maps) +* Regex: `Pattern` +* CEL: `XValidation` + +### CEL + +[CEL](https://cel.dev/) is a small language that allows us to write expressions to represent validation logic. +This comes with a lot of quirks! + +Useful tools and references: +* [CEL playground](https://playcel.undistro.io/) allows an easy way to run CEL expressions against some types. +* [Kubernetes CEL docs](https://kubernetes.io/docs/reference/using-api/cel/). +* [CEL language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md). + +The biggest challenge with CEL is the complexity limit imposed by Kubernetes. +This estimates the cost to run the function, and rejects it if it is too high. +This takes into account the cost of a function and the cost of *potential* inputs. +This makes it, typically, required to put maximum size bounds on items. + +Kubernetes changes version-to-version on how it estimates cost (usually getting more lenient) and what functions are available. +We want to target the oldest version for compatibility purposes. +Our tests do not currently cover this (a prototype of doing so can be found [here](https://github.com/istio/api/pull/3275)). +A list of what features are in which versions can be found [here](https://kubernetes.io/docs/reference/using-api/cel/#cel-options-language-features-and-libraries). + +Istio has some custom macros that are expanded at compile time, driven by the [celpp](https://github.com/howardjohn/celpp) package. +This extends CEL with these capabilities: +* **default**. Usage: `default(self.x, 'DEF')`. +* **oneof**. Usage: `oneof(self.x, self.y, self.z)`. This checks that 0 or 1 of these fields is set. +* **index**. Usage: `self.index({}, x, z, b)`. This does `self.x.z.b` and returns `{}` if any of these is not set. + +Unlike typical Go usage, CEL does not have a concept of zero values for unset fields. +As a result, an optional field needs special care. +Do not write `self.fruit == 'apple'`, for instance, write `default(self.fruit, '') == 'apple'. + +### Testing + +As validation logic is really easy to get wrong, it's useful to write tests. +This is done by adding YAML files under `tests/testdata`. +Each type has a `valid` and `invalid` file to do positive and negative cases. + +Aside from explicitly testing these, these also form the seed corpus for fuzzing when these are pulled into `istio/istio`. +This fuzz testing verifies the CRD validation has the same result as the webhook (Golang) validation code. +Currently, this mostly serves to ensure we do not make something overly strict. +In the future, it may show us that its safe to disable the webhook entirely, if CRD validation can cover the full validation surface. + ## CRD Guidelines ### CRD Style diff --git a/extensions/v1alpha1/wasm.pb.go b/extensions/v1alpha1/wasm.pb.go index b670f8ff7e0..e8be6e7c908 100644 --- a/extensions/v1alpha1/wasm.pb.go +++ b/extensions/v1alpha1/wasm.pb.go @@ -539,7 +539,7 @@ func (FailStrategy) EnumDescriptor() ([]byte, []int) { // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type WasmPlugin struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -849,7 +849,7 @@ func (x *VmConfig) GetEnv() []*EnvVar { return nil } -// +kubebuilder:validation:XValidation:message="value may only be set when valueFrom is INLINE",rule="(has(self.valueFrom) ? self.valueFrom : ”) != 'HOST' || !has(self.value)" +// +kubebuilder:validation:XValidation:message="value may only be set when valueFrom is INLINE",rule="default(self.valueFrom, ”) != 'HOST' || !has(self.value)" type EnvVar struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/extensions/v1alpha1/wasm.proto b/extensions/v1alpha1/wasm.proto index eb7d8fd2a47..6c2a84836d7 100644 --- a/extensions/v1alpha1/wasm.proto +++ b/extensions/v1alpha1/wasm.proto @@ -236,7 +236,7 @@ option go_package="istio.io/api/extensions/v1alpha1"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" message WasmPlugin { // Criteria used to select the specific set of pods/VMs on which // this plugin configuration should be applied. If omitted, this @@ -462,7 +462,7 @@ message VmConfig { repeated EnvVar env = 1; } -// +kubebuilder:validation:XValidation:message="value may only be set when valueFrom is INLINE",rule="(has(self.valueFrom) ? self.valueFrom : '') != 'HOST' || !has(self.value)" +// +kubebuilder:validation:XValidation:message="value may only be set when valueFrom is INLINE",rule="default(self.valueFrom, '') != 'HOST' || !has(self.value)" message EnvVar { // Name of the environment variable. // Must be a C_IDENTIFIER. diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index 9777d4595b0..486ef52bd09 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -133,14 +133,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -180,8 +180,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -215,8 +216,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array type: @@ -235,10 +237,9 @@ spec: type: string x-kubernetes-validations: - message: url must have schema one of [http, https, file, oci] - rule: 'isURL(self) ? (url(self).getScheme() in ['''', ''http'', - ''https'', ''oci'', ''file'']) : (isURL(''http://'' + self) && - url(''http://'' +self).getScheme() in ['''', ''http'', ''https'', - ''oci'', ''file''])' + rule: |- + isURL(self) ? (url(self).getScheme() in ["", "http", "https", "oci", "file"]) : (isURL("http://" + self) && + url("http://" + self).getScheme() in ["", "http", "https", "oci", "file"]) verificationKey: type: string vmConfig: @@ -272,7 +273,7 @@ spec: type: object x-kubernetes-validations: - message: value may only be set when valueFrom is INLINE - rule: '(has(self.valueFrom) ? self.valueFrom : '''') != ''HOST'' + rule: '(has(self.valueFrom) ? self.valueFrom : "") != "HOST" || !has(self.value)' maxItems: 256 type: array @@ -285,7 +286,8 @@ spec: type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -2217,14 +2219,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -4134,14 +4136,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -6051,14 +6053,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -6445,8 +6447,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array workloadSelector: @@ -6459,7 +6462,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -6468,7 +6471,8 @@ spec: type: object x-kubernetes-validations: - message: only one of targetRefs or workloadSelector can be set - rule: (has(self.workloadSelector)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.workloadSelector) ? 1 : 0) + (has(self.targetRefs) + ? 1 : 0) <= 1' status: properties: conditions: @@ -7318,14 +7322,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -7480,11 +7484,11 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) - == ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) + == "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : + true' labels: additionalProperties: type: string @@ -7513,7 +7517,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -7529,7 +7533,7 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' maxItems: 4096 type: array @@ -7544,7 +7548,7 @@ spec: type: string x-kubernetes-validations: - message: hostname cannot be wildcard - rule: self != '*' + rule: self != "*" maxItems: 256 minItems: 1 type: array @@ -7624,7 +7628,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -7635,18 +7639,19 @@ spec: type: object x-kubernetes-validations: - message: only one of WorkloadSelector or Endpoints can be set - rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + rule: '(has(self.workloadSelector) ? 1 : 0) + (has(self.endpoints) ? + 1 : 0) <= 1' - message: CIDR addresses are allowed only for NONE/STATIC resolution types - rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) - && (has(self.resolution) && self.resolution != ''STATIC'' && self.resolution - != ''NONE''))' + rule: '!((has(self.addresses) ? self.addresses : []).exists(k, k.contains("/")) + && !((has(self.resolution) ? self.resolution : "NONE") in ["STATIC", + "NONE"]))' - message: NONE mode cannot set endpoints - rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) - : true' + rule: '((has(self.resolution) ? self.resolution : "NONE") == "NONE") + ? !has(self.endpoints) : true' - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints - rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') - ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' + rule: '((has(self.resolution) ? self.resolution : "") == "DNS_ROUND_ROBIN") + ? ((has(self.endpoints) ? self.endpoints : []).size() <= 1) : true' status: properties: conditions: @@ -7773,11 +7778,11 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) - == ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) + == "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : + true' labels: additionalProperties: type: string @@ -7806,7 +7811,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -7822,7 +7827,7 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' maxItems: 4096 type: array @@ -7837,7 +7842,7 @@ spec: type: string x-kubernetes-validations: - message: hostname cannot be wildcard - rule: self != '*' + rule: self != "*" maxItems: 256 minItems: 1 type: array @@ -7917,7 +7922,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -7928,18 +7933,19 @@ spec: type: object x-kubernetes-validations: - message: only one of WorkloadSelector or Endpoints can be set - rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + rule: '(has(self.workloadSelector) ? 1 : 0) + (has(self.endpoints) ? + 1 : 0) <= 1' - message: CIDR addresses are allowed only for NONE/STATIC resolution types - rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) - && (has(self.resolution) && self.resolution != ''STATIC'' && self.resolution - != ''NONE''))' + rule: '!((has(self.addresses) ? self.addresses : []).exists(k, k.contains("/")) + && !((has(self.resolution) ? self.resolution : "NONE") in ["STATIC", + "NONE"]))' - message: NONE mode cannot set endpoints - rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) - : true' + rule: '((has(self.resolution) ? self.resolution : "NONE") == "NONE") + ? !has(self.endpoints) : true' - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints - rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') - ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' + rule: '((has(self.resolution) ? self.resolution : "") == "DNS_ROUND_ROBIN") + ? ((has(self.endpoints) ? self.endpoints : []).size() <= 1) : true' status: properties: conditions: @@ -8066,11 +8072,11 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) - == ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) + == "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : + true' labels: additionalProperties: type: string @@ -8099,7 +8105,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -8115,7 +8121,7 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' maxItems: 4096 type: array @@ -8130,7 +8136,7 @@ spec: type: string x-kubernetes-validations: - message: hostname cannot be wildcard - rule: self != '*' + rule: self != "*" maxItems: 256 minItems: 1 type: array @@ -8210,7 +8216,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -8221,18 +8227,19 @@ spec: type: object x-kubernetes-validations: - message: only one of WorkloadSelector or Endpoints can be set - rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + rule: '(has(self.workloadSelector) ? 1 : 0) + (has(self.endpoints) ? + 1 : 0) <= 1' - message: CIDR addresses are allowed only for NONE/STATIC resolution types - rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) - && (has(self.resolution) && self.resolution != ''STATIC'' && self.resolution - != ''NONE''))' + rule: '!((has(self.addresses) ? self.addresses : []).exists(k, k.contains("/")) + && !((has(self.resolution) ? self.resolution : "NONE") in ["STATIC", + "NONE"]))' - message: NONE mode cannot set endpoints - rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) - : true' + rule: '((has(self.resolution) ? self.resolution : "NONE") == "NONE") + ? !has(self.endpoints) : true' - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints - rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') - ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' + rule: '((has(self.resolution) ? self.resolution : "") == "DNS_ROUND_ROBIN") + ? ((has(self.endpoints) ? self.endpoints : []).size() <= 1) : true' status: properties: conditions: @@ -8790,7 +8797,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -9328,7 +9335,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -9866,7 +9873,7 @@ spec: type: string x-kubernetes-validations: - message: wildcard is not supported in selector - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. maxProperties: 256 @@ -13137,10 +13144,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == ''/'' - || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == "/" + || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -13169,7 +13176,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -13185,8 +13192,8 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) ? - !has(self.ports) : true' + rule: '(has(self.address) ? self.address : "").startsWith("unix://") + ? !has(self.ports) : true' status: properties: conditions: @@ -13293,10 +13300,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == ''/'' - || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == "/" + || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -13325,7 +13332,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -13341,8 +13348,8 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) ? - !has(self.ports) : true' + rule: '(has(self.address) ? self.address : "").startsWith("unix://") + ? !has(self.ports) : true' status: properties: conditions: @@ -13449,10 +13456,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == ''/'' - || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == "/" + || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -13481,7 +13488,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -13497,8 +13504,8 @@ spec: - message: Address is required rule: has(self.address) || has(self.network) - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) ? - !has(self.ports) : true' + rule: '(has(self.address) ? self.address : "").startsWith("unix://") + ? !has(self.ports) : true' status: properties: conditions: @@ -13704,7 +13711,7 @@ spec: type: string x-kubernetes-validations: - message: scheme must be one of [HTTP, HTTPS] - rule: self in ['', 'HTTP', 'HTTPS'] + rule: self in ["", "HTTP", "HTTPS"] required: - port type: object @@ -13757,11 +13764,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == - ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == + "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -13790,7 +13796,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -13804,7 +13810,7 @@ spec: type: object x-kubernetes-validations: - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' required: - template @@ -13990,7 +13996,7 @@ spec: type: string x-kubernetes-validations: - message: scheme must be one of [HTTP, HTTPS] - rule: self in ['', 'HTTP', 'HTTPS'] + rule: self in ["", "HTTP", "HTTPS"] required: - port type: object @@ -14043,11 +14049,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == - ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == + "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -14076,7 +14081,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -14090,7 +14095,7 @@ spec: type: object x-kubernetes-validations: - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' required: - template @@ -14276,7 +14281,7 @@ spec: type: string x-kubernetes-validations: - message: scheme must be one of [HTTP, HTTPS] - rule: self in ['', 'HTTP', 'HTTPS'] + rule: self in ["", "HTTP", "HTTPS"] required: - port type: object @@ -14329,11 +14334,10 @@ spec: type: string x-kubernetes-validations: - message: UDS must be an absolute path or abstract socket - rule: 'self.startsWith(''unix://'') ? (self.substring(7,8) == - ''/'' || self.substring(7,8) == ''@'') : true' + rule: 'self.startsWith("unix://") ? (self.substring(7, 8) == + "/" || self.substring(7, 8) == "@") : true' - message: UDS may not be a dir - rule: 'self.startsWith(''unix://'') ? !self.endsWith(''/'') - : true' + rule: 'self.startsWith("unix://") ? !self.endsWith("/") : true' labels: additionalProperties: type: string @@ -14362,7 +14366,7 @@ spec: type: object x-kubernetes-validations: - message: port name must be valid - rule: self.all(key, size(key) < 63 && key.matches('^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$')) + rule: self.all(key, size(key) < 63 && key.matches("^[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?$")) serviceAccount: description: The service account associated with the workload if a sidecar is present in the workload. @@ -14376,7 +14380,7 @@ spec: type: object x-kubernetes-validations: - message: UDS may not include ports - rule: '(has(self.address) && self.address.startsWith(''unix://'')) + rule: '(has(self.address) ? self.address : "").startsWith("unix://") ? !has(self.ports) : true' required: - template @@ -14678,14 +14682,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -14720,8 +14724,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -14755,14 +14760,16 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -15031,14 +15038,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -15073,8 +15080,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -15108,14 +15116,16 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -15286,22 +15296,22 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object type: object x-kubernetes-validations: - message: portLevelMtls requires selector - rule: (has(self.selector) && has(self.selector.matchLabels) && self.selector.matchLabels.size() - > 0) || !has(self.portLevelMtls) + rule: 'has(self.portLevelMtls) ? (((has(self.selector) && has(self.selector.matchLabels)) + ? self.selector.matchLabels : {}).size() > 0) : true' status: properties: conditions: @@ -15445,22 +15455,22 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object type: object x-kubernetes-validations: - message: portLevelMtls requires selector - rule: (has(self.selector) && has(self.selector.matchLabels) && self.selector.matchLabels.size() - > 0) || !has(self.portLevelMtls) + rule: 'has(self.portLevelMtls) ? (((has(self.selector) && has(self.selector.matchLabels)) + ? self.selector.matchLabels : {}).size() > 0) : true' status: properties: conditions: @@ -15632,7 +15642,7 @@ spec: type: string x-kubernetes-validations: - message: url must have scheme http:// or https:// - rule: url(self).getScheme() in ['http', 'https'] + rule: url(self).getScheme() in ["http", "https"] jwksUri: description: URL of the provider's public key set to validate signature of the JWT. @@ -15641,7 +15651,7 @@ spec: type: string x-kubernetes-validations: - message: url must have scheme http:// or https:// - rule: url(self).getScheme() in ['http', 'https'] + rule: url(self).getScheme() in ["http", "https"] outputClaimToHeaders: description: This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. @@ -15678,7 +15688,8 @@ spec: type: object x-kubernetes-validations: - message: only one of jwks or jwksUri can be set - rule: (has(self.jwksUri)?1:0)+(has(self.jwks_uri)?1:0)+(has(self.jwks)?1:0)<=1 + rule: '(has(self.jwksUri) ? 1 : 0) + (has(self.jwks_uri) ? 1 : + 0) + (has(self.jwks) ? 1 : 0) <= 1' maxItems: 4096 type: array selector: @@ -15690,14 +15701,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -15732,8 +15743,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -15767,14 +15779,16 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -15919,7 +15933,7 @@ spec: type: string x-kubernetes-validations: - message: url must have scheme http:// or https:// - rule: url(self).getScheme() in ['http', 'https'] + rule: url(self).getScheme() in ["http", "https"] jwksUri: description: URL of the provider's public key set to validate signature of the JWT. @@ -15928,7 +15942,7 @@ spec: type: string x-kubernetes-validations: - message: url must have scheme http:// or https:// - rule: url(self).getScheme() in ['http', 'https'] + rule: url(self).getScheme() in ["http", "https"] outputClaimToHeaders: description: This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. @@ -15965,7 +15979,8 @@ spec: type: object x-kubernetes-validations: - message: only one of jwks or jwksUri can be set - rule: (has(self.jwksUri)?1:0)+(has(self.jwks_uri)?1:0)+(has(self.jwks)?1:0)<=1 + rule: '(has(self.jwksUri) ? 1 : 0) + (has(self.jwks_uri) ? 1 : + 0) + (has(self.jwks) ? 1 : 0) <= 1' maxItems: 4096 type: array selector: @@ -15977,14 +15992,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -16019,8 +16034,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -16054,14 +16070,16 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -16305,11 +16323,11 @@ spec: type: object x-kubernetes-validations: - message: value must be set when operation is UPSERT - rule: '((has(self.operation) ? self.operation : '''') - == ''UPSERT'') ? self.value != '''' : true' + rule: '((has(self.operation) ? self.operation : "") + == "UPSERT") ? (self.value != "") : true' - message: value must not be set when operation is REMOVE - rule: '((has(self.operation) ? self.operation : '''') - == ''REMOVE'') ? !has(self.value) : true' + rule: '((has(self.operation) ? self.operation : "") + == "REMOVE") ? !has(self.value) : true' description: Optional. type: object type: object @@ -16343,14 +16361,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -16385,8 +16403,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -16420,8 +16439,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array tracing: @@ -16536,7 +16556,8 @@ spec: type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: @@ -16753,11 +16774,11 @@ spec: type: object x-kubernetes-validations: - message: value must be set when operation is UPSERT - rule: '((has(self.operation) ? self.operation : '''') - == ''UPSERT'') ? self.value != '''' : true' + rule: '((has(self.operation) ? self.operation : "") + == "UPSERT") ? (self.value != "") : true' - message: value must not be set when operation is REMOVE - rule: '((has(self.operation) ? self.operation : '''') - == ''REMOVE'') ? !has(self.value) : true' + rule: '((has(self.operation) ? self.operation : "") + == "REMOVE") ? !has(self.value) : true' description: Optional. type: object type: object @@ -16791,14 +16812,14 @@ spec: type: string x-kubernetes-validations: - message: wildcard not allowed in label value match - rule: '!self.contains(''*'')' + rule: '!self.contains("*")' description: One or more labels that indicate a specific set of pods/VMs on which a policy should be applied. maxProperties: 4096 type: object x-kubernetes-validations: - message: wildcard not allowed in label key match - rule: self.all(key, !key.contains('*')) + rule: self.all(key, !key.contains("*")) - message: key must not be empty rule: self.all(key, key.size() != 0) type: object @@ -16833,8 +16854,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' targetRefs: description: Optional. items: @@ -16868,8 +16890,9 @@ spec: x-kubernetes-validations: - message: Support kinds are core/Service, networking.istio.io/ServiceEntry, gateway.networking.k8s.io/Gateway - rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], - [''gateway.networking.k8s.io'',''Gateway''], [''networking.istio.io'',''ServiceEntry'']]' + rule: '[self.group, self.kind] in [["core", "Service"], ["", "Service"], + ["gateway.networking.k8s.io", "Gateway"], ["networking.istio.io", + "ServiceEntry"]]' maxItems: 16 type: array tracing: @@ -16984,7 +17007,8 @@ spec: type: object x-kubernetes-validations: - message: only one of targetRefs or selector can be set - rule: (has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1 + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' status: properties: conditions: diff --git a/networking/v1/destination_rule_alias.gen.go b/networking/v1/destination_rule_alias.gen.go index 141e5e1d460..d169b4aca12 100644 --- a/networking/v1/destination_rule_alias.gen.go +++ b/networking/v1/destination_rule_alias.gen.go @@ -179,7 +179,7 @@ type LoadBalancerSettings_ConsistentHashLB_RingHash_ = v1alpha3.LoadBalancerSett // The Maglev load balancer implements consistent hashing to backend hosts. type LoadBalancerSettings_ConsistentHashLB_Maglev = v1alpha3.LoadBalancerSettings_ConsistentHashLB_Maglev -// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="(has(self.warmupDurationSecs)?1:0)+(has(self.warmup)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="oneof(self.warmupDurationSecs, self.warmup)" // Standard load balancing algorithms that require no tuning. type LoadBalancerSettings_SimpleLB = v1alpha3.LoadBalancerSettings_SimpleLB diff --git a/networking/v1/service_entry_alias.gen.go b/networking/v1/service_entry_alias.gen.go index 969da7ee61a..1e4732ba4fd 100644 --- a/networking/v1/service_entry_alias.gen.go +++ b/networking/v1/service_entry_alias.gen.go @@ -34,10 +34,10 @@ import "istio.io/api/networking/v1alpha3" // +k8s:deepcopy-gen=true // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> -// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (has(self.resolution) && self.resolution != 'STATIC' && self.resolution != 'NONE'))" -// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" -// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="oneof(self.workloadSelector, self.endpoints)" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(default(self.addresses, []).exists(k, k.contains('/')) && !(default(self.resolution, 'NONE') in ['STATIC', 'NONE']))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="default(self.resolution, 'NONE') == 'NONE' ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="default(self.resolution, ”) == 'DNS_ROUND_ROBIN' ? default(self.endpoints, []).size() <= 1 : true" type ServiceEntry = v1alpha3.ServiceEntry // Location specifies whether the service is part of Istio mesh or diff --git a/networking/v1/workload_entry_alias.gen.go b/networking/v1/workload_entry_alias.gen.go index 9999202ea74..ad4fd17af76 100644 --- a/networking/v1/workload_entry_alias.gen.go +++ b/networking/v1/workload_entry_alias.gen.go @@ -29,5 +29,5 @@ import "istio.io/api/networking/v1alpha3" // +k8s:deepcopy-gen=true // --> // +kubebuilder:validation:XValidation:message="Address is required",rule="has(self.address) || has(self.network)" -// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(has(self.address) && self.address.startsWith('unix://')) ? !has(self.ports) : true" +// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(default(self.address, "").startsWith('unix://')) ? !has(self.ports) : true" type WorkloadEntry = v1alpha3.WorkloadEntry diff --git a/networking/v1alpha3/destination_rule.pb.go b/networking/v1alpha3/destination_rule.pb.go index 47ffa25885d..01bc9fa7795 100644 --- a/networking/v1alpha3/destination_rule.pb.go +++ b/networking/v1alpha3/destination_rule.pb.go @@ -188,7 +188,7 @@ func (TrafficPolicy_ProxyProtocol_VERSION) EnumDescriptor() ([]byte, []int) { return file_networking_v1alpha3_destination_rule_proto_rawDescGZIP(), []int{1, 2, 0} } -// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="(has(self.warmupDurationSecs)?1:0)+(has(self.warmup)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="oneof(self.warmupDurationSecs, self.warmup)" // Standard load balancing algorithms that require no tuning. type LoadBalancerSettings_SimpleLB int32 diff --git a/networking/v1alpha3/destination_rule.proto b/networking/v1alpha3/destination_rule.proto index 7fb0e229939..bdd6becd0ff 100644 --- a/networking/v1alpha3/destination_rule.proto +++ b/networking/v1alpha3/destination_rule.proto @@ -377,7 +377,7 @@ message Subset { // ``` // message LoadBalancerSettings { - // +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="(has(self.warmupDurationSecs)?1:0)+(has(self.warmup)?1:0)<=1" + // +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="oneof(self.warmupDurationSecs, self.warmup)" // Standard load balancing algorithms that require no tuning. enum SimpleLB { // No load balancing algorithm has been specified by the user. Istio diff --git a/networking/v1alpha3/envoy_filter.pb.go b/networking/v1alpha3/envoy_filter.pb.go index 3670ff55c14..44cd1f74cf7 100644 --- a/networking/v1alpha3/envoy_filter.pb.go +++ b/networking/v1alpha3/envoy_filter.pb.go @@ -822,7 +822,7 @@ func (EnvoyFilter_Patch_FilterClass) EnumDescriptor() ([]byte, []int) { // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or workloadSelector can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or workloadSelector can be set",rule="oneof(self.workloadSelector, self.targetRefs)" type EnvoyFilter struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/networking/v1alpha3/envoy_filter.proto b/networking/v1alpha3/envoy_filter.proto index e71ffab4651..94259eb3cc0 100644 --- a/networking/v1alpha3/envoy_filter.proto +++ b/networking/v1alpha3/envoy_filter.proto @@ -421,7 +421,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or workloadSelector can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or workloadSelector can be set",rule="oneof(self.workloadSelector, self.targetRefs)" message EnvoyFilter { // `ApplyTo` specifies where in the Envoy configuration, the given patch should be applied. enum ApplyTo { diff --git a/networking/v1alpha3/service_entry.pb.go b/networking/v1alpha3/service_entry.pb.go index 30872a00ee8..f4d7978409d 100644 --- a/networking/v1alpha3/service_entry.pb.go +++ b/networking/v1alpha3/service_entry.pb.go @@ -594,10 +594,10 @@ func (ServiceEntry_Resolution) EnumDescriptor() ([]byte, []int) { // +k8s:deepcopy-gen=true // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> -// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (has(self.resolution) && self.resolution != 'STATIC' && self.resolution != 'NONE'))" -// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" -// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="oneof(self.workloadSelector, self.endpoints)" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(default(self.addresses, []).exists(k, k.contains('/')) && !(default(self.resolution, 'NONE') in ['STATIC', 'NONE']))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="default(self.resolution, 'NONE') == 'NONE' ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="default(self.resolution, ”) == 'DNS_ROUND_ROBIN' ? default(self.endpoints, []).size() <= 1 : true" type ServiceEntry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/networking/v1alpha3/service_entry.proto b/networking/v1alpha3/service_entry.proto index 66782f2432f..e2478b5c597 100644 --- a/networking/v1alpha3/service_entry.proto +++ b/networking/v1alpha3/service_entry.proto @@ -437,10 +437,10 @@ option go_package = "istio.io/api/networking/v1alpha3"; // +k8s:deepcopy-gen=true // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> -// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (has(self.resolution) && self.resolution != 'STATIC' && self.resolution != 'NONE'))" -// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" -// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="oneof(self.workloadSelector, self.endpoints)" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(default(self.addresses, []).exists(k, k.contains('/')) && !(default(self.resolution, 'NONE') in ['STATIC', 'NONE']))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="default(self.resolution, 'NONE') == 'NONE' ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="default(self.resolution, '') == 'DNS_ROUND_ROBIN' ? default(self.endpoints, []).size() <= 1 : true" message ServiceEntry { // The hosts associated with the ServiceEntry. Could be a DNS // name with wildcard prefix. diff --git a/networking/v1alpha3/workload_entry.pb.go b/networking/v1alpha3/workload_entry.pb.go index 0c6ee0de4fd..30835d1a739 100644 --- a/networking/v1alpha3/workload_entry.pb.go +++ b/networking/v1alpha3/workload_entry.pb.go @@ -193,7 +193,7 @@ const ( // +k8s:deepcopy-gen=true // --> // +kubebuilder:validation:XValidation:message="Address is required",rule="has(self.address) || has(self.network)" -// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(has(self.address) && self.address.startsWith('unix://')) ? !has(self.ports) : true" +// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(default(self.address, "").startsWith('unix://')) ? !has(self.ports) : true" type WorkloadEntry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/networking/v1alpha3/workload_entry.proto b/networking/v1alpha3/workload_entry.proto index fe8df9aff72..50a01a8ffa4 100644 --- a/networking/v1alpha3/workload_entry.proto +++ b/networking/v1alpha3/workload_entry.proto @@ -176,7 +176,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // +k8s:deepcopy-gen=true // --> // +kubebuilder:validation:XValidation:message="Address is required",rule="has(self.address) || has(self.network)" -// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(has(self.address) && self.address.startsWith('unix://')) ? !has(self.ports) : true" +// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(default(self.address, "").startsWith('unix://')) ? !has(self.ports) : true" message WorkloadEntry { // Address associated with the network endpoint without the // port. Domain names can be used if and only if the resolution is set diff --git a/networking/v1beta1/destination_rule_alias.gen.go b/networking/v1beta1/destination_rule_alias.gen.go index 931e2eb9d40..fbbfad1a3b9 100644 --- a/networking/v1beta1/destination_rule_alias.gen.go +++ b/networking/v1beta1/destination_rule_alias.gen.go @@ -179,7 +179,7 @@ type LoadBalancerSettings_ConsistentHashLB_RingHash_ = v1alpha3.LoadBalancerSett // The Maglev load balancer implements consistent hashing to backend hosts. type LoadBalancerSettings_ConsistentHashLB_Maglev = v1alpha3.LoadBalancerSettings_ConsistentHashLB_Maglev -// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="(has(self.warmupDurationSecs)?1:0)+(has(self.warmup)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of warmupDurationSecs or warmup can be set",rule="oneof(self.warmupDurationSecs, self.warmup)" // Standard load balancing algorithms that require no tuning. type LoadBalancerSettings_SimpleLB = v1alpha3.LoadBalancerSettings_SimpleLB diff --git a/networking/v1beta1/service_entry_alias.gen.go b/networking/v1beta1/service_entry_alias.gen.go index 70b3137bbb8..356788e0bd4 100644 --- a/networking/v1beta1/service_entry_alias.gen.go +++ b/networking/v1beta1/service_entry_alias.gen.go @@ -34,10 +34,10 @@ import "istio.io/api/networking/v1alpha3" // +k8s:deepcopy-gen=true // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> -// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (has(self.resolution) && self.resolution != 'STATIC' && self.resolution != 'NONE'))" -// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" -// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="oneof(self.workloadSelector, self.endpoints)" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(default(self.addresses, []).exists(k, k.contains('/')) && !(default(self.resolution, 'NONE') in ['STATIC', 'NONE']))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="default(self.resolution, 'NONE') == 'NONE' ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="default(self.resolution, ”) == 'DNS_ROUND_ROBIN' ? default(self.endpoints, []).size() <= 1 : true" type ServiceEntry = v1alpha3.ServiceEntry // Location specifies whether the service is part of Istio mesh or diff --git a/networking/v1beta1/workload_entry_alias.gen.go b/networking/v1beta1/workload_entry_alias.gen.go index c53cb4855f0..e0461605c4a 100644 --- a/networking/v1beta1/workload_entry_alias.gen.go +++ b/networking/v1beta1/workload_entry_alias.gen.go @@ -29,5 +29,5 @@ import "istio.io/api/networking/v1alpha3" // +k8s:deepcopy-gen=true // --> // +kubebuilder:validation:XValidation:message="Address is required",rule="has(self.address) || has(self.network)" -// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(has(self.address) && self.address.startsWith('unix://')) ? !has(self.ports) : true" +// +kubebuilder:validation:XValidation:message="UDS may not include ports",rule="(default(self.address, "").startsWith('unix://')) ? !has(self.ports) : true" type WorkloadEntry = v1alpha3.WorkloadEntry diff --git a/security/v1/authorization_policy_alias.gen.go b/security/v1/authorization_policy_alias.gen.go index d018f0fba96..502f11e0bdb 100644 --- a/security/v1/authorization_policy_alias.gen.go +++ b/security/v1/authorization_policy_alias.gen.go @@ -28,7 +28,7 @@ import "istio.io/api/security/v1beta1" // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type AuthorizationPolicy = v1beta1.AuthorizationPolicy type AuthorizationPolicy_ExtensionProvider = v1beta1.AuthorizationPolicy_ExtensionProvider diff --git a/security/v1/peer_authentication_alias.gen.go b/security/v1/peer_authentication_alias.gen.go index ab8bdcc01a8..0047374d1a2 100644 --- a/security/v1/peer_authentication_alias.gen.go +++ b/security/v1/peer_authentication_alias.gen.go @@ -133,7 +133,7 @@ import "istio.io/api/security/v1beta1" // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="(has(self.selector) && has(self.selector.matchLabels) && self.selector.matchLabels.size() > 0) || !has(self.portLevelMtls)" +// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="has(self.portLevelMtls) ? self.index({}, selector, matchLabels).size() > 0 : true" type PeerAuthentication = v1beta1.PeerAuthentication // Mutual TLS settings. diff --git a/security/v1/request_authentication_alias.gen.go b/security/v1/request_authentication_alias.gen.go index bde0f9c9618..e2b9722202e 100644 --- a/security/v1/request_authentication_alias.gen.go +++ b/security/v1/request_authentication_alias.gen.go @@ -260,7 +260,7 @@ import "istio.io/api/security/v1beta1" // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type RequestAuthentication = v1beta1.RequestAuthentication // JSON Web Token (JWT) token format for authentication as defined by @@ -292,7 +292,7 @@ type RequestAuthentication = v1beta1.RequestAuthentication // fromHeaders: // - "x-goog-iap-jwt-assertion" // ``` -// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="(has(self.jwksUri)?1:0)+(has(self.jwks_uri)?1:0)+(has(self.jwks)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="oneof(self.jwksUri, self.jwks_uri, self.jwks)" type JWTRule = v1beta1.JWTRule // This message specifies a header location to extract JWT token. diff --git a/security/v1beta1/authorization_policy.pb.go b/security/v1beta1/authorization_policy.pb.go index edb36e3e5b6..9b7ac4e28ec 100644 --- a/security/v1beta1/authorization_policy.pb.go +++ b/security/v1beta1/authorization_policy.pb.go @@ -377,7 +377,7 @@ func (AuthorizationPolicy_Action) EnumDescriptor() ([]byte, []int) { // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type AuthorizationPolicy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/security/v1beta1/authorization_policy.proto b/security/v1beta1/authorization_policy.proto index 3bb1049b6ea..5064bcc84f1 100644 --- a/security/v1beta1/authorization_policy.proto +++ b/security/v1beta1/authorization_policy.proto @@ -270,7 +270,7 @@ option go_package="istio.io/api/security/v1beta1"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" message AuthorizationPolicy { // Optional. The selector decides where to apply the authorization policy. The selector will match with workloads // in the same namespace as the authorization policy. If the authorization policy is in the root namespace, the selector diff --git a/security/v1beta1/peer_authentication.pb.go b/security/v1beta1/peer_authentication.pb.go index a6291ae56ad..cbc0d543366 100644 --- a/security/v1beta1/peer_authentication.pb.go +++ b/security/v1beta1/peer_authentication.pb.go @@ -227,7 +227,7 @@ func (PeerAuthentication_MutualTLS_Mode) EnumDescriptor() ([]byte, []int) { // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="(has(self.selector) && has(self.selector.matchLabels) && self.selector.matchLabels.size() > 0) || !has(self.portLevelMtls)" +// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="has(self.portLevelMtls) ? self.index({}, selector, matchLabels).size() > 0 : true" type PeerAuthentication struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/security/v1beta1/peer_authentication.proto b/security/v1beta1/peer_authentication.proto index cdd92ff7974..aac0ac5eb1f 100644 --- a/security/v1beta1/peer_authentication.proto +++ b/security/v1beta1/peer_authentication.proto @@ -135,7 +135,7 @@ option go_package="istio.io/api/security/v1beta1"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="(has(self.selector) && has(self.selector.matchLabels) && self.selector.matchLabels.size() > 0) || !has(self.portLevelMtls)" +// +kubebuilder:validation:XValidation:message="portLevelMtls requires selector",rule="has(self.portLevelMtls) ? self.index({}, selector, matchLabels).size() > 0 : true" message PeerAuthentication { // The selector determines the workloads to apply the PeerAuthentication on. The selector will match with workloads in the // same namespace as the policy. If the policy is in the root namespace, the selector will additionally match with workloads in all namespace. diff --git a/security/v1beta1/request_authentication.pb.go b/security/v1beta1/request_authentication.pb.go index 86c85c60642..6957db8065a 100644 --- a/security/v1beta1/request_authentication.pb.go +++ b/security/v1beta1/request_authentication.pb.go @@ -300,7 +300,7 @@ const ( // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type RequestAuthentication struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -433,7 +433,7 @@ func (x *RequestAuthentication) GetJwtRules() []*JWTRule { // fromHeaders: // - "x-goog-iap-jwt-assertion" // ``` -// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="(has(self.jwksUri)?1:0)+(has(self.jwks_uri)?1:0)+(has(self.jwks)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="oneof(self.jwksUri, self.jwks_uri, self.jwks)" type JWTRule struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/security/v1beta1/request_authentication.proto b/security/v1beta1/request_authentication.proto index 4ba3dfe2c28..69caaf056b9 100644 --- a/security/v1beta1/request_authentication.proto +++ b/security/v1beta1/request_authentication.proto @@ -244,7 +244,7 @@ option go_package="istio.io/api/security/v1beta1"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" message RequestAuthentication { // Optional. The selector decides where to apply the request authentication policy. The selector will match with workloads // in the same namespace as the request authentication policy. If the request authentication policy is in the root namespace, @@ -316,7 +316,7 @@ message RequestAuthentication { // fromHeaders: // - "x-goog-iap-jwt-assertion" // ``` -// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="(has(self.jwksUri)?1:0)+(has(self.jwks_uri)?1:0)+(has(self.jwks)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of jwks or jwksUri can be set",rule="oneof(self.jwksUri, self.jwks_uri, self.jwks)" message JWTRule { // Identifies the issuer that issued the JWT. See // [issuer](https://tools.ietf.org/html/rfc7519#section-4.1.1) diff --git a/telemetry/v1/telemetry_alias.gen.go b/telemetry/v1/telemetry_alias.gen.go index 93c066c6d5b..d6382c8bcbf 100644 --- a/telemetry/v1/telemetry_alias.gen.go +++ b/telemetry/v1/telemetry_alias.gen.go @@ -27,7 +27,7 @@ import "istio.io/api/telemetry/v1alpha1" // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type Telemetry = v1alpha1.Telemetry // Tracing configures tracing behavior for workloads within a mesh. @@ -205,8 +205,8 @@ type MetricsOverrides = v1alpha1.MetricsOverrides // TagOverride specifies an operation to perform on a metric dimension (also // known as a `label`). Tags may be added, removed, or have their default // values overridden. -// +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="((has(self.operation) ? self.operation : ”) == 'UPSERT') ? self.value != ” : true" -// +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="((has(self.operation) ? self.operation : ”) == 'REMOVE') ? !has(self.value) : true" +// +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="default(self.operation, ”) == 'UPSERT' ? self.value != ” : true" +// +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="default(self.operation, ”) == 'REMOVE' ? !has(self.value) : true" type MetricsOverrides_TagOverride = v1alpha1.MetricsOverrides_TagOverride type MetricsOverrides_TagOverride_Operation = v1alpha1.MetricsOverrides_TagOverride_Operation diff --git a/telemetry/v1alpha1/telemetry.pb.go b/telemetry/v1alpha1/telemetry.pb.go index 518794b1c13..60b133a9f39 100644 --- a/telemetry/v1alpha1/telemetry.pb.go +++ b/telemetry/v1alpha1/telemetry.pb.go @@ -544,7 +544,7 @@ func (MetricsOverrides_TagOverride_Operation) EnumDescriptor() ([]byte, []int) { // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" type Telemetry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1498,8 +1498,8 @@ func (x *Tracing_RequestHeader) GetDefaultValue() string { // TagOverride specifies an operation to perform on a metric dimension (also // known as a `label`). Tags may be added, removed, or have their default // values overridden. -// +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="((has(self.operation) ? self.operation : ”) == 'UPSERT') ? self.value != ” : true" -// +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="((has(self.operation) ? self.operation : ”) == 'REMOVE') ? !has(self.value) : true" +// +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="default(self.operation, ”) == 'UPSERT' ? self.value != ” : true" +// +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="default(self.operation, ”) == 'REMOVE' ? !has(self.value) : true" type MetricsOverrides_TagOverride struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/telemetry/v1alpha1/telemetry.proto b/telemetry/v1alpha1/telemetry.proto index 98e277b9515..4c3880e69a3 100644 --- a/telemetry/v1alpha1/telemetry.proto +++ b/telemetry/v1alpha1/telemetry.proto @@ -258,7 +258,7 @@ option go_package = "istio.io/api/telemetry/v1alpha1"; // +genclient // +k8s:deepcopy-gen=true // --> -// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="oneof(self.selector, self.targetRef, self.targetRefs)" message Telemetry { // Optional. The selector decides where to apply the policy. // If not set, the policy will be applied to all workloads in the @@ -622,8 +622,8 @@ message MetricsOverrides { // TagOverride specifies an operation to perform on a metric dimension (also // known as a `label`). Tags may be added, removed, or have their default // values overridden. - // +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="((has(self.operation) ? self.operation : '') == 'UPSERT') ? self.value != '' : true" - // +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="((has(self.operation) ? self.operation : '') == 'REMOVE') ? !has(self.value) : true" + // +kubebuilder:validation:XValidation:message="value must be set when operation is UPSERT",rule="default(self.operation, '') == 'UPSERT' ? self.value != '' : true" + // +kubebuilder:validation:XValidation:message="value must not be set when operation is REMOVE",rule="default(self.operation, '') == 'REMOVE' ? !has(self.value) : true" message TagOverride { enum Operation { // Insert or Update the tag with the provided value expression. The