From e141e9832f04a7ba1faaecd0dc17371578ada44a Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Tue, 26 Mar 2024 13:19:09 +0100 Subject: [PATCH] wip: crd: require unique hosts CRD does not support `uniqueItems: true` validation: ``` The CustomResourceDefinition "routegroups.zalando.org" is invalid: spec.validation.openAPIV3Schema.properties[spec].properties[hosts].uniqueItems: Forbidden: uniqueItems cannot be set to true since the runtime complexity becomes quadratic ``` This change adds [validation rule](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules) to enforce unique hosts. It also adds maxItems limit to overcome rule cost error: ``` The CustomResourceDefinition "routegroups.zalando.org" is invalid: * spec.validation.openAPIV3Schema.properties[spec].properties[hosts].x-kubernetes-validations[0].rule: Forbidden: estimated rule cost exceeds budget by factor of more than 100x (try simplifying the rule, or adding maxItems, maxProperties, and maxLength where arrays, maps, and strings are declared) * spec.validation.openAPIV3Schema.properties[spec].properties[hosts].x-kubernetes-validations[0].rule: Forbidden: contributed to estimated rule cost total exceeding cost limit for entire OpenAPIv3 schema * spec.validation.openAPIV3Schema: Forbidden: x-kubernetes-validations estimated rule cost total for entire OpenAPIv3 schema exceeds budget by factor of more than 100x (try simplifying the rule, or adding maxItems, maxProperties, and maxLength where arrays, maps, and strings are declared) ``` Note that validation rule is not added to `tls` spec because then rule cost error re-appears apparently due to exceeding total allowed schema cost. Example validation error: ``` Error from server (Invalid): error when creating "rg.yaml": RouteGroup.zalando.org "duplicate-hosts" is invalid: spec.hosts: Invalid value: "array": hosts must be unique ``` Signed-off-by: Alexander Yastrebov --- apis/zalando.org/v1/types.go | 2 ++ zalando.org_routegroups.yaml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/apis/zalando.org/v1/types.go b/apis/zalando.org/v1/types.go index 32ec2e7..da7bf54 100644 --- a/apis/zalando.org/v1/types.go +++ b/apis/zalando.org/v1/types.go @@ -43,6 +43,8 @@ type RouteGroupList struct { type RouteGroupSpec struct { // List of hostnames for the RouteGroup // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=255 + // +kubebuilder:validation:XValidation:rule="self.all(i, size(self.filter(j, j==i)) == 1)", message="hosts must be unique" Hosts []string `json:"hosts,omitempty"` // List of backends that can be referenced in the routes Backends []RouteGroupBackend `json:"backends"` diff --git a/zalando.org_routegroups.yaml b/zalando.org_routegroups.yaml index f977a68..a3efca9 100644 --- a/zalando.org_routegroups.yaml +++ b/zalando.org_routegroups.yaml @@ -134,8 +134,12 @@ spec: maxLength: 255 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + maxItems: 255 minItems: 1 type: array + x-kubernetes-validations: + - message: hosts must be unique + rule: self.all(i, size(self.filter(j, j==i)) == 1) routes: description: Routes describe how a matching HTTP request is handled and where it is forwarded to