From 23d4b81bef31745f4dcf7d54e40a6e7eb3c5e452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 16 Dec 2024 08:09:37 +0100 Subject: [PATCH 01/32] feat: :package: add separated chart for CRDs --- README.md | 2 +- hack/test.sh | 1 + traefik-crds/.helmignore | 23 ++++++++ traefik-crds/Chart.yaml | 23 ++++++++ .../gateway}/gateway-standard-install.yaml | 0 .../hub.traefik.io_accesscontrolpolicies.yaml | 0 .../hub}/hub.traefik.io_aiservices.yaml | 0 .../hub}/hub.traefik.io_apiaccesses.yaml | 0 .../hub}/hub.traefik.io_apibundles.yaml | 0 .../hub}/hub.traefik.io_apicatalogitems.yaml | 0 .../hub}/hub.traefik.io_apiplans.yaml | 0 .../hub}/hub.traefik.io_apiportals.yaml | 0 .../hub}/hub.traefik.io_apiratelimits.yaml | 0 .../crds-files/hub}/hub.traefik.io_apis.yaml | 0 .../hub}/hub.traefik.io_apiversions.yaml | 0 .../hub.traefik.io_managedsubscriptions.yaml | 0 .../traefik}/traefik.io_ingressroutes.yaml | 0 .../traefik}/traefik.io_ingressroutetcps.yaml | 0 .../traefik}/traefik.io_ingressrouteudps.yaml | 0 .../traefik}/traefik.io_middlewares.yaml | 0 .../traefik}/traefik.io_middlewaretcps.yaml | 0 .../traefik.io_serverstransports.yaml | 0 .../traefik.io_serverstransporttcps.yaml | 0 .../traefik}/traefik.io_tlsoptions.yaml | 0 .../traefik}/traefik.io_tlsstores.yaml | 0 .../traefik}/traefik.io_traefikservices.yaml | 0 traefik-crds/kustomization.yaml | 27 +++++++++ traefik-crds/templates/crds.yaml | 42 ++++++++++++++ traefik-crds/tests/crds_test.yaml | 53 ++++++++++++++++++ traefik-crds/values.yaml | 3 + traefik/Chart.lock | 6 ++ traefik/Chart.yaml | 4 ++ traefik/charts/traefik-crds-0.0.1.tgz | Bin 0 -> 125870 bytes traefik/values.schema.json | 20 +++++++ traefik/values.yaml | 8 +++ 35 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 traefik-crds/.helmignore create mode 100644 traefik-crds/Chart.yaml rename {traefik/crds => traefik-crds/crds-files/gateway}/gateway-standard-install.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_accesscontrolpolicies.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_aiservices.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apiaccesses.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apibundles.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apicatalogitems.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apiplans.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apiportals.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apiratelimits.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apis.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_apiversions.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/hub}/hub.traefik.io_managedsubscriptions.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_ingressroutes.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_ingressroutetcps.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_ingressrouteudps.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_middlewares.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_middlewaretcps.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_serverstransports.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_serverstransporttcps.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_tlsoptions.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_tlsstores.yaml (100%) rename {traefik/crds => traefik-crds/crds-files/traefik}/traefik.io_traefikservices.yaml (100%) create mode 100644 traefik-crds/kustomization.yaml create mode 100644 traefik-crds/templates/crds.yaml create mode 100644 traefik-crds/tests/crds_test.yaml create mode 100644 traefik-crds/values.yaml create mode 100644 traefik/Chart.lock create mode 100644 traefik/charts/traefik-crds-0.0.1.tgz diff --git a/README.md b/README.md index 635e64d10..34c898ef5 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ helm repo update # See current Chart & Traefik version helm search repo traefik/traefik # Update CRDs (Traefik Proxy v3 CRDs) -kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/ +kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik-crds/ # Upgrade Traefik helm upgrade traefik traefik/traefik ``` diff --git a/hack/test.sh b/hack/test.sh index e71504fb1..49933bd06 100644 --- a/hack/test.sh +++ b/hack/test.sh @@ -1,3 +1,4 @@ #!/bin/bash /usr/bin/helm unittest --color ./traefik; +/usr/bin/helm unittest --color ./traefik-crds; diff --git a/traefik-crds/.helmignore b/traefik-crds/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/traefik-crds/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/traefik-crds/Chart.yaml b/traefik-crds/Chart.yaml new file mode 100644 index 000000000..ac4dc30f9 --- /dev/null +++ b/traefik-crds/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +name: traefik-crds +description: A Traefik based Kubernetes ingress controller +type: application +version: 0.0.1 +kubeVersion: ">=1.22.0-0" +keywords: + - traefik + - ingress + - networking +home: https://traefik.io/ +sources: + - https://github.com/traefik/traefik + - https://github.com/traefik/traefik-helm-chart +maintainers: + - name: mloiseleur + email: michel.loiseleur@traefik.io + - name: charlie-haley + email: charlie.haley@traefik.io + - name: darkweaver87 + email: remi.buisson@traefik.io + - name: jnoordsij +icon: https://raw.githubusercontent.com/traefik/traefik/v2.3/docs/content/assets/img/traefik.logo.png diff --git a/traefik/crds/gateway-standard-install.yaml b/traefik-crds/crds-files/gateway/gateway-standard-install.yaml similarity index 100% rename from traefik/crds/gateway-standard-install.yaml rename to traefik-crds/crds-files/gateway/gateway-standard-install.yaml diff --git a/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_accesscontrolpolicies.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_accesscontrolpolicies.yaml diff --git a/traefik/crds/hub.traefik.io_aiservices.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_aiservices.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_aiservices.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_aiservices.yaml diff --git a/traefik/crds/hub.traefik.io_apiaccesses.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apiaccesses.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apiaccesses.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apiaccesses.yaml diff --git a/traefik/crds/hub.traefik.io_apibundles.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apibundles.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apibundles.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apibundles.yaml diff --git a/traefik/crds/hub.traefik.io_apicatalogitems.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apicatalogitems.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apicatalogitems.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apicatalogitems.yaml diff --git a/traefik/crds/hub.traefik.io_apiplans.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apiplans.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apiplans.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apiplans.yaml diff --git a/traefik/crds/hub.traefik.io_apiportals.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apiportals.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apiportals.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apiportals.yaml diff --git a/traefik/crds/hub.traefik.io_apiratelimits.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apiratelimits.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apiratelimits.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apiratelimits.yaml diff --git a/traefik/crds/hub.traefik.io_apis.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apis.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apis.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apis.yaml diff --git a/traefik/crds/hub.traefik.io_apiversions.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_apiversions.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_apiversions.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_apiversions.yaml diff --git a/traefik/crds/hub.traefik.io_managedsubscriptions.yaml b/traefik-crds/crds-files/hub/hub.traefik.io_managedsubscriptions.yaml similarity index 100% rename from traefik/crds/hub.traefik.io_managedsubscriptions.yaml rename to traefik-crds/crds-files/hub/hub.traefik.io_managedsubscriptions.yaml diff --git a/traefik/crds/traefik.io_ingressroutes.yaml b/traefik-crds/crds-files/traefik/traefik.io_ingressroutes.yaml similarity index 100% rename from traefik/crds/traefik.io_ingressroutes.yaml rename to traefik-crds/crds-files/traefik/traefik.io_ingressroutes.yaml diff --git a/traefik/crds/traefik.io_ingressroutetcps.yaml b/traefik-crds/crds-files/traefik/traefik.io_ingressroutetcps.yaml similarity index 100% rename from traefik/crds/traefik.io_ingressroutetcps.yaml rename to traefik-crds/crds-files/traefik/traefik.io_ingressroutetcps.yaml diff --git a/traefik/crds/traefik.io_ingressrouteudps.yaml b/traefik-crds/crds-files/traefik/traefik.io_ingressrouteudps.yaml similarity index 100% rename from traefik/crds/traefik.io_ingressrouteudps.yaml rename to traefik-crds/crds-files/traefik/traefik.io_ingressrouteudps.yaml diff --git a/traefik/crds/traefik.io_middlewares.yaml b/traefik-crds/crds-files/traefik/traefik.io_middlewares.yaml similarity index 100% rename from traefik/crds/traefik.io_middlewares.yaml rename to traefik-crds/crds-files/traefik/traefik.io_middlewares.yaml diff --git a/traefik/crds/traefik.io_middlewaretcps.yaml b/traefik-crds/crds-files/traefik/traefik.io_middlewaretcps.yaml similarity index 100% rename from traefik/crds/traefik.io_middlewaretcps.yaml rename to traefik-crds/crds-files/traefik/traefik.io_middlewaretcps.yaml diff --git a/traefik/crds/traefik.io_serverstransports.yaml b/traefik-crds/crds-files/traefik/traefik.io_serverstransports.yaml similarity index 100% rename from traefik/crds/traefik.io_serverstransports.yaml rename to traefik-crds/crds-files/traefik/traefik.io_serverstransports.yaml diff --git a/traefik/crds/traefik.io_serverstransporttcps.yaml b/traefik-crds/crds-files/traefik/traefik.io_serverstransporttcps.yaml similarity index 100% rename from traefik/crds/traefik.io_serverstransporttcps.yaml rename to traefik-crds/crds-files/traefik/traefik.io_serverstransporttcps.yaml diff --git a/traefik/crds/traefik.io_tlsoptions.yaml b/traefik-crds/crds-files/traefik/traefik.io_tlsoptions.yaml similarity index 100% rename from traefik/crds/traefik.io_tlsoptions.yaml rename to traefik-crds/crds-files/traefik/traefik.io_tlsoptions.yaml diff --git a/traefik/crds/traefik.io_tlsstores.yaml b/traefik-crds/crds-files/traefik/traefik.io_tlsstores.yaml similarity index 100% rename from traefik/crds/traefik.io_tlsstores.yaml rename to traefik-crds/crds-files/traefik/traefik.io_tlsstores.yaml diff --git a/traefik/crds/traefik.io_traefikservices.yaml b/traefik-crds/crds-files/traefik/traefik.io_traefikservices.yaml similarity index 100% rename from traefik/crds/traefik.io_traefikservices.yaml rename to traefik-crds/crds-files/traefik/traefik.io_traefikservices.yaml diff --git a/traefik-crds/kustomization.yaml b/traefik-crds/kustomization.yaml new file mode 100644 index 000000000..3806a9de8 --- /dev/null +++ b/traefik-crds/kustomization.yaml @@ -0,0 +1,27 @@ +--- +kind: Kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +resources: + # curl -o crds-files/gateway/gateway-standard-install.yaml -L https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml + - crds-files/gateway/gateway-standard-install.yaml + - crds-files/hub.traefik.io_accesscontrolpolicies.yaml + - crds-files/hub.traefik.io_aiservices.yaml + - crds-files/hub.traefik.io_apiaccesses.yaml + - crds-files/hub.traefik.io_apibundles.yaml + - crds-files/hub.traefik.io_apicatalogitems.yaml + - crds-files/hub.traefik.io_apiplans.yaml + - crds-files/hub.traefik.io_apiportals.yaml + - crds-files/hub.traefik.io_apiratelimits.yaml + - crds-files/hub.traefik.io_apis.yaml + - crds-files/hub.traefik.io_apiversions.yaml + - crds-files/hub.traefik.io_managedsubscriptions.yaml + - crds-files/traefik/traefik.io_ingressroutes.yaml + - crds-files/traefik/traefik.io_ingressroutetcps.yaml + - crds-files/traefik/traefik.io_ingressrouteudps.yaml + - crds-files/traefik/traefik.io_middlewares.yaml + - crds-files/traefik/traefik.io_middlewaretcps.yaml + - crds-files/traefik/traefik.io_serverstransports.yaml + - crds-files/traefik/traefik.io_serverstransporttcps.yaml + - crds-files/traefik/traefik.io_tlsoptions.yaml + - crds-files/traefik/traefik.io_tlsstores.yaml + - crds-files/traefik/traefik.io_traefikservices.yaml diff --git a/traefik-crds/templates/crds.yaml b/traefik-crds/templates/crds.yaml new file mode 100644 index 000000000..84dcf5a01 --- /dev/null +++ b/traefik-crds/templates/crds.yaml @@ -0,0 +1,42 @@ +{{- if .Values.traefik -}} +{{- $files := .Files }} +{{- range tuple +"crds-files/traefik/traefik.io_ingressroutes.yaml" +"crds-files/traefik/traefik.io_ingressroutetcps.yaml" +"crds-files/traefik/traefik.io_ingressrouteudps.yaml" +"crds-files/traefik/traefik.io_middlewares.yaml" +"crds-files/traefik/traefik.io_middlewaretcps.yaml" +"crds-files/traefik/traefik.io_serverstransports.yaml" +"crds-files/traefik/traefik.io_serverstransporttcps.yaml" +"crds-files/traefik/traefik.io_tlsoptions.yaml" +"crds-files/traefik/traefik.io_tlsstores.yaml" +"crds-files/traefik/traefik.io_traefikservices.yaml" + }} +{{ $files.Get . }} +{{- end }} +{{- end }} + +{{- if .Values.hub -}} +{{- $files := .Files }} +{{- range tuple +"crds-files/hub/hub.traefik.io_accesscontrolpolicies.yaml" +"crds-files/hub/hub.traefik.io_apiaccesses.yaml" +"crds-files/hub/hub.traefik.io_apibundles.yaml" +"crds-files/hub/hub.traefik.io_apiplans.yaml" +"crds-files/hub/hub.traefik.io_apiportals.yaml" +"crds-files/hub/hub.traefik.io_apiratelimits.yaml" +"crds-files/hub/hub.traefik.io_apis.yaml" +"crds-files/hub/hub.traefik.io_apiversions.yaml" + }} +{{ $files.Get . }} +{{- end }} +{{- end }} + +{{- if .Values.gateway_api -}} +{{- $files := .Files }} +{{- range tuple +"crds-files/gateway/gateway-standard-install-v1.1.0.yaml" + }} +{{ $files.Get . }} +{{- end }} +{{- end }} diff --git a/traefik-crds/tests/crds_test.yaml b/traefik-crds/tests/crds_test.yaml new file mode 100644 index 000000000..deeef0b22 --- /dev/null +++ b/traefik-crds/tests/crds_test.yaml @@ -0,0 +1,53 @@ +suite: CRDs +templates: + - crds.yaml +tests: + - it: shouldn't have any crds by default + asserts: + - hasDocuments: + count: 0 + + - it: should have all Traefik crds + set: + traefik: true + asserts: + - hasDocuments: + count: 10 + - isKind: + of: CustomResourceDefinition + - equal: + path: spec.group + value: traefik.io + - matchRegex: + path: spec.names.kind + pattern: ^(IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|ServersTransport|ServersTransportTCP|TLSOption|TLSStore|TraefikService)$ + + - it: should have all Traefik Hub crds + set: + hub: true + asserts: + - hasDocuments: + count: 8 + - isKind: + of: CustomResourceDefinition + - equal: + path: spec.group + value: hub.traefik.io + - matchRegex: + path: spec.names.kind + pattern: ^(AccessControlPolicy|APIAccess|APIBundle|APIPlan|APIPortal|APIRateLimit|API|APIVersion)$ + + - it: should have all Gateway API crds + set: + gateway_api: true + asserts: + - hasDocuments: + count: 5 + - isKind: + of: CustomResourceDefinition + - equal: + path: spec.group + value: gateway.networking.k8s.io + - matchRegex: + path: spec.names.kind + pattern: ^(GatewayClass|Gateway|GRPCRoute|HTTPRoute|ReferenceGrant)$ diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml new file mode 100644 index 000000000..6daca116a --- /dev/null +++ b/traefik-crds/values.yaml @@ -0,0 +1,3 @@ +traefik: false +gateway_api: false +hub: false diff --git a/traefik/Chart.lock b/traefik/Chart.lock new file mode 100644 index 000000000..7a83ae7bb --- /dev/null +++ b/traefik/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: traefik-crds + repository: file://../traefik-crds + version: 0.0.1 +digest: sha256:03a8641bfa1d261b699d166dea5aaa21d9e27bfc2328d157dae3809375709260 +generated: "2024-10-11T17:04:46.473483814+02:00" diff --git a/traefik/Chart.yaml b/traefik/Chart.yaml index 668303cf1..91af7b126 100644 --- a/traefik/Chart.yaml +++ b/traefik/Chart.yaml @@ -27,3 +27,7 @@ annotations: artifacthub.io/changes: | - "fix(Gateway API): CRDs should only be defined once" - "chore(release): 🚀 publish v33.2.1" +dependencies: + - name: traefik-crds + version: "0.0.1" + repository: "file://../traefik-crds" diff --git a/traefik/charts/traefik-crds-0.0.1.tgz b/traefik/charts/traefik-crds-0.0.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..81b81708ab0708c9690920b0da69b75c9afef055 GIT binary patch literal 125870 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

cGY4Vk6_fP6aP@xuLYlNujY5k*1$SN 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 za Date: Mon, 16 Dec 2024 08:10:40 +0100 Subject: [PATCH 02/32] fix: schemas --- Makefile | 3 +- hack/test.sh | 4 +- traefik-crds/.schema.yaml | 13 + .../gateway-standard-install-v1.2.0.yaml} | 0 .../gateway_api/gateway-standard-install.yaml | 10345 ++++++++++++++++ traefik-crds/kustomization.yaml | 4 +- traefik-crds/values.schema.json | 25 + traefik-crds/values.yaml | 6 +- .schema.yaml => traefik/.schema.yaml | 4 +- traefik/charts/traefik-crds-0.0.1.tgz | Bin 125870 -> 126070 bytes traefik/values.schema.json | 12 +- traefik/values.yaml | 6 +- 12 files changed, 10400 insertions(+), 22 deletions(-) create mode 100644 traefik-crds/.schema.yaml rename traefik-crds/crds-files/{gateway/gateway-standard-install.yaml => gateway_api/gateway-standard-install-v1.2.0.yaml} (100%) create mode 100644 traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml create mode 100644 traefik-crds/values.schema.json rename .schema.yaml => traefik/.schema.yaml (79%) diff --git a/Makefile b/Makefile index 43ffaf01f..bfb25b4a3 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,8 @@ test-install: # Requires to install schema generation plugin beforehand # $ helm plugin install https://github.com/losisin/helm-values-schema-json.git schema: - helm schema + cd traefik && helm schema + cd traefik-crds && helm schema changelog: @echo "== Updating Changelogs..." diff --git a/hack/test.sh b/hack/test.sh index 49933bd06..2909b29ef 100644 --- a/hack/test.sh +++ b/hack/test.sh @@ -1,4 +1,4 @@ #!/bin/bash -/usr/bin/helm unittest --color ./traefik; -/usr/bin/helm unittest --color ./traefik-crds; +/usr/bin/helm unittest --color ./traefik +/usr/bin/helm unittest --color ./traefik-crds diff --git a/traefik-crds/.schema.yaml b/traefik-crds/.schema.yaml new file mode 100644 index 000000000..c71d1b799 --- /dev/null +++ b/traefik-crds/.schema.yaml @@ -0,0 +1,13 @@ +# Required +input: + - values.yaml + +draft: 2020 +indent: 4 +output: values.schema.json + +schemaRoot: + id: https://traefik.io/traefik-crds-helm-chart.schema.json + title: Traefik CRDs Helm Chart + description: The Cloud Native Application Proxy + additionalProperties: true diff --git a/traefik-crds/crds-files/gateway/gateway-standard-install.yaml b/traefik-crds/crds-files/gateway_api/gateway-standard-install-v1.2.0.yaml similarity index 100% rename from traefik-crds/crds-files/gateway/gateway-standard-install.yaml rename to traefik-crds/crds-files/gateway_api/gateway-standard-install-v1.2.0.yaml diff --git a/traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml b/traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml new file mode 100644 index 000000000..5bf4f3032 --- /dev/null +++ b/traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml @@ -0,0 +1,10345 @@ +# Copyright 2024 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Gateway API Standard channel install +# +--- +# +# config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.1 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: gatewayclasses.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GatewayClass + listKind: GatewayClassList + plural: gatewayclasses + shortNames: + - gc + singular: gatewayclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1 + schema: + openAPIV3Schema: + description: |- + GatewayClass describes a class of Gateways available to the user for creating + Gateway resources. + + It is recommended that this resource be used as a template for Gateways. This + means that a Gateway is based on the state of the GatewayClass at the time it + was created and changes to the GatewayClass or associated parameters are not + propagated down to existing Gateways. This recommendation is intended to + limit the blast radius of changes to GatewayClass or associated parameters. + If implementations choose to propagate GatewayClass changes to existing + Gateways, that MUST be clearly documented by the implementation. + + Whenever one or more Gateways are using a GatewayClass, implementations SHOULD + add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the + associated GatewayClass. This ensures that a GatewayClass associated with a + Gateway is not deleted while in use. + + GatewayClass is a Cluster level resource. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: |- + ControllerName is the name of the controller that is managing Gateways of + this class. The value of this field MUST be a domain prefixed path. + + Example: "example.net/gateway-controller". + + This field is not mutable and cannot be empty. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the GatewayClass. This is optional if the + controller does not require any additional configuration. + + ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + or an implementation-specific custom resource. The resource can be + cluster-scoped or namespace-scoped. + + If the referent cannot be found, refers to an unsupported kind, or when + the data within that resource is malformed, the GatewayClass SHOULD be + rejected with the "Accepted" status condition set to "False" and an + "InvalidParameters" reason. + + A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + This field is required when referring to a Namespace-scoped resource and + MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Status defines the current state of GatewayClass. + + Implementations MUST populate status on all GatewayClass resources which + specify their controller name. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Conditions is the current status from the controller for + this GatewayClass. + + Controllers should prefer to publish conditions using values + of GatewayClassConditionType for the type of each Condition. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + GatewayClass describes a class of Gateways available to the user for creating + Gateway resources. + + It is recommended that this resource be used as a template for Gateways. This + means that a Gateway is based on the state of the GatewayClass at the time it + was created and changes to the GatewayClass or associated parameters are not + propagated down to existing Gateways. This recommendation is intended to + limit the blast radius of changes to GatewayClass or associated parameters. + If implementations choose to propagate GatewayClass changes to existing + Gateways, that MUST be clearly documented by the implementation. + + Whenever one or more Gateways are using a GatewayClass, implementations SHOULD + add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the + associated GatewayClass. This ensures that a GatewayClass associated with a + Gateway is not deleted while in use. + + GatewayClass is a Cluster level resource. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: |- + ControllerName is the name of the controller that is managing Gateways of + this class. The value of this field MUST be a domain prefixed path. + + Example: "example.net/gateway-controller". + + This field is not mutable and cannot be empty. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the GatewayClass. This is optional if the + controller does not require any additional configuration. + + ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + or an implementation-specific custom resource. The resource can be + cluster-scoped or namespace-scoped. + + If the referent cannot be found, refers to an unsupported kind, or when + the data within that resource is malformed, the GatewayClass SHOULD be + rejected with the "Accepted" status condition set to "False" and an + "InvalidParameters" reason. + + A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + This field is required when referring to a Namespace-scoped resource and + MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Status defines the current state of GatewayClass. + + Implementations MUST populate status on all GatewayClass resources which + specify their controller name. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Conditions is the current status from the controller for + this GatewayClass. + + Controllers should prefer to publish conditions using values + of GatewayClassConditionType for the type of each Condition. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_gateways.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.1 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: gateways.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: Gateway + listKind: GatewayList + plural: gateways + shortNames: + - gtw + singular: gateway + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + Gateway represents an instance of a service-traffic handling infrastructure + by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: |+ + Addresses requested for this Gateway. This is optional and behavior can + depend on the implementation. If a value is set in the spec and the + requested address is invalid or unavailable, the implementation MUST + indicate this in the associated entry in GatewayStatus.Addresses. + + The Addresses field represents a request for the address(es) on the + "outside of the Gateway", that traffic bound for this Gateway will use. + This could be the IP address or hostname of an external load balancer or + other networking infrastructure, or some other address that traffic will + be sent to. + + If no Addresses are specified, the implementation MAY schedule the + Gateway in an implementation-specific manner, assigning an appropriate + set of Addresses. + + The implementation MUST bind all Listeners to every GatewayAddress that + it assigns to the Gateway and add a corresponding entry in + GatewayStatus.Addresses. + + Support: Extended + + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: |- + GatewayClassName used for this Gateway. This is the name of a + GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: |- + Infrastructure defines infrastructure level attributes about this Gateway instance. + + Support: Extended + properties: + annotations: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Annotations that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + + An implementation may chose to add additional implementation-specific annotations as they see fit. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Annotation keys must be in the form of an optional + DNS subdomain prefix followed by a required name segment of + up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the annotation key's prefix must be a + DNS subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + labels: + additionalProperties: + description: |- + LabelValue is the value of a label in the Gateway API. This is used for validation + of maps such as Gateway infrastructure labels. This matches the Kubernetes + label validation rules: + * must be 63 characters or less (can be empty), + * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), + * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + + Valid values include: + + * MyValue + * my.name + * 123-my-value + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + description: |- + Labels that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + + An implementation may chose to add additional implementation-specific labels as they see fit. + + If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels + change, it SHOULD clearly warn about this behavior in documentation. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Label keys must be in the form of an optional DNS subdomain + prefix followed by a required name segment of up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the label key's prefix must be a DNS + subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the Gateway. This is optional if the + controller does not require any additional configuration. + + This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis + + The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + type: object + listeners: + description: |- + Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. + At least one Listener MUST be specified. + + Each Listener in a set of Listeners (for example, in a single Gateway) + MUST be _distinct_, in that a traffic flow MUST be able to be assigned to + exactly one listener. (This section uses "set of Listeners" rather than + "Listeners in a single Gateway" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules _also_ + apply in that case). + + Practically, this means that each listener in a set MUST have a unique + combination of Port, Protocol, and, if supported by the protocol, Hostname. + + Some combinations of port, protocol, and TLS settings are considered + Core support and MUST be supported by implementations based on their + targeted conformance profile: + + HTTP Profile + + 1. HTTPRoute, Port: 80, Protocol: HTTP + 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided + + TLS Profile + + 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough + + "Distinct" Listeners have the following property: + + The implementation can match inbound requests to a single distinct + Listener. When multiple Listeners share values for fields (for + example, two Listeners with the same Port value), the implementation + can match requests to only one of the Listeners using other + Listener fields. + + For example, the following Listener scenarios are distinct: + + 1. Multiple Listeners with the same Port that all use the "HTTP" + Protocol that all have unique Hostname values. + 2. Multiple Listeners with the same Port that use either the "HTTPS" or + "TLS" Protocol that all have unique Hostname values. + 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener + with the same Protocol has the same Port value. + + Some fields in the Listener struct have possible values that affect + whether the Listener is distinct. Hostname is particularly relevant + for HTTP or HTTPS protocols. + + When using the Hostname value to select between same-Port, same-Protocol + Listeners, the Hostname value must be different on each Listener for the + Listener to be distinct. + + When the Listeners are distinct based on Hostname, inbound request + hostnames MUST match from the most specific to least specific Hostname + values to choose the correct Listener and its associated set of Routes. + + Exact matches must be processed before wildcard matches, and wildcard + matches must be processed before fallback (empty Hostname value) + matches. For example, `"foo.example.com"` takes precedence over + `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. + + Additionally, if there are multiple wildcard entries, more specific + wildcard entries must be processed before less specific wildcard entries. + For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. + The precise definition here is that the higher the number of dots in the + hostname to the right of the wildcard character, the higher the precedence. + + The wildcard character will match any number of characters _and dots_ to + the left, however, so `"*.example.com"` will match both + `"foo.bar.example.com"` _and_ `"bar.example.com"`. + + If a set of Listeners contains Listeners that are not distinct, then those + Listeners are Conflicted, and the implementation MUST set the "Conflicted" + condition in the Listener Status to "True". + + Implementations MAY choose to accept a Gateway with some Conflicted + Listeners only if they only accept the partial Listener set that contains + no Conflicted Listeners. To put this another way, implementations may + accept a partial Listener set only if they throw out *all* the conflicting + Listeners. No picking one of the conflicting listeners as the winner. + This also means that the Gateway must have at least one non-conflicting + Listener in this case, otherwise it violates the requirement that at + least one Listener must be present. + + The implementation MUST set a "ListenersNotValid" condition on the + Gateway Status when the Gateway contains Conflicted Listeners whether or + not they accept the Gateway. That Condition SHOULD clearly + indicate in the Message which Listeners are conflicted, and which are + Accepted. Additionally, the Listener status for those listeners SHOULD + indicate which Listeners are conflicted and not Accepted. + + A Gateway's Listeners are considered "compatible" if: + + 1. They are distinct. + 2. The implementation can serve them in compliance with the Addresses + requirement that all Listeners are available on all assigned + addresses. + + Compatible combinations in Extended support are expected to vary across + implementations. A combination that is compatible for one implementation + may not be compatible for another. + + For example, an implementation that cannot serve both TCP and UDP listeners + on the same address, or cannot mix HTTPS and generic TLS listens on the same port + would not consider those cases compatible, even though they are distinct. + + Note that requests SHOULD match at most one Listener. For example, if + Listeners are defined for "foo.example.com" and "*.example.com", a + request to "foo.example.com" SHOULD only be routed using routes attached + to the "foo.example.com" Listener (and not the "*.example.com" Listener). + This concept is known as "Listener Isolation". Implementations that do + not support Listener Isolation MUST clearly document this. + + Implementations MAY merge separate Gateways onto a single set of + Addresses if all Listeners across all Gateways are compatible. + + Support: Core + items: + description: |- + Listener embodies the concept of a logical endpoint where a Gateway accepts + network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: |- + AllowedRoutes defines the types of routes that MAY be attached to a + Listener and the trusted namespaces where those Route resources MAY be + present. + + Although a client request may match multiple route rules, only one rule + may ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: + + * The most specific match as defined by the Route type. + * The oldest Route based on creation timestamp. For example, a Route with + a creation timestamp of "2020-09-08 01:02:03" is given precedence over + a Route with a creation timestamp of "2020-09-08 01:02:04". + * If everything else is equivalent, the Route appearing first in + alphabetical order (namespace/name) should be given precedence. For + example, foo/bar is given precedence over foo/baz. + + All valid rules within a Route attached to this Listener should be + implemented. Invalid Route rules can be ignored (sometimes that will mean + the full Route). If a Route rule transitions from valid to invalid, + support for that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, the rest + of the rules within that Route should still be supported. + + Support: Core + properties: + kinds: + description: |- + Kinds specifies the groups and kinds of Routes that are allowed to bind + to this Gateway Listener. When unspecified or empty, the kinds of Routes + selected are determined using the Listener protocol. + + A RouteGroupKind MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's Protocol field. + If an implementation does not support or recognize this resource type, it + MUST set the "ResolvedRefs" condition to False for this Listener with the + "InvalidRouteKinds" reason. + + Support: Core + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: |- + Namespaces indicates namespaces from which Routes may be attached to this + Listener. This is restricted to the namespace of this Gateway by default. + + Support: Core + properties: + from: + default: Same + description: |- + From indicates where Routes will be selected for this Gateway. Possible + values are: + + * All: Routes in all namespaces may be used by this Gateway. + * Selector: Routes in namespaces selected by the selector may be used by + this Gateway. + * Same: Only Routes in the same namespace may be used by this Gateway. + + Support: Core + enum: + - All + - Selector + - Same + type: string + selector: + description: |- + Selector must be specified when From is set to "Selector". In that case, + only Routes in Namespaces matching this Selector will be selected by this + Gateway. This field is ignored for other values of "From". + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: |- + Hostname specifies the virtual hostname to match for protocol types that + define this concept. When unspecified, all hostnames are matched. This + field is ignored for protocols that don't require hostname based + matching. + + Implementations MUST apply Hostname matching appropriately for each of + the following protocols: + + * TLS: The Listener Hostname MUST match the SNI. + * HTTP: The Listener Hostname MUST match the Host header of the request. + * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + protocol layers as described above. If an implementation does not + ensure that both the SNI and Host header match the Listener hostname, + it MUST clearly document that. + + For HTTPRoute and TLSRoute resources, there is an interaction with the + `spec.hostnames` array. When both listener and route specify hostnames, + there MUST be an intersection between the values for a Route to be + accepted. For more information, refer to the Route specific Hostnames + documentation. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: |- + Name is the name of the Listener. This name MUST be unique within a + Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: |- + Port is the network port. Multiple listeners may use the + same port, subject to the Listener compatibility rules. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + Protocol specifies the network protocol this listener expects to receive. + + Support: Core + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: |- + TLS is the TLS configuration for the Listener. This field is required if + the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + if the Protocol field is "HTTP", "TCP", or "UDP". + + The association of SNIs to Certificate defined in GatewayTLSConfig is + defined based on the Hostname field for this listener. + + The GatewayClass MUST use the longest matching SNI out of all + available certificates for any TLS handshake. + + Support: Core + properties: + certificateRefs: + description: |- + CertificateRefs contains a series of references to Kubernetes objects that + contains TLS certificates and private keys. These certificates are used to + establish a TLS handshake for requests that match the hostname of the + associated listener. + + A single CertificateRef to a Kubernetes Secret has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a Listener, but this behavior is implementation-specific. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + This field is required to have at least one element when the mode is set + to "Terminate" (default) and is optional otherwise. + + CertificateRefs can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + + Support: Implementation-specific (More than one reference or other resource types) + items: + description: |- + SecretObjectReference identifies an API object including its namespace, + defaulting to Secret. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: |- + Mode defines the TLS behavior for the TLS session initiated by the client. + There are two possible modes: + + - Terminate: The TLS session between the downstream client and the + Gateway is terminated at the Gateway. This mode requires certificates + to be specified in some way, such as populating the certificateRefs + field. + - Passthrough: The TLS session is NOT terminated by the Gateway. This + implies that the Gateway can't decipher the TLS stream except for + the ClientHello message of the TLS protocol. The certificateRefs field + is ignored in this mode. + + Support: Core + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: tls mode must be Terminate for protocol HTTPS + rule: 'self.all(l, (l.protocol == ''HTTPS'' && has(l.tls)) ? (l.tls.mode + == '''' || l.tls.mode == ''Terminate'') : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: |+ + Addresses lists the network addresses that have been bound to the + Gateway. + + This list may differ from the addresses provided in the spec under some + conditions: + + * no addresses are specified, all addresses are dynamically assigned + * a combination of specified and dynamic addresses are assigned + * a specified address was unusable (e.g. already in use) + + items: + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: |- + Conditions describe the current conditions of the Gateway. + + Implementations should prefer to express Gateway conditions + using the `GatewayConditionType` and `GatewayConditionReason` + constants so that operators and tools can converge on a common + vocabulary to describe Gateway state. + + Known condition types are: + + * "Accepted" + * "Programmed" + * "Ready" + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: |- + AttachedRoutes represents the total number of Routes that have been + successfully attached to this Listener. + + Successful attachment of a Route to a Listener is based solely on the + combination of the AllowedRoutes field on the corresponding Listener + and the Route's ParentRefs field. A Route is successfully attached to + a Listener when it is selected by the Listener's AllowedRoutes field + AND the Route has a valid ParentRef selecting the whole Gateway + resource or a specific Listener as a parent resource (more detail on + attachment semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does not impact + successful attachment, i.e. the AttachedRoutes field count MUST be set + for Listeners with condition Accepted: false and MUST count successfully + attached Routes that may themselves have Accepted: false conditions. + + Uses for this field include troubleshooting Route attachment and + measuring blast radius/impact of changes to a Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: |- + SupportedKinds is the list indicating the Kinds supported by this + listener. This MUST represent the kinds an implementation supports for + that Listener configuration. + + If kinds are specified in Spec that are not supported, they MUST NOT + appear in this list and an implementation MUST set the "ResolvedRefs" + condition to "False" with the "InvalidRouteKinds" reason. If both valid + and invalid Route kinds are specified, the implementation MUST + reference the valid Route kinds that have been specified. + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + Gateway represents an instance of a service-traffic handling infrastructure + by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: |+ + Addresses requested for this Gateway. This is optional and behavior can + depend on the implementation. If a value is set in the spec and the + requested address is invalid or unavailable, the implementation MUST + indicate this in the associated entry in GatewayStatus.Addresses. + + The Addresses field represents a request for the address(es) on the + "outside of the Gateway", that traffic bound for this Gateway will use. + This could be the IP address or hostname of an external load balancer or + other networking infrastructure, or some other address that traffic will + be sent to. + + If no Addresses are specified, the implementation MAY schedule the + Gateway in an implementation-specific manner, assigning an appropriate + set of Addresses. + + The implementation MUST bind all Listeners to every GatewayAddress that + it assigns to the Gateway and add a corresponding entry in + GatewayStatus.Addresses. + + Support: Extended + + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: |- + GatewayClassName used for this Gateway. This is the name of a + GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: |- + Infrastructure defines infrastructure level attributes about this Gateway instance. + + Support: Extended + properties: + annotations: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Annotations that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + + An implementation may chose to add additional implementation-specific annotations as they see fit. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Annotation keys must be in the form of an optional + DNS subdomain prefix followed by a required name segment of + up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the annotation key's prefix must be a + DNS subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + labels: + additionalProperties: + description: |- + LabelValue is the value of a label in the Gateway API. This is used for validation + of maps such as Gateway infrastructure labels. This matches the Kubernetes + label validation rules: + * must be 63 characters or less (can be empty), + * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), + * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + + Valid values include: + + * MyValue + * my.name + * 123-my-value + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + description: |- + Labels that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + + An implementation may chose to add additional implementation-specific labels as they see fit. + + If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels + change, it SHOULD clearly warn about this behavior in documentation. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Label keys must be in the form of an optional DNS subdomain + prefix followed by a required name segment of up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the label key's prefix must be a DNS + subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the Gateway. This is optional if the + controller does not require any additional configuration. + + This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis + + The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + type: object + listeners: + description: |- + Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. + At least one Listener MUST be specified. + + Each Listener in a set of Listeners (for example, in a single Gateway) + MUST be _distinct_, in that a traffic flow MUST be able to be assigned to + exactly one listener. (This section uses "set of Listeners" rather than + "Listeners in a single Gateway" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules _also_ + apply in that case). + + Practically, this means that each listener in a set MUST have a unique + combination of Port, Protocol, and, if supported by the protocol, Hostname. + + Some combinations of port, protocol, and TLS settings are considered + Core support and MUST be supported by implementations based on their + targeted conformance profile: + + HTTP Profile + + 1. HTTPRoute, Port: 80, Protocol: HTTP + 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided + + TLS Profile + + 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough + + "Distinct" Listeners have the following property: + + The implementation can match inbound requests to a single distinct + Listener. When multiple Listeners share values for fields (for + example, two Listeners with the same Port value), the implementation + can match requests to only one of the Listeners using other + Listener fields. + + For example, the following Listener scenarios are distinct: + + 1. Multiple Listeners with the same Port that all use the "HTTP" + Protocol that all have unique Hostname values. + 2. Multiple Listeners with the same Port that use either the "HTTPS" or + "TLS" Protocol that all have unique Hostname values. + 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener + with the same Protocol has the same Port value. + + Some fields in the Listener struct have possible values that affect + whether the Listener is distinct. Hostname is particularly relevant + for HTTP or HTTPS protocols. + + When using the Hostname value to select between same-Port, same-Protocol + Listeners, the Hostname value must be different on each Listener for the + Listener to be distinct. + + When the Listeners are distinct based on Hostname, inbound request + hostnames MUST match from the most specific to least specific Hostname + values to choose the correct Listener and its associated set of Routes. + + Exact matches must be processed before wildcard matches, and wildcard + matches must be processed before fallback (empty Hostname value) + matches. For example, `"foo.example.com"` takes precedence over + `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. + + Additionally, if there are multiple wildcard entries, more specific + wildcard entries must be processed before less specific wildcard entries. + For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. + The precise definition here is that the higher the number of dots in the + hostname to the right of the wildcard character, the higher the precedence. + + The wildcard character will match any number of characters _and dots_ to + the left, however, so `"*.example.com"` will match both + `"foo.bar.example.com"` _and_ `"bar.example.com"`. + + If a set of Listeners contains Listeners that are not distinct, then those + Listeners are Conflicted, and the implementation MUST set the "Conflicted" + condition in the Listener Status to "True". + + Implementations MAY choose to accept a Gateway with some Conflicted + Listeners only if they only accept the partial Listener set that contains + no Conflicted Listeners. To put this another way, implementations may + accept a partial Listener set only if they throw out *all* the conflicting + Listeners. No picking one of the conflicting listeners as the winner. + This also means that the Gateway must have at least one non-conflicting + Listener in this case, otherwise it violates the requirement that at + least one Listener must be present. + + The implementation MUST set a "ListenersNotValid" condition on the + Gateway Status when the Gateway contains Conflicted Listeners whether or + not they accept the Gateway. That Condition SHOULD clearly + indicate in the Message which Listeners are conflicted, and which are + Accepted. Additionally, the Listener status for those listeners SHOULD + indicate which Listeners are conflicted and not Accepted. + + A Gateway's Listeners are considered "compatible" if: + + 1. They are distinct. + 2. The implementation can serve them in compliance with the Addresses + requirement that all Listeners are available on all assigned + addresses. + + Compatible combinations in Extended support are expected to vary across + implementations. A combination that is compatible for one implementation + may not be compatible for another. + + For example, an implementation that cannot serve both TCP and UDP listeners + on the same address, or cannot mix HTTPS and generic TLS listens on the same port + would not consider those cases compatible, even though they are distinct. + + Note that requests SHOULD match at most one Listener. For example, if + Listeners are defined for "foo.example.com" and "*.example.com", a + request to "foo.example.com" SHOULD only be routed using routes attached + to the "foo.example.com" Listener (and not the "*.example.com" Listener). + This concept is known as "Listener Isolation". Implementations that do + not support Listener Isolation MUST clearly document this. + + Implementations MAY merge separate Gateways onto a single set of + Addresses if all Listeners across all Gateways are compatible. + + Support: Core + items: + description: |- + Listener embodies the concept of a logical endpoint where a Gateway accepts + network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: |- + AllowedRoutes defines the types of routes that MAY be attached to a + Listener and the trusted namespaces where those Route resources MAY be + present. + + Although a client request may match multiple route rules, only one rule + may ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: + + * The most specific match as defined by the Route type. + * The oldest Route based on creation timestamp. For example, a Route with + a creation timestamp of "2020-09-08 01:02:03" is given precedence over + a Route with a creation timestamp of "2020-09-08 01:02:04". + * If everything else is equivalent, the Route appearing first in + alphabetical order (namespace/name) should be given precedence. For + example, foo/bar is given precedence over foo/baz. + + All valid rules within a Route attached to this Listener should be + implemented. Invalid Route rules can be ignored (sometimes that will mean + the full Route). If a Route rule transitions from valid to invalid, + support for that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, the rest + of the rules within that Route should still be supported. + + Support: Core + properties: + kinds: + description: |- + Kinds specifies the groups and kinds of Routes that are allowed to bind + to this Gateway Listener. When unspecified or empty, the kinds of Routes + selected are determined using the Listener protocol. + + A RouteGroupKind MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's Protocol field. + If an implementation does not support or recognize this resource type, it + MUST set the "ResolvedRefs" condition to False for this Listener with the + "InvalidRouteKinds" reason. + + Support: Core + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: |- + Namespaces indicates namespaces from which Routes may be attached to this + Listener. This is restricted to the namespace of this Gateway by default. + + Support: Core + properties: + from: + default: Same + description: |- + From indicates where Routes will be selected for this Gateway. Possible + values are: + + * All: Routes in all namespaces may be used by this Gateway. + * Selector: Routes in namespaces selected by the selector may be used by + this Gateway. + * Same: Only Routes in the same namespace may be used by this Gateway. + + Support: Core + enum: + - All + - Selector + - Same + type: string + selector: + description: |- + Selector must be specified when From is set to "Selector". In that case, + only Routes in Namespaces matching this Selector will be selected by this + Gateway. This field is ignored for other values of "From". + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: |- + Hostname specifies the virtual hostname to match for protocol types that + define this concept. When unspecified, all hostnames are matched. This + field is ignored for protocols that don't require hostname based + matching. + + Implementations MUST apply Hostname matching appropriately for each of + the following protocols: + + * TLS: The Listener Hostname MUST match the SNI. + * HTTP: The Listener Hostname MUST match the Host header of the request. + * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + protocol layers as described above. If an implementation does not + ensure that both the SNI and Host header match the Listener hostname, + it MUST clearly document that. + + For HTTPRoute and TLSRoute resources, there is an interaction with the + `spec.hostnames` array. When both listener and route specify hostnames, + there MUST be an intersection between the values for a Route to be + accepted. For more information, refer to the Route specific Hostnames + documentation. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: |- + Name is the name of the Listener. This name MUST be unique within a + Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: |- + Port is the network port. Multiple listeners may use the + same port, subject to the Listener compatibility rules. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + Protocol specifies the network protocol this listener expects to receive. + + Support: Core + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: |- + TLS is the TLS configuration for the Listener. This field is required if + the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + if the Protocol field is "HTTP", "TCP", or "UDP". + + The association of SNIs to Certificate defined in GatewayTLSConfig is + defined based on the Hostname field for this listener. + + The GatewayClass MUST use the longest matching SNI out of all + available certificates for any TLS handshake. + + Support: Core + properties: + certificateRefs: + description: |- + CertificateRefs contains a series of references to Kubernetes objects that + contains TLS certificates and private keys. These certificates are used to + establish a TLS handshake for requests that match the hostname of the + associated listener. + + A single CertificateRef to a Kubernetes Secret has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a Listener, but this behavior is implementation-specific. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + This field is required to have at least one element when the mode is set + to "Terminate" (default) and is optional otherwise. + + CertificateRefs can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + + Support: Implementation-specific (More than one reference or other resource types) + items: + description: |- + SecretObjectReference identifies an API object including its namespace, + defaulting to Secret. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: |- + Mode defines the TLS behavior for the TLS session initiated by the client. + There are two possible modes: + + - Terminate: The TLS session between the downstream client and the + Gateway is terminated at the Gateway. This mode requires certificates + to be specified in some way, such as populating the certificateRefs + field. + - Passthrough: The TLS session is NOT terminated by the Gateway. This + implies that the Gateway can't decipher the TLS stream except for + the ClientHello message of the TLS protocol. The certificateRefs field + is ignored in this mode. + + Support: Core + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: tls mode must be Terminate for protocol HTTPS + rule: 'self.all(l, (l.protocol == ''HTTPS'' && has(l.tls)) ? (l.tls.mode + == '''' || l.tls.mode == ''Terminate'') : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: |+ + Addresses lists the network addresses that have been bound to the + Gateway. + + This list may differ from the addresses provided in the spec under some + conditions: + + * no addresses are specified, all addresses are dynamically assigned + * a combination of specified and dynamic addresses are assigned + * a specified address was unusable (e.g. already in use) + + items: + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: |- + Conditions describe the current conditions of the Gateway. + + Implementations should prefer to express Gateway conditions + using the `GatewayConditionType` and `GatewayConditionReason` + constants so that operators and tools can converge on a common + vocabulary to describe Gateway state. + + Known condition types are: + + * "Accepted" + * "Programmed" + * "Ready" + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: |- + AttachedRoutes represents the total number of Routes that have been + successfully attached to this Listener. + + Successful attachment of a Route to a Listener is based solely on the + combination of the AllowedRoutes field on the corresponding Listener + and the Route's ParentRefs field. A Route is successfully attached to + a Listener when it is selected by the Listener's AllowedRoutes field + AND the Route has a valid ParentRef selecting the whole Gateway + resource or a specific Listener as a parent resource (more detail on + attachment semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does not impact + successful attachment, i.e. the AttachedRoutes field count MUST be set + for Listeners with condition Accepted: false and MUST count successfully + attached Routes that may themselves have Accepted: false conditions. + + Uses for this field include troubleshooting Route attachment and + measuring blast radius/impact of changes to a Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: |- + SupportedKinds is the list indicating the Kinds supported by this + listener. This MUST represent the kinds an implementation supports for + that Listener configuration. + + If kinds are specified in Spec that are not supported, they MUST NOT + appear in this list and an implementation MUST set the "ResolvedRefs" + condition to "False" with the "InvalidRouteKinds" reason. If both valid + and invalid Route kinds are specified, the implementation MUST + reference the valid Route kinds that have been specified. + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.1 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: grpcroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GRPCRoute + listKind: GRPCRouteList + plural: grpcroutes + singular: grpcroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + GRPCRoute provides a way to route gRPC requests. This includes the capability + to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. + Filters can be used to specify additional processing steps. Backends specify + where matching requests will be routed. + + GRPCRoute falls under extended support within the Gateway API. Within the + following specification, the word "MUST" indicates that an implementation + supporting GRPCRoute must conform to the indicated requirement, but an + implementation not supporting this route type need not follow the requirement + unless explicitly indicated. + + Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` MUST + accept HTTP/2 connections without an initial upgrade from HTTP/1.1, i.e. via + ALPN. If the implementation does not support this, then it MUST set the + "Accepted" condition to "False" for the affected listener with a reason of + "UnsupportedProtocol". Implementations MAY also accept HTTP/2 connections + with an upgrade from HTTP/1. + + Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` MUST + support HTTP/2 over cleartext TCP (h2c, + https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial + upgrade from HTTP/1.1, i.e. with prior knowledge + (https://www.rfc-editor.org/rfc/rfc7540#section-3.4). If the implementation + does not support this, then it MUST set the "Accepted" condition to "False" + for the affected listener with a reason of "UnsupportedProtocol". + Implementations MAY also accept HTTP/2 connections with an upgrade from + HTTP/1, i.e. without prior knowledge. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GRPCRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames to match against the GRPC + Host header to select a GRPCRoute to process the request. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label MUST appear by itself as the first label. + + If a hostname is specified by both the Listener and GRPCRoute, there + MUST be at least one intersecting hostname for the GRPCRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches GRPCRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches GRPCRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `test.example.com` and `*.example.com` would both match. On the other + hand, `example.com` and `test.example.net` would not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and GRPCRoute have specified hostnames, any + GRPCRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + GRPCRoute specified `test.example.com` and `test.example.net`, + `test.example.net` MUST NOT be considered for a match. + + If both the Listener and GRPCRoute have specified hostnames, and none + match with the criteria above, then the GRPCRoute MUST NOT be accepted by + the implementation. The implementation MUST raise an 'Accepted' Condition + with a status of `False` in the corresponding RouteParentStatus. + + If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + Listener and that listener already has another Route (B) of the other + type attached and the intersection of the hostnames of A and B is + non-empty, then the implementation MUST accept exactly one of these two + routes, determined by the following criteria, in order: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + The rejected Route MUST raise an 'Accepted' condition with a status of + 'False' in the corresponding RouteParentStatus. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + description: |+ + Rules are a list of GRPC matchers, filters and actions. + + items: + description: |- + GRPCRouteRule defines the semantics for matching a gRPC request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive an `UNAVAILABLE` status. + + See the GRPCBackendRef definition for the rules about what makes a single + GRPCBackendRef invalid. + + When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive an `UNAVAILABLE` status. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. + Implementations may choose how that 50 percent is determined. + + Support: Core for Kubernetes Service + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level MUST be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in GRPCRouteRule.) + items: + description: |- + GRPCRouteFilter defines processing steps that must be completed during the + request or response lifecycle. GRPCRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + Support: Implementation-specific + + This filter can be used multiple times within the same rule. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |+ + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations supporting GRPCRoute MUST support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` MUST be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations that support + GRPCRoute. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + If an implementation can not support a combination of filters, it must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + GRPCRouteFilter defines processing steps that must be completed during the + request or response lifecycle. GRPCRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + Support: Implementation-specific + + This filter can be used multiple times within the same rule. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |+ + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations supporting GRPCRoute MUST support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` MUST be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + matches: + description: |- + Matches define conditions used for matching the rule against incoming + gRPC requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - method: + service: foo.bar + headers: + values: + version: 2 + - method: + service: foo.bar.v2 + ``` + + For a request to match against this rule, it MUST satisfy + EITHER of the two conditions: + + - service of foo.bar AND contains the header `version: 2` + - service of foo.bar.v2 + + See the documentation for GRPCRouteMatch on how to specify multiple + match conditions to be ANDed together. + + If no matches are specified, the implementation MUST match every gRPC request. + + Proxy or Load Balancer routing configuration generated from GRPCRoutes + MUST prioritize rules based on the following criteria, continuing on + ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. + Precedence MUST be given to the rule with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + * Characters in a matching service. + * Characters in a matching method. + * Header matches. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within the Route that has been given precedence, + matching precedence MUST be granted to the first matching rule meeting + the above criteria. + items: + description: |- + GRPCRouteMatch defines the predicate used to match requests to a given + action. Multiple match types are ANDed together, i.e. the match will + evaluate to true only if all conditions are satisfied. + + For example, the match below will match a gRPC request only if its service + is `foo` AND it contains the `version: v1` header: + + ``` + matches: + - method: + type: Exact + service: "foo" + headers: + - name: "version" + value "v1" + + ``` + properties: + headers: + description: |- + Headers specifies gRPC request header matchers. Multiple match values are + ANDed together, meaning, a request MUST match all the specified headers + to select the route. + items: + description: |- + GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request + headers. + properties: + name: + description: |- + Name is the name of the gRPC Header to be matched. + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: Type specifies how to match against + the value of the header. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of the gRPC Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies a gRPC request service/method matcher. If this field is + not specified, all services and methods will match. + properties: + method: + description: |- + Value of the method to match against. If left empty or omitted, will + match all services. + + At least one of Service and Method MUST be a non-empty string. + maxLength: 1024 + type: string + service: + description: |- + Value of the service to match against. If left empty or omitted, will + match any service. + + At least one of Service and Method MUST be a non-empty string. + maxLength: 1024 + type: string + type: + default: Exact + description: |- + Type specifies how to match against the service and/or method. + Support: Core (Exact with service and method specified) + + Support: Implementation-specific (Exact with method specified but no service specified) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - RegularExpression + type: string + type: object + x-kubernetes-validations: + - message: One or both of 'service' or 'method' must be + specified + rule: 'has(self.type) ? has(self.service) || has(self.method) + : true' + - message: service must only contain valid characters + (matching ^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.service) ? self.service.matches(r"""^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$"""): + true' + - message: method must only contain valid characters (matching + ^[A-Za-z_][A-Za-z_0-9]*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.method) ? self.method.matches(r"""^[A-Za-z_][A-Za-z_0-9]*$"""): + true' + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? (has(self[0].matches) ? self[0].matches.size() + : 0) : 0) + (self.size() > 1 ? (has(self[1].matches) ? self[1].matches.size() + : 0) : 0) + (self.size() > 2 ? (has(self[2].matches) ? self[2].matches.size() + : 0) : 0) + (self.size() > 3 ? (has(self[3].matches) ? self[3].matches.size() + : 0) : 0) + (self.size() > 4 ? (has(self[4].matches) ? self[4].matches.size() + : 0) : 0) + (self.size() > 5 ? (has(self[5].matches) ? self[5].matches.size() + : 0) : 0) + (self.size() > 6 ? (has(self[6].matches) ? self[6].matches.size() + : 0) : 0) + (self.size() > 7 ? (has(self[7].matches) ? self[7].matches.size() + : 0) : 0) + (self.size() > 8 ? (has(self[8].matches) ? self[8].matches.size() + : 0) : 0) + (self.size() > 9 ? (has(self[9].matches) ? self[9].matches.size() + : 0) : 0) + (self.size() > 10 ? (has(self[10].matches) ? self[10].matches.size() + : 0) : 0) + (self.size() > 11 ? (has(self[11].matches) ? self[11].matches.size() + : 0) : 0) + (self.size() > 12 ? (has(self[12].matches) ? self[12].matches.size() + : 0) : 0) + (self.size() > 13 ? (has(self[13].matches) ? self[13].matches.size() + : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() + : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() + : 0) : 0) <= 128' + type: object + status: + description: Status defines the current state of GRPCRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.1 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames that should match against the HTTP Host + header to select a HTTPRoute used to process the request. Implementations + MUST ignore any port value specified in the HTTP Host header while + performing a match and (absent of any applicable header modification + configuration) MUST forward this header unmodified to the backend. + + Valid values for Hostnames are determined by RFC 1123 definition of a + hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + If a hostname is specified by both the Listener and HTTPRoute, there + must be at least one intersecting hostname for the HTTPRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` would + all match. On the other hand, `example.com` and `test.example.net` would + not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and HTTPRoute have specified hostnames, any + HTTPRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status of + `False` in the corresponding RouteParentStatus. + + In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. + overlapping wildcard matching and exact matching hostnames), precedence must + be given to rules from the HTTPRoute with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + + If ties exist across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: |+ + Rules are a list of HTTP matchers, filters and actions. + + items: + description: |- + HTTPRouteRule defines semantics for matching an HTTP request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive a 500 status code. + + See the HTTPBackendRef definition for the rules about what makes a single + HTTPBackendRef invalid. + + When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive a 500 status code. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic must receive a 500. Implementations may + choose how that 50 percent is determined. + + When a HTTPBackendRef refers to a Service that has no ready endpoints, + implementations SHOULD return a 503 for requests to that backend instead. + If an implementation chooses to do this, all of the above rules for 500 responses + MUST also apply for responses that return a 503. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level should be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in HTTPRouteRule.) + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + Wherever possible, implementations SHOULD implement filters in the order + they are specified. + + Implementations MAY choose to implement this ordering strictly, rejecting + any combination or order of filters that can not be supported. If implementations + choose a strict interpretation of filter ordering, they MUST clearly document + that behavior. + + To reject an invalid combination or order of filters, implementations SHOULD + consider the Route Rules with this configuration invalid. If all Route Rules + in a Route are invalid, the entire Route would be considered invalid. If only + a portion of Route Rules are invalid, implementations MUST set the + "PartiallyInvalid" condition for the Route. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + Note: The precedence of RegularExpression path matches are implementation-specific. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given\naction. Multiple match types + are ANDed together, i.e. the match will\nevaluate to true + only if all conditions are satisfied.\n\nFor example, the + match below will match a HTTP request only if its path\nstarts + with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t + \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t + \ value \"v1\"\n\n```" + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + Support: Core (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies HTTP method matcher. + When specified, this route will be matched only if the request has the + specified method. + + Support: Extended + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: |- + Path specifies a HTTP request path matcher. If this field is not + specified, a default prefix match on the "/" path is provided. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + Support: Extended (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + timeouts: + description: |- + Timeouts defines the timeouts that can be configured for an HTTP request. + + Support: Extended + properties: + backendRequest: + description: |- + BackendRequest specifies a timeout for an individual request from the gateway + to a backend. This covers the time from when the request first starts being + sent from the gateway to when the full response has been received from the backend. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + An entire client HTTP transaction with a gateway, covered by the Request timeout, + may result in more than one call from the gateway to the destination backend, + for example, if automatic retries are supported. + + The value of BackendRequest must be a Gateway API Duration string as defined by + GEP-2257. When this field is unspecified, its behavior is implementation-specific; + when specified, the value of BackendRequest must be no more than the value of the + Request timeout (since the Request timeout encompasses the BackendRequest timeout). + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: |- + Request specifies the maximum duration for a gateway to respond to an HTTP request. + If the gateway has not been able to respond before this deadline is met, the gateway + MUST return a timeout error. + + For example, setting the `rules.timeouts.request` field to the value `10s` in an + `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + to complete. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + This timeout is intended to cover as close to the whole request-response transaction + as possible although an implementation MAY choose to start the timeout after the entire + request stream has been received instead of immediately after the transaction is + initiated by the client. + + The value of Request is a Gateway API Duration string as defined by GEP-2257. When this + field is unspecified, request timeout behavior is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() + > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() + : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() + > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() + : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() + > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() + : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() + > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() + : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() + > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() + : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames that should match against the HTTP Host + header to select a HTTPRoute used to process the request. Implementations + MUST ignore any port value specified in the HTTP Host header while + performing a match and (absent of any applicable header modification + configuration) MUST forward this header unmodified to the backend. + + Valid values for Hostnames are determined by RFC 1123 definition of a + hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + If a hostname is specified by both the Listener and HTTPRoute, there + must be at least one intersecting hostname for the HTTPRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` would + all match. On the other hand, `example.com` and `test.example.net` would + not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and HTTPRoute have specified hostnames, any + HTTPRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status of + `False` in the corresponding RouteParentStatus. + + In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. + overlapping wildcard matching and exact matching hostnames), precedence must + be given to rules from the HTTPRoute with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + + If ties exist across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: |+ + Rules are a list of HTTP matchers, filters and actions. + + items: + description: |- + HTTPRouteRule defines semantics for matching an HTTP request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive a 500 status code. + + See the HTTPBackendRef definition for the rules about what makes a single + HTTPBackendRef invalid. + + When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive a 500 status code. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic must receive a 500. Implementations may + choose how that 50 percent is determined. + + When a HTTPBackendRef refers to a Service that has no ready endpoints, + implementations SHOULD return a 503 for requests to that backend instead. + If an implementation chooses to do this, all of the above rules for 500 responses + MUST also apply for responses that return a 503. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level should be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in HTTPRouteRule.) + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + Wherever possible, implementations SHOULD implement filters in the order + they are specified. + + Implementations MAY choose to implement this ordering strictly, rejecting + any combination or order of filters that can not be supported. If implementations + choose a strict interpretation of filter ordering, they MUST clearly document + that behavior. + + To reject an invalid combination or order of filters, implementations SHOULD + consider the Route Rules with this configuration invalid. If all Route Rules + in a Route are invalid, the entire Route would be considered invalid. If only + a portion of Route Rules are invalid, implementations MUST set the + "PartiallyInvalid" condition for the Route. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + Note: The precedence of RegularExpression path matches are implementation-specific. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given\naction. Multiple match types + are ANDed together, i.e. the match will\nevaluate to true + only if all conditions are satisfied.\n\nFor example, the + match below will match a HTTP request only if its path\nstarts + with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t + \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t + \ value \"v1\"\n\n```" + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + Support: Core (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies HTTP method matcher. + When specified, this route will be matched only if the request has the + specified method. + + Support: Extended + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: |- + Path specifies a HTTP request path matcher. If this field is not + specified, a default prefix match on the "/" path is provided. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + Support: Extended (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + timeouts: + description: |- + Timeouts defines the timeouts that can be configured for an HTTP request. + + Support: Extended + properties: + backendRequest: + description: |- + BackendRequest specifies a timeout for an individual request from the gateway + to a backend. This covers the time from when the request first starts being + sent from the gateway to when the full response has been received from the backend. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + An entire client HTTP transaction with a gateway, covered by the Request timeout, + may result in more than one call from the gateway to the destination backend, + for example, if automatic retries are supported. + + The value of BackendRequest must be a Gateway API Duration string as defined by + GEP-2257. When this field is unspecified, its behavior is implementation-specific; + when specified, the value of BackendRequest must be no more than the value of the + Request timeout (since the Request timeout encompasses the BackendRequest timeout). + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: |- + Request specifies the maximum duration for a gateway to respond to an HTTP request. + If the gateway has not been able to respond before this deadline is met, the gateway + MUST return a timeout error. + + For example, setting the `rules.timeouts.request` field to the value `10s` in an + `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + to complete. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + This timeout is intended to cover as close to the whole request-response transaction + as possible although an implementation MAY choose to start the timeout after the entire + request stream has been received instead of immediately after the transaction is + initiated by the client. + + The value of Request is a Gateway API Duration string as defined by GEP-2257. When this + field is unspecified, request timeout behavior is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() + > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() + : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() + > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() + : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() + > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() + : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() + > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() + : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() + > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() + : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.1 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: referencegrants.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants + shortNames: + - refgrant + singular: referencegrant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + ReferenceGrant identifies kinds of resources in other namespaces that are + trusted to reference the specified kinds of resources in the same namespace + as the policy. + + Each ReferenceGrant can be used to represent a unique trust relationship. + Additional Reference Grants can be used to add to the set of trusted + sources of inbound references for the namespace they are defined within. + + All cross-namespace references in Gateway API (with the exception of cross-namespace + Gateway-route attachment) require a ReferenceGrant. + + ReferenceGrant is a form of runtime verification allowing users to assert + which cross-namespace object references are permitted. Implementations that + support ReferenceGrant MUST NOT permit cross-namespace references which have + no grant, and MUST respond to the removal of a grant by revoking the access + that the grant allowed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: |- + From describes the trusted namespaces and kinds that can reference the + resources described in "To". Each entry in this list MUST be considered + to be an additional place that references can be valid from, or to put + this another way, entries MUST be combined using OR. + + Support: Core + items: + description: ReferenceGrantFrom describes trusted namespaces and + kinds. + properties: + group: + description: |- + Group is the group of the referent. + When empty, the Kubernetes core API group is inferred. + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: |- + Kind is the kind of the referent. Although implementations may support + additional resources, the following types are part of the "Core" + support level for this field. + + When used to permit a SecretObjectReference: + + * Gateway + + When used to permit a BackendObjectReference: + + * GRPCRoute + * HTTPRoute + * TCPRoute + * TLSRoute + * UDPRoute + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: |- + To describes the resources that may be referenced by the resources + described in "From". Each entry in this list MUST be considered to be an + additional place that references can be valid to, or to put this another + way, entries MUST be combined using OR. + + Support: Core + items: + description: |- + ReferenceGrantTo describes what Kinds are allowed as targets of the + references. + properties: + group: + description: |- + Group is the group of the referent. + When empty, the Kubernetes core API group is inferred. + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: |- + Kind is the kind of the referent. Although implementations may support + additional resources, the following types are part of the "Core" + support level for this field: + + * Secret when used to permit a SecretObjectReference + * Service when used to permit a BackendObjectReference + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. When unspecified, this policy + refers to all resources of the specified Group and Kind in the local + namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/traefik-crds/kustomization.yaml b/traefik-crds/kustomization.yaml index 3806a9de8..a615713e7 100644 --- a/traefik-crds/kustomization.yaml +++ b/traefik-crds/kustomization.yaml @@ -2,8 +2,8 @@ kind: Kustomization apiVersion: kustomize.config.k8s.io/v1beta1 resources: - # curl -o crds-files/gateway/gateway-standard-install.yaml -L https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml - - crds-files/gateway/gateway-standard-install.yaml + # curl -o crds-files/gateway_api/gateway-standard-install.yaml -L https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml + - crds-files/gateway_api/gateway-standard-install.yaml - crds-files/hub.traefik.io_accesscontrolpolicies.yaml - crds-files/hub.traefik.io_aiservices.yaml - crds-files/hub.traefik.io_apiaccesses.yaml diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json new file mode 100644 index 000000000..1fe1ef7d9 --- /dev/null +++ b/traefik-crds/values.schema.json @@ -0,0 +1,25 @@ +{ + "$id": "https://traefik.io/traefik-crds-helm-chart.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": true, + "description": "The Cloud Native Application Proxy", + "properties": { + "gateway_api": { + "type": [ + "boolean" + ] + }, + "hub": { + "type": [ + "boolean" + ] + }, + "traefik": { + "type": [ + "boolean" + ] + } + }, + "title": "Traefik CRDs Helm Chart", + "type": "object" +} diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index 6daca116a..c6ad93429 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,3 +1,3 @@ -traefik: false -gateway_api: false -hub: false +traefik: false # @schema type:[boolean] +gateway_api: false # @schema type:[boolean] +hub: false # @schema type:[boolean] diff --git a/.schema.yaml b/traefik/.schema.yaml similarity index 79% rename from .schema.yaml rename to traefik/.schema.yaml index 84bc794f5..c1d47dedd 100644 --- a/.schema.yaml +++ b/traefik/.schema.yaml @@ -1,10 +1,10 @@ # Required input: - - traefik/values.yaml + - values.yaml draft: 2020 indent: 4 -output: traefik/values.schema.json +output: values.schema.json schemaRoot: id: https://traefik.io/traefik-helm-chart.schema.json diff --git a/traefik/charts/traefik-crds-0.0.1.tgz b/traefik/charts/traefik-crds-0.0.1.tgz index 81b81708ab0708c9690920b0da69b75c9afef055..b27ef6d26118b4db53c5a9028986c769f37576b9 100644 GIT binary patch delta 110019 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

s(0?|9~kox82?-|cQ5 zC+{uEYr*Z@$k~QuI_e>Rmy_1?#&wnlQqF>tA3_8vU2VWSKuQfZd*!+kbN4%b1;r|` z8b}p5Og)@2gDU!0I7}Rpt#L76?xR@a%!Qs4CrE>6HPFlyCEt5kaw+k9~Tks^veq?`{xpysxY~t zZeHI?2-Uqmsw-A+hi(qNMWPxwGn)+v?+`6yI%#enuf1TSscm}mhNCn<37qfPS>{rW zhzXB<3!AgZ((4q0o!wh)DxKE&h#HJvaQKPMf4-J2IVez+_HPRA)5J)eYlZFLfgHsInKAj$qTK2fGYd2xC3K$1J6>o~xA-QO zguL}t{+v^}ge+L~V^)g0IZjhp*L*>c<`&8JMd>-7~+(+O}>1yK=F!fG(!txNB-gYZ+ z@MDr4lLu9dNZJq3plX_ugB)m6#N8xib1UGMV%>hw!8ix{W0#wc#m79x0xq#Xj zwwYW%@tIr57=kp@ee20d5(R+kt-`#QnF4bj&xp98tHCdk)mdCW=U*5w+GSvb8e|a9 zUEP(F-tD=WTq4RUX5+5fk-No5iLNn$Y69IvC;s=LRTsH>^B*49LA0b)5?5hY9M;U5 zU`g2dN7y8y3v@ssEV+l*guo0QC+m~6oEXp;Q$ra^Ap!GH2kkNsqf+ybH&~xy59ukP zsQs0C!PCt(h_&#!Gg8o3#Y-Huo3xVKgc4*yimw4OrPi1X72}x_`0dkUo_$;d;SbLr z#xW~!*j0#F&bxcNlh(fO+6U}63)Vczf<97&LJKhX%oLK+GJC3gZ|cx7j|=pl zsY7?R0q0;Tq+?O^WaWvc)K&0LA5@)7c|GOxy5q2r=bQl}v1BryW0G2H;zU{WFIE7B zL&!u1McCd*5;8gp_8o;Kw`!a#_jSTyEP%nGS2>`~7Mi!Px92KX!8Pkbbxokp5pJz? z%k{G$GX-ds&rm7;`~$Pc(@}i0N+y9XlB=`ZlF1HbA4|G1lbN5;dv~;zm#J7_aXTIC zqjscp^+kj;kziJK7>Jii%pa;uY$_IR_=Y<11T?(0Acn_H%H%pKlQb~(!pV$f=H-e> z6^59oXX2r8;~s5|Cn(F9y3F9NuvdS_2A$EPZPn#=E|Ne}4nf(xfy&)f;wL z1D}r^#!=0!(CgfJ27x~bj+Q}bV)_65OdAs_4&ji%GZ2HmDv*zaWMK+cl$3yXebEe4 zmee>`&ne|<=y-Rl@KpohH9?ds8)?gUMb}Z^;_GXc-#p2$NbHbTs8@bDt5mz@W9>ej z>;NQA{Oa_N#2X#Wt|Adwn}_zard2XOTU%#0Y_{4oHwOQ^Wq#ZKgnsV!XTAN&oGFC0 zeK}PlXcLrbL49h(m%I;hCAjH5I*Z;74c6&TZolA@IMq)EXvHf{FdBVJv9r!Am-F3W zy&IU>R7DU45>N^1YCj``k*OFs5nJ3D4EryE>7zZt)?q?B^ zPmLa!;yR$41|gp!z~>=@=dSk=ooI1HdQg87tzWZ6zB5bJMV%2ORyk+{#dtIjGj>!dTMCUd6S7W#|l&D)1jyQCvP-90;{51~QQvRxkk1 zki3k55O=J{3aVnCL?X0j1Z|Qw8yVmu?Pqb2ne3!IoxCbr*3;3Mg&y-vkumBJ#HYr{ zhg`mdB8L$E>*Q!s55YA%V7MT4eUwg?XmE=uE>K+TQ2T8R#pJBl&+?eZe;sK}I{Wr~c^*)Y#a3h8~NS6&LB2rS||Aaq=5d}t&H%) zOC^5&_mcwZ!?hRJ;dLi|@B#Rv744T9?$nU?cF3y@@h3kBs&yR?!BcPmt_WQFcH_zJ z85H3h_H@V_v|N>go{cY^le2%5`&)TuH#>75Q>|iI5yAiz+Ck%?@BQOL} z%Nl`^&Qf#sl$WOJ3+Z9>6p2C~4`AvNP7iU8)H6+Xie)co?c?brRRgemHR90cOVIyn zSjtLU=RKtGPUFIl$;nzunw#nQcQHqZg4l^!?YR0WWuz689FjvG2wuC;F7%L?q7Zpl zBO#?$X>UPCRKrq@>wIn4^)@A)bd{w7K})|@C3%#@P--Kqb2&+Qyq2NpW|o|TU3~Mu zM?=28=3;#(0N^Rg3yu|iGSR-)E0qzs!0fZzlIk&n7GQc85Ns3E@_h|g(!ulyC3M0* z96GMYA0NQ#HbjizW_ZKyEUqei!s+Stu)uaDS0r^M382rD%r!~?I(ETiwI7F@U_Hc0m)Wx}w^ZXq0Y>fe=k0z=>-!{EL?O&d3|)r+!!7s*(8ZwkLj+~? zX!Fi-7NACU_!SJ-Uk>i!u(>CEv&3Z;NOx7V9+_4=%&8Gl864-H)P4Wfd@!z)E9arB zsp~5b0f#UEPO=IZ##Gf%l=Q~K5|~J$en==YC)c_K>L|^G-@poadfMip*R=@&i!CPA)=LPq%RV;v3*cE@$48tr z7?PR|8Yc|ZzdP(XgFZGUe|QupJkXq841TW=fCl$_H{fXgZX9C=;d+dmMHS{--O!!n z3xV8+8Vo3<(l4iBD1I#1jJ4vfz;kJ6{X zZk6#ZrQmL?ePy0V@on&krE4bCr=73k?3cfnP~*~zmNO{J&t#sGgu*h@{)8w8&97|% zOdBjct2k+qP}nw$-t1+jcTZCbn%)CbpfE_xGNA&$+j1 zS66>)uf6~6)ek;vGj*VD%<>IKMxjcY7OIp>1a_i%)uKKx*+Jhx_{{@(Gs%xs&OUrP zU!ycZSqE7aGXcbxT&N*SDewhCO10Fn?Cc&f#0SOSd~6hr$<6t)O!EV^&*_jfMVaaZ z4h=2!i29prY?(ga0s!FW^73`&<$AqS02uI!-%ucMQbWPz-dq^6;cJtv_I?%O3ywaY zRO{P8yD{Y!`YMJ)taGq=spfjfiY$p)H*4qXk@;|US<3;{JtO$7^1xl&=7!)j^*}q& zM6#LcA@eS6H>Z-~I_IN0Oq*$DYv-DU`p)|O#DU(4K+KP8_(>Y|z@0UPA)2_Q1B`Gz zgZo&6-|Y17+d$P8g<9wWR%`fe2G(o%MebuB?yIAw`pqJJXSFwbt9=u%f6vZ9;`#r9 zb-eCsp##3sP03KP zE_*L$vNS>nQbHIL6Y2DA)JAvg21qZ9IkP~zF_?=vpKHIf5<$3G*Fk%G0oj?3^@&i2 zz2p^86Yn6tQ%Aq#eOZ%K&nosF5*}~h@Q*l_+_&9ggPm%mQX)^z70g&kQoCScc6A-bw8s63U1F31oS~*+?_`(wo%q8J9iBISc(~dvII4E*A zxh>m{k9+kWlo%={)bxaBt9YOuoQOV~(1s1QFAdPsF*3Sy_a#p}kN`CL^(yCxim8jP zJqfiTu^>ht3#%~d4|VHYIgU0=_gW5hSDIuI6%PquHVn^GS+iyhx9eczyI*T2yN_FP zbT}Eb=fFWV=`L%4Gy_YieN|@I6iBs(FcEy+IAMD-Z8B&uOp-h7m>124Sd=i-RN37l zjb*x(A)b#NyUb0uX#lR0!=%`*LRu8o0X3%&l$v=95q~Nc9(;jV5`3s%F(2)5-}qse z6271+;nU<_KuCnES;27-o9kx?)qyo6_lL)S5$^mFTDS?(TJ(1LcsY!=GZ;ccZxHUI z(H2MiV=O-lib;1}WxWSzz_EPk{NaPRGB!Z;S1lD6V;@Vbwg9lKP#NO3;~;nXGPKVM zrxe@p@clHun3V(eR^uLm`h7LOK!UY)(ZJgoU}diNo@tD1s^u%Vq>plh;Z|?JO$O{0 z2Ywh7WrsCS!PE%$Q32Ju{VDp*uA2E}mN*fKtW@J{dE^=r8lsF|2PwMa4>(}-RIphk zN!f?lpcdA`?Eo9va!BH_W#m6`bt5mm5*iVa5#Pwo>#5o{SqLmjRl`hO__`;$PEO8$BZ?f%Xeab@LTAg47NB^0LcIY8)R*YhK()&pa`0bcQGc#@Wyx}qI} znJO0S-1_U}@UjIEw@al|*hJ19Pm)>S2(q*o=Kg&V)qa3pIXO2B;#lh5mJF6ZLY7eGY>+fx?p_O6+*a5hF6-S zZLPz+nu+|2i(jtHeg^h;TbCm72CWz-|1P#FtrwrgRhuDl?_QxLPYiWD{p5 zOQ)_%D?3e!IWo(PC-f6%zhQ`nbcNo70V*`YeE}RqQ>bK@Ym^I3VUt@6W52j zasIwy9~}`@xOotBa^+Ty#Y|n#d)EXCjQH;1QdT^H8%jHF#~fmH=t<}27Rv1Q)5K2= z-2>Es-o=^U@?ZsTfQw*}n`)=`MtY4;zXB1gyMe5&!06-Rb+GeV!jtu_2(88B0P_fZ zY20AjK3jHJjqwF*3}`F?u_KiS!COT}T8X-{n@~gbr*6HKHgZUj^U`mbQVGFbN}sfx zVpR7D9YZu5jcpMO7`OP@%nxcs5e!H#*#U?)dJb`owX%TT)(X-^uq_&vp~k;rMnOq) zC#HSxI8}%0>F}oaS^~ht`l;@>ky6if>D{|tzk{}U3ALTq`e%MbEi?m5pBGV#tpYz{zu7vd#X6|ucVA-i)StI3TWExg^YXAv%)~UY z6np0V7{R|kMzDK!CT8LB#~=3ku}lyWhmjlBxnzk9n4vV+v>1|dA1lAlaus^z(U%{} z0#lF-^{v0k#Q38cDFNIvDxjNqN`(zk{FC}Cl^BnRt&&r=n^-yNJwb@D%MU|w7~NBZ zKAe>kA~0bj;fdqaGGXDg8)5YJI^(U42uX@$<_}rD6&%(w8cwHEV$djs_!Ny;$t?N{ z(5HiBkphYfe;4Wl)hRf-4h)5m@v@e>_WCUiG>MTwj^&^iMggJ^Y0|{HsZZd;w5_z6 zRNPG{|7bf7vAv?{^X*O097rl>Ar(6+V~5=7qz!jN(OQZl38hv({Afoo&`p z-x3VXA#LtsLxVYmtKMmyNaz&S6oHg$qO1)$%ph%UIquUf)T@mOsx0~q?o#hkeu1s{ zg$^%#d}s=^{s15_)#M6?Wmg%iK9r7{peZ+mGv5xihiD&1hU2Ib9mf>;y|9f#P$nV1 zWXD1L;MfHjhn+5u&a1pECHO``ck-6?C&(gbPSqZ|oLlaOuxa@>jM}+`LDeCT5MRID zzehwz6Xfe;-gJ(%^h`?Z*wHp|oFkpSJ7Md2Hj~WmC<%aU#LYHbZ3VR8D0sA{^CZ-8 zG?O|j4vuc;W#7UjL@K|m;Ava1)HN&~5)K?Uk^Uvojf_FaVS@ZE62V=lcnkd7(P;EF z1Ck&8iJOKk#QAcdMopFEvSM4Q-sU($l#-s%g-WSO(#26bTGX2j(M!>3AM}bt0NKQI zD>(G77&8FEgEMFAkYJsFM^w)u1Tnfo23bS0-{{KF+-4TR+#Ql-^ZUZk+=H?C&wr0y z!I|*B?u^aP=O#b**u#x3uMN#PR$maz*)NJAl~aC{M*my6?brJw_Wlv`WUN0~K(hQi z`zhBqg@Dvi7$hLMhj`+lCj)%l5DMZ&<14Q{NUw!r%r0#%PdljUz*?zPdkms}al76# zNSNo2Ap5u~Nd5|!Ik>pAvm^A&0*-7ONr+61y_Qb z@z*ZIU4cWMhk|?PA19(fD5H_w1o%i!i!{eak9={~)Bq+srxPw4CoD`_Wvq!v(>Tw0 zxdNzovruP-^GY=>a#O4}V$WVdk$Tx2T}{I<63D4IyL1s7BIn|a`C54>{~*?h{zD_M z<_|v;bYM~)do*s8LfUpQ+d9iuE&?t(ri%i$W#-`&!hB-u_W9sE}4;#|LG4#l;)&t&U>??}i?#>Qm=EO_u$Z%j-HLws8+Q9+% z3B>z`2qX7dTWvb1qE%9q>dC?+x#tTH;EVxe8pRT>WQ-cC^u~||sgn3H@bpe~lU~l( zSlk-vw&m8w#Bx1sCZlq1rJNK$SD87O|w8&qWaPrOrt8T z?k*nJtB((}SJO)jkr|9r-`ffRGD+m^e$5AJR7qjq=0AUB z$i%UOIdb&xsR^IzO^1cYo^nMM`|fp6vS1KE)r95dusbf)X2L!!fWmf~dj;}yc=@^V za(rLQ83=r2hVf*1s!SeP>s8`yWC}6Z2p5~vjOCvm!@09igVkKoD{58%lR}<<>DH&G zzY5yDG4-Z-nog?imC$kqlofQjvOh$iOPa?8Vq}%S`Cq(AgewKAE6FW30uo}z)>0l2 z$kzkBqH@GV$Tw+J4bH{&lJ*dz=vP_2XPZ1bok^>re0huf;$o&Qhw_sArW`=a1)G%1 z@u}(zTOCz01DCp*L@rMOkx8(*8y|K;&B|UBX1E)VR@ItSadrx16s&Tu_%UoLXg)zV zU9v>(f+@+H-6;j>aQD1tBIj0s))%$^l%Yky*XwE6wI4HLp<=$yss^8sRF!LwuZCn( zq{5>2R!nKRRF4L++J>kZ{LU)qSFAgbP55;E!H{$%7?dFg(VPGj-px$J)UG|DIwHzy z<%4Zo0%S+q$a?q_qO#A{@wt><8XQNFm>rQf}D~eGJf(%xLcNyt^7Q+ zTo$?$ZPK8|Vk-gC5LwhSpOyxyu#$!{Dv!x?oNRox-{?BMhAhDAN|2r$W1j4>VoB0g+BahP^t={#ZOEzgZmc_Sta!~iM8@&bf5u@k$bkBV-&rrs z73pAXnU>FsYp#Eoh7pH09I}7GkxO(GAhU|ftQ|%i@z((YG+9Z1N8{h)6Vq8_Z4WZ% z@z2KSoJFOij#Oc2FA}%VV$!t5{CU&(J`1mngU_V26un#$^;kLM)6$CdXIvH7S+5$= zjQq|kwc7=m+fYe{fN4)w@BlIXDv55)LXhs101~Mz@ym=#CU1eA?I?V z5~9Xzp!xuRM{hzR`>s|8L=6FW+K9BeiWlpS9^p3m^&!;mb{NvRL+VKGio)x&&;6>9 z=6s9{_zC3-<0d8$kSdTFJ!+eN?5-3i$_UjAQ_OwAOUFFQl2Uf8uzUbk&-5VaCITtQ z+2|v$EK5^pOajY!Y?OEy%~W?`=#Q=~zIMeLoe01ow;2r=&c>XfKRc)@2ZX+BDlTQe zymA9$vC`t$?b(HZB&jTk2>E6s zR&Z1Y@^p-r1cht>65On#Fx&SoL+=q7e3=SDtHs&>BITi-!H@D{Q&D|fkA<{YbD&yc&g zb4breejT`<`E(-cP$>zw+pn+YFmO#C?sGs!mR?^Ps`Jz5Gh2W}aN7kj?7#w>`n?K*DQILp8E>x#sC7e^%D_61?l&JB2Rj zlfhB7^IKDDno^*J*1~z^ib^i_W=NxxBhpsv7Y#1nY31Ot1CD+J6(WD=N0aK!8(V|=++rlHGE9V8SWSSx@dlID+fdiuw z&`2=uF;o2`Z~@Wb`MvNvh^DXBRZ5nDA$Olf>`*#g8621#K)bq;5|y09DwVl~1;bOu zDrZisEl!oqJ{oY|W5`PLuQs1rRoP46s^x?Xo0jMOXLDSblZA1n$wu7R zi%O39j_xf~qXgskVQ$94L?R^;2b=lMxRJOsm>f6Uid}Mv8do}l*qOD#f7&L{s3yeU zY=LqR+(^2Blj+u!|Flg~4>~7J>cL+VqnEQHt`=ugvuZ;Sg~yzWH`%Q`YsL1+`sjE^ z(Qb}r+930=Wi_Egkdq8e-6WL}nHfh$=8d%^#aDj1Bw-K_ZhK%972@UCG!l@DZy&n4 zsz3|bR2ll?$b5cq5^DazBjETc#@u!}b9bb&cu;`Mo^v#QKmBQY1tCUC9l-(^E!gZm zB2c9<^(~W+vF5zDg$r@`hBXb+LXNm5jc;V;Y^4Zqw5t|j zoA7I7*%)Du8E1M8J8R)*PN$14)z`9n>#7n%y@ebm>QIgb*#;uU(hzb0}< z4Z!k85z9M&6<_h6WCM%c+O+~+rx|d2Nhs?m1hlrlJz3rDK@`LVzE@J-1nh!1D3xe(jhgZmGpnJ{0Ib#8#KK1P$)*5-sa=K_EVu?!P!qZ4JpfyEu8im+!2HiSslAqdRVYB3@Th{qBQPjahjqqrb;)dA; z#P0PngdeT{`G9IucwydM7Lc|}Hf6Wu`A;=r4Um9-wsfBK=B{Uuh93G=LhKB@vK@Pv z0_z(sv(HFaz1w)8c|O-bh5|Sfq*(OL5{?vY(1QyZb49GBqMV7Ivx1I)XZzO-i1(vG zy}E%bsKiRyQr9ywcPb9gGOWpl=wjI+HAnRi`NF^%yDMYhmdYFQE6$67V?*NmC-IUq zp>|a_WuQ}q9Ilr3Cy-I4G@>ellVcDR>a+2agmb6uF?Mf2MyTZOWC4DbAxhO)`;bS- z@8^4&f%%qK>)fogS4$ABgF0@JiecG(rYBw0X_J~vZ^s0$Sut1IZGri=J&aglnIb}O z=p_4SraYFOS7_3$HQKZl1b?x&s;7s~!1`wo!3p^z^#~gwSGL@rr_c?MH#k=XTs1@` zG1fG;>Eg`E$o>}dg8)3V@lFXMV=YTV^fjzMuQrdyCR))z3W-ijO4iuhum{ zX)&XXO#8PWyxZcg$O(Y%Z9g<~WpI4j;$O)LY=-+S&aUk5J~W$Qaei*0BFGEqgof&z zn)2K@zF}h&$geOF*>Ni7!ePekn}5SY)+Rs7XZMrp2NM80x&Yp^6kY_NKDH)e!usbj z8~L&Da{UPq((FS;b%M$lXZZ}z9#9GX)aOHDn%E4iom%XLU52+V&U*Vi0vldg>)D}S z$qOKY_>|{E2K6q^ax;3qK}!TL%mQih-b-Qe=J^X7-Q7SxGl6rfKzPNjFvxXr(NcZd zLaRs%fHsycWdJ~u4{KiigAr)pe>Z}srwZLeIcgV*K)ckuO?$QWG2knxR9pqodT)+- zWVi2la)V6r zh#nR90RZkV1d@gL_hxwBfBQF?q0Q;HCY|0VQ1yP=4nZ3smoN4jE|?m;W^yM-FoI+& zIo22(cb1dCt6X#dGBh%t&pUwYY4aPn3`$4bs->whPL0{S%o zg{!B(fOjXkbPHUElZX^#zb9lm?Vdl5<9&kHnkcA!$P zmu(><&lw!7TWr|hfubn8d&HLSV|m#ga%V$DLKc-O6^2uChAH=~U>u;pnXu2+BTZQK z6`89isuDaJQgJX{pEgM^^s!VJ{09L8mH=Oh%9WM<>7E^WumwTi$PpIDv^F_D-+$<1|4@{|L zjFs!_e#I$(-zHYvz{?c0-J<>ug_w54LMCu3YNkYymRa=UmilS0P{QYCpx+C6QBnd4 z%5cyJPm2sap3JS-oR41FMMis#2#e_#ABCTdjXRBS)>mkyM;!3$bq8GaBGTIXi*1rZ zuqB=FSyRtf9iW+AY}#t+JBYxT0PK0avnNI*`KnLleMpOkukD=Eh!vFme=_Q{K+XH? z&?Zn^;xeN_>AVM2O4M&;b@(BTcnKb?(Yr#|QPqPPM5ff~y?45Y?3+oD_L_#XeFb^I zzUXHW&;D)1;pbaR00pR(*?hc_?^jpaeWS)X~)1as&*A9;Wl z>Wj7j30#8}AyfV>rzA?{M-f}JdIpV>guFg4w|7Vrdmhs-_*9&bOobXuJb?mR@&^=z8J=8n zkp?IQR`N%6#K=#=v`$zPgFudu5+c^8Y`}@YQ!Q9J;cb_eyS9$At~*7ZN4nvP-C4wC zC%5%xAtP}pe3?(l0Waa^h{g`MHxTg#A!n=;2?%#H)~!aAz}z5WHg zdrU=42lht$m}{NF@V(0Gd3G?eqJ95vEX;We)3!|U?^r6Dy#|6V&r!hxOZ(;;R2TqD zt>`e?QQswVYj9{xzjImK7SVov$LZjp;tm*w3$MgwA*iNWi^A{$iuM3Qs6quO9!h7l zNKy0cjhSfo^c2+faaACohkl2`i~jNPe;0Va^tyBV@jbz__XJxc(Md`AKAqdcfE0(|aqX7U~uPX}H#flU#p% z`HP{aSFj~N4^uA?qagH2pSp@z4c|c-vvm<0t-LKLu%vGz`Qm65R@z50MX39bd%qdp zlIpdm&2XX=J${q1RO^Y03^JwbuDJT?sa=iPZbHa|gCt=->6;1CqG^w~TJy92-B9gL$M zhhgI?wS8W>kDguoK0unN-drfd^bxnR`dqD&=TICkrze>qLGd9V!)2Ivz5sNN%-#Y- z)TthtWN?k>xu{A}pX(W}(QJ1oN~3e!Syh)UD{jt`E2Z131NJT}k&t2cA&L8=v5Bv2 zPr+16dRNSlAOEauUexSx@F)J6AMYmH9JA!*H_8jvNLE_RG+58SkCW%Y(N*DEr2LC&JaKl z22z`a?97p(mRA1W+~|ajBQ87Sianw}Aweb`H%@D&HP_-IA5W2+r&7&Ogv$QCwjsn! z5+2T~LqLF%hpmwsw;%J>E_eg9bflRR}H9s0)gk_MH?W; zpa2SL;@(jmOVf+RZV1v*A4~4QtrGO`^;!7ZDS+O}bDb4RYV!GK8>2gp?qLPN2KNta zxblK^FZyXI`j}zY_xVGZMb&FGw|2huj?)8uwj^3icbrN;v3YfOOkJ9b9dqqYTInlg zE3f5VuGZ}4h-$-a{uq$dh*5JRZizBGma{A5p0(iOz1Wnn6gLFKQ6s0u?ehu$;_U#m z*lY7`)QbFP(y~7bT_VL$OtU0UQu-n4Tq-tB+yp&=t6b78?Bv4NoD8?iOpJ%2L%GHV z=NSCEA?0oRIcMasp0!kK2uAs)N_Sed+X$PcAP-7VD)XP^^H03_m4ZHLx8%ejCe6RP z%9JJF(xnjI#i)?Dz~iKvB!N43OtDNxCNhhRWQj#InI=vSh&&+_JCylzRj%@3%{uWR zW637v^q3U_Bo}dT(F2(2Q@f;XSGx)kX78^+@qc4lYwq=rMA-Y|r#*4mjHSb|TVGXG zkok$0@~}8Y?79G-;CfB2V<*7qZhcFATf26-(e78X@i5Bd?k2=WjiTC&wTi{7+=Nu>!B9D2BEQ~AMP=J8yh=fOly6aJ*w`(jhF zP!0?LRJecF#*|Xzc_T@CSjI-~imHsMeHpYFl&8ek+N}T%a`E6JuHuXiP)brMam%dP zQ#P99h%#%K+)V%CZxGYC9Px|Z_`TilZEUbh9nkUPrt_(&fcxWT*=_F83CrJ;}v zwV#c%7Fs~%62be8inDe@jq8R?NmYBmKiU`L8dSPo&kr&9O9Pe0|BS(3zTogBNV2K< zEpeuAchq+qI-$%jlt{WYpw*_kvoTj6q!4<*WrW)JqHwX@Wr0|eGE7|(c_?G$*@Vg9ENzHeu6UQ1 z1{S`xBbU}r(Id5_c9GIrJ;oEe(p;_N8s0b1)B7`Rh<6s=PDVL?_Y0q|XF2LlNAYnt z?(ki^GW~mH<6Wn==P%8t+yq11z8Rig7X(2X5xV0d77kEk8PY!K#u7$@dpCx0Xd&B? zuLEEKkX(%!V=m?1>};WEn^K0==YU4S_L!$%Vm+;_hbc)NTEp{34<%)1DOm}wy?7_) z510;7`gV%(Zr*$CXi;9(3)BpJ($&>v#S~3W zD=)3zXHIRNxFe(TyKxJijgJVtt3Twnz#lCsd_@xd(@9FTgncf)%v8RaQ|pcW+Xf_*_?b!ra9oVsvaH4cmCyq^n5wiyMKW4gBBre+1qi;1#>TsS4gQ<_ zc95OP*W;y7KFVmB;4D;@f=)K`B?oY{a_1AC{_RM&o*{gqnz^L5g|cPW$@1n)IvH>;tga)Zs7> z^|-jbxf`D~@V3eV!-Roqdi=i1j$^O$^8FU?CteZL{c3Z**Pcf>W_tl&M_#isv;Ll+ zZ?DZgW&WIi`@8VfbUueazd3zYR(F38Di*uow%z(di`Vg&(0Ucmm}mupZ^3A;t0GSt zps?jeOD^5Gp;eiP;0and)d0;ub9zkVOC9*cn!hNdZXA`Z3HsF`m1KWPdnx3aIBlTuhPsz^kMTRNQCh$K`Oe*=q4Jp z!F?pCt<;3ZfKmY)pa@&I$$XQ>J_65FIar*X4kS*=F&{1E8ymRSzhf^yZSSCsgjF6A zKYWyD(zo$|Dfj{{Sw2Z4S^Ox^e2Wgf2;V;TO`o8XB;wwTD((-GOJ<@W3ulh=3GMiI z$;~v&iunG0eX2$bHm%_uEuM;`3*iIf0Y>9N8OaziOSm$G;EIuOl$HXXF2QV){4O1? z@h865zuz9pBb_Yp<#s=3EqVbh?EuG@(c4~rzE6Pv*UREB|F6^A!&z5mp6u?I*IxOr z_r3VuYXb{GOOTja0})7#`Rw;$OIGVlqg^zK;(788>>|}!E1`D~wXk*kFM~~6z+%GL z&~Q@|$s5HXF>N=KozT2Mf7|kiXQ%+2WpmnUEjYru+i!^*MF$1Bq|f>Y0_VTKafw77 zfZEouV1nL^l@%$2!{c(-dw=4^Wg$Yba%I0+{hCe*Nz$?M{Y#Ww*lG5~_lJsGN8S#+ ztdUj&6ZyQ<4s{z`rIgueq*5!H0ZJyseV@N5SSm7Ak}}d#4ymROpUT>2@`JdeEamHy zS^Ha(u3zxGLL-bK>iB6jhcIE0%)&D`mf*npGz$vq)MMwdLJeT&6-kG`8(bFYy?^Y2 z!FUoP=PJs+a$W->SM(CIQH1b>m24dmxa7aDlnW6msCwz~xDXGDt#b(kz>|)46Hg}| zNZ)I5g2ePc4}p)DPY%UGC^09kIqVRpQ(wqIeT2<^WH*(0;+U6zIdot$4*#sG)CrHt zCMQD5!pw-tKLRp=hlkx06?*@Tm5&(lae_(Hu=f6p-G$wm2p4LLBaxF{Fbf(W6yeL&JwU1D-T9Bnh-1JUAtv=n1I%reDT~MZl2;lJ*R=cTVzr6fi}$ z>OS|#M_w$eqxR`~Cr`cQil1qt8P=v4o?9+Q4Dq;r5e_Nc!QTI%9mf8G-nq$?BbX*p z&v_Zf*moLJ$SwXj%f9UD3Uf$EJK9C_A*T~aU<=L2me3T(>v1bC=x4#1w$o`xDY^9h zU%=>qpS?TM#1B?$?BimIujg_uLN)Dc|4wqd99~G@efGP2Xd0Ot<MOs_%OHD4IcthuMzgaMDK-W_OEPnociR?&wWNAF$ zvu4G84$izUHM#7zcrs$ujt4ZWtB&dZ@q1diCG`>%tGjfZzHPUS@Ug+K-qG&V(J#(n zHt>^_^Xq3CD!=>Xs#~vhn_Bw{waQTba(Tn;9mR=P*E6<)y6=Xrmo5D|dYSjr9e@e| ziS(qW`8?`y`9MRib8VCa|H&@zuO>DQy3i;pvg%x7H*yLXaS<2+Mh}vJUh~)oV?mIh z-GWlbCJkmjIz>aR=%n$mKAr6~X3eVZuRKVW4~r7kQ_3KDSTjB*Tg7flsdZQ^qgGvFcV|_Nn00D+oR%~;$E7+rI1fYiFIhFhsgskbX zdXjIM`n+-`I^BdE6SDbGDho>v@U5+lQ*SsVTpt%jIxu-VO&Pij|31#$xfB+4$#`>e zdt1O8)FR8W7Yr*mGG-V(EAiTI3qk zkbc9h*e|6{Ih%wLByCqo+1EwK|FFvG~0DB@G9tf*EW=b0=vscU71- zlS%`D!QM1)@D-9t545fHJ;Ik39L2=A+I1z8rAz0Z<@IUOOC?b?RCfWmHZIO^(KyQK z^B{*CzES-eG)aE9LbBQOf?gj@*0pl0D9@nE?#a?;B5Nn5C`IV9)G@UV)W(wJXdV0n zz4Ys_JN(+jrIeEV_uZ8drpibprQYzwra4#2kKH*TKOB*iv~a@5YM1`Xjtp&I)_AvL zp`<;$=0d?-7oBB6W2yp3y0r!2WyoZ7NL8(lC6%TQin4q9!?KdWf_7|u55@u8$_P(s zVAG6*8@L&k;!A?%*oIaTh#9RVm5hd{J#KJ73RH*;es zy}mi0(T$&r`B5gwiv1dlrsN>8+mIbJLMv{`anW8pFK~3%`4olDap7S5sv0+l&G7Zu zL~A*2pQeC$*V+Iu|A+l-p4nUuo7DwBv1>5jy`Ii@#)I>DdJIl;dU?Cl^sx+p$;<7* z*HVsq6}Hds*6j(+(c$@6Y$wSP#I$sa#VdD^U>r+S^_KS6o0i{=t4k+C{rlIc|E_WC zM!{~^K|&+zvvUPmDzH$X??KrAcJ~>4S*DV57Y)s@-17-QehRCPhw;?7(fK4W*$V_w zmF8`2Cw<>GLYLMgSt(i&a>op`3nUf`9L4U@@jqKBYJDjffi79w4W3o36xwG+G>Z8i zF*wlL?LbvJaT_g^;P@~^%W#wcN74zoRX#_qggHN`#(bO#<}6tE%q&sk;XmW~HjW zg3R7((GwFYy`;aWw0NMPI$W{-Z#VZ#EQO*80)TkjVmU%drM#%5YafWSt|Bj01aouL zw!cX=A5}bXW{IZbMcO$@qrf?&Y-!n7(vgZJKFJrsblTu?(un|-x#6HRDbb`1GqRN= zr#AAUj=u1XB4Z451VjA>xe7cTJ|sjzNtqJpZO+<8{lR3K3|58mtf9Cnadc*qjaybwzKSPs=))}}`5grvF4X%50-M>Ef6cHAYnFM%FgRjd3ei8Uyeq0)YE|8bJJfEqR z{530GbngzdupEUg+6;00wm$rHN&-ZaE?&)~aX_T8!bSbM%vqnyP_jYr*-q5p=;PRH z32VpR(vbklEN~O5tFrZAT0G5I#jLF{-)o8oRIgzd%L+TR>`V{-0O- z8rs1#i^`Jmd>*Ddrq4HrFs3=ujkmX+8TytQR=F3YDH12NTiKoNVdP%3VY`8=xGT?F z{&9Qqqy^M1#RDjA&NsZTa+b$A=NQH1#1@x@LXb6(t0*uu+doTJ>C&mDnH4ZAN0}oM z7Qkt`G@_jn=f(xb`iavblCij5F6bp_TLhR_0pOuu#;#`9&TLfWIG)-@ZYS?yxrb!Yc{w(^?1bII zVlygC6Vd@j|DRq|nG}x7o#+Hc>u%Zgx7gLh3?P2cZOP%EWXma1nAt}M*7{trnUSyd zksw3d4~|h7ap*ron)Z{p_PmM6409L}#haLFtQ4vhF?;i+DdNbug}thXZw2qf!Obg$ zLl+`>EKMJUCA5%U!SAz_NVlGjFPY^CGZF8ZtnIG z0FG~R4OO23jgBTCp_=g4?!R+EH{xc2b6DeQxK98pQ)k^P=&yNB*x`MyIEu=PZ z{358W-i%oe3D^raPW6@asOS zqOCwL$se1~Z0`_r}SbW#A+s?iaB>V*#7Ik%PPo!4!_R^#Qc&3Q)k)M3!m zQ;rh9=UjfqR<$bk)4&UJr-RE$BcVhUoCcU3Bi5-=-XtS7D5=tY@3Wom7wR9^dfK-J zi);QQ67jt1=23W~7HdOZ{v{u-$WFrGs6kV?Yf>!}yxB(c>hGLT9Z+QDmg)r5Xbdes zEsiv9x95NBbtT~L7U~UvCHC(vHvr>FOMtk;;`z#G(AKIYtFRW9A}CMMrLsQrfo~M&u2s4I^FgDx_nb zn++A^Xtv{_gdB5WQh%%Cw9O`eigv*WOM5Wj64uED2M-D z7h<>NUvZ^?*$`%eJEQ8Oo1DHK_!msFDmobVmDS$;A_Di%;wBj&N04~+)9)^W{*@_uW9`fyq`55VXj4kHUEaUHi4a~f zw!>@2hv$;WZfWkH6u)?JCN=~X+=g4!EAovCT^aesNsMniRliafm@bVhZTWA@Xu z|Nc5`dU8o;w!VA8pDb*HF%~Y2uC4|Zl9k5In}C^K`3DyqSJ|6Vq_^k@XQg1G0+oeH zAGe#*E%*_+9KivuYVMePN!(dlCN}QOLtFp40ypKQrD>?&~R1>xUTf_#3ROQE#1hN5b z6)jb|1b}ch>AdPNlrw6bP9|Q|nWa#SRY4jfRjohHGEdf!7@Itv?qGKM=xHn+ef-av z-laalB}OTC6-;r}H1&z$L-cXFLrohPO=$GNp>RuWdGqUut!L#yxkzz8lqL2|BWYaLqi zAO5hN9Tut!Tn(tHu{z@^%C=WXB)ErWI zr7iSsScT03equ|Wj>tX#@&$O^F8BXZ2T32PXt-$1yEVt)#U6E=GcFcwetRj-0qFX< z^F;RwlrM?GB$vV-kZ*0%wp24lT>?b%Zx7-ynCv;0WmByfQRv{&y^{>SKY2Xi)Lftc zgC3la=?r`TU)}rRCLF%J975N*8iTbvtgEtM(Krb+BfNTq_$5>c5X-!bxbTuO%!b0G z(6kyXc=YpTCb4YBIzt-ntK;VYB>ru)#gRrTdrvDj0o*wMaAydE{R9&m6c0bQk_68S z&j?U~%UFy=fnl-S6y>)CTsw$obj&23lVwqw@{BZ*t`FTjVQo+3nally!VChM;qG`h z=V(*NRWbE|69o6caZ^&*5@PG_>aik7V&Q=-cu(c^-+l<8kz=v=!`QR~h?#O&0{RUM z{Y(pt3w!v8%RG^58Um-E`LF9|V69mQzO$c2TR)+Ca6^F~;X(G}rr+W+msNglvn{6u z8_~4{QthvpjkjYh=?(^NGJy|Nl>TQm_VJ>c@owviUx8IswZ}(*G8Vj@OV+T7vl>O~ zMZt>a$VA-;nOvh2!w-HC@c;4$+Yz$|khP}aLh{fgor%zB6aO##px}S-gTS(ji4PrB z&A!o!=ZU&<$EFfOjJRwDtMeH$+) zp%mI&cS{T~Owh~KGNEu;a-4b_j^2e)!vB&AH^{f$4}1a#{QeKAa8Qv*ErE0Lg7SM>OywP6Q?jY&ru_7E=8cQlb78IM(H9D?N5@riw07@^HaBywM zd-U%Nq^O0kSls&hM6k+}gzs{G4O>v=ue+jLXB26d)H;k;;olMDwX7aPP=m^ZcD-@s z(fEAd$i!@hJgF-jRB435TM=F8R90FGy3Asrc8lnR^jRx)IsjqHA{EF4Y!k;%1{+M) zko6lOty`s5)-wNdn?qJk(&~mwwuY9fIs|cXaG=j00Y3d-6xGj{`O5fQOhd=%6~I{3fIdoqy+D#d53BI4q-+4ZnNkvl9|JM?HsebC@t-1rF(M z0+>y!bXxw_4*}#!=sjdA>7~54V2BV~ymmcvVH`RE%Q}lhXP_PrqX9U*ObBA-{v9HL zac&^cwuElKLo#&W+HbmcZA)6D^C!?}#w3ejX+Y>QGJM#$(RubsnsZQO{Yk|_w%V)I zWIQZ@mtV@Kp`09K!E(e_X2`R<5|6n<_PJ@boU>_IlmOtc|Ju1QBb3g~kQ_aj5V_D& zSu2I68`UuIjj3~|7TqQO7j1VH6=%~e2pD%KXmEFTcXuba1a}SEI0SchcY?bHcXxLP z7TlRmzW<+@bLPz4%*@qWRb8tu`l8=jyY_xISl^&?;^LIts<*)G=P32kd9dP$0cxl$ zb@IY9o*Ax1?Zw>S5)VqDp{4epXsd(w3{Yx|rQRhAw97J9N5c~f67!tSP4g7i?awrO z+9ny~#^i8RziwUEB29lxmiGdTD)DGBnS6o@RC{@&<@4wZ!RC*p8Ib25?UwdX^vOCdu34Ks10LS*hK%hOgtS#*{q?%MqrhWzW!S~hCv4sE-S)Ao2#VE6Y zC95<2=!wbB(Ms=y4zxt-k}p7utEv z;Ca*_qBkC3__fnkP^SSwCOl+wrUBo*@GIN&ajsFz-q86jeyTe{S1(lT$Vu@51>#VK za|3Fx)0gS^B3a7Osr4#AW8_SR+*+hh2%pmT*~G(q$lflaNc8y2bakdT`86)No)3tH zh-4;6A1fdG-7%MiW=qn=*`?~__F||&6@gPER0du3|A{JO_ml7>N(L)6hvvcYGf~XW z`-duox1*7qrVMJ1$2p#YZfNx*A;X#eD-{C%Qia=KV5xQgrV72?49ms;7phR2?k`nH zg!3*SeYGa#yY&xMm>Bb)slvS2|4bFG%zQsR1X6`?5-!FGl~J;2>2^+peDU;#aW<%c zP}2fzGGf#z;h9Nff8N>8z3ai8XkqMVK&sF<(gxOGziXLftq)^`u2@P+;>~cpg56Q< z4^=2g_J=C`T=#FP&^YK1Rah&0@g2U-RxTF07kotka~RW6s3{7R#^kGubyWZ zsD(9x!6Ay@{7s=2=e4f7G3Q2}HlL?VerXY`4gGGR3>k8};%$oBa8z86t}=GB!KpE6 zhwWM$I9X^FoGI1G!ro}6Y~?*uNU!p$)b18>{cC0Nt1yES3GnxFPm{uKk z@{``hS--(#(^(ABZpUvXQ{Ofb80xpfAenQV%Zd|CFAlYHaIOcKFGP;8XjF?_p_}U3 z2fD@2_e!JXp&=KVVpnXA1x%Vr7cyvY3>kFMX&dN+f8nLl>W|lHRqpnF)hbz);Ja|C z(`7MJkvk9C;1f-l_Kyb{Ro*h8A+j29oEre*8Bfs68>*ULcsrI5~>UQ50g*=@&9BJ z7Ty0ZCLzjyZ4!!5{>vo%k0c?e;+5KkijV8&7tG;%nj6vN2hZkijlDoYk2_DgOQ=laeFhc|BIFukk=5{E?|%=qO}Pos zh z@D-w5gk8x6`SkNVP1ZhhwMaTIkcrb{>YdYp^1K)>GthU^OWMefj`SV>bXli$(=WB) zc!3Hb`4*oW_^H#CPXL`31J?m{lm7NgIHw5mGE+AEbluGJ8!!eJW? z!EQ)B4-yz?mfA}4IvjT=NnGpHC$JBR-neo+FTfpztqd83RqlwXKy2C2%$cQDj#$6> zy=^#UGH*@2L{6|Fo~3I32#`nx|E2EpaB{*&df^DzsZd2mQ+%sTBz~*o@9!I?TVwka(;8fV9K@tPLbmg(5?E~9IwCO#Wv3LHUI=PxeoL{KvDo8 z$w@L_f|h@5xGvqATn{B4|H7(%?C9M+ATm`8qC@D>eIGN;n-#$;L}Drka+{$X0LR7Y zD8S23xIzoO^EyC6X8Pf!OJS^A^! z>qO5qFt#FL85U4ew{Kx>gNK7$ijym0j`ii&Z`&jp_vFG18_F+{?# z)@HdGyt7)rU2E}z)tfB{e;=jkvOa}@xC@aw=`C@#Fd}+G;HLywc4V{RIml!W)SgLX z#REGSi7jJ6n-W%}_@O@tZDE8?CkS;t$z^{td=5uB-6P*+G=tlr(;@LJp%x&9`EzZ2 zUUB4g51q9nEq{6YqhR zayEC8s*6~!AFQ|e6W+xSt?U3etdd{51NETv?JUpFq0fkalN|)e4Wz~2sL7#gOcr;vaHpq4 z+?J+_JAn#lG7BV7&Lt?sLVesgnK6d)ObVGO%i8WI7o+UjrAhXZl3rK6n!?t(7f9r zf1pY-ZW{o^8POD9Ow2!Z5lX8f>x(;{zq+(=M8-Hn0t@!RYrg0ByuS$Yt@6I^t&QA% zba=h&R16V*932UU=nG!qc*FKWPvzV}j&BKv)A;+7sEZdM>Wb9ZXuC55lmCvOzf3d^ z3+!hHDqby!btB25zP{(eBMM|)4e5107W{rwq?Z5)%8PMpPkUcy(+5sX3kT_(BZYS4 z8bQql&_AAga=w5<-$CB)cKXkkqc2;GEzkychXj2vw|{X(D0^>gQPr&D6fXE}-^ zh5!p>DI~hQ--L(}5MkR^aJWb;vsaO%fshJkifjf&gg!>sb~ajvEm8w5&U1XL&pXB} zots*v=4HRr!2UGS2Avn79>LJk^Wy?)1@u%{&ndJFZV*`bi0ikK5n>&|gVe&?4>{#b zXo0Gx9`;QGlTV&K8)r$PgR8z(Jtqkt#C;I^rjg_uY9=jul)OaBTf(%s*%u_J- zc*vo04Ux5Q$cLq2AuFA_#YQV=Oltv-n3I4B{hRAdjEF)y?MmlVjg*b%%-%O!vlUjo z)@XkP!wAAofJi02&sMk7$+x?Y`iF~i$90J=hxf@6p}}^FlPsM0Hje`I0Y=ghj-|G% zST%1qdP4NMs2!qHOF7()!egqV`flWM5Vq%Nf=Q+LIiGC)+K`QwPjJB^dcH|mTlW{# ziWZ}6?=^!L60i7jkMl4fJeoe3wO?~a9{+%brc-&Y2+MH*p-h~$4br+2difRIm+!JT@0y))Fb`;RLsneOiyrNn`LqNUm4#^;H>*)nV zPlb-H^$(%_Ky!nNc2>I1X^c|(**t@bC|$`hgJv@eAP-I|3R0#<>NU+{-?M@|Mg-6R zzbkxiu(WBC<`*H@Aqzorq|qwP5{bG%k?UY4)tuk`9gg13Lp*IzRVkP3!UqIF@g(I% zXp`b6g@tDPDOEViZoLoy;F7F zPn!KXVdUm2wyxRjd6n4d#n!;S$=_+CPZmGlPO!2}Nn)gRj-f5^Tibp#U5mQ{rfl5= zwy!eu{Jgdr&wFbL%*Sx*zEGs;7}vwkb=Hcy=jeVu#%x#ZaZ&BOI9)}g?=g2(w1agx z${)zoVBHXm5{7q1iPZ4Zoi7=)uTTdaQZHwCIslvRj3s{^ZM?@3xjmiNM<2fiS(VE1 ze^Emy^Xe!MoA+H-*Dky`spe1t_&h(8dvPxn9gx=)C>aqAOuuQ`FVYJKy z+s_8?z!E?kpY&+H0MnZL06n_3C>i~>=xYq%sAFs+0SyhZY&yG1v+aVRYlx&7`gx)> zlpRZuU$aU<>x$<{jVi*R&erI{6+D^1TZ`fWU(T8eFAGq>Phw(M4Nrm?nMl|oNOBzo zUrzCiF&u)~^fRA9ci&LS5EWC|t2jfU9|&w-NQ%q+Fu?R@*;;`9wzKC&t3^dqIn*7p z2Kb#pbN*$-J=7wRR+49fAeJ#eA|a0X_wMq|@1D=ts4>Bz?vq~AMeoGC_^)A+F5O!I~cqA9e&WXOBhy^wkb2dpbxo?tA!q{+8L6R z$3(eXz;=cWg%p6QID(*<5b*|2lE&kxlK0gU6fC6>_8@MT;?8U;ZFTw_Y%I-R%Bfb- zymtWm!~Fw{8TB_IafZQhW3jRzdXYX}dxi}s>)x8CnjfL)oFtv+fL`2l=OlTEE~Ig5 zK6Q@x_*qm$rU!%5mE2=_PTX!(KM&F1fq{)|yLP5huQ9*_RqsU6Oc@}Vs=^s=F&tl1 z=KsbIW=#QqGmQXGU6uEpwwC@4HhLCuvJY9zUOe*wx*qTF2zkFK4w=$ts^|NQcWT31 z{gr5qLgZr*z`N&_^2VD;CYzga5BcTINx|oNc}s%u#hoeU&362!?N1Z_=czn{7a(_- zh0n%tp927Thk_N|HH|P)=%r2F!l(ARzcFXA3^vb(?H3;LD<-aH@To_SPBWcoS#eU0 zxiT89QshRI!$M)BTu?nA0xyp4;6>Tqlvt)_5z5cSBW0{Xd3d<>4Q%I!9dQeBU%-5# zWczk)w5eC86;r7Dvt|=bf46Jt4i)QgO%s9ET|gz{UBtf#6oHiG!4_cRc@Q7xgTq1&|6=6a_fwk#eM1OP7rs!*5=Zd zG0OmIhXjALLo^kS%6kRNEFW*;$Cf1XJmssV#EdoKty}Co*QvzfjUiRhaEPEhoO1OL z05sbPbI&!9JA9d~^hn=Ak)7)Dt)@9xD%M_jY+&zleqKiT)k^=&DXn{C==z>v*3(#A zMXg=WlVS9;&)a_LdvNfvc(;Hum9-bG3sV^4R0}VbPEBII*7j9+(fAMH^UUDx&!wQ~ zvqlv-9_}1i%4F5O=z#+cZ$nQ>xMldrfR-?MpoG|Kt-@)1mtu`6j;^%*3?W~p;ncFn z=TpiSPt852+{hMgH*67CT!C6RRSNZflPj45QVoKF>j92Tu%2`1;VF(A6kwE(*)M%N z^X3#T#Ass8|CL!bj2e31^f(R1YNG#r)o5>|? zH*}^0;MQ4herkd#J!_|r4m;Uw2q!K$9W7wsMY;On)oDmk-k~-eulrj-u3#`@Zb^-5 z4l99GR~u$>m9%@B>lJb^*Ik$}W*uwCIV=V_DL zwJI~UY`IS6uI^h_-JA`S5MgWnEg|N?%qazx-6DvmuA5W!vE@R$^MQL_`4RBtLce(P z_1*3lAsi4$?LEr@Yf1!t+2ed35YyvY82UEGgWBA3Q+yW)K* z@IMUV%m}kYw{&+YkK8=O3cfNmGi=U~gB4k1tJEr)u_oPhG<>#@)S$_A6#7atR0=T8?X!@H?hvLO zg-jy?84_|9?F7*!ygUy2jwst=EtBTkUK;#0LINq4Th-3tLhyB)kiv1 zm$MU#-}Nm}L1YhA~b-Y7OM>6$2)Ehc&rRr z4BrYX68vtD5RacjIy=k(|1gLoKn8KN!kN5nF{V|m%)P@iU~RNw$-yM<^3kfuj&7({ z4hM0_BZ_StSTz+qpO0fw+ZGNjC-VVR5RZWhA}laUVjQ$PfK7{ghsdzuW_aQjD04}X z>$28c*bIqug$R`u`{lg%W~>cnL?COIc>M@I(BjwKM8+Hdt0YX|=&p^Hqw~&cidG|8 z%#&(uw)$q|K3utq=>BAunXl_LQAAk~Gk`H2Dbw%`O)KAXODpzDkF3Bw^le1mF7BL} z=#+=FLq|+6yhQ{T$=NTBo)3Kd41{&<4S}g1eB9=U704I<8CCunZC1yCnl)J>y{!@g z4Mf1wBM9rShd+Pvz|Xh-*}1my0GurSGntqIVdd=^_eEo>=ZC1S*?vHK{I|9RT)A|~ej3NXeSfXqa#jFV&nzAMUKNP`zo|&hsjuW5_ZRK)r zVHhh|6a=z)l;b%&%SJGRq`HS&bn1lm^B!ZmzYA&7*FK0y~lcSI;G|?QXQDpb1#KS(sleg{Rq6n z#Idq8)Z2*wp7bqp2N&LQ;Tkb@Fz0v$+Jnzf@Gng!;?OE~fr+-7Ga?i}!#zOKcE^np zm&Gg-@36)?%l5nLHtgVDPoyQ!ER2ll-Lq`REAMyfipm!LdWmEI$xD)88!aJvB*rN$~?_yZ<>b*x4& zb;}wKaLhJ$wG0{9h!mA1A$M{5qmi{tuVfPRte$22~!MUg+$w@+%YZE{6cyQ}N^3+v#$9 zb7z0^XAL3Vd@>+>C8J4g=+t7fkN_)Lgt1(**qnGE^DG@%o{bW!B9%tTF)xMxWAJlb z#@L&%{Q$#iy1VI2ft&JvR-cNTE_eEC45pN1!bdHO^vA;{=Vw%z4Q+Wy?m37cQ}My# z!e-79&vDgii)r(^ERnk;%XxCx_uLbff?i(C(7DmLQd+?EcRx377USlG*Tgg9cRmL= zGFsPF=tII;GpDhA6G|6py9VKcgxZ=CGgQv3L z_|pBZm8iT#qri8k^fYUT2f;v|Yl8v3FGgMBb!iRJON()Va?DCt&vAA2sy(tW`GWC< z!m#P6i7o)5nZkr7mxXZf$8TMa6BSAMT8*(N>|Z-p6F*IMY9#72tIOJf`$EoU zDxns(Sn~>xeNUxxtX(bKrTX$HPj*vKc4H#i@tgq z)==GE$!|HiknRZE%B(#qq&m=gc{yqW3u~iX2#AL&DK5C{HvCm$!$8byg?tHB8%Eh( zCwAL{|48=tVA(y5Q5f_!RNFd}rKWj16+->g zUdU~#yQ-)jh@juTfyCs%*Z?LJA>4-YTzmRF2D0zm-CORTWX$&6?#!no zxa$<}N~oO&E1f53FlgwW0i-U97wvJz8UTQc^mMi%-8}fMmUfdOxqQ4%%CFL zxcn!!Y?qxu_CRt^Hf>iq!l>?Q}w7*T?0w&pb#tQUcB5?QF+rxy%(l|rtwIOBYQ z0)J4=ua~{P1>E(u;6ocFF58}(#dy{Y$U`>KDpCDFpI?|ou!61oQ}DbXbVP-U;>~kiub1=Er4oH@7VByq-C@I1pvD0@5M*!(Sl@PF zpmZs!)=d-)O(?M_G=G4t%h-pVA1vc^X^1gII*Z-;N3K^Jej4E3hHbJ#LMGLfoPqqP z=!Ep1hN-6*(fCP~f7+uVkumG25>A1t`dQRus6jFYHx~z5GEU5UG9ZJh^uP=qKI{k2}J!8DQf>&q2{#!Cck+Bd3x}jtP zMBvsoc=YyY1H*^l1SS?jn$QXk0d_99^)3yZ^pjHq;*dn0tsy7scr!DS0JQ^WHip#P zPivOINGc_kkRe<21@Q?N%)6&ZCPI zI^N%0coaRU_%$xcy;tMSRTFvZ`<8lyc5Bd9OUS+`y{4R}SNDR>9pQHmf{xLBz|fnu zbtNVo_@O?hLFr(+ape$oUIj*kC{SN~3=!IHR4HM-qCCy zX}8q?VyMW%HrBf>wmc7>7qtqq$<71y5B2mWyNL`Kz3cVGADasQ<+f|a%?$MXNx7cmFeZ$?U$Vz`4v z(`VW8dU=!g%^j)0ya=|uTpowB0Yk_gQ+w^I8_3G;mv{0p`HvorfV+trAirn<gVO{`;sPMAZDf1NgHtQsRSgdBh^7+ehC5 z#|}~u6M?eXK+rdtzFtD12$GM00~I6uDI%)YVHOP)bOhp?bhj8&Iws3!Vwx|6kUCLa zBlK|iSwiJn>bzxm6}l!fGj(+x%VbV;jsj`n==AB z*oweDCL~ON^iUt4;J{T@j>uizbthz%Y6tw2n^L^a^&<;SF=0Jd(3O;;U={Uq&XkSZ zxBPDgW&WBDzV!X<+5wtc%~3ZqtM9A$9-I6T!o*0Xv%03th1{RM3>Z?$9VvZ@FV39m zq(H4m0^*B5|G^i(hmizI+t32>MV^I$Da93Cz_Tv)4Urjs;PI$b z5lAfeJg=WTY>X+~QU-`+Nnl18Wda3c<1I`m3*qFPz6BXCJf?boHHPiFuDJ)@oiA*b zh-+E2#2|MFs-5tzG{A|;4!2%vVT-b!g=80A{}whwozabU0xO%$C$G&_H_dwxT&2Si z1IV^(|54kE-7oUUE!87C?#}kG2%lnw<#Bg5iUx+aBk8Z zRp(hg_Yc3QBrbitq@~J$cud~3p3e==qjO=NdlhL#&TqJU{YPJ1cl{sw;s#J(d|zVd zhS8qI8l?ZQz`tMNsLb#Hc=oiXnL9JtAFlAMXLvLrznEoL{p?ONA7gSjY$eCb^k{;E z*Zj*b9-d(RcYg5}EBgJv^NX8*_(cK-=R=^rxCQ&F`xTgOb$q6Ei4Z->=MF8aNj#Ih zeKPJ0pUQLdD0!K2G&!)G&g6D@(rVOh1UMhB-_-8}Pi+^`)Cq29oyzLjOgoC+z8tSd zLdf=boyi@a1IL{5-Gz=ZCoo9m^M3V_%brZs*Dtt}owGxd9p%&MOJq@0w4vswm?CRk z_wE)BP4Zt~4j3EF_xQ$DHJum4t+8>~A+nwFy+qo@T_3a4cE6oINN!2$?v}@;3$SGS z+0o{Cw#$JD%j#~ZZLt^oNrWh}FIbY2C$+C!`FQVUauljyu7!(lV=)-_Blx68AKn3@ zbw1X+6Cp;we3B!p*LNgu%>}?cGW0T?A+H*RTT7X;vos=wJH4Xx!6ahaso^|TXEwr98_fEFeH^ChG z6WddUr1Q;UC!O+By;*1F4!?bI2Z|rby;#__$>OL=GfO<2(1gq?1_j5ZgeZ7$J*G<4 z4^0Gk1nXWuqQ=AjJ{waO5Qh z@xt~dB*E+r)d;KdLIg9S?zgsHc}C;jD<_t%$!cgQ%okqB~O>f{ki`lN(0Vm== z+JCw+v1Y5YJ3lhBRSosAiUiMJeqmtdDniJX91))+z~Y9%_CD~+@&$j?Z~fW09L`b8 zyQ6%6S%MQu8lKpdBJPukfBKCv&!L`;T`L4CnZex;Ylp^q7xEbpi}e*fQ;{%i^9$D! za>(P~(Dup+<@?cWzmI_2>bv%1Z@mZU{Wc*XQ(!M2VOYGxy`_p)e%{8aco~E1YuA9L#1cuJP1l=DpRyV zG*Dk;g7?$zv4u?CBe3?-WR4iG807~Pc2yz-Y!dtjP6stdsBnF` zqL+|6UT5}OrK3-Kh5>P*&bo2xn#Wh+Lv8g|F}bhLFeqkPX)=A}s|BPv{o zNvSFh8qZ}sI~NA*p<>41_XK-5$c0Xxnm_nr8LmQ8kEFt{W;62UDjp!d=-Uj$7smlP z#_YG<^g6Ad9Jt4<`6deQ3left0EjxxZml|+k9u6%d57w_j%uAf9- zOsqRinCI7}Rest-)#(j6PkR617aOGX;S1aE(#PT5*R#hru&c@wAFOoY>~itzAH0Kn z94`-SkX&)SS6;(X8RWgNVM^wGi>?A$Js&)K<;1MRudby;#6)n0Vu!Ezd=TsKOkdw zhhmqv{nHgrIuEHLUwPJ$us9sE#r^JnB<_aMvO@n zWCyTSsNeE#vR+s&7T;s2#93=JZO~zEB29ZeBS7z|{Ow(pf$F);7MrRleoX$|<$eAw z(2lr0WVue1IUgR$FpCkdbSpxnGG~^y*<@Db}LrXF)4`7>Xr`Tj%T08a@WcsMEj z4sNyUmo6n>JKvw@*Q?ZHNM*?MiRm#hXiupp_x@?U=0FrQFwaledg!ORcT2cC|KGtnYaa!IS@0_>-14oHj6`GbuB58de%z@pgBi#q0Q>|twWkG% zfMD^vYt<&co?MJxLvH{GDFFH+k$eNXdlv^2nnd=P9LfoMlnFlOTrmr3Tv?PZN(Y{* zKK)a;14m(RC==$;ZTLW*6wjC^iWtCzr_9c#Sae?mx-FUcq_X1FDJoRv&0sz^@shwDsK?qPi@FT=bPBO-VJWC3Yrxy%5p?vhZfcYh}OED&CEV$7( z<;2)02=Fk%&#Z$0W7kfE)IKJ<8Mp@=uwh|oUA@&I9xN%vsO{>ali0!K8>6`{EyC%042lMMl zBk;V4wi79j>CO#LPU_#_K9I*@5TAcSljfJ!U44o@Lhd}CBevia&-wDlY*bQQvc*SV zV4ul}IQ_Chm-c+6Y%AJqSZIgah$I6)A2mJvyM4(a_J~Yc8qW3k_va#HU+tX~?<2rA z{O2^Y>PW8HK2nICCbUAgXkdE{Nu6>BlZX>ki@YZ~VM+%^PA zQ>1r8Do9*XiWP-pRs@kZ6|<(4t!KqZw`-9a_^z-tBp1W+Ryk(j#Wz|$1pipWupR*a z>CrcQwKqF_%6{JoR2%JBp@Cs)lSg$UT>3w1qjCkKodd}LxQ8{ZQR@Uk7T~q)TwsUU zg|gJ?roasthjIA%!{t#jp`Qt)FiQ0_JVTT?d5E~7qnvdhqres;PZdm68l6-v`Jz#b! zn_mBlJP{c57_j#K(~8tAWhN+zHrk>${D%~NT;eeXX9Dhd%pebuvvAxg!pzD5Uy99H zIQc}!woGl4WhU9~8*J3s3O?*jI@ zX)-lpqXeS-UgrED3TG@47T2$DDczQ!v0(NwDaux$LAWM?a*wk%3w)Se^p7$l;k$8m zjc#TKHlI49QZB7PaX<%CV68#%cn4XEq*o;Z>R5*6@&%5loI;BgCQR_&2L=Y#um|%1 z-!cN?E8h!>hMFamec{XB*Wx_4sP0a?qwe1qQw*&^CkUXiwyD~b-KBmLJfhk{m+q0u zSq_T&8P|RrE7=mbOOdq!6$V!eb5Dt}0X2YMG9UUdms7~j7NAUdvH>mR_wwERJ@_yc zlkM8!bp2dek(9uxXV2&LzWela6P=RX<$HJfG*?}$pOZ=0?d!Vud-3UHX0G~OA$l^$ z_cCSG7PJ$v3W~IjlaQ4;;O2Xw!o}?1!Wq+l!2Dz>+1$vw>G*l=Y2^^TFR1vK^eL_+ zVk0Z-Ei3C{V?ROccp8xk%H!o&o0#{d%J~vloo9Ii9m+L`Qz+#u*^uU&+@H3I;VPhd zy^iYh{0Z~{Lpv7SC|t8;_JJ9T23Wfgss;4)>1v@QU$@YYEKVJc zLLSFjI@|B>zguC(R#Q1@jtTA8tSmd~1pe)_9sF{N*v^~G9wmE`7ej9SyDELfp4K;>Q_NzAm&SdwHF{bHg3>IGkZg}w6xyyr=x zyx{QcWyxNjFAz?gDtsw_g#wv9} z4xLFGIrT(Y*Cx#SIgvC6AQS3(i9%H{?fq<|M1C+7BElZoqbRk>@oBUI3!S0SjVjTA zvB;r}_*40>-$0-3J~c<`Lg%(wQ0g89`C!NF^=vnf4<;^QTk!LyMUIywmd|?i#x}*` zW2z>`PaWTkIai55cRD1+l@9$2oVBO{E++w@Fw%G0il?!hkzRr)KyjWbG>bIW@p`=k zr)q72#0>Dlb9;iOd}UJ~eT)sq5${>J2S25*HfoW-MJTf zqea{VyupcQnHOHpHxL{D6nAPl&os%{T?qiRffXJyc9Y!!tXM-i0#BRnHK32%m)I`s zhcE0VZB}VoB;Ns7L3lKWBib?_CnbS7cZmYt78Z3EuF%orjWQQ;_QRPH@s_+sb5t2s zVRr~x;xA8h9#f#zzl_^o)l>Fly4`w=AI=K0r*OH-^K2OftPe{MHFzJ#6AGBHHc@*` zZh0ENw}vn`vKVq!u;a6J;{0%$P4soaaa?R*&2828PcsL6jH)!mo%3UNjf}soMp;es6fTTeYdPty8-6X7*JC|GLN7{nm1YE1c}NqvK=E zxK#r5+ROmxVBhC;HQFW|DIcjxbkmIEa8t>QR7|CN$W|syB?^uQmxB%naHoDTBb6qS zY#VL`qXWiy@M;}MwZ6t8tfrc)$mO0^ua;T*ykivfiXbas<+!k@v7Lqw;`KHUwhaO@ zDM-Ryo_?i=q_7pIK%GNSBJT!;5OeAE?3t8Hf+jJ=7EXVYZ$CzkmE){}#to&|Ef6E{?XGLp}dXWyEN5Bvs?3v|A#V^XIRUB{Ubsn(5N9ry;j z&Ox?YZmS};AUARy<@bho7w&@_n8~tFzdYC|a*&Qn3rQLTW}PU@{g}^sHpgFL#%+(R z%>}5SM-M=v5aX_8X|h+adv5sH{1%c+1l3@{+46MEnSIt<-RE*M1>rC-M?SmGZJ!Qx z1w1@(@=XZ)rc*3ah3P_BH(9kE__>Pm#!u6ZlHN-8Ar-}a5;JqKNlf326Vv7V983?Q z7On9qv`3rH?EAYjmO~0C67WT&uCTH$Zv_ZPotCw<8GH%d4qw$?S?0>GUg>;|9wH{f z=v{h(z?ZH})ib-{M&|M}1ohRZr(_eCUY^Ho>B{>w9}pK;X3IG`QZ!exO39=l+h>C4 z=GrNgq30O5d&o9$lZ$=7H4PoX9{<^EdT)^R%F}VKNkj6>=mG>fSHhmNh$6rPeWsbx(n%6W@FCaKeN)G(Je}EhoZKiaa6Q6xLclki3(bQdDQ93`JRm1h*rw z_~vWZZv37ZuJxr4o|twRe>2HmTd9Xfu#Jo{s-oW!26{Cvxq2gNbrDJFvfCD~2_mGZ zV>M@td%Y6;T);Iu2YfARi>(w5M*sjcB_*KY%9vP|I_4@@olioUrYQtT1#C4_8_%-S^oM6Y2?BT76&F}I%rhCyitmfaDX4sM5FWp-a}Y+SccAtH7h ziU~3KQHS^{$i@=Y{5SGl)br8105|(6Xf}s2g|<@?tw7>GPhTC}x0s~1>Q2)U z@)!RNKIJ`!!3Y4qEP8s~SO%r+UAjU2X(VsAb}glBo6~2t?(V`0Cxa*Dt=VHmK}Kzv z8l)2LF@sn6@Wj1+0$_`ci$dub$aTepzV0xi8`L z&#>;5Z8sis77ReZ7o_+*Im&$2wlQh73)M-KM8r@1?fvox!Nk{ibuj^e9Lm`#)6@S0*%r0hR0;tk+cy4^ZRPSy0zk4&iV)qEGqco<-@7YIz|N#>ZJXzm zV#e*qa57tn5|W=~6F}5fMtKB}+=YVW)7(>?XH{m|flakK*U`OV7E0jDLznOTKHuO_ zLLvZ2wuSvA+ZJsE%QbYS{*rAnZozCtb7QagnvgSi-tx74G$9*bE9_V*=3<6e7W{>8 zo~v8fhE!ZckuHsPu(7oc*q%?`rsmRN9i`v77^0FzWAk}1Ft*$g8ZN>$3Y?gDKX>B~ z?cFMSVUNZSd8g46CV(R=sNjx$^#T-$mBw{S-}hoVLq^lY0n(-q;*0r+_)Hzc8%;B- zzEd$=<<*uh2d~6^q4Tm|Ob`pw&Q-H9vQP1+ov=;%ruX(Uq&EFFjEn6AWw765nytu;wdgZ0cH_#-rN;_1XeY7^qY=B8#(JClOzxxn}mmy!GuH5Nwc!eH!dxJiIKjA>dk z%CE?T>*&~Wv7GmgjL^Jy7T?z!%}GJP=1Va@%z~=R;>ysNqW@OJJt{!YVYsMInzZqb3V6DYoj8j;CA(k*&L&y`XS_cD%Eu$Pm)lPwBjBMpYlZ zbSUFi`;W~=EQ$mLAzIw6*jE5mua~?B?_Q_g63B2=7b;*VtaEo8l-&e0_?I!uo~1~_ z=cQ!K>6XueoC!AB;-;D`62-MJ+IJmmpRLb48Xkq&tcZ3!`UBN6bj9LlIe=u_5m6lD zidUa%bM>?x_Sny#UJp}s+EmGjLt6}UZ=LpTAK5c7HXk*|@jmS~x5lL_rx_b(Xs6Xk#jl;u4qtw* zAzW1X_>Ir3*sX4c4FYy#n)FP5kspz^DoiVbNHE3{lwv`U2m{ops+Q&pl(AV(Kap@8 zu9cuBRdx9tQPmM9#G!67%RV$xI>t9|eu3S`8_lO0SXq6b+g_<(VvLD40M%L52ea=>WDIbyEKT{ z$B$v84F5y6IT7+Ke}KK0u-`EqVV6~q;v4~coBn{*rNsMWQx7EDz9gB}j-xH^rwtC7 zf)@8ti4_m64@@SoQ2wOGVaEM=K85>7Y}+;So0IBKp(AF7PwbJ!O_~$&oqscPoGbbx zww(jTwimz?>b2X)x#^z+yF2G)7k5JWjgU5u`-*Lm{DphP*|*bIW%H`CwS?ByX45Yk z8!Z;$c1~^_Ri!bmS1hP2@K$!exyvGrn0vLU6^_)~f&s%(SVtCj2Fr&p<@dq>bX!#7lj41bA^+qu(fo_O$d5 zZ_r;apPEGceTZx&9!1&Fmvjyv@1-?o4N5<}T1tn4OWJ5fx@T(R?2qQaj@$iS{e(=3 zr35(t;Eus9K$icUZa;D%OM&Hz7&$UWl|U^UtvEi0*7vO~o|v66za2G_>&eA~{OI@i zVx+a*%+9K$t=un5PU>uRV20OBq!-&0;aK}~_nJI~{`eZ?=b2E_3_}v{R;NAVzJ%S) zATakQin8E$_fXSE(KI{uBbX3!kyPOqeoO%UQXGth+WF2rbYT&Sd*MJxW26p3Th43!F< zHrzJ-7YrIPF~f>!PW{RLdDo5Rwcf~m)?n?JADZ|-gUrlY3Nq7MeNupZWgW)irxyW- zy{diSU^A)#Kd|wPJuqOM$sptt)nvP#CR#jBmcH3+eYx0CUR;;T$@0#hM6ds@Toril zm|#3FFOwjf47^uTXrxB*<{Y6hvi(Y9Ld#eqoIhLQhfk&1YGs$Fv~Jal!XI1_PP|^B?h;t5uR&M-y>X0Ky5EYt5UIPdeM}L!01r#qM;1 zx!+KWyJ$N3g4kvhb&WCRJp_zx>m6hh!=_L%&9M}2qO$I`jcX94w zp3n;Pm`>T{fA@r`Mwx&1wBG$-dTYMhsb3;17KrF5gH=0Z5Kb4!WpxBOa~~UzgmKv@MfqbTTBWGpbn6prISb8l#d zs^!!}QEXMt$;vevHAMl-U|u$N&LBv-|7AJUy=OZvo!v{ewENZLv=~y96N=mY;o_|u z{NfGbqKU^O-5|JEy=)+CK6woz!6i1YQR6jO;s92s`#B6aX;Etn=<`A5-rnD)@t~F{zQ6y$yZcP%{r<%j z?_t+FCg7Pd&rUqvwtdp$KAeY*79G35-dzYhdEWlOqhq)FVkoGVN^y!+1$){2TGG9~ z9h33_Qa!o~!__E(APY|uAtp%3i0{o1TSNxE3bCe*ufj2->qJ{Ia1 z`=Yo6Zt(%ZLtI9K2Yo=QUyxY!L_2J8gLPT}AWSni zA|?;?T>8j~zAxvLs?rMyt|rx9^mZ%Xj7b56_4)J#ZP}UNAbg~} zMuLF%C=Ob2H7G$dR&?|&w@NqdDoxKW0bLs_HAqLs z42!{S?90i24TCM!`(blLj-hsLxW#r3^Da%DS8s zgn*AUhB~LI*0q5tLP(#U=T}+>9;RlRx#ikoW)x2OhUxU>=ghvzm3DuI znn*+(9$Lkp?SG9uuR=xcLaAmh=@wK19*tem6fX!o9cYgt~asJ7N_C@%74 z>sjc(I?tFSe&+8J7+;Ugb}J-`t%jQ|#~P%2Io;I1U*d&O( z?DUC;DEQR!Azrg|UkdxLw3LU3YvrF~Wm|(tn%>#N#J&V2woIm9jQ#&wRnj|w|BN@VYAOZb zEnGi(#pZRP#I#mFOoz(6xy7_t1lZs6PJS=ji(Z@u72HXn5AD6I5{nBqR=l+jriw|Q z(N+I_YA3rtL)y}eKO1U#8H`4gQIrJ5Wk$^#xaKc`%#7lA` zSZ3?^3FQ1>OUK_VBszyWhORk3%f!cPdU8pt10vB>u@ziqA6>d3k=(=32UoBa0 zo1eyH(%;LnqNxVg19SIoU*B0AD$}8{Q^G3UE$7y)ld*x8aDNxO3tI2rYrV-d$Vg)G zl4rHo5+xdb3Uc))!XIJv2*n?Kl*M|*|ZwH zwO40_AqdwlF$(*;7Sg+hRZzq%a~EfJL7agW8yrYRzDMkpv4|1d>96;`{`jJNSUZ9aa)IEWbu?E0N#R~$}4 zLfqaihcE7AD&wd>TAv86<$jZn`BYXc3BZ3@mSkm(Hjg`oLWJsDqBT*z;!lHlo$YN; zl4B8~Tmk@ZZ$GQVnzZD<7#;C*%0Je{okX;&&$We%71^mMDvP#tYoN%{L?3b>{z^9&ClaKV7!i#uFX|ZyEnKbP4&9-4aTT$0FQ# zeJs|W|Gs?7^+;n=>@+>u^zN%LqtvMqH3wbmBcEVgH-Bei&@C>)0e-WPQ4 z^Azqx>H#$8yQqq{Av9hah7SVcMTHg-Jb~T0P|tqwVK|8OV=3_?0>r>Lnd6~%F!Vj% zV_Jw^0^Da6PtBz|xS!kVS zXo1@!K!j2Rd>%*NDK|5gSrm%rp=+j1*^h(o*byapgzwWXw7% zjYZefTuzOD7L!Gf#kIqzb>@%22YKrE9xzeQFkq@kkPGM)oD&I>$F^!z{yNVCESK_h z#D2(E)pvi&=w5OnFIa~KBSw8Z%Wg1L6bOfKv8b9rg8=WQ>&avS9w$S9Zf1Nx3j@L3 z;0?ijb1Bl37;N%k4bfHr4vGR1gHFIDA6LP8T$m2Lx5e)(fybjjLco6FsMlGC(D;I% zu3hYcj&YzsbkAu!zpZ{G>6%qPJ157S-oAueRAFa3p?D_6Wwc=EG2?0nD(M0vF*7_z z5|{atyBUQ22`(ozPC&rFNyo;PI*I0re*`;Ob|6jy*4#Ns0P#V&D$e+%DfD-2He~po z61GV5dH=)u2@kmFMWn~_{=EfBntjK;&aOA} zIuX+2E|(>ZqQ9|A3*t^%w%YuADq9=tP5oPEOomqFQ!%;IJ3&+?Q_mVD?}B1>1Y>bs~Ld zPGYQi?a<2?3xF_$J&!w4GaeT`Okx6M43lbj$)4C`hdzD^UETvsuAA2oYqy)_pFHTv;M-+uCBt##Jr< zz1Y^@TIzT3{kwyU&msPgN$1N(1%jtp2*Js|X}cO#3Jt!YYjl<1#L7^K`W z(}4v$Yh-)Ls7v*#KRb$MyFVwDtoB2`Fs12V_mQE6yFz4_)OpG9#C{E_|E<=96Vv&C z*^(@J)F<18Knm|d`myz@2}rzskY5fCNW!+%)mnZNcW?1-WI9FC+WJCq5yj%gRb^x| zOFAF$Z2|}$geOrw!;LJ8y-j1tQrA=D?|lo7Tk8;bC#D)g=O7W&e+X6Iw81W#Gs~|c z^666@b`T*7dSqfIMet2k$=Ho|kS@m*+)~iL4V>h1X2Py#$6qaD;*1h=g;HS+;HebG zU5!C~v0^^;S}4cqo*I{tQ1e_pHh&el9dqg;H3m>@6KIZjjIcS6QUcGab31S)N6a6UoCNIyOt1HG+bDp7Y~=K+Y@b-!~ENSV(HrcAi}2%5RENA zg3+=Rs8F{~D<`U&rPWyI=(F-xqJMLdfa&-?PE-YfI&3+J_F6@RLQ4^yf?8>LI6gPY zY7KBA(+6`p3lxosywF5XHTk?*8$2{E1c>N?13Q?PV>z+pcM7kG>hI>msdqP1lJjl?dA$?LHC0ttH&DAYz zF-nW*S7=*oNzzcEauIVY;8u>+uI;#a^#Z`qCAfxA&Wi9 zcuJ}YUj5O-(hgGPka&9u_)4)Lj@PchK{VARVns-#Xdp)Yk2y!dQE1`$#}IKlB>^{k zOWNv}gl6)N+kKCnVY<-QZ_De;MC&npU)MiCC>nojuLqT{^cK(XADK87h`v`;ZnpqH zN@eUCZ>We>k~l;EpP|4p9<_HBJ42Qmi6C3_^8&q>erXSF_dvk07g+JQxX8qPw|ig9 zA$;4WO_$?(>%Lfq>f)P_`P}}ki|^vT=_2~?wmPLSFe0twg7uo!T3UO*L^#*YD^%K# za(t;3ep?6+YZ`g`5aC%&T4`ikgapvecIIi`Bm6H*p59Qj!ad(m#M3VJm%9DuTvS&S z;4fC&c-)!uROF^yACtED%-Mj&5Xoft6r@HEjzWEJo4cZ-j2kzd>rznrW4!&dRAhu$=K#@zZRii>T;k>W`;m{zKND|CRM<7A=T zR4u)+)!C0F1Rb0GN^k)XU#A5dFmk5K4p|KkSqvFCgdHvj-XHq;Xj{Zh`dXVE$X$Mv z!o6LQ-P27h$<~q@X&n(={3aNd5mdU%PS1iLb~0b1vLw1?x#Kv=GoZ6_q{FkeCc?A! z!p!476&B`EJ5OTKG?K!WLlYI^48N*|vPkv0y-wPQIqN{05fcCwBEA*!7I{{Jy!zzi zo}kYMY&RptIqnf<35-hMbP?GpE&dh=e}|uZ2#a#J~b$EtL9R+p?^jAcZqtR(h5?v>NGNd?v$&$#+qLpop&!N06 zT+5V>;$N1B>3i9k!ZI>tmTf_p9%!pYwDs4ynqYM`rGPy2)YDS5ps_(dm$@yz$Se^TV~Iv%vd&^uD^$gzyrJn6saJA~l1M zy2XQhPOl4aF@8Fng3amJKG(6&9b0s?=5n!)!MiZ?`GkHhxrZcNqszkC-1ugFGX)8% z_tq~DJ`pAM6SaVVs-qhF&m^{vtn7L#9jk)6P-dbh!>-zMO;2!pYf<0?*7|X&pw{ca zPe+Ir^%$OqQ?XcX)YE#9?gY(6J64Y-lW7T{K|Kb5=rCZS*C96PG~oJ45JK`@D?WyA zvh&FYT5*A752H-Yn#dwx)=u})AUS;ze5@*lxikpQCrMi7z;K$(6NOqGVXoa=j#)FQ z&Xc>EI81H4sx1|pVbHOGbkF4>6F@v?zgcy&nOPoZZ90$2uu`ml1Ka7`{Cg*3Hr~iS z-UT2ID&P5<-apJ$6@1?11Sq1Qv8FVaUAOuRW%P=3PC6%Jy`ZbE|m z-Q$BL05uZwQR6K5NbFkv*TkR?h@u(7uB-X6X`efMtDbBg>< z>H2(}`ohxo+U$6U$qfGZD_*fji$5P9mzyx*De$GO8PAJUllr0nNI@Z4Ic5(PDe{CF zCmYpih6=AfjXb0w%^I{w_IyMB`#FJh5JJ5}F)6j_=xZEY!HyFyec6{hZJodUPuZp` z-AA5rik~mU3gj9*r;>2{!Laf6mT%k2Mie+yh!UeXZ^o}4LImUpNRkhjycVN22>7Fxt^T1}5%k9|fBR)1=n|m#`eVti$Vg1x82HyKw>HtYQL_cUjUZHkE2e(yt9GRERX|w(iGTF_d~@PW7fak z5E-qUToT^j%nID_JQ7vML$5z**q@*ge|^Nu8=jwHd?*-@R*^7|+)hbhoVj=il|uBi zYSJfdthA%(2>3cp`907O@TMc#d1}u~?+>r?I$oEWY8t+h^NGMy%3$s;<(?<}QMEGr zHfeY#QWbi0N^0F{b2kx>l1_XEeX+}H9ADOSoUeIJ%Js~Jzhld-b5Z;9KWyGBwthw8 z8sv;g>9&Un=jr707(ph0Cs&^mA)2#V|7=t6aejbDcn{uR>RUg+ZS%8*TY>QbqmR!l z4e)%_m)~vY;oi2ob*v*sJB*$l5g8XLnvISxzI*OhekXy2j1Oo!Jv#Ur%~57rT;sQ8 zcW%2HA&G$oT0)l7@4>Tk&P5h;5~ccU!c*sfp%dwOVrfxhtS;D;9yoT$;)XvI{W~e6 zbQ}=4t!E<*1h#F5+PezxywkH48=u>F{veUpn0%}b+y#-A)hn9W8@wyNKobL=V@Gud z=!!VLit(pv6HiL9$D3ujm(#tWHsbJ?+h=Ded^wA3Z4)T(f}YN!r$g=NKg-qQY%7W% zDsD@#l|)uIB=Sci^Rd=b=q?p2QDF*<_W>8m$~H;Qxz7i2d^}@gPI6<;m8r6gK7ufl z_J3T>xG0+!FoNSrRQm1TTtglCPEpJd_`$=?q}HvF0G5w+7{t zFx@OCmvqjWq9)tfIEyO2n_GE)`-^D8165^>?=q~~;MP}o5?r48v*qY)vE>!g~MFBGt?+1%Oxn%u3{433(rlvsg^zM|vy zRpSPCDew+cq^2Hpq#YNEw+l`z>*s7QNxAk1I--K7Kwqa`!0Yuw0qgyBv-?@-WnPCn z!}$fgTaOsvdq~k09cW7b8r+mwDOjjX$a*qVH;4CgFJDzqdrS${SV|}j_A%vaRg)h# zsS-<7krw}F3A?iwMO1}Zs1LSe2Fh@mR1EJD=4uY3WP9STEHe{!vVlbUAzj$nl|kgC zUB*Z*3zvqqKq4UmGp?}F&7}X|12$15UlKU8|d)N4H-JkZrmvytCu=qDkMG z9v=(*fkA>%pnKS+ppEX_tG50=@@b3Dd6n-4npyGT%i0SY$+o1@ie=<>AAQ3bj7={J zs6JLk419Y7WlcIz%9rJBQT6*miuE7uYyS?xdnqixMcDgP`#IO89&T;3u$c=^>HF=* zWUE;4?vvgn8aj9+l)PC>uw8_y`kocV&u~Ip5Mn(q8!%wWP@)M>29Yh1Q46TKP=4UEGc~X4% z&WPTYi@J)l-Yw=v4h5<@jIpQdm+P(tX?X-@xfmjTSs{c!TjNjeBIDQhBpMS`K@3W6 zfWgW{hhK@tbtX=4TM&mJD!WPetVj8o9P)jF&;I2uF9L4ALhCQoD}>lH0(9)zKi2Ea zxt!_Zc*l^#y6tdJ+_wZKwFaj^T5!-FEHb`Z1jy@#OmIcM-tVShg4=O>K&Hp*| z_ah4e<-eVzzr_jp$j7lwmw)+l%F6RFfMrDO5F05}m>bHN&jT?h;td{b@rI+Ler3b2 zbaBfgslf(4W{VYaH-^|=GVzprN$83THMIcR8Ibj087J44 zwT)Du#V|0+>O8bp2(y4?2(v$2eg?CE8uNX$=EC8|$*th{W%{hR5ek)zeZ~R_@V@@> zmfp8u`od%Kd0ja_uw8X;jv)&>XtiUdDJ{NC)`4!^2+U@eU>kc;Q{|Ig@rix%bY_@; zdiZW9^Drv`K_*Wsr0(Wo<1S9#1OK=;^UaV6%aH;8wAd#*UtMu{ZTlu+nw{MY_e`j@ z->;^KQ!S`rwavYF=YPIrWJ@-zV8y zqa>3aJhe``rZ(L>GovJby=PlNGUW#+sKqI-oK8i4W)9 z7h-?;$Yt0^%yzo=ffE;L9pkYeDsTUy*5{WrM9=Jgqncss`?MY+8qF^vh#{E2N-5%0 z{`4=q7Y>2wmo?69Qdt{Ne8-$O0@6)tW_7ltPm0fsJq~jgl|dyb)*JWw71SJ^-E=>1 zz)DAGTWX@Np2so4h-7UJ3#wKo;qlCtC& zMxlzGYo}qhFBtVM1F;> z`P{u>{Ixe^Osr}yy8wSrT<{3xX7b>_?|kNs=KIkJt;qGB+#ZxER&{2caPSl6L1!)I z@kk|%yy(;N{aU>ikNGFMJRy^Vk!`AN$sLxlfA;2kwfAW)vBgMThCTD={Vur47Mhau zMY7OdZ2BBsJ?!1(Sa;PdtoarU=_D-UpO9!L|y zCKimE5BmGD;a!ps%0{P%yi8^^gu(f-#WE(lP9ouUQ4ZEG0O6APw#rGL<8U7S=SFI) z+by_Iz_Y4s^!{_mqvBZ}#wY~wqf~H*k>|4gbG_P=hBa$^Cj$R21O-D7WP#5MK|CM|FijB%A0tW) zjb8!@LG2nm7igv%$E-pW3R-=D$6DYC`U zH$dfWrg>pgFTP=pQIk3w)vh{TxP0L3*nICEVqdYqO+_F&q6+I!^l^&`ZfvM)#ao?- zN(H_hLvyZ>mMCY5Wdp=;&4bAjFhVhi6fRQcEAm9P+~LQKxr;&Cs3U{(f$~d*U*Jl?$O)3p9=)yAjsjP!?}5XEZH{2hwJkid_PPcRQ0kPzv7Jcq%su5UL+ zK3^<<$AT~_EmCKLW;^4EAd3MjnC}TGE)7$F?~rnXe#P1Rz>C+aQ~= znedBB46BeMsJ=c#&gGb?KLtqIk7gH2jjQ`aq?;TC)aA}K3AqSoyG1G0oTw8w!nykK zCIVSz0!YY6P05!0f|Ao_?o`C1D<}TS4}@KHY;E zG;5JESG}%nKGh`pa<`K^P7DnzcN4N!8NmJH+3jm*VqCm=2v08AERT@;R80B~@BcDo z_n@0xE(y7%RHcSxo2I~qXBke@7rYJv8eu$86cabWsRq+K89ZC!yMyb)!K4An`~F%h z;rl*q`Z)1B^n(@pBi{#NWB0wqZ7%&iC&*W@lJ&!!PxEa&#f0p@=5XjufevYrFE26p zB!lpI-(l>{?RtdhIXICI>k0sp{~8UvA7X#3ft+e~9{G;+aE9I&wJRI3XE6LmRsK13 z?#a3cRl4nB`HcqaUlT60oPCr^#!)QGGd?PJj|-i9LJu07j{}<~79w)5@YpLJ3qYE* zqs=rOciG)~w-_=qGQppd_IrFhT!g#zW>;Q==ZayQ<796KPyaYzmhD}rcjNd*tNNC9 zb?$6rM2lVY+U~iFXIHPmuf1TfI}0{o{v@2rDXH@KwKK#ry)%USdn_Ltkv%Q0=Slx< zcJ3&tNcRP?frD;5)P$D`J0k&?st9(FQ6S$QW6^RK3>b1B(g*^5C5hJ7JD+neVstia z{Q9b?)`hEMj8fRgebjSDY2WzjU_j^vQ1#Mb-eb=30<= zK`|($G<-3Sf;47n8+Y24o@)M2Tebw8COdmu#|j}FAyVP3;8E2mel!-RTBjs{I`j`m+CY=!m`P<20E{uwjIUg+6v zC1aIT^U=)7IM-W~{nZ@t_O5DOvuj;rXnlGOilzD%bfrG3b;^lGOs%{kFb}t96+gG= zITp9nbdNu^P7pWYki>0#%G??I{eEw=iR)9b2YC`qJkDJ5 z`zMuvK3Q&I^*Vpc zh=~_&=&VODB{Y&|SQ?zXl<(WBGd=;L{93>IdRJ zDg6+*VcGvVD@bYocu2$XIR5^E5#^g4jsO;UgF`0X(0%>&KgrDPPhR9=CorpvD8W%Rdl21xruNvoZ=jiDkhWHSvn@4 zp_r73&b}B~2O93ps@H7IA!@1Dp@gu1D`sh-%<$b~Im!soePy*wOYVO$?Dd)a%dv|d zH-{Nhr^2o|+C1(2n2F*c!tN@PjYp4U)sgBNRWu&Ge%QNCQPmpmZ--^1{r&^MYPG0F zQ6~3PacdZ9yMX$;%*9izkK8a2_Qgesw9%AMMQk8at}s$8M8;`G1o)65f}Z7xyh1@q z@NJA;XFBo5QL;<*iq~~Lh(m`F*@RU{Cf)Rmr1ed7un&j9W)+SghlS(jE3gzpO_aIX zjgz1Xl1R@lYliEqN`SQx$Qb|%pKMOu-7&(qbjp;X_&GkODAdAVPRqK&TdgpDTD2-XkzcL&n=@aC_?75Vxdaz2ji)D6ZM0aR`eY3S5?>Gb2K=b7n`Nk!v zvA3kpKP{QzZBX8cbC1?({eAM>cd(yFA0bPtijJO%1v#bMmWw1u zs}Uh7h3v1Ef!DgoifJG_1>!`*4D z+iL6}94a@guw_V^)==cH)+)tok|gTo&kO6O$)a-qj?-f1`vHnfC_0WgHMsRU(0TZh>tl>gvxSNP8Ue zzGVVPE$DXnjx6mH)ob49mybKUy=%xhp1YPV_`4NqGTfDpKQIl!hM``2-(8F&dFq@f zH1t3Be{0Y#l+{k7(?&9kB4BFd^PVxwZPD`uc|twLym}xK(>pxo2ReT{eTE;mZJnXBC4-Hxyi&Xl&UlCs7gZ{*!CIx3`{h3E;#bcmF~7#X4f@odHm@(*(Zfvn>O3gQOEKNrn~T7N8!~*g)}}b>2iYq} zeMJBzfsD<9At8EURq1smdHVB8>7&~>VDs?eib2#NtrFOAp zDg$HhoMRYLZ~0cvW%t@9YTHYmIZvi9;!35Pd4AUKK~;=-3YXYZBevY+yOzVq+a&^3 zV?BsW5kI=oW#bYY-vB}fm}sLRH*Bv17$0H`vLfw z^U$2wJOOp1H4j%Rgv>@g;84>wCyRfWF2N)k;oo99cE&ktm^`}xS%r1~botkG|1)i! zZo)4PPU-_ou1y%jGz+VQ*1VIrn5E%9{xFr$0u4iWY#glQBj3MUw=WDqHOG!w*m_+A z2z{U^3}7?hi8p;WVCn;Y-b`+I{eXcUIZDrh&cHm`a0td-!M2_-$;wqOx)(g8Er7?W zQO{4nV0&d0S<+nuR6A#X=j$O=av`jiOII9S_#h8hs>L}SQSmTlRd63rz#}CkdS%g{ zMRYXe(eE3*yEGb(In=IMwy1y4=@n`#JH0wa6Q-gRZ#(5mEYcaolUcHy)3I7o$XA`$ z-D~j0IJNIi*xil*3Q|bg-3U_z`jd+Lik2?c_;ZiDS~bIf!J}zxP09cZ-wYz|D2;)l z-;+y;7GnE#JIS-vAKp!P}=>T`DMyr?oWDo z|92{#$m5BP@YbHbbjSJGG?-V@BF5v$f}UU_60w(@$# zGuB_q``*oIApBL%Er}eu=d>BGg6|JEL&M0Dr^%8#Ys!WVdm0Nw@TC{ZpAWuChIXMj zb7YLzm{4@u+>(RKxlPa$Fs=3yfhXIG(%S%woegsV>4Lr}E}kK)*KoR~*_Pi(k@DFp3KLF98`NA`Naam)vitmLayGwkHll#(Y;z zjov!I;)Lc`_B3K20uC!v$AQ1G_aPv-lN!k}eX&klMTDf-iC-J+PZZl9OQ)q*8oY zVadzNcXbjhdOwG0DJ4 zK{U#a(up+wiYAqNz~X{jW4DNWqND{#cfVO}64{wcuxOnf9`w}}Q}Fl&eenU_TEm={ zgu)t8HPF^VIK~~M4XTwBu|b2I@aP|*J>d;X9+&DdUV#WNgHyVj9U*qCQ-d_EU4qEK z6cc^rN>C;o|MAMqDyEGC#Dwnmb83x_Z(M=Q=pl86m#KmIDkntnv16ZMR;zTM7w@u; z5?nYmypDgVwUj5NS@M(#{`y3f+IxXMY&c1*r16;|CJ5)Ik3@HWz%^p|>0tMV%!J!% zCvfG?_*gfJFRh}``xC`ZS}ZJ2SaYPoeWZm%>GK`>5u*vsXcmCnq|MlBO4;{IK} zP2a}K52`fiv~;Z`kOB*q=Au4zYZ!Q!7MNwix8YMvru}dp7?Hyc8a=#~QT7{oWK>8N zGg)4td|R#oOa-piTzVVaO%UfaEmD{8Q)k2_Fw8cBP@^FQgweN~3j8YeS9wNS_{9r1loP54 zqD7qG3k##eqCnwGzu%Yti?N%t8~6y!1It(s53IOSV!T?rcip9e&&A7KyNB6ti<^Ha zYuafZ6xvZ~Gx_q87&eOBJ(Xm2SPg5UqBJWiWnmr5gfu?kq{z7QDnul}dzDr{YW&!` zR1{_g543^U0H@qc-4OAy#I4?7whG!dp67hA#RJtaNX}z%?3Evy1#QkwjXJsp9R4Vl zGT`5VE7Kvt%3z{w3H`Ya2x=cM0~R&#Zh;JV!GwmQCj`Qy!O-F=C2B^4A7Bz&u>tYG z=e}8y?aq7JM}HpGT29DywnENa-@`#<4v-hAQ%#Hk6yKq!zr8v2&oxiRkqs#QcHw>v zlxVxCt<|<^Suou^TAj(O0;89#be%-L951=?EHx$mol>>BlGS?KbKWk?KQT58m=I%p*|En3VJu)k*Zp#R zC%MH8$aFAsc!#=Z5%qX{Z6`-V=96gK8MJN^EW(2~vg}oRfDlfGZCS1RT~Qc&lF+e{ zg6jdd{u6kr;Nu~(5Vn9a;Hyn7)GNgxn>ejj|CKypJo_RqR(^ys>GBQPYI++psmYW} zAHZw++3DpPSd~;+S{`QUO;B5W{7Oo@QugYDLo%V_gAGADG3L%D#?EhM=~4faU|Wgk zd0~JO4DJ9Cd|kiI`pWx6f)3|)30>~l!Om)?(gGgp0AU098o!wKu8-mohUyYg{bxBR zZ!f@mcW^|waK>I#|0CIo zgs(OJgGO}Gp|1BUE*ONUYSq+p7RYM){Y`LpNh`R4ns2?3_3yHXtyju=DFmljcTAw6 z7Dw$s(ZLchX2qGMA^o9|xfV}wNxud^3pJ*YCwzEme&qeT?`Awg^uVU>BtH@jDNv~A z4_Q+2?L&z-ZLj~Yt8>ZL?btg_SiS|d-%Or)5(&A4s_jqD2j~A5O_TkBT7<50Y}>yW z@?ZDg5f^XYnWBX!V9#fHYca4;x-=Sey+{CTN)LrJ>*% z_86Q*xT0ku_~&5dnhmA~R9;@jaRS%O`r|)dXq21bi8G1$RSCLBx_^vY22qoPm%poe znUU7LuAw?pOUn0$S>1%2nPalN7Z-I71b@jsje_lxS1|LX7$l>|6pD=!FGR@ zol07Sr&vHIWKAxOg*a;lTXua6$ajcN(5!s=nvQBN(=)Y9juR@>gm3JG;fdqU<;5m` z`iC6urVi{3$>p8AX=mXW@ip%}Wm}ocE;uFDO)Kb^uM<=6z@Nb+L;7~BfmyB-#xM1l z{HToj|CayOYd@7=31Tj1td5;1*G7b`{>w!Xl(Lp6?Fhct}v39QpSmC=I#YF8Q?tWrw^7<{MKk2d!WyckbyqB&;a3|nX!M#T40M*ioO~I zals{|N1^1@4h%rD&;9i7zj&<_#z|appg?=TIY7J4d;zK7`-V)1n1w4qn}3!|jwnB^1qSgPhokj z6h)k!EYgzFj_#o%zx8?c@j8ujny|GYM7itZu1Gr|9Ne5204a4=_5zA#t}Ubl6*hcm z#Vm+tmYHXQ10?WN>8muLJWOdxQkRT{6iKNB4X64$*1V|hg`&||)UXPM!?x_evV7Pw zOX!f2pX_y`b-0u@BfxKhD;KR|*i6SML1?0X>@CU`*mp5%oSC&MHM{iqE}wPcCxKD| z*%s?@$|SD~G(7q-T?$m&4ZC3H=+ne-_U||8Z!8; zke_5HOf0wu9#;kS@&S`|y%}v}07OMc1}7Cut%*tD!00W86fn}-bjtY5Flo>8jeGLZ z4R#QgQO}2!%6p&3ad=BvoN}Hk!Z|0>$|<=YyH2&vdzv~WM|g)wW!%~Xr-B80$L(!K z%d^;c$2s60Wk6*54+)8QDwZ+=*6!bjMwtogE*f~W@2x%}eoud{l0N2PcVxHpX{(4Z zco(%M90ZLwkB`6<fw;M` zc4bA5)t3qXkZm!{-=17?=bMa;RK-Xd#Gf#DYp)sFTf|5VqOGPPv|0Q?mb3j6_v&El zjjBw!Owoa0k;c;LiD5jES|D}F9?mS2G%&Mw;;3R zXpXl59lhwbRXS^@5^hC+LL@P9YvvDPK*xxvRs?3wh=famtv|4GdN=nMM-2T|NrRI+PK(4UPH%KX^)#$p?74*B#r9bjN!Ie4gt+@=dt zJSDX!GUH@iYva%|`tQ#CG&i_qBW8a3r$-B+n_=77rd^FslR4uaELDG`OOE=P^z2u4 zv7Q9{_Kl)ri(|}J6b->dBtIs=BAqN*B$jfzyR5u=;JqA^emT81Mo{)VDJ4i;-;Lp@ z7&BQeU(gO&J^($h2%xSbFLnKg;W2^g=_{x$Gjn{1LVQLLUJr+m5BK_KviwP5+G2+W zUA}4n<`KocGmo)ka&G3-Y~5;uIwg8a zlf$D!Tz33CR-#=?*VnZyfqFXatqg`xviGT(X0A`iVHSIKA*v?>BuuuCxK{Ny_~R+t zZVucwZwX^5CgVl|hnrWI0#2MTV8uLZzL9dDf7(@~rNDu=E?XI!;xCsyNMrV>j+Hf$ z=q!VS-;`Zw286RU3+W+RJG{_(vhh z)C?%J45nRfFn{y8&9z!kszn&^;eUPWg+gzPoPi;8G5YQDS?~Nx)h$UPVW?#|M7z6N zWg?lB9Uiz=F8IFyDk9b01rg}5&w=_4mOz3;9E+se^s_PWtNf*|$WkGfG_fV?Y4mf# z`)b>oMJ8j5hm%-3Ao+ZZkNvQ$fyffwR#m)Zr0_=9Fm0nxJvMaRUx_#sNo(9_;~3vo z-|QG`&lqc6IQ*C)ER^dZ6Z*lv(lw*5*{7b;@&+0(#Ggv9fBEjurygo5#XV2D>eFou zb827d8lr3VsfVYSSH&m4igo%2C@ShdE_}XkVEEJ%j!eHs_=eFnw1ZFYVYFUbb*pWP!l5UdC=Yzc5h1aB2V+UwBh}hQ zk7DhXVy&g$zouNf*TH=$g6&=h{R}1By^imhi?#95NM~pAGjJs!;&7A8IM*j>Y z`@N3unTz&&9BZ#^-}6AqTFS>)C;!KfL@}-Uq=j-ye{!2~+MHs2P_$cviKbDuQ*s8JX{WflYvop4+HqFW%1e8>> z4?J#Shy4S*aW9u_`ldmQCmL?PXNdyG6(oA)b+jRPSh9c_1%r|W<+2os?%em7rfjnz zp>~h3f0W1YXn2hu1eDVZ8Ad!fSpS|$>gADYkJiT~TpF#5)Hhu^CG&L=t&rrD8XH(&TYga#Uu(On3+=`g?NP+r-MY`!K_ zCb;L{g-MSU}9a=iHwkicHv> zmW0*zqUb&a(LIWxd#C4f5kiIPa(O36Ua^bzv|4@!mU(S&+VY%j(uySilkb3Wz5!~} zf6%>XwUsxphWwySQ@fA646Y6pR;+D6;r+J{`#u*4`Vtfv#N@&gZ(|K4p+KsaSdP@&exQJBm%k1cjLnbY8oIeaIHI78M2f5jvT1w$My zGXsr)PnU`)A(C7Vv<1c!^#CxlHP4^YB2_p@z^;{SNo5!@rHaGB7A?li)x&I2E!Tq` zR$8+-^((1jAFasUF-_Kv?xlT&^)_49@f_C!Z?nbrS*3WwHK);aqM5vJs~G%Td<)mr z&Q@#DfW_*8a*ZX3tY3$Hf5w0)P9s>yVzGdLg|^*o;kT?ag1awqMFJWHS%g+aMf3v? zkQvq}*kKaS5}Rwp!qZ~wfbMwXN3Ti&@`D?SBN4) zn%+BH(9qeZyP0LVjB|RoJX?yhkll|BonK6;RP1dB^V!1H(!oWce+KzfvIXBt?wA#? zmpCdk3e~FkuEItv?pY-%D}J|K}400pxU}iD-{>= z7CRAHE#aW9f2MNCN3J?+jgWHlmFNh2N@Nk3@sT2CB0y!p(+ZeFoa(h@OArr$LWFsT zYjjzT5d}A40aJ>~f7UJe7M)wTptsay?K1IE65NWaC<^XJE$oV}i)bxeK0_@`GVa`R`qVhX#^PJq7>@dRtJ@rJaS=tWmXBxah1 zRMXN=hWmfr+7Ke8mQFvV1;jexFJB$6FYdB?bQH)?jm`g!e-=DqD&M=scK%1PgLROq zvo(z)zi&(?lgXQl3;6G3GO7RfyUFX(?EJ0z;J%P+G#Y(PQ~nE+3b-XrIs2?x0;NdK?*6O{BfmfY`i>`Ism2!gMBf^o zilGUPl^FIye-np*VHuyTUJ)@lTC(KKNY(RPNQ^1&#}2+#bWAsf3iqfayh;J<<+e6bC={$8Gs8U zyt;W?lv+VW35>cTu)biaIV?Qo`xdnWHWdnk_a=Ht7x*ea)1w{&F4f^St$a!X(q zT1w{fw`36aT^@d7PqO+sJp;Rratdf5l6xjKkt`6)g#Vtmtz4p=QKkWD3Nj=kRB2Be z3d+TFe{C_*NS2h^!^#)+el*a2$+g>pfr#TQ;d(uW-Nfga7E+C&)Y4e-<%r5)#Wf3b zCfS&#d;|kYU>lyr;R|Uut!j`JHY5<(IRmE0>?SPTjZIlKKc9uXB=?WATjF|RH6=`n z%pcvLi<=)qO`a^kQ^!j(Doer?Nqi}UuFR~ck(mUq*(x*N`okOYq2rw`Q(Ivuvy=su{T4E1gh;SpGGr>17pin> zm)~6-fh&7WeI$Jrq5AXXBMy?`+|Vj5 zmcju_33C5eZV+*y0a-28?zZXSrVj*?LBK+;;~RaG2kny7KxsvaO!H(pcG>9T7xfwZ z$NABW<*uU{>uARM(#%+O#^z(m>SBgnN=vyG`HTgUHHFeuF~TYe{csx z@MiU46Fd$If|L06!)#MoX;oA_B14-Ll#nYrkJ$U$+v&@m@xCoR>fTdO#bf*udR*3U zA%4ZiZZ@fhI7^%3>xxscWzu=FyyY(J+jya}dbIlyYmVUVZ0PL5<*YiUTa8I= z7)7^k9C8}j4n2#I$G1g)oTyP4e>owZQ40)i%o5EbLR<9YlJ&AFbl2ARW=hj}#MP?J zYPkhC0uLj0C6eShQT4jor#e1}1@|yZ55vJ*k)_PwuvpF=W9f)S{Jvr-wjew)gG(H}>7yWI%|xLhQSzqb$(ft`?x15}D#^O)(T z>_jiJC|Z*T$#Vg_JMi-ae{)|j-c^yg2-l~usggFBm3@YC^F*;AlWca!(_fh6i@xlb z>x~x*8E7{9PyzqFH}}n-jVrB7#EI!=cW$UDlg-cxRafuk8_rZyJ#gR{IVp~iZ<~Zj z0cVUkoJOn00?u9QG-XU0q4?*U>z+?f8HGZKaX>LLH?he zqJZnhz0FwQh9`O*K@D-i4UaqHZ?m;OBJ?zYy68kaJ^ zINDi<4p>;5sODO-2US7hQ)`Vv$zbn3Ik4fz$LhU7jV{Y~y-s(xnU(keQFIxR zH~Q9^z_Yzs+`|Zt*MAO1>^+#Qi3he>kLh}Yn#0Z4Eu?Wq?KTs3OKQ|1mwuN`dxH?e z?b>af&fnS&-?PQWz1iVy?cBt#d_kMNd!r+Jw0V=Q?B2u&?A;6Ky&vSg*ABixo*}mI zj{bL9$-Tz69hmvQgDL%syaw3+b)*p1Y6$knSN-~o(AFbK-^BYfQ&CfgSjq~wgM(_<=8x90UQP|6g5?I-r z#!NGrBb8d+sUhNNpy3>z8S6-mU+74U%9JHXQ~A+Uel(STd8YE54fz-1?GRiD{ZfR!t_6p?%5j>xyU^Ubv!3s8;ljL480WL&Ta+ zC0j6Q^pHJd(3e=Hp}{Ec$wt%rj@b%$x?*ycaowcG^;7(+^nMS)@l!5VdPB~*IL!$R`6 z+#=sHUw^ZT-MV6O44I}pdUWethczO|A*JhG_r z>U&~8a{FO+J~=J_>%8)>mz96LYDUkoz}TNe(tmKgcTh3r$u5-2->#LIPo6!c%1sWU z7_MWK;;(iTMy4%oHJ1Bwe&Uq?95q^zPY8`gvLv8^JR}Y)3B+2sQ5<&PG_t*G@N2UK z-1X)>6frgDA>_KOSW;RjM99(xgHSrwIE`gYr;=K+%I0T*h{sD2(PTMZiZK>S8DG4< zcz-o%nTlpdno9UgOCIzkkIdY28-#T$(pK#+rS>)q2y`^0Vio7A5>Ek~be(4s{R7-6 zxtVH6p3Kn>UAuv7qjl7CVT zmFsDkgU6`Np^z?BzpcNvtPm~tv~2IjgTQTqCOxDt?x(O*wOM^y3{~!cgD!1hp~`Jk zTI6a2>^fgll}Fjny0TDQqtd`zO)s6HGmSt?cw&|&un%r&VPX2)+HE3Y)p1+ee!jfV~H5gUt|a>9Y%@1!LEsC3VCDaDUej`w#x< zl3@LyfC(AxCJ@;It8^y1d>FlP0Arj`*iUoHbV)lD@8UZq0r?3S?&BOq_ zA3q~|Xt7xkE1mM7O#|sy&lbX*AU7=Jk_Bz)gd5#&P0%FZ%cwND;eUjd`5ntH=gfA4 zh2_-AGCfE@qjs|psaH$yQKZ`QR0+<=s+EVfn;B# zfKx~-W3zmECmVr7*njAl`*yfj;tBam{9s?npiOt}utCaHUI0y!VBJVC|1I@u(r(k; z0$rEjd9xCYhT4Xae}soCLtB*?D7LlJ#K$7^UC*7<@KJ=Up`VuG<||zUzh2mP!E~~e zX>f{WmQ0}yWqC8bsy3Nprf7jsB)!SWc;$0zWRG1am(r#{YAJVB@nLCWC^h-{<^xvn zch<*FRB4hUOZ#%O?*5A=TW@p!Ma{-r?!UR0A>RQNf91x}F@UX3m2UH_raJRB(89x& zxnQ4D#6bZ}eQb>cBJ9jV&+VEy-21l2O7|S;E(CG%jE@zE0@M^499l`a8s`eoHi#|W zM8~|0fk+e&SuX6^MVKY{QcK1GUODf2z2{@8NBG&)Xd4L%ifox+<~_I88dV&3btP2H zYL=1ef87QAv$=&usXRnUQeTsYj8*P^r~ZytzZTy#MlW5ycYqcNcxR2iJY(}n_>Ji59@)gOdPY+*K9vl1+ zf4V@8AN% z6!v15D394^PJ3+>cztPy*G?UlU{uSBq zHkPF&pqE_bq-UUfJ8!`emEpBCifiY#cf8Cp}m{HzLz2$>PS_Bh9Ri%&4iW;m*d zE;I9uWmw%!5Hz7T?&vbp1eiZuf8~Aeo|5Z4{LmT0tdT=98m#C%V)zAjxXLV1fDB;z z6s?QstI~q8%Z$u3tT5qf1{n_OYFAhW0b?AnXo~sR-?B-mQtyS*X#3gM(wSCTZA8bg zF=}NC3RjyY&9hW#$!OfLC;cf`9VGAwneBskOa?6J6gUS_4V$aN08y#ke|m9Ity)-n zbTcqgJvt*$*yr-OYHf91w2OUfB*0oF0*QN(RIA^5>bxzIV5hgDm)_^{%UQP9$L zQMB69cP>H?&FnI-{$s7%7EVFn2MLd37ILatw6?WaAeHz*a?PrJ>Hik)fU;}Muvn}~ z6ygbb!|s_>Y%0a)brDpq%9ZM=4V-2)He+_b|99`_jiRfvV3ogOf5a3CuuMj*Kmvy~ z0++@=K+Qd$OyWLG*OOa$X|?@Usv*nO8n7zXIs8crFt<8ywzCuLdIn!>cLu}CgCKES z4-G8A)p@+Qcy$Vo5@Cde2ks;0^pIQCDyi*_qV<}QO-l2|Lq+I6klj~Ctzc_gdBC>l zm`RR~m4sw1GU*2168(uQnxG10t7Q_A3_b__ra|+UKI8!%I^4JSaBc-c-0@*H>MMAq zi6+?C5Q_MB)Le#WKP6G;>^64!{q614yx6QIK(9TTB)JF{1WYL?(r0;>mE-{{f0~sV zT67R#HCa4I7qk^IY+1X4goJ%gx$ILn-Sw;C(F)-YXdy}9XHFZM9d@49KY_&?ORXkG zTo}^jA;$WCTdBJ?tbUb^W%pWlT7SKZULFDh=7Je-!s6)ZrROS|+4ifP!i-RvUlADE zZz7u*C%b2nVI60&_?<@)Jri;{e`d+(=b2%uYWypkkIlXx+mMs-jOh{5bL_gdcalP} zxWNRS!D}7N$uJ%-Lb)Rrj_sIhqnSe;DVh+L1ah4M#zt2i%FXM9pRqIGp|g&{Q^hre zm3c3SJV?jmVPlM$8MK5tuwxf3>I(is_cI zh+(OI=TI^ohUhM-nou_7=0Ir5+N>6zU5}`YVJldX+K*0Chsv^Z-;Wa z^{nz9N83SMY}=EmcQ9QJe>LB^-j@^YIk?Xb;5ggDW!87T^|{GBXKs(KvFGCyd(Q5# ztsG&!HGMstUw#YXNgZC>y1IJF(`qT}aPRmyc061md?OOBzY&4f7OC zc$QSVLT$KjxNg&=(3CLWu;@f;)Y*2nlgC9LAvyBv2+0B0e-Vj=qlgyh)sxQ>tq|QvkB}TkNRA^U#}Sfaw?Q5uIgXGVM@Ww9^_*i6 z@j60sJZngfBQS-#j=&U0V2bAyBZ=1$nBoXbQNNDB6h~l+rt1hyaRjE=siWiwOi{Xy zz!XD2aRjEQmpSMG8g4m;Qx|QGYReKjkJ<~@Z7I^GQrvUk$|b8*AVVwSnqH|9O~O&h z{@u2&k10vVl%!)y(lI3|zm6$M$CRXv2U>47-q<|eMMJp3%N$4(bo_LM*dcw{I6-se_>Jqn{ms6ouQ0$cK2sxM8Ny=In(s~ zYiE=OiRc9hG8vJPAWN#*16_}lrb$R;IO2)YG>S&|=V#|<6Ifql^daZNORiVh{C_ME zaanp)e5uB+DVp-JWD%o^sc|SC5+g^BvAuEqJMe+8&3-nEd$iyY%Uk+~Y00O9_4ilV z-2AU33I7A-EgS6trx0h#`{k5dd2PrmMwO(|kT;Av3#F!qyfoz5dt5DpMiJ3L&(E_Y zj9TdA)REE~JXuPnl+jJLdr1fBR)6nhq5pd^55tH(Q0d>r;*}vCw8o3v@w4@dLq4h_ zB|ugg@`gE1{i$L9%oFqAwWsE)U(QuI|20!ujm@9`Fn{h#0_Z#c-%P%%pZ{-Oy*Zx$ zk8!EYXldl?=B@f#vp9{6ru}`s?{GW8y1*Z~{@z*ulW#Ox(R)T{vW92LJb#ZK1F@JY z#blA!IwC8o-ijcLSyIh*4Mdjc@5$ur+81o|QItEU0~b!DSZ?jKE4U<&5B>1@B!7~t zztv*m#o~K%1p?5G6?5Jib&HqG>?6YdnN`DsAhikfh_j^>Svh42?7!cWf`#R+#8d~X z8@6PhTbhDs=`$m)RqtyilYj5Y|9f(chtQ2Vg#IZ1G|H%{p)o9{54e}015tO_gpo6$><4X;qP zoPvepkIU&b{%rpG0c0Zc*EFID{1;?H^Vbd4?1Pc{%s d{g0!-a=eb$@p}C0{{#R4|Nm&5)4u?;4gh0I<*fh! delta 109791 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 diff --git a/traefik/values.schema.json b/traefik/values.schema.json index 2dd2eba65..539f26ad6 100644 --- a/traefik/values.schema.json +++ b/traefik/values.schema.json @@ -1675,19 +1675,13 @@ "traefik-crds": { "properties": { "gateway_api": { - "type": [ - "boolean" - ] + "type": "boolean" }, "hub": { - "type": [ - "boolean" - ] + "type": "boolean" }, "traefik": { - "type": [ - "boolean" - ] + "type": "boolean" } }, "type": "object" diff --git a/traefik/values.yaml b/traefik/values.yaml index 84f35b41a..a850611d7 100644 --- a/traefik/values.yaml +++ b/traefik/values.yaml @@ -968,8 +968,8 @@ hub: traefik-crds: # -- Set all the following to false if you want to manage CRDs your-self - traefik: true # @schema type:[boolean] - hub: | # @schema type:[boolean] + traefik: true + hub: | {{ tpl "ne .Values.hub.token \"\"' . }} - gateway_api: | # @schema type:[boolean] + gateway_api: | {{ tpl "ne .Values.providers.kubernetesGateway.enabled \"\" . }} From bf37c5f2e32a47da186367f77e140f9c2a5e8583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 14 Oct 2024 14:26:06 +0200 Subject: [PATCH 03/32] fix: use Files.Glob --- traefik-crds/templates/crds.yaml | 38 ++++++-------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/traefik-crds/templates/crds.yaml b/traefik-crds/templates/crds.yaml index 84dcf5a01..a2c4de9d4 100644 --- a/traefik-crds/templates/crds.yaml +++ b/traefik-crds/templates/crds.yaml @@ -1,42 +1,18 @@ {{- if .Values.traefik -}} -{{- $files := .Files }} -{{- range tuple -"crds-files/traefik/traefik.io_ingressroutes.yaml" -"crds-files/traefik/traefik.io_ingressroutetcps.yaml" -"crds-files/traefik/traefik.io_ingressrouteudps.yaml" -"crds-files/traefik/traefik.io_middlewares.yaml" -"crds-files/traefik/traefik.io_middlewaretcps.yaml" -"crds-files/traefik/traefik.io_serverstransports.yaml" -"crds-files/traefik/traefik.io_serverstransporttcps.yaml" -"crds-files/traefik/traefik.io_tlsoptions.yaml" -"crds-files/traefik/traefik.io_tlsstores.yaml" -"crds-files/traefik/traefik.io_traefikservices.yaml" - }} -{{ $files.Get . }} +{{- range $path, $bytes := .Files.Glob "crds-files/traefik/*.yaml" }} +{{ $.Files.Get $path }} {{- end }} {{- end }} + {{- if .Values.hub -}} -{{- $files := .Files }} -{{- range tuple -"crds-files/hub/hub.traefik.io_accesscontrolpolicies.yaml" -"crds-files/hub/hub.traefik.io_apiaccesses.yaml" -"crds-files/hub/hub.traefik.io_apibundles.yaml" -"crds-files/hub/hub.traefik.io_apiplans.yaml" -"crds-files/hub/hub.traefik.io_apiportals.yaml" -"crds-files/hub/hub.traefik.io_apiratelimits.yaml" -"crds-files/hub/hub.traefik.io_apis.yaml" -"crds-files/hub/hub.traefik.io_apiversions.yaml" - }} -{{ $files.Get . }} +{{- range $path, $bytes := .Files.Glob "crds-files/hub/*.yaml" }} +{{ $.Files.Get $path }} {{- end }} {{- end }} {{- if .Values.gateway_api -}} -{{- $files := .Files }} -{{- range tuple -"crds-files/gateway/gateway-standard-install-v1.1.0.yaml" - }} -{{ $files.Get . }} +{{- range $path, $bytes := .Files.Glob "crds-files/gateway_api/*.yaml" }} +{{ $.Files.Get $path }} {{- end }} {{- end }} From 69ba344108415e2d1f0c69f0a57ea61e4089db7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 14 Oct 2024 14:57:46 +0200 Subject: [PATCH 04/32] fix: CI --- Makefile | 3 +++ hack/ct.sh | 1 + traefik-crds/values.schema.json | 8 ++++++-- traefik-crds/values.yaml | 6 +++--- traefik/charts/traefik-crds-0.0.1.tgz | Bin 126070 -> 126100 bytes traefik/values.schema.json | 4 ++-- traefik/values.yaml | 4 ++-- 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index bfb25b4a3..d927b19a3 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,9 @@ traefik/tests/__snapshot__: test: traefik/tests/__snapshot__ docker run ${DOCKER_ARGS} --entrypoint /bin/sh --rm -v $(CURDIR):/charts -w /charts $(IMAGE_HELM_UNITTEST) /charts/hack/test.sh +deps: + helm dependency update traefik + lint: docker run ${DOCKER_ARGS} --env GIT_SAFE_DIR="true" --entrypoint /bin/sh --rm -v $(CURDIR):/charts -w /charts $(IMAGE_CHART_TESTING) /charts/hack/ct.sh lint diff --git a/hack/ct.sh b/hack/ct.sh index 2a50ffc1f..06f7f69e2 100644 --- a/hack/ct.sh +++ b/hack/ct.sh @@ -3,3 +3,4 @@ git config --global --add safe.directory /charts ct $1 --config=.github/chart-testing.yaml --charts traefik/ +ct $1 --config=.github/chart-testing.yaml --charts traefik-crds/ diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index 1fe1ef7d9..cbfccd7cd 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -5,13 +5,17 @@ "description": "The Cloud Native Application Proxy", "properties": { "gateway_api": { + "default": false, "type": [ - "boolean" + "boolean", + "string" ] }, "hub": { + "default": false, "type": [ - "boolean" + "boolean", + "string" ] }, "traefik": { diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index c6ad93429..4cbd7a28f 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,3 +1,3 @@ -traefik: false # @schema type:[boolean] -gateway_api: false # @schema type:[boolean] -hub: false # @schema type:[boolean] +traefik: false # @schema type:[boolean] +gateway_api: false # @schema type:[boolean, string]; default: false +hub: false # @schema type:[boolean, string]; default: false diff --git a/traefik/charts/traefik-crds-0.0.1.tgz b/traefik/charts/traefik-crds-0.0.1.tgz index b27ef6d26118b4db53c5a9028986c769f37576b9..984a6a8b6c6c9f218bbcf8489a33d2b973ad0495 100644 GIT binary patch delta 119490 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

UuHA&zY-_> z59GJ3w+B!m&Xj+5=agH1ZAcd*O44XZ4+h`wF!@H4CB0{aCM$TC%yREBV2i0zOcrsiBeJCG zjR>-sCDmxxKxB#jo=m>3eZdYNMY(Z0aPCBk<=Rerf=m4P&<~$Z@;ABqvE~ym=HHV` zV1RBcoAZChh+Dj*W*-su&#dYm1ffkJN1QCA$jTv8p#S}z6euhoC8j!9-mnGx+%gn+ zOP?5at@>OunS4+F_t6y+p&LVl{wV+B_VT*&@1NgX|M4*=Bc(shi*=`iwI9q&w;!fI z0cJOUO%2BWqpIlr_CNZ!^L;jJ+|p$>+hRNa`~-iyS!Gssx1$%p8(t!Bc?}wlKQ6AX z@MrVa55N&;|wH!lQhxa{>On~IkZDN Vw8sx`|1SUl|NoTMWGMi&4gkuhkIn!9 delta 119353 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

Q_8{{IOv{!*fl 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 Date: Mon, 14 Oct 2024 16:09:19 +0200 Subject: [PATCH 05/32] fix: update CI --- .github/workflows/release.yml | 95 ++++++++++++++++++++++++++++++++--- .github/workflows/test.yml | 9 +++- traefik/Chart.yaml | 4 +- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71c88a367..bcd422a12 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,12 +6,14 @@ on: - master env: - tag_prefix: v + traefik_tag_prefix: traefik_v + traefik-crds_tag_prefix: traefik-crds_v jobs: test: uses: "traefik/traefik-helm-chart/.github/workflows/test.yml@master" - release: + + release-traefik: needs: test runs-on: ubuntu-latest steps: @@ -27,7 +29,7 @@ jobs: git config user.email "$GITHUB_ACTOR@users.noreply.github.com" git config --global --add safe.directory /charts - - name: Copy LICENSE and README.md for packaging + - name: Copy LICENSE, EXAMPLES.md and README.md for packaging run: | cp ./README.md ./traefik/README.md cp ./EXAMPLES.md ./traefik/EXAMPLES.md @@ -35,10 +37,10 @@ jobs: - name: Generate default static install run: | - kustomize build traefik/crds > traefik.yaml + kustomize build traefik-crds > traefik.yaml helm template traefik ./traefik -n traefik >> traefik.yaml - - name: Get chart verison + - name: Get chart version id: chart_version run: | echo "CHART_VERSION=$(cat traefik/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}')" >> $GITHUB_OUTPUT @@ -47,7 +49,7 @@ jobs: id: tag_exists run: | TAG_EXISTS=true - if ! [ $(git tag -l "${{ env.tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then + if ! [ $(git tag -l "${{ env.traefik_tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then TAG_EXISTS=false fi echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT @@ -58,7 +60,7 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} custom_tag: ${{ steps.chart_version.outputs.CHART_VERSION }} - tag_prefix: ${{ env.tag_prefix }} + tag_prefix: ${{ env.traefik_tag_prefix }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - name: Create release @@ -97,3 +99,82 @@ jobs: registry_username: traefiker registry_password: ${{ secrets.GHCR_TOKEN }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + release-traefik-crds: + needs: test + runs-on: ubuntu-latest + steps: + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + git config --global --add safe.directory /charts + + - name: Copy LICENSE for packaging + run: | + cp ./LICENSE ./traefik/LICENSE + + - name: Get chart version + id: chart_version + run: | + echo "CHART_VERSION=$(cat traefik-crds/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}')" >> $GITHUB_OUTPUT + + - name: Check if tag exists + id: tag_exists + run: | + TAG_EXISTS=true + if ! [ $(git tag -l "${{ env.traefik-crds_tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then + TAG_EXISTS=false + fi + echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT + + - name: Tag release + id: tag_version + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + custom_tag: ${{ steps.chart_version.outputs.CHART_VERSION }} + tag_prefix: ${{ env.traefik-crds_tag_prefix }} + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + - name: Create release + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.tag_version.outputs.new_tag }} + name: ${{ steps.tag_version.outputs.new_tag }} + body: ${{ steps.tag_version.outputs.changelog }} + prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + - name: Publish Helm chart + uses: stefanprodan/helm-gh-pages@master + with: + token: ${{ secrets.CHARTS_TOKEN }} + charts_dir: . + charts_url: https://traefik.github.io/charts + owner: traefik + repository: charts + branch: master + target_dir: traefik-crds + index_dir: . + commit_username: traefiker + commit_email: 30906710+traefiker@users.noreply.github.com + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + - name: Publish Helm chart to the ghcr.io registry + uses: appany/helm-oci-chart-releaser@v0.4.2 + with: + name: traefik-crds + repository: traefik/helm + tag: ${{ steps.chart_version.outputs.CHART_VERSION }} + path: ./traefik-crds + registry: ghcr.io + registry_username: traefiker + registry_password: ${{ secrets.GHCR_TOKEN }} + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e5ed3f49b..832e2c0fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,13 +23,20 @@ jobs: git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - name: Check if values schema is up-to-date + - name: Check traefik if values schema is up-to-date uses: losisin/helm-values-schema-json-action@v1 with: input: traefik/values.yaml output: traefik/values.schema.json fail-on-diff: true + - name: Check traefik-crds if values schema is up-to-date + uses: losisin/helm-values-schema-json-action@v1 + with: + input: traefik-crds/values.yaml + output: traefik-crds/values.schema.json + fail-on-diff: true + - name: Lint run: make lint diff --git a/traefik/Chart.yaml b/traefik/Chart.yaml index 91af7b126..7d4080045 100644 --- a/traefik/Chart.yaml +++ b/traefik/Chart.yaml @@ -29,5 +29,5 @@ annotations: - "chore(release): 🚀 publish v33.2.1" dependencies: - name: traefik-crds - version: "0.0.1" - repository: "file://../traefik-crds" + version: 0.0.1 + repository: https://traefik.github.io/charts From f829dd12ee8bfa1d8616c25bfe82fa44ec63b7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 14 Oct 2024 16:13:20 +0200 Subject: [PATCH 06/32] fix: add hub only when api management is enabled --- traefik/values.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/traefik/values.yaml b/traefik/values.yaml index 5baa12ee0..510526271 100644 --- a/traefik/values.yaml +++ b/traefik/values.yaml @@ -970,6 +970,6 @@ traefik-crds: # -- Set all the following to false if you want to manage CRDs your-self traefik: true hub: | - {{- tpl "ne .Values.hub.token \"\"' . }} + {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} gateway_api: | - {{- tpl "ne .Values.providers.kubernetesGateway.enabled \"\" . }} + {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} From c49084920fc4917614e07d2883276179b960df8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 14 Oct 2024 16:33:17 +0200 Subject: [PATCH 07/32] fix: CI --- .github/workflows/test.yml | 8 ++++++++ traefik-crds/.schema.yaml | 2 +- traefik-crds/values.schema.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 832e2c0fa..c76f9d9cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,6 +28,10 @@ jobs: with: input: traefik/values.yaml output: traefik/values.schema.json + id: "https://traefik.io/traefik-helm-chart.schema.json" + title: "Traefik Proxy Helm Chart" + description: "The Cloud Native Application Proxy" + additional-properties: true fail-on-diff: true - name: Check traefik-crds if values schema is up-to-date @@ -35,6 +39,10 @@ jobs: with: input: traefik-crds/values.yaml output: traefik-crds/values.schema.json + id: "https://traefik.io/traefik-crds-helm-chart.schema.json" + title: "Traefik CRDs Helm Chart" + description: "The Cloud Native Application Proxy" + additional-properties: false fail-on-diff: true - name: Lint diff --git a/traefik-crds/.schema.yaml b/traefik-crds/.schema.yaml index c71d1b799..09783c714 100644 --- a/traefik-crds/.schema.yaml +++ b/traefik-crds/.schema.yaml @@ -10,4 +10,4 @@ schemaRoot: id: https://traefik.io/traefik-crds-helm-chart.schema.json title: Traefik CRDs Helm Chart description: The Cloud Native Application Proxy - additionalProperties: true + additionalProperties: false diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index cbfccd7cd..82c5776c2 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -1,7 +1,7 @@ { "$id": "https://traefik.io/traefik-crds-helm-chart.schema.json", "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": true, + "additionalProperties": false, "description": "The Cloud Native Application Proxy", "properties": { "gateway_api": { From 55ba3a8487a80caf412021fa3c291fa1c6a17ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 14 Oct 2024 16:49:23 +0200 Subject: [PATCH 08/32] fix: snapshot dir --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d927b19a3..d0dca5f9c 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ IMAGE_HELM_UNITTEST=docker.io/helmunittest/helm-unittest:3.16.1-0.6.1 traefik/tests/__snapshot__: @mkdir traefik/tests/__snapshot__ + @mkdir traefik-crds/tests/__snapshot__ test: traefik/tests/__snapshot__ docker run ${DOCKER_ARGS} --entrypoint /bin/sh --rm -v $(CURDIR):/charts -w /charts $(IMAGE_HELM_UNITTEST) /charts/hack/test.sh From 77095819a73ed8518d5d4652ad8c527c5e082770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 16 Dec 2024 08:11:13 +0100 Subject: [PATCH 09/32] fix: remove dependency while not published --- traefik-crds/VALUES.md | 36 ++++++++++++++++++++++++++ traefik/Chart.lock | 6 ----- traefik/Chart.yaml | 8 +++--- traefik/charts/traefik-crds-0.0.1.tgz | Bin 126100 -> 0 bytes traefik/values.schema.json | 14 ---------- traefik/values.yaml | 14 +++++----- 6 files changed, 47 insertions(+), 31 deletions(-) create mode 100644 traefik-crds/VALUES.md delete mode 100644 traefik/Chart.lock delete mode 100644 traefik/charts/traefik-crds-0.0.1.tgz diff --git a/traefik-crds/VALUES.md b/traefik-crds/VALUES.md new file mode 100644 index 000000000..bdeae3953 --- /dev/null +++ b/traefik-crds/VALUES.md @@ -0,0 +1,36 @@ +# traefik-crds + +![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) + +A Traefik based Kubernetes ingress controller + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| mloiseleur | | | +| charlie-haley | | | +| darkweaver87 | | | +| jnoordsij | | | + +## Source Code + +* +* + +## Requirements + +Kubernetes: `>=1.22.0-0` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| gateway_api | bool | `false` | | +| hub | bool | `false` | | +| traefik | bool | `false` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/traefik/Chart.lock b/traefik/Chart.lock deleted file mode 100644 index 7a83ae7bb..000000000 --- a/traefik/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: traefik-crds - repository: file://../traefik-crds - version: 0.0.1 -digest: sha256:03a8641bfa1d261b699d166dea5aaa21d9e27bfc2328d157dae3809375709260 -generated: "2024-10-11T17:04:46.473483814+02:00" diff --git a/traefik/Chart.yaml b/traefik/Chart.yaml index 7d4080045..17a713aac 100644 --- a/traefik/Chart.yaml +++ b/traefik/Chart.yaml @@ -27,7 +27,7 @@ annotations: artifacthub.io/changes: | - "fix(Gateway API): CRDs should only be defined once" - "chore(release): 🚀 publish v33.2.1" -dependencies: - - name: traefik-crds - version: 0.0.1 - repository: https://traefik.github.io/charts +#dependencies: +# - name: traefik-crds +# version: 0.0.1 +# repository: https://traefik.github.io/charts diff --git a/traefik/charts/traefik-crds-0.0.1.tgz b/traefik/charts/traefik-crds-0.0.1.tgz deleted file mode 100644 index 984a6a8b6c6c9f218bbcf8489a33d2b973ad0495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126100 zcma&MQ*b80xAq%jl8J5Gw*AJoZQHhOJDJ$FZD(TJ`ey&XeNOG#buLcVbJ5k^wfdr~ zSFc{{haUxn0`y<)hZ2a|KthqhNJ559+JlqTkXe<%Sc%m_Q;CyJPF0mnM$OvNz}DD9 zS;3B1!o=DJ=(5|x4VyicoyYG&DL=!PXk11yDyO)J&zH&bsJIAubiO|MF(cwrodAYp zzLshUMLsb@_PDVZ^2M-<$g-e>WSe<_CP71G&B0-HSB2CB=G&Hu9@)dbrLZKk)*|(L zQ#f_-Uz5w@4f?^u!(;pLa(=vA^yBt?Uf*9lC@KpJ%lq8ipI?;A<^5oHe9iARr%X|9 z`fMHaYF)Xj$}{|QJ*jQR}T!n+}no&o4myuMJj4{QsXDmMgsD^06sFb|XLzcm;u zCbo~MP%b2=a8oDLBR42k#*;%rn(E24bFA$<>16pRE_9wHR;jR7kx;vU)2J=Bk6p4~ z_qL8MmO)0OPl7(I0H-8Udh|7xSP`HC7-{d1X1H5=kWGl>T*-!bwldaYucaksmU1X| z9lk7Cjck`Xe_r0^A79-)IXJhr$0=q}k2t9d@KP0WbK|3D)o5}`0|BWGm7i|>9k@b{ zm5{mZW#64|k*Snsi>NZ|T+ay}1|amWH&Us0XVrfdBYB=RgeKkGqIVkZXY1KH$E&dDgiVm5;Lf(=WO9u!hKd=Kx8lfW`iym)XKQsP76`y0m| zLrhZpa=&co1g6a1bq&Sg>(h5yTKC;aBO;aYhoh|C_+VP|6sm{enaWI`*U{b=<*zuJ z`iHnlrms$vx1gr^(H~x3?-h=pJRJUezh0TQQ8>cj=eNiicO z=x;RDVtl!&szPl%5>lP=po77K!SVUK0FPa7*`#2rfTpZ8)uR_VW^<|{M5lAgw_gQs<$S~pccWamaC98#FnRf(OmyL}1A zS81l9#!6giWt@l^Ke)51=4a^R&mfKtN}HgAz-&)+vkX{l5qb_neCAK3@v z6XL{1(t9&6(Q&j-UceZx8ufkH7v&qB+^WdoZOJtfrMjeIZsXa^~7aubXn#D>|OWE%)tpLVOQO+g?t>>33JMm4Q|=M>95)OdgH5cTw{CG4rT8 zBRT;0jf#=<{>GmD4odC+KJ(L9RQmn1zJFKreZo$OpRjt_OQqXj9CjjFBI^p35ifw) z)(Fb92|X{g2{((JT7`UXEv_upE6e5r!Oi^|w<;vy!V{4R4gr zDpY;kQA7elHqZ6O#;Jq0>ej6Ih}^8!_8~+x0%n67nz~;ukk|slT_o2H7*RvdO(yxdjWmmGR%jx-O%yzt6;mIgd zmh$5DX+qAdv*=&<8g@KwdAr)|Ukg03N4_+co)4y~{6n32 zG7x(Ls`xV^a$izZj4UG=MI{3t%m4GqT;ArA57|g1 zr^x1@s!YVGmxRbuj0g)4NZjdB^BU6P_)y+t@A-6^6=VT|rxtL{OzKsBlJl&R33Z|Ndb z>X}%&Ln`z#K*8-1_5e)VXw_-Jt0Ltx|1*1X5eAIvf?V8lrnhz{|sU z6B&3^hJM1&(_Q_wr4Qqm3x;)SFPyPzDt+z+=8FjP5lZrydXIA2gCuZ4H7-Sv%b`%} z*X${2F&345eF+vfn?m+MniWN3naGyWE_@~G#`Id!B^HwF3bnG(<8dI*T#0AD9)M~Mf=vq`3{b0&<mxk2t?Qx$X9P zBPvTLfnoL5Cu4~f4hLqJev+%U=pnHWbsMwks{hHmtrIt`(V(kJWPPb$FZ>4VL0TNn zIY85x3@Ad})UW`?oqRISA5^O{E{sf1`6SnA0ow|XTK$`Fas&JBrA4OOmSx->=87g5 zhayh+42GukIH?%tq2#Es{>R6cmS=euvU9hrHp)KZQaUj`Kb0)=(aW^ds5pftGk%UP zoyf4Ec;IH0Qx=hdJe6nXtY!jB&RNA1LGRIryY3%a-H0AN<;>!-;)oimN7^<0CGZ&f z3KKyhvtI#+lhCv$)U|8cDx}UN&Cob}fUi7J|Vaai!)=OH&^F*?Icxn$R+?xu1qL^qhT43Tz!Fv;H83pf(j zN_}q7f7n0-q=PxkYzMOvDOXYW?zvPnx=xq*bi$-osRr#>bvR}A*S9v>fkqInYLS&q z-UgBwB358OFK!{Jn6mvLC54$;7}DWNCLvn<+qgJ@u3U3oypT%2tK?&m9gjHJ%W~vq z7;|$&@%@%!w=I8Gt=OjwthN74Kl!UUR?Q&-0&-d)&HBJYY`53=O_4coG>>Q7d&=qK z)%>8Ko+Uf}=Y=@u)0yM#b9yHZ`C%3LWAPi^Yjttv$DTK%=j-O@ zA&lR*tF!gzQ0}0Yhu`C&jNg`J#}TfsD-SI2kXFV6X`+*}d8G=)rYOS^N$cada!NY&RMcoUQxyk> z3bdmpUt8v}1r)=ya!ui65olSqme}8>zwUuDpr`TDWdDpNu1THNn^Xs5n~bPFrbZ!I zh_$iFvbT9i)i87#b5dJm*0K+8Yye50l(?L-TJzOXA+}c2cqE>F|KXiJZHJyYz_v*0 zYt=pO$Y-Oz&lhC+uH0>GW%V}xW7QdA*tq1yny~TvaWwD73))7PvG^u4f^mGFvaYM% z*XN?&4-4PxWLcW6_GEF~FEb%e_IvU7&S&?}Fk}p09Frq}mn{e&tK9HJiv%M4l4Ni_MM1jugcaYs=PBcK^KV;65!6*hVA$REJLqW`cq6@rj?Jb;dY2_|d`0Hw>;}*#}(hOs&o>CF> z$n{}7xLCQeD)Bf`E9Vg!6W8Z^egE**+|k|H#oZm`=OZr*z5XElN35SCOlq_Aofn5Y zQDT@9WR@jNK)Z>H7W)t{y6;EHOO#)~KegS_ z`9@l=6KH%vCNQ%~Dpc4<{x25MeoYz?YaVPG1eG^5b3~6;qV!kKWr;JuKst=u&oaW|=ilcZ+1SA?f`9 zQKroO^3dV;~79uzr@N7j=q%=%QV7GZa4bwE(|g@8SmEZuw~T^P2Ch#C%chE!pX zWRF-jksw|A=y$RN&rfwa+FdMGK$nq$hsIm_GKLkjI5dXlv5GjD;uQ7+Ws_G+uVx~= zugqPhNyq2{r?j-ogVDjrlO2Y7a%ojnDJ)_ZgOy^*^Y!x<%1LUWqZdw<3t@kXtghYb z#=Y+Sne?hnsDNNKtD*wELX;7hy~sU+elh?ks6E02I&rB<7%Fm*uuc8$d{Vs2@P z15y1syEDuCeiJT(h9&`g|Kf^k({=8|+^lA-!|P9W?~N|;8+HF3-1!wNRd__i@}?%b zisDNuLc~XTvnx$3yr1aJXZx50C{)v;={k|9_RnoI zcDKX+eFh;1`|Q9R+rvEIggQ@VH10mrNX1PUmcuQq_cTfIaJn|?WeZt7{J^M;ykR2Q z7)`}T&STL27iMPS7Nfu%4qp>)Qs$+W<g5btJtMQ`XR-q6%8K5%BZ(Ev-iuxGE%%2zw)=osmjH@9;T8kF7L>PLcG_!IM66>gB;|Gq;iG4h{ z);B1@j#_Mlnut98r;+bfNfa-q5d8PNc0&zLXppV?l@B?4o?W^c-nNe!B@H*klGm($COiK51vfBI23+bu8!h-19-K>wf^n8;m?x{}TdC^t@sW`COJ zy4zKA#xSlxQ>$MadScBJ9%>^`Xk7qRR^ZI)*kYCQ*?!)2vkZzYqP=!lv^P&wpd+(m zLwGqAYZjF-k&if&LLKS1Q$6k1DFv=nomG^LJD3@wNi&>V4nz&cj#Lazr9Y={?M6%1 zn~+eEdMrf8V`WI-dReDwb56AZk;{?Ho~LT7UyY&PUR+{V@X5JQZ7BrE-$*SvsbDQz30y;#Uu@zqwJxpr z*+9L{)=u(U^)uD~yy6Z>1$taBc)DF57g*lldq*ead0U0=L#xph~Q4u{lT1q9gHJJ3~6K4oZO=gcvZ81N8HamSC zdAEQ5_Uv3aT=9l7UrD9X&4Jv1a;|ST7p-lR>IqaMQ<;~JnAfSriWP;OubQ)L*p&>K z47+l(Y#>?<>Zd%&@q&&QQuM@_Mq6JyN9Ws+HvFMI-xBJGO|& z9f;|9URKsM`+U}aqqbsw!}{GID+eZhO^;h`SHUyZP5V4x$5d5he#R5D^s=1`FhscS zGe?`|^FFz>E$xy6H3l)1rtW{oSKMxSBJ<_*p?>o!6Npqw4JXc8oF}uPmE^Nn)9tAB zEa+e^(!4uXN=#75s~m5*5yHvFT0)PMJf!?UEj(krjl>zt{b_qbV!gTb&fw}N7L%~~ zutNr_O|NP-O5OmD@BbAYrM&eFq5WF*#SLFBYHu(Q}MwaTF1S*g?zChKYqH=tSq zKCa+IL#(KHfRCgS5&c&reM;yFFvq0H8YJkqoB8WG?9KLzcri%s@2tXbvZaUsX<0pmTIOFZPpg0#_47_G(kb2Su5K^ zqF+$n5?ruGAzr|nn6pj7j;!_pN-)^JXN z2*f7$k_cSRfwFXHUn}YHd@43f`Cy#ZxLoQ;2qgwX+vYGeU~|~S^TZ26t20_MrMV0G zRBW8<3)_aE=s3-vz8Jh%uRbKYJ_lH0 z=3lsKsL11_lN1CDpQ!w*(7hMDsR~;W$`-Ho^BjTC)MQz~4 zW<9bgRx~@N?}?D;&R}FhS9C4bBZYFi_O7K8p>9qSU}L^m747U|U@}XYx%|YR8Ttx( z&<(pfD;zb;7TJqJd(TcoDc)lx6_c%Jkbs^MS`{qqnLQPMkiwepoVtV@nX$H;{B=0u zaHpq;8YIW{JZ{S9sl~Zbh@@Hfiz@2e!bhKv@T=vI5x$hgxPLFf=1ILOF3FELbj zfqIAi5R9NN<1ARcoRq+X3BP=#CWw=m!3Rh1l>*;W+#=|^K5w7nFx}QjK(4&PE0J3Z z`Xnu~=o6+_9?*-P&xp>o*jY%`f>Ba|wp$VbjpORr1sa+nPE+3*#XMKC!O;S53)U?n zXO_z0NF-k?Y0Kd`Kcoy}H?0 z=8(IQ&LK1JjZw0rRYwuHC6CM7@?}0ciGk{WpR}!%i{zhyUZ&`GLjKaM^fs>twrG~9 zPngJVjNv@k%?t+sxthH#yj`uXzrU13@S+g7@;W&zZ1uZEXvm z=I2tbCfI`2=(KC3#1Laoi>k_(gv285N2&Hd{z5B(#XOpRi7m6?g0kOVMNU2&p0g>% zVUd*WaFoS%ptOESU&@wqp5>uy?tiK~Uv-aZ+5{X06rlE}&VbNYj9A%%HnfG4(6xS}wc_6vNYb?C85;j4^GZhQ$J3U$%bShG&^um8epbDM z~M_U<< zp~VW98I)PgY+_i^p*<%PsehmO`De^$t0VAgUer?hB4`zYK$`K3HOfkG79a~+)3B{* z`jBH=ikpqmHSc_-s-AhlNLDDhC9ip>F!^Yyv-W(uS$%b&eR+tX3ct#X#6SJdsHUAV!eBKckxjCVJ@{@YA;&l9oBZ{hCD9k2}xgbqbOY|BhirEYqX+ z^4g6Lhk19meY#4EMD688koS*jQTYuBxtWSp&*}p~&PSI1}CXoX@Vp0U(^! znQOohl4SsC3@V~R-?{ePs(QsCLJN)wr4L}tr#-lvN^74p9LYt&3_=y12%(}vd(!O# zDXWrFs&?5GaeO5M0fR>t3eJ%q2(@SuwpMoq3Sq7su>9H}Eur|8jVC>{UjTZ1aUJ43 z2{lCqdB~7U#oN4+0B+zD6zbzWz7}6yz6=xvPVjq`6(a&OSQ)}}y&cHeCe1b%7|@%< z8k+5*n7G@5o4}y?aQt`DRjJZ;;YaCBolQ4 z>LX@_8(WY#9c>5ke0zst$No4ruesHQ77Z8}e*+xDG<;K7cLiMLG@w~F{)B*g)Bc{5 zHWCHMRpgor<&(pBsk=t_2m*jSb@$OH!ziTo?)?)fh;hs?bv>U@&~w}K`QCSIaQ55n zwgmTG`&jd~)XMH94EgmQ26oO*UUkPY!-EQ8U$yQP2cA;wfgbWi5>b|Q5F-lf!5_W(md91Y8 z0V?3WXz&(2r_|xV=tl;vY#OYG=HXQA8CNX!diq^-|JH3Js5P4AW?NPNTT05b{NHkC z(N9;_G_ew3EwUC)d~bRJp4>i9hR7!*st{wp<^_MR^{LA`1kdka6JUN6=Murb^rg$+ z$JWfB$~qOU#%!cPx)vDkT{V)nv9JnAkw#kr*shcmxX~hhj@z-~>o0rlgZ=8qNfi``Ks- zIx!TJVf1LV5GUl#zLXHO4@Q)7EyuyDk4O@JLp`@Vie;Icd51x%4LsDk0 zTQ9Ud94tl)E>P8Y$sezZ8OO!we4@R4U7qI-rBEBBJB-(lnR!TXldna@8+`@h=L<9| z`e<;|x;&-Tt+6?ZMiX|s_b2nztN(s`8P<2WBXrrEr=?dBUDU+zkLW_&xi{RRC7BW>nC=WC>NTTLgYAbg_r-y6Q7u;#zZ0z^kbr0Qfbd{jLaMgyF_~= zumBJV_BG??HV|wBcL}>h{orH2#VJontt1<2{ztXX;Tj_(f`O+QBc8RkvAvQ1Xsrt{ zl1?nf(p%vL=LAirMTUa3)V|`Xhg(_CJ}_Z#MSJcJ#*e=H&ITCGW6VMr_vgyc zD{XMPSnf0xINN#F?a7Cy1`iLxCa3|Ii|#ot&5^M7sm*vOwkx*W2=3nmCvVFdFaP6@ z7me0ktA73R7i|Wp$W|EBY)_YN;B5c62;g0r_0Yh`VQ`@6h-w7u4Fonf7>z$@(xo8R z3NJcK1bQor2hSm+-Wqwn_x~`U4Rk!c^U%QysY(<2A1`{D#elMUDZJPKfZvNjILwe3 z*6s!*F9YsF%XR=`st*rxnnTu)u#o%?sI6i%;6r#-@ge3o`HbIcOa|_@U66#`DN+1D zNg7|RdVdN$u@>}M05*=2Q;krJZI7><;6TIb3j=RsWym~Q9}j^EOdn4t>zc}ck?mC` z?az$CWNy8pMN1eJzU4tc%O73c-2SNqxQwZGbI5$j+{RH~ZkX1f$MZAW-?DIYbW!Jt zk=_wIcVY_*)otUb65LZId&^3ngS|LxZno;_a< zl>{LL?EYuziQ#hJ7s@<`SXQd%7BdU7UfjUvSR55j&~V9BvSSb zVV+GhHSlHe+UDgbJkoU_b-6!&yY&+`V_s*dpNHqktc{nIk>WFaVK2@r)I820fcsJw`_$= zi2wmrQ>_nonGw}zkiL_79Oj>j8PB>KUlGH~#orAOfo9Rn&- zWf=uxUPU~qR&-)Yvl&MkhvYDQ$yBnx-R)O7k}aO~gvqR3jB?8I3_E#f3e<+y2FFYE zc~)#h??;qKXZzrFtd-8RU2JKtA_`z;vCLIftiPuZKiK1$?sri4n_C=$z1OrPl5a50 z$(34qj=d7}`?+}BYycIopvka(TmxB4C&29(CivEMf~>|btDleeVD(Jr?~SW#d-WVF z0}_y8;Z^Pa^vr!LYDsR|@7%;f-TZo-zONEBKdp!vdf67+kg+!zRKEOqUAb z;?WL{L9|-n>C`g`s=0|kO7jPaD(`-y^p^?NK1rj%Vb^cGW{s9Rqwn9)3KuDN+`;0_dzoxnTSPqPi_c4ngP&bZ+3X}t z69+N;@u?SDwECeE1Zwp3-R}eEZirNP-kDJOCJX-CB6Tsgiatj`;>$U=97CRKIlh=+ zXj8wjy72~ff>*9YwvH52qD|3&ig|&J)U}a#B$I6@37tXlVgbpc(|k#+yb5yI6x>T7 znZR|3`3NQ<7`P!6mB}3><-dnb~G*aIt#<#XNxkx zpRnwzkQg}Ws@Ex*n-n*$M8DLf?ZUww^MKYwm*` z_z=~|7wx`>NA+6GyR;c&{8M8}|8-W7S59z_veNPby&b#E=>mP^R|l<<;k*M`5Aplz#FT)c@b>@2QHkO>O8a@pkQ9qsK-|4I|M#uw0*LFDc%T1k+G zZ#^2c)=7!LJtUe6yYzlSyF?Uc0o^_@%{e)*Cqm&GR)R z%?(z2qnXp*oq=qJTU3%rr(J_mj&J16Aa*RDOU1$;Jx2-OZ_d{hSX2Dm?50Dw%Sp6# zB1P#9AW`yI$q1fH?OE9Z;)8Y>hqgOw`%qyhx_@P@`C^jP0|u_Ome=HHwCx)>neuYQ z#(h|jnq6m?)hB$n-ky$*HQc1_s>Z18HaLTq4|McSJHx6i36=C%NiLUfDIRkEYs04w zUvr@Ex#g=KLOl`ekHN@^Zs$rx3uHvs6Sd%gb6UH&w9Tg{0+8EyOt#Q&eS~xe1;5Tt z0N;1|>&{gYJ=8a}I2{+ptEZb9KH<;t$UY96{D}^OwT1!bO{?=X_#!CVq!BlA87_nN zsva}+px9Y9)-z0ZFN*g)1rh1VpV&GL+9O%!tyU|-K?s<}D8*cwNeloARCUIYzZC`#k-;Y4B zKh8^+rUyefXJW&C<||#jyK9(t+{O(Fp-p!jvA)}m00IW@?hrI>+!OM8L3eVJ5=9+O zs3GdydSoW9_s_<`@%{P3+tc&gTd?mJe)bv%+n}!)$2pVJn*9fHyRJA}6!ODBL89-N z6H}4H4;+CkEjl(B)t^87iBXC)fJ~E^`XyuHBy2+Et?4SHrp*pSgzv&Sx+_-=NcG*c zw&$sv6tY7+hPmStM&GV)&{5$ea%eS{3UMk6-#5@M}pMR1xBKk|ej z4i0oEBKnj0^44Mj6Qp0TPPJIgKf0V)F?f}FMf2vpDM;cf^164(^XM(qZW|e&a9z`0 z4%3?t(_h(6{5M;~ke`6K3Q;10pm5v0ON;ip%&tB5aMI44XgB8a0sVe-I;3pEPs#M! z=_UM%>A|GkH38C(j-En029A!mQ`V_VnQV`=$YUuaO8G4)pf>*`6w3F8Sy5jY0VyK! zTJEUQt`1Zut|~>%+NZTGu#NtJI@G*!JAy%ZpwHjw_%*MEa${q*+iTBWLSnw?Owt}q4ih9d2cfzB$%VbX#~-hf&(VZtk@J%L)i$wS|0vI6!#k-o_Z%qfh544ErS6rbzPmD#R&3x_eVsG=ekj@y|FD`v ztIJ*fN93>PeqfI)#)FMZZ$mN-55RUpp)ui5Z8gm4V!rGaWrFX;j!4#AXSjBptPRP| zleu)QLl8qn+){G@bO&Cy{$wHYgQO9ki$FZ*Gy5-)hDD2-Y*hRp5!GlKiRYz8H_rCb_6&;z!cAY%_3N6xp6(f% zF9G`^ck0D729I8mYAn(S(-hFUwfXLxN(8D%po6EC_Wq|vlIM)>CL+oPgjTvE^inMM zx!SzPcs!Xv7yp=QDr6wohOF#QFKd2pt(c5iJW{$PLErCkst|3{J2=gK&Voo8=NNn{ zJPo}4Tq|RpOad-D6%zyxQRKPhHnZ^Xnv;G-3ohgori#|f#HZ>=aHd(Sen?QTtg_KO zpN&xHU2Yi(0*!mMROZKqwwq|16^uZybIJ@$&qR6AGQdylgTlkdO)L=!(}@0m<1+&R zyXnHeM%;2S_+%e7N-7GVNr%Z+)H3(=mijAKNVmwf*fuiUrl$6Nd_ z1Vq=ec>f@Jar1dRki43O!FbXWMy+pnS6rz&>AiRTZNna6+k92gsAq(rh^ygQV^h$X zScw>?-u=edF!$S`i%Jv>C(fzdFc?+CJhG;Z>e=-aaFHaIybSQ#=^-cof616=&4OdX z#9!GHj24x0IvMwF(Hy$}-lFJf$}y^==qkmixPa`K^$X1pMahxa^{ z(GPzt5+Vc{8wfj4E&?f9D7U=ZMA~()fs_a9qr^+nb{;M+Ur&wcIl-GMY1~V{`WHP^ znf~y{NYl$I>1Ixi5N)9x?|4%4pyK+S)wF97m zo#f-i0bg%E8|oF#85V}8)FfwYJ=JBP>1{8@Xv+q7Rxpf94|EAEJrOv~4nM=d8+ny9 zPk^yM@kre#!B`gp$9V=?EF4uapBC({@3^OFBlE2REvl5Lwhmh_HR$a(Q@E?yT7B$9 zc2o$0?5<@vXIn?074)_vLdTh1%9B8362H~DNZV=P45`tON{z{hiT=w@iNLbw z&ZM(9NrMb@6;|a+%2AN@j+jK5_{+3QO1TYwhQDa4)d306?>@6cG^#>-F@ zI&j0uFL|c<v&LZK-0N9&2@+V{o7ZF0%ELc!*rw%-fr5;7FC!l zLJcve;S)N8OOQ|Kwit96V%m@p3EK8>ByAcF)by8z_C!a&^HBmRm~cyP7n+gZv%fYF z)hLX(aqpDvjaFtW=H0@n)Cjj^te!GiJUgJ3#~w6PL4AbKfKr5gR^)X2+Bm&R^GI2d z3QT~S4Ks|-XpVz+ZNFnT} z1Xig3!R{XZRp6Htr^&`S3$XENS_Zfu!~1jxxT#n!_}1t3nQyMF2D7)G`R06E4Re~L z7K=KMo9JBU*6Mf=T9{mw){Xp+Ygk;CmyJSA8aP~)pA1@HntwK|eDtHhQa{#6J1T87 zX~yIaM8r$9vS>G?QE+WOD@R}&W3|#5q{|>ggW=fC^w;TpAKe&i^xw+Z?e#G&kNcPy z3>!xe157$yK4qrx)%p6M4Bt7XPy$W%l;PN;^w(`w{qT{YQ~iL2p;IB5)ATV7S^5{O zxcV1n84b_aivBJ5_^c&ErRj|`0G|}jQmflq9W%6A-&hJXN$(%-;zoHtDTt<5he({U z6^2cPXB&N#_KT~B0Qe>T#T$(As#x?k+C69ctB=Xiylnt%Y$bGWh3Pgm$1TmH{+$8K ztL}^K1fQxmc^YIAe+D_pp8*UtnNK_)$HX>AVytJ&4!h2-IW7DgqDq|LQ?Q&A4?7rl z%7h(~;#`nzVWXn|&U3pZ=$(O{U# zLJnmgCNA+lEBVnuP0mYiUUP|P2zuwtIT}k>bAOBA9os;?L31vN_MqpMd9&to?7NBD zlCZf*VQwJq7=)p=B8_l?8gU!@2<}>1E1+g;DQ*}BX-RgVxXoehmOy=YGmOoIRs;1Q z(saJZ-CejtPXeQDcw1cX%9f?GLDLGz!zbb5u8%@#evHKuv!j3 zE{4+cRolZ9c*x{;a^RRqIDMxca)ClO&0e7p!ocS}c&X&@_CwzaQ`wzH)J=wNzt09x zYRo--A=`Q81l0`IdD*euk}>*nK4B$^&yB!qkWY#LJ-2~x2=W45^j{%x@B5?VcBKZ% z^ebv{0r<*B`Kn)rH@kuazTZ62Y@2?}HH;l=3u5wyZbq^P-1L~uiV4ar)aPGrfe5N6 z$t|z1&*md2q8lV9)Ts)c5{3G2XTxvsa`aaGZuMDg;q-Gs!uQ(BSA~Qsc9?u-$SMoN zfwP2ms=p}Z??ol&nY5Psbj_@o4qR3V4w&`*v1aLce8b4M?j|$PJ|Tm{t%=^9@8&%5 zVC#&-5sdoCGz?2;)@QfDIN&KVTaDk^mc+}QkLjWdm5Ys?>Zji1YHcl+Pby3;QONeE zEg~yZ9fpvJgHnKQpQ+%_g}0>}@pm_rhscdflnLeF;8L|QuMhO;8mcGSHSq<4>GD*h zlJ5x&T4{LWy*UexyoXVPnz{4A^ZEoFSzOG<#bY5v#^y#;nmv--=;OL4Dk>&U{kN&q z>yMw(2-4Ob1w2b&JGyu4Z7zz;knKNW5;uts>Ub!@*cD?1$5WSS4x}J7_SlSHK5TOhd?Z)@uN@MUD%A3Dj^OLLwtP>brp*Fjh?j ze=28u25Db)4NTe#$ zUFFhlX)HvE-E=0s?J{YnS_SrHdEb?mRIfR_$u3L)9Q&@>}fr=`l3{ddt8indnTZrjE>>{n$T3GiXi zT*i8C%(DiTt0oS|eHw(zM~}TBB0+suPh)f#Jx)sb=W{sG{}fuXI7OH{*NeYs#(l^=c3W#6=_J~aYYy@xGS6gFQkll zqw#+uWeeB=3PdO#HUCYNVI5<+L0F=*9#3c0PhJ7I^uU2r+ttk96E0~7iaB24O!wG$ zqY)K1zc+&c!w>DA+^&@I<;WQ56>Uy`0_oc%Y3%yq4j2 z3nCMVN;uDzpZXJF!(&M7EU1PzC8nDw7F=kjmwdga=^sU-#+HqeAY$gXtOv0+dUyY^ zWa%3{Iaq8Uw)6xqeIWtYVF~_u?t>*k?T=ta;{IBPatZZyi0v8sKqoK{yOiL3{Vr}h z63y{yJ4_*T9F8OBxHfd0Toc50<3_(wMJGvvrsRkq|C=AP5rp}CKR*|mP4gvwADBnk z0k%58IDQHKe4CrSgXW3#cE@?UU2iO#rl%ieaM_Iv2A8C~8+EhRk=NzAd}>=cI5OG& zAK;h)QG)N%$2a3>#NM$ICT zCYjYA?uVW{$C8)QeO8u);c^;+Hiw2V67}r}(vXvMX9KyQO z5j(EOq$ILv=q7*MA~vH4{6o#u=69j?o1^Tbro(~!t1OS$KfCkE-kqG?2@(AlkWW>o z!^N#WQ83Bd$=}p#>JUDK{nR72#|JeXC7nZUFk=3>I|pwr!i0w#`c0wrxe)c2?S&ynTCS zZujan)AKO#5+`2bEzVjI@$G*{Mdbl=_%pQ!b=9_?3QAhQEvhvYFt_ObmgwQa5Iehe zhuV)G@YlW5bk20(#)xX8#D(w;K1Fd$ll`1>l!Vcu=BriGDzR2-NZuN8=DYZBUTo!r z)|LyxuTmVGoz#>J4kk!CtkV3yQL(igP6~}`i6ym~+wxA)SdL!)9*dh(?!B>!b}nl| zqrZQGN7r@=TEY&;DfxOrr2tvJWmMR=;To z-C}yx5Ps*<-z1WT_rMl2l1RvaFaxp4k+cp-`|)Xu1Ifx^77~k2&Z$0jthX@j3d{ZR zB`Fc-`en(hj0nm=S}};GG62`6AJRdT6|!FQ`~8CGs`1nYW05Bvm$ng&%wlKjDKR3j znfXrj3^C|Vq>Dk!H>2wS#v%uoEGR}G_VJ{gZ_z&;Fx&T3qG>zDjC5pBYX6L#tO6s9 zM_Ska8-@+t{|5}KS_64QTSSOp^iWQ058SgjZ#0DxSj>32g!Yf|y7 zLUsDjIa0x6Dgdo*5%YV%gV8CwGD0RPg)UcVOdDE@r;ODMMZDDvw~63-H0#w2FQ!$Yu`!?Xz0%6k?dEHY zhpjd?*aMBAon<>aa!0*t4M3HyJ(OBJs&gN6gjn&BS}+jnedGjzzC=Bt9^2JaSA(bx z76WCVpk{{Nfa1^hegPRgC5CYugy5RYf8}9)o4fy=hY7+;9OH8)otMv?0dGWvZMR-#k2ZO!rW*_o3#g}~q2Svxv7I*&DENVHAgSg9d^ zpk}rR7FykZFmC^IRI*ogm=VqSPa*~~7phR;TccY2#hjN*b=vit)=@F?GFYdj*kT*x zq$Si3hui*_f3(J`GR(W~bvJfp!14$sNNVOjWPTa7gTs?C>qT&KBSAZrta0^{dqcjP zOX#K2#g@HgN>6KiGPkRE#I!mUpfyDG;KHwUxz>6<*Ib2Z&T$5tgB%Som+WJm?IhG4 z%#_@`oW%$(MhfSF@n3P6ZG;v9Dq#UZH za0XB@yio=YM`FzM5}wBBc1c2}z~CPr4JSSvlBnf*FauB}`uPpG2lFyu0IDl>LB?jw}osZes&ac5lPk zzj>fCZU2yyGLx8Wr=LQGt7nA5e`avBDHgkKl%GANW3+MBH)VzVv<7ox40PZBPZsuf zrC_K2e@BHm(End5Ea;c!|D?iFC#i>aGHN?97wCR5X5lHwdsaLwa$g3ob?^}o>NB&G z(pa(e8I8%?>INmG3rZB1a=8GXhB966W7ok!1N>IN>jYcCOqp-6&6Wcte9nlVOi=If zg9W=J`#S*W-m(g$)zK=LtCaU+S)EVixFEso5TVOcmmE*S5xwQqw=|-TxS(Czb7g6F@df z549Xcr2dh!;pfBw3*x6LMbmZ&2A(#v1;3Fn6+=WdK5J|GV!x z6vFwRd>1hB|EBMPdiek5yLdGJ|Mp!;W8&a{q_ZFjnIIb5B?!Y${o9hku5*^p3m1~2 zh8n))UTYdUM-icYfV5~@g!Cyky#eEA?~^pB8CSd}LFQkz8iz|D4mJ+s3p*e98swBVV)S@8>2$z$JN&}XA*zqCzQs<-#SGaCBKti*}oZ@^u_X6bvCPW48$!dTHM~{L9!a~&~UTq?_ z5fs9Gu^|^aU`r%$_9eXz&%ogjD-`mmvmtD)M#4uyV zSC6?pTp=AI_Jx;azSDrS^wukc==#fpjJD{F4?>i{I|7HK3f*4^oO<_AH z|5wW zMP*Wq<_a9W##$lqXAfifDeaL`<3uxhpzD3QSlUiMmDL>@4k?|^qAzqf z@;7SY5k+|;e2}VzPjOYDZ@2786zrq+iT1rzZ$;D6+OpwdevP!l)T?7QHJi0vq0ii6BiN7LErm=s!^;NP zMkXF%%LvJ@wjFdi4zOx5)`hbbr1OA^fvIo*f(9fJQ8HSQra#N#xA+%0$0uH~eoKCb zw%00{BUTF(jC&u#*D~gVX<;*cifwBS(!jD4f~$IhIJEQIRuFXg9ZO=;t#c3pI~W*Z zo{X@r?AK+VKl}|pBYVC!?8RiB&w(8{fmfwHTZ(opKK&pag#nVI6MgfZ3b-Q(uy%sR zJ{}W#;S_(V@TTZ}ous_S+m?keE9$P1r9xVowm-2Geg(%#Cr@58yyCzeb^aYyt!;%u z39{Ti)*-@q&t{6qCbq{ckn}|LV6qPLV#8u5M_x>(BHU_xFxAAyu40xcF8}dPJW{hB zcCWC93T%yK<1pPoA<0=#R)!x$GYF2%uuxHxU62h!QIf+8xd`j#njl-v_KNxAR~2c zq#lWs8%jc_5IlHklyOYt#<>O6SZI5c_UI8zI$`Mk6IxrDrJv?RlldxQeQdY(Skw#W8?0f5(h?i)vAO zOeU-x!;Dk+H=1QF|G6dAX|273jKw+dz61=1)oMQD?+5~=)@b6%j7|te4e&4%u0s4A)AkUi>;n6G{_W6bdq1P z=QzNMpVQ#x)+ZP^^XzO2F3R~=?dcb}pfs8~w@?#+>n!&Dh;bYpR7<3o{f@vge4D#U z&^3Q*oQCrGohW>FKil7G#`u17SVZP-px-ivkzlj{LCNhXBXwwa;^hW|k3DM}IT&Le z#DXW}ASo6VK~7eW7dGGDGF)oXbo$5LLP#_v6W$!j;^-e29z z5m%_ro!+)pUsUZQv5El~nT7Iu^?j~aN6gBVM`6&Luo}B(_*atkRYEnDf5plvQd!}3 zzk5mGRO~&yyEbcTA(8#Vrs|k3!Grpuquw^Qbnk9Qho0?neFSghIi2SF`&K$T-=JPO zI1oC*}7Gzm5`IIsNoI=(U`vDl?fcuvDQ_PBAzB&&bjgZ{>` zCmolG8ztqQP*1#(_(5EWttjCER%Y`8hHZzC)Z8 z!&($G>iBSxstppbcR|;*d(O!p0YC7Ym@4IbLXb%BHu`V;{QOBSz8pdvd6>9*SQy1k z?{~Xpj5F?~eR2@JuswV(zt@4UOCcvQCLGGGJrBn(lARNv^-ZUG&AK*!)~+>A}A{CzvUl)SCw82=m05Le6AN$$S4o~c^D$ZX^|roT=PzwZC_)EFgO^a`)@)g5+^kjmB(WnG4wh4`W~+D>9MK^2{@W}688noapbsRs zz~0otN>KMpuX4^bq@Mp*1S}6_TLSsGLTqx~pNaGMyo{}4`%_SYTA>&&<=Em&!h$ zC+0046h3ic#NMluIV%G1B6Gug>U7%yGl%ZGw%bwG+d20CPO{%UPYAen^}S^1P=K*T zTtLm`CqtGF!FvU1*RD*uvINl~V0#=AcH#Eq2V87Rz9ei3ay~{NsMl5=(S3vZ=cmPM z4bANLr#e+w)e|KG_Qinuz_W`a=F@(XirPR*C|piknyg1l)#(7ulm(~i(PQ#C1ccz~ z7ZG1j>`;(h`@Rp0VN72kF}I76mK{{)yUx6$kd;io9Ut~+Tf)~VcY4xsPJ(tYLlsyQ z`mFLb0Y#GIV1>HBxq8`2D;RU{+_^I3D_l?xDU)KS&#w)#Jvt=*kBjhDoh6^ z{K>i9+~&l6ydoS-FHZagG5D4X+W6}Kr)Cmx@!S8krFU_Pj zd5`K@ij`lNkKv1AUQWD$a?uLUT$LCUD}`%XOk8|8X;oO(sk`m=k6tdu?$RqnOl_b^ z4Hxcy5w7*}HxZi}&n7(_)(;*DN`h*5lZ@ION88J#jcC~MAZK^09gBXpvip+mp7J_2 zs1}9`Y$hCcP3EHaWYQ&Iw{MK}w>j}?o&k5Oa>}d@zF|vz%wC1uEB5T@$ zf~Tbaj3Kpv>p)TuY+riDtZw|IX(;;nf9uS7Lu*bgA4}V|X1*_+ppR}bwycfR{-ltY z1Uzky`dcE-m0ILv^j@F-GlHa<3@3zlrm}?ayJv#Z+*dn3>JjKQHkY3BEEX9+=Q1WqNQAE?6VpRF z1eyf8Vr6|dD@B=^*fn7mu8MQ~?u_xd++oU=%R+^Tp5C{C666*HzJ@dPjN!!9SO3s> z)^!|#Miq3}^Ve<-zVP>0VzbWp*m#?QM;3_UeGJ3K=ie!2>^8G9EA>R!iZy$}DCXu2 z4C0r1(~@;-#5+hUu5_9q*m83y7!(RIh~*v%y>6&@UUmP(h!Q*wC_wU2-nAOZ)t%|! zJ|hEA_#)FdUl{An0zg1I{UG15g>>dE=k+x54Q(mQUL91SmStGW1DOY5NS3$ax!D1s^x0z-uyV zDN%^@U}V)ut5oK86cBck^l(m=TYr2lOll^7V~7SlNmRXYP#ro0alum3i)1tZu1%PW zRR#oi?CZM4vUdaJxTUGqN@(xU6;RRpz0{CpYRRmB1v@=+isplNjH?rKil$kg`J>Bo zipII<1=IU;ibr8H~YDuf98AF(kmKVF?l~ zXsJ`1CfKA~MBN80mQ)>2dOO%8QXzDz9soM^Pb{)@D>nF~+s27ITe-ojFC2{q z!FpHVQI8mg_T+L22JIjm{qa`*96zF|Pd{_KiyN*{olhNCiTRs%G@Hg-652DC-KO;4 zW88POR%FP@zVa&sSR!rIME%J&{YiyW3NqO67g1QHe&V2 z2LzibHVT8v{CaRh{lF0e2u|QPwZ`yOs_ulVyV3CmtKqE!uUZBZjo?oUfm!id1xar@ z+G>K9nJTYq`Ws4h0DElGA2*b>tsw5a>n0Kzit#6cF+TFj79MtA?q~UfBDEns87uEdO_Q{LS8WuY%|Fzg z6#lo4wY*LXPB#Wwp&D&cq*;hI3KFseW7gGk*0zNg^-arV7nF0a-~)UwT5)Fp{zF_& zgaPd5SyU%r_BE9#3A}RyWXpKq)Yc zdc^ksG9)T#-M9WD+z-C=JlK@8xSEZY-EVfh1COF#IkpDEj!~j^R*srb&s{n*I@;=C zIQ|-Gx=5g-SoiU;{}EQ2)|}gEg2XYrT&jQ~^^cNLmyzZE?r}I{GTkh|d>(X|=yq<+YYg#y|^4~jAvy(hwY2mBJDJ;#~?VKSOu zqa_e3JH#?{{h9U7TLv(9Y<>F^lm}a5Rv+5x87F>A?YdF(8xiy}SvyeMxZEi`F2*&W)anpxs z0Z?^m=kQc!-^HpUD#%S^dS>ypO-n6VV@}YD%F(U>=mazt3~@8dpXyEaf>%YE^pV8L>GB!_DU_u@s}_=@+P{7l1$er>B#g82dvf!x z$JxX>NW0shV#z2vDF)JrOeAK?x!7OK@NC$xnG05HU$*u5s{PUycGsEYyI6(!#HH_; z4#aWX4$@qiTuS%Y32Iv)+GVhg_G-10*B^$s;TEZ3p$+dL-OY6S<10sT!qaHEo%l0E z*7#KHJSgY_DJsQ|Ihp-^c%GWtQTo=RU?9!#_z6Xx=Qt$HT4A`RVWC z$D_aaYA_lbNn7buvkd8vH(;KEQp_Wn(ysd6&a9O5pBC(9jMyc^M&$I%x;^nN0sC{>YdzF9hW0JMqv_tjZq)> z6OnG4@5#KxZ^$&&87KOE6^if)M~Z6T8wqAV@&d(_j9*q5#NMQg*IjMK}36DDqGcE&oo&x2^xjI>q(86K- z9olVim`ds&Lf)e3{91ajpF;b>a-~;uh)f!*oOA;3;nq@AEKCSjba@|Y&qtZzylMuk zXG+BIgj9)Rf0}$&WpM4aI>Xr7+AB-YJb_|!Brpc+B^N)Zh!t>6WGB_HS+m1O)$;6T zv|o%ia-H|s?W`8=$QdQ+m&0d{gcS4H7|4>RbkbwD)8m(B(QsCGxt9pEAG~;0`@Fku z!uu5_hJUB^UcC0Svvj8e#y6S(xmq>?XWx)fWYS(+g%CA$rW1-jb zy|G-@BzFz#rfD}E+wpw@Lv5cW;V70n&}~~_PMc~^QGmsQgdK5(T~m64)bh+xaEi8i z#d7s|$egrcc=R4R&0XLc6aXsJFy+w**)Mgl6Jn1!bK*F7M$e{}e%|-RUHXWq$(G4D zxo?_e(k#{QAkCgWF6)^2pMnbSdRg~Sw5+&tR@lx<1Jwg1pwUF%NvU7c3O%Dl3)^%* z1be;o_ZrIGP{M(X`^rm~v93KG-$qLvt>Wv=lxu51u#SL1uJIC|gWF4ugst%il>+90 zC$f4~I8}b@8a^s!=kcCltiapDc(v_Yt9_!!={mt2EROI89#>-P$S-^$qjK#_l^E%+ z0PUj~De0|nu85!O=z?53MmP9_B zKoKT8A@ws zyVc`(b@>AS5qkFqmT5zIY(nk`MYki#6Bc$E++#V2S9cwP%JI6Ya9tz1aMcr&r^Ps?=NE9h33<L{p~xr{UL(BTDMev;dpKbv_$;ak(4@3#HIZj!#ZIb-!~wr}vhybz z3cv%WG;pX&i(cEC|EL~CcTJ1H8R?bYSEvc{#e#1}L7fM*VYMA@A@RCryZsGM3t*jX zFCf86>=`6tR!HYO<4D+jKIo_-4hivSp&7k{@TchGm8Gc^CmZzcZlE*m?OT8Vuv}UYbX|I;dN^MlHiC$$tt)6<^}2H*;=jT zUL&$P(!4}=%146n1z8>0XD3ptc{2tY?K8KzvB6!#!U2Tz77u}0Z;QFpSad?(+gMU9 z0|hGsCJ^F|yz@x+pcje?c1g&{X&@&JikmF1+|B39haO-8E^J269IN0r9yo75zybW#l6 zcN7#`XO|b=2ypaWbu1g$l5+A9XugXIb2;|E zK2mEzFa3||+>7b96Y0D7?txj)TNt8ZP?KnX#JJOP^*m($(4Pi+0$tBttEx-Q65JzWGaq=XkR;` zw1L39m+nR+h`<)Y?Lnk5h+zb+!D(?y8~ohCZx2ZXO$NHt0k^ z>A;nf=xrPW-^gify#@}E7S}gyvn+9hHm#T zM4ku`MMJP~w|joe8g=whSQM%9I^c7>`R%U474#O!sHx`Nh$K!3>idCq#0i6-rKZo8 zaK*(+yMMw@P;{y8nhs**v0?A&1#i~|7iyjb`3Ttdj0&mDK%pQHTH;m@&-sd!05PWP zUrlH5t@?$6kgmhTxn*ds~H2* z5kYS|9?mKW+WsYu*m~gFPB9vFZnBwK15gT+DxJb*LVpEyg9h7uesOggcMSpIJ6`yK z^A#D0PHo*_H^rFyr{LFepWtvqPRsfD6D64k0&K-Rl5H6PtdM&eXz z|DmPytmz5!;doiJ!hhv>7B0p|_R)c#vFh!+4RvZfIGRDWhVpwZWI@)ZIJvqPI>3AG zJAbE!m8mvREJ;1Q389E_x;`QuG=%W{?ZIS^5y$d2Pd0Qwd+!??*d9KWh1k_F)#U-^ zqp>yDe&6#Xh5z28Ck<4~B*yp<)@H}(u95HhH|7hyJ$=l&RaEn9WoB)JNui#@l$EBm{AvKr^AUoUhJ^@$#-p)dw27&7jzz$t!C^Z ziOP&s~5F@-8c?N6w0TwxcDf1Gc!oF z6pH#sZbdrzc*&8&9lns?Ljo4ey6T45scaZxQmruVxV&j_gOncmC^eTS!)p z$=bJYSF0;t{Q9_EqqpL6imgR${2|Ssr6(AjgIVaXAHT`%l^TtiJp(PZ%0@w}i~r%4 z{gP!jPFdpG(TJy-6mc@cDV&SxsX%oTjFn2IHDi^Gy>En`|32^$x@*MdOZwTTa_4-z zBcF5A>+V#$C%?xX(;Li!@D20*dI-(M$M6-aTV)72 z5yJ{zfkWAtxM61|H64&w2z`6lwI z`E!0u|4SQIXO%k-q)KB7NF_-HUD8e+Xtt6C$QEYFPFSY(YWv3S9e^b4n>6#~OF9`D zMQqSTS*g%AdSrmM`ecs(oufkmP}tp6-^OqvSF3~T((bpnjas+?eHr(>d3zL`(Dnq4 zjb!onc7IGBU0gGK-+WHuI<`7%?M0V+81ve&w8@Jq=1KX}sy&DAeFTe8A)zjRYOGYP z8B6Wr$h7j&KJu)JQEdVIbt=wDh8gX{=18p(3E`Z81td5);r<;c)mi<74NA0?Nq3AY zZz@v4bcCmq53h-#V#AAbI6!IC7~55A}FSIjK#NX((Qj_5!=8Za;BUpNYL?sUfY1 z(llMdQ*x`P+pj5@=SFn2`w)7tIf8=#j{a6wj&F=gt(WMoW>>UnIEk0cEE*JA4~b$ zFFUt#)W!HMKwGwmetR1!i7x*8{rb<#{qqhtj;3jObjOslqz)y3i9rS9P72?CA6l4X zt)`*CJb^1mahkloH1iY@2O#XidZVWxlq4N37%Z9im`XiEEjOO4rze~H`So#;gTN47 zCe#?^m_eXA9b_35v48hXt;M6>Lz%zFv_VtbsfDiDt&`9ecocPO!czHrr}U3%?Hy|m zV6mAzag5bMbabo5jaP6Z@kA_hp-b+Ol)UKlJ*FcG-I;Xg3>0JLT$i~YQYV@i z12pis$WR;NC~1eS@OKxv#B%#Edy?P=Hbi@F=;W0Dn0&=H0r)HrB#gEQjv}6|tM^-p zkJ;7t9*57_T;qZXu`YNzZ4a`qhDtkM7MosZGB`{gVnv*Epy~BfcqJ(<;40bNa$Ew1 zVbzC4ezj@~mDQwOs#1j8EoCgPm8_pU6ZwgYL1PUo1}@=XFg)Huq5HT=ZU7rh|EYyM zh^06Pz&+=RfsJ-tLF}H1McZ_YQ=M3<5&=C(d>;M1!Wyx{R4bvAA3{&3&Kd_eiq_HV z{%0#xOwY@9dsM$YrWQ}w(0ns~F3o#d8ehaY%-U-l^`#$H>!GKIV+%CHsCwIB>n(8s zw8WHe-KB+-?=Ln%!D6kuvsig$(H$^Z^g$%Y#5nvjK0`3FYk?bMK3$&~Y#z_(pJjmr zb#V8dE;?)oy|hxRQ~yw|F>56w_II@m!ccAUvf3xxJi zV;f!gP?E^byI-Ei!Dl*w`GD;Xt0a($b_>ZLzYGk9EZ;O^+W0)O#1iv}7m4&4DCs_1 z0>l&Xu7kyEOzrFCE;F0HL8jOg`o*m~!-#`njARnT>lI{SGsK0(02#TMg}%*@uH#hh z?+!g<0H%qHbksQArzIL=3*q@WW>#RtX{|Z9o*uX^PG{0H`eR1IXOMo$3qKg#?(goI zJ%p%saSO{k-EMEwN$`2qKYm}A<-O&&71MRW=`b3h73{RS7!a5(Xv9jQyQuE0gYsw# zd0C;Gs>e+xq;k>_*jLx9(RjV)GN!WS4YX9|OqCe%v6iaUsAHopUsF?~F8@e>*QKq% z`c@_Zfn;pPYX5R)1ukpT;~5+Lg=O+efjd_maJ8^lwN2`9ZNx=!eX)^9NN!2yjk8)} zBGDWt-CTRR-&?I2jwyu6m!-^`<=7k`LJN-_i=oLL7{loW{;m4JyzYX@OY;3GvF>)m zj$3gLaInUTas+SB{-V%B?R`n}`)s8Ur_leCKJ#^P5H_pN|M}YM_p$K&7C`ob5(qw< zy9aa3kS7{4Adr$tC#1?Uf8JiM9V&Nxo%8knYxsJ=#1R)P8%R zk?!|-&-)J^V=4g(N~f+_sWP5<;8ioPHNl}RucO+GVxoQ5QH`tsB`hbv+gbYE>}$Q! zWCmX2cDmHP(C!o4i^D&Q5hwa%oE!@AHYt6NcEz~b6cOyu?oS{&U{b|h3gJ9;{7^AP zTdu`jZH6wG@c)$GPrTdqxijOy1y+hAmXjA63{6Op-u3BFpuA~zP)Sb(zM8m-Vs()t zREh(QS$@Z>E0g5zssTaApKdb8++uoICU=Ju$A8{hNkX)O4`O>!j!dCgb)V<$`Rd2V zXb>bxs0oXUiZF$ziE_Is)+{3x-cGC0MJ9s<0x65KMx4P+A5APk<*f)xKw`I6igOV& z9ey2}UE^oBP~T{@C`{7p#g(F)+{;F-J3g;jAemuysMg|s&Zls{_7|(TxK{u1zSmy ze&6&egm?f1L^*+b)#9&Ml>~bq+T4^PDvxT2L!`SCOw`;KYQzQ?Gz&`jJ{wCzrO=OvZ%pYP_K5Q>Kc)=r7=i+f+ zjJva&BXVP)%)P1g?Tcvmcv!|VwqHa`y_QjmGI+`0&JAOh49?PkIkM-w#?mUkG+ zoRQJw5|Zr#h!at*Y4&=F_B%acyVoQO<<}A@J0UUrm6eIsw!{h<;m~bqQh}NQFeV(~ zC$1po6+GVp?W14j5De7VWysbXgQS^#UW1Ut(G!XEeFDgaH6Q#zIqRODw`pmB`_dD0 zzlRXd%sh&k$QB`C2N^{87b5bgiIfTQR>#1v9wsj zaOO4Zbqhes+sK-VIgmr6t3~Hpo}aNWh}D<_=C&S)^_T)W-rHtl8WHYYJgWUJD_m+S z3-3?W=kWAQ{-E$Q!$#8w>_A!}3EmCMwlmmv7k^;^ta+p7_$sVygt&=UVZ|mbz=VB+ zjCDpLRbRyvqV%~wMQ~#$1!7E%py57XR_`Ck=6i`fV(ep+-p;;KrL%eRR16=5{Hu+t ztWWI0&bQL^^qoc1kfGp6XE_w5^1;6EPmI^TxXBj^H#nDxU0oozv(m$H)FO>1xa}11 zRZr2}*w~RnT%v=JOpi3Og9rAVreZ(Ay|K4)v*)<%m$7FJ;-Qvh5aaNAnA)dM2;}SA zr7I)}A1G406k(!zO@x3UNH80DE+PX&s8vvq|?NdT>L^l6iMm0Zo(#P8trJztS zA!Kiv-x*u{h3t$3UVYO-8AZmnNKdYL@Udq@MuIf(m#E0>(UP^ua`K;WLA~l5FVZGj z(*-3?Hkc6^R?cH-Y6hOTQ>wf(dJ#9`wVyeV7~*coo;P7PUF?dGmtVGXo-^-d0lT>6 zRh3+S{R*VniEUc46B1G`eOP~`MKG{8;j7pb`2(=wm`v09vW1Cc4Ac_K2dH^kUQ9ZD zNrpT&69VSkiwA8ndR8^KXU_xanS^8~tSm6nEHMSXgpOK3YKg#P#z+k;MO08&|F|mT zz5PxV)7--jl1F+N9V@6g4?H7XJEHEyRCXSXBm;9DDVGbBA%0?^-SzSQ9M5}79f#)1 zC8AQuwknS-;?9w^z5d9EFNx*1sQJCk3|8_`EN&Mw?$3q0_K1TWh(s%4*JjqG7)l?S z_(t#4IDlM&RWV7e9ah8cJg$wwLeHq_PE$!@XFSVyFcbl$i!29O(L;loJaK&ZI}v>7 zB8zEMHey6YP27g!d`v-`x@^s_k&BOT@>+i61M`Zq)UbkiYeO~j^IWk0E_t%a|82t>c+k9bBNQL;_cjN1I1s(Ga~;XbUs z`|>$K*Nq!V=gIH1zvF7ARh*MvcbdWQbSIu9u2vi$JyeCEGXsQ|4!i3Zx*qt&vJJIc zr{ou9x%|(k)AWZ%$J|?MUQi7jEonh(6dP8Il{;H`!Ye`-Gk1B#yI8mPyFc-;cOPA! z!Du?+%bLP&$Ahs9aTnkTMABeYJO=Wi_|(rlf?1-(vhRdX{+wrz6kJf}Z2Whuj7Or? zr8yo82cHQ0fo(Rzq)jtF7k1#ik2rD71JAUJ(qd?m0_dzS-=t}sg=ktvMDZ{dSU~MX!jsi=~DiB64Xm@)c)bA z7&W^(Gixyoy%Fe@lFx@1pRP-mzv?9}q&+~?u^KZ-`NSIW_kq*K9_gjNscsiX8dx<) zGBa_c?&MrF#~F4O!1-MhKIThez;@F$- zT2Utf{RjqDn{+a8UMh1;o}#Px{~+w1f+LOkw$aDV#O&C%C$??dwr$(?#I|i?;)!kh z%k#Xu_Q9^N-hH&XtM9X}zPnei>v#SA&O86+dnlqM?`XTDRHukhcNgl?8%t%{zEP?f z_}o)kuA)wKAe9UOGr-xfR1sU(U3anBCYo)VHQ54K0PRIUjy)x$Q3oBFW){P|YJpC@ zbnhR?ps4@Wlqh_u=02JE(EfhMZU(_Wc>ez7W_%U9HI_G9KCO6wYDW;15N6jlOHG5w zqQi90<42+{#c%$g6%?>j=#e|rcAiy-&@sCWhfw5WOc_paPR#xd}j+yiL0V`;|k*63vW>gy+v4V~`2dc~+8Y!vT zeGOsPoNWeWVGC67;0S488#ZQJD2xS&v<}5AW&6k1J4BrVaf7sQ4lOLKbjnML5fU|n zNh?j64}X=da)DS1?W`0EWvCYK^c=CalCO$U6>2)~Xr1PQz084Ev_Zlm!m0fbK#dDZNZa+BK^;R{_(>~CeUxVHAu zET4H1*@=+{BaYc2oi39(+{3J92iF_B3*s1t9PfdMCRb26r7>AH=eCNS6+RVwN)Pdm zzDJv16y2gR4Gbemae623CidZJ910G5;B~c4`!sciHg5LYyr2c1Gwqe8jaf@Y zSnC{%WqP}MdxMc}K+414hwr?eWGKDM*Pp;8cZ5oZ@11+YEwhBuo)9Q}!0W^x@;!6l zkd~m=X%GV|C70ZZ?AkuGuz^eoVMKb5Kk`&UeCKO?&EwSNuHPk};e`%;mZRm)R_5@3 zH^sc10P4v?ECtxD|J%J_3n~v3Qnzs>RJSwKx1$62p#ubb|1F>Meqr0GX3FzsB9dhm z;IPEa@ZQ7T%y9GWPwhKSbAwDy5#LP)Gf%?pC1dsRH8|mA=u;&TTw%(sq$8?8<=_oq zFh^6G_Thj>vd{pBlh;S^VMrqeNFaVoLEZnd{C~F)q7Y5uW zY8Hj?L$Mq2=}xF8>BN{HiwP_a7)r!|CR)E7y1kkj{D$gtK+b$QylfACyhy+HAJ(P9 zi3J#lG7W{kgqDOIim9NB!U)ixN$)?5B7eokjH=Yg)cvw#$?vvC!DYgjPSXRC-2vbf za1M18T<8|cUD|HG5X)KB*J#kc^g0m_LBSGCvgwjc=ZK|<{lz?c79}k;cp9K10%lUP z0^IC%jz|<1rGsn70#vZm1 zJTQML+CT^^%El6fnKJ5|s)kiOA7tendW@nLjt9yGra*!sw1=S#*+5EcZ|E_=b|)F| zc-^6yp13~R+?6>n+0@FAsFC{`*_#E%l2HfNpgG?E{F<X@sA-tW3R*abt3-zdxa#u?&Qbo2aC0Ki9r@=w;db<>=wMEyOVsqq@$S~86nc}}9q?154P zcYLs9YImZ74Qm6wB9+Df(3x>Kti>q53vvz4=hoM6i0UMRGMTz?$g#no1Ibi_iEjn* z+7?k%QQwlcH**s825vm8mDKPj;YiX+(6M^sTe0iOyAw-m0*_Rh06vZil8XwB*`p3+jZyqsDEN)w0k3sn!4XzJsF@nzo_V*z7eaZ`m4Y;)e*|& zoHk6Jod(id$B*;hdB-HMo?G9ljh}PhD(;O7q&M!X%l`S#m0|L&LggETOP8y~I0yx{ zD|cGGsrZ6hKd;P$BB-ww3%WpL{HF`_fVWu*BPI+&#N zGeEYF1dBlvWb`eIFroh3ej+1NvyNXkD=hxbDuU=RBSDc$$e!VwC(S}+)0!C@lceOz zOqeXjM_Kvhh0-RsZ8IzpN1i1doGHQjRvq-m)6R$6U>yA&EcDj6NP}2P%?m6zqkbo>0m}hf*Wz zkmbj8I3bj4fbwu`n$QSWlYw$!OiexEnldq8u{_rqm?4w%_PCG9-p-q*}jghw&$gxvb&Ux+Qajh5M6Aq_t-XWGv zXYHoZE)6^$FcWz_R@_B$zPrA;t%$_JQ-0o1$}$JRJ(24e`6X~G-C(cKnKb@RABQS= ziSNr_r3N;Ju$HrTO8b&P6OKlBE`%V+JdSReMNTTW8z%;z=Qh_hXW(<*-Jxs za4MJ$q6QVDo=EHF3sq^t^D)hNP;|xK=C!1mE^% z-G`Ze{0rmsbyMc1kkQ>od3ZzI{rj-k`6;~Spo|CZyjJpsi!d9!=}0%mp(7g4EVLl< zdB&b&;QbAOkp=spA;drD_SS#rIh_nW6$A-DKVIA!2}8LrAh+EiD7;pK4*a;UA6VH! zcju-%al=%$c#R28I(+O$*4Wi!ItC;ZBNUJMl;VVMbhXK&=SX7~8wQq==q5d1ug*e_ zqKN2Ey+f7_oC!=J%`8|6Z=MkeFn*oQK}N14$R0@^eesp#JK zMgddMXrClZ*QOGIbg&wF`=!^8`&*lv&R<%yL%Sf=sv2?ZT0=7ZK~GbkUsQ#dn~#Ku zy|XIbqmjs|%5Gf?byu@j9aaYm&T@Dv9HCSwu+lXO&7}m7RBzY@GR}Ie@n;pPYr=A(;;t0iSJf^BVN0*4Q_nTEB?{nfbsexxT zLV4>igoK;pW9NBJXCd4KzQdy+SR}hu#|}i zt7>Q%w9WWu;yu*=6%XnW2|0RG)~6X-xLN~6#ISV#F%yx z4Y)%Lz}9|{=qYTiiacgP60-Lc75kQFeEjAP`Tiw99bF=EjqrG;thzmjcSsdS9bpLQAVL>% zsm9&LDxlyN14Tyu6txAa66ULBi^DXboxpdrnpfc2Z-Kui#_&>LK5&f2=$o>@F|#Ll z{TpQyrQmXqO1j2_T{{3{fum8e+eTF)=*WVcc3_%d!mckgq_P-2_cXY*7Q;ZbNk2(f zv@}RVy4{k~<=yik?FEc9@e6EIVK%NCP9vlq738cE)qtg_lbO9{fs}_&JYVg45YgZL zA{oL+*r>gFO6d|Y{DQnR>8k5qF5MFD_g8AlgzgCMM0HHrKha7DCm2sHC8VRPybym`AK)^fzET~2 zCCo-N^RtK>oZu^ASzV8K&*mb7e1sr3Pj+-_-iB_0-}ulgSP-Xhp-vD3U~Vw`a07s+ z!KFG1U$H!=_$GD||J5d4jE=J1jhoD72u0<0eDBgad^~@XGoArTkI_^Y!Kk#n`@obE zd@q~13-=%^9{*ayI)iu<%(7@$(RjN6_P-NIT3g>$eAzTr+7=Now+3+?Dlz~IjM zZD%Z8y~~#&6)<653kZY&skH*M?m-m+R${c=+f}h8(1amf(1{#9bs__dn&e5zLDk+K zdL!L53=ADdQhU1|Etcfz#p&zy$BZx^F0q~WdoJ@S=gv-X3E)!YBag?-mrO3dABDFU zk4?eo%mO>dRHXJ@H4VLhAsV#Wtw{0@eDcWsKJwKu5?iJfJMg%}g0zd#v5noD$>(m5 z?@>Xm1IG}{gKqz}=m>+P0I1@P5R7tst48yl)`z(CU!?DSq?xk>H&0Z)2J!Yn7`{@0uLehFDJ89kMu$qTwflB^w_$7S zenpFUykAh?^mE-XiGKHT`$>M6fFu&Dk3!P=JiqOc{W%X8XBINK+=oubmf}x%#_wn8 zHuboud2>{@{CRVhs~t;$MG~2wZHi*tpqhUi)1#xR?1!j#vOE4SR~k(UX?jj0~AuZSk+2=X&~uughO-2ixm?~ z@wA6-v=a6w@qP`Sc$0FGm;XiT3Y;xg5dmfcrnh{ltX7uBr8%(5TqyCbAM79ODN_Km zmAHur9Aui zhUo6^4HoJ}H7>8ow0H558fjDzpWWy)zh`Ar2v@ywPQ*FG2nlHfnDHD%VqCkR{YE=u zv>h$$tVQHH`|KUpE|Y~ZsgR>x3Tid?mSzXq0Z@I7QUGe49g045tJI~UqvU-o?{76) zO0ZnRt$6Mi%i^>@Z34I77FsURrAGtm^NLWhC61h8iHNGDJ{uKf_c5c#Z$JaWxcMwe z-qRLWN|rk%!RyuXLXi58EgK?vfI;DuwXd!3$Ol0_LpS(3B_!5{E0>nJ1GJ#XSV_Ta z^X$0|jtJ_%1@Y0PRg6J`jh51`a~i!T<*(RzqIC`G6EL^4KIy+Awm7JUtGbL}7hh8> zw+-g0aT1~2FWJPw=OnL8@^5>*-)ViTAKu9viCAOX1st3rA)tnk@5Y67PAvr<0JDAX%Ok96 zX+z;3w!E!aK~WgNE!<=yaBixx`dw{HmO3uF^gp!#Izoven*Io)f;;~rs!=0Ee;@Zv z4IJdZMBcd27u?Gcl_X^!b+$!2Fv|$DjX38nA+=n9;bi$!aXbg-0O=Ob))32cpD(D;29NHw5URAmMlXt6NW>H)VJZB}KeUQ2RGre^ z#aAs-U4y(f#*Rfeb>{kv7tGvkpt3AG20kz}mW$pCd@iC3_!C)bUWmd7f08=;Cu!20 z%(+zcPa~P_sSwP!9=Os6)#OdE^HO-x3*>j`_w1t5ovf1Mt*=SzM@1z(z9hQF(cg+< z%Fzsk`@Dq<-sTu!Pbt{4-*0a^MBHtL^QfXna>rV#7 zThGfMCbRW0cj^qszlPXmJ@}%(_Ii72VKnOxk6tssr)o8QM|A8QpS)$98U??e*;(vb zOX57mO8nj(rl~yL*cPR}j=obgJZ}w(ML5S-yx$L&j|Rh8I{a=8fJPmEB9<87Sk2}QEh4q6?p{m{3qbo#9JXPE{ zhy|)`oq7sS6GfN}I8T>)^Im4M@|VC)C(a-3 zx1QeIOZ2S5?kOsScls-Ig+L^*1twe{?aXByD94M0&E}UE&sd!{z5k_6B){~&W7_e~ z&iH-1q`gB$l~E`}HJ-#_VgMJ&)>sY}|CHcKT#OB~?RQWYqUF#&+DW4bSN-#fd@Vo< z&^`V%^ab~3FcDeg%(8!9SXb7bFrr+GZ@h=@>gFG9kuB==`EoGDlGjf3%WLwSgs;Hf zl=I$tc3yH7X-vnFjv28V9kzIEe%FyViSj(FPkd_>HfUMYp~Fw$Q^B%NuKX|&Shdm| zcA9=tN!LP&u-z3pRZu{2Qif^1=+>x>q^UUG9GXENG6qgu$I(CcW{=93eBvCXP9EAA z01y$FOXc*!KUm;zVCvR949gI^PfMYaPG$<014p&hT&eLPKNQO$Nb1h9O6kredi3z? zSq+6dpn&KcRS$XM*L2s*X}$E}$Fa)a>>uonqU`%UmBKzK=dgXdce1Q_E%Ftu%n9qd z*G6T^Fr54BEW9|ukhf|r@ka9zZ?WVhs^OK6Y?J+G*Abv4!Z z5HVfGc@o+gyX&J0nz=bSd|rAxqHCEWrJ%6XxtW~-k`YNzg7vk0B ztD=k|Op(oYT9l{bf3q#WnLO=}zX0}kMt;w+@m8s9s3DEUg~*)0faey(;wRf;3=CQ{ zz3EA=I#A{PhU_j$6d02~9uu6;U&nn~L7G6iVbfmxqh zvg6@Rd1{^PvUBW`}`4eK63^&S{qd?%~nLZypb z*5PUvf5Iv}h8>is^LHMwdxe&Q@#Ls#3I1vOju!py$#l9v;p0@cWncpfO# zbbmaWsHsC=qLG~=y4J;=V@BEQkyf^bOMPYN>gSnty;wrqqiQrybdD^bl0a>Dx^3qxmKCoV^a z`D`CIxT%{?NU18--a_Lg4ON6FC{d9%tZf8Mhcq9t4!#(h`k{T{lsk0aCdn3fnfkM} z`uh;~cocs#ZE)SZC1J$(eLjn@wLtfKZW898@KLjR?_zU){R1UW;T5^3nQ9BAP*1(` z9nO-Xx|~KHoA`hXBQDx!>6H9T=Ue?NZ2Vs~#u|~VClgi_Q#A+Bo2^ZGceuUx7awUU zWUotEtLUfCO~bh*yE$6>(U@yG9J*qNdFRiZ?Us<_qVUU^1ee?ph%Uy=ncs=0yGbO< zyR_s{y2dNZp|X1SJxZ) zq|nXB6K9hNWIpAy!QJqAf33ZPZhypmBSj5|xPBOEa)3kZ$ffN?)mIjOW9A^$ukfBwn#W3ekqH_dYBr=;p6oEHR)yWrwA&HL(=(3aRLAERO z(76!-p3SsR$pyNDi(j7ud%0brHqrp)vQr=rezKmV(LvVKeC8<>l|%;Rt&g-wv^JIT zt^TTnoqq#H)$VVD$W}pHM*@?v%@Tvy- z*td_oh!fwQhSSSd_iMI;(j)@TtBpX#F}_s?4!`da4Zx#F!T)hCMuyLCCBeR0`ryY&h7t{d!Qf7=p|{r`#Mi^_~#qKtIk zh2`>&KrcE))aCMCIrOGoxG{8nQyOg#J4C^VQ}Vk5%sr$%XLMsM!PH1;6{2jh#jN&U ztg9`|9)U-#-oG~Q^k9rI_Nt>vR4|z_Fs2x)b*i~P5X0PIp9w1s8H-ILE=Rg}m%fkj z4(%f!@j`pgin`S9uWu>*jM+D4@OJUsU$2F1IL1pnfskuD%Bsa&&gGV<^AGiSjHYPW z)G)ROwsqE`O5d7WdLG5V_K5VrzX~Q`^ncI!{jpmHCIX35L(F?CtF7;o@nv$D9Z*9q1-qD<=)1 zh(YWZMai&1GJvI_H#4KZvblght47)3D-OKN30~o z2=h?UZII?$<#VfCDeK?Dq!1GM1YhrLWO#I2Djq8$cax)Nt5(u&;30W#SMj&*3f4Gn zC&X32Mu%mnSZf12W`6(_gQ7OXzu(eWQUBOE*c>z~-eNpMj;GvVRe3BWw|DK@6@hdHTIx4EU1SbT3nm?{+}EVPGN6tYleL|zW8UCE#( zuMHO)eP2J9H!|R~Y$IxLwV?-47&)n;pm_%XteQcJmC}YTXiqtG=(JvX|Cqrqkg_zZ+PYFXVKby9YkW)j-3{R zlmAt|zrSnLr^{)es%bDzMjl$!r{8~nKkI#7o%TXiy1!YwvbE6sa+3I+3JnL*5XDcU zI#38fanI4l+zW84VlGsq7 zFk^)8Plwba*Q8t&41Lpwcd*t+uyt=>)v0J5a6A|5Sz{;HwlO##C;D2*I?rSqvVGB_ zM~m*Ng|>}sKTV9?ITiK9V)$15K~r>^lIE1!k9yz4pw{u#2jJJT$g7SGhC}=^(fHtj6Lsq|m!jH?ct`xd@WNvF%#k8!+ z7SU>K8f{YOJrb#nAh@@JmvuKEp~)0Mx3AT7%o|QnY5Y!0(nn~mR<70}^~lQ`@Yn0O zWk7v!?p7blJG`k8XbaqnW+!)kGW2qZxN_?*^Pg)Oj>fFc5=ot=`408&Q&IBHiL4L< zG^eH4pPE}b2?6xjLhwvHQ!k`u68dBh`7F4xhO}oZES<@<1XT~BX0EXF+^Wv2hs`$7 zQ%PY4J>P?%Kj*i199WRz)>h7GRTB1mwU5fGffB7vte-R$1UBEo8Dear;* zk;Q3a52|m)o&Ktyq5oEa6y52oz7yqTJ*`82EH)Gk<@g_Uj#;CUm3>;AF*FqiliDjG zXa1*-QK{~3c{-I0ya;K49^4_y`VGP8boO!~a?JLJojVu4y@-KMal7z~{)e6a#ivC} z>S8=^$v}QKf6ADtG&Yj2N%3E5<>3hDP7$4v5NI-$Vx?SEa9zVfkfCjFEKdA7C1H%# zKs>K=ZB2Lxai*SCe#b5q;+H=)D!LH6bH7+@)KC1(a(V$K}ouYf9!~M zOzc6O7)lW+ZpyiA^P%R*DU*TLUP!1Gxt|$WdMs`}>3BP~@8jOZX=5$o$JZISo(_uO zIJB~F;Wn>iKgu+Q81NX9)nmT=f+xJWdk{Sj_1OFa6oOg#&+JKs{%>Q8;_SquWdGW_rhkj(xH(!tFZaXB(zSVqT{I={=w^M8sxoPI0M*l^+sY$ z=eme+{%LTPMRDXNSm0`ncFPU^HkI3{rics#Xb8SNs=#Y4h04@U#(=`_M%Q?mu#iyx zFLzmR4R#GvH#mKWqr@sETw4y(`ofFJMr4bhk@R3yBl$!X12ndb)`Dg4A9G0ed_taBL~4)EWre&(Afqxjc{zL0aAhxl77+te?4`5 zl8?}=N$Z_njvUjs0H^FLjr8KgBs|92w!oB1XZRhT_&dVM;Q@Zrm=0sy7m=4{G6nuCNAv$b-VM>n1!lHplVq?4!S^dT+^3N3^rk1OQWi3-;Rz57nZ()8G0P5`*gj9Ua~ zB39OBd2%VU>LAAD37P`oGI+sfi(xfd8w=!vb0rLvR*Bs=VPkvOJy( zQsahZYNIsZ1zpn;rhIOHwm_b{&J>1lcUumP0gzFs1i|NN^%){ldnQEd{jCb^mbq>J z&Z?OijD0~w$0Ir%65ja8LRAe9eiOkREM|=VLFmQC?gcOV;Ee4=H!WMw9Fm3%`Ph4V z1jWtkO%9YfV&aZwJfp;P)=?z6jKj0IUJ`#V5?N;_UD!U2f07G%;Kwfhlqa~%`Z@_%67wqI zS!X_+_vJ)>l5%O%%Pi_v#JSAf9!pyv3tJhBS}0GODbJf23mW+eR&TTW%=7+UY>QajWJcOpy4!itVmbGXV)njj? z>c+xddt_VYJ__fe+OuGt_@YG8C@h)8AL%Oi@Xe7I|6v_EOER06^r8LnoJ9U{?Y*ki z8N?TI&hmvk!|_4=ahybc@bdEVa{?N7-?%m!Cn@CpVg4Nc{lWZ$JyzYEe`30!>vc8v zsya71=W#kbp&kFCjI4UynV&>+x$8R}X>e`*q(_YI;O7e&R)VDvj}{aR-M_S>`m4mC z3N9GsnxNugEV+4Mbh<%QR+^m+GBh`Q`xdrz+b^87RS!pLOnO7WyE+fwqiD8E2}0?1 zN)bcpwo8Gqn@@IIzc)Whj9An0V@EG{`+o}}z zG>t>2i9$@I2|B&gzf?Kqc9aeg!?z*$9@ZWt^1{c8{3sD_jAzX0UwwX4YJO4Fl^QT? zX1BP)Y}+5Nmxp?EdVYSdVb^-wV_^Pt)Y*(^c2!|E5YK-oV3eWbMZfVFv-9F9zzqjF z@Xs?@y`-VFgHBh%N^&7LC`!Dr9{?0 z>&C##J}ZP!!IgErt1N`iG`clZNP-Bc)O2N$@qg9iBxWMp!Kfp14%q!`CN{oGS+~Uf z7Gd@}%uQMVX`)Td&(#=DsR>rf9QWS5b^&@zQP@C(OIFR!t?q%=@^3Q$kK=&Y;XLA< zQhRmi0alB|p$x5-8CUka`q2N2lAWoNqID18INMj;dM3&$GVzq|<)yei0S_nslYa7B5NhemdDm$n;NPa!sS-xF7AL~6k zyBi3jW$HvvK9pPHNoz@?rhTi;@3p`5hlCzOVy@^^M^@?9h->%X4ZAmFEazM+^;W2P zVDDI*X`)CNV>eNqHR^FkT7VhysrbXPzYo?4faF76f1T)CR^B#h8tA#L8|BbsEC z_?ttL2Wrle6|{^>A55EQ4Te}#=IcQlE#)}re+CxEAahT4to`J#NAU*r#uNKxWb3$v zjurol%6?36!d~z!(c?jHLhNLs$pb#Gy|L*j9a4SZXz~VBe>J&!t`rWVz+_;MJm{Pl zc{zmIe~!lSj;Su^j)oRXVh=pa?g%=o*()%VM$MwnL_jGTi1HFua+>I`F!KQKF*r4# zD1p$?8xsi`zG5|dMS>&f-{kg+v3;qty(VPG3{lX4HtT_81_f+&yJ+PBrHblL78kj2 z=EYAY$sL~ZbQn$ZWWiD7o~Q&fn=F;}@CeSRjI4)y1+WHlC)9$@t8v9m+XEvJ zsU+P<%-X3TsK!lCAHxP@mR{k$)xuNk;(wMt$Er&kBhOEKn3U06V|TXf+O*wgqUeiQ zhMB&%8jXZtWZx7s(s-o)Gc-jUvrmQvD)>|im@+DI5cy{;O1t5yQhn|+zd9z{mbiC5 z4oF{`$)4H2$NYb1%S8e4A(GyT$5|$0lBB+b%G0ce;fZ%hAgQ!{V0Qif($ed|%G;+8 zF1NBCMyaEcqIT%DIIX6qQi^t|BOUf5^tTpIx%~AwW8w~9G5*z(5H0ZOBxWPKBkaDE zky8zg+!v4ySCu2w^skz7~Yh#?aiz9?9ecJ)U3wh@O-(R4=9pIAF_+* z8Ei1^C3QuS>_oE@Z*iqU5Mw79IY*?W{6laiI}O9Rp@(efUm_r5YdIB7yF~E@l^H@x z03dasDf|ULw5QQS`aLl=OT+^KY@Da>fSWv#e>079}$tHnYR6)rn3X;4QoGi7eSGhrnK#;T#3;Jn+;AI7~1Mepc1G+^4f~9d<)|twpb2on94|r9W?KxjL~-Lu{eEa(ZZrKQc1nPB$f7_33Ld-c-qf!I;`{TSc$TLF65}-Q&Z=7{>18 z*z%=7H%k6!bW8l(9(I)7UTr1ilU|T~VyTlEkGI56v(%d(_S0%aqz|U^W-Ie#+qVRb zP{(G%p>41R12{aud{v&9G@a6U3V*#PG+q9)VN*UX+g)Km--mJJ{FLh=^S!12ezTK{ zmF@Xp$oX6yMab**eY^Mjekr+r1eLlW1%u7y8$_GZdr3>uaozOWpQwQNm;SmBA7wCpH-eL&f8&nplJ z+_3%C*;VTMOHrDm^ZNJLZ}VYKP=&Y(du?jW!>5!zF8;Dg9a`+rc#jCmkWlIAZ8E(P zzk6FaCHg*tIc{N0PPz=gvXVo@`AAjp96!U57W_i%8td@;+SwjewxMefn{d4&WarS< zd|;!+X0 zj2#O_rfU!E3YMKl803X*42NNCtoJ7Jp`}t8vl-AX_Fhk$2ER1PzK6uE4rO1ItK{xK zQ9%Halpw(WDB8FGm(?E4BG{tR#GQy@-L-v@(M4MC#GU;OUp3w5$z98NfAE?XqP2I< zRcoSBLW2R9Mw%lpqGe8|lpyif2F3qkvQ>+76f_+B9G~9)&0(YRuim;KxxGdT<1$yz zNx;{itUT(Pp$FC$OT*ZODk8c%p_z-*uy2cys)4&T;hWzz&?8kV#}cf;entYOEIW!Bs8aA2G%`$7-~F*}NCmQCj6x(*fPF zE+WR*Z4}k2;W8ZQqOC%ch$OwSXqzQ_{p8Ag`DY4fw2y2~B6yp?ET-#vC*85jf$XFO zV|djc(mF-rm-Rt?zr7sN5`FbiCzF4HNz3M!icRZGHhvPeapa%n)~c z{5{q;6U3K;1o;FT;*J`)m(J$(vTBM91}=_=-shK_T*4A1s3IzfdTgU}7cLyF z;Q7wi+;p@N^-6Cb4oj}uDJ^?3tZA2Z^(n}2=U(IcN z44T)y3EuWBvxA3oZqeN{T%wvbC9SeH8neBY-!6AW>JYU~`LAQG=PD8h>em;O)_g9I z6HUEwx9}C-ejb^A2-b%P=M8!Y%d6$@&TV6@igWjN5GQ&=5pOfk_hN!TY?W0oPM$tC z5_?)*1*Y$$oHr3!Gh(>6-m+G zCja*qRR6OK|HtxM{g8g`pL^2lW2Zu3FcjY}Uxn`lD}vRm>;w)&ixLGnrtS!DzFDa0 zdt+weG?0&|@Z8DD)$l6HPsE@u&D}?FbB&4O5_?P3=nQlFsWfF>cf5He{zaYe3&93L z=`w5~PXzDBu!{~RW!PJ>_5AznX9duHc0~;}C$4YdG;6`X)||w|)N8NiqI4*F*5<#< z|B3^bF=HA|&;@XY@u&Ayktl_zxLeY5pEG!9wh{MIuc_)Yd;6fJer7&&Vw*)#a;#zYH5{vt_=D$To)+1o|*X!U*q*;O3YxmDa3SA*;6iTNg^Cp=n?+=#M9TVRV>8KdzTeG9!SP3v)I zY8IMsXD2JWIOQ68PIX~H<&5eo?+`}MRn;<&`|hQ%>#Q5y@1*Jpb%)f)gGMNT=FGkD z*^=#xkCG^SP6*%M-M(hpjvFq?EMvXSd6^XjKEJE^ES<68DVL7MM?_;gYkJ5=xt3*p z)!t5lu$qvSoI?Sre#X7ye&Q$Br`L{`P%N#`zdB-G`y&a=aVH?j_~KBN9Jf1l?5Ji|6Y)Hg1fDF$=avCPOL!&Uh(4^M(*iW z<)l!Ag;Cf(-^sF|^V8OF3#PUyji2PO8{IO~c~Azq<6%r|59qy0y>88@Z+xY<2qU7( z6wksIFXA&v`MtcNX!Nu3P^k?h9~I1%A&|?s@l+=E6N)afejNgXQG6wnd#M3HBc!?6 z75OwI{^EIp2_}9j#dE`)juFpC!x5t2mLWqEAlw$i-jYJKn`txULbP>`*P(r>nYT5M z+!KN33#Hx_3G)1f-uR`*3!tjL)~%Gq&JT@~Vwzp?&|$1ocDN`THR(Q@o+m-_qavj% zD07{5(Gl#M!@P#DNR{<76e0TyOBNWF0jS>8pI(Ws>xxFHk$FG8eRW?mI0nxey`BHEX`b zX3pj)27KTxC51lj!aBPU=~DxC?5p$iN(w>I*H|Y1p`8D2=1W!gjoS_hIC*r%xfqH3IY?B7zpxw59;~{6V*q77ziKfskytnDfjqlUb?Q4Fu}G1-D5>W@oRw0f zSBnu`YO^0qZ&8F0>}YkRy8ddZkb+_h+qb{YZO~-@AgycT&`)y9g)V{d0w1QQC+V;< zOv#R8fwn_t4_>ZB8a^{|$RbFV8TyB*>}SwW1SZ{X?o1(oI1LUzBLFVg;%v6&55}jD z>o)`2(;baOfx*)|;;6(SYa*FlO)Ix;He(NQ>#aZ(%5J#QPw23%eekF#)5b&CRHOPK z=HyUN{uA#snW`1|=q;@q|JMv#gEWCz>XA)nroGy}4PAoH&FV1daLQ{Xow7*jURx)1 z-|U@sl{*sU3s*@RWM{Fkz4q25pK}}411NwJ#qO2Ll*^hJX4JHU>4`stbcjSq^nu5e zD=b{ln5dX{U%|; z7CiozT}Et64iY})apepDT-vu!Pt@%&j)RhxOYTAQ=$>3$|3w9BMD#>B{a8xyTg*phLoFR%IT{;0s62Vs*;!#?deUCeg z3CC;{y@Krv@QeFFTbyvzyS?D1kJ2u0?kOI>_wV317pOIxFD0t6c&>@@7 z7fTfdihJ-bOId30G)6%N&7oxnz5e&1Y4U6gUpr7}ixXG(1j&Bj@oXI^2)B?bqFROs zyH$?XFOSF#qM8_=J=!Harl`UF?2 zYr2A3wQ9e@a9$kAw~2g(%?6K_$JtP6z%U$HR8ti<^8=!&>Y)2^BzYa)gD~W1KJ?eg z{{h}WA-{touFAM_zl$S=)FK!(FBninuUdq>2Qa3~>pbYv_EzjpZ{WJxG_l>TVQ^4T|;lq>NXRm*vsb*g*0uSpqj~Kbe*+!}jVUkZU!X+AGPHERRCACCej`Zpku)d`lL84jNek z$hg!eexzKo_>yyB@qc6Td`t;?H5!`lWS0y!vh0b;MwUQE8__4vAUW;6-_3)SjgNb` zFIQHA@vta2tfHr-@G!R>zpNZW-7Mu0>egEhp>9|X_`3dbz}Iz`1HSHnuiO6UfUi5? z>kjxj^6SRe9YWm>p>Bszw?nAguSq!`Lfx$8w|*@@gt{F<-JA^{uHuKQcwaeO#Sd3; zOF3M{`+t78ivPN=;+_J6p9Q=Ve%aIEYsmi}v9!`?ie{1rc#g{RWHTd|0=|dXfy=Ac z_>y1t;fQ#J;^v&tvP7hGoPuU97&8%@n1G^mWtPA)1-#9LNCzUDz|=-D5K`m&B_vjA zlHY5irgt_+4Rp^)CYB;OoqwWBHX&@boRN{0Qgk#Umq|Y+tR40yaG$)}ijy8sHi-x| zlWO!^2UGRl`gp>UE%pfv7$vU;Hs&8Vz0QWRWpjT|Nl=6c7{ zD03wbk>$0S(`BM^O_ZzbUQEFqE0z$f6sL;vUE~h&4SL*OTQa1wWtu@20idFfQ!PV5 z>)zYQ_U@et*%_%(8f%KT3D9pb?*4I@*~02l<~wO+(q~CDBR5>5-RN915FFLNbj_+p zNNL~5=Hij%%$;aPq$?7&wo;?uhV1PpPK}5y6JaHwkh^jWs9XU)IofC|Lar$RJQd8$ z^cZM0G4eC?v|(lrC_lw{&Q0{!X<0EEO<3g3Vcc z#|T9$5JSi$x}{GvEUnjl;2=BLruQSunc?>hs?DC?nk(AF^5`)nee$gFiaP&!|9RF# zju0z3KeHPo&uo+dP^T?_!9}S@bq522Y}6e9r^Mw}XtO;RcBzQrF?wu%mP4 z#Pp(sKnD2n@nS*@dDsuU@eEM*t_R8gc;4x2Yz)Jpn|C`7tGa#2K+tvj;Ec0xuo`uR zlcW-*&VQyJiQv7sP8gv}8mDE2sV7~Q_43`-3(XfrUefsrtHbC(%nr`dYC_@}o9P_2 z>M}1J)SV5)3vzNo)6K~VWZ)LhUP3l-wWd{E_Qj7km=h}cNo3y5k_25AvcASm-{r=; zxw+~5x1Nc^1zN4L9&fgYn}P@Jnfv`!L@~JQLm+;itN4x;B`m4#c%@<8pWSuW$ffC? zJgRUERVEggT%&4DLF!fXHNu+czG}aGef{0bcPi!jeP(P6cUoW>%$6l7S4nD_YPwI0)lZK8W)Xq**$>kCSLli-@eUvchnk0X047W3iD2eTxds^{K#E zh^5`L2P%LrRQ!m8IHkc#Z}nB>Iiq09c8BT5TRN z%372^qGrhD7%zaC(>TuHK=QE{+ZLnh$Sq5TTBreI#BFk>ThKQ@C8KLcmyR#c%RJdQ3T}G*gSxUTZJ9+th`I+_tB9t8nxTBsQ zdl|9{V<`mGS1H11Mt5g!T%}8Tevm+~-iILo@z^O1#)!spTbZX)QEqK88GPIO5Zc~< zYerK{l&;z`Y&E{EnmoT^=zXgu<5y@l7c?kb>Q}T{2>x33BKj#H2OF#D7pxN;T*LnbJTbj*J-l4$Sa8PaF zP6-g7FOb#?FX{)N^#;#+1803fvqJ&19)lkSl=ZQ#!w&5?P@|znTK5rQeV<~>(omcs z*|;RLBE3Xk4WiZw*nf(573koh`qH=P+ zK{6y6pY+{H)c};mTn5pfURESw6t0xeOUYTq#VuxCniUjWa3*tezgjYs(%IAV-}#-1 zemX|p`1U<#(sRDQNlQ1{tN1^A&iqWCK!YcIem!iW#?;d^I?ak+_pL51LSYyOTJJ`c zQX43Z=f@@7&m(L!*KPumgZ@po;>Myg}je zq~U4&v~i5T$81XG6VbdbfJ~Tw3ucdcPHLXW-9~>-c?A|7+;2f#;ipa79IQ|C1C!&r ztZ9;LWb&zUtOBDfb!x6k{a6lO;E4=7lS!o{O+C1X;kP2kmpvSY(fLYrPEfHUcm+oE1&3o?qLdUDw65GzFTP)vOmc}} zN7G2=8>;gNp50bVv_VTkb3V}pm!E3IQZ?3<6-4B*;WH@MTRVKpn)yi0uSymNf8LJo zf%H~s3w2_tIuqAnj7dro3CN&PBp-8y;I?yP7~fiIp3@YyZ=U6K!e!FPN`~a#Dk)ld zy0vsG$N^$qrvfP+-zLBkZkO7nV+)krT>af9Oj)3)juP0fX| zqNNZVOXYHoBq6L!`?gh2=NpgD^#O#5IzVYA`I^(*r_{bn3AJ0Hh7Q2$ZMTa)H-?ES zv;DjO73qb3#O@kkry^=(-Ro?j$twmG9hHRM(Kw;EaS~UsLm?SWSz`u;X4RPNptF9_ zQS&uEjbLT5lojHi`!F36yKz*CS$W46rt>S+yu+ebI3yA9+HH^upq1RqK;wP+_FMc~ z575xWE64z}Sj6*~Z&*5?v(gbuUZE!JstsX_423_sgj^9U8f_)ca}Qv`rzB1VVB>zp zL~0y!gW~2C4G@SWyM`o-v;ZHBgucNOTPYHacFuvBg~>tj72)e%Lg$}EN+&tZcX1ixW}1j> zjOje7BW&3TI5q)QaPA2^0lY|`VHe4B(GQgs3#|yIx7zncU!#nnIv1PAyV|&!)}^aj z2#>{WL#k{S7^jiak{U@PGNQmi%hwo1t(dvOKdeTrvJc+LG#nq&>2&%bg*3xuRn$(; z1IWe5o*2ai??+t%Qx#3oL?>bz&@G=+CzsJo=uE9rXHDGFhZO$53a0o~mf;EMs1Zl; z5B?4RpQoqfou=gC{mO3nRaYB6lq|B$u~kV^jx(d?Kc(4yY8wOemKIKTSA7@;`7D^;q2rPpyEUM9>_yl1GWoqN}IXYv#E5z%P|4@qhO*-h7^&|NiSP_YoFPQKA-S(H}7`0z#c!)rLuR zyLOY}H_yj zHHA(%CRY8l5=}Vi_wEw-iF4>|^fbXBo(kx=z z=iPWB;*Zed2h?BlEL|iqW=xIOc~(@kA0d1V8hOb+lejX&wU48;JUcso_P)N2vNes< zSL^C@{LS&-Ynp)X|1Dj!SL@3CqG(!0JzzntCXOGNO`dntP%%ILZL0Ol?8lSwH^#q> z|9|%0{kv@=$shfF{)!GWV?BnXEIG;SXvdqYaqPrrVn)pTop04T_z(%7%kxIN@V$Ys&D4-wJ)z#JY_|yiZO$=()>QyB0veIb-Z{QgkctM0s z2=|B4>h_e*vO>E%*Yc&3wIV}k!bu_2dRI!=1H==QP zCBdV$^@j72+?D7k0HYU357Y}R45u(&(}+f4$f#5BLYr@&m)iYOsgkS^i;{)wW9vMbife^P_h?=0S=r=d#N1`H zfZLxjPJla<6zzDEIWKNlNeY%ofmgOFr&0CdBlOY8dez-0%-bV-guFd^I~u?HpFe!| z`$v2G2Zw(g{_E4z_FR|F17)t=W%rdf*6+5mi!09Nj+P-cq4*<_0Rhd4T>>J?Mk*MFwZB@wwQCd7dR%l`j?AEg1~R zzH1-rtRWFw!#--eliGg%{m1)m>5v{6r3FgTMsce;J2%9ef0HY!J>e@{8D0?UVXf{s zv>?1uSs*k9h)u4Xj9t*_hsLkJum9m9IL}Ky$?}d$Mu#RYfBzK|Q(pr^@+@D7ij^yIpncq=3d)F?s+h#yUX;JYd3CF`oVpJo%3 z1NpKJaHj32jbpoOKmWUSAveB5yMzfMgTbp|Lw2N&1Plutd`p8_)gVX|O=zWq6z7&o znq`4n`?Ls?#9)+Y`W{Ha?xFX*WC@?mFp#H0P5DYL(G^(~Im9w`fI3*!+*CMl3q(Nl z6s{_UaL?!Y5@WrLSd5b|tzL5EXSlR#2P~Bi5tR!Y)jt;4o9BV*brUBjRz1 zs}AVeOM$nYScfO=kg`OlJ)DxSzWnmZmtoxjU+mW6y8qUHz96DG|0 z>z+Q&3Da?j@SZ;5d0%SuJDA@8mN{?YxJ3bE1R(eZ8Wxj|v)4v7f~k@Ul%mVp(ONq` z8$2CszQ^&}ygxVWmrB`%d@H9&73R!kC395kP%rmC#3A1ze8`$y3@uqQzcOzR_5Zy` zIh+RjNs^%p^w=d}| z|J~=mqx0-YxlI0RE`Q4cAB{gm}1O849 zho;D;G(RsvL3zgW#jG&H{ZGM*b1FsUSW;lDPd>fZkb>VeeqE7jwT4Ut{mR1B8a*?C zW!Rhvg2zAKqU;vQl+CCX2z<_pv-6jKe{xy-IdnlXBzCOX+ER^4u23e^mZX8;B$H-| zn&Mo=H#+UE0-Ikijp8tbRJ@@=)&!m6p9@wlr6i-Xu_?B@5{0QT(>2hoT|ZqD6oYHn zT#U(IY4V;GsfESGm?IB3iy5Ph=7zaDj(vY5gd=xq(l>k|l}m(Q)o?!)Yf7C4md`{{ znRE|KmXJ5qLP_zaiYxC&PAn0Y4n`yEO_BX#+7`yuL@Ne01ms~)bG(v(x1-VWj4oAb zGg%Z)d;WXdD_$~^6_dJrG-8U+W{V=LmPc^LX4i{~m*Oa8w=6#r+0BTS$uz52QY}h$ zB!w?bq`-v6S^BxT(s<6i6>VbG;~!og?W(6b(hnp3%_`^wiHqk@PF88~uu`}vPJT|? z`bcU*^oWWO(@G&L(mBrx6)loOD!f=+&$3FmB?6kwJ~K!ih#;~Ok@C_B)qdc$0+a0s zq84IS%RPsiFR#MusAH*RX)ot2sco^8i3~0cIwi=6zgTD;a{{abu44`gGbjoU4?eN& zDu4ytzpF@nAdO`^p5~_pPTU}_Tk)<%r;?NEu7!nxnkEKM+i;~pylrq@g3Uptz_`Aa z+8FhS?xvZyO46K_6JE~bhN1=|G9~-;T5cW`bW8BqWC=J;H9kM!+9Yl0Gqq|(2RQTz zFYjoX;&xNbED8;fqov_B9vS{S+26s7tuhWKymXcm3&NW^GV*5q;u$$UK6!#Gof*OH zTQ=1U#_yaEse8)FvJX<@Zm*$rJSH#Cg$mxRw6EM}^f(!lGuw@FQO!#>$v)_SQA$k7 zp`2c`oa|p6j;{{J5Y?;yqNK-!u=&nVkdB z{YoCcZpzG+rkS%|nC)RJR(aP!mEXB#gk@m&tAPx|PBKCU%{cO1=LNqhs|F|H87(i# z)nV-?9|w9Se)!xh z#blCw(9?SZ3!$L0WOwT1n5=RlPN~%{4`QX?3JevlY*i;|t5EBZTupX#HYhE8=1k|y zI?+>ZSIN(wfkJ4ejz-P&oJpB%nz4giVPXa17aXqhxkuu88Pd0fJZuXxUTMEAWk|NM zIw>i5;XQLyg)P;zE;@!a$c7rY$~|Zlj)b1}S|-s4x0eKz(cO!He-=5#)n zZyPCMU~c6)FhGG`DS9XlhHgbUNiLrZa7sF==tzARvkTO>#N#H4J4TgtY~gFD)fcXm zXiBg(3h$W+(a>(zHIOU%UY@GAZADDOzKeSS6@KUFilAXG@_b25)~ia`b6op6)K3y` ztnou&8ZCMSYt`Y`*4TR~?OWH|H>A2dYoS6V2a=yM!3N3&>10q6LpFo?0+%M*TEa2q z)#?JGw165-?nyE@kSg9lPkS(Q2GG*D9aNL9A}elkwnAR$xN!uwrqtMAY%1h!SF+Uc z<0oHYH1UgPlDme4l0#_x5LZGavddXZ<|x4x-=g%*r?gniAiUTCpynmn8|~pK1x<>I zmK6%iA~n^u+|Rx3np3FN&mE7}%Bo19y5PJ3Nt2ruo~$x8sAax8R5jIw02q zf_72^J8eXN^o+;}%&+0`vKaVf<$u1TO?RLgGsnxYxxbE^Fr~W3bR|NeU@R4W7-rxB zWyn;wXvc?+ohDrFmP%cc^tcsjBWUx!@me>z>0kBMbkh3(NBwchCYAw*qSKMwp+Lu% zE-b&gTtXZ;h5-3p!ZvzerS#1e_RT;eUMm94n3#GsIu+03BeR?mOnx9mgxt5PRZDkg z0oC}&&8!7)oDQ5t*3KrIyOHNQgoZmTS#g`cH6oe8K$~-cxXE4y0Z$k6kV8>PlN!_< z6F~10Q|V-$wgX8q8_%0tKU;3|IdX3_ex_0jn2Pk&3_4j2Xt1Nttx0i{P$h0CDe_^xa!8)r3 zhw+=NoWb-FB2fjDIW~p1FdtB(M{{|YzGoV)3QUw&;2FOfk}FAD`M-vHwLwAtaMgAX zft$#p$o{!tT4$$uZYO9aB5Bd`4_n50 z`wV%Y66HCai>TeQ#nOb&2Y6BmURdu9mx| zE{IY->JAavw>?{xBNJA@YkPz-c2=lpq^x3jih9PXla)I3HXgI!YNHvfN&xtlx{uoA=00Q+A`eUjle$^he~s2Ep$)iE zmma6#QY9`%DwW=jdH^)s2bf_SfDBt!H#-$hgqL#GT&taGXDahGPU>Ir<_N$jawkAU zPe}19*^QKlC2O{1(MFw218(|Vr-(@qFK2D6oY)ko`(Wg30Uu|J*f<--#fgc+kBY#5 z2rQh=sQM5FP9*+KEWfRbd$T3XoBQJ3YzymVvp6>~C=b1H*w)0h>14(brcErD-3QBN zV_Q3dqEW;M;@0$`$ae8+?uk{iZJe41!Km3jKFt=fX||0^({p2OPEz&8q3K3@4B*d1 z13hjJcV?5AGuy+P**ezD_HbsljWM%ze3|WI%iI%JW;>WN+s2c*Czi}sab&iPA+z12 z^X+2CY!^3XtC%sH$BT)@iiyFAiNc8K#E0p|hKaz1i9MFLjR&($ESPQMz-$!{r6>N& zHnCrRjd|YpD7+Wm%NDU-B9Ff9W4vq|-(~yQE}y^=8^(0`O&_sAslBBm_5n;xTgPqb zxGaY;Ra&rGHjkA;nq_3bzC&Az$D3L{r><&YoCj7)-PNLwED(a1Rwr^}&3IWeI4QFk z#3-~!UoCQWO7;ZHCu5rD`}5-=vHx*0B=h4jx=EfsCG!*Y??;d1?{e3Bhl8)ebsFD< zGY)@+e?EFd_V@Qcn^LhqKOVn(XC%bCcYcfb$B(4>qHJ$(Z*T7aTEn(Z8g0RMjUU@a z3~j*|``&TMZv34*dgM3dcm~}3m>e9CuZbmv!xJGwxU6Hy@bsxAgWHZGg6L3BED26Y zRW8`U!CqhPRZ(SatP5=F?fV|AyUMwcjw0Uif_(}MygBy$RhYL)C5}rssawL6hksm7&#CXo*>%BN~8BnvC`>Yax@09La-Svsw_eG zjFX600}3)`Xm86-p~Zbga7flO2tHXw_SFOr(7mDX8*Fh}?8X~zPMYCC3f4i2y@Pc^ zHk|M8Yi{_fZK{S$qPjqXuM1P;0VfI=z{9T27c|QkB{Mc`0zIW{4lqf)fP3DI7R%Z& zYq#T;qzZh@=a|^7LSzCr-3d9Qd4A{yH#d7$&6q4>oFo$}@jyz3 zq3XRV>12{6>SASc{N>A%_2o67wS$r+EW4E(^~=YPb*gQ`)1Z^(k};EFYA5XG8JdI+ zlmt*B{SL!P-y?1eq^Gs^&}cbgG2li{S3VSW1sW3+=6+PNYEc%LbR8g+hA)D$hrr8_ zU=3D_yG%&FWQ9WB0zXKh`!>KV;Q`rvgsHOAahnGI#yEc z8_Yy^hrWU+)Do(Uk1}peA&HDuZZDZ|aCM@u*syz?N|DNP*vAOo(!@)s*BjGNBV@<; z0U?~t_}I0PC^9q%7cFQYBq(ou&V`;O8a;z*&AkrNjJ7&$bw@q$XT` z_rs6he-r3r$_t$wB(DMDak5eU(AAAmEW=Ln|6(TR7JKd=k@p}SL-#os@>$NBc_yiWfpb2W3 zXetiLLa>POYYHi8S=6uU<8Zmo4g~?9ek3MIA}o(ICy7I3W=2y_F-N!QJalU?UU0;5mnH5 zp&Do57?MUid(%m!+A!;#sEd5*9J-;}dHSIXDbp%_PKm0d6}y3KIr*g9 zX)304o)tG^a(4c*vx}Prl?n}GM{ZnvX1B68I1y21B4l9z=JH=CA4VlHHPqc_9Zn^2sb6)T3S@V6?Ns}$1bWCGoKTNpGx00BuDX4q zYoEB!LscbrpQvJ|?$cGR+Pi@`0GnwKVU299MLGGTE>8j@AKBMS^YeZUo#?2Q4#e&?Yqi|6D zQHt7kfGYk9A;rsW=^Pin&RjfstQ~<_v+AHkWfk8wbp)b%L!|WR(>bTKv<=lgII@ZeMAJPajnQ zpLInWK5ZHXR_!n)M6NXie>%obOh7_Aj(F%vs9+>3guFyn*)1EB{Y%D7#hHrpT#PeT zO~$;uIht0p{HUBHasfV9F+QUwVNz6jq&@r8$gci*nf?vl`!@^L#|mK|xtb%pnpw4k zA~rP|4knxrU?UD*z`x2)B%b!i&M1CAlBOQKisBmlw7)itk8=e%8~p>XiJyJ``#(I| zJN)C@(fI$od;8(5#~=Ua=Rd|?Kk(^&3Bd=?pY;XI-$9Bhfq^1bMWgjxLa%IDcQL$I-Wykr%WBDpKGiq+~HT1$v4P3y*-dsuIN^U`GdCY2t`OEzm#`6SFKTN4*M zGm3e3W|W;7WoJg|dUj@%of&0kMsZ)?nNje0Kr_lZ&h=MWS@LZ=)v=Q(XF9xTYx2i! zzzdx~23c9EI944AF=e7s1xT<)iw^x1VW<`N!Gf^1Aw|LtZWG9=)1;DkTqbl(j$jefj z?x?x7kJ9*Rr4<9F0@;Iw0m#HMi!QseB8AZFUXczuz1PliNHQp9E7jgxIBiXSvhG3X zV$~u97Z}%FFFQazs7vlJRl#_|7lj63_NL+5qK-Z84r$5fb026CR8>fLQI$N;HJ%wO z#6p=k>Uk>B{n>mL?v$(239TxztK#Gee>o+p3Ne;dh7y>Q>}C-aLxc|y%;f4|r;8$G zWxfPJfqHG7-b+;~qj)P8vdZ>7)Nwn9{geb^@YtNHuuvDMkt{e=wG!G^EV{o&22$IS zwXRh=uvqi4c}y2<@|suYtej<4#ZsNaw7TrR<&5rcGs|A+%5@BM0$cp(6=Ln^`~H@pmxcQy~DTT=nam&H79xHoJM9CVS>N$F;tW38+^LJ#i~t z4Ek6f?_)Lkbt3S|14ZGJb;FLyuM~|>*1eYYiOMG~r|Esx=hOAsP3HjA6Pm5Q*P0uk z8L(GxPC`IG+u}D!9SD83Wqtq{07_VDp6%PN6n14n^Ve8D9s64P@cU$d-a@r z^ZF9fzsuB?>?3)0+i(7SQ3)xv6+v|YDZpnE1gja9h;NW3iyY2Weg1)P&*IMv`IsW6 zPOjY;i+=(*j+}&2Dg~W@f}+w~Qi^mB5!~sVIfuS>A z9IU28tK|CEKePkr_#S=Lt1Y1}rqh=X>d+wjrY4W7^NwkVx=3wN>oZicC)ibM0&u-| z=)2xwd}r$<)R6T}cw0%VA?u3ZzV4o_B-xProOo+4!`jpemKE|n_c?mH%MTeuCtvj; zh56E}%Njn6)m{2+;0*%P^y;^H&D#!CO@L@y0Iykn)`YWJefs7Z>E~A!nZ3&r`JT15 zf2e$s@43&;2ONIA3vlndwmmr3i^c33S#2ShTVk^d)4jDrcc0v8=oYh6z;v^E-Bq<4 z0>Ed!$65m1xhOHG)J*qJL(sw;1fw}17xn4##cEZ+;VM;U+07Kxy_A*Nt!wSmgy_|& zxhCl40kn}m1COZ~;(Ma1hK7IX?y_{=n_!#4n&fCUk5Tsu%M1@#} z26awDQklab-hYcY=KCW1h3x|jG*}k^75g!H^a!D$Ba?Ua1E|7kOnZ9=v87ItZYfw9vbcGzua z6YH86+jhKtr~1){gzi_xaDdrYDR(9?1We1{a|G+Titb8<4jEMueaAh~I>0bEtPfSS zcqQj@rMofLCIhD>=dzY%x`!h7P|yZjucXm@dh2!}Jo4tVF7uw#YHH!UXh~-bV70Wf z0$>G}s_;!U)jW|E37t3NlDn?na3(7iC17uC7N6F?nP1uV?o}c$%269g&|DxV)L*GXs2GSoPwZYN}UtmP& zBF}-w{p_m~h*iK9Qh0Il2Z;AakTg7D*0kOnKR)?l+ZQoK1*{P8idM-(ub9(w&qbSu zsv7totOgptZgt-m?G3C!uqyT7Xu|o?H7y6)#EWCMzwJmab=n3%7SOYSN)6>KMJe^qFw&=wv?O22^FlD7g3e|#3JwS2$SkY z9SvEqs?xB(XJE}_sSV9AkkSg8cqO)_KfzJD!CCl`sI7?e{-~Ej|NN1>((>WF?-@99 zpO2%^f7X8J)rl6L@E;#B|4Ba|iIiu~%lN}lzns&UK9080$I%1K<7gZ6aNCGjkN$J$ z*ZykxqRtLl7yB=69Lm4Rzpu3jtrJ*ne}mNDK;r?@*I(Z3$nVwo1FOyO(E};UZ{#`U zR%X&L#c(z&)vg?qvlI^#nyVu62nOBH>zAfz`k`d9s1{IdFK1L33((p5%k|Ypg&e0q zsTg5MRoTR6}msFN-PgV0$jrhRAgW4%!fP{(pJ zN>%7M{(JSdhN>`BdQ?w+0m6Rxgj_k${*WPd)ko=)tJp8^x^Zz|=iBuzN^9)<{!SLz z$tU4tX_#$R3(fYREV?_Tkg~DbdyRFD@rB^yR-T1M!Q0YoZjXH3V}!;%)0lQ2PYtOP z5Qe6ywlX}RNsj?GmjememuBtL{F)eg_VshEQhsfkts0-U#&=F18)7}T#rP(P>l|F2 z|E3vmt!XPtdRAvMY*?G`{W-C=5WVQvCkkb4Z-oj5G2s~x=VI%XQdDppUcHnVHmIDl z@OKS0phG%LHKXXxCOpsi9e84}7;gMH59LVBc)&%hOD~OTUK8Jlk~93 zTd{D*Hhriuk}i0)puiXo%&$|Em35b&^nH)T4iyiv%K+-7~4Mvm9g zS63)g7n4g|SqRQLAn$0AzJoESUC@VNVy1QZo0yl}oDblUT_=ETt>CrZfouJP)=&a$ z9fZxu8L;!?e?_0cc8|uJhTJoFC45BP5RCYy} zR-auFCiCpfC_6LC&Wz%Dc4m~ovooW3pPd;c^z6(izkM@GFCxY!V6JnTL&9a2vZAtJ zBs%9(`_DO{^Lf4;lQRXJj1U87=Pxn(O~ggjVWK9;?wksNN%&a-r$)(`i=<6*cFXeU zxZn|lWSo*0YQWf00rAUONfKTvAT@|MR%I?QXvHdYk?TIFg@Fu+E=4n^$$NUkhJ=l8 z#$=#C3F?6ggE2Xa2CZloWP$)34b2Vp0&snzqZ39ZEa9OkrTguo7M3j*CJK3#TuD)R5&n2+l>f4-0qQM#-&pQk5qLMkp5WLTb@9V}-nmCrpU=-3+a$ z2|&jsOIUWx2*ryrRy67xT)OSR((MM7K1@LAwu4FU3mgy|3_2oS?IH3@UxZ|zPVo@# z^MyvVjr!)ti|;QGeJ<*CS8PV>)sa`MMVYIiY)iYglkF9wx`NoJO2=fy&2K3b_18l1 zMbm*3tlt1jl<#W`626OMjP9^Mxye1UJ$8t?&IlhCQI{gFkb=Y9!OYg49n9r9%cqsw1!=Z zEXHhqgu}etk~nTeTP9j?HriuuaQjh88U~bslB~}F3#vnx;}zRs&3wK zxipO@+h-f5+tW?c&5M7uIi6c9c)-VWzJ}K2I$vAcAYXsJ^EP*H#@h((o^G6WPIQRN zaUOn(VZxe}i;OvGm2UWboklg8g)eMy;x=k<5)~{{8^?xZlXuonpGJ&kgLEHQAaF=@%JyPZnsM>C+9&l)2HyF8{xNh^Cn{?k(q7ip~uO$x5 z_-XGMM`v)w=54Ka4Rgr;iY{&PZ3fQhX;sa^go~*HeGd}e-U93e^x#7*I`6cqngvm7 zk%>y|Pllv!^=OLF&N1p`^fy@Bw;e0GBjq+o8M=zrG8yJ90>~6+4x_{-8l&`IEDy#a z`-SayQ{XR8J7Py`6ARpRwlOpB#brxV^J!OGTP?$*TbYa#alWm2I9p>=Q@APlVjdR# z1}T0J21@DY7XDUttmDdI6t<28BqlWj76&(2oM&9H>W-K1v*Kp_{$Ip6zm#nWpb(aD#8`r@&-RLsFRP#vqId7XM(TMD(P5t*K~6mzn#Kh)8j7_6eJKozxK z4&obc$!>1;2ffw12sQ7>qOZcDC_06up15*0`iBxoXQO`@nWX-G@byN7Qg>EUP0q9d zAsLaeDd`u;P3BvCRh1da6PHyv3f?hJr^QaH4qy5$5S1GG#miHB8zpmJ5)nhgyFuJR&_S-{H zNwuE4lQL0d1ulYHldFzSKyV$sNF5Ag#GUBO#z?5p z`4(;sNmZQ=+j9Rjgfkt&F==_jDpk!g+=*1i@GR657sFLr&9a+m<(6_aAi{dGo#6^f zCDdd_REXeL@dXTflr4-bRv26K=Z;CrL@MCnF8gu#zeC3j9-o(7E?0(elLnYU>2^A_ z)e&i3cUg1Nypd~`3CN9ER17p#ocqzfSj-@SEzi|YLgUnQwEkCY{en#dWJev~-Jsyb z=oeOU70?P>pkz8mSMV7lY%a1~O4E|hx^&?wledkea;c;7W}xAe%^4#0sMMQz$&w5p zSZJ4~-3+Qlfi1>*eU$Z`k~u3A`PvQBctHf|*3p5csHxgpFkDCW&jroN@#Dwc$H>bG zCN}ZH=ni${7CEA;vddWlTlnH3Z=CV|e03VEDB-5!fAv)&UC_6?@j--Qn8j7eW=gHVdUrVk-y(lu-8b zeK6I5Sr5!h2juBf^4OTc!PEh!Z`F2}4c!U4l*8%@vyAW{b@`4IQc@euV$UB9-ld?D ztVhzp^P=;4o@rzW7anL942eetY>@|{1pZy_o?9r^Ekt&mvy~hTZD=q*n*pjD12046 z1}d&nNQsv7bDVgN_ka|oD$Vt7{8kyAC zWIGmPP!Ttwg)!^sgb5IWu{kVi+*Az@Hh(!UnL6DprlFq45QzmiO-asZnJ>+KCqQ3$ z4n&|`z2S;Fgcc+#VBdF9qKz5a=d9q@oD7zWMQ*G&Q&4(bs5CVYAgt7RoNrn?f%GMO zk%E~Fnn2~A6;)R1u1$Wtg9_(%D9`bBMj?*&=T4>8XOlj#cyIs*LXHOKw5&3k=gXJa z&OnaPm;V!5&}Y^hIYL}IqEq+bKWkWkwWG6+sTl&c9Feo{zpnv28nk5>SrC@4L5lX% zc+`a(*AA8#(PYDbSO>PlldIt9*jUh#78R3g3Lu1mBW7iC?KHbY@3qbbhtzYm(+y&G zmCcyY`mCkoqR5#LgngLjS&~%&?#zlbOK4^7Hr>U(&+^=m0cieV&XNi#4tu1YsLyDk z!ByD@u-_=oZ0*2t_emYt@5&TIh4$f?q}^k1ZT+_|_&C|IZQHhO+jg>J+qP}(*v^h^ z+qQM{JokT2b)CN5Rb9PmRjs*Z{nq=rzGIBfm{fqIxW#NGVZH*_6tr^b>*FMpSrEp6 zP=g3j=x=Jmqj6GbJzAw6!0lU#lP5UDFwfT5m5)wUv!t8Gf8%BE@s+K^2B`*1gh(XA+4)A(EX$v+BPmHuoG`vxR1lc*nJS;2|m z%hC=254pcewqAukqKvb)ZK*^#E2&6g>R?EIg<hhdhBhv(`BMzyN`D=HgmwmhjL*lTQnQElv1Wh+y^B@77p*WdH0pHeg ztTS;S>Hs9e37y(Hu_)4#QcrSWv76Fj(3X)jMEJ`JBoo>RzjY?liXz)=a8fW&Dlk_BmZemXg$Iw)3f#IbOl)xxb>WXGhJ#w&(mXENIcj+-g16%hiMxUcstt_asy zKPozKwLU4Tif;rG8s_Az_m`}EbPSX#4D8V3Yg=m>KoOe)eOCez=i5na#Rph46eszh z(;9pJp+p)7JfqGsg;#rLhJl;_Gr5*<9;60T<_-a{!iZ|1g1E2vKq!HKlTNPa2hhZgJhq$%t!VbDSs0Ha318JKk+GAuVUqC} zLfB9QdedR5Y!iCIdz&tfq)hJW&)sJ4JeU0)a0F?WLfGpUCb9~3-*2R2Y8jLHel4RW zRrDE;O~ZUlo7+F&NQ0;5M~zfzsBUn~X0+HT_ySi#{26mom}iR|_YBz8A%S3Luq*vW^G{ z(NwStD4Y-YnGHBypc^&vujd<+Z`|gcZQ!Ig&t5{`&++$am6dCsm-9@Dqh&1HN;SZq zkvVT~VFH1Rqc4&7C936?ANl=0f;TQ-)|pRKyXPM}59Gm?#jiuQ9_x>o zyw;o#W9RSvzL~aP+!!ApT1sa`qiEHW&xnU`wpnS-S<7ckpYqYp@rp11Y$_aVHsB)f@srBD6!w28<0yFCN?#6{ih-TOYrJ!F=HknX>t*y>>nR2R;CtB zH8ZBYDXPp&6BWObcFDS$t$a|c}uE(+BwdCq0q}foJ>czwSW0Iap z#SnZx2)+E;Fy*yZ=P6SMBy|oIephu7iIZh@En1ipl9G)AUSLkGE3>??C`%F^{gsRN zb9E+MPRtZ*9>SC=wUc)PA|r`!D>dyP>QktFQ$Ed5?`D|ul3d&y+qYHhiA}_JFB>6N4Q55IqtSDMa$4fXadG!c{CWmaS1dNa6xeK#b z&*TSjsBRv0YVM@Qlv1d;Dxh}R9CXOEl`V-sMsYfIE7@2%RJ|*9+tZ^_J`T4o^`XD= zh@l5phRObz%L;`v!)V#bFruXf-fk7uR2*MaoBnO6JCvq^0(Xy$+@j^2>(T+y3wF5d z_nxwqr>yAkl5$w`$eME)z+s3sWg&kTNG##*RGNnTJQ7jZJnD?nPA8RtLu-+-gi7e7 z&Hj^T_w7gY-2@=dCJxkPU^x5Epr8~|E5ckKH;{D6Y)02_t}EMOsdQm^&_6;C@FSOExZRCI-wh{xf(^tlOlqbrW1p7C?rk=}< zXP}RQ8`slEKSvkX5%s?{ZzaXV7mE~Vi=EnZmq-z^KjwuR2-?&Q%1>5`8r8T2UkGg? zHMz5K^q9O`*;=UM8NSRlLunIT^>KC*0ZF{;*^`{&Y{nLpP?@7n{UF?q%E|r(U0s)m z8-TAS_Q2VOx%Z8$LvV-mB{oK?W+`KVYxSiVsqYecx})i-dN{E=tlXk|GXjCKx80Q9 zyOTufhD)NB!c#*Hf$oLknf--u(^WOlv=zZv$F-|)bd3guE|w$ZZ5RLS;4-q`<=;P9 zA!&qRsm^&0@Ml29V-NH#4$TB9OAar5O_O~&Hsj^(IQAfU>-6~ccy7d-H%9PVE=dUf!gXK6@{#{oFOkC^NU5RLiX#-qdSpT_}GSBvilF;_6HoGu8PV$>_%&0~L zP|nd!h&+5^T~0Q$$UZ1ZqDT|@p$_#=VvRNQlUO?^F$PZ+?$Fku&4lMk_Zc<=xnWjv zE$p3`|5sow#4b&s4@0j>At6awa?A8mw}lNhImSB)xasg9`qVH4$fJxY^*{k5fb1n$ zEm|qIqpCuIdsF{uJr{SbMydLeiE7yDnIn`hB`W# zLhqayQOX!7H#EG9QhYlO-+6&l$Z5NUe{2cTtqBJVp$}Dz2&T+%>m~I4Oy>YYRHwpx zNVOs-`rsF%BmTWC)$_VFwq~+FyJr;{=rzJArCWU!dKWV4G6G%LprD$x`{}|R{H;5j z)YxBY6JLNT?u^Bfe!b}+#^`F*SfRY7wy$Upe0kc1Ms#uRIbF}OU=e0=&s5N{aA|;_ zrTkvp4>xu4*+DUnP>s?*u2z)=XgXknIt=d^l@dep$F2W&f%1ctHW!2u$Nx^Ow@}oE z8H6U3X?+jdMr@i%;Iw;sb8-ZDcz`_KK<;;PHX(as;=%MuhQ1?sUoW;I7_?i-wk2=; z&fattfL4N1Owv^Oe*$amp&I5zI+!kl2Zq~nQa!*u0JVM&nNamS_;wbKNr(H@8Wp2V z)acM!Q|sjfgl0o)F~-4F9#KCHq*qNgqK8@we1_axW=X{Ik8-luj^GPS!*OVlNLqG3 zm2P`N-#<`wK9tY4$H6&rrpF>8k%L$5Kc}W26p%ZHb3bMkvPU-7sdaYF^UW@StP2WD zzXqXLqf+ar^mp7{K%qHvbpV0AT*|^Xr(s#@K3DTeujG-`_}2dYbS(=%Xo=2frP8nc zulJ1>VoV1R*w(R9Ps%kU`UNC92-nuXPcSuRt|;3&gFMq$lv|%~SCn7t-4SAlWnAfH z+piF#LKm9|V^u2S3l9ua44F$mB$%e{!;W{;FflqId_MisF;}rUVgP5h^u3_-z%$R0KKC#a5F5dlO9`!}er#SFt%&RaO)ZjqEZwuH5;IR%`Bzxkcf zS;}TDzVc!!4YnnC`%g+O?re+71aRCF@&F>OuN?{jcRtdpiWfuMK1{o&FW~17>^e4f z6{vRyO@-J^ehLHTXg)>{9E&5DjXI$qLmjLIMcxpBoM2B{L=Zv`HvEu+LP5th?g20C zYeZRYTUILcR~fYHZZ9R7%}+EJ1-0G}$lTjnB~pcTo`nfhQ&W}rRZ!e^1X9WfHfnxz z^h^|&YE9E`nR9xS7jRu|vcnTsR=5i$Rg5)hzgr(E7*njK$iBmIXN>{8IJ0eY2#o$` z03FOKdXQ7)rdnxB&r9Gn$e13}-^o*j_?ggdk4Po3L7E zYRTZ@KXgcU*)hEQYQCSqC+Bbsn2aK(Y%&Teko=_tyzMhxhhkn=jazL7o@hqXZuT*>bPZbxbDO@Hvhz|h+1F*_nDvHg17x#Iyk+-`0tDS z>a(3)CvYtEIHfbp235u9D4s4hMeQDOOpxJ}b6rf?!c>GhJ+DxL`dsa9Sja(zl_p_0 zxoD`xj~~CVFt)qS^NxN`7zvA`4|Y2x3zzCZzw=s(3iw+1>1ac-~cKo=)g^kD}wh+&k<@2e0=%Z768N9;wG9a37 z91A0&Aryqaq7vx*?bV*ok)arjr8N=8AGvh6unmT)+*6-_>Vd{Wsd~^ozQ(v*`kY${ zL$caiAqx7pina_V(2mBY@Hto08$E>i(+`s{M(7(N^5 z>3T+d=t7%^aU4JSv(~^L%XtX$)XeNqHNA};;WO~NCDnfWOkB=asS{oV1}CyI$NNGT z^mPpT@ml25iBGQS+080>R*LBM*?G zk^uzN1KCj;kINf@RqdoC-x0$Kp`66n$*palv-qzk-e40`3{aUF9Z=S^N->ogkdu+i znv??SHJ0jf`@SA^9HV9AS8!cfN6(DyZ>Vr5(xN($l)8yb>G~3Bl^?8V>yJ~3yec_* z&P}m3rSxT%nxhp=lNiyc??%rM>&8*^1YR%~A3K$p5R~JD1KO%*RyaMqVck4#0hIWf ze;YI*bd8&jW}t{A>5Hfr#fVEjM4U^&#DEE*#BmghJBOTHco~vlb(olN(X}d4Ge_Si z_^L~OUU|wY-Kk~F6B>|EycTFqDt8)yQsw7B@Jpm0nm_vrT}^jRxTUMC(y5N=C{dKZ zN|yg}FG;Hg-+2pWUCw0m)L-zIIsVrE^xgbxLJs*Hz%X;hWTs zn!Mlibm@Ls;!>zhi<*v?oKIGut=P%jCA6=hWLn5RtG zuB>$H|A`6}i-0bI&h>xGbL5lzZlhwR-z0BUu%hxJdy$xke2TMaaxpowPH&@1pSd6t zrB*OPR0GDZtb)W~iNyoJ^paoMLB0Cc#Nf6Ir1xnzWNq(?2vP()SBY-As{VqHu!B;V zt%r=yE1xh?(aHUd+-9UxdW0P6>+Jm4?B`I1x22j#JnjqP;Z=!p*pheFgER8nq)7K& z-Spg|={>C0o|&YFJuuGR?gGP2D@3_hGRp>lC_~UM(O6ESf9Xau2q|PW@j6xXO{zAH zPE)^UdN`H0LO#vlw@of;dG=FnSj;$Vr;SsF)L?(3g_Nka6E6qVoWB$C@tq7(_;!f$ zXxMpeZB$&=37FcFHVD44@^-v2bXZynZ}OJ^ksXFqwV>2sjEex(BF~0_YB%B3Y1$j2 z!fgU8c;NFgph{3%%JMK2ln`Xlf0Nf)=5198xoeA*1UT>hJX2GGhDBMBDo;bKqen75 z(P;bKdr@4+eE{DOt-;C1wpqyQmD_Gxvy-BQycYuFWabaXgyNQhETQtI}bQj&#l zNg1`(ZNRYb5|DKC1>KhUASZ+_iKBcvNGKPv&cq%WOGYxQoqihIk5LW5!wc1I z^}6!_uChX=EmP5RvHJHfJOc&xrc42hG}mH=a-w9K4vIPpYG1DCXaOG(zSCz0c5gQW z2*iITQ~5g0r*D{7q5_NQ0PIPZnTvh{jGf zql;Vz&Yo4+dccVV>O29rN0E5)#f^Ufr1F?pz|9Ss77H7&4f$(`9#;zost*CF*FfoF zFuXqUQ<>>+Y#tP=q(@@8E~Og@r+|yJMw{~Twb$)XF4;$6QiVX>)nMb`WUsta!P?IA z3o!twZu9!i-wwG>Pj{cX9e#w4*QieUUU=+h9&hvc-goX7oAGt}e12%CDe-0XxW5jZ zkH@rZX=m}ApIv`kOg3B-vg(%Rojwh_1ko5!SjG-=?tNoFfp6?L#&-z_ zeg!j{V^Y_Z+kq?#jlJ0t->M#5BtTLJ zL_?JpHh#fkM)Xm)kn#1U4!i{9D1aG!KGFbLkSGFkraN0-rvA_8Wwy{O-@9J!7c=8k zRpD*N_v^)T?9&q*>^J+za%t)J^faFD+rTs*5AJ7r45?Wm8sGQws4w2f?epe2G=z*_ z-J{jX4yDKM9&BhZ8m5bkJ$?EW5H_KtGY%RHwLD3_j)8BhOdCwa>{fME&;nmW+Wvm5 zc~q27BpWT8D7BXXKUOREP0gJ+om5W{IOnGY;??hn69TrJ4g|pmF#X8reEbSJQqW*V zx099h&+#(IsUo$o+0hrdeX>kgM#u2mQ!z{yvj#+4WI1k4t17CTQZNS`j8!JRq~Ema z-NYQ3%Ek(1j0!@8y`MksN?E#6e3EL?#Ba@!OBuUtJ`v}n8IG>0JLq}I?tRw_RKgH~ z_P5%9P!;|p9K$VnCU^iN|AKZ+7EvQ)9~xnyc;xSaDVdHF(9sH85-Hvt?eQQf_kP|9 zje?Y4LdcG?N{%oT{FKk7hIo_$F9it~;%@A_x_pkc+j9|{vnF@|Q+UDLmb5+ZyTjK# z{*WT%5tRwD_)${FTZLVR|yF(zPF|IVF~$N1cWu$+H`^()~er^h^b< zE3|i~E!eLM>{Xtj{1(ASEqGvy@;=h!%Ht4wK?mMK`2`-cyNXt!f`gB95UFdyg3dg3 z`SMe^kw~N7kzY^Xqg#VQBCQyFZEj@{g6fDLQsY>=ZLUtU!eFFF#74f~cO`2Dj3#nRCa>Zp#o`0HVQKX);S*T>po?ztUU>`0RYZe-b5@ONKQcCAg)rK&I=a81FdS3>78 zz_N2)w)f&;>(C#Z+7+Jnn|lo?v8G0xL9Q^&D+iRkG0;V_BN;X-Z6I5 z{-4C`Ux`VZxt%YtTQzI8C^XN%ROm~eEHB%=!`X3ZJ4Nfs`)+7@SW>Se7r8%Oe35{{ z-Ds&ck6M3!AS2W`)ro^jD>C+>ne>CK>V<($-WNCjiUelPd1rtvgXbRY?S>*tb6_{z z6|Eh^$4Fw3D^25H)M-5!^v=9yyD4=XQ3n&`%OwT+wP{p7sqGL`kO7AGLgnU3WqWfI6LV5ga9G>QFE> z!KVaGZhi%oZZw*4-mE`~`B6*A#)i6~dq^CXuj3>o;JAgFWLb*iyIp5$o>}b|+)rPd z4PaGry;g$#e#oX`>$ZocthqmLJ4Y^^qXd#LuOf7jl&VEHx2D0Sjpy5BEpw7*_rsi39EyKj6W?3 z{Ivjlm77SK`NY;%FxuPlkd|X3{L9T)>W<|Pd957Ix7_3* zpSdT2gP5b$JY^317;bDjAxme{5*%{${!DGwg61NQq6ChUtwRftEvzy2rs;{&c3^g^ zo!-`VdBgLNVLWf;+310Dr z(*nlYXe`sJBPB&UgAi`IKVw!Ziq)(M6y*?<&8yE->Pl1cS(TGWo74;a%z0kblY-VD zwpfa{(fYlsig94N)FvpCj@;%Xu?k5Mee^(o6s;Ztp`4jxw^0jcPiz1U#0x0V1jry} zMB1zm)stR9B&`E>fKamKaYFmfK?z z=8B0O2vUK&t=(AljcHZB$TRM8pBz`sI$ShT!wstVSesw>n`io-GzKc)8vjhu0C|aIRlRVdbp2Ld3bWO*7!Q(1ErJQhNY$m^&)MV z?$qoK&eG!gm~R2j;)iH#7mfM3LOyVm`4gZVvp z2|>a?pRe~p(C2ph8FX>Hylg88S-;fnmh>D__X6#yZms=^Z@dQptRlt3(uVTBd59*Z zUc6j5FX)aEXd6Hz8Zd&@wN)g(o>8yDkAeoMw6WFTRNX?haqcJ2;k|}uL2R@IRBpj; zvQU8JL>8>TkpJ2dPs*g_mWP-ulMV00iZSj$;N6zRYiVAvvByzKH0MgAHEr~hhxM~y z^%b&_RFuFY`DwqBmtHrC*5uF`*U+o9pW2nnh7Tko^L?wBbdQoFrcj7zK#u^kB|fg>$lW+P@i;;hmheTJqg7AQ2^4U+GOHB%R@#(h4V5{^)3rH7O{e{1T98a? z$9g(+qWyqU>&H$mbjl0&#uou*%l=4-9Fko2z%C(+MF8w}pM_kI@)SN43lTo$a{YfTb**lRI0SKqJ`6mn9d`=GeNU z%~m#DyI#buB%F}FC!lk{j{!lcC$W;jw;7_$kV2x_0cdMp@6@G)Cs1xNgzrhvjW@LF z&PCkeMC%^4h$C3!k%TB_M%zq&X8)lk0jRk6JnuK|>P(mc#L zM9a>^*Emk)0j&XDO~4?VbuFKziY4m>sU??=(uc&%09CcAgxkf=4X4LQ$p$FWnKXMZ zr_srJaU>&L{N}UJ*s6#@rHXo~w36pFeHId39OjE-IWtZ^Wz$;3o*>*kA6%Gyp80(3 z@2}RG$~obZ+FVjM)z;K|*2iK>r|?vkGCFxqE4}gO9T%e`OHNqL%+@1@)WPi}yVF9E zWfGZ74#JaYEPJB2zaux2`(pQ<7witj8&BawOg>uCS7-7~47@aV`RQOaL%I3k{stwR zsM(HV*>cDKqMJnxD_lp5G?pxr$LI@`qKHOh<@YVeeGqsd3~X4+|9dgOJ)KZBmbyYg z76`cNdTEp`vA`nyHx87+^#3zC>9`2CHj3`(k7&qH_%sVnSCgzj+R)R3GtETzO$(dL{F)nk|992+-L?ki%lxby{MGu*R z22f!){lnIH_zVPLtcE}pPQ~>vH^0q1u2Nr&dComolqiDN5G8<}LWMjHA&^#Z_pRg5 zaLqZdHTZmj9GWT5fUXKOQbzi2jAQ=slZ`~AbCE}a7 z_!>Dys@Hv{!~NW!$Cd7uje)|du6SOqSM3}!52Qj(@XLMD!LrPVf4E7byL!bE{+rFD z`-I>z<$if)PKoX+wZDr`^Fwu;O}XDX9dTIO`8xd|@qIgswSd@?Vn89Fu-(N}DN7Zj z6d5y;;1p9d$;{(GO-~jGq~U$(a}PXmL7PI?ZGpW3BQhv$2~tiXs3Nd+(m3R5sw`~s zd@#q2UT`UbI8frcrh$9|CAyIWU<36@f?6IywHBh*J^%JB zwh;@NV1Nc|DM`TSC1=o7Hv93-27}iK=H5ZMq!ODoUa%`M^Ma(`brf0~9{4x(bvzwF z9U`gVi|#B1RX)HIPU9KUC zoe5TX0RXBoQurrIQUITwNKIHLnKCAlG1!t)0QI9O{Z4@SMK_uhDftDo2>(B<7w4#95+%UoTWb4nL$5u!wrQa*y#O3do= z#rnpn_7!*7>i%n^R*%vI?XG$PN8*%@jt1_i}er_H>a9rH>hv>NAk11<@I+< zU?TQtpXE0c(KEvm?l1XUM27uIx=5?v{U;$R>UghzzQ3|B0!z?gMegqrr~J*h^(LH9 zkHbDncLq6NS?sWE-QI5)4jDeC96BKYJh$uNTmw&j$TdtL?aF!vy zZCt&Eh&^6}f5^og!rX?vi;u(YT}8C=C6EnYj9{0#Y4Aydsh8XW4;BKW8bsJ9MoAG`vNn-Qu?oAZE`jB5$x zvkEI^$F-LswZz~2lrYU_+9~Swq}Th?9xVoigEQiYiOPKSHEbKX3#F1pB~gRtbM(Y~ z2Bk#n4g2L_3Z7(CDfk{0`pp_d;#J0p;>=bb3-*fHC0A+2V})Iq3QQO$DN~dq6L4nT zSp&k6)3{ls_}DVniS$&7pDSEhI=RqD-^jkAcK!Kk2KHNr)q+$O{2NZqi zZF(bek$%x6|GWuIzSC;9{D9aYVy|XL$88Pl5kX+RPX^?fE7^8ut;x!0fv7#xv`tPU zy}_}6Jbgo6dAdn_l(#D-6C89Cv1(rf2$pgY*D#FOMjY=K9qH;M(7hY1{Rxup)-2=T zWl4qxGG>&plu&Ta!Lsi+EUpmBCeLnhL)Kk_Exvaji`(u04P2DWiVG0>!ZE-rI*T1a z?7qd09UcFj4|GU*nfjnZFE?~B;ZnE(sNSjqeyrf`DuX0Z@P8#21rjhc6FVRA@a3^)yai$ywi?QKQ*p)=t1>Ym0Bws2Jf+ufjKoB>j zx5jY|w< zV|;8@rZrzQb+zG1q)KrzK>G&y-u(SrE&Ihn@Gptct6NAsv{&gO2F(BMwOosa#%(3J89?1TH$Ax zt0uK6{Macn;NgGqjD{@U@G0#J)HIg4p6hHfF{4(OZQ1|ojA2p#=#0LcoxHND*Z-w6 zKK$bJTmss3o~z~jkIooSV~|^qUZ!<;-ccyC9QofmV_e*i&NzsrO`ihEcR+LVv%j%I zt8xF&Us)ttSE*uJ36Bj(0=P!^ZMSSlyLR72t$BhoVAqFXKg=EmSdmhnRw4fwXP{r! z_|9!XXvJ$J+R!)u{r#n}gg3^2&2XU@XI` z8ct#5PK5Z>mMQoUr^5vk?Xpu_)`i%AG!u#s~@fiVd{@Z7i*Z6<% z8KcaiZBoLM$@2(L&YLkt^|Mt12h=%Kr}W<-#7YBPu`>m=#6inu3){G*x0zsIKuE`^ zMshm;htH_{u$K`p694(TuW?HDenWOfT9oF`u!RCqX+3zO0?H-2<1?TxM=sS+Z{tm{ zK20CnP4gsxs2=D5q=zQ8B^`PMQ?d!9FTY;s_L3?VAOt3t`Jqu#l%EL-G&Q|3>WecP zZwFWxV)B#dyAX3)b=1sj#i8VYnRKSOX5+^|ii0jke4!dUz_h`i&d4o}YI(E1-yciH0t(7tYiD5Qkz3>Eqxppjj=_Z#HDfyTXYr^OZrqNTZi zfkv>ve}P6?Z50&`Mg!2!W-)XlGZsHl5BwCMGBa>a3_l^coc!x3tplww)D7jBJUIwE z5~i74IP>3tBGQa`W-!+#`wUPutQmcvAoM2X?`1N!S3;z(7rn}nWtqXB%jVUHYkpYH zrw*93DhcXEil>)lVvHZ&2|F$EAKfO-4NAMh5;YC5(FeMPDd(F#v)Du0X;M zLCAj+HpRo$>rJIlS7*b|j!L$jAw@yzB$kFq!e!Xn;BZG#YsH(xgz6Qb6Vk$t%gm2M zdvQ*q^kH|Sg$<+s-mSNz6KVCMwb3S2^|lvc zZEhkW#}tXe7Zt~gutvi=$Z5r29|CcQ=Z?EH^0!6+H(p1_=V4nqB37}Rh_yBD0$37b zF57yd=VcAQuH&(et={*rhMPB9cf-{hzFXmq8RlW&ZVue8v$=@z+;g!;X)qdh!&#TP z*`$>nc46Rbj+m}A?J>frH--1j)8!VSut{7U%^`cySc)8G^AQb=3!`K zjbygJoObLT+wW;$WsRUlba%4On={m0$J`uSc>4>x&fp_z`vCzfX-$jM5U=-dqjOYL z%(x?ZPXQ>J(S0j&kw!i61y^ISd`o$z<5>mjkh^~If)35u2oQmrg)<@BQdBBSU?O9t zK$M{8!y=(ssj*zG7h{Qg_m8%S_>M;=#K?zRnE5lT#mJ}d?eif1MeEw-%Kk#BU3x3S zzJH_ka$G28?Cbm8K!Nf@I^K4;iVAjm9=C+~eu!t#jXnMIg3V*GJ};U@^;&+Zv-vxN z>Q#4*lX@|PXwivk&eES-S)Horpi>X6Y^~g+J%z-&Sc&7pZ-o~!K(3YXTqxSPG_J6&ANHJ zFKu6@UYM&;aPY}ff4n}l;8ZeY09GHRX1S?UfDk*uMLlS>0 z0YNdC8e2?C%Qm|S*@@3FKys@H-z@{cPqyS=V4C5{UG`zv$R=;_LC^6AxB55(RZfRzV(lI4LKWq2?p%J6~A77dL zWJ*`KAVX{(vElo18u zK@E0LFLE=;J7;l$^eMCuL&Oy{Op(sMJ(EVZTRo_C`6?SIBs6HHaKTq!088=Dj*&`+ zkET-k{V4?Z_M8A|Gfm)GAZP{xF(1Oe#?dKTK?wcsURbP=g1reOEi)-7XD5d0BOLle zQB-82&{GjRP>jHZ4C3`xon}PUn~!0WA3j#O>o0s508~V*la&8g?0GhFSim#mUXVV) z3@L>=F)KQgNB~A1lBIVi57e{kE2x^fXYB-L0 zZ8cMtaxp~XT3F{m>UaibkzyWBM?78i^tYt)Pk9B#czo11`pz26Id4%$OG1gE_`a$Y zBk^aMLAK5Yb(yj`I+x@A9#cnhS6_G-BM};vHa3AOv4vxW3G9N9OKvx|T%K^-CGZ{* zRHE6&LRb|vJ+M+eX+41IY&8Be;hDFBXSQc6V;rk+mIt?OduX z$3MP)<9q<)k|Z<&)+_d#ET3r~3?y&u!Bo64Gu`;q!v$=XLJpvo8gU`NI{0Ane#BU(oB0Vcdw+kY299de^l_*`e-^8qFJ+G+FP~^?8NxU|7fGufB0pn@;As=hoiW*VqmxhU@#2VRp2aFIbOS5j zszFfb+DaX_-Z&rajT&7-Ok}8llTcQ^)RYs!FJciEi{(z$1^YkDKW7!4dd$@hQ@E#; z)MGhI0x^>#8t7ric~|KI$!-99t6d1m0lgj}x$pU(QVEpBrv5BBAP;IV3_r;(c?rT- zhR88)tepGvj{fc+&|wz}{m4fb`AVq1+xqJD{sF_0VGrwCTe$B~1sy+a&Czd=lkn@9 zNAwlC_v;Mt=BbWdKWhGkfO}qp`BKj`+RmUS2l+`M$P$MlF93>4DzLlYVF2i zp1#&Hl!Cyqn&4%g!N(8?an0eckenbWkp{s5N&T4ZYTAV!qbcQ-a@Mh7R-Gl|(c$E5 zW5%J_A#ps^OP>SII?lkxV**TH>0z8T9J zktg0~Y_Ebpq;JmZ5hu@{I_5XO`td?NZpHTBb2X!Ua>6Z{3-4z=o1=JzJP~Z0xUlb{ zhA_mXSod4bH!nP~7tm%RpTQI>W%Ubb)czoUVIqDFUsx_O6um9)$?A-5fkY4Wh`5?k znXoxtloED-o)OU*EB1uVVX9VBVb zzYN-UdlB}0m{hXSHF=K6J<&RIqjR!Vk_G1azAqQ*5?{H~Y3|p)CjV{3q=@8_0g2Qt zbq+ovsmwzj)k#;WQr(`>6x6oRWINgz@VL)RC0%DLe^A%0*GL>AGmu@)XkAHHnD`-f z{xx?bm;dW3;{9zZDqtEoLt)9Gre|y{!EU`gCR>7*1wsJaynHK+;3pgWVZ3KxHBYAv*&UC|j{O;H@+<2YlL+!uu|x=~F7 z#DiOb=d`MIYZn@4#{6nt&9kX(aJ?I!Yn7W8paup=trUJWebiuI zs+}xrt`e?;LZ)3e54#4+|D0u+?QXGJkxAA`^mx>x0X`nT)pN$m=QZ^)UKbn z+{tNnc=2s^y}7>M9PhRJ%9RUrdLgRV+(EJ$)3DF<^Z#*OqVZNlEP>37Z7O_*STmX- z^MpWrbj)qa%ok4?5Z?`4YqLI^V7kF<4>epWU!Hv7P>owg!`v~gVqCW+YwOd-bk#_y zEyiCq4vo*lU!Ciy+jn>FmXNOda#Ja1CduMMFM2cjg)8l*9094!5+=e7tA@9=gx_UIPGzf27A-Pw*?Fz#y|LlwLrj*bkq2sT)*xUyovYJK9A_?l_|@se_29`1M(&kt51>(cmd-Y zBV?5yeE{!HeNIC^uKa5~BL8bWW(28Hl4J)46wGTc`aU@}RUVJ(<;q;)Y;a|5yuW3F zgF}1~1N>t>wuL=coX&8zeH~Vs0%W%jYd=CtnMa&H90n3HkJMC;7M^z+VHQv*VxhfR zQ?1UgsTcv-*Zo+JEBU_vXX|nOKh~oq4VCiq#?i?sEuS$$_E`m-#YC#E4(g48<7V+T z*cLv$%pafe<<3j~#YT7=s2!F?Ga2^Gvw61Z5pFzX<0o1v<>#uV&-F31MV^+`SHA%} z7r-m;E|KXO>ak=Jgo~^z`2t# znv+i7%wRMV0`!`IjtaT7J(a4U*lOkN2dPl<&w?p8RLg5-5VMs^o-*{~z~)5WU{^{E zMOU{Kgo^J5Y9{gRr5$VHkEiFU7l+zf1H&h=PFu{pk@%m4i4=wynhPAj5+-oKzTY%^ zY1fipSnHtZ=C!l{luv-KcTzziPtsc~aCwmD43`%d@pgd1=$eW`tm3OGSr-|%kCI|j zIxJd_jyd&lWYjkai!JuQGi<%Evrl}WO>$pS1XoO8p`)^&Y6on&GFKKlSDN=P!8c<$ zh^2ctLx3l`HQO5e3G_96XyL1l`#Y#`IE__A9&nz8&jAK@TG^F1_kuIVgHMNaGpVyu zGR8GiPH`hPbOf-hyAniSPpj9PcH>iXoztI#N`A1=NK&U!0M&7JDgf0TQM7Iev=A~k z?66{Bz02u}(8AR7#87i{w6oUXYLeGq*tTp@|BI@73XC-97Dhc2 z+n!)z+qP}nw#|t>vF%K3+qP{??3~Vg-`@K_ee+hmz51?Ey{gu;tUQ9@N;3d`G83Ki zz=qRgVuC6Ou>M@tl5w2$!0abUe3;j)#dpRCz!dNbSOgX#cXo$PQ-%9|S&xoi*5j<3 z{ptT}J>sr={<(-qDFRY~aO0obu2LO8X*tTPTrIL-8K(ZZ|?SPohR1M+(2c)Ch%Pw~utsFPf3*WI?EYoHn7RARUVVV`*M}%q3 zUZRDWxf2}W0@TAaqSI4Uf*v35yLmUr6AqcjTAV}QG1EXs)EO6=3G!+eA-GB?#t+yU z+T*0#?C|}{kx3H=%dJzQd6_(PuKADjsPTW&ZY40@69bfO`aGERva}RZxPvN1};3?rhQ*ZYb-LF zIJF9ag}&|JCPhQbLw|n}%B{GlobLI_!nJp)W!0e&Zs6ZXnZ(cs*5HWtVUq(UCHAY* zWPf8tODL`xOcn;M?;h_+)uOT5_X+FX=GwN*9G?E2FCj_y9^x+8N`s zS;o9c0P<59ft#S-7=xx7rg#JG^M~!gG3OlLtt>&S@8Pu0@ajX5^v-@-sZ9E1;(Z=? zgB^L!Z!zs>_58j@<@ST^FVzziF)+YF%$!Pv6R;z0ayQpXC)&e9x2a3~8PbTvVcj-B zVK?0}V0Fyc)bXd~_Oi&_$iAJ5{MvF_lBHM2l1FQPuYc(Ehn z72Z?$Q$uh*P6lFZ4jG$qr(~W(=GefW^iNP1#~8B_AI|3w|7tLXlN$XO3rcRoV*7-3 z<>$iIO^-$0UXu0~&8Ba2XowLZ1X6;CMYD`3`VQH-5OaRG>wjU6dw@Nz{cz83PyBGX za=_ug=6`Nsgi`>)7gKUUrO%jO&LiM;xey7jUIZk+b0HM(0ryr+>GEMr5_=*QZUL7h zz-*o;5VP%t_-0gpV0B?CJqv9%25DapC)mF~wpD zVV^OeW7Nk}I%S>lPz3o$hLQ`{<@IQKj0^@z(-s>Q@I!|CL*SU+yQ&Vd zXxwZF#&g0bK_VawCCrqcF#w`Ws+cxr0whf9c-sR}w`L!SV*i>Ayed~ttXTKHib60A zN}m`fafm-re1M*7(wx?>#jC9>JfO759qv$PUuJw%b+vuEUto{PF%!(Fa zbv!gN1#LzEeTwr@8|FHRDBb$cgi^JK0|{5lc{*-}Jo7e`++S-Oj^oWvt=n-`GC;H0 ztT|^t9&WNA1r%F|Gs2mA0?Dc;e;;e`9x4=W{yl}Xp`_LAi4yKSDF5ABgFVDx%!GZ! zJWIC)l!UGjVG=oTN`Xs9{_e_HpGW!)hm=b1EgUf%-LS%Jp0(L&&A)IBmZBrwZ`K+- zVH1t5n-#-Jz@h-{l}W%{c4=?j`lYPQ4BJdtKuqH*p?FSzCk~hx|&;BCl-_ zoym8h%-P1jn>1d-(A5EtTRk#%kHgW`Wlnu#|3f^M+BEDr zn4iivPO(Zg4W$=pQh&@Gy4h52`*RePTbgNCm0Mc=*guZl)`jihhR z8$k;c=o+n4tLNAk#jw&T9*W4?TIhR%0;wb~;wWzHwocgE%zDd)DXc$NCN&!m#&}LG za|VvF+FEv4rU*Wu-;v069&AVI6r4awHK$NaKmJ6VpzhY;gXihbi;yWV(?;k((<*Xs z&Z7es#PtYIW@{_VZq?549V;X&lIM`IW*;=+? z1^u{dCUmK%t4V5`WHC|kv|pK>KdmpXtV}wXsgxQFW7}Hf%BZXNs2N0+2^{97r)K3UI1uni{q#CXlyX-M<;c;;Js5F%UOg5N}(XwybdLbC^#_LjdHl?Z%XMMy z6fKY8%TrGRfdN|@MZmd;xr^oA70BMD!e5>B3DE&=@TOjJYAQf!BPv4Fs}!?>lq_0K zBazj??Qj#x>f|DXgcd?NU2h`pz(?#lP5V8pFe3P)3qdGV>C1Q|{xTk^vZvf*g~>%Q z16eaBg$@y4lWUF0m0x8D$hMz15U|9*11|_j&$2h4J5PqZ$il;PkotPFw7A+`**RRD z+2Uf)Cxx%1H!2OCnr#-~q9+N^mWdXb;tv28>+sS{q+sPK6ms^t$=siVKWfv*-uZ0@ zXjao)jb{2>^xT<3aSY9G|v#G4YpNrFEH`SLL89f;X2rz6O5JO1=R-TZ{6oaJy2Jw1=tIro(BnDIoXD%Eq4ia572M{N3u*R{ zE%fT6e2N1tS68D}kdRjL1-|iM#YOq|U3zE5Ry6pW7VuYKHKC+kHA2UJD$78SjP$Jv zRG9jdBZS1#$TjD)!RS&OECKU{(LL$@A%cwtq09M-wknX&Y_0)b8)Dw9$Vk$<79qrAM6R^}91ou%Eiwc#I0}!6ibRX~=GPz!4?5 z8U(ZH2@BwXUO;f3b5v)h@8>>ZWaHSj&Z|R03=s;`XeqE@t15;#f&xaLwi7gC)IVEdsKqisCk4S!P+}^;9 zZ-O3vP>`k=4@k-nrwSRYLPT(LCq@!T#f+^Y+&K&f1yd11MXYoSz#?V7AJ)ujf`ddK zC@9AkE&`Wzp)YVEy8@|5wh4P~dfYIwA1I^frvX!#&AE4RaOWxZHD4PCdKyR2V9?N? zt2VNkewYcz#cN9$urYHq^|J|}L|k+VX?PHbawpuQ^g)@Q-jKQldL)4)axJFzqsVg& z6EUuGJL_-@?3?3c{WBlyr6?~{bKq$3aN9|-`7@Bx3Nrb}hX8q?6mjw3v!41mVI7;D zUyH*);c+J$l&ZUTM!kRD3b-*NHveb}`dbW|^@=cBP$6Yp-ZN8{)6O7sAh8FNI>S#i z|BLJWa8M2whO}umV+-l;L4OWHOQot(O-zqFSXQ=UJ*r$=h0kT4!V{=5Y8I$C;Hn3>tRr9{dlDpKo7R;Psa8H z(G=t>j5p13zFE#q6HD~5TCAD|A%aRkciVvg(;}%{HPSXZ`pEK5yH!Ne zXYCcjNe~r(2pSI6i^gE(V1kRr33*Khr2jOSyTP#ANRAvVZM|2Fk|?_zszl?)?W?VG zEf*4pFa=vwXE7vFN>;#4xSFBW0tk;%^#&4_qIp8=^RWvuaE$T5X0!T#T+)dqW`jM* zr&V8>a>?8FrJ}=Lsv)fyrv0}CY^w{M2KL5Ek(R7+Jqd>&wJTI;)?|5AEm)8?q4CF} zY}N{P8W8-4{5AWb6uZYbIeD+o_1+|YM#h5VYyBb`_z7%jg-vaXG%$P!jB9AdrwT4( z7hvOrRp(UCNAPoAmqb1}-8GB|%)K}@ik%=ZH2W8FtBuIr6-}R?aYn9@YlRNVo zH|S=L6|O&p5w%qSAZLQF2`hsCjt_f9Ll%5Drf>x(gMYBVf=}E8iz7cZoMlAVz$3#X zzLflN$ux^D9vK;vb;-zhIj?kCE6>b&czxS$YA<=#yqGd(;9U>(c;>t+2p ziduGD`CZSb80U%_cE~|EXEV+|r`mGUU5PnWd@RRjT>h2LKVz_&n|9y61_y?q<_ zyzD&R+CY123smrRRok!jb?<6`dfkBY^=2G+^XRj_r`SGHZ>^3YBMRME?=su+ICxo9 z%g-XZ2-G>$)}HM8sY~lsrz8CIlDO3-y~8b=SD|YqyQH}l@ZkkTy<{=P(u}|oN`Jga zHgKfFFn`IqK^$a^#bk5b`@3KcsH9mwmb=xzTK*hufcbW$L@tIsSTJptDYr*6Y2VbI z49F9A%hT;?I%^2NeQK{waRXl7_3BBBo?mvjHSqRH0|})YW_y7iAjIV(Y7~k*6o; zlEc-@=Z}^o-yqeSD4We43LdQi%dCHway(eozyC%fL*A%YM+`z*z0}Q6%-`~3A`mv~ zaeF7z){9AGzvaPTg2nKoL`2ot%_1Rw9|3U_?-HU*Lu2@XPoaSasu|TeLJftJ$ycVv zOtX>%Ra_U^GBYS<2vLgMc`)n@q=IK!p&BLPn`vV*_t9w2Kb8P>dyY#5SsvI+2Zts; z)XT*?aGjYgaG!V60a~fp4*l#R7q5Bq#6VGmSH~7~EhfubN&b>OWhLd7=cZfguWIK* z-OsEZpsLmsbvv{Av5Moq$sNIu4`(#1Wkg@Vj-oN3M<#V7rx9P2G1WnWSpGZRr=m}! z2LoY~&6n^vU(h5H*Su(sN^BQY zGvQUCiy4y@Zn@OV6lFOJ%FMs+7CJ+o-i2}kDVYS=3t+3A<~#_l)MSatvT6HM(}U43 z@Wd|G4L$D4^tcF}Y=Q3HfE&YeGq0hD>+w635|;twng0nYO1NNd(iBniMLNf!%LG8q4{MAHSKK8rp`{b`2t zu))u5RoT~-YC1+|ci2LVo#EaH1+98w#CdIZc!HiI zvq+C`%_f(5haUZ5@(BxGnQ$+YzDcALh>L6Ic&IM>v<3O5^-p*_SG$6Vp5$@`msG`{ zN!mUccZ5#ixP216NW1PzD-b_7;-o6^I zgM-O(f1Ak}p94ml^4SHCF~!wQ;qrR(mdct;)X~Ymmz=YKlN{yJ>`i2lm9--0CYd5? zS^pSr%@*+0-Z2r!>DWHj5lI%TBdt9p&5o z_J!?8{v`FFW7H%GBg)Mzaj=5p(JScYAD7@EU_*5q$yGfz;$nYguA|0;0l*{9e}Tt} zZON(s0FNmD3q1aB(i%H-Z{k0|V`Xj#Z+g_j*2WvlXxv9dq`&@G&N`$f8WF?>1tTWJ z(%_pzB!<%KaerpA0XvB6WgVT=;aUV;y~8LuJH?yd%b%G7t4?VlQ>vQ_X}mSc^$$eZ z5g6mwfe+9)sgX}5GxoD(2MA(w0r!F@;f@n-&L0>WdZdgX;xrE@RLvNBpO?Bn0l*`n z(JgdG5z`H`?}_lAwmug+#w=xK$0vHG%AsCHf#CTo4H|m3LYOSk5#dQ(banvnc;K1o z1N)@Y($}yY&hiC3K3o-JMiPc6b|wpZXW*Q=(dOFKF);(0VkObI`l0VoSpF~Ycont@ z03IJho(_*5_k&kXNI#Bd`@J`1S3lIBdg|N>AGYzX=mUGWuEOF)zWNe%+9oB*p1r19 zd;69fZf%_}Z&Y(1Z1;2ZsaiS5 zAo_A@0m_NHp z7cCRLBtOc;5fjqZufsfM&WQr>9VKd?tf{ID=kT$M5dMH+R3?Hz{)Ya< zY^P!Q#a~w@>&fSe-I4WPVb2%SFu3b2A&3y1k`S@PzDm9Cuk}REVv*@phb+0Y=%ahz zA$PZ0>OFp?qg;2j`KH6bJC6d@^}yJ&y`7mdlR4Y!tV~DRg4(5o(Y`(%Z5d4~-943Y zW!OQB2o+*jqKJvaaTU+Zh6;Hon?4wpU<(bp(7{pt)vpa`(9y9(O(a5R+}deJxLa zyXIjo`33+y8d`Q3($BApEA-id)oKqpPI^gb?9A1R=|C5>-KUK^x~^x9Z(vlGB|chc zLD}Ts)IE9ydD~wdSiw1Cd9A#KrqD=xVn7tn`xIUWGI~6E^hgO=hF{;1OD6fP*bTg6 z2t?5r8xklWhK8Dd8*!WZ{12 z_6~5jo3a7b85tgIP*4J@ z<;Nxx(M(^uBW@IMKu{kc@$^{4_v! zgh34bm!DRH6@s&nvvA5f`qCYvp{h<0=@G6evDyoht)!Ok93(^{?Z*g zY?UJ@(o@qgiK(Oh<)&c)xoIjt`&Q0UoBh%vYq)ETef9-Xz1LHB*Qvg+lBvFfIM{_| zz|tpwFb4BTwr zE_Sm0yZX|f=%HgowSMXVxq@%Fi0(KMLWU>lV?iFp`S8;Vx}8AY+Fz;Z*`*l6R0gc* z+cJEN6BuX+{ujnU1LqEyltdm*q|T+l5E^7OI-dau;ok`5AWz`w*0j@Bn*1hfaCB=r zb}KJor5pGL$O@h&u0D$B$_Gn`xPCrYSW=zQO}g1Uyu$U_(dgR#hq=KnIux};vpBX2 z=o7_rlroh8{sld&?q1J30kfA##t5`6GEY{J8WJ70R2WY*NTd1XJOxCS19I@ozV}nq zHJ@a8yk>NOYEav6LzG;=Y@6SrMZxUazhhS)V0Qlnj22D5ec6ux0)G6v(+arrZ^ZTZ zpAbNBpcXJ&7G5R~fgKku{xY=(r%;tD?YnSAT{jjHX{lrBN^p$3&{O-Z(~@;+Wo~_J zXB9`sboLd8r1o4dpf4p@ruQa|*gV4$Q*B+{Qv0B{xRJ0JXRwfhEK;%y&;D~ex;F>N zMbWWhgk}vS?&(QurD0wx$%~`BHf1`oA|6kf^)XuHymbB|zqx-aA{M*PBNp6E1`)aV zm+hDjupKGi;;;VMj^n=(MK#=ley*zo%uoLP8**qSiE3j-&kaP4l|1LQR-1G98& zMZUv8*ru%l*3sMRwdF9E=!cqewO`68z}v7v$`x`6 zqHNWm8tXjl#;;Utc*dPLkmeF}96q;0yXB52iSm2%&^{=ijRiwWKA zcpD#&WyBunCt3M{bd=S~VhSi_vq2a~*jg@>)R5|9+L!NG?s?%TS74>v!X-k3n$`vr zs1f22uQN)T#qlYiN8;$lV}!m8}%J4 zT#uv>r=}<*nNLl!;{eOrvoG>NnV<0q<7MOT$%^|Xz;|rpTI8Rwu<;}b zMPpr$r~lzEVY*x9UOGY1D2>{iZkP)ik0aufcVzyX0UC(pfGZ;JhrnDS#XsLs7#Xct z##5`*LsD&0h-!#r=BB475NNe4*PwTnDlGjkGsn+3sIr$5Cz>{U-SVJduAEZoI17DJ ztzTT=$_U{%kJ47Lkh&?AX+ynDpt|Jh@?5i(i<1=@QF*NNimf;U!-Y)d!Ha%kRy@D< z2IYzPfd7QQrmMa4s*2jS@dJ9ksS#EECCL5VOQ4c}l3t7yw41J0#3a5ZCZ}@frZInn zEqpmWU+Nyz*VWwYhTO+?2XCt&7r)?JfA=&LRwt_y}dCS7Ffn;28D80k#WAHU!|<~Y<4mXzB}@lWF_9R{r1r&Ymr3X^-_abd-ef=G#b>ZU8Q?pb0DMQc1W9dIK*e5N zFzTxASwi4ZL|vmy#YN_B`38OCsz$TLPeSVEG*w>qZ)+ER3+0Au7;bA!VN->3eEQUu8q_uci4nbTUS>$!JSSYUsf0>ojeuXgjRZC(1CUS4p)4c zm?YBkK0l5tQl#u8Mlz4E!QY3802=F8oXizzK4X$h7R2AAx;Xd&58$JF5Ti9RJ)P=q zt1S>H%`IpcAWaV7pKAn5YNtdq$;sOLhzYo5>+ev=Q{?*INzL}KYd1yj3msN3XNc=t6(~mC8F@ElN?$Ima`+8 zkP;W~gVbpviS(sOMdPT~rh53%ATBxibL0(d%nClN9CxmuAzyjZl~$b=J^o=`Hs;Nd z)UAC4ZaIgyTTx7U_?c;|5{~YYkC#&Dx*5(IT1e}6(7OE_H$fM^-T`uOLt00pp{3c$ zRGUM@$XTwwNq+K3lod^DKq6Y+a=?y%vmrk}KjG~oJaCO^Iu_n<;c;q`bMt9uWo9l~ zRYoV%xxwM4^(?A*DvOuXck%CRf-0>pkLT>de0jp{o+|AW$0i3ax5w5eF`xBt-{i@tQnpkPIYFWpgS>7VWhMyPA z*&bXghE{T%cVM5H^>@C|O#@BdGD8(v5WAgA4aiz*OX6Hw%r|kAXTLC?)bX5|S#T%9 z%2H1_sJKRZM{yis0SLFzx7o_P`-#;@691;tI-S-k2JST z3&l@W%k@lkNh>WNFmrCEIJ^Bh4QmtXmM3Yop-91^FAw9Ixkz}gjvHMDIc*F%yOzBK zQl?S7iFp4y)wI>sb=A#vq<$SqOutsCe;~Hw1!5_}#DwKXg zDxPtoEq{beJcToJv~@MX%YRcMzXj{u`3le-H!|gpB4lG(bgdE?s1|3kEIxfG`t|M2 z;BQavs)ldH6-=S~$^9hiDV%YQO0}@LN)_{>E<5;)Z$7-?r69*a$>EF8`^{IrtalgwbX!xA-1~j6&zIiNZbNNHrkkw!c{H>+r5?Qr_gCgSMCL>(F!1Yg}MzH_5X$ey}zKmfDtAC6pR2Xt?(ww z!@8H398|m^k>t_cGFS-U9XBi0a*_eOBLTl4LmPe2|Q97rc zqN;@@4v-he8K?S>3E}&kbQeD{*}3j+nuRd+>o2W%?jK0ymAhaylI; zcBKu1xo;li!IH4Ka@sMrWQlb{Z$b`Rd0p@PwZGiR;92)b(cusHLo+}=SFS}~*Ew5{ z_gpT(SZfA{+P`$iwTvo8taf92x6#9UhpA;7s=>J1?*iC=x6~$dKcwIuhMQnBIby|I z`Hr%fTT{a`nZjL;41sJ_xXH`#c-Jzs{llWcGa~F8x$YXRpUpYHDcW z;M?jbviFsAadkAAQ|aNpc{X$?Ng*{Qe=p94_nA@j`0UIbX)I+^EO4#QHZ?1~CxKY)PrhH%h9Ah)WrtU`%I#hHyEFumf}{Eg%TVTaaj2bfxUhv@e2{n?@%IEH)&$I`ydQ?hNuFk0 z)kADK3gLc%-sm!PXLkL)QF_1m8O#i`#OeLZ+ANBT?w?g7!JxU>w7q6W?3ki&D1;w} z2OGKMAL`bREih3#_4dt-*z0^NS8$O;w9%;5lz3cAO9IBqkFg6BiHfl}f$9cePc=y%I@A`W?p`)}=_4zDL3JG}~Eg z$n2b9FhD|@4GoukVV;>^`NVQ)F^`?6Oi_n)!A zO98ya_l>QsYa;Mx^EAEupAMK6D`h81z>BaKVgl7p zfB7ka=pG?E5!D#Dq)r@hZGQ^@eNvyunnoekSG3%I2~m)P77;0G+#n-OmdUor?pC9Q zjA340xCgR!8GsE>pF^1nG+6c(#G_givpMIF`7zafHXyyGfn!dtiY&D)6+HzhE#6Ni zRHeR@qO&tNh&UO^IdbQ6&7RI0bAc^^q;T&`Q-uFpiXxu4!W}m0ZZHGJ+PGLiNIcB! z8ZB)y`8ixNI^DdY@Bp=zJWQDDdzPwHvqhrPf=F{xc#grE_f;e_ z3d}&uCfDYK0JRkK=+ZJ(zsPnYe(5q`uUQ9bwl^Y}s*tNUP~|U%aOpCZh+O%+#{0Gs z-oza1Un2&0WI>F0sf3CJNFb*f8ck+2YaV~3^qDj#ok5$hC#S83VlYtf$$pulw_40N*hb(EC-n3gA1U=PgXB=j_d!KZ}+iX)uCg zP)loY``e0$y3q-rPnbz=Br~XWfeBlo(Va+c-XUN5eMqGt`wKl)wRXJ^a2p~>A z7j?N+i|WIq{kW%+HXEg}#id=a^qDAQynHhmz@+%2y7(?{;Sb5{OM+NQzo#^>I95 z=90j`&Vx;A#jNtz=6f3B+i88deu3D%f(`Zbe$O2rxpqlelJpZl?=>@N!10HlDk*tw z(NDKhYDA6poLjxQV8_h;y3i++#Jx3c^b&&OViPx~O1}7C;Bg$4txV{{SRh$4?Z)pq zc7S{_-oB9}uetlzV4eZGiKs=*d55|z5~7K}LQQaoHdqx?lk%?fJ^YVBi&?_m=>kCv z+QUyJ*%@_HJX&5*AKFz@D)^|0;76{JWsI{q z*P4*3iY*xnyt|yZ)A|mrk)TLDDQ(*mdh3At4f>9E5J(g8No`0RPAYiP;MPv5duMa3 z(1Xr*&n2A{DUR=zW?q6f`5;%!2N#i#F5199Szkons0km!1HtDbK~btAMk0$LrERn{ zHTd>y-qxjR-O=K-M=(+c35*tQZEP!Qj%IejXG;7-j}YM%tQ`==CDtNgo-zW3I*qO% zWH(v`+VrX5;jcD$$4qk76mWf;q#hqTH{Lx(2>-ly6-Yj8)Xr!|$CRTw2caAq7(AMy zfOVaJaLs()|9&>VTH9cqTkN{>E(|#dP0`J`>(MRl@@jajylv`$75kCBy9E#)$Hp{@ zt=)mArjyW(+8}ox7KYpQh?2QjE+<1+J(8I2!tty#)wfb+*0CRIiL0xA*>;=5+A=mb zJ$z>nHElEZB*gkfx#AL4nVb=`&%rPH9ixNKBS!}z6y#k#w_ZmvMnr$OL@{(Z#Wq_= zsqqCUD|gsONJPYKh-zagt6zN6!;(1Gkt_o6_O;xq^D~vz?O@~Zfz&f56+PmOY%o^) ztN@tBj+7!iMY^A6n84C`QPo#z=e-%fi?q&v5yZawhb~NLUPe$RY1zAU_)^C=adl>p zNyyp>j(8vIeL_EFFV6R67#37T8)YQGp?0I$W!lO8nNVocwNQ>9V31TxFvY@408N3) zM@YqWMCX(p&44L3>NkUF;Bv=-yDQ)PDKUs-6F@d%z>Mh zUBlZI(q#0WP2q0cbH`wus76c#ZB^bCjA5;Qq01)xcPp0#f3iO>-mROQ(s7RqK`CZE z?8|vLS^Lv@%K&Z4uAx*LX~iz}rK>^fe_H0(@|i`>mqkS;)J%X%bT62_y|f+jW@zy> zd>(OGMDj3Mn{^Vm(WYq4Gt-gC=1CP%vGdT=N|NMBjJQQ)S6BmE)DcsaB0OLcYnX~UZ8MsJI5C4?7k6%clPFd7vBDI4yI47Glc zUV!$pg%iI6Z``_&L5PtAp$~TPs8+8fN{}Pp@JkUdHc4PT4(-R{VR$aC1*7_ez-d{5 z8AFYC;{!diI`%9G0%}&t70I(&=1+kI=Kj;%)94iN66?buB}-AJ@P1~Ie6boMa=#`s zDdQiAV$7>X3A}JS(|0jXFi~ zKHI{V@kmr2)bP7BC>O&i{!-L=VPQfR`Sbu1Oph4_kgVas1Q&iG`826 z5*4*l!W>g>DWrndff551^!#d}J*PO;WMb}B7Qs23#}p0-nvjjeNU%m8bo>BfKZA3Q z)#slL zqE=mOFSbZjK?H(nj8ITbwehPy$`nl%Yd{}D=(x>LXNkIh+CUKV#fMT2uJMNjw61Pj zeuGbfU9Bc;0m?kV=z*F@virPfyiYii-6m9Y2FZ4X4mJkV3=g_X?d(jT>Q^1yhd`AT@R4)V6QNrB61l-!|N z6BH;E^)N~*#d%ci`NBpjHAI~EaA%&~#DdG!d-AUHU*-`Nz&w(v1DMB6t};Za-%5EX z9pu=R!FzT6bAVpCY&v6)NAd3plx?xL##dq_rqQJ1@|9~IE${en&uACFDkcW#;)9nc zZ=Z8NUb#niP|mnucu(`&6>n_+l64s}t_^0`HMPIF3R~9;$T@?E)i-dHvoBcc*64Jn zbu~U@{xY6F){_2@AHic{x74tgP!C7YtIis5e&4Z@Y*1emu#6T(y%(R7noO*9bI*T%xuzx5mQ~S z2T(VhrvsnZpjU=Md$9z&t{KnAa&A@{WUOKb55eRaK!}K{7VBr|G^(kDr-+rno6YCx zH6!*-f>e=#xkGYREqjc9eRk?M^AtPmh-0LfGLP%FeFQJhRVDyw4|CrggTtcXhO1i0N9X=Gr(i@WtRbc%aZ&LsS8Fl0OSI zVuR$7QHT{=wN{+JSA&oz)UT|StI5m&a}QP8?68^s_A5G9AX-G{#)o6aHle^W-+`Ct z|5UpjIwFBzv(qt$8{UMDD}Wo5nb%Biv>q|+wx{x~cw$Dd;8b7o&)faIvpJWHRLO4{UoCB0Kp*=Hd z@`t1<$XCIcQWgFx>DyT!FNwYE37{^GV>KAq%}?0t+T^8tTX$imnivA>9b4}^eZqpx zs$B>&!r2v0Ghz@X)R$+Ra9(*C+`%anUSija#1|9dB0GVeN)%8{3u95U%<17$50Z-? zc)P;v(=T)8TdCisR8{7wl}c@r$}v~BNe{{Wt1ce0L|6cDlv4{+kZ}W#hVKzm?*g!F zqeVcLlK<|u$54!sUYvx?pvcdk%YBdMv|E(vYeUNo>QF5HZSvuum~$j8h1@d8wy5E{ z!{9_-m59+Kz99UGgsYW088l<^B;epy>R4>N=jPh(E^tvFH_KH=EGc3%vfpb~&BhYQ zoDd2_Rlbelv|`;5?)FWFLZ}a2Xyia_disXqw8cftb8gl{%xMF4f#cK)N-i);AJ^*C zgl5t5IFb-`pB8Re!5_6OlCP%-)RQU#AO0$w*lSXLdL@pWX3>00p*FyN(>{zNBHBZK zrLV?updd^nTE18LO#Y2wveczMS5C||!S6@T@d@wjiDwd9#+F?j-c8f78`$Pd`q#`&B0 zO|uH{_yHNu`;ZEB0{x(&+q^u}d+Hi36M9+Ohn?9TQ*{cY7Q9+YvUPwSXv=$}J$2UT;#Ci7f=O>F-CX0(NreOou(pX8i#DBnFA7 zSSn-kNP^~0V$~fbP3)VIxE6OD5%mIxts3`BnLx=-x8btXjtPR4%7Tt@I9n)P+f}yv z()@6@>ohKd^WGd#ZKcW=VI@5q4fypVf~9)n%pHj$YDduRq^OrT%nY|mjcEo8uuwl4)k8%DYnP#elu(>vrjrOt8!qbCQRsE}MgLiB zMFQ&rK=Oa7P>p^sU=r$KbJ%Bguh{0b-`Z1~<{;`PJ(tgUtjV_x48!A=4TBvRmucr| zAj43tamdM5$`5pYWUYaK1R`RcPn!8TA;C+?w+HiWn;2%r;7^T(x}xvYXNI&i(rIiR z&>w{p*jj5*v4_tF57VIkPD43uo<3DFyqyGdUbh1kO^+u1#vFb4ffJc)ZMA%CABXf@ z=(W!RH~m!X<~%!^HR~A|R9MXyzh=Dzr)`u0ir{BlV-j;IZke}jWKg+ zTG8u?N~s-Fc>u2R+}*FmiZnk~Xed?vj;e)qUyyfnxd$gHrindnO$8apG*}G`%=$lR zM~@}J4dqNF_Nf#wJf~`whGvZwwv{@2FCAvI>2g{cim_=5=F_ON%T>U~nCw=jeN7dN zV8X~zf*sJiT<=9S_T{ivoUku83mI+7Mri_=6!-!O3^$$^Y(MtUGRT6XyFqVad^Z~; z7u}e9X2J-uGSWUrWhQudBxPj_=h{Eqc9TTqem!TcLHflyWcAFju&wd{DK7l?ZsiTkS1j06PB5&7S|20e$>s+Jw$)QW zq>9abANy(Mv_x-2zA(w%JZ`{QEr}X_+vDRC- z3{>Vfcm_X4srbv|y=}l_ClLI)3mhE0@U!Fde(CY@edoG|75woEXOoxh=>;DA5toar z`4im14jp9JNFsq3d%d;#W}hd{lp)oMyN7#7Dn+XnLt)(%Ge#hZZ;u7?UC-m`TkZ4= zxXzTVa1m8;RPu+$FzOIFHh(!5$R`o+$c@u=8Y>0+PJ^LfkBMSe`PKUV^A^@ibNrjO zn1#;Pr!FJ-nR`x6DMa~@$@@i7X-^xQ8#?&aF6p6m#mddL9aHJP4rg|K8u4-X=dcZj zlpgaQ8wdMG+{QkkJn)FG;?;t>s71&k4_82U@DdZGuO5?;c%b$`)Zr zz?GaT!w8Ueoa0Czox#$#720vWAFbYFHdKxX6eB2LNrmFG+_UDx z&F43rAHqDiaN|SOz0I^+62Ay&0f*nWG3D|@x#TvTi`Y8X{XQF7(3U1b*rm4h_n?Zr zfNa+SweJ^6lh($~QEUcm$Md0;L<9d=>1KM{BHsPv=Y4AWp<5G9*+{|19ktr|*`+QdJ%KP^Z7i2;S0}VZY0v-)SPIQA3&FjxW_8R)y2Fdl)kzB3A3pg+S~2 zPg_N`=lN96Pc5ABx9gg+9bG)}Uq77}ZZbsuP`u1+><$q`lsA#3gD7`?{pi^Af4hDw zzvE4{ZaP|5AHPnbwZ2_tvxo<^w?&VyCBKY$e2Lz`+qdu+D%rya&*DIYO>(zu6K!@& zf?f;y<9ZZoS#_ZXd8{@>pH244epRv;z#quH=>a)cW3Cx0d?i;J%G$%eK(@I7(Twy2 z=HQ_mHxS{8(~3)wW~AqwPTG*AR3BICUbKlAvWD*Hr8(Bzaiyuy z1GhrS;t*>bSoX{Qeh5YK`bDPJ;?rDrSH?{=?U&z ztuhZznDd(z`+>(TMe+Q}dhRxe4x$CPY6MwPSufT*w}4_VX8kUy5Rsg6md>Xlx!hl* z%VFro(PYnm;>Ir`Oe)he3bK)T`sCPaH!f z{Bye|O4a&_BL7Dq;BS3ZKW;V1G=3a%NoNsLJMxr;JVAZogrstL1y%g(y55aLCU;$-|q0#S*K|^DXB9li&*{p^<%LqzHFQ_Ce#>|dfu|*u4 zG~w)u>0veW$YUrM-d>!&Tlr|qBq&Wj)(HdJEvoBbQWw$2K?7gZ-n>h8KmUK1IjGc-l4{AAERwFiR z$#RBo>Z445*L6@4FCGiUlJbTzc##FtYHB=*JsL>ZJYll4jrO~^q)T?j(-uzi7zx@c zZZnV$E&(`^CoPwX;=1Q=o3#fx61-6Sei-0WSi278^m`#L>wI}WDk^^KD60C0e>r{i z7D^{uQr=`?F08>bco8mb0Pm%fhVgrKN(Lg1Ya-h5xt*rdmJmihIaT%p>!X8SSpN)q zVdFFCh5Gq4)Pg}T%%4FoT)UAEq!%`&3fW}p{3*J>7mNg10`=zcWt)I^s|+EzV!;oz zZacLQQQpJ>3y*5fSv>v_9eI-Snu6Oc&0f_dE4F^Kk?i&lozdIx>68Dx;>a6*S>O57 zp8tLL%{K>!rTp)E555`lzwhMvnDf6Ke!F$n_sQ{5p55Z)dYj*?8QyvCxXJUpZu1wf zYTlbl=r#kj%IWn&K(>XJ*HA83=k^?(9Lph_+de}!_mIu~sbzDYJMhpmwxCyBBz9L> zVbCLS`!5h2Sfhz|+cAz#j`i1hQl2Af@NWnbXiEH}P~y5wH*karwhRf)LJsDRn!a9` zfE+tVjW;M+r1;a8kH`mAZN?7^(6-=OXY%3#asI+O;C5n@RjgzgyKbUcr0Bq+`IJV{?z=Jm zH+#orDt{F*+r1f+cT=#`Jbp}W;J^0Dsep9FPa;}#jVLpdddoSTd9bj*nr)HEy6~NL zR%&LXHa1e-)-#a@3$-#(TU<^p^R%!IUGX#6*PcB!Uuf!ouLK4v#i*yGtvn7pF9@Msbqyah$v{=$KSbz+J-}`bLeE#g6 zQUqlEW~?kv`4dz^0DD%<%M;QZw5-!Ia(c1Cd*Dksdik^|{LMe?#yoFK^k+jw}?0D%_yj7XY8X z0{pRQ9y#_Gok{ye;ZAEAGYhp zu=I0N(iLC#x>|oxy>p$gNf`uOWs7ar`A+=#dqu<1 zOBOb;ahu;1jQ?E{0x-t&NUT7_GF!4lf9wc^OUmPB1T0(nvvstMo6ZBwp^jZps&f&4 z$D_0^pubxfzA83h(br`mFwJ(PP6iY?>io#9{k3B3cn*0=km#h=-f0C&Wn57n(OJDQ z%ided16(Cy!Dn0@LWL&#USctO%ExkYjBgeb`{@!9>+SH)Fwt7GOM@UPoGM!h?rRl1 zWPMPcYsN1ZUAR0y!Am6`VoHn9?j6XN)Ixn#Yk_Ld;$KTT8ZDoam5@B;R|c1%RZfyW zKPE*AHd4oLRL+RBa8X;xh*a1S%Ph@k6x|T^E{HP8ugV7x4sU07LFFzAaQ*on`SMF* zf5rCq_Q<#7^WuBt%P%Xlc0QR({u|rfBY!3bdj#VZcAWQb6E@P@C$Xpv6Dj7HQn}E% z=jy*IZmfnr$q;Vh{q&3fm}!qoukeqq_>X%JzCI|&f84)+Z;1c6i|6Bx|1kWvf$$G> z6TxqV@DKdGF8pKWIF<_0A2ZX`T}FRsFKg|+c8K+`&k*Y|#CrVRVm<0Y0$O7|J|Ul~ z2`m|0s)I{)aH-ZkgG+UAsg~w6xKta*JGfK_m+IhB{iI#0Z7Sj5QEl#e@Th)l9@Q;m zXZF4hZpO^s6qP=h*+228pZ$Lo(YUYmzsvrA@Xdp-AC&F?2ls~j&pUZOZu>v-+Xk%v zCy@>xDcJtiuXUDx=(cM2UtuG6Y4tDUlpLKL6Zm1M*E?AK2dn?@-0EM=;A&R#+=knA zy{Gv<93=Iwc%52J?C+VVt6o@wkQON|2om^e&ALDlUveKbuIK7KV}CW3O7dDQrW_Ca zd6orlS%V3&Jy?nKx_prJgO*4~;F2aCOSovTR~4vp0xvo>F5y+`Wr$u%s zf^2C_GmbnQ!bS%J(qKUP-5ZcVENs_=c!C?jCh-dI0qh@=}trp_Jr$$)t`S zz52J7$^aYpu;-U@_<|_X)l8=9X6N$t>GR!pmE`1%cdXItW2d^s>thmtvSP@L@xi^* zNF#A68mk8s4JGQ$)8{2#bt;IerrK;HeQUip-am7$zKdIEFDbL3duacy?orzhDxq+v zieCZZyhgoZ?^Z&xvMNDP2h#f5Pi*$OceHqWk&Ce?rc*H7nIWY9#~HAi-WP?jt)Ls)D0P@~0n@Xzean;JTFzt+I# zJdvsD-gofd6+YP11ne-@n#3iGS;A{}YGw4_ zVVa)Vm+MwX7uv~}rX`r$ITm%%rA7wb%rv#(+mPO8vZYV*(CM7H^0ll-)G=Le1A3%A zCqWJGIP~3luhrX6H@feRpKemO{+DrG^t1mbG-cqT>*WIIu>U{2|DYWIdH>+y;b8y2 zi|6CE|2zD)0T+Ocq^NoU?4Rl!0r@DZz5x5TJ9Y zV!(_TFe5$`X2b@SzX2Vhx$6NP;$uUH@W$J(-Clkm{9`h^QJauvQ93T~Hrxro{GHX@ zkLQ|6bHfvRr>Ml!=!T>;xnwD!Xn-1H@G17{W-6I2&o5(<)a~|L!~NHi%DV=@?WB<= zLis9M>JEvs6fz|VQ(Gv2ge8CoN6o%bg3-LK8H+@G33jce8Ijw5#AvC5!qPSNwCM^4 z4OwOz&oKLlVda~%$u^Wp)|o}tx^}msjZfy-MzY5AouKA2-M#(K^tS~|dCp7_)5fd- zkT-F#NCcXD&HO-~@j0B=DLF?+1NkAF5gyBwsx!P+Xr>?-W^7CthuD-+Bmx?Z)P-sk za;d$!;i&pGi?bR}>V!Z8HNQKp`7=OM2w^o1Zzzs%%Q(s2*4NF1N;Y&$hP=Ju`9p92 ze}C+!KXm&4?;U>q_17i;|KZ_-hlBtBE}oCu|GyEpKm4oU?XPq4*ZB7D(xqR}T#inT zbIVCgemFlrL7(-U2D;Ebmo{E46+|r=IJD7;DyK^ID3)oG*=i*cb?YZ(&nDx8v6alo_|lyY@t9_x#uaSyBWNlFpGADuqo@=0TI9A73( z%CY&6Q<0@?tTZGwZ}^w>JC6yA=`1Ql>}83yYZyQqh~YDa8r^{YnU z1`S5Ec2ll!3k`a>`iq4L-4ROlgP6PJ7*j!JO+E{2h7K`yJfX2V0m&TdF@n^O-AcDx zbo{$>BA5IM90y=Sb)CZ25^w0GW~Uo$j_7xv88eklkxS79)=3NEw|w|`I>hmD zT{E38cl*%Iv!ZE@^`rb0EvPhIlxvf|Q&L*BrBy_a*%!qo(zlzq1;5$Xo`mouaX)}B z_bHof)m=B$nm5_m-|--a0DHCc9-uyB9p5|CX^-A_K8OBwJl$?G z8jW_}?7x}5nZDWId$0fV-}XkM(Oy@hiWg22Hs|lw;4b{I#ACo+EBK2Kceyb(1C#0J zcgSR??2@g+WAL5BVw5BdOcLt0tD{pq=Cq=z(h7>ly~A}gDp^PbXg@rG5qHGdkv<&N z8LecV_1Ml?bT#s^v#rsVVF~Ga7CNWbrX|lhqsc(PZuY? zAuYs@ySqdDjAq~XLPPuu@!2)EEB{W2xME4dy{h8B(ywYv6?KCrnKn0?W_)kH#7n_O zAe@$+->Ja*D)CtppiBPrI6K!pIorW|$FSPL@<1%lYFa()~n` zj{xctKkZYR7;b9WB#l#PzI*r?GU_fO#taDBqSB3YK+BJob-?dp)K;jXM~dfK6>$7jqAV8UcIzFk`g#UA9?Aa z>u(tu+Eb73sk^VKuWv+0Za}@?sq4m0*}NL3uK#wI;p#12l20^heH}E$?Lhe5ZA97-i1sl( z{o=ojoaz?_))oKt&DRgh`0rnT{ml^nbr;Xa9sgzdZ3AIodW!I4AsS5op)M$_5GqxO z4ZE_fb%%(#sg)3y^F&11(oknY{w77Nt{{)dR84H^77#&FoIAf%L{znbghh3I)97hc?Swl?L5R+B=!Vr_yF#91UYlz7zcQ?dj z4KZ0mOx6&SHN<3n1S~nkWNj-ZOFL25K^)V*R-;%O|EGg#*9^i5MsakF!MqTb9=4KR7A-Cz4~_d;Qh~s zlRy6QCj4se&9wPnyWc*V?CyU1DF5mGoA9fj>EySg$^T4#`T1b-NAutC@|&se%X?q# z?R~4h_>W!p5B~v;6n=p>|4qrb(iAsaPW%@~?JiN;-3IG_J$QKU;bFP{*S&i~{jWQDKC<|) zhtoqF|5fC-=IF2X$S?O!0zc=mU+$kO(O-q$aW~ocFZXYE2@+PgU+MGW$>~#dc|#=o zJd!EbhtJPX2z-$YVORDU!mfs}t4}TL%H92y5GWImgOEKYr-%DW!1MTW9|n%&s9v!Md5TE)j|h!wO1EzsQXNmEj`e|MuU`dyp8Aio+OYON z*k~DOvYYx{u7Ij&YZydJxEhE%ciO5^bAw8%o56ifv-}zcm05DkOw~%$hxJI^_)MVD zR@YLC?FKHyx1|UKdKE|lWJq=-+`XI0vF2vM*5&>e$!%uN!!TmkG--AldCxy@s(wG@ z>20ZS-nNHfiz9PQ5^1Q_MD9BlmLLiDzfgQO$tT~?afj2b802OfJ7sfJ1ni74g!4sL zcLeMRNQ`D$_&NHzywi35X?N9JgNPFx>NN+yc@Te3V{A13o-=}PD$~MWD|73ZPz}Rw zU~b*c$yTSimuIreo4882NO;;oHP#iq26Ob+EksZO`o z$}34K?sn-$0vbgg0d_{=dr%yS?>R>$MOUrB*y2%Uy*!s+f zThmqCN9yv573v#ffNw;jN1!4h3n9~Pm7+RV{aMjs1%?qZw~cztR^LBWdzw<_058m4 z8#^`_%t_G5bwxX)ric>NujW26!`(+w-TUh>o0kwc)-x=u(i~_R2RF5Z?!U$FAGGJ@ zkg_L~$LT~Q6P&e|h`?xowUSc`Q(rg-1Gc$QhFXfIAjHN&dM)D%5weBOM6q{ZpA{Bv%^r1gvIu$Rua&6(wkL3}i_HB~V>n73^ zGYZu-AS4B1A?A&hgA0SatyK1#pGa!FsO|F;N!mC+^|w2kpP%ppw?p5}0YW$6Li~`KIh%J&4iCjlNdCn!s$4 zl;+pPT<0!q8b>B~%Y3HSg77>i*t(ctMWGV>@5Xd^dvbbDHsx3B`Cm56GuWnyE`f^u zEG9w1sC8;bf`*eBjc6ROq${n<*cPDF?q7B!2^KsG6Ba|l8rmBo49{PQP?F;l2zu9H z@Zd0lFN_PRhP*+P$&@9>Cq7(S^F2?YT5c$qEX>WEifUY4P5;Fy2yThUC7IKx>P;^` zzLt(ygiI-P8(wkS>IYeKH7S{gmZ;Uwr0LYm7{_A{Juo=ltiY*gM&GqO$56suTuW=V z(_Zg{(O^Mm5yL*r!JK5VwDtd@n>_f!VIR$QWR|6Fo(ohdk6C&xlD9^9z$|;QP`)ag zWug_8@&_SPv`cN0kxmLNS8R(;u!?Kf;b3>Yrb&obQ1zO%G5cG!>u6Y?cO!6lC( zE?FSrP{I#JcZ2~l8;Pg|$n}Cp>O!=-F(-wk^h|_aH=!dEvr9x0(rF=#B18prN%(Tf zLQYc_-4HrgVqP5-WNvzyB{!>xRsNh5bk!@@g)KdW>WaOJsIv(Ccz}cyO@nzF%${VZq0G)Q^F+ zX{lg8!=F+C22x`)GB@?xpI^tRIlq7x!84BhQ6n%wQgcZjJh(rGSBX$Z?KSsP7CK3< z6N}Fi8q4kjuP1FwZP#8@D=)bjxmnjNU9B$_d3+;YNNt-&)EN0rf{NH z@tQJY2pb^cHO@}oB}sYkwlQ`CpPmZ=Ef$#^f078nBD+Hn-Dl0X4x^Uue}TPEOz#^y z=>j3%^1im^C-6}nZLqn1l<6~E^(gYaildIzt{wOf=jSKt(|Ro&#_rW9vC15xk3c3p zo(>Zz|9y0FEXR1VP#@#7dj5-E(K8sU&#BTc5`bWK=Fz3cQj@hb8Un$est3a3kOwq1 zLd)i%YDI=*ampiyc3VR4Y$tkf@oh-1W|^lW;UPuUbC^4Z=t1fF+XkFOq`CNyQ28&)!~ z&0>tCpdmq%qPotQehYpBPaW)3WN~;ZW;|}lG{8F^#hj_7Sa#mqJQ?_!@yo?V72}_v z#R8$Q6BqZwuxjp4fja^SMYpg_Ie647`fHa$?vQGKm9T(IHYOt0&^2s1W1(sp$H_vZ zJptl(@VDR5@G%5Q%bPf*jhKesk-^YPbCQVeX1lo}*hecJ)-2xhmRAx$Ne&EG^Ox3z zXr_wERiQa6$?xCW)+oqZZC+5Q*KEGBkjwcT{^cPN&WH-Yx}k^Lz)Q5*cP zn@7P3p&rIWkP5=3%nA$Ac*xzBC-pFDTlWXE$BF73MXKk9%mu(%XGbq@i4)Ij&^#Ij z^FsAqjIdEZ%Ti&243oTFzj4Qt2e-tf_f%ZEF;6>> z(GCF4RSO`N-`;wKO%xB%qEG4k`5C@7#$8qhtWM~Xsa;?MpgsiRb|m@ZIf;eQ!9u(d zUue7RMc${aWbwZBU08$@J@(#F2qN$gA`iL~m_2wV4r zN90gHqV)R`!{0oA`Y1Pu7;jTyF3Z&erH3Y#?bjf0t@StKe zN5Zz;+&^+$y6y@1O@e${nWZ*4Z9t@}dp;IKx(=zdF-*Ev;5l_pbRm?j0R^X;twV!z zx@*s40+_fBg28P`!gTrw%(K~q?hh|xwv@LpUGbMt6qJETy^~nN!GQ`hfcDF zBm6|8z-<&kz-_odu9MSO|L4DR|NQ3!KOy{k=`6qZa)~_l*1rpX-fRQ$qY|S;{ z%8y?TWuJ^5-wcC~Ew2=eD*x)KrC2N%w$xJ=(T(PRoR``z8B}Q)@z~bJW%`mJSt`dm z`Ci1Za6FYJd{0R^#uAxl;dP9Gr({9ZNhlx+X2Bo=BE2VG4zAR$oI zHh3bP6~bJm210PD^97N_oyks5*(zab<-$i*27!Zaoy^zzWJCP2;u+o$qPkXP7B(+7a*As$U&pn!e>a|U4+3zkjX9VmeDtDdNXHqT5B98?|C5Cq%l|n%eE9INlK*q>;gJ7x7tbe>{{#HCiTt0} zPuuc;UO#Qm|53w0Ay}LLlZ78F|L6776ZE%qW&fxbhwPtH%R~0hkp1&1XaBr@>XH3J z%byJSKg~=s!?7vPXy0_^Uo>u$s;lr;F z4E(gvB$OI<1F( z^*Q`(!|q_4XX!#oNJzQ^vTP_exP>xb;Ba6x{TWl;{%Ewk4UtY&12$O~vrAJ)OyD?_-D&xBH_Q`#5FTkWq(?%o9u4gPBOKa z{rqBkz2kblV|w-b4I@`74CS$!x7u|iNLZ-2gRT|K+a|5E`TYN9?_HPMxUogy{LWLL z#=CZuU7|?IvNMyZUG*ulJ=Tux=o6J>&Yv>@yFn7A?nV!Qmdu=-cRz)-fWEOWXkH|F zhNzl}%x<881z_DTOg7fN_rTV!a~WIbzio%Cwd4%!7ZC@h66hoUoni7k$6zk0cFIP3 zRM2zSMzrn+iMth!U&QpYoy$ywtJ$i_BG--BWBU09NBBX6s~=X4#$&(TAXsR&K3pxX z=rfNqi``fV)$b9k_0r@=JRz{4*0AiWd8GsU95CkCLp!_~`IvCH6^8Gx>`}=I0dibf zlvo%vLdp5*OLAlvMBXNv>lL{bf_$KI!M@FF)A!#02{}rHTYSrc=0e6)gUu%&jKjrJ6`@C0mx)$M#WnUJF^C&8nLN#05+ zWU-fh(e;nLr!3y-{ahcevZHz_nKH<%OWn>=6WfI|J%TKcqwjC1YxW5R4k#h z2*q67TOwJez+zw8CkQPS;B=632BOZq=R@1>2rOo(MBJN@xiuX#ulk}Dk8ar9qJ==j zsZg!%RrwAypHcrH^y;_a>eMXeA1exs&d4brm$W{Iw2j=+YSx{$=97ik%frFT6K#)v zXan}db4`7A{7x(WR)OtZ7>vsxTtR7akcSqv8k@Qn2$p%V4%9EQSJhwGEg`2dxq0*Ln;olufq$8E;#~M6rK>J zX%fy>XcB0llN)%@upw+jiBaG=ow5_fv}}?u7ED?;O!72sy;ZP|jZ|238bwCbe`C+n zvp5v*YLjvR%2TizQM+J2?S{9&#vKFTO&=)Fts+{ktgS$@Ko~*l2>4p+fW7PEVL!8a zRBFEMvckw$<^C5N<471Ku+u?`u)z)$LZ4!vEQ7ya%_&3!awVX9}Ji^>#KJVbF zf4c|*mg^El*u*#;Y?UM-UH05nnm6~H422_UR=(qp+Z4+Ckp^RWV4KGEaS)y-O z>2_+1w+-Vp#>oWu0?f}Qj*U}ljdQm5$aHsLvP=X|0udWv=bCaOSg)Pb{0JtCHU{=L znx>I8N{tsX4SoYLC3>JMmBVENF{l^Kcl(uEYxd9`xoYUv1^AB157~}7;9HG8J=?KQ zh{inGt!l1eysGk=C#bxRMV0{2K|Kc|uvN%`bt2A`uErNy)Z4EjKAoJM@0=LrCucKy zly|SHc;M(jEXFouiGAkicV(45c62FOU>L_Gz2`!bEYUn7RFjBNr7KukBzcOQU`dk& z260lCMAv%$4HesHro|hkS>R(wZ9P#J`6wk4Q_6rFF*8`LRSrbyxP?r+#ML${vNg@qWJNMX7c6)0#K~-8M(?;# zAzv`1H}w~KllLxNCmix$!(#~7a&Q?sxD0)PE<+X1pnAH#4kw_NCHT4q>AsZa|K>hF zOiCd)%OPQUUK^TFVqPE^1qa>M=O>ei!7g^l)O?61B;qV{aLwa7X%Gmz`=Xq4LK?0G z$nN{w+iNl{^c{P_&#-JW(ZPcDKQks*@!);{2#=Nm{DfyK zN4Z*!tG7!={txPi{x7+wlB0RBNSbK&L&y;CFHaPcdQGonh4fapAM{gKLw-2d~(HrUft~&G@O_KQ&>opI4h1T&Y%%meWWf&17 z5cGzmm&k8t__BZeIa0$O@X!!#GBmpOt~9k-lsQuQ0;Cp)+gVzMN44uz@~?|^2)ke- zpOER^Vp0Yf4$RB)-gc=*!GYi>=J|l6CmT9yIL%l!^-yK4mXFy)oc0 zh6Pxkx7`u*wcZpXbC;^#V1tEBgJUGinJucdxVgTp4x3l{)582cW4YsNyZq@|zW;_C z?*gJJZBk~GTP>%#t`@|%GNR$;AmGcgbUn-17-ROYXIRO-wR9ro^_XXSUQa)gLP>eR zk{~b~B5NZWtgi~kGwbpo0Q=h~McNeDslBaE32tF8_DpmTSojjfLzXkH_RwYtcIqf@k1fZIul7V5 zJ(#xju=sMT02(6V%Rn@J-P!ETyTg*KMGHt^^QRrs8NOk+sP9G3RQ;Zd?mS(?Qwrwd zu#mO&bRCvk(7S`*e4;rXSmyx;9$*iGaFrWw^4y@XW1zVGVk;YL2Rg6C^`$2qavpY> zmhicxB-~Rv!VOaq`bh9TDF_Gb>W)(nKCiTc&pqYf#_0xq4oXUudM}jjGP;mKhvm95 z;<{a?2-_>`D!5vY^ve_M4$E#=hF5iYfCpr@Eyz0Ml^&kZmml=x1qW=)uCg$0oq=&f zX3p{c?{dSO=V`rJ>sTnG#Y29r?eXhkL@Odle(gJssXfUZL)vK8ZFSmFrj}P;>bQX# z?ef5tXRB;Duio+pCdeuS;(no(aM%< zN8`5Sn$@C+`vfOA>y-#Ot_WWwLb}|YH|(BC#jYW>cb*Td;%7!}4lPEl(*Pf3X z@k?dFvheRa#x*D)lL*>cSaf;q-on@EWD^rN`X*s+?WH2y zTW2w3QsJ)FD&OmTJclkEE~ZIXxI(qKKDl;D6J+(B2^kz=hHS47=rs@STFmKW7{Fnq z>cPdI6ng6`zk<+Y^NJRZ%^knMFOS@px1>UW5O;it-t!VVG{FLg@`r@)6iqXr`YDMz zcC&G^?{9CfO}A!_*3P%nr0SYsoWSD`ohA@-j}#9XxwyVk$B6Z*BL740=@e$rhs*u# zx&$+cTr7GvYHj_!yaK_TA{XFQ6JkM4L?c-|Lvy5M5v+@F32^Ll%4L7%b<=)bTGv`+ zI2|W|A31IqbO=qXf8ci}MP`YV5Zs(Fy!5Ndm)`f7TYC+DGUCLp*@x!%i} zncA_dc)+YonO{>8@xW{2n$RJ;XOTe+C$adQM-e>{axrGf=;x_Hm1_Jen~lxQ9$N>4 z@s#NiLUHUSwo^c|AZx38TW)nfz^qj3c4Nfj$RrTnm}_mQr8&(hSr4roxvA===j$cjAx(2b1x!{Bf{XwAt&vt$z=5EFMnwr z4(y(_KAMX;f$S`ZUzbwk- zwI~B%>N+I0ZQWt*YBq^@p&@_jn=rQ)>*~*s#bTf zrlM+Gaz{$VL}-lbk%Yym2D@28C}dN>f!&wQElg>9Z0lZ+0RRdQp+DR&)_XO=w}5TS z><8T$;9Cqtlfo#~YLx&GA6w@wLv(1e!bn;34}&Em9>CvrlFtJ6H*CSSN-f{8GcaZ? zD8l@r1&OH+mhCrSgZ(HVk1Bozd1(OtQB-`%aDn*od_Mb%v?!C77v}%n{Ox4m1RIwdf* z4q*XwY&PimNHJC}^s&rlCxM8^3lY&|F}CxO(zZ6*AgPwo()`DojM)Sm4D@LTWE07Gz9WGiI>DfMrF zQsG~BY_%OMd4f1)ddJgWnB;R`UCY&4$3_iT@1-uSy&PEO4rZ_CU)Rm+k=C`$l(u4% zci8ebw`;wcqL*Q8a@1~6vGnF!Ab5Wty>pat^j|rr(TsF9PNuMsY49tXZ6aI#4ZD`) zN{F&}V6!a~WkF#tgZ%UHO6)XEKs7l&!>6qt;yr?26p4qQBwz4kJ6WMLj!k52*;n`i zc$x`(+;(O!sp0IEKdBnoEFE>ZF5*+n$Sg6{ZP+b z)xn}~%O2XH$1gB+(N4hrI`l+>`S22bG2vKU7Sa4ZVpUiFCM?`7{eULWRe&0jT%aBG zuCH)_(Ad_u!XM*XBm3IO3h|@&EgOOjtNcNrDd7oJ=!!tq{e=3Jwbf#9-)4}qeSIK> zuYSpZLR|cTE1zT>>#!=iw_x*D^)ll4=ZDR^f#j<*=zuitYL#gEnH=T99Y}Ow`AzQ@W01qswz_nW2HdxwQ!z*t*4nx2vf_(hI9B`E;jhvT zBkPM&sn@|{YZ;`)Dtl;KOu=v&&|ujnOKe|ggNETRRIa>bh>P<3jbf8|TsYUa+080R z=V%zRaBM557BLlF*SSq5G>56hKHW?CF(1Zzq1uvjR3TA%y&AfonKk`0qY>JhExKug zgv-JqV#*T?)q4C>Ka=7?G5L3;-tkC#orE83m+2I{G>MWl#OhanAN_qg9bMs4_sR(0>0ThL zYa<&{<3es&Dx_}rEbL!WF@n$HM)>;3yuas#-mX&iNvMR+TS8l!)>i7&eJIQMCP%0q zZbMl0qnX(8dsop$oKU=P1gp@MAmBF z%2kLc1OZBXHjH(ipbYuMTHw_aB=1*m(Ca&9$yOP`ugU{8oq?EZzHqkBEP0@b5uDh3 z4mtj;{jV&b9Fytv16HFo=U-T&2dCV+s&^Di_*rEjr)h@1C7RwbMIdL84T?AS;usu) zz#|*KBoY#dfJSDY@F9d&rBZ|$-Y67$I$VraA|nrASc~`_!~S6jHY~a4QY7#6yPh!H$l07#0=h^-!;7GzdmeoP_;Ir|MOKszJh`>s-2N159knRWbI zzGJ1QmWTJ}cU+1Bi2uY;IwOxekn0N9MEkYxk}*c4KES)C1z+W}9Qk zPXGS;$LqFBE=Vd3j@RVl)$K<@wWh(Hb<~{;xnN<%vb$kI={b{<$?Z4xrZQ4xSKXtX zZK=aBc5Cy@2*uZ!bYIcJR?~!0HcN=BA|Tu5S`KAerqd63-w2{Hg2|VWe&Gr|-$1z$);k&Pq+~(HSao zd%eLCb6qz*W^WTMSJ#3kI;WQqoFMZ9Xrtn{zC*VxPKBg$wZ&@J#@JM*d8}n?W$QOh zvl((kK3w(mcDmNBQ6bOsx8C4eEi1Pxyaz`vnx-r%rNo&+#gI`RiJ$8P?Iql>Ac2t! zSR|-VDUa#x)V|!f%+x-cM|4qMK|33;*L6)X;&`ios@tg@rJg`>l$WpBbOpd&+gRht zaT%N1igc}Jlx=NJ9hit%~`q> zkF!YAgo#Y8?@m_*hiVO@6mAC4eMsthe)bn~D+KvSlNGsfTY@?HB!d_f8c9aOm77$) zZ(w^C3kU)_no*m~qX-9woFkW#YbL?YZ)0s+X!-V5+1dxULL#-f7pRkJ668N~m3!(h zq{z~epPI6c5E$8Li}9kDIq9wv4k+fHNg6qjahpTP<-xXL#QRh86%SN zj+%H7hLqs$Dy9*WxvFnmxuiTLy^!Iz_Z5jzzJxCjHaUnJKiMC*z|-jtBgwC>^H}l% zLtb4M(c=xl8?#lO9!CqPt0rTfu(IEHcNWX7p_&5fh`7?@7d&-yZT+HOMwXDJgVLG5 zG4B)2qDYnD;Z9eX<$u?kFx%2v2qC9;%xyy?u)G*`)eFrhQ=zy=QiLO=sVuH2oOp8< zd$J?=CJJ#iQLnCtWa55X^eS>NRp6(Lbk(0Vy$0Sg02PZ2lMk*JTq<)KZB5;tF?A(@EmCj^*fLhf`4DH@k^?u*27R_bRf_vFR>2VaL@KJaCzP z>ZA|5qzeOC-ae}8X{UK?YWkRzw4aLhP|*EQ&rK+2K^r>;_NJOX6w`}ZZb&IN16Dhg z^q_;iG;lzk&UV_@L-!;z4=~HjWovOCU#m)WtO^;dmk7a&I~S5jHiy6ah+L5zVND=8 zpS&bT?}VK3Fl241fc)gc8=81ICr^vFYxQd?a=AHqM=nuMo072h{%mDc;g?r$Zp@ki z(><%-r!ibZ0(LPR9|L$J@v;Gz{HNMOY#%q?#7j6Z00i&%u{VIS(Lh zSi7NRTLfx8t|NsXH{TsB=$LQ!pWdrvE-U~nFfd(W(3IyPWSa7*?eK!j7Daz7@KqFR zNaQwBBi!7P+1(L*y~|qVp(a%-^DZND1us{V)-L7YeUohrHE6JwEB%UuJKK^XUAH5)>xau{?`m{pgHQJLuJwNsn!rmPD=05KXUcw|5f2SENNHEaC%=ky`UfZ~>c1|0zi(mq z))THw(Kbi2wM9*7lk-?9XeNV`K`tVwKBxJ8*TOzw)%b?hHH?FA?_jlFS9POnip-%W znkX-P%M~H8d>3Ou+r!n`K@V*0hHR~c-@hhbyVJ#eDU9t-7yS%5+nuiOnX|TgTPq@r z4OfhvTh`sP%x28>2&;dFoc&JM_sm)Q9j>*Px9@o&Wi937tDFD!BT-DNK5n5LlH8`8 zHdL%H7462!MAIl+@CM}N8{AYWBb!PF4&I|I0q7tX-?>Y~Lo$Mz@2aJstcU6wCRg>O zE_Bs6^?n_}dVp8UmrjmtSs*N&n~2iZcf_CHx--HR zp@GI=bmu~DCd}_Slvj2uo2|$-lU#%+WGZ076bG2GNIZ~J$^JQRjrcYPAz>_3rQ<;D zcqF270d9mefxPd5NcNVSZI(%|h|<=L{=p1T-{yv}6}Pj7d`SrrV5R5>Dra0vDtWXb zDyC6HQiO$=gU`O_-k7v4{4!T7CwO zdF^i6@|*{6V}I%~CzGMB??txVz1Hy<`k#+086uXW^a z=c`$Y2Uvm#`5ej|nz@)?mbBFn3K)+)5N#yJO(*YheK7~gHuu+NF=@EK3ZLxe2IpM5 zWy^8!aVn%OnFHx`_IY#d7yk_|tpTdfbPepwR~9zIl4x^yH@$MI>#Ao1%N=)?h}&lx|tC*be0Uo%OP)=$0cwWKFfel8R31jqr6WrTzDj zoo6`0neNR?*-qGed+_CI+=8`jfCW?zs`H*Ts)+~QYi&WtvA$P503o65i zDOC^$TeKJ>SNC&8wOkE0SZU4T)UTw9eYL`O$23_vxR>q~*4u13$1^++yiFI|rq91sG$gl>%4wZP8*jOVL9v4?H*Qnz*5+27aENsXXN)SDm#+NO|~*cZ8)9Sp;f)goxP)5E+nK z0dj~_y|QQt`~i@OFnzd2ljRt*;3h0!N>SN*CEuWN3lH>$lB_)@K0<;!Q58YK{iuaK z(RCKBW$vwv+mpoAmTvgQ;>EN!M%!KAg?Lfi_*{l~vJ3z8;zX|gY!^)77TOK)7b2eE zEH*xnHWIy<%80~F(~xRf`pIDbuUiMgOsOU6r?dcHC;a8BL;K>Iy`!T*hH7m7Z#3r- zQ~BL3uJb>N8?1v=ovdga`F&$DnM_`vpTmDAlS%!*-%Vb<`s(!jyUEM5)0dOUtFI`Ism2!AMBf;kimnL`l^FCw6PE$QB0gKaB4Tp1V9AN$s%IIGLMCBw_v!n|$?5Bp z)2|8Gp}!}!^H!Y1uML(mLxbtrAfNmR_O;)|Ie*NDxxK`aBN12n$Mt7<)zUP|B#r75 zK!nE=pdGb`UlXDNVX);V^ZAqpkk;HT4W=`)tGYj>QM#n3I9#w~F?Bduq%66(zWU|m zwDNNo=TKRIb0oaHc~g{HK|u+WhtBK5yjo1ZOt-e6>EfQrd(IvTGTuzSONXsOwYs?@ z0~YL6q2w08EVPi!`ESX<@4LMG#8R?4ot}bTM>zpB5Xn80nn)IiMZ$m2$5t-T&Ir?x zX$m4FBNSv zixHK14wIf*k{`5z1K(fqz9N-57io*duD0mL-Iky4&A2fg~?dn*0tAM)oKc_EWpVjq0 z=cg~v5Bi_SXwO*xvwq$-RRLKMGOxf^(*o5WuPK7oW>V7y)t^6^I;g&qK8;ZQ{W6Jz zU^ut5%7`U*fKq_m|CcL7oNGW<3$?p#db#NXfn?yYkjwZ+-sC|$CpC~;ks{MPS&UsY z`uIhC2mf(;P-D4vP-7j`SYMhNtB%-wG+AB9uuEtu*CL;?K(Z!Rx@wNF^&a`;C=ezy zBLz=@1#cD~)|1CUL2we^eweNcE3JZxhi7P$fD&>=XAygUdwYG>v)(tQS6x2^RXoOL zFypd>3;rwCce6=6#9dlnUzeYXEtAfZ#VwDS$a;6^-CBpr>Cx^-tT}?WvthDx7qjY+ zZq+BXVHMr7amZ<8C-f{_9^Vx6ajZt62eY1+SVZ&pY@+<#}I?Q zJ|uh&!LrsHTnhk!bMUh{k#={&C8MD^QO^m+H`O_H!5NA-M6H>~f+Y*?thz46KHCn(w1grm#*AAQ7p(Lo8IyC7bf|< zFFNLGtwX^BO{X6!$$#(7bMt58N$X;9V*1(94Ry_AbLxbusdv4HQ`J-n4v>+ff`okA z#6$|9F@`vemW>6RyUuCKm^4iB&o@^+lfEwAta=eM!zUPt*F33(v@a-68c);o;uE|d zX3`zKe4rs)(s;9^5c=}MQzW>lyxbrSTwXYVz%349A*gOl`NX36NbyC&!tOkcyA}%Y zsy8PjX%NuXGLTq?4-%2Mb(%9tF~Li#JTPcuRLbY`-U-4>mB~%7uim|TyPbmp4}Bcv zuimIeYnGjXd3>bl9aAJVWGrOu`C7%jjcvDmZ)K)5=5KyV@*ea$%kp_0jD`FAw%2 z*ADiggT3fWw-8vkQ>3wn_NF>K0lAB7)>FW^XVNv05q3;uG@8&fUERnFsRM zn&t@|ZTxm9u&O*xqqJ5<_#(knP~4^n2ACvl0VTGYG8i;M%4v=o)WZXHT%D$*M>>6j zOh={j)U1En$ZRwaYMA>NsOuXR(FWDuBY^InmBjxDLOmW(F-hE};IH=rq<@rdh&^aDfT9`z~EZa+*baDY0{W&UrVqQ=Xr zzcz~pt1D;>Jhoy#|dg&3C;{cek3A_#~p}QX;R-tu=sWbG5jK5**tWO6(n| ztcgc%vmVv;8Z?KiuUkOll-g}7?3U1|eIETTo%R|ahU>N4CY|@%EWc-qj(dH=o9elV zU-^PIefQc#cBu0v8|l4?PqKHfMDP7c-h1`nYv3883-6eJmzLaXeVZjS|94QOf01o~ z{$EE5(^?J5{qa@5{{QsVtGfRG?A7T(|NkiM8SDQ`=WSE1|LuqAPifBl7rOrZ_caZF z@zI)IKY#FK+WdUd-g!PgObPa|wc&ta6otN=D1nu|Y0NZ}d8Se;J2iMb4OE=NJ7XQG z@e3WPQ5mx2pejG8$`7jYFHcpTqahy!dH%AmTAW5{a_y9_n*`@ye7OFU4^Ww2u6@b1 z#57GKD<+f3z`msSbwxA{E?m+iR7-ltpgy3GA?BJ+C7Uy8z z<|6B@UU8Yf*q|=>Mv+uRJXqzB!q=NleWsTNJ+$e3dUT!nEN;z`Jk*?(4wb1}{7Nem z>QKyp=00sn!A=NEvX=rMEaNBtPaF`Ih~fR`k{tm1D>><6nb-ujKP+M(`wZz3t8iL27$P5$UHx-n3ao#Wi(u*BqGxMEML4Wp-(PH|!ktz3s zt%EH z9Ge*XlSmrKdj}L_o@@iDymzg{eDdreRUUE>#PA#=7k{}WGjiQBR%5v@XD40?$fHIp z{0X74NEQSnkcY(ON&>bP9u&mxn?|&E1$J$gfVtk#LlIL$4Z4349)QqsM{e_>Kl)w1Jb=|MB<2;$_7iK&}^9voyxbdCU zXn=Foj6v}bkwhz}=D;she6@iTIqALXqRkbF8FiR?B{CAAzHCYF8PN{{iyzwObbaK6 zgnSPCt1d|%xQPa`YBzf4vhTpCw7cY>e?I7+5BldXQvVE?%2WNkh6a68`3%V6g9oeT z-3N&5m@pbF-A_vqh0R(HO77TdTvn*0ltblu8s^Dk)cR6Lm#E)1Ut3m)mSGS(3^i*wHpB6=xBXBUK4K!4_j!KJMY=B$mtE%!S`&kzjiZ&`OyjAtm={nPx zXbCB1X#@MxEv3bT%ToXVS-6*uL6~0PHgm z8*GGV%bcAfEhxJN9jQY;0M~}-fACKi1naK_>eT<7PF}q_JFD0KI{)sV|9O=5ob^Ao z^R}@T2%k=IoVqTk@^D=vRGmXzFI0K@blRcH8hmv`_VttYfrKMSpvc#vjM_)!B2A+e zd0>381SZV(QbZ&q5;PpmXhf5sieX3OBbU-J0FutZIGT_OaItL|pKmKiOEoS9mjyB$ zzc43Zw6;R zdAVf4od=u!9^S?TnQl@z0%pxb2fVkR5k0i%EQsY!dC(?-^owV6VJOHA3%O)LTR7p` z^jiZo3D`0!L#`R2W&XsX%NeuNU|~6QvJ4Lr(5PK4MC#SjdjzTWI8}l>Y3NitC}!jYo|;n&12ag&&>E~sY@A{RiVn~93DT{SB)~@~oph)V z>ua&ESBWm*b}`Qfv)O?<76ZY)2mvRMR@P?m^j10omtmu0@7vS863>*c#4qhD8FcBc zTyBsul;;4GBv>^9%>PQgoV4q7H^{C_klrjsqoTH9o41d3yAwehhCea~~} zHhdHzYnZ2nxcN#Kz^~@EFQ`ryG7XMV&5|k9p)78$FRMf5Ia9R2R3yE@$=LF}HN3|* zkV|QkBeiSQ{IImqm74r~^8qXPJMCjDM9h0RV=4V}^Z3HL?vSomoe(tO_ia4%y1yoFHnvv?$20dEy;#yBeOh5l1 z!qt@j?qezJ%FyD5X*@K_JaBmt9KM{1a8+E!&ii&XFM4oAA}SY59+!K%Vht!AwiRp0 zPmyIsxgw*}V_Vk%ou{%S;xX4y3i|h!9ox1RvlC){LPk(vZ4TqIqZk=WGIttU77o`m z%rLwT`30--+aN-uVTMjciJlDTArE>*kEA6&BCCh2-7vSEN!-}F6cpQLGJF3F8rYD29;-b2PWc^MzZBoJMlV^u zcY!t&@YWK2dC49d)-T;->tV*Q`Lblyw}&4qj|;vJ*&myi1_0ZJdH`&F+5l|3)Cpko z-jr_rK*RJrwrx9I0k%if7+~|$8({N>Znq8r+eVs%-sNn8V|~`usat4Tm#2ndpX>5L zXni_|hNXFH9{S1ScC^uB-}-bBP0RDsNc1i)Fi2r1dWrIyefG3hM}h52BaY8fgMrOQ zkAZCq;_Af^wre)9?MT0YtzFB3ty|aO-to|QVDma#eVp)+Q@562wAYE6jO`YH>WuE;l@g^$(&_`@=Ebu!ETCd>4QNcPek_iP* z_Th)!oe&%^&s}_sQRh%w-{F&zpB9r%N$87Kj+_7R!#9cqOCE)iB{nU+k?w6QVJbpJ zuC5_>K1WDHoFVjZ?r9A`4WdkGCa-HEK5s5!Bk~kj*SklRG4uTpES4{&%rFQ4Vd9`X`_0ioBnC6MmTw0ci>3TY8$e&VQc^})`Cl~he z*#7*rH*Y-%)O9fxWK;0u8+y~b5KMOJF!kgnOa_Xs!j*nCdz|Xj+9f@LR!a| zM-jK>gy09q<-+7x?pAHl;=__hMnFqfMbT;t-2E}4cq7W(Q4ZCMjv1=(luL`GfRjyP|t>ZMKv01bG z{ja^BH-fIpf@R*tuqhJKG8wi40UXul5@tx>)pX+Zr4^cnyN?Nf!%qQbU^^1W-*D&(H*ISqxj&t^grnpHnXT z#7))lmZB6S}xmfnDb%*uW zr|4xNAfPUo@}^uIJ+t&YMN>O|6;qfMD)TEQhW6XYCdA3^S!7VhNi2TnQAAIKT#Q*V z`gv-Qsv7^wW@B^j$JXU!JY{->@Ep6T?Hr^~EN(DBr_ikfIT^&`1t>>ifo#WI8_68% zNYR9_B#^5Va%^EhFiuW?vazc4k`va?+QS_V(4@kJT{uzFo)Jp z&K=3Zz5?7ipt@3C>Uwyik9XFQ`3!1PQ^^9Z*fEs*gv=W(o-xP~g|lQKLYx4|JI}EX zqVGzgM2L%%Z+X~zn!7WZw38OU&3g>f+rEr$J*T|K(6$#7+vZ^ET}+oj&3CVNWkh=p z=CeH*&NeWa_0hLJGnwbk?a(y#e2ikx*&Mc!A*{EiuZQu=??61M!D~}fS1)*4HDw*< z9UsGvhe^j1?7J}IY-PaNz;xqlwAsd7(_vlN#8A^|3h+qL;Aemtkf7nY8C@R7-120G zmVKI7JdG>cl@9JUrT87ZM>L=8*KpEX2Fk}+;t8{T8c6nP8rjY$(g)%WLx?9}cVzr{ z6thP^h3GSN?8V68XWsBLYz#GNScaoV1GigahOh3=$AB?R>AYv7#a_)7yE0Vxnkf2> z6FV|Xcxuo6OcBG*!%oZ(PhxoR1)7JkVYrzA2vQGJ1{fFy7!UkVho|neok#0568I9v z{TK#zXAVM}-|8At&l}Eo(#ouxM9_*xgGBM_JFGII!LE9ERK>o_B zz*_-msWNYQ))gw3GWq zA5wDU?U0fK+94%}o53L^#~~%hAtlFJJEY`TYloB^hm;&UUe_Td#~~$0NBh!<;~^!- zAtlElCC4Ep$99W6q~tiHp%!Q+N$}NKA1^Owrg5 zi7B2WF~!b9jvT_Nv$jUGWeJ@{?S<<$WNA|=?m1xPl2$5^p=EK+tkj4m;i#nlZade9 zkfcLM(jg@25R#O)LrBsgBx&u1)`yJ`*2(*b#7xtWYFhfq@HAhy4g_pqSTe6DEhJqq z`^#5fRI_B<5NSiSl@>Ao9ZBGd#?el`F_}yzug}lnzmv(N{@=5gXRp6HJ^ya<^6d2G zWb*2($?2=}v-7XWWG7$mX_?Ygel^+pTlK|#A#F4oeGP74V3zG`aj5`+W z1bL*ByFV+#0^Xm_n5L&+JEb&mL@!8?$%u>uSy0U$=xU@iO+qTe5l@t+Q8c=xQaJ|fCCxM8|+@sUuHA&zY-_>59GJ3w+B!m&XjlOlv{pnNEahY(r8EzBhEsp=^>ql zynBzQWzZ@jI_UjbmV{9YoSZmP>cNwRWJ(#?WV22>NH^-2h5r3w9)=NnpwfSeMVBEH zw91Rz@UwBpAs^L|62Pkr>0!vJKQ!#0d0-xNdupuu<+KX@*Gy?OHh=!Z{JAR*ppX8) zo_trQ|F6%_4)p&qn#zonMlNsOsIN7P)5u8L-{tSg zCnKdl&5L!XgS8*bOSd1UKLKVpe@zX>{-dhs{q{flxAT2AYuwUhHrrx5|NI2IS!Gss zx1$%p8(t!Bc?}wlKQ6AX@MrVa55N& k;|wH!lQhxa{>On~IkZDNw8wA%F8~1l|CH8bDFCz%08$ae_W%F@ diff --git a/traefik/values.schema.json b/traefik/values.schema.json index 22878a9f5..aa76667a7 100644 --- a/traefik/values.schema.json +++ b/traefik/values.schema.json @@ -1672,20 +1672,6 @@ }, "type": "object" }, - "traefik-crds": { - "properties": { - "gateway_api": { - "type": "string" - }, - "hub": { - "type": "string" - }, - "traefik": { - "type": "boolean" - } - }, - "type": "object" - }, "updateStrategy": { "additionalProperties": false, "properties": { diff --git a/traefik/values.yaml b/traefik/values.yaml index 510526271..cc00e97da 100644 --- a/traefik/values.yaml +++ b/traefik/values.yaml @@ -966,10 +966,10 @@ hub: # Enable export of errors logs to the platform. Default: true. sendlogs: # @schema type:[boolean, null] -traefik-crds: - # -- Set all the following to false if you want to manage CRDs your-self - traefik: true - hub: | - {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} - gateway_api: | - {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} +#traefik-crds: +# # -- Set all the following to false if you want to manage CRDs your-self +# traefik: true +# hub: | +# {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} +# gateway_api: | +# {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} From fd01dc00c6c5a729026cda24d27ed201f1578923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 18 Oct 2024 08:11:57 +0200 Subject: [PATCH 10/32] fix: apply suggestions from @mloiseleur's code review Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bcd422a12..5642e73b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,14 +6,14 @@ on: - master env: - traefik_tag_prefix: traefik_v - traefik-crds_tag_prefix: traefik-crds_v + tag_prefix: v + crds_tag_prefix: crds_v jobs: test: uses: "traefik/traefik-helm-chart/.github/workflows/test.yml@master" - release-traefik: + traefik: needs: test runs-on: ubuntu-latest steps: @@ -100,7 +100,7 @@ jobs: registry_password: ${{ secrets.GHCR_TOKEN }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - release-traefik-crds: + traefik-crds: needs: test runs-on: ubuntu-latest steps: From 412fa8c885e2bca7f377fb9b913ab1fb31474f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 18 Oct 2024 09:46:05 +0200 Subject: [PATCH 11/32] fix: tag exist condition --- .github/workflows/release.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5642e73b8..f029351c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,9 +48,9 @@ jobs: - name: Check if tag exists id: tag_exists run: | - TAG_EXISTS=true - if ! [ $(git tag -l "${{ env.traefik_tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then - TAG_EXISTS=false + TAG_EXISTS=false + if git tag -l | grep "${{ env.tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}" > /dev/null ; then + TAG_EXISTS=true fi echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT @@ -60,7 +60,7 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} custom_tag: ${{ steps.chart_version.outputs.CHART_VERSION }} - tag_prefix: ${{ env.traefik_tag_prefix }} + tag_prefix: ${{ env.tag_prefix }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - name: Create release @@ -128,9 +128,9 @@ jobs: - name: Check if tag exists id: tag_exists run: | - TAG_EXISTS=true - if ! [ $(git tag -l "${{ env.traefik-crds_tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then - TAG_EXISTS=false + TAG_EXISTS=false + if git tag -l | grep "${{ env.crds_tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}" > /dev/null ; then + TAG_EXISTS=true fi echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT @@ -140,7 +140,7 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} custom_tag: ${{ steps.chart_version.outputs.CHART_VERSION }} - tag_prefix: ${{ env.traefik-crds_tag_prefix }} + tag_prefix: ${{ env.crds_tag_prefix }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - name: Create release From 31eafa9bcc662818be75ceb733b880f38f7466ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 18 Oct 2024 09:59:25 +0200 Subject: [PATCH 12/32] fix: charts_dir --- .github/workflows/release.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f029351c5..a9156fef8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -73,6 +73,12 @@ jobs: artifacts: "traefik.yaml" if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + # avoid helm-gh-pages to push both charts + - name: Delete traefik-crds chart + run: | + rm -rf traefik-crds + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Publish Helm chart uses: stefanprodan/helm-gh-pages@master with: @@ -152,6 +158,12 @@ jobs: prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + # avoid helm-gh-pages to push both charts + - name: Delete traefik chart + run: | + rm -rf traefik + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Publish Helm chart uses: stefanprodan/helm-gh-pages@master with: From fb5215c8b41f391c5f0997573ffcebf07d49b55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 18 Oct 2024 12:05:32 +0200 Subject: [PATCH 13/32] fix: changelog --- hack/changelog.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hack/changelog.sh b/hack/changelog.sh index a5e951a1d..5711a42d6 100755 --- a/hack/changelog.sh +++ b/hack/changelog.sh @@ -1,9 +1,9 @@ #!/bin/bash -chart="./traefik" - -version="$(awk '/^version:/ { print $2} ' ${chart}/Chart.yaml)" -changelog="$(sed -e "1,/^## ${version}/d" -e "/^###/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" -sed -i -e '/^ artifacthub.io\/changes: |/,$d' ${chart}/Chart.yaml -echo " artifacthub.io/changes: |" >> ${chart}/Chart.yaml -echo "${changelog}" >> ${chart}/Chart.yaml +for chart in "./traefik" "./traefik-crds"; do + version="$(awk '/^version:/ { print $2} ' ${chart}/Chart.yaml)" + changelog="$(sed -e "1,/^## ${version}/d" -e "/^###/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" + sed -i -e '/^ artifacthub.io\/changes: |/,$d' ${chart}/Chart.yaml + echo " artifacthub.io/changes: |" >>${chart}/Chart.yaml + echo "${changelog}" >>${chart}/Chart.yaml +done From f8dce184398923e1c664940cf3e9cc9f552db380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 21 Oct 2024 09:16:24 +0200 Subject: [PATCH 14/32] fix: get chart version --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9156fef8..bdb7f48cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: - name: Get chart version id: chart_version run: | - echo "CHART_VERSION=$(cat traefik/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}')" >> $GITHUB_OUTPUT + echo "CHART_VERSION=$(cat traefik/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}' | head -n 1)" >> $GITHUB_OUTPUT - name: Check if tag exists id: tag_exists @@ -129,7 +129,7 @@ jobs: - name: Get chart version id: chart_version run: | - echo "CHART_VERSION=$(cat traefik-crds/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}')" >> $GITHUB_OUTPUT + echo "CHART_VERSION=$(cat traefik-crds/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}' | head -n 1)" >> $GITHUB_OUTPUT - name: Check if tag exists id: tag_exists From 5f39c43cc9ebe01e9aa02ecfc6ce86513165b72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 21 Oct 2024 16:12:02 +0200 Subject: [PATCH 15/32] fix: reduce changelog on patches --- hack/changelog.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/changelog.sh b/hack/changelog.sh index 5711a42d6..f261f73ff 100755 --- a/hack/changelog.sh +++ b/hack/changelog.sh @@ -2,7 +2,7 @@ for chart in "./traefik" "./traefik-crds"; do version="$(awk '/^version:/ { print $2} ' ${chart}/Chart.yaml)" - changelog="$(sed -e "1,/^## ${version}/d" -e "/^###/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" + changelog="$(sed -e "1,/^## ${version}/d" -e "/^##/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" sed -i -e '/^ artifacthub.io\/changes: |/,$d' ${chart}/Chart.yaml echo " artifacthub.io/changes: |" >>${chart}/Chart.yaml echo "${changelog}" >>${chart}/Chart.yaml From a5b407a56e2be6917ea7b9efcb364c7f0452a62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 21 Oct 2024 16:26:55 +0200 Subject: [PATCH 16/32] fix: ci workflow to handle two different releases --- .github/workflows/changelog.json | 53 ++++++++++++++++++++++++++++++ .github/workflows/release.yml | 56 ++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/changelog.json diff --git a/.github/workflows/changelog.json b/.github/workflows/changelog.json new file mode 100644 index 000000000..24ce6011e --- /dev/null +++ b/.github/workflows/changelog.json @@ -0,0 +1,53 @@ +{ + "template": "## [#{{TO_TAG}}](#{{RELEASE_DIFF}}) (${DATE})\n#{{CHANGELOG}}", + "categories": [ + { + "title": "## :boom: Breaking changes", + "rules": [ + { + "pattern": ".*\\((${REGEXP}).*\\)!:.*", + "on_property": "title", + "flags": "gu" + } + ] + }, + { + "title": "## :rocket: Features", + "rules": [ + { + "pattern": "feat\\((${REGEXP}).*\\):.*", + "on_property": "title", + "flags": "gu" + } + ] + }, + { + "title": "## :bug: Bug fixes", + "rules": [ + { + "pattern": "fix\\((${REGEXP}).*\\):.*", + "on_property": "title", + "flags": "gu" + } + ] + }, + { + "title": "## :package: Other", + "rules": [ + { + "pattern": "(chore|release)\\((${REGEXP}).*\\):.*", + "on_property": "title", + "flags": "gu" + } + ] + } + ], + "pr_template": "- ${{TITLE}} ##{{NUMBER}} by @#{{AUTHOR}}", + "empty_template": "- no changes", + "transformers": [ + { + "pattern": "[\\-\\*] (\\[(...|TEST|CI|SKIP)\\])( )?(.+?)\n(.+?[\\-\\*] )(.+)", + "target": "- $4\n - $6" + } + ] +} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bdb7f48cc..0e99514e6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,6 +54,13 @@ jobs: fi echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT + - name: Get Previous tag + id: previous_tag + uses: "WyriHaximus/github-action-get-previous-tag@v1" + with: + prefix: v + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Tag release id: tag_version uses: mathieudutour/github-tag-action@v6.2 @@ -63,12 +70,30 @@ jobs: tag_prefix: ${{ env.tag_prefix }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Render changelog configuration + env: + REGEXP: "?!crds" + run: | + export DATE=$(date +%F); cat .github/workflows/changelog.json | envsubst > /tmp/changelog.json; cat /tmp/changelog.json + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + - name: Build Changelog + id: changelog + uses: mikepenz/release-changelog-builder-action@v5 + with: + fromTag: ${{ steps.previous_tag.outputs.tag }} + toTag: ${{ steps.tag_version.outputs.new_tag }} + configuration: "/tmp/changelog.json" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Create release uses: ncipollo/release-action@v1 with: tag: ${{ steps.tag_version.outputs.new_tag }} name: ${{ steps.tag_version.outputs.new_tag }} - body: ${{ steps.tag_version.outputs.changelog }} + body: ${{ steps.changelog.outputs.changelog }} prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} artifacts: "traefik.yaml" if: steps.tag_exists.outputs.TAG_EXISTS == 'false' @@ -140,6 +165,13 @@ jobs: fi echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT + - name: Get Previous tag + id: previous_tag + uses: "WyriHaximus/github-action-get-previous-tag@v1" + with: + prefix: crds_v + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Tag release id: tag_version uses: mathieudutour/github-tag-action@v6.2 @@ -149,18 +181,36 @@ jobs: tag_prefix: ${{ env.crds_tag_prefix }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Render changelog configuration + env: + REGEXP: "?!crds" + run: | + export DATE=$(date +%F); cat .github/workflows/changelog.json | envsubst > /tmp/changelog.json; cat /tmp/changelog.json + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + + - name: Build Changelog + id: changelog + uses: mikepenz/release-changelog-builder-action@v5 + with: + fromTag: ${{ steps.previous_tag.outputs.tag }} + toTag: ${{ steps.tag_version.outputs.new_tag }} + configuration: "/tmp/changelog.json" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: steps.tag_exists.outputs.TAG_EXISTS == 'false' + - name: Create release uses: ncipollo/release-action@v1 with: tag: ${{ steps.tag_version.outputs.new_tag }} name: ${{ steps.tag_version.outputs.new_tag }} - body: ${{ steps.tag_version.outputs.changelog }} + body: ${{ steps.changelog.outputs.changelog }} prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' # avoid helm-gh-pages to push both charts - name: Delete traefik chart - run: | + run: | rm -rf traefik if: steps.tag_exists.outputs.TAG_EXISTS == 'false' From d0c2fc107e902d2b57f2ed3090f6de137554be7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 21 Oct 2024 16:28:24 +0200 Subject: [PATCH 17/32] fix: Chart.yaml --- traefik-crds/Chart.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/traefik-crds/Chart.yaml b/traefik-crds/Chart.yaml index ac4dc30f9..1119f044d 100644 --- a/traefik-crds/Chart.yaml +++ b/traefik-crds/Chart.yaml @@ -21,3 +21,4 @@ maintainers: email: remi.buisson@traefik.io - name: jnoordsij icon: https://raw.githubusercontent.com/traefik/traefik/v2.3/docs/content/assets/img/traefik.logo.png +annotations: {} From 0ac444ecf345c02f629f7f3114e132bed76e4d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 21 Oct 2024 17:09:22 +0200 Subject: [PATCH 18/32] fix: more reliable changelog.sh --- hack/changelog.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hack/changelog.sh b/hack/changelog.sh index f261f73ff..f15d96a16 100755 --- a/hack/changelog.sh +++ b/hack/changelog.sh @@ -1,8 +1,13 @@ #!/bin/bash for chart in "./traefik" "./traefik-crds"; do - version="$(awk '/^version:/ { print $2} ' ${chart}/Chart.yaml)" + version=$(yq -r '.version' <"${chart}/Chart.yaml") changelog="$(sed -e "1,/^## ${version}/d" -e "/^##/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" + + echo "${version}" + echo "${changelog}" + + sed -i -r 's/^annotations: \{\}/annotations:/g' ${chart}/Chart.yaml sed -i -e '/^ artifacthub.io\/changes: |/,$d' ${chart}/Chart.yaml echo " artifacthub.io/changes: |" >>${chart}/Chart.yaml echo "${changelog}" >>${chart}/Chart.yaml From 4a36ec0e3cc2919afa4fa4c514359a4f2dd40122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Wed, 23 Oct 2024 07:45:20 +0200 Subject: [PATCH 19/32] fix: apply suggestions from @mloiseleur's code review Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com> --- .github/workflows/changelog.json | 4 ++-- .github/workflows/release.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/changelog.json b/.github/workflows/changelog.json index 24ce6011e..adf70f36f 100644 --- a/.github/workflows/changelog.json +++ b/.github/workflows/changelog.json @@ -2,7 +2,7 @@ "template": "## [#{{TO_TAG}}](#{{RELEASE_DIFF}}) (${DATE})\n#{{CHANGELOG}}", "categories": [ { - "title": "## :boom: Breaking changes", + "title": "## :boom: BREAKING CHANGES", "rules": [ { "pattern": ".*\\((${REGEXP}).*\\)!:.*", @@ -32,7 +32,7 @@ ] }, { - "title": "## :package: Other", + "title": "## :package: Others", "rules": [ { "pattern": "(chore|release)\\((${REGEXP}).*\\):.*", diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e99514e6..296208e2f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,7 +98,7 @@ jobs: artifacts: "traefik.yaml" if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - # avoid helm-gh-pages to push both charts + # avoid to push both charts - name: Delete traefik-crds chart run: | rm -rf traefik-crds @@ -208,7 +208,7 @@ jobs: prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} if: steps.tag_exists.outputs.TAG_EXISTS == 'false' - # avoid helm-gh-pages to push both charts + # avoid to push both charts - name: Delete traefik chart run: | rm -rf traefik From 958b1e32af2f88d31e4df153197ddb73ba145ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Tue, 29 Oct 2024 14:41:51 +0100 Subject: [PATCH 20/32] fix: preserve CRDs by default --- traefik-crds/VALUES.md | 1 + traefik-crds/templates/_helpers.tpl | 20 ++++++++++++++++++++ traefik-crds/templates/crds.yaml | 13 +++---------- traefik-crds/tests/crds_test.yaml | 27 +++++++++++++++++++++++++++ traefik-crds/values.schema.json | 5 +++++ traefik-crds/values.yaml | 1 + 6 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 traefik-crds/templates/_helpers.tpl diff --git a/traefik-crds/VALUES.md b/traefik-crds/VALUES.md index bdeae3953..a736566bc 100644 --- a/traefik-crds/VALUES.md +++ b/traefik-crds/VALUES.md @@ -28,6 +28,7 @@ Kubernetes: `>=1.22.0-0` | Key | Type | Default | Description | |-----|------|---------|-------------| +| deleteOnUninstall | bool | `false` | | | gateway_api | bool | `false` | | | hub | bool | `false` | | | traefik | bool | `false` | | diff --git a/traefik-crds/templates/_helpers.tpl b/traefik-crds/templates/_helpers.tpl new file mode 100644 index 000000000..b1da60202 --- /dev/null +++ b/traefik-crds/templates/_helpers.tpl @@ -0,0 +1,20 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Render CRDs file. +*/}} +{{- define "traefik-crds.render-crds" -}} + {{- $scope := .scope -}} + {{- range $path, $bytes := $scope.Files.Glob .path }} + {{- range $doc := regexSplit "\n---\n" ($scope.Files.Get $path) -1 }} + {{- $crd := $doc | fromYaml -}} + {{ with $crd }} + {{- if not $scope.Values.deleteOnUninstall -}} + {{- $_ := set $crd.metadata.annotations "helm.sh/resource-policy" "keep" -}} + {{- end }} +--- +{{ $crd | toYaml }} + {{- end }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/traefik-crds/templates/crds.yaml b/traefik-crds/templates/crds.yaml index a2c4de9d4..b7c283a19 100644 --- a/traefik-crds/templates/crds.yaml +++ b/traefik-crds/templates/crds.yaml @@ -1,18 +1,11 @@ {{- if .Values.traefik -}} -{{- range $path, $bytes := .Files.Glob "crds-files/traefik/*.yaml" }} -{{ $.Files.Get $path }} +{{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/traefik/*.yaml") }} {{- end }} -{{- end }} - {{- if .Values.hub -}} -{{- range $path, $bytes := .Files.Glob "crds-files/hub/*.yaml" }} -{{ $.Files.Get $path }} -{{- end }} +{{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/hub/*.yaml") }} {{- end }} {{- if .Values.gateway_api -}} -{{- range $path, $bytes := .Files.Glob "crds-files/gateway_api/*.yaml" }} -{{ $.Files.Get $path }} -{{- end }} +{{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/gateway_api/*.yaml") }} {{- end }} diff --git a/traefik-crds/tests/crds_test.yaml b/traefik-crds/tests/crds_test.yaml index deeef0b22..8e6d12ddf 100644 --- a/traefik-crds/tests/crds_test.yaml +++ b/traefik-crds/tests/crds_test.yaml @@ -21,6 +21,9 @@ tests: - matchRegex: path: spec.names.kind pattern: ^(IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|ServersTransport|ServersTransportTCP|TLSOption|TLSStore|TraefikService)$ + - equal: + path: metadata.annotations["helm.sh/resource-policy"] + value: keep - it: should have all Traefik Hub crds set: @@ -36,6 +39,9 @@ tests: - matchRegex: path: spec.names.kind pattern: ^(AccessControlPolicy|APIAccess|APIBundle|APIPlan|APIPortal|APIRateLimit|API|APIVersion)$ + - equal: + path: metadata.annotations["helm.sh/resource-policy"] + value: keep - it: should have all Gateway API crds set: @@ -51,3 +57,24 @@ tests: - matchRegex: path: spec.names.kind pattern: ^(GatewayClass|Gateway|GRPCRoute|HTTPRoute|ReferenceGrant)$ + - equal: + path: metadata.annotations["helm.sh/resource-policy"] + value: keep + + - it: should have all Gateway API crds without helm keep resource policy + set: + gateway_api: true + deleteOnUninstall: true + asserts: + - hasDocuments: + count: 5 + - isKind: + of: CustomResourceDefinition + - equal: + path: spec.group + value: gateway.networking.k8s.io + - matchRegex: + path: spec.names.kind + pattern: ^(GatewayClass|Gateway|GRPCRoute|HTTPRoute|ReferenceGrant)$ + - notExists: + path: metadata.annotations["helm.sh/resource-policy"] diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index 82c5776c2..fbc7b04ac 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -4,6 +4,11 @@ "additionalProperties": false, "description": "The Cloud Native Application Proxy", "properties": { + "deleteOnUninstall": { + "type": [ + "boolean" + ] + }, "gateway_api": { "default": false, "type": [ diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index 4cbd7a28f..7e62df857 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,3 +1,4 @@ traefik: false # @schema type:[boolean] gateway_api: false # @schema type:[boolean, string]; default: false hub: false # @schema type:[boolean, string]; default: false +deleteOnUninstall: false # @schema type:[boolean] From 09c242089ac54e747751caef68212a230f7e1330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Wed, 30 Oct 2024 07:55:10 +0100 Subject: [PATCH 21/32] fix: add some annotations on CRDs --- traefik-crds/templates/_helpers.tpl | 2 ++ traefik-crds/values.schema.json | 14 ++++++++++---- traefik-crds/values.yaml | 5 +++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/traefik-crds/templates/_helpers.tpl b/traefik-crds/templates/_helpers.tpl index b1da60202..e43c7aa39 100644 --- a/traefik-crds/templates/_helpers.tpl +++ b/traefik-crds/templates/_helpers.tpl @@ -9,6 +9,8 @@ Render CRDs file. {{- range $doc := regexSplit "\n---\n" ($scope.Files.Get $path) -1 }} {{- $crd := $doc | fromYaml -}} {{ with $crd }} + {{- set $crd.metadata.annotations "app.kubernetes.io/managed-by" "Helm" -}} + {{- set $crd.metadata.annotations "meta.helm.sh/release-name" .Release.Name -}} {{- if not $scope.Values.deleteOnUninstall -}} {{- $_ := set $crd.metadata.annotations "helm.sh/resource-policy" "keep" -}} {{- end }} diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index fbc7b04ac..79a08cfe7 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -12,15 +12,21 @@ "gateway_api": { "default": false, "type": [ - "boolean", - "string" + "string", + "boolean" + ] + }, + "global": { + "additionalProperties": true, + "type": [ + "object" ] }, "hub": { "default": false, "type": [ - "boolean", - "string" + "string", + "boolean" ] }, "traefik": { diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index 7e62df857..a31b3f309 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,4 +1,5 @@ +global: # @schema type:[object]; additionalProperties: true traefik: false # @schema type:[boolean] -gateway_api: false # @schema type:[boolean, string]; default: false -hub: false # @schema type:[boolean, string]; default: false +gateway_api: false # @schema type:[string, boolean]; default: false +hub: false # @schema type:[string, boolean]; default: false deleteOnUninstall: false # @schema type:[boolean] From dc9036416cd644df6c2c0d7c0ceb61fe5e539c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Wed, 30 Oct 2024 10:45:08 +0100 Subject: [PATCH 22/32] fix: schemas and helper --- traefik-crds/templates/_helpers.tpl | 20 ++++++++++++++++---- traefik-crds/templates/crds.yaml | 4 ++-- traefik-crds/values.schema.json | 3 ++- traefik-crds/values.yaml | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/traefik-crds/templates/_helpers.tpl b/traefik-crds/templates/_helpers.tpl index e43c7aa39..6342768ef 100644 --- a/traefik-crds/templates/_helpers.tpl +++ b/traefik-crds/templates/_helpers.tpl @@ -9,13 +9,25 @@ Render CRDs file. {{- range $doc := regexSplit "\n---\n" ($scope.Files.Get $path) -1 }} {{- $crd := $doc | fromYaml -}} {{ with $crd }} - {{- set $crd.metadata.annotations "app.kubernetes.io/managed-by" "Helm" -}} - {{- set $crd.metadata.annotations "meta.helm.sh/release-name" .Release.Name -}} + {{- $labelsAndAnnotations := + (dict "metadata" (dict + "annotations" (dict + "app.kubernetes.io/managed-by" "Helm" + "meta.helm.sh/release-name" $scope.Release.Name + "meta.helm.sh/release-namespace" $scope.Release.Namespace + ) + "labels" (dict + "app.kubernetes.io/managed-by" "Helm" + ) + )) + -}} {{- if not $scope.Values.deleteOnUninstall -}} - {{- $_ := set $crd.metadata.annotations "helm.sh/resource-policy" "keep" -}} + {{- $_ := set $labelsAndAnnotations.metadata.annotations "helm.sh/resource-policy" "keep" -}} {{- end }} + {{- $newCrd := merge $crd $labelsAndAnnotations }} --- -{{ $crd | toYaml }} +# source: {{ $path }} +{{ $newCrd | toYaml }} {{- end }} {{- end }} {{- end }} diff --git a/traefik-crds/templates/crds.yaml b/traefik-crds/templates/crds.yaml index b7c283a19..9440dd591 100644 --- a/traefik-crds/templates/crds.yaml +++ b/traefik-crds/templates/crds.yaml @@ -2,10 +2,10 @@ {{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/traefik/*.yaml") }} {{- end }} -{{- if .Values.hub -}} +{{- if eq (.Values.hub | toString) "true" -}} {{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/hub/*.yaml") }} {{- end }} -{{- if .Values.gateway_api -}} +{{- if eq (.Values.gateway_api | toString) "true" -}} {{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/gateway_api/*.yaml") }} {{- end }} diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index 79a08cfe7..7189c84bb 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -19,7 +19,8 @@ "global": { "additionalProperties": true, "type": [ - "object" + "object", + "null" ] }, "hub": { diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index a31b3f309..bd3a42a72 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,4 +1,4 @@ -global: # @schema type:[object]; additionalProperties: true +global: # @schema type:[object, null]; additionalProperties: true traefik: false # @schema type:[boolean] gateway_api: false # @schema type:[string, boolean]; default: false hub: false # @schema type:[string, boolean]; default: false From ff1c67657c31ce5c073065293af9a12bda058574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 4 Nov 2024 08:18:12 +0100 Subject: [PATCH 23/32] fix: doc --- README.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 34c898ef5..686e50bbf 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,6 @@ helm install -f myvalues.yaml traefik traefik/traefik One can check what has changed in the [Changelog](./traefik/Changelog.md). -:information_source: With Helm v3, CRDs created by this chart can not be updated, cf. the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). - :warning: Please read carefully release notes of this chart before upgrading CRDs. ```bash @@ -90,13 +88,42 @@ One can check what has changed in the [Changelog](./traefik/Changelog.md). helm repo update # See current Chart & Traefik version helm search repo traefik/traefik +# Upgrade Traefik +helm upgrade traefik traefik/traefik +``` + +If you opt-out CRDs management system, you can still apply it manually: + +```bash # Update CRDs (Traefik Proxy v3 CRDs) kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik-crds/ +``` + +New major version indicates that there is an incompatible breaking change. + +### Upgrade to 34.X + +Starting from this release, the new traefik helm CRD management which works around [Helm caveats](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations) system is enabled by default: + +```bash +# Update repository +helm repo update +# See current Chart & Traefik version +helm search repo traefik/traefik +# Change CRDs ownership +kubectl get customresourcedefinitions.apiextensions.k8s.io -o name | grep traefik.io | xargs kubectl patch --type='json' -p='[{"op": "add", "path": "/metadata/labels", "value": {"app.kubernetes.io/managed-by":"Helm"}},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value":"traefik"},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value":"traefik"}]' +# If you use gateway API, you might also want to change Gateway API ownership + kubectl get customresourcedefinitions.apiextensions.k8s.io -o name | grep gateway.networking.k8s.io | xargs kubectl patch --type='json' -p='[{"op": "add", "path": "/metadata/labels", "value": {"app.kubernetes.io/managed-by":"Helm"}},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value":"traefik"},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value":"traefik"}]' # Upgrade Traefik helm upgrade traefik traefik/traefik ``` -New major version indicates that there is an incompatible breaking change. +If you still want to manage CRDs your self, it can be opt-out: + +```bash +# Upgrade Traefik and skip all CRDs installation +helm upgrade traefik traefik/traefik --set traefik-crds.traefik=false --set traefik-crds.hub=false --set traefik-crds.gateway_api=false +``` ### Upgrade up to 27.X From 39fc5a37ec7d7661f80da65923d07378ae55f6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Thu, 31 Oct 2024 09:38:37 +0100 Subject: [PATCH 24/32] fix: CI --- traefik-crds/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index bd3a42a72..e68d5f04d 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,4 +1,4 @@ -global: # @schema type:[object, null]; additionalProperties: true +global: # @schema type:[object, null]; additionalProperties: true traefik: false # @schema type:[boolean] gateway_api: false # @schema type:[string, boolean]; default: false hub: false # @schema type:[string, boolean]; default: false From 2af71bcdd2788f7a2f964ca464a8cf7b31de34c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 4 Nov 2024 08:25:40 +0100 Subject: [PATCH 25/32] fix: CI --- traefik-crds/VALUES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/traefik-crds/VALUES.md b/traefik-crds/VALUES.md index a736566bc..68d56e701 100644 --- a/traefik-crds/VALUES.md +++ b/traefik-crds/VALUES.md @@ -30,6 +30,7 @@ Kubernetes: `>=1.22.0-0` |-----|------|---------|-------------| | deleteOnUninstall | bool | `false` | | | gateway_api | bool | `false` | | +| global | string | `nil` | | | hub | bool | `false` | | | traefik | bool | `false` | | From 34e03a94987414c717f27db289861c052f16e034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 8 Nov 2024 09:02:10 +0100 Subject: [PATCH 26/32] fix: review --- traefik-crds/values.schema.json | 8 ++------ traefik-crds/values.yaml | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index 7189c84bb..99668a020 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -5,9 +5,7 @@ "description": "The Cloud Native Application Proxy", "properties": { "deleteOnUninstall": { - "type": [ - "boolean" - ] + "type": "boolean" }, "gateway_api": { "default": false, @@ -31,9 +29,7 @@ ] }, "traefik": { - "type": [ - "boolean" - ] + "type": "boolean" } }, "title": "Traefik CRDs Helm Chart", diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index e68d5f04d..bc5f1b94f 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,5 +1,5 @@ global: # @schema type:[object, null]; additionalProperties: true -traefik: false # @schema type:[boolean] +traefik: false gateway_api: false # @schema type:[string, boolean]; default: false hub: false # @schema type:[string, boolean]; default: false -deleteOnUninstall: false # @schema type:[boolean] +deleteOnUninstall: false From ac7881b0d2ceea1348103417003d0082b652041f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 8 Nov 2024 09:04:50 +0100 Subject: [PATCH 27/32] fix: doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 686e50bbf..69b738df7 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ helm search repo traefik/traefik # Change CRDs ownership kubectl get customresourcedefinitions.apiextensions.k8s.io -o name | grep traefik.io | xargs kubectl patch --type='json' -p='[{"op": "add", "path": "/metadata/labels", "value": {"app.kubernetes.io/managed-by":"Helm"}},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value":"traefik"},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value":"traefik"}]' # If you use gateway API, you might also want to change Gateway API ownership - kubectl get customresourcedefinitions.apiextensions.k8s.io -o name | grep gateway.networking.k8s.io | xargs kubectl patch --type='json' -p='[{"op": "add", "path": "/metadata/labels", "value": {"app.kubernetes.io/managed-by":"Helm"}},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value":"traefik"},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value":"traefik"}]' +kubectl get customresourcedefinitions.apiextensions.k8s.io -o name | grep gateway.networking.k8s.io | xargs kubectl patch --type='json' -p='[{"op": "add", "path": "/metadata/labels", "value": {"app.kubernetes.io/managed-by":"Helm"}},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value":"traefik"},{"op": "add", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value":"traefik"}]' # Upgrade Traefik helm upgrade traefik traefik/traefik ``` From 8d8137838003dcc830a2f286729113afc8e733c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 16 Dec 2024 08:11:37 +0100 Subject: [PATCH 28/32] fix: tests + add condition --- traefik-crds/tests/crds_test.yaml | 4 ++-- traefik/Chart.yaml | 9 +++++---- traefik/values.schema.json | 14 ++++++++++++++ traefik/values.yaml | 14 +++++++------- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/traefik-crds/tests/crds_test.yaml b/traefik-crds/tests/crds_test.yaml index 8e6d12ddf..ce1ce07c1 100644 --- a/traefik-crds/tests/crds_test.yaml +++ b/traefik-crds/tests/crds_test.yaml @@ -30,7 +30,7 @@ tests: hub: true asserts: - hasDocuments: - count: 8 + count: 11 - isKind: of: CustomResourceDefinition - equal: @@ -38,7 +38,7 @@ tests: value: hub.traefik.io - matchRegex: path: spec.names.kind - pattern: ^(AccessControlPolicy|APIAccess|APIBundle|APIPlan|APIPortal|APIRateLimit|API|APIVersion)$ + pattern: ^(AccessControlPolicy|AIService|APIAccess|APIBundle|APICatalogItem|APIPlan|APIPortal|APIRateLimit|API|APIVersion|ManagedSubscription)$ - equal: path: metadata.annotations["helm.sh/resource-policy"] value: keep diff --git a/traefik/Chart.yaml b/traefik/Chart.yaml index 17a713aac..827dcd369 100644 --- a/traefik/Chart.yaml +++ b/traefik/Chart.yaml @@ -27,7 +27,8 @@ annotations: artifacthub.io/changes: | - "fix(Gateway API): CRDs should only be defined once" - "chore(release): 🚀 publish v33.2.1" -#dependencies: -# - name: traefik-crds -# version: 0.0.1 -# repository: https://traefik.github.io/charts +dependencies: + - name: traefik-crds + version: 0.0.1 + repository: https://traefik.github.io/charts + condition: or traefik-crds.traefik traefik-crds.hub traefik-crds.gateway_api diff --git a/traefik/values.schema.json b/traefik/values.schema.json index aa76667a7..22878a9f5 100644 --- a/traefik/values.schema.json +++ b/traefik/values.schema.json @@ -1672,6 +1672,20 @@ }, "type": "object" }, + "traefik-crds": { + "properties": { + "gateway_api": { + "type": "string" + }, + "hub": { + "type": "string" + }, + "traefik": { + "type": "boolean" + } + }, + "type": "object" + }, "updateStrategy": { "additionalProperties": false, "properties": { diff --git a/traefik/values.yaml b/traefik/values.yaml index cc00e97da..510526271 100644 --- a/traefik/values.yaml +++ b/traefik/values.yaml @@ -966,10 +966,10 @@ hub: # Enable export of errors logs to the platform. Default: true. sendlogs: # @schema type:[boolean, null] -#traefik-crds: -# # -- Set all the following to false if you want to manage CRDs your-self -# traefik: true -# hub: | -# {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} -# gateway_api: | -# {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} +traefik-crds: + # -- Set all the following to false if you want to manage CRDs your-self + traefik: true + hub: | + {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} + gateway_api: | + {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} From 605bf170bd9d7851d0b12aaaed027b0dae65b9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Fri, 6 Dec 2024 14:57:51 +0100 Subject: [PATCH 29/32] fix --- traefik/crds/traefik.io_ingressroutes.yaml | 366 ++++++ traefik/crds/traefik.io_ingressroutetcps.yaml | 247 ++++ traefik/crds/traefik.io_ingressrouteudps.yaml | 111 ++ traefik/crds/traefik.io_middlewares.yaml | 1126 +++++++++++++++++ traefik/crds/traefik.io_middlewaretcps.yaml | 87 ++ .../crds/traefik.io_serverstransports.yaml | 139 ++ .../crds/traefik.io_serverstransporttcps.yaml | 120 ++ traefik/crds/traefik.io_tlsoptions.yaml | 114 ++ traefik/crds/traefik.io_tlsstores.yaml | 97 ++ traefik/crds/traefik.io_traefikservices.yaml | 644 ++++++++++ 10 files changed, 3051 insertions(+) create mode 100644 traefik/crds/traefik.io_ingressroutes.yaml create mode 100644 traefik/crds/traefik.io_ingressroutetcps.yaml create mode 100644 traefik/crds/traefik.io_ingressrouteudps.yaml create mode 100644 traefik/crds/traefik.io_middlewares.yaml create mode 100644 traefik/crds/traefik.io_middlewaretcps.yaml create mode 100644 traefik/crds/traefik.io_serverstransports.yaml create mode 100644 traefik/crds/traefik.io_serverstransporttcps.yaml create mode 100644 traefik/crds/traefik.io_tlsoptions.yaml create mode 100644 traefik/crds/traefik.io_tlsstores.yaml create mode 100644 traefik/crds/traefik.io_traefikservices.yaml diff --git a/traefik/crds/traefik.io_ingressroutes.yaml b/traefik/crds/traefik.io_ingressroutes.yaml new file mode 100644 index 000000000..ccb374a94 --- /dev/null +++ b/traefik/crds/traefik.io_ingressroutes.yaml @@ -0,0 +1,366 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressroutes.traefik.io +spec: + group: traefik.io + names: + kind: IngressRoute + listKind: IngressRouteList + plural: ingressroutes + singular: ingressroute + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRoute is the CRD implementation of a Traefik HTTP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteSpec defines the desired state of IngressRoute. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: Route holds the HTTP route configuration. + properties: + kind: + description: |- + Kind defines the kind of the route. + Rule is the only supported kind. + enum: + - Rule + type: string + match: + description: |- + Match defines the router's rule. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rule + type: string + middlewares: + description: |- + Middlewares defines the list of references to Middleware resources. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-middleware + items: + description: MiddlewareRef is a reference to a Middleware + resource. + properties: + name: + description: Name defines the name of the referenced Middleware + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Middleware resource. + type: string + required: + - name + type: object + type: array + priority: + description: |- + Priority defines the router's priority. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#priority + type: integer + services: + description: |- + Services defines the list of Service. + It can contain any combination of TraefikService and/or reference to a Kubernetes Service. + items: + description: Service defines an upstream HTTP service to proxy + traffic to. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be + sent to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for + the health check endpoint. + type: string + port: + description: Port defines the server URL port for + the health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme + for the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to + the client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as + JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie + can only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + syntax: + description: |- + Syntax defines the router's rule syntax. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rulesyntax + type: string + required: + - kind + - match + type: object + type: array + tls: + description: |- + TLS defines the TLS configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#tls + properties: + certResolver: + description: |- + CertResolver defines the name of the certificate resolver to use. + Cert resolvers have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/https/acme/#certificate-resolvers + type: string + domains: + description: |- + Domains defines the list of domains that will be used to issue certificates. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#domains + items: + description: Domain holds a domain name with SANs. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain + names. + items: + type: string + type: array + type: object + type: array + options: + description: |- + Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. + If not defined, the `default` TLSOption is used. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + name: + description: |- + Name defines the name of the referenced TLSOption. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsoption + type: string + namespace: + description: |- + Namespace defines the namespace of the referenced TLSOption. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsoption + type: string + required: + - name + type: object + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + store: + description: |- + Store defines the reference to the TLSStore, that will be used to store certificates. + Please note that only `default` TLSStore can be used. + properties: + name: + description: |- + Name defines the name of the referenced TLSStore. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsstore + type: string + namespace: + description: |- + Namespace defines the namespace of the referenced TLSStore. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsstore + type: string + required: + - name + type: object + type: object + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_ingressroutetcps.yaml b/traefik/crds/traefik.io_ingressroutetcps.yaml new file mode 100644 index 000000000..ae675f6a6 --- /dev/null +++ b/traefik/crds/traefik.io_ingressroutetcps.yaml @@ -0,0 +1,247 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressroutetcps.traefik.io +spec: + group: traefik.io + names: + kind: IngressRouteTCP + listKind: IngressRouteTCPList + plural: ingressroutetcps + singular: ingressroutetcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRouteTCP is the CRD implementation of a Traefik TCP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteTCPSpec defines the desired state of IngressRouteTCP. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: RouteTCP holds the TCP route configuration. + properties: + match: + description: |- + Match defines the router's rule. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rule_1 + type: string + middlewares: + description: Middlewares defines the list of references to MiddlewareTCP + resources. + items: + description: ObjectReference is a generic reference to a Traefik + resource. + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + type: array + priority: + description: |- + Priority defines the router's priority. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#priority_1 + type: integer + services: + description: Services defines the list of TCP services. + items: + description: ServiceTCP defines an upstream TCP service to + proxy traffic to. + properties: + name: + description: Name defines the name of the referenced Kubernetes + Service. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + proxyProtocol: + description: |- + ProxyProtocol defines the PROXY protocol configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#proxy-protocol + properties: + version: + description: Version defines the PROXY Protocol version + to use. + type: integer + type: object + serversTransport: + description: |- + ServersTransport defines the name of ServersTransportTCP resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + terminationDelay: + description: |- + TerminationDelay defines the deadline that the proxy sets, after one of its connected peers indicates + it has closed the writing capability of its connection, to close the reading capability as well, + hence fully terminating the connection. + It is a duration in milliseconds, defaulting to 100. + A negative value means an infinite deadline (i.e. the reading capability is never closed). + Deprecated: TerminationDelay will not be supported in future APIVersions, please use ServersTransport to configure the TerminationDelay instead. + type: integer + tls: + description: TLS determines whether to use TLS when dialing + with the backend. + type: boolean + weight: + description: Weight defines the weight used when balancing + requests between multiple Kubernetes Service. + type: integer + required: + - name + - port + type: object + type: array + syntax: + description: |- + Syntax defines the router's rule syntax. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rulesyntax_1 + type: string + required: + - match + type: object + type: array + tls: + description: |- + TLS defines the TLS configuration on a layer 4 / TCP Route. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#tls_1 + properties: + certResolver: + description: |- + CertResolver defines the name of the certificate resolver to use. + Cert resolvers have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/https/acme/#certificate-resolvers + type: string + domains: + description: |- + Domains defines the list of domains that will be used to issue certificates. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#domains + items: + description: Domain holds a domain name with SANs. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain + names. + items: + type: string + type: array + type: object + type: array + options: + description: |- + Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. + If not defined, the `default` TLSOption is used. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + passthrough: + description: Passthrough defines whether a TLS router will terminate + the TLS connection. + type: boolean + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + store: + description: |- + Store defines the reference to the TLSStore, that will be used to store certificates. + Please note that only `default` TLSStore can be used. + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + type: object + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_ingressrouteudps.yaml b/traefik/crds/traefik.io_ingressrouteudps.yaml new file mode 100644 index 000000000..a815d8683 --- /dev/null +++ b/traefik/crds/traefik.io_ingressrouteudps.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressrouteudps.traefik.io +spec: + group: traefik.io + names: + kind: IngressRouteUDP + listKind: IngressRouteUDPList + plural: ingressrouteudps + singular: ingressrouteudp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRouteUDP is a CRD implementation of a Traefik UDP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteUDPSpec defines the desired state of a IngressRouteUDP. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: RouteUDP holds the UDP route configuration. + properties: + services: + description: Services defines the list of UDP services. + items: + description: ServiceUDP defines an upstream UDP service to + proxy traffic to. + properties: + name: + description: Name defines the name of the referenced Kubernetes + Service. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + weight: + description: Weight defines the weight used when balancing + requests between multiple Kubernetes Service. + type: integer + required: + - name + - port + type: object + type: array + type: object + type: array + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_middlewares.yaml b/traefik/crds/traefik.io_middlewares.yaml new file mode 100644 index 000000000..f3ea9fc58 --- /dev/null +++ b/traefik/crds/traefik.io_middlewares.yaml @@ -0,0 +1,1126 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: middlewares.traefik.io +spec: + group: traefik.io + names: + kind: Middleware + listKind: MiddlewareList + plural: middlewares + singular: middleware + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Middleware is the CRD implementation of a Traefik Middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/overview/ + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MiddlewareSpec defines the desired state of a Middleware. + properties: + addPrefix: + description: |- + AddPrefix holds the add prefix middleware configuration. + This middleware updates the path of a request before forwarding it. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/addprefix/ + properties: + prefix: + description: |- + Prefix is the string to add before the current path in the requested URL. + It should include a leading slash (/). + type: string + type: object + basicAuth: + description: |- + BasicAuth holds the basic auth middleware configuration. + This middleware restricts access to your services to known users. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/ + properties: + headerField: + description: |- + HeaderField defines a header field to store the authenticated user. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/#headerfield + type: string + realm: + description: |- + Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme. + Default: traefik. + type: string + removeHeader: + description: |- + RemoveHeader sets the removeHeader option to true to remove the authorization header before forwarding the request to your service. + Default: false. + type: boolean + secret: + description: Secret is the name of the referenced Kubernetes Secret + containing user credentials. + type: string + type: object + buffering: + description: |- + Buffering holds the buffering middleware configuration. + This middleware retries or limits the size of requests that can be forwarded to backends. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/buffering/#maxrequestbodybytes + properties: + maxRequestBodyBytes: + description: |- + MaxRequestBodyBytes defines the maximum allowed body size for the request (in bytes). + If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a 413 (Request Entity Too Large) response. + Default: 0 (no maximum). + format: int64 + type: integer + maxResponseBodyBytes: + description: |- + MaxResponseBodyBytes defines the maximum allowed response size from the service (in bytes). + If the response exceeds the allowed size, it is not forwarded to the client. The client gets a 500 (Internal Server Error) response instead. + Default: 0 (no maximum). + format: int64 + type: integer + memRequestBodyBytes: + description: |- + MemRequestBodyBytes defines the threshold (in bytes) from which the request will be buffered on disk instead of in memory. + Default: 1048576 (1Mi). + format: int64 + type: integer + memResponseBodyBytes: + description: |- + MemResponseBodyBytes defines the threshold (in bytes) from which the response will be buffered on disk instead of in memory. + Default: 1048576 (1Mi). + format: int64 + type: integer + retryExpression: + description: |- + RetryExpression defines the retry conditions. + It is a logical combination of functions with operators AND (&&) and OR (||). + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/buffering/#retryexpression + type: string + type: object + chain: + description: |- + Chain holds the configuration of the chain middleware. + This middleware enables to define reusable combinations of other pieces of middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/chain/ + properties: + middlewares: + description: Middlewares is the list of MiddlewareRef which composes + the chain. + items: + description: MiddlewareRef is a reference to a Middleware resource. + properties: + name: + description: Name defines the name of the referenced Middleware + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Middleware resource. + type: string + required: + - name + type: object + type: array + type: object + circuitBreaker: + description: CircuitBreaker holds the circuit breaker configuration. + properties: + checkPeriod: + anyOf: + - type: integer + - type: string + description: CheckPeriod is the interval between successive checks + of the circuit breaker condition (when in standby state). + x-kubernetes-int-or-string: true + expression: + description: Expression is the condition that triggers the tripped + state. + type: string + fallbackDuration: + anyOf: + - type: integer + - type: string + description: FallbackDuration is the duration for which the circuit + breaker will wait before trying to recover (from a tripped state). + x-kubernetes-int-or-string: true + recoveryDuration: + anyOf: + - type: integer + - type: string + description: RecoveryDuration is the duration for which the circuit + breaker will try to recover (as soon as it is in recovering + state). + x-kubernetes-int-or-string: true + responseCode: + description: ResponseCode is the status code that the circuit + breaker will return while it is in the open state. + type: integer + type: object + compress: + description: |- + Compress holds the compress middleware configuration. + This middleware compresses responses before sending them to the client, using gzip, brotli, or zstd compression. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/compress/ + properties: + defaultEncoding: + description: DefaultEncoding specifies the default encoding if + the `Accept-Encoding` header is not in the request or contains + a wildcard (`*`). + type: string + encodings: + description: Encodings defines the list of supported compression + algorithms. + items: + type: string + type: array + excludedContentTypes: + description: |- + ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. + `application/grpc` is always excluded. + items: + type: string + type: array + includedContentTypes: + description: IncludedContentTypes defines the list of content + types to compare the Content-Type header of the responses before + compressing. + items: + type: string + type: array + minResponseBodyBytes: + description: |- + MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. + Default: 1024. + type: integer + type: object + contentType: + description: |- + ContentType holds the content-type middleware configuration. + This middleware exists to enable the correct behavior until at least the default one can be changed in a future version. + properties: + autoDetect: + description: |- + AutoDetect specifies whether to let the `Content-Type` header, if it has not been set by the backend, + be automatically set to a value derived from the contents of the response. + Deprecated: AutoDetect option is deprecated, Content-Type middleware is only meant to be used to enable the content-type detection, please remove any usage of this option. + type: boolean + type: object + digestAuth: + description: |- + DigestAuth holds the digest auth middleware configuration. + This middleware restricts access to your services to known users. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/digestauth/ + properties: + headerField: + description: |- + HeaderField defines a header field to store the authenticated user. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/#headerfield + type: string + realm: + description: |- + Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme. + Default: traefik. + type: string + removeHeader: + description: RemoveHeader defines whether to remove the authorization + header before forwarding the request to the backend. + type: boolean + secret: + description: Secret is the name of the referenced Kubernetes Secret + containing user credentials. + type: string + type: object + errors: + description: |- + ErrorPage holds the custom error middleware configuration. + This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/errorpages/ + properties: + query: + description: |- + Query defines the URL for the error page (hosted by service). + The {status} variable can be used in order to insert the status code in the URL. + type: string + service: + description: |- + Service defines the reference to a Kubernetes Service that will serve the error page. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/errorpages/#service + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname in + the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status code + of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can + be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + status: + description: |- + Status defines which status or range of statuses should result in an error page. + It can be either a status code as a number (500), + as multiple comma-separated numbers (500,502), + as ranges by separating two codes with a dash (500-599), + or a combination of the two (404,418,500-599). + items: + type: string + type: array + type: object + forwardAuth: + description: |- + ForwardAuth holds the forward auth middleware configuration. + This middleware delegates the request authentication to a Service. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/forwardauth/ + properties: + addAuthCookiesToResponse: + description: AddAuthCookiesToResponse defines the list of cookies + to copy from the authentication server response to the response. + items: + type: string + type: array + address: + description: Address defines the authentication server address. + type: string + authRequestHeaders: + description: |- + AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. + If not set or empty then all request headers are passed. + items: + type: string + type: array + authResponseHeaders: + description: AuthResponseHeaders defines the list of headers to + copy from the authentication server response and set on forwarded + request, replacing any existing conflicting headers. + items: + type: string + type: array + authResponseHeadersRegex: + description: |- + AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/forwardauth/#authresponseheadersregex + type: string + tls: + description: TLS defines the configuration used to secure the + connection to the authentication server. + properties: + caOptional: + description: 'Deprecated: TLS client authentication is a server + side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).' + type: boolean + caSecret: + description: |- + CASecret is the name of the referenced Kubernetes Secret containing the CA to validate the server certificate. + The CA certificate is extracted from key `tls.ca` or `ca.crt`. + type: string + certSecret: + description: |- + CertSecret is the name of the referenced Kubernetes Secret containing the client certificate. + The client certificate is extracted from the keys `tls.crt` and `tls.key`. + type: string + insecureSkipVerify: + description: InsecureSkipVerify defines whether the server + certificates should be validated. + type: boolean + type: object + trustForwardHeader: + description: 'TrustForwardHeader defines whether to trust (ie: + forward) all X-Forwarded-* headers.' + type: boolean + type: object + grpcWeb: + description: |- + GrpcWeb holds the gRPC web middleware configuration. + This middleware converts a gRPC web request to an HTTP/2 gRPC request. + properties: + allowOrigins: + description: |- + AllowOrigins is a list of allowable origins. + Can also be a wildcard origin "*". + items: + type: string + type: array + type: object + headers: + description: |- + Headers holds the headers middleware configuration. + This middleware manages the requests and responses headers. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/headers/#customrequestheaders + properties: + accessControlAllowCredentials: + description: AccessControlAllowCredentials defines whether the + request can include user credentials. + type: boolean + accessControlAllowHeaders: + description: AccessControlAllowHeaders defines the Access-Control-Request-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlAllowMethods: + description: AccessControlAllowMethods defines the Access-Control-Request-Method + values sent in preflight response. + items: + type: string + type: array + accessControlAllowOriginList: + description: AccessControlAllowOriginList is a list of allowable + origins. Can also be a wildcard origin "*". + items: + type: string + type: array + accessControlAllowOriginListRegex: + description: AccessControlAllowOriginListRegex is a list of allowable + origins written following the Regular Expression syntax (https://golang.org/pkg/regexp/). + items: + type: string + type: array + accessControlExposeHeaders: + description: AccessControlExposeHeaders defines the Access-Control-Expose-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlMaxAge: + description: AccessControlMaxAge defines the time that a preflight + request may be cached. + format: int64 + type: integer + addVaryHeader: + description: AddVaryHeader defines whether the Vary header is + automatically added/updated when the AccessControlAllowOriginList + is set. + type: boolean + allowedHosts: + description: AllowedHosts defines the fully qualified list of + allowed domain names. + items: + type: string + type: array + browserXssFilter: + description: BrowserXSSFilter defines whether to add the X-XSS-Protection + header with the value 1; mode=block. + type: boolean + contentSecurityPolicy: + description: ContentSecurityPolicy defines the Content-Security-Policy + header value. + type: string + contentSecurityPolicyReportOnly: + description: ContentSecurityPolicyReportOnly defines the Content-Security-Policy-Report-Only + header value. + type: string + contentTypeNosniff: + description: ContentTypeNosniff defines whether to add the X-Content-Type-Options + header with the nosniff value. + type: boolean + customBrowserXSSValue: + description: |- + CustomBrowserXSSValue defines the X-XSS-Protection header value. + This overrides the BrowserXssFilter option. + type: string + customFrameOptionsValue: + description: |- + CustomFrameOptionsValue defines the X-Frame-Options header value. + This overrides the FrameDeny option. + type: string + customRequestHeaders: + additionalProperties: + type: string + description: CustomRequestHeaders defines the header names and + values to apply to the request. + type: object + customResponseHeaders: + additionalProperties: + type: string + description: CustomResponseHeaders defines the header names and + values to apply to the response. + type: object + featurePolicy: + description: 'Deprecated: FeaturePolicy option is deprecated, + please use PermissionsPolicy instead.' + type: string + forceSTSHeader: + description: ForceSTSHeader defines whether to add the STS header + even when the connection is HTTP. + type: boolean + frameDeny: + description: FrameDeny defines whether to add the X-Frame-Options + header with the DENY value. + type: boolean + hostsProxyHeaders: + description: HostsProxyHeaders defines the header keys that may + hold a proxied hostname value for the request. + items: + type: string + type: array + isDevelopment: + description: |- + IsDevelopment defines whether to mitigate the unwanted effects of the AllowedHosts, SSL, and STS options when developing. + Usually testing takes place using HTTP, not HTTPS, and on localhost, not your production domain. + If you would like your development environment to mimic production with complete Host blocking, SSL redirects, + and STS headers, leave this as false. + type: boolean + permissionsPolicy: + description: |- + PermissionsPolicy defines the Permissions-Policy header value. + This allows sites to control browser features. + type: string + publicKey: + description: PublicKey is the public key that implements HPKP + to prevent MITM attacks with forged certificates. + type: string + referrerPolicy: + description: |- + ReferrerPolicy defines the Referrer-Policy header value. + This allows sites to control whether browsers forward the Referer header to other sites. + type: string + sslForceHost: + description: 'Deprecated: SSLForceHost option is deprecated, please + use RedirectRegex instead.' + type: boolean + sslHost: + description: 'Deprecated: SSLHost option is deprecated, please + use RedirectRegex instead.' + type: string + sslProxyHeaders: + additionalProperties: + type: string + description: |- + SSLProxyHeaders defines the header keys with associated values that would indicate a valid HTTPS request. + It can be useful when using other proxies (example: "X-Forwarded-Proto": "https"). + type: object + sslRedirect: + description: 'Deprecated: SSLRedirect option is deprecated, please + use EntryPoint redirection or RedirectScheme instead.' + type: boolean + sslTemporaryRedirect: + description: 'Deprecated: SSLTemporaryRedirect option is deprecated, + please use EntryPoint redirection or RedirectScheme instead.' + type: boolean + stsIncludeSubdomains: + description: STSIncludeSubdomains defines whether the includeSubDomains + directive is appended to the Strict-Transport-Security header. + type: boolean + stsPreload: + description: STSPreload defines whether the preload flag is appended + to the Strict-Transport-Security header. + type: boolean + stsSeconds: + description: |- + STSSeconds defines the max-age of the Strict-Transport-Security header. + If set to 0, the header is not set. + format: int64 + type: integer + type: object + inFlightReq: + description: |- + InFlightReq holds the in-flight request middleware configuration. + This middleware limits the number of requests being processed and served concurrently. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/inflightreq/ + properties: + amount: + description: |- + Amount defines the maximum amount of allowed simultaneous in-flight request. + The middleware responds with HTTP 429 Too Many Requests if there are already amount requests in progress (based on the same sourceCriterion strategy). + format: int64 + type: integer + sourceCriterion: + description: |- + SourceCriterion defines what criterion is used to group requests as originating from a common source. + If several strategies are defined at the same time, an error will be raised. + If none are set, the default is to use the requestHost. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/inflightreq/#sourcecriterion + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position + (starting from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the + X-Forwarded-For header and select the first IP not in + the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider + all IPv6 addresses from the defined subnet as originating + from the same IP. Applies to RemoteAddrStrategy and + DepthStrategy. + type: integer + type: object + requestHeaderName: + description: RequestHeaderName defines the name of the header + used to group incoming requests. + type: string + requestHost: + description: RequestHost defines whether to consider the request + Host as the source. + type: boolean + type: object + type: object + ipAllowList: + description: |- + IPAllowList holds the IP allowlist middleware configuration. + This middleware limits allowed requests based on the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/ + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider all + IPv6 addresses from the defined subnet as originating from + the same IP. Applies to RemoteAddrStrategy and DepthStrategy. + type: integer + type: object + rejectStatusCode: + description: |- + RejectStatusCode defines the HTTP status code used for refused requests. + If not set, the default is 403 (Forbidden). + type: integer + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider all + IPv6 addresses from the defined subnet as originating from + the same IP. Applies to RemoteAddrStrategy and DepthStrategy. + type: integer + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). Required. + items: + type: string + type: array + type: object + passTLSClientCert: + description: |- + PassTLSClientCert holds the pass TLS client cert middleware configuration. + This middleware adds the selected data from the passed client TLS certificate to a header. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/passtlsclientcert/ + properties: + info: + description: Info selects the specific client certificate details + you want to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + issuer: + description: Issuer defines the client certificate issuer + details to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + commonName: + description: CommonName defines whether to add the organizationalUnit + information into the issuer. + type: boolean + country: + description: Country defines whether to add the country + information into the issuer. + type: boolean + domainComponent: + description: DomainComponent defines whether to add the + domainComponent information into the issuer. + type: boolean + locality: + description: Locality defines whether to add the locality + information into the issuer. + type: boolean + organization: + description: Organization defines whether to add the organization + information into the issuer. + type: boolean + province: + description: Province defines whether to add the province + information into the issuer. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the serialNumber + information into the issuer. + type: boolean + type: object + notAfter: + description: NotAfter defines whether to add the Not After + information from the Validity part. + type: boolean + notBefore: + description: NotBefore defines whether to add the Not Before + information from the Validity part. + type: boolean + sans: + description: Sans defines whether to add the Subject Alternative + Name information from the Subject Alternative Name part. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the client + serialNumber information. + type: boolean + subject: + description: Subject defines the client certificate subject + details to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + commonName: + description: CommonName defines whether to add the organizationalUnit + information into the subject. + type: boolean + country: + description: Country defines whether to add the country + information into the subject. + type: boolean + domainComponent: + description: DomainComponent defines whether to add the + domainComponent information into the subject. + type: boolean + locality: + description: Locality defines whether to add the locality + information into the subject. + type: boolean + organization: + description: Organization defines whether to add the organization + information into the subject. + type: boolean + organizationalUnit: + description: OrganizationalUnit defines whether to add + the organizationalUnit information into the subject. + type: boolean + province: + description: Province defines whether to add the province + information into the subject. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the serialNumber + information into the subject. + type: boolean + type: object + type: object + pem: + description: PEM sets the X-Forwarded-Tls-Client-Cert header with + the certificate. + type: boolean + type: object + plugin: + additionalProperties: + x-kubernetes-preserve-unknown-fields: true + description: |- + Plugin defines the middleware plugin configuration. + More info: https://doc.traefik.io/traefik/plugins/ + type: object + rateLimit: + description: |- + RateLimit holds the rate limit configuration. + This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ratelimit/ + properties: + average: + description: |- + Average is the maximum rate, by default in requests/s, allowed for the given source. + It defaults to 0, which means no rate limiting. + The rate is actually defined by dividing Average by Period. So for a rate below 1req/s, + one needs to define a Period larger than a second. + format: int64 + type: integer + burst: + description: |- + Burst is the maximum number of requests allowed to arrive in the same arbitrarily small period of time. + It defaults to 1. + format: int64 + type: integer + period: + anyOf: + - type: integer + - type: string + description: |- + Period, in combination with Average, defines the actual maximum rate, such as: + r = Average / Period. It defaults to a second. + x-kubernetes-int-or-string: true + sourceCriterion: + description: |- + SourceCriterion defines what criterion is used to group requests as originating from a common source. + If several strategies are defined at the same time, an error will be raised. + If none are set, the default is to use the request's remote address field (as an ipStrategy). + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position + (starting from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the + X-Forwarded-For header and select the first IP not in + the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider + all IPv6 addresses from the defined subnet as originating + from the same IP. Applies to RemoteAddrStrategy and + DepthStrategy. + type: integer + type: object + requestHeaderName: + description: RequestHeaderName defines the name of the header + used to group incoming requests. + type: string + requestHost: + description: RequestHost defines whether to consider the request + Host as the source. + type: boolean + type: object + type: object + redirectRegex: + description: |- + RedirectRegex holds the redirect regex middleware configuration. + This middleware redirects a request using regex matching and replacement. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/redirectregex/#regex + properties: + permanent: + description: Permanent defines whether the redirection is permanent + (301). + type: boolean + regex: + description: Regex defines the regex used to match and capture + elements from the request URL. + type: string + replacement: + description: Replacement defines how to modify the URL to have + the new target URL. + type: string + type: object + redirectScheme: + description: |- + RedirectScheme holds the redirect scheme middleware configuration. + This middleware redirects requests from a scheme/port to another. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/redirectscheme/ + properties: + permanent: + description: Permanent defines whether the redirection is permanent + (301). + type: boolean + port: + description: Port defines the port of the new URL. + type: string + scheme: + description: Scheme defines the scheme of the new URL. + type: string + type: object + replacePath: + description: |- + ReplacePath holds the replace path middleware configuration. + This middleware replaces the path of the request URL and store the original path in an X-Replaced-Path header. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/replacepath/ + properties: + path: + description: Path defines the path to use as replacement in the + request URL. + type: string + type: object + replacePathRegex: + description: |- + ReplacePathRegex holds the replace path regex middleware configuration. + This middleware replaces the path of a URL using regex matching and replacement. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/replacepathregex/ + properties: + regex: + description: Regex defines the regular expression used to match + and capture the path from the request URL. + type: string + replacement: + description: Replacement defines the replacement path format, + which can include captured variables. + type: string + type: object + retry: + description: |- + Retry holds the retry middleware configuration. + This middleware reissues requests a given number of times to a backend server if that server does not reply. + As soon as the server answers, the middleware stops retrying, regardless of the response status. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/retry/ + properties: + attempts: + description: Attempts defines how many times the request should + be retried. + type: integer + initialInterval: + anyOf: + - type: integer + - type: string + description: |- + InitialInterval defines the first wait time in the exponential backoff series. + The maximum interval is calculated as twice the initialInterval. + If unspecified, requests will be retried immediately. + The value of initialInterval should be provided in seconds or as a valid duration format, + see https://pkg.go.dev/time#ParseDuration. + x-kubernetes-int-or-string: true + type: object + stripPrefix: + description: |- + StripPrefix holds the strip prefix middleware configuration. + This middleware removes the specified prefixes from the URL path. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/stripprefix/ + properties: + forceSlash: + description: |- + Deprecated: ForceSlash option is deprecated, please remove any usage of this option. + ForceSlash ensures that the resulting stripped path is not the empty string, by replacing it with / when necessary. + Default: true. + type: boolean + prefixes: + description: Prefixes defines the prefixes to strip from the request + URL. + items: + type: string + type: array + type: object + stripPrefixRegex: + description: |- + StripPrefixRegex holds the strip prefix regex middleware configuration. + This middleware removes the matching prefixes from the URL path. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/stripprefixregex/ + properties: + regex: + description: Regex defines the regular expression to match the + path prefix from the request URL. + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_middlewaretcps.yaml b/traefik/crds/traefik.io_middlewaretcps.yaml new file mode 100644 index 000000000..fc23e11b5 --- /dev/null +++ b/traefik/crds/traefik.io_middlewaretcps.yaml @@ -0,0 +1,87 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: middlewaretcps.traefik.io +spec: + group: traefik.io + names: + kind: MiddlewareTCP + listKind: MiddlewareTCPList + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/overview/ + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MiddlewareTCPSpec defines the desired state of a MiddlewareTCP. + properties: + inFlightConn: + description: InFlightConn defines the InFlightConn middleware configuration. + properties: + amount: + description: |- + Amount defines the maximum amount of allowed simultaneous connections. + The middleware closes the connection if there are already amount connections opened. + format: int64 + type: integer + type: object + ipAllowList: + description: |- + IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/tcp/ipallowlist/ + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: |- + IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client IP. + Deprecated: please use IPAllowList instead. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/tcp/ipwhitelist/ + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_serverstransports.yaml b/traefik/crds/traefik.io_serverstransports.yaml new file mode 100644 index 000000000..fe2f129ad --- /dev/null +++ b/traefik/crds/traefik.io_serverstransports.yaml @@ -0,0 +1,139 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: serverstransports.traefik.io +spec: + group: traefik.io + names: + kind: ServersTransport + listKind: ServersTransportList + plural: serverstransports + singular: serverstransport + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ServersTransport is the CRD implementation of a ServersTransport. + If no serversTransport is specified, the default@internal will be used. + The default@internal serversTransport is created from the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#serverstransport_1 + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ServersTransportSpec defines the desired state of a ServersTransport. + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + disableHTTP2: + description: DisableHTTP2 disables HTTP/2 for connections with backend + servers. + type: boolean + forwardingTimeouts: + description: ForwardingTimeouts defines the timeouts for requests + forwarded to the backend servers. + properties: + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a + connection to a backend server can be established. + x-kubernetes-int-or-string: true + idleConnTimeout: + anyOf: + - type: integer + - type: string + description: IdleConnTimeout is the maximum period for which an + idle HTTP keep-alive connection will remain open before closing + itself. + x-kubernetes-int-or-string: true + pingTimeout: + anyOf: + - type: integer + - type: string + description: PingTimeout is the timeout after which the HTTP/2 + connection will be closed if a response to ping is not received. + x-kubernetes-int-or-string: true + readIdleTimeout: + anyOf: + - type: integer + - type: string + description: ReadIdleTimeout is the timeout after which a health + check using ping frame will be carried out if no frame is received + on the HTTP/2 connection. + x-kubernetes-int-or-string: true + responseHeaderTimeout: + anyOf: + - type: integer + - type: string + description: ResponseHeaderTimeout is the amount of time to wait + for a server's response headers after fully writing the request + (including its body, if any). + x-kubernetes-int-or-string: true + type: object + insecureSkipVerify: + description: InsecureSkipVerify disables SSL certificate verification. + type: boolean + maxIdleConnsPerHost: + description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) + to keep per-host. + type: integer + peerCertURI: + description: PeerCertURI defines the peer cert URI used to match against + SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to validate + self-signed certificate. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact the + server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust domain. + type: string + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_serverstransporttcps.yaml b/traefik/crds/traefik.io_serverstransporttcps.yaml new file mode 100644 index 000000000..2f24c8474 --- /dev/null +++ b/traefik/crds/traefik.io_serverstransporttcps.yaml @@ -0,0 +1,120 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: serverstransporttcps.traefik.io +spec: + group: traefik.io + names: + kind: ServersTransportTCP + listKind: ServersTransportTCPList + plural: serverstransporttcps + singular: serverstransporttcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ServersTransportTCP is the CRD implementation of a TCPServersTransport. + If no tcpServersTransport is specified, a default one named default@internal will be used. + The default@internal tcpServersTransport can be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#serverstransport_3 + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. + properties: + dialKeepAlive: + anyOf: + - type: integer + - type: string + description: DialKeepAlive is the interval between keep-alive probes + for an active network connection. If zero, keep-alive probes are + sent with a default value (currently 15 seconds), if supported by + the protocol and operating system. Network protocols or operating + systems that do not support keep-alives ignore this field. If negative, + keep-alive probes are disabled. + x-kubernetes-int-or-string: true + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a connection + to a backend server can be established. + x-kubernetes-int-or-string: true + terminationDelay: + anyOf: + - type: integer + - type: string + description: TerminationDelay defines the delay to wait before fully + terminating the connection, after one connected peer has closed + its writing capability. + x-kubernetes-int-or-string: true + tls: + description: TLS defines the TLS configuration + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + insecureSkipVerify: + description: InsecureSkipVerify disables TLS certificate verification. + type: boolean + peerCertURI: + description: |- + MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. + PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to + validate self-signed certificates. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact + the server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust + domain. + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_tlsoptions.yaml b/traefik/crds/traefik.io_tlsoptions.yaml new file mode 100644 index 000000000..498fc3c8b --- /dev/null +++ b/traefik/crds/traefik.io_tlsoptions.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: tlsoptions.traefik.io +spec: + group: traefik.io + names: + kind: TLSOption + listKind: TLSOptionList + plural: tlsoptions + singular: tlsoption + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TLSOptionSpec defines the desired state of a TLSOption. + properties: + alpnProtocols: + description: |- + ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#alpn-protocols + items: + type: string + type: array + cipherSuites: + description: |- + CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#cipher-suites + items: + type: string + type: array + clientAuth: + description: ClientAuth defines the server's policy for TLS Client + Authentication. + properties: + clientAuthType: + description: ClientAuthType defines the client authentication + type to apply. + enum: + - NoClientCert + - RequestClientCert + - RequireAnyClientCert + - VerifyClientCertIfGiven + - RequireAndVerifyClientCert + type: string + secretNames: + description: SecretNames defines the names of the referenced Kubernetes + Secret storing certificate details. + items: + type: string + type: array + type: object + curvePreferences: + description: |- + CurvePreferences defines the preferred elliptic curves in a specific order. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#curve-preferences + items: + type: string + type: array + maxVersion: + description: |- + MaxVersion defines the maximum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: None. + type: string + minVersion: + description: |- + MinVersion defines the minimum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: VersionTLS10. + type: string + preferServerCipherSuites: + description: |- + PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. + It is enabled automatically when minVersion or maxVersion is set. + Deprecated: https://github.com/golang/go/issues/45430 + type: boolean + sniStrict: + description: SniStrict defines whether Traefik allows connections + from clients connections that do not specify a server_name extension. + type: boolean + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_tlsstores.yaml b/traefik/crds/traefik.io_tlsstores.yaml new file mode 100644 index 000000000..7eacb770e --- /dev/null +++ b/traefik/crds/traefik.io_tlsstores.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: tlsstores.traefik.io +spec: + group: traefik.io + names: + kind: TLSStore + listKind: TLSStoreList + plural: tlsstores + singular: tlsstore + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TLSStore is the CRD implementation of a Traefik TLS Store. + For the time being, only the TLSStore named default is supported. + This means that you cannot have two stores that are named default in different Kubernetes namespaces. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#certificates-stores + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TLSStoreSpec defines the desired state of a TLSStore. + properties: + certificates: + description: Certificates is a list of secret names, each secret holding + a key/certificate pair to add to the store. + items: + description: Certificate holds a secret name for the TLSStore resource. + properties: + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + required: + - secretName + type: object + type: array + defaultCertificate: + description: DefaultCertificate defines the default certificate configuration. + properties: + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + required: + - secretName + type: object + defaultGeneratedCert: + description: DefaultGeneratedCert defines the default generated certificate + configuration. + properties: + domain: + description: Domain is the domain definition for the DefaultCertificate. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain names. + items: + type: string + type: array + type: object + resolver: + description: Resolver is the name of the resolver that will be + used to issue the DefaultCertificate. + type: string + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/traefik/crds/traefik.io_traefikservices.yaml b/traefik/crds/traefik.io_traefikservices.yaml new file mode 100644 index 000000000..01e28fc5c --- /dev/null +++ b/traefik/crds/traefik.io_traefikservices.yaml @@ -0,0 +1,644 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: traefikservices.traefik.io +spec: + group: traefik.io + names: + kind: TraefikService + listKind: TraefikServiceList + plural: traefikservices + singular: traefikservice + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TraefikService is the CRD implementation of a Traefik Service. + TraefikService object allows to: + - Apply weight to Services on load-balancing + - Mirror traffic on services + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-traefikservice + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TraefikServiceSpec defines the desired state of a TraefikService. + properties: + mirroring: + description: Mirroring defines the Mirroring service configuration. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent to + the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname in the + Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the health + check endpoint. + type: string + port: + description: Port defines the server URL port for the health + check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for the + health check endpoint. + type: string + status: + description: Status defines the expected HTTP status code + of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + maxBodySize: + description: |- + MaxBodySize defines the maximum size allowed for the body of the request. + If the body is larger, the request is not mirrored. + Default value is -1, which means unlimited size. + format: int64 + type: integer + mirrorBody: + description: |- + MirrorBody defines whether the body of the request should be mirrored. + Default value is true. + type: boolean + mirrors: + description: Mirrors defines the list of mirrors where Traefik + will duplicate the traffic. + items: + description: MirrorService holds the mirror configuration. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + percent: + description: |- + Percent defines the part of the traffic to mirror. + Supported values: 0 to 100. + type: integer + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards the + response from the upstream Kubernetes Service to the client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can be + accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can only + be transmitted over an encrypted connection (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + weighted: + description: Weighted defines the Weighted Round Robin configuration. + properties: + services: + description: Services defines the list of Kubernetes Service and/or + TraefikService to load-balance, with weight. + items: + description: Service defines an upstream HTTP service to proxy + traffic to. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + sticky: + description: |- + Sticky defines whether sticky sessions are enabled. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#stickiness-and-load-balancing + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can be + accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can only + be transmitted over an encrypted connection (i.e. HTTPS). + type: boolean + type: object + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true From 2a499fc05f14c239db49b9d07ea4c985326023c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 16 Dec 2024 08:12:34 +0100 Subject: [PATCH 30/32] fix: doc --- traefik/VALUES.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/traefik/VALUES.md b/traefik/VALUES.md index 34dd0045e..efcf1f1b9 100644 --- a/traefik/VALUES.md +++ b/traefik/VALUES.md @@ -24,6 +24,10 @@ A Traefik based Kubernetes ingress controller Kubernetes: `>=1.22.0-0` +| Repository | Name | Version | +|------------|------|---------| +| https://traefik.github.io/charts | traefik-crds | 0.0.1 | + ## Values | Key | Type | Default | Description | @@ -320,6 +324,9 @@ Kubernetes: `>=1.22.0-0` | tracing.safeQueryParams | list | `[]` | By default, all query parameters are redacted. Defines the list of query parameters to not redact. | | tracing.sampleRate | string | `nil` | The proportion of requests to trace, specified between 0.0 and 1.0. Default: 1.0. | | tracing.serviceName | string | `nil` | Service name used in selected backend. Default: traefik. | +| traefik-crds.gateway_api | string | `"{{- tpl \".Values.providers.kubernetesGateway.enabled\" . }}\n"` | | +| traefik-crds.hub | string | `"{{- tpl \"and .Values.hub.token .Values.hub.apimanagement.enabled\"' . }}\n"` | | +| traefik-crds.traefik | bool | `true` | Set all the following to false if you want to manage CRDs your-self | | updateStrategy.rollingUpdate.maxSurge | int | `1` | | | updateStrategy.rollingUpdate.maxUnavailable | int | `0` | | | updateStrategy.type | string | `"RollingUpdate"` | Customize updateStrategy of Deployment or DaemonSet | From 1f5ddd50fb85c21e3be157a65a1651c1935d41d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Mon, 16 Dec 2024 08:14:00 +0100 Subject: [PATCH 31/32] fix: rename gateway api + add enabled flag --- README.md | 2 +- traefik-crds/VALUES.md | 3 +- .../gateway-standard-install.yaml | 0 traefik-crds/kustomization.yaml | 16 + traefik-crds/templates/crds.yaml | 4 +- traefik-crds/tests/crds_test.yaml | 4 +- traefik-crds/values.schema.json | 5 +- traefik-crds/values.yaml | 3 +- traefik/Chart.yaml | 2 +- traefik/VALUES.md | 5 + .../crds/gateway-standard-install.yaml | 0 .../hub.traefik.io_accesscontrolpolicies.yaml | 368 ++++++++++++++++++ traefik/crds/hub.traefik.io_aiservices.yaml | 245 ++++++++++++ traefik/crds/hub.traefik.io_apiaccesses.yaml | 190 +++++++++ traefik/crds/hub.traefik.io_apibundles.yaml | 125 ++++++ .../crds/hub.traefik.io_apicatalogitems.yaml | 184 +++++++++ traefik/crds/hub.traefik.io_apiplans.yaml | 103 +++++ traefik/crds/hub.traefik.io_apiportals.yaml | 139 +++++++ .../crds/hub.traefik.io_apiratelimits.yaml | 166 ++++++++ traefik/crds/hub.traefik.io_apis.yaml | 190 +++++++++ traefik/crds/hub.traefik.io_apiversions.yaml | 194 +++++++++ .../hub.traefik.io_managedsubscriptions.yaml | 204 ++++++++++ traefik/values.schema.json | 17 +- traefik/values.yaml | 7 +- 24 files changed, 2162 insertions(+), 14 deletions(-) rename traefik-crds/crds-files/{gateway_api => gatewayAPI}/gateway-standard-install.yaml (100%) rename traefik-crds/crds-files/gateway_api/gateway-standard-install-v1.2.0.yaml => traefik/crds/gateway-standard-install.yaml (100%) create mode 100644 traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml create mode 100644 traefik/crds/hub.traefik.io_aiservices.yaml create mode 100644 traefik/crds/hub.traefik.io_apiaccesses.yaml create mode 100644 traefik/crds/hub.traefik.io_apibundles.yaml create mode 100644 traefik/crds/hub.traefik.io_apicatalogitems.yaml create mode 100644 traefik/crds/hub.traefik.io_apiplans.yaml create mode 100644 traefik/crds/hub.traefik.io_apiportals.yaml create mode 100644 traefik/crds/hub.traefik.io_apiratelimits.yaml create mode 100644 traefik/crds/hub.traefik.io_apis.yaml create mode 100644 traefik/crds/hub.traefik.io_apiversions.yaml create mode 100644 traefik/crds/hub.traefik.io_managedsubscriptions.yaml diff --git a/README.md b/README.md index 69b738df7..3d7293aa7 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ If you still want to manage CRDs your self, it can be opt-out: ```bash # Upgrade Traefik and skip all CRDs installation -helm upgrade traefik traefik/traefik --set traefik-crds.traefik=false --set traefik-crds.hub=false --set traefik-crds.gateway_api=false +helm upgrade traefik traefik/traefik --set traefik-crds.enabled=true --set traefik-crds.traefik=false --set traefik-crds.hub=false --set traefik-crds.gatewayAPI=false ``` ### Upgrade up to 27.X diff --git a/traefik-crds/VALUES.md b/traefik-crds/VALUES.md index 68d56e701..a7ddb2a3f 100644 --- a/traefik-crds/VALUES.md +++ b/traefik-crds/VALUES.md @@ -29,7 +29,8 @@ Kubernetes: `>=1.22.0-0` | Key | Type | Default | Description | |-----|------|---------|-------------| | deleteOnUninstall | bool | `false` | | -| gateway_api | bool | `false` | | +| enabled | bool | `true` | | +| gatewayAPI | bool | `false` | | | global | string | `nil` | | | hub | bool | `false` | | | traefik | bool | `false` | | diff --git a/traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml b/traefik-crds/crds-files/gatewayAPI/gateway-standard-install.yaml similarity index 100% rename from traefik-crds/crds-files/gateway_api/gateway-standard-install.yaml rename to traefik-crds/crds-files/gatewayAPI/gateway-standard-install.yaml diff --git a/traefik-crds/kustomization.yaml b/traefik-crds/kustomization.yaml index a615713e7..805135a05 100644 --- a/traefik-crds/kustomization.yaml +++ b/traefik-crds/kustomization.yaml @@ -2,6 +2,7 @@ kind: Kustomization apiVersion: kustomize.config.k8s.io/v1beta1 resources: +<<<<<<< HEAD # curl -o crds-files/gateway_api/gateway-standard-install.yaml -L https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml - crds-files/gateway_api/gateway-standard-install.yaml - crds-files/hub.traefik.io_accesscontrolpolicies.yaml @@ -15,6 +16,21 @@ resources: - crds-files/hub.traefik.io_apis.yaml - crds-files/hub.traefik.io_apiversions.yaml - crds-files/hub.traefik.io_managedsubscriptions.yaml +======= + # curl -o gateway-standard-install-v1.2.0.yaml -L https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml + - crds-files/gatewayAPI/gateway-standard-install-v1.2.0.yaml + - crds-files/hub/hub.traefik.io_accesscontrolpolicies.yaml + - crds-files/hub/hub.traefik.io_aiservices.yaml + - crds-files/hub/hub.traefik.io_apiaccesses.yaml + - crds-files/hub/hub.traefik.io_apibundles.yaml + - crds-files/hub/hub.traefik.io_apicatalogitems.yaml + - crds-files/hub/hub.traefik.io_apiplans.yaml + - crds-files/hub/hub.traefik.io_apiportals.yaml + - crds-files/hub/hub.traefik.io_apiratelimits.yaml + - crds-files/hub/hub.traefik.io_apis.yaml + - crds-files/hub/hub.traefik.io_apiversions.yaml + - crds-files/hub/hub.traefik.io_managedsubscriptions.yaml +>>>>>>> b296543 (fix: rename gateway api + add enabled flag) - crds-files/traefik/traefik.io_ingressroutes.yaml - crds-files/traefik/traefik.io_ingressroutetcps.yaml - crds-files/traefik/traefik.io_ingressrouteudps.yaml diff --git a/traefik-crds/templates/crds.yaml b/traefik-crds/templates/crds.yaml index 9440dd591..859453ae7 100644 --- a/traefik-crds/templates/crds.yaml +++ b/traefik-crds/templates/crds.yaml @@ -6,6 +6,6 @@ {{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/hub/*.yaml") }} {{- end }} -{{- if eq (.Values.gateway_api | toString) "true" -}} -{{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/gateway_api/*.yaml") }} +{{- if eq (.Values.gatewayAPI | toString) "true" -}} +{{ include "traefik-crds.render-crds" (dict "scope" . "path" "crds-files/gatewayAPI/*.yaml") }} {{- end }} diff --git a/traefik-crds/tests/crds_test.yaml b/traefik-crds/tests/crds_test.yaml index ce1ce07c1..c9dbe2ec6 100644 --- a/traefik-crds/tests/crds_test.yaml +++ b/traefik-crds/tests/crds_test.yaml @@ -45,7 +45,7 @@ tests: - it: should have all Gateway API crds set: - gateway_api: true + gatewayAPI: true asserts: - hasDocuments: count: 5 @@ -63,7 +63,7 @@ tests: - it: should have all Gateway API crds without helm keep resource policy set: - gateway_api: true + gatewayAPI: true deleteOnUninstall: true asserts: - hasDocuments: diff --git a/traefik-crds/values.schema.json b/traefik-crds/values.schema.json index 99668a020..c79af9218 100644 --- a/traefik-crds/values.schema.json +++ b/traefik-crds/values.schema.json @@ -7,7 +7,10 @@ "deleteOnUninstall": { "type": "boolean" }, - "gateway_api": { + "enabled": { + "type": "boolean" + }, + "gatewayAPI": { "default": false, "type": [ "string", diff --git a/traefik-crds/values.yaml b/traefik-crds/values.yaml index bc5f1b94f..35b12a591 100644 --- a/traefik-crds/values.yaml +++ b/traefik-crds/values.yaml @@ -1,5 +1,6 @@ global: # @schema type:[object, null]; additionalProperties: true +enabled: true traefik: false -gateway_api: false # @schema type:[string, boolean]; default: false +gatewayAPI: false # @schema type:[string, boolean]; default: false hub: false # @schema type:[string, boolean]; default: false deleteOnUninstall: false diff --git a/traefik/Chart.yaml b/traefik/Chart.yaml index 827dcd369..55c0c6896 100644 --- a/traefik/Chart.yaml +++ b/traefik/Chart.yaml @@ -31,4 +31,4 @@ dependencies: - name: traefik-crds version: 0.0.1 repository: https://traefik.github.io/charts - condition: or traefik-crds.traefik traefik-crds.hub traefik-crds.gateway_api + condition: traefik-crds.enabled diff --git a/traefik/VALUES.md b/traefik/VALUES.md index efcf1f1b9..41df7427e 100644 --- a/traefik/VALUES.md +++ b/traefik/VALUES.md @@ -321,10 +321,15 @@ Kubernetes: `>=1.22.0-0` | tracing.otlp.http.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | | tracing.otlp.http.tls.insecureSkipVerify | bool | `false` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | | tracing.otlp.http.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | +<<<<<<< HEAD | tracing.safeQueryParams | list | `[]` | By default, all query parameters are redacted. Defines the list of query parameters to not redact. | | tracing.sampleRate | string | `nil` | The proportion of requests to trace, specified between 0.0 and 1.0. Default: 1.0. | | tracing.serviceName | string | `nil` | Service name used in selected backend. Default: traefik. | | traefik-crds.gateway_api | string | `"{{- tpl \".Values.providers.kubernetesGateway.enabled\" . }}\n"` | | +======= +| traefik-crds.enabled | bool | `false` | Set it to true to opt-in CRD management | +| traefik-crds.gatewayAPI | string | `"{{- tpl \".Values.providers.kubernetesGateway.enabled\" . }}\n"` | | +>>>>>>> b296543 (fix: rename gateway api + add enabled flag) | traefik-crds.hub | string | `"{{- tpl \"and .Values.hub.token .Values.hub.apimanagement.enabled\"' . }}\n"` | | | traefik-crds.traefik | bool | `true` | Set all the following to false if you want to manage CRDs your-self | | updateStrategy.rollingUpdate.maxSurge | int | `1` | | diff --git a/traefik-crds/crds-files/gateway_api/gateway-standard-install-v1.2.0.yaml b/traefik/crds/gateway-standard-install.yaml similarity index 100% rename from traefik-crds/crds-files/gateway_api/gateway-standard-install-v1.2.0.yaml rename to traefik/crds/gateway-standard-install.yaml diff --git a/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml b/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml new file mode 100644 index 000000000..821f969b6 --- /dev/null +++ b/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml @@ -0,0 +1,368 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: accesscontrolpolicies.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: AccessControlPolicy + listKind: AccessControlPolicyList + plural: accesscontrolpolicies + singular: accesscontrolpolicy + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: AccessControlPolicy defines an access control policy. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AccessControlPolicySpec configures an access control policy. + properties: + apiKey: + description: AccessControlPolicyAPIKey configure an APIKey control + policy. + properties: + forwardHeaders: + additionalProperties: + type: string + description: ForwardHeaders instructs the middleware to forward + key metadata as header values upon successful authentication. + type: object + keySource: + description: KeySource defines how to extract API keys from requests. + properties: + cookie: + description: Cookie is the name of a cookie. + type: string + header: + description: Header is the name of a header. + type: string + headerAuthScheme: + description: |- + HeaderAuthScheme sets an optional auth scheme when Header is set to "Authorization". + If set, this scheme is removed from the token, and all requests not including it are dropped. + type: string + query: + description: Query is the name of a query parameter. + type: string + type: object + keys: + description: Keys define the set of authorized keys to access + a protected resource. + items: + description: AccessControlPolicyAPIKeyKey defines an API key. + properties: + id: + description: ID is the unique identifier of the key. + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds arbitrary metadata for this + key, can be used by ForwardHeaders. + type: object + value: + description: Value is the SHAKE-256 hash (using 64 bytes) + of the API key. + type: string + required: + - id + - value + type: object + type: array + required: + - keySource + type: object + basicAuth: + description: AccessControlPolicyBasicAuth holds the HTTP basic authentication + configuration. + properties: + forwardUsernameHeader: + type: string + realm: + type: string + stripAuthorizationHeader: + type: boolean + users: + items: + type: string + type: array + type: object + jwt: + description: AccessControlPolicyJWT configures a JWT access control + policy. + properties: + claims: + type: string + forwardHeaders: + additionalProperties: + type: string + type: object + jwksFile: + type: string + jwksUrl: + type: string + publicKey: + type: string + signingSecret: + type: string + signingSecretBase64Encoded: + type: boolean + stripAuthorizationHeader: + type: boolean + tokenQueryKey: + type: string + type: object + oAuthIntro: + description: AccessControlOAuthIntro configures an OAuth 2.0 Token + Introspection access control policy. + properties: + claims: + type: string + clientConfig: + description: AccessControlOAuthIntroClientConfig configures the + OAuth 2.0 client for issuing token introspection requests. + properties: + headers: + additionalProperties: + type: string + description: Headers to set when sending requests to the Authorization + Server. + type: object + maxRetries: + default: 3 + description: MaxRetries defines the number of retries for + introspection requests. + type: integer + timeoutSeconds: + default: 5 + description: TimeoutSeconds configures the maximum amount + of seconds to wait before giving up on requests. + type: integer + tls: + description: TLS configures TLS communication with the Authorization + Server. + properties: + ca: + description: CA sets the CA bundle used to sign the Authorization + Server certificate. + type: string + insecureSkipVerify: + description: |- + InsecureSkipVerify skips the Authorization Server certificate validation. + For testing purposes only, do not use in production. + type: boolean + type: object + tokenTypeHint: + description: |- + TokenTypeHint is a hint to pass to the Authorization Server. + See https://tools.ietf.org/html/rfc7662#section-2.1 for more information. + type: string + url: + description: URL of the Authorization Server. + type: string + required: + - url + type: object + forwardHeaders: + additionalProperties: + type: string + type: object + tokenSource: + description: |- + TokenSource describes how to extract tokens from HTTP requests. + If multiple sources are set, the order is the following: header > query > cookie. + properties: + cookie: + description: Cookie is the name of a cookie. + type: string + header: + description: Header is the name of a header. + type: string + headerAuthScheme: + description: |- + HeaderAuthScheme sets an optional auth scheme when Header is set to "Authorization". + If set, this scheme is removed from the token, and all requests not including it are dropped. + type: string + query: + description: Query is the name of a query parameter. + type: string + type: object + required: + - clientConfig + - tokenSource + type: object + oidc: + description: AccessControlPolicyOIDC holds the OIDC authentication + configuration. + properties: + authParams: + additionalProperties: + type: string + type: object + claims: + type: string + clientId: + type: string + disableAuthRedirectionPaths: + items: + type: string + type: array + forwardHeaders: + additionalProperties: + type: string + type: object + issuer: + type: string + logoutUrl: + type: string + redirectUrl: + type: string + scopes: + items: + type: string + type: array + secret: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + session: + description: Session holds session configuration. + properties: + domain: + type: string + path: + type: string + refresh: + type: boolean + sameSite: + type: string + secure: + type: boolean + type: object + stateCookie: + description: StateCookie holds state cookie configuration. + properties: + domain: + type: string + path: + type: string + sameSite: + type: string + secure: + type: boolean + type: object + type: object + oidcGoogle: + description: AccessControlPolicyOIDCGoogle holds the Google OIDC authentication + configuration. + properties: + authParams: + additionalProperties: + type: string + type: object + clientId: + type: string + emails: + description: Emails are the allowed emails to connect. + items: + type: string + minItems: 1 + type: array + forwardHeaders: + additionalProperties: + type: string + type: object + logoutUrl: + type: string + redirectUrl: + type: string + secret: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + session: + description: Session holds session configuration. + properties: + domain: + type: string + path: + type: string + refresh: + type: boolean + sameSite: + type: string + secure: + type: boolean + type: object + stateCookie: + description: StateCookie holds state cookie configuration. + properties: + domain: + type: string + path: + type: string + sameSite: + type: string + secure: + type: boolean + type: object + type: object + type: object + status: + description: The current status of this access control policy. + properties: + specHash: + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_aiservices.yaml b/traefik/crds/hub.traefik.io_aiservices.yaml new file mode 100644 index 000000000..9fc481387 --- /dev/null +++ b/traefik/crds/hub.traefik.io_aiservices.yaml @@ -0,0 +1,245 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: aiservices.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: AIService + listKind: AIServiceList + plural: aiservices + singular: aiservice + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: AIService is a Kubernetes-like Service to interact with a text-based + LLM provider. It defines the parameters and credentials required to interact + with various LLM providers. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this AIService. + properties: + anthropic: + description: Anthropic configures Anthropic backend. + properties: + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + token: + type: string + required: + - token + type: object + azureOpenai: + description: AzureOpenAI configures AzureOpenAI. + properties: + apiKey: + type: string + baseUrl: + type: string + deploymentName: + type: string + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + required: + - apiKey + - baseUrl + - deploymentName + type: object + bedrock: + description: Bedrock configures Bedrock backend. + properties: + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + region: + type: string + systemMessage: + type: boolean + type: object + cohere: + description: Cohere configures Cohere backend. + properties: + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + token: + type: string + required: + - token + type: object + gemini: + description: Gemini configures Gemini backend. + properties: + apiKey: + type: string + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + required: + - apiKey + type: object + mistral: + description: Mistral configures Mistral AI backend. + properties: + apiKey: + type: string + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + required: + - apiKey + type: object + ollama: + description: Ollama configures Ollama backend. + properties: + baseUrl: + type: string + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + required: + - baseUrl + type: object + openai: + description: OpenAI configures OpenAI. + properties: + model: + type: string + params: + description: Params holds the LLM hyperparameters. + properties: + frequencyPenalty: + type: number + maxTokens: + type: integer + presencePenalty: + type: number + temperature: + type: number + topP: + type: number + type: object + token: + type: string + required: + - token + type: object + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apiaccesses.yaml b/traefik/crds/hub.traefik.io_apiaccesses.yaml new file mode 100644 index 000000000..fef19fdbc --- /dev/null +++ b/traefik/crds/hub.traefik.io_apiaccesses.yaml @@ -0,0 +1,190 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiaccesses.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIAccess + listKind: APIAccessList + plural: apiaccesses + singular: apiaccess + scope: Namespaced + versions: + - deprecated: true + deprecationWarning: APIAccess is deprecated in favor of APICatalogItems and ManagedSubscription + name: v1alpha1 + schema: + openAPIV3Schema: + description: APIAccess defines who can access to a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIAccess. + properties: + apiBundles: + description: |- + APIBundles defines a set of APIBundle that will be accessible to the configured audience. + Multiple APIAccesses can select the same APIBundles. + items: + description: APIBundleReference references an APIBundle. + properties: + name: + description: Name of the APIBundle. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apiBundles + rule: self.all(x, self.exists_one(y, x.name == y.name)) + apiPlan: + description: APIPlan defines which APIPlan will be used. + properties: + name: + description: Name of the APIPlan. + maxLength: 253 + type: string + required: + - name + type: object + apiSelector: + description: |- + APISelector selects the APIs that will be accessible to the configured audience. + Multiple APIAccesses can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be accessible to the configured audience. + Multiple APIAccesses can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + everyone: + description: Everyone indicates that all users will have access to + the selected APIs. + type: boolean + groups: + description: Groups are the consumer groups that will gain access + to the selected APIs. + items: + type: string + type: array + operationFilter: + description: |- + OperationFilter specifies the allowed operations on APIs and APIVersions. + If not set, all operations are available. + An empty OperationFilter prohibits all operations. + properties: + include: + description: Include defines the names of OperationSets that will + be accessible. + items: + type: string + maxItems: 100 + type: array + type: object + weight: + description: Weight specifies the evaluation order of the plan. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + type: object + x-kubernetes-validations: + - message: groups and everyone are mutually exclusive + rule: '(has(self.everyone) && has(self.groups)) ? !(self.everyone && + self.groups.size() > 0) : true' + status: + description: The current status of this APIAccess. + properties: + hash: + description: Hash is a hash representing the APIAccess. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apibundles.yaml b/traefik/crds/hub.traefik.io_apibundles.yaml new file mode 100644 index 000000000..a45a0b137 --- /dev/null +++ b/traefik/crds/hub.traefik.io_apibundles.yaml @@ -0,0 +1,125 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apibundles.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIBundle + listKind: APIBundleList + plural: apibundles + singular: apibundle + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIBundle defines a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIBundle. + properties: + apiSelector: + description: |- + APISelector selects the APIs that will be accessible to the configured audience. + Multiple APIBundles can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be accessible to the configured audience. + Multiple APIBundles can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + type: object + status: + description: The current status of this APIBundle. + properties: + hash: + description: Hash is a hash representing the APIBundle. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apicatalogitems.yaml b/traefik/crds/hub.traefik.io_apicatalogitems.yaml new file mode 100644 index 000000000..387e72aa4 --- /dev/null +++ b/traefik/crds/hub.traefik.io_apicatalogitems.yaml @@ -0,0 +1,184 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apicatalogitems.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APICatalogItem + listKind: APICatalogItemList + plural: apicatalogitems + singular: apicatalogitem + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APICatalogItem defines APIs that will be part of the API catalog + on the portal. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APICatalogItem. + properties: + apiBundles: + description: |- + APIBundles defines a set of APIBundle that will be visible to the configured audience. + Multiple APICatalogItem can select the same APIBundles. + items: + description: APIBundleReference references an APIBundle. + properties: + name: + description: Name of the APIBundle. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apiBundles + rule: self.all(x, self.exists_one(y, x.name == y.name)) + apiPlan: + description: |- + APIPlan defines which APIPlan will be available. + If multiple APICatalogItem specify the same API with different APIPlan, the API consumer will be able to pick + a plan from this list. + properties: + name: + description: Name of the APIPlan. + maxLength: 253 + type: string + required: + - name + type: object + apiSelector: + description: |- + APISelector selects the APIs that will be visible to the configured audience. + Multiple APICatalogItem can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be visible to the configured audience. + Multiple APICatalogItem can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + everyone: + description: Everyone indicates that all users will see these APIs. + type: boolean + groups: + description: Groups are the consumer groups that will see the APIs. + items: + type: string + type: array + operationFilter: + description: |- + OperationFilter specifies the visible operations on APIs and APIVersions. + If not set, all operations are available. + An empty OperationFilter prohibits all operations. + properties: + include: + description: Include defines the names of OperationSets that will + be accessible. + items: + type: string + maxItems: 100 + type: array + type: object + type: object + x-kubernetes-validations: + - message: groups and everyone are mutually exclusive + rule: '(has(self.everyone) && has(self.groups)) ? !(self.everyone && + self.groups.size() > 0) : true' + status: + description: The current status of this APICatalogItem. + properties: + hash: + description: Hash is a hash representing the APICatalogItem. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apiplans.yaml b/traefik/crds/hub.traefik.io_apiplans.yaml new file mode 100644 index 000000000..92e1b9b5c --- /dev/null +++ b/traefik/crds/hub.traefik.io_apiplans.yaml @@ -0,0 +1,103 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiplans.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIPlan + listKind: APIPlanList + plural: apiplans + singular: apiplan + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIPlan defines API Plan policy. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIPlan. + properties: + description: + description: Description describes the plan. + type: string + quota: + description: Quota defines the quota policy. + properties: + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 9999h + rule: self >= duration('1s') && self <= duration('9999h') + required: + - limit + type: object + rateLimit: + description: RateLimit defines the rate limit policy. + properties: + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 1h + rule: self >= duration('1s') && self <= duration('1h') + required: + - limit + type: object + title: + description: Title is the human-readable name of the plan. + type: string + required: + - title + type: object + status: + description: The current status of this APIPlan. + properties: + hash: + description: Hash is a hash representing the APIPlan. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apiportals.yaml b/traefik/crds/hub.traefik.io_apiportals.yaml new file mode 100644 index 000000000..bc0417016 --- /dev/null +++ b/traefik/crds/hub.traefik.io_apiportals.yaml @@ -0,0 +1,139 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiportals.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIPortal + listKind: APIPortalList + plural: apiportals + singular: apiportal + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIPortal defines a developer portal for accessing the documentation + of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIPortal. + properties: + description: + description: Description of the APIPortal. + type: string + title: + description: Title is the public facing name of the APIPortal. + type: string + trustedUrls: + description: TrustedURLs are the urls that are trusted by the OAuth + 2.0 authorization server. + items: + type: string + maxItems: 1 + minItems: 1 + type: array + x-kubernetes-validations: + - message: must be a valid URLs + rule: self.all(x, isURL(x)) + ui: + description: UI holds the UI customization options. + properties: + logoUrl: + description: LogoURL is the public URL of the logo. + type: string + type: object + required: + - trustedUrls + type: object + status: + description: The current status of this APIPortal. + properties: + hash: + description: Hash is a hash representing the APIPortal. + type: string + oidc: + description: OIDC is the OIDC configuration for accessing the exposed + APIPortal WebUI. + properties: + clientId: + description: ClientID is the OIDC ClientID for accessing the exposed + APIPortal WebUI. + type: string + companyClaim: + description: CompanyClaim is the name of the JWT claim containing + the user company. + type: string + emailClaim: + description: EmailClaim is the name of the JWT claim containing + the user email. + type: string + firstnameClaim: + description: FirstnameClaim is the name of the JWT claim containing + the user firstname. + type: string + generic: + description: Generic indicates whether or not the APIPortal authentication + relies on Generic OIDC. + type: boolean + groupsClaim: + description: GroupsClaim is the name of the JWT claim containing + the user groups. + type: string + issuer: + description: Issuer is the OIDC issuer for accessing the exposed + APIPortal WebUI. + type: string + lastnameClaim: + description: LastnameClaim is the name of the JWT claim containing + the user lastname. + type: string + scopes: + description: Scopes is the OIDC scopes for getting user attributes + during the authentication to the exposed APIPortal WebUI. + type: string + secretName: + description: SecretName is the name of the secret containing the + OIDC ClientSecret for accessing the exposed APIPortal WebUI. + type: string + syncedAttributes: + description: SyncedAttributes configure the user attributes to + sync. + items: + type: string + type: array + userIdClaim: + description: UserIDClaim is the name of the JWT claim containing + the user ID. + type: string + type: object + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apiratelimits.yaml b/traefik/crds/hub.traefik.io_apiratelimits.yaml new file mode 100644 index 000000000..8e328d3c5 --- /dev/null +++ b/traefik/crds/hub.traefik.io_apiratelimits.yaml @@ -0,0 +1,166 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiratelimits.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIRateLimit + listKind: APIRateLimitList + plural: apiratelimits + singular: apiratelimit + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIRateLimit defines how group of consumers are rate limited + on a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIRateLimit. + properties: + apiSelector: + description: |- + APISelector selects the APIs that will be rate limited. + Multiple APIRateLimits can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be rate limited. + Multiple APIRateLimits can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + everyone: + description: |- + Everyone indicates that all users will, by default, be rate limited with this configuration. + If an APIRateLimit explicitly target a group, the default rate limit will be ignored. + type: boolean + groups: + description: |- + Groups are the consumer groups that will be rate limited. + Multiple APIRateLimits can target the same set of consumer groups, the most restrictive one applies. + When a consumer belongs to multiple groups, the least restrictive APIRateLimit applies. + items: + type: string + type: array + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 1h + rule: self >= duration('1s') && self <= duration('1h') + strategy: + description: |- + Strategy defines how the bucket state will be synchronized between the different Traefik Hub instances. + It can be, either "local" or "distributed". + enum: + - local + - distributed + type: string + required: + - limit + type: object + x-kubernetes-validations: + - message: groups and everyone are mutually exclusive + rule: '(has(self.everyone) && has(self.groups)) ? !(self.everyone && + self.groups.size() > 0) : true' + status: + description: The current status of this APIRateLimit. + properties: + hash: + description: Hash is a hash representing the APIRateLimit. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apis.yaml b/traefik/crds/hub.traefik.io_apis.yaml new file mode 100644 index 000000000..a7b9e5e60 --- /dev/null +++ b/traefik/crds/hub.traefik.io_apis.yaml @@ -0,0 +1,190 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apis.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: API + listKind: APIList + plural: apis + singular: api + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + API defines an HTTP interface that is exposed to external clients. It specifies the supported versions + and provides instructions for accessing its documentation. Once instantiated, an API object is associated + with an Ingress, IngressRoute, or HTTPRoute resource, enabling the exposure of the described API to the outside world. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APISpec describes the API. + properties: + openApiSpec: + description: OpenAPISpec defines the API contract as an OpenAPI specification. + properties: + operationSets: + description: OperationSets defines the sets of operations to be + referenced for granular filtering in APIAccesses. + items: + description: |- + OperationSet gives a name to a set of matching OpenAPI operations. + This set of operations can then be referenced for granular filtering in APIAccesses. + properties: + matchers: + description: Matchers defines a list of alternative rules + for matching OpenAPI operations. + items: + description: OperationMatcher defines criteria for matching + an OpenAPI operation. + minProperties: 1 + properties: + methods: + description: Methods specifies the HTTP methods to + be included for selection. + items: + type: string + maxItems: 10 + type: array + path: + description: Path specifies the exact path of the + operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathPrefix: + description: PathPrefix specifies the path prefix + of the operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathRegex: + description: PathRegex specifies a regular expression + pattern for matching operations based on their paths. + type: string + type: object + x-kubernetes-validations: + - message: path, pathPrefix and pathRegex are mutually + exclusive + rule: '[has(self.path), has(self.pathPrefix), has(self.pathRegex)].filter(x, + x).size() <= 1' + maxItems: 100 + minItems: 1 + type: array + name: + description: Name is the name of the OperationSet to reference + in APIAccesses. + maxLength: 253 + type: string + required: + - matchers + - name + type: object + maxItems: 100 + type: array + override: + description: Override holds data used to override OpenAPI specification. + properties: + servers: + items: + properties: + url: + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + required: + - url + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - servers + type: object + path: + description: |- + Path specifies the endpoint path within the Kubernetes Service where the OpenAPI specification can be obtained. + The Service queried is determined by the associated Ingress, IngressRoute, or HTTPRoute resource to which the API is attached. + It's important to note that this option is incompatible if the Ingress or IngressRoute specifies multiple backend services. + The Path must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + url: + description: |- + URL is a Traefik Hub agent accessible URL for obtaining the OpenAPI specification. + The URL must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + type: object + x-kubernetes-validations: + - message: path or url must be defined + rule: has(self.path) || has(self.url) + versions: + description: Versions are the different APIVersions available. + items: + description: APIVersionRef references an APIVersion. + properties: + name: + description: Name of the APIVersion. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + minItems: 1 + type: array + type: object + status: + description: The current status of this API. + properties: + hash: + description: Hash is a hash representing the API. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/crds/hub.traefik.io_apiversions.yaml b/traefik/crds/hub.traefik.io_apiversions.yaml new file mode 100644 index 000000000..97184effe --- /dev/null +++ b/traefik/crds/hub.traefik.io_apiversions.yaml @@ -0,0 +1,194 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiversions.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIVersion + listKind: APIVersionList + plural: apiversions + singular: apiversion + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.title + name: Title + type: string + - jsonPath: .spec.release + name: Release + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: APIVersion defines a version of an API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIVersion. + properties: + openApiSpec: + description: OpenAPISpec defines the API contract as an OpenAPI specification. + properties: + operationSets: + description: OperationSets defines the sets of operations to be + referenced for granular filtering in APIAccesses. + items: + description: |- + OperationSet gives a name to a set of matching OpenAPI operations. + This set of operations can then be referenced for granular filtering in APIAccesses. + properties: + matchers: + description: Matchers defines a list of alternative rules + for matching OpenAPI operations. + items: + description: OperationMatcher defines criteria for matching + an OpenAPI operation. + minProperties: 1 + properties: + methods: + description: Methods specifies the HTTP methods to + be included for selection. + items: + type: string + maxItems: 10 + type: array + path: + description: Path specifies the exact path of the + operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathPrefix: + description: PathPrefix specifies the path prefix + of the operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathRegex: + description: PathRegex specifies a regular expression + pattern for matching operations based on their paths. + type: string + type: object + x-kubernetes-validations: + - message: path, pathPrefix and pathRegex are mutually + exclusive + rule: '[has(self.path), has(self.pathPrefix), has(self.pathRegex)].filter(x, + x).size() <= 1' + maxItems: 100 + minItems: 1 + type: array + name: + description: Name is the name of the OperationSet to reference + in APIAccesses. + maxLength: 253 + type: string + required: + - matchers + - name + type: object + maxItems: 100 + type: array + override: + description: Override holds data used to override OpenAPI specification. + properties: + servers: + items: + properties: + url: + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + required: + - url + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - servers + type: object + path: + description: |- + Path specifies the endpoint path within the Kubernetes Service where the OpenAPI specification can be obtained. + The Service queried is determined by the associated Ingress, IngressRoute, or HTTPRoute resource to which the API is attached. + It's important to note that this option is incompatible if the Ingress or IngressRoute specifies multiple backend services. + The Path must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + url: + description: |- + URL is a Traefik Hub agent accessible URL for obtaining the OpenAPI specification. + The URL must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + type: object + x-kubernetes-validations: + - message: path or url must be defined + rule: has(self.path) || has(self.url) + release: + description: |- + Release is the version number of the API. + This value must follow the SemVer format: https://semver.org/ + maxLength: 100 + type: string + x-kubernetes-validations: + - message: must be a valid semver version + rule: self.matches(r"""^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$""") + title: + description: Title is the public facing name of the APIVersion. + type: string + required: + - release + type: object + status: + description: The current status of this APIVersion. + properties: + hash: + description: Hash is a hash representing the APIVersion. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/traefik/crds/hub.traefik.io_managedsubscriptions.yaml b/traefik/crds/hub.traefik.io_managedsubscriptions.yaml new file mode 100644 index 000000000..ca52b4f83 --- /dev/null +++ b/traefik/crds/hub.traefik.io_managedsubscriptions.yaml @@ -0,0 +1,204 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: managedsubscriptions.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: ManagedSubscription + listKind: ManagedSubscriptionList + plural: managedsubscriptions + singular: managedsubscription + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ManagedSubscription defines a Subscription managed by the API manager as the result of a pre-negotiation with its + API consumers. This subscription grant consuming access to a set of APIs to a set of Applications. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this ManagedSubscription. + properties: + apiBundles: + description: |- + APIBundles defines a set of APIBundle that will be accessible. + Multiple ManagedSubscriptions can select the same APIBundles. + items: + description: APIBundleReference references an APIBundle. + properties: + name: + description: Name of the APIBundle. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apiBundles + rule: self.all(x, self.exists_one(y, x.name == y.name)) + apiPlan: + description: APIPlan defines which APIPlan will be used. + properties: + name: + description: Name of the APIPlan. + maxLength: 253 + type: string + required: + - name + type: object + apiSelector: + description: |- + APISelector selects the APIs that will be accessible. + Multiple ManagedSubscriptions can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be accessible. + Multiple ManagedSubscriptions can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + applications: + description: |- + Applications references the Applications that will gain access to the specified APIs. + Multiple ManagedSubscriptions can select the same AppID. + items: + description: ApplicationReference references an Application. + properties: + appId: + description: |- + AppID is the public identifier of the application. + In the case of OIDC, it corresponds to the clientId. + maxLength: 253 + type: string + required: + - appId + type: object + maxItems: 100 + minItems: 1 + type: array + claims: + description: Claims specifies an expression that validate claims in + order to authorize the request. + type: string + operationFilter: + description: |- + OperationFilter specifies the allowed operations on APIs and APIVersions. + If not set, all operations are available. + An empty OperationFilter prohibits all operations. + properties: + include: + description: Include defines the names of OperationSets that will + be accessible. + items: + type: string + maxItems: 100 + type: array + type: object + weight: + description: |- + Weight specifies the evaluation order of the APIPlan. + When multiple ManagedSubscriptions targets the same API and Application with different APIPlan, + the APIPlan with the highest weight will be enforced. If weights are equal, alphabetical order is used. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + required: + - applications + type: object + status: + description: The current status of this ManagedSubscription. + properties: + hash: + description: Hash is a hash representing the ManagedSubscription. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/traefik/values.schema.json b/traefik/values.schema.json index 22878a9f5..d591b7463 100644 --- a/traefik/values.schema.json +++ b/traefik/values.schema.json @@ -1674,11 +1674,22 @@ }, "traefik-crds": { "properties": { - "gateway_api": { - "type": "string" + "enabled": { + "type": "boolean" + }, + "gatewayAPI": { + "default": false, + "type": [ + "string", + "boolean" + ] }, "hub": { - "type": "string" + "default": false, + "type": [ + "string", + "boolean" + ] }, "traefik": { "type": "boolean" diff --git a/traefik/values.yaml b/traefik/values.yaml index 510526271..48c06b1e9 100644 --- a/traefik/values.yaml +++ b/traefik/values.yaml @@ -967,9 +967,12 @@ hub: sendlogs: # @schema type:[boolean, null] traefik-crds: + # -- Set it to true to opt-in CRD management + enabled: false + # -- Set all the following to false if you want to manage CRDs your-self traefik: true - hub: | + hub: | # @schema type:[string, boolean]; default: false {{- tpl "and .Values.hub.token .Values.hub.apimanagement.enabled"' . }} - gateway_api: | + gatewayAPI: | # @schema type:[string, boolean]; default: false {{- tpl ".Values.providers.kubernetesGateway.enabled" . }} From a21dae9b83242fd8d9545fa93b1d53e481f66f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20BUISSON?= Date: Tue, 17 Dec 2024 07:53:56 +0100 Subject: [PATCH 32/32] fix: doc --- traefik/VALUES.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/traefik/VALUES.md b/traefik/VALUES.md index 41df7427e..850188553 100644 --- a/traefik/VALUES.md +++ b/traefik/VALUES.md @@ -321,15 +321,11 @@ Kubernetes: `>=1.22.0-0` | tracing.otlp.http.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | | tracing.otlp.http.tls.insecureSkipVerify | bool | `false` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | | tracing.otlp.http.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | -<<<<<<< HEAD | tracing.safeQueryParams | list | `[]` | By default, all query parameters are redacted. Defines the list of query parameters to not redact. | | tracing.sampleRate | string | `nil` | The proportion of requests to trace, specified between 0.0 and 1.0. Default: 1.0. | | tracing.serviceName | string | `nil` | Service name used in selected backend. Default: traefik. | -| traefik-crds.gateway_api | string | `"{{- tpl \".Values.providers.kubernetesGateway.enabled\" . }}\n"` | | -======= | traefik-crds.enabled | bool | `false` | Set it to true to opt-in CRD management | | traefik-crds.gatewayAPI | string | `"{{- tpl \".Values.providers.kubernetesGateway.enabled\" . }}\n"` | | ->>>>>>> b296543 (fix: rename gateway api + add enabled flag) | traefik-crds.hub | string | `"{{- tpl \"and .Values.hub.token .Values.hub.apimanagement.enabled\"' . }}\n"` | | | traefik-crds.traefik | bool | `true` | Set all the following to false if you want to manage CRDs your-self | | updateStrategy.rollingUpdate.maxSurge | int | `1` | |