From 7bfad655c225c765b2a53544612a1d2c1f8662f4 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 23 Apr 2025 12:18:40 +0200 Subject: [PATCH 001/120] Fix: networkpolicy for tenant to access from cluster Signed-off-by: Andrei Kvapil --- packages/apps/tenant/Chart.yaml | 2 +- packages/apps/tenant/templates/networkpolicy.yaml | 1 + packages/apps/versions_map | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/apps/tenant/Chart.yaml b/packages/apps/tenant/Chart.yaml index bba14724..5582dc71 100644 --- a/packages/apps/tenant/Chart.yaml +++ b/packages/apps/tenant/Chart.yaml @@ -4,4 +4,4 @@ description: Separated tenant namespace icon: /logos/tenant.svg type: application -version: 1.9.1 +version: 1.9.2 diff --git a/packages/apps/tenant/templates/networkpolicy.yaml b/packages/apps/tenant/templates/networkpolicy.yaml index 7815162f..6d80f996 100644 --- a/packages/apps/tenant/templates/networkpolicy.yaml +++ b/packages/apps/tenant/templates/networkpolicy.yaml @@ -24,6 +24,7 @@ spec: ingress: - fromEntities: - world + - cluster egress: - toEntities: - world diff --git a/packages/apps/versions_map b/packages/apps/versions_map index a1175417..3d26fa55 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -130,7 +130,8 @@ tenant 1.6.8 bc95159a tenant 1.7.0 24fa7222 tenant 1.8.0 160e4e2a tenant 1.9.0 728743db -tenant 1.9.1 HEAD +tenant 1.9.1 721c12a7 +tenant 1.9.2 HEAD virtual-machine 0.1.4 f2015d65 virtual-machine 0.1.5 263e47be virtual-machine 0.2.0 c0685f43 From 8547dc3b215cc9e6fddba5d643693c79837d4d92 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 23 Apr 2025 15:15:30 +0200 Subject: [PATCH 002/120] [virtual-machine] Fix: Add GPU names to virtual machines spec Signed-off-by: Andrei Kvapil --- packages/apps/versions_map | 6 ++++-- packages/apps/virtual-machine/Chart.yaml | 2 +- packages/apps/virtual-machine/templates/vm.yaml | 3 ++- packages/apps/vm-instance/Chart.yaml | 2 +- packages/apps/vm-instance/templates/vm.yaml | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/apps/versions_map b/packages/apps/versions_map index a1175417..01fd53d3 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -143,7 +143,8 @@ virtual-machine 0.7.1 0ab39f20 virtual-machine 0.8.0 3fa4dd3a virtual-machine 0.8.1 93c46161 virtual-machine 0.8.2 de19450f -virtual-machine 0.9.0 HEAD +virtual-machine 0.9.0 721c12a7 +virtual-machine 0.9.1 HEAD vm-disk 0.1.0 d971f2ff vm-disk 0.1.1 HEAD vm-instance 0.1.0 1ec10165 @@ -153,7 +154,8 @@ vm-instance 0.4.0 e23286a3 vm-instance 0.4.1 0ab39f20 vm-instance 0.5.0 3fa4dd3a vm-instance 0.5.1 de19450f -vm-instance 0.6.0 HEAD +vm-instance 0.6.0 721c12a7 +vm-instance 0.6.1 HEAD vpn 0.1.0 263e47be vpn 0.2.0 53f2365e vpn 0.3.0 6c5cf5bf diff --git a/packages/apps/virtual-machine/Chart.yaml b/packages/apps/virtual-machine/Chart.yaml index b4ad45b5..225f9c24 100644 --- a/packages/apps/virtual-machine/Chart.yaml +++ b/packages/apps/virtual-machine/Chart.yaml @@ -17,7 +17,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.9.0 +version: 0.9.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/virtual-machine/templates/vm.yaml b/packages/apps/virtual-machine/templates/vm.yaml index 67f192e7..21c07c3a 100644 --- a/packages/apps/virtual-machine/templates/vm.yaml +++ b/packages/apps/virtual-machine/templates/vm.yaml @@ -74,7 +74,8 @@ spec: {{- if .Values.gpus }} gpus: {{- range $i, $gpu := .Values.gpus }} - - deviceName: {{ $gpu.name }} + - name: gpu{{ add $i 1 }} + deviceName: {{ $gpu.name }} {{- end }} {{- end }} disks: diff --git a/packages/apps/vm-instance/Chart.yaml b/packages/apps/vm-instance/Chart.yaml index 5f70145f..b0b6a3b9 100644 --- a/packages/apps/vm-instance/Chart.yaml +++ b/packages/apps/vm-instance/Chart.yaml @@ -17,7 +17,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.6.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/vm-instance/templates/vm.yaml b/packages/apps/vm-instance/templates/vm.yaml index 4a8ed2a4..8b647e70 100644 --- a/packages/apps/vm-instance/templates/vm.yaml +++ b/packages/apps/vm-instance/templates/vm.yaml @@ -46,7 +46,8 @@ spec: {{- if .Values.gpus }} gpus: {{- range $i, $gpu := .Values.gpus }} - - deviceName: {{ $gpu.name }} + - name: gpu{{ add $i 1 }} + deviceName: {{ $gpu.name }} {{- end }} {{- end }} disks: From 4bb524e53dfad29633efdbbcf9ea091fc1b0666e Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Wed, 23 Apr 2025 17:37:54 +0300 Subject: [PATCH 003/120] Suppress wget progress bar In our CI wget spams thousands of lines of the progress bar into the output, making it hard to read. Turns out, it doesn't have an option to just remove the progress bar, but explicitly directing wget's log to stdout and invoking --show-progress sends that to stderr which we redirect to dev/null. The downloaded size is still reported at regular intervals, but --progress=dot:giga shortens that to one line per 32M which is manageable. Signed-off-by: Timofei Larkin --- hack/e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/e2e.sh b/hack/e2e.sh index 9857a042..26401225 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -60,7 +60,7 @@ done # Prepare system drive if [ ! -f nocloud-amd64.raw ]; then - wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz -O nocloud-amd64.raw.xz + wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz -O nocloud-amd64.raw.xz --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null rm -f nocloud-amd64.raw xz --decompress nocloud-amd64.raw.xz fi From 7537235f437a77b5baeb3d6cdece9899c449f299 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Tue, 22 Apr 2025 17:40:15 +0200 Subject: [PATCH 004/120] [kubernetes] Add gpu-operator and introduce GPU support for tenant Kubernetes clusters Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Chart.yaml | 2 +- packages/apps/kubernetes/README.md | 50 +++++++-- .../apps/kubernetes/templates/cluster.yaml | 7 ++ .../helmreleases/cert-manager-crds.yaml | 2 +- .../templates/helmreleases/cert-manager.yaml | 2 +- .../templates/helmreleases/cilium.yaml | 2 +- .../templates/helmreleases/csi.yaml | 2 +- .../templates/helmreleases/delete.yaml | 2 + .../templates/helmreleases/fluxcd.yaml | 4 +- .../templates/helmreleases/gpu-operator.yaml | 57 ++++++++++ .../templates/helmreleases/ingress-nginx.yaml | 2 +- .../helmreleases/monitoring-agents.yaml | 2 +- .../vertical-pod-autoscaler-crds.yaml | 2 +- .../helmreleases/vertical-pod-autoscaler.yaml | 2 +- .../victoria-metrics-operator.yaml | 2 +- packages/apps/kubernetes/values.schema.json | 104 +++++++++++++++++- packages/apps/kubernetes/values.yaml | 20 +++- packages/apps/versions_map | 2 +- 18 files changed, 237 insertions(+), 29 deletions(-) create mode 100644 packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index cc8b5a83..05076167 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.18.1 +version: 0.19.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index bbc55cfd..3067a323 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -27,20 +27,46 @@ How to access to deployed cluster: kubectl get secret -n kubernetes--admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "super-admin.conf" | base64decode) }}' > test ``` -# Series +## Parameters - +### Common parameters -. | U | O | CX | M | RT -----------------------------|-----|-----|------|-----|------ -*Has GPUs* | | | | | -*Hugepages* | | | ✓ | ✓ | ✓ -*Overcommitted Memory* | | ✓ | | | -*Dedicated CPU* | | | ✓ | | ✓ -*Burstable CPU performance* | ✓ | ✓ | | ✓ | -*Isolated emulator threads* | | | ✓ | | ✓ -*vNUMA* | | | ✓ | | ✓ -*vCPU-To-Memory Ratio* | 1:4 | 1:4 | 1:2 | 1:8 | 1:4 +| Name | Description | Value | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| `host` | The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). | `""` | +| `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components | `2` | +| `storageClass` | StorageClass used to store user data | `replicated` | +| `nodeGroups` | nodeGroups configuration | `{}` | + +### Cluster Addons + +| Name | Description | Value | +| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `addons.certManager.enabled` | Enables the cert-manager | `false` | +| `addons.certManager.valuesOverride` | Custom values to override | `{}` | +| `addons.ingressNginx.enabled` | Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) | `false` | +| `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | +| `addons.ingressNginx.hosts` | List of domain names that should be passed through to the cluster by upper cluster | `[]` | +| `addons.gpuOperator.enabled` | Enables the gpu-operator | `false` | +| `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` | +| `addons.fluxcd.enabled` | Enables Flux CD | `false` | +| `addons.fluxcd.valuesOverride` | Custom values to override | `{}` | +| `addons.monitoringAgents.enabled` | Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage | `false` | +| `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` | +| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` | + +### Kamaji control plane + +| Name | Description | Value | +| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `kamajiControlPlane.apiServer.resources` | Resources | `{}` | +| `kamajiControlPlane.apiServer.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | +| `kamajiControlPlane.controllerManager.resources` | Resources | `{}` | +| `kamajiControlPlane.controllerManager.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `kamajiControlPlane.scheduler.resources` | Resources | `{}` | +| `kamajiControlPlane.scheduler.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `kamajiControlPlane.addons.konnectivity.server.resources` | Resources | `{}` | +| `kamajiControlPlane.addons.konnectivity.server.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | ## U Series diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index a208bc6e..385adacc 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -39,6 +39,13 @@ spec: sockets: 1 {{- end }} devices: + {{- if .group.gpus }} + gpus: + {{- range $i, $gpu := .group.gpus }} + - name: gpu{{ add $i 1 }} + deviceName: {{ $gpu.name }} + {{- end }} + {{- end }} disks: - name: system disk: diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml index 8ee5dc82..04080631 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml @@ -4,7 +4,7 @@ metadata: name: {{ .Release.Name }}-cert-manager-crds labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: cert-manager-crds diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index 8a7213a9..3d8bbaa0 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-cert-manager labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: cert-manager diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index cf6bbe12..4edc3c24 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -4,7 +4,7 @@ metadata: name: {{ .Release.Name }}-cilium labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: cilium diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml index 2fe33509..ec6092f0 100644 --- a/packages/apps/kubernetes/templates/helmreleases/csi.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -4,7 +4,7 @@ metadata: name: {{ .Release.Name }}-csi labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: csi diff --git a/packages/apps/kubernetes/templates/helmreleases/delete.yaml b/packages/apps/kubernetes/templates/helmreleases/delete.yaml index 35cacedb..10a8d995 100644 --- a/packages/apps/kubernetes/templates/helmreleases/delete.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/delete.yaml @@ -38,6 +38,7 @@ spec: {{ .Release.Name }}-ingress-nginx {{ .Release.Name }}-fluxcd-operator {{ .Release.Name }}-fluxcd + {{ .Release.Name }}-gpu-operator -p '{"spec": {"suspend": true}}' --type=merge --field-manager=flux-client-side-apply || true --- @@ -76,6 +77,7 @@ rules: - {{ .Release.Name }}-ingress-nginx - {{ .Release.Name }}-fluxcd-operator - {{ .Release.Name }}-fluxcd + - {{ .Release.Name }}-gpu-operator --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index c11629b9..1a4f982a 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-fluxcd-operator labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: fluxcd-operator @@ -49,7 +49,7 @@ metadata: name: {{ .Release.Name }}-fluxcd labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: fluxcd diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml new file mode 100644 index 00000000..9a003e12 --- /dev/null +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -0,0 +1,57 @@ +{{- if .Values.addons.gpuOperator.enabled }} +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-gpu-operator + labels: + cozystack.io/repository: system + cozystack.io/target-cluster-name: {{ .Release.Name }} +spec: + interval: 5m + releaseName: gpu-operator + chart: + spec: + chart: cozy-gpu-operator + reconcileStrategy: Revision + sourceRef: + kind: HelmRepository + name: cozystack-system + namespace: cozy-system + kubeConfig: + secretRef: + name: {{ .Release.Name }}-admin-kubeconfig + key: super-admin.svc + targetNamespace: cozy-gpu-operator + storageNamespace: cozy-gpu-operator + install: + createNamespace: true + remediation: + retries: -1 + upgrade: + remediation: + retries: -1 + {{- if .Values.addons.gpuOperator.valuesOverride }} + valuesFrom: + - kind: Secret + name: {{ .Release.Name }}-gpu-operator-values-override + valuesKey: values + {{- end }} + + dependsOn: + {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} + - name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + {{- end }} + - name: {{ .Release.Name }}-cilium + namespace: {{ .Release.Namespace }} +{{- end }} +{{- if .Values.addons.gpuOperator.valuesOverride }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-gpu-operator-values-override +stringData: + values: | + {{- toYaml .Values.addons.gpuOperator.valuesOverride | nindent 4 }} +{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index 8daaf01f..bedb876a 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-ingress-nginx labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: ingress-nginx diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index eb19f23b..dac132fc 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -7,7 +7,7 @@ metadata: name: {{ .Release.Name }}-monitoring-agents labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: cozy-monitoring-agents diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml index 89634565..9c901457 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-vertical-pod-autoscaler-crds labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: vertical-pod-autoscaler-crds diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index d5e17079..fff634e3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -7,7 +7,7 @@ metadata: name: {{ .Release.Name }}-vertical-pod-autoscaler labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: vertical-pod-autoscaler diff --git a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml index de19c968..e47ea4f3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-cozy-victoria-metrics-operator labels: cozystack.io/repository: system - coztstack.io/target-cluster-name: {{ .Release.Name }} + cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m releaseName: cozy-victoria-metrics-operator diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index ed0de279..58e63f1e 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -12,7 +12,7 @@ "properties": { "replicas": { "type": "number", - "description": "Number of replicas for Kubernetes contorl-plane components", + "description": "Number of replicas for Kubernetes control-plane components", "default": 2 } } @@ -61,6 +61,21 @@ } } }, + "gpuOperator": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables the gpu-operator", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, "fluxcd": { "type": "object", "properties": { @@ -90,8 +105,93 @@ "default": {} } } + }, + "verticalPodAutoscaler": { + "type": "object", + "properties": { + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + } + } + }, + "kamajiControlPlane": { + "type": "object", + "properties": { + "apiServer": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "description": "Resources", + "default": {} + }, + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "small" + } + } + }, + "controllerManager": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "description": "Resources", + "default": {} + }, + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro" + } + } + }, + "scheduler": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "description": "Resources", + "default": {} + }, + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro" + } + } + }, + "addons": { + "type": "object", + "properties": { + "konnectivity": { + "type": "object", + "properties": { + "server": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "description": "Resources", + "default": {} + }, + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro" + } + } + } + } + } + } } } } } -} +} \ No newline at end of file diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index 9fb60221..f18e43d2 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -1,7 +1,7 @@ ## @section Common parameters ## @param host The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). -## @param controlPlane.replicas Number of replicas for Kubernetes contorl-plane components +## @param controlPlane.replicas Number of replicas for Kubernetes control-plane components ## @param storageClass StorageClass used to store user data ## host: "" @@ -24,6 +24,14 @@ nodeGroups: cpu: "" memory: "" + ## List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM) + ## e.g: + ## instanceType: "u1.xlarge" + ## gpus: + ## - name: nvidia.com/AD102GL_L40S + gpus: [] + + ## @section Cluster Addons ## addons: @@ -52,6 +60,14 @@ addons: hosts: [] valuesOverride: {} + ## GPU-operator: NVIDIA GPU Operator + ## + gpuOperator: + ## @param addons.gpuOperator.enabled Enables the gpu-operator + ## @param addons.gpuOperator.valuesOverride Custom values to override + enabled: false + valuesOverride: {} + ## Flux CD ## fluxcd: @@ -135,4 +151,4 @@ kamajiControlPlane: ## @param kamajiControlPlane.addons.konnectivity.server.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). resourcesPreset: "micro" - \ No newline at end of file + diff --git a/packages/apps/versions_map b/packages/apps/versions_map index a1175417..8d0f9b60 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -59,7 +59,7 @@ kubernetes 0.16.0 077045b0 kubernetes 0.17.0 1fbbfcd0 kubernetes 0.17.1 fd240701 kubernetes 0.18.0 721c12a7 -kubernetes 0.18.1 HEAD +kubernetes 0.19.0 HEAD mysql 0.1.0 263e47be mysql 0.2.0 c24a103f mysql 0.3.0 53f2365e From b56624a7818d6fd8c18491e3200ed32b5d600cd1 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 23 Apr 2025 17:04:06 +0200 Subject: [PATCH 005/120] [cluster-api] Update operator, providers, remove Kamaji workaround Signed-off-by: Andrei Kvapil --- .../charts/cluster-api-operator/Chart.yaml | 4 +- .../cluster-api-operator/templates/addon.yaml | 45 ++-- .../templates/bootstrap.yaml | 45 ++-- .../templates/control-plane.yaml | 45 ++-- .../cluster-api-operator/templates/core.yaml | 45 ++-- .../cluster-api-operator/templates/infra.yaml | 47 ++-- .../cluster-api-operator/templates/ipam.yaml | 45 ++-- .../templates/operator-components.yaml | 241 +++++++++++++++--- .../cluster-api-operator/values.schema.json | 47 ++++ .../charts/cluster-api-operator/values.yaml | 32 ++- .../capi-providers/templates/providers.yaml | 8 +- .../images/kamaji/patches/hardcode-port.diff | 13 - 12 files changed, 426 insertions(+), 191 deletions(-) create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/values.schema.json delete mode 100644 packages/system/kamaji/images/kamaji/patches/hardcode-port.diff diff --git a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml index 5108c7dc..323a3594 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: 0.18.1 +appVersion: 0.19.0 description: Cluster API Operator name: cluster-api-operator type: application -version: 0.18.1 +version: 0.19.0 diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml index a2eb8fb9..6a341496 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml @@ -1,26 +1,8 @@ # Addon provider -{{- if .Values.addon }} -{{- $addons := split ";" .Values.addon }} -{{- $addonNamespace := "" }} -{{- $addonName := "" }} -{{- $addonVersion := "" }} -{{- range $addon := $addons }} -{{- $addonArgs := split ":" $addon }} -{{- $addonArgsLen := len $addonArgs }} -{{- if eq $addonArgsLen 3 }} - {{- $addonNamespace = $addonArgs._0 }} - {{- $addonName = $addonArgs._1 }} - {{- $addonVersion = $addonArgs._2 }} -{{- else if eq $addonArgsLen 2 }} - {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} - {{- $addonName = $addonArgs._0 }} - {{- $addonVersion = $addonArgs._1 }} -{{- else if eq $addonArgsLen 1 }} - {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} - {{- $addonName = $addonArgs._0 }} -{{- else }} - {{- fail "addon provider argument should have the following format helm:v1.0.0 or mynamespace:helm:v1.0.0" }} -{{- end }} +{{- range $name, $addon := $.Values.addon }} + {{- $addonNamespace := default ( printf "%s-%s" $name "addon-system" ) (get $addon "namespace") }} + {{- $addonName := $name }} + {{- $addonVersion := get $addon "version" }} --- apiVersion: v1 kind: Namespace @@ -56,5 +38,24 @@ spec: {{- if $.Values.secretNamespace }} secretNamespace: {{ $.Values.secretNamespace }} {{- end }} +{{- if $addon.manifestPatches }} + manifestPatches: {{ toYaml $addon.manifestPatches | nindent 4 }} {{- end }} +{{- if $addon.additionalManifests }} + additionalManifests: + name: {{ $addon.additionalManifests.name }} + {{- if $addon.additionalManifests.namespace }} + namespace: {{ $addon.additionalManifests.namespace }} + {{- end }} {{/* if $addon.additionalManifests.namespace */}} {{- end }} +{{- if $addon.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $addon.additionalManifests.name }} + namespace: {{ default $addonNamespace $addon.additionalManifests.namespace }} +data: + manifests: {{- toYaml $addon.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $addon := .Values.addon */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml index ed5d7924..78dad47e 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml @@ -1,26 +1,8 @@ # Bootstrap provider -{{- if .Values.bootstrap }} -{{- $bootstraps := split ";" .Values.bootstrap }} -{{- $bootstrapNamespace := "" }} -{{- $bootstrapName := "" }} -{{- $bootstrapVersion := "" }} -{{- range $bootstrap := $bootstraps }} -{{- $bootstrapArgs := split ":" $bootstrap }} -{{- $bootstrapArgsLen := len $bootstrapArgs }} -{{- if eq $bootstrapArgsLen 3 }} - {{- $bootstrapNamespace = $bootstrapArgs._0 }} - {{- $bootstrapName = $bootstrapArgs._1 }} - {{- $bootstrapVersion = $bootstrapArgs._2 }} -{{- else if eq $bootstrapArgsLen 2 }} - {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} - {{- $bootstrapName = $bootstrapArgs._0 }} - {{- $bootstrapVersion = $bootstrapArgs._1 }} -{{- else if eq $bootstrapArgsLen 1 }} - {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} - {{- $bootstrapName = $bootstrapArgs._0 }} -{{- else }} - {{- fail "bootstrap provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} -{{- end }} +{{- range $name, $bootstrap := $.Values.bootstrap }} + {{- $bootstrapNamespace := default ( printf "%s-%s" $name "bootstrap-system" ) (get $bootstrap "namespace") }} + {{- $bootstrapName := $name }} + {{- $bootstrapVersion := get $bootstrap "version" }} --- apiVersion: v1 kind: Namespace @@ -57,5 +39,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $bootstrap.manifestPatches }} + manifestPatches: {{ toYaml $bootstrap.manifestPatches | nindent 4 }} {{- end }} +{{- if $bootstrap.additionalManifests }} + additionalManifests: + name: {{ $bootstrap.additionalManifests.name }} + {{- if $bootstrap.additionalManifests.namespace }} + namespace: {{ $bootstrap.additionalManifests.namespace }} + {{- end }} {{/* if $bootstrap.additionalManifests.namespace */}} {{- end }} +{{- if $bootstrap.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $bootstrap.additionalManifests.name }} + namespace: {{ default $bootstrapNamespace $bootstrap.additionalManifests.namespace }} +data: + manifests: {{- toYaml $bootstrap.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $bootstrap := .Values.bootstrap */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml index d72249d1..8a020afd 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml @@ -1,26 +1,8 @@ # Control plane provider -{{- if .Values.controlPlane }} -{{- $controlPlanes := split ";" .Values.controlPlane }} -{{- $controlPlaneNamespace := "" }} -{{- $controlPlaneName := "" }} -{{- $controlPlaneVersion := "" }} -{{- range $controlPlane := $controlPlanes }} -{{- $controlPlaneArgs := split ":" $controlPlane }} -{{- $controlPlaneArgsLen := len $controlPlaneArgs }} -{{- if eq $controlPlaneArgsLen 3 }} - {{- $controlPlaneNamespace = $controlPlaneArgs._0 }} - {{- $controlPlaneName = $controlPlaneArgs._1 }} - {{- $controlPlaneVersion = $controlPlaneArgs._2 }} -{{- else if eq $controlPlaneArgsLen 2 }} - {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} - {{- $controlPlaneName = $controlPlaneArgs._0 }} - {{- $controlPlaneVersion = $controlPlaneArgs._1 }} -{{- else if eq $controlPlaneArgsLen 1 }} - {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} - {{- $controlPlaneName = $controlPlaneArgs._0 }} -{{- else }} - {{- fail "controlplane provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} -{{- end }} +{{- range $name, $controlPlane := $.Values.controlPlane }} + {{- $controlPlaneNamespace := default ( printf "%s-%s" $name "control-plane-system" ) (get $controlPlane "namespace") }} + {{- $controlPlaneName := $name }} + {{- $controlPlaneVersion := get $controlPlane "version" }} --- apiVersion: v1 kind: Namespace @@ -70,5 +52,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $controlPlane.manifestPatches }} + manifestPatches: {{ toYaml $controlPlane.manifestPatches | nindent 4 }} {{- end }} +{{- if $controlPlane.additionalManifests }} + additionalManifests: + name: {{ $controlPlane.additionalManifests.name }} + {{- if $controlPlane.additionalManifests.namespace }} + namespace: {{ $controlPlane.additionalManifests.namespace }} + {{- end }} {{/* if $controlPlane.additionalManifests.namespace */}} {{- end }} +{{- if $controlPlane.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $controlPlane.additionalManifests.name }} + namespace: {{ default $controlPlaneNamespace $controlPlane.additionalManifests.namespace }} +data: + manifests: {{- toYaml $controlPlane.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $controlPlane := .Values.controlPlane */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml index 828d2269..648e1b60 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml @@ -1,25 +1,8 @@ # Core provider -{{- if .Values.core }} -{{- $coreArgs := split ":" .Values.core }} -{{- $coreArgsLen := len $coreArgs }} -{{- $coreVersion := "" }} -{{- $coreNamespace := "" }} -{{- $coreName := "" }} -{{- $coreVersion := "" }} -{{- if eq $coreArgsLen 3 }} - {{- $coreNamespace = $coreArgs._0 }} - {{- $coreName = $coreArgs._1 }} - {{- $coreVersion = $coreArgs._2 }} -{{- else if eq $coreArgsLen 2 }} - {{- $coreNamespace = "capi-system" }} - {{- $coreName = $coreArgs._0 }} - {{- $coreVersion = $coreArgs._1 }} -{{- else if eq $coreArgsLen 1 }} - {{- $coreNamespace = "capi-system" }} - {{- $coreName = $coreArgs._0 }} -{{- else }} - {{- fail "core provider argument should have the following format cluster-api:v1.0.0 or mynamespace:cluster-api:v1.0.0" }} -{{- end }} +{{- range $name, $core := $.Values.core }} + {{- $coreNamespace := default "capi-system" (get $core "namespace") }} + {{- $coreName := $name }} + {{- $coreVersion := get $core "version" }} --- apiVersion: v1 kind: Namespace @@ -65,4 +48,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $core.manifestPatches }} + manifestPatches: {{ toYaml $core.manifestPatches | nindent 4 }} {{- end }} +{{- if $core.additionalManifests }} + additionalManifests: + name: {{ $core.additionalManifests.name }} + {{- if $core.additionalManifests.namespace }} + namespace: {{ $core.additionalManifests.namespace }} + {{- end }} +{{- end }} +{{- if $core.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $core.additionalManifests.name }} + namespace: {{ default $coreNamespace $core.additionalManifests.namespace }} +data: + manifests: {{- toYaml $core.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $core := .Values.core */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml index 5841336c..835607d4 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml @@ -1,26 +1,8 @@ # Infrastructure providers -{{- if .Values.infrastructure }} -{{- $infrastructures := split ";" .Values.infrastructure }} -{{- $infrastructureNamespace := "" }} -{{- $infrastructureName := "" }} -{{- $infrastructureVersion := "" }} -{{- range $infrastructure := $infrastructures }} -{{- $infrastructureArgs := split ":" $infrastructure }} -{{- $infrastructureArgsLen := len $infrastructureArgs }} -{{- if eq $infrastructureArgsLen 3 }} - {{- $infrastructureNamespace = $infrastructureArgs._0 }} - {{- $infrastructureName = $infrastructureArgs._1 }} - {{- $infrastructureVersion = $infrastructureArgs._2 }} -{{- else if eq $infrastructureArgsLen 2 }} - {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} - {{- $infrastructureName = $infrastructureArgs._0 }} - {{- $infrastructureVersion = $infrastructureArgs._1 }} -{{- else if eq $infrastructureArgsLen 1 }} - {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} - {{- $infrastructureName = $infrastructureArgs._0 }} -{{- else }} - {{- fail "infrastructure provider argument should have the following format aws:v1.0.0 or mynamespace:aws:v1.0.0" }} -{{- end }} +{{- range $name, $infra := $.Values.infrastructure }} + {{- $infrastructureNamespace := default ( printf "%s-%s" $name "infrastructure-system" ) (get $infra "namespace") }} + {{- $infrastructureName := $name }} + {{- $infrastructureVersion := get $infra "version" }} --- apiVersion: v1 kind: Namespace @@ -83,5 +65,24 @@ spec: {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} +{{- if $infra.manifestPatches }} + manifestPatches: {{- toYaml $infra.manifestPatches | nindent 4 }} +{{- end }} {{/* if $infra.manifestPatches */}} +{{- if $infra.additionalManifests }} + additionalManifests: + name: {{ $infra.additionalManifests.name }} + {{- if $infra.additionalManifests.namespace }} + namespace: {{ $infra.additionalManifests.namespace }} + {{- end }} {{/* if $infra.additionalManifests.namespace */}} +{{- end }} {{/* if $infra.additionalManifests */}} +{{- if $infra.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $infra.additionalManifests.name }} + namespace: {{ default $infrastructureNamespace $infra.additionalManifests.namespace }} +data: + manifests: {{- toYaml $infra.additionalManifests.manifests | nindent 4 }} {{- end }} -{{- end }} +{{- end }} {{/* range $name, $infra := .Values.infrastructure */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml index 06960afb..4a33c42f 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml @@ -1,26 +1,8 @@ # IPAM providers -{{- if .Values.ipam }} -{{- $ipams := split ";" .Values.ipam }} -{{- $ipamNamespace := "" }} -{{- $ipamName := "" }} -{{- $ipamVersion := "" }} -{{- range $ipam := $ipams }} -{{- $ipamArgs := split ":" $ipam }} -{{- $ipamArgsLen := len $ipamArgs }} -{{- if eq $ipamArgsLen 3 }} - {{- $ipamNamespace = $ipamArgs._0 }} - {{- $ipamName = $ipamArgs._1 }} - {{- $ipamVersion = $ipamArgs._2 }} -{{- else if eq $ipamArgsLen 2 }} - {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} - {{- $ipamName = $ipamArgs._0 }} - {{- $ipamVersion = $ipamArgs._1 }} -{{- else if eq $ipamArgsLen 1 }} - {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} - {{- $ipamName = $ipamArgs._0 }} -{{- else }} - {{- fail "ipam provider argument should have the following format in-cluster:v1.0.0 or mynamespace:in-cluster:v1.0.0" }} -{{- end }} +{{- range $name, $ipam := $.Values.ipam }} + {{- $ipamNamespace := default ( printf "%s-%s" $name "ipam-system" ) (get $ipam "namespace") }} + {{- $ipamName := $name }} + {{- $ipamVersion := get $ipam "version" }} --- apiVersion: v1 kind: Namespace @@ -70,8 +52,27 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $ipam.manifestPatches }} + manifestPatches: {{ toYaml $ipam.manifestPatches | nindent 4 }} +{{- end }} {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} +{{- if $ipam.additionalManifests }} + additionalManifests: + name: {{ $ipam.additionalManifests.name }} + {{- if $ipam.additionalManifests.namespace }} + namespace: {{ $ipam.additionalManifests.namespace }} + {{- end }} {{/* if $ipam.additionalManifests.namespace */}} {{- end }} +{{- if $ipam.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $ipam.additionalManifests.name }} + namespace: {{ default $ipamNamespace $ipam.additionalManifests.namespace }} +data: + manifests: {{- toYaml $ipam.additionalManifests.manifests | nindent 4 }} {{- end }} +{{- end }} {{/* range $name, $ipam := .Values.ipam */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml index 27b8bf80..0ee82bfc 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml @@ -1305,6 +1305,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -2836,6 +2843,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -3048,27 +3062,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -3078,6 +3097,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -4711,27 +4732,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -4741,6 +4767,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -6043,6 +6071,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7574,6 +7609,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7786,27 +7828,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -7816,6 +7863,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -9450,27 +9499,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -9480,6 +9534,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -10783,6 +10839,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12314,6 +12377,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12527,27 +12597,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -12557,6 +12632,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -14190,27 +14267,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -14220,6 +14302,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -15522,6 +15606,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17053,6 +17144,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17265,27 +17363,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -17295,6 +17398,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -18929,27 +19034,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -18959,6 +19069,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -20262,6 +20374,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -21793,6 +21912,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -22006,27 +22132,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -22036,6 +22167,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -23371,6 +23504,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -24902,6 +25042,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -25114,27 +25261,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -25144,6 +25296,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -26481,6 +26635,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28012,6 +28173,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28225,27 +28393,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -28255,6 +28428,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json b/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json new file mode 100644 index 00000000..d22038fc --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "core": { + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "bootstrap": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "controlPlane": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "infrastructure": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "addon": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "ipam": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + } + } +} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml index 12507a3c..545bae39 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml @@ -1,12 +1,30 @@ --- # --- # Cluster API provider options -core: "" -bootstrap: "" -controlPlane: "" -infrastructure: "" -ipam: "" -addon: "" +core: {} +# cluster-api: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +bootstrap: {} +# kubeadm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +controlPlane: {} +# kubeadm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +infrastructure: {} +# docker: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +addon: {} +# helm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +ipam: {} +# in-cluster: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional manager.featureGates: {} fetchConfig: {} # --- @@ -21,7 +39,7 @@ leaderElection: image: manager: repository: registry.k8s.io/capi-operator/cluster-api-operator - tag: v0.18.1 + tag: v0.19.0 pullPolicy: IfNotPresent env: manager: [] diff --git a/packages/system/capi-providers/templates/providers.yaml b/packages/system/capi-providers/templates/providers.yaml index 18ae6c7d..7cb59f3b 100644 --- a/packages/system/capi-providers/templates/providers.yaml +++ b/packages/system/capi-providers/templates/providers.yaml @@ -5,7 +5,7 @@ metadata: name: cluster-api spec: # https://github.com/kubernetes-sigs/cluster-api - version: v1.9.5 + version: v1.10.0 --- apiVersion: operator.cluster.x-k8s.io/v1alpha2 kind: ControlPlaneProvider @@ -13,7 +13,7 @@ metadata: name: kamaji spec: # https://github.com/clastix/cluster-api-control-plane-provider-kamaji - version: v0.14.1 + version: v0.14.2 deployment: containers: - name: manager @@ -31,7 +31,7 @@ metadata: name: kubeadm spec: # https://github.com/kubernetes-sigs/cluster-api - version: v1.9.5 + version: v1.10.0 --- apiVersion: operator.cluster.x-k8s.io/v1alpha2 kind: InfrastructureProvider @@ -39,4 +39,4 @@ metadata: name: kubevirt spec: # https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt - version: v0.1.9 + version: v0.1.10 diff --git a/packages/system/kamaji/images/kamaji/patches/hardcode-port.diff b/packages/system/kamaji/images/kamaji/patches/hardcode-port.diff deleted file mode 100644 index 5e80d417..00000000 --- a/packages/system/kamaji/images/kamaji/patches/hardcode-port.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/internal/resources/kubeadm_config.go b/internal/resources/kubeadm_config.go -index ae4cfc0..ec7a7da 100644 ---- a/internal/resources/kubeadm_config.go -+++ b/internal/resources/kubeadm_config.go -@@ -96,7 +96,7 @@ func (r *KubeadmConfigResource) mutate(ctx context.Context, tenantControlPlane * - TenantControlPlanePort: port, - TenantControlPlaneName: tenantControlPlane.GetName(), - TenantControlPlaneNamespace: tenantControlPlane.GetNamespace(), -- TenantControlPlaneEndpoint: r.getControlPlaneEndpoint(tenantControlPlane.Spec.ControlPlane.Ingress, address, port), -+ TenantControlPlaneEndpoint: r.getControlPlaneEndpoint(tenantControlPlane.Spec.ControlPlane.Ingress, address, 443), - TenantControlPlaneCertSANs: tenantControlPlane.Spec.NetworkProfile.CertSANs, - TenantControlPlaneClusterDomain: tenantControlPlane.Spec.NetworkProfile.ClusterDomain, - TenantControlPlanePodCIDR: tenantControlPlane.Spec.NetworkProfile.PodCIDR, From 04e2b3952b5686c6f7381a62abfae0b0f07eed13 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Tue, 22 Apr 2025 19:29:23 +0200 Subject: [PATCH 006/120] Update Kube-OVN to v1.13.10 Signed-off-by: Andrei Kvapil --- packages/system/kubeovn/Makefile | 4 +- .../system/kubeovn/charts/kube-ovn/Chart.yaml | 4 +- .../charts/kube-ovn/templates/ovncni-ds.yaml | 4 +- .../kubeovn/charts/kube-ovn/values.yaml | 2 +- .../system/kubeovn/images/kubeovn/Dockerfile | 49 +------------------ .../kubeovn/patches/disable-nm-syncer.diff | 14 ------ 6 files changed, 10 insertions(+), 67 deletions(-) delete mode 100644 packages/system/kubeovn/images/kubeovn/patches/disable-nm-syncer.diff diff --git a/packages/system/kubeovn/Makefile b/packages/system/kubeovn/Makefile index 559dd118..e2fed120 100644 --- a/packages/system/kubeovn/Makefile +++ b/packages/system/kubeovn/Makefile @@ -1,4 +1,4 @@ -KUBEOVN_TAG = v1.13.8 +KUBEOVN_TAG=$(shell awk '$$1 == "version:" {print $$2}' charts/kubeovn/Chart.yaml) export NAME=kubeovn export NAMESPACE=cozy-$(NAME) @@ -13,6 +13,8 @@ update: tar xzvf - --strip 1 kube-ovn-$${tag#*v}/charts patch --no-backup-if-mismatch -p4 < patches/cozyconfig.diff patch --no-backup-if-mismatch -p4 < patches/mtu.diff + version=$$(awk '$$1 == "version:" {print $$2}' charts/kube-ovn/Chart.yaml) && \ + sed -i "s/ARG VERSION=.*/ARG VERSION=$${version}/" images/kubeovn/Dockerfile image: docker buildx build images/kubeovn \ diff --git a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml index cf67c7d9..4e0752a1 100644 --- a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml @@ -15,12 +15,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: v1.13.8 +version: v1.13.10 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.13.8" +appVersion: "1.13.10" kubeVersion: ">= 1.23.0-0" diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml index 3d9a7e88..01136f89 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml @@ -271,10 +271,10 @@ spec: {{- if .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} - name: local-bin hostPath: - path: {{ .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} + path: {{ .Values.cni_conf.LOCAL_BIN_DIR }} {{- end }} {{- if .Values.func.ENABLE_OVN_IPSEC }} - name: ovs-ipsec-keys hostPath: - path: /etc/origin/ovs_ipsec_keys + path: {{ .Values.OPENVSWITCH_DIR }} {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml index 98c6bb2c..1ebbd3a8 100644 --- a/packages/system/kubeovn/charts/kube-ovn/values.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml @@ -10,7 +10,7 @@ global: repository: kube-ovn dpdkRepository: kube-ovn-dpdk vpcRepository: vpc-nat-gateway - tag: v1.13.8 + tag: v1.13.10 support_arm: true thirdparty: true diff --git a/packages/system/kubeovn/images/kubeovn/Dockerfile b/packages/system/kubeovn/images/kubeovn/Dockerfile index be05d4b8..8914c18b 100644 --- a/packages/system/kubeovn/images/kubeovn/Dockerfile +++ b/packages/system/kubeovn/images/kubeovn/Dockerfile @@ -1,50 +1,5 @@ -# syntax = docker/dockerfile:experimental -ARG VERSION=v1.13.8 -ARG BASE_TAG=$VERSION - -FROM golang:1.23-bookworm as builder - -ARG TAG=v1.13.8 -RUN git clone --branch ${TAG} --depth 1 https://github.com/kubeovn/kube-ovn /source - -WORKDIR /source - -COPY patches /patches -RUN git apply /patches/*.diff -RUN make build-go - -WORKDIR /source/dist/images - -# imported from https://github.com/kubeovn/kube-ovn/blob/master/dist/images/Dockerfile -FROM kubeovn/kube-ovn-base:$BASE_TAG AS setcap - -COPY --from=builder /source/dist/images/*.sh /kube-ovn/ -COPY --from=builder /source/dist/images/kubectl-ko /kube-ovn/kubectl-ko -COPY --from=builder /source/dist/images/01-kube-ovn.conflist /kube-ovn/01-kube-ovn.conflist - -COPY --from=builder /source/dist/images/kube-ovn /kube-ovn/kube-ovn -COPY --from=builder /source/dist/images/kube-ovn-cmd /kube-ovn/kube-ovn-cmd -COPY --from=builder /source/dist/images/kube-ovn-daemon /kube-ovn/kube-ovn-daemon -COPY --from=builder /source/dist/images/kube-ovn-controller /kube-ovn/kube-ovn-controller -RUN ln -s /kube-ovn/kube-ovn-cmd /kube-ovn/kube-ovn-monitor && \ - ln -s /kube-ovn/kube-ovn-cmd /kube-ovn/kube-ovn-speaker && \ - ln -s /kube-ovn/kube-ovn-cmd /kube-ovn/kube-ovn-webhook && \ - ln -s /kube-ovn/kube-ovn-cmd /kube-ovn/kube-ovn-leader-checker && \ - ln -s /kube-ovn/kube-ovn-cmd /kube-ovn/kube-ovn-ic-controller && \ - ln -s /kube-ovn/kube-ovn-controller /kube-ovn/kube-ovn-pinger && \ - setcap CAP_NET_BIND_SERVICE+eip /kube-ovn/kube-ovn-cmd && \ - setcap CAP_NET_RAW,CAP_NET_BIND_SERVICE+eip /kube-ovn/kube-ovn-controller && \ - setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /kube-ovn/kube-ovn-daemon - -FROM kubeovn/kube-ovn-base:$BASE_TAG - -COPY --chmod=0644 --from=builder /source/dist/images/logrotate/* /etc/logrotate.d/ -COPY --from=builder /source/dist/images/grace_stop_ovn_controller /usr/share/ovn/scripts/grace_stop_ovn_controller - -COPY --from=setcap /kube-ovn /kube-ovn -RUN /kube-ovn/iptables-wrapper-installer.sh --no-sanity-check - -WORKDIR /kube-ovn +ARG VERSION=v1.13.10 +FROM kubeovn/kube-ovn:${VERSION} # Fix https://github.com/kubeovn/kube-ovn/issues/4526 RUN setcap CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /usr/lib/openvswitch-switch/ovs-vswitchd \ diff --git a/packages/system/kubeovn/images/kubeovn/patches/disable-nm-syncer.diff b/packages/system/kubeovn/images/kubeovn/patches/disable-nm-syncer.diff deleted file mode 100644 index c9c683f9..00000000 --- a/packages/system/kubeovn/images/kubeovn/patches/disable-nm-syncer.diff +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/pkg/daemon/controller_linux.go b/pkg/daemon/controller_linux.go -index 07014d11..7ff19ae0 100644 ---- a/pkg/daemon/controller_linux.go -+++ b/pkg/daemon/controller_linux.go -@@ -118,9 +118,6 @@ func (c *Controller) initRuntime() error { - c.k8siptables[kubeovnv1.ProtocolIPv6] = k8siptables.New(c.k8sExec, k8siptables.ProtocolIPv6) - } - -- c.nmSyncer = newNetworkManagerSyncer() -- c.nmSyncer.Run(c.transferAddrsAndRoutes) -- - return nil - } - From 8a4793d571e45e08b90afffb913a9ff11279c2d4 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 11:25:10 +0200 Subject: [PATCH 007/120] [ci] let CI to cancel previus job if new one is scheduled Signed-off-by: Andrei Kvapil --- .github/workflows/backport.yaml | 4 ++++ .github/workflows/pre-commit.yml | 4 ++++ .github/workflows/pull-requests-release.yaml | 4 ++++ .github/workflows/pull-requests.yaml | 4 ++++ .github/workflows/tags.yaml | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml index 67445b77..10968e38 100644 --- a/.github/workflows/backport.yaml +++ b/.github/workflows/backport.yaml @@ -4,6 +4,10 @@ on: pull_request_target: types: [closed] # fires when PR is closed (merged) +concurrency: + group: backport-${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + permissions: contents: write pull-requests: write diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index a33c78e2..535f483e 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -7,6 +7,10 @@ on: pull_request: paths-ignore: - '**.md' +concurrency: + group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: pre-commit: runs-on: ubuntu-22.04 diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 815ccb59..7a49f012 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -4,6 +4,10 @@ on: pull_request: types: [labeled, opened, synchronize, reopened, closed] +concurrency: + group: pull-requests-release-${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + jobs: verify: name: Test Release diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 92226c2a..594d4444 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -4,6 +4,10 @@ on: pull_request: types: [labeled, opened, synchronize, reopened] +concurrency: + group: pull-requests-${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + jobs: e2e: name: Build and Test diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index f50c9b0a..d0e61aa2 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -5,6 +5,10 @@ on: tags: - 'v*.*.*' # vX.Y.Z or vX.Y.Z-rcN +concurrency: + group: tags-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prepare-release: name: Prepare Release From 19409d801d037b6ffafad5e1df5b98b4ec4e7182 Mon Sep 17 00:00:00 2001 From: Ian Simon Date: Thu, 24 Apr 2025 11:44:25 +0300 Subject: [PATCH 008/120] [postgres] remove douplicated template from backup manifest Signed-off-by: Ian Simon --- packages/apps/postgres/Chart.yaml | 2 +- packages/apps/postgres/templates/backup-cronjob.yaml | 5 +---- packages/apps/versions_map | 3 ++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/apps/postgres/Chart.yaml b/packages/apps/postgres/Chart.yaml index 4dcda816..36842881 100644 --- a/packages/apps/postgres/Chart.yaml +++ b/packages/apps/postgres/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.10.0 +version: 0.10.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/postgres/templates/backup-cronjob.yaml b/packages/apps/postgres/templates/backup-cronjob.yaml index 9775ca87..1998357a 100644 --- a/packages/apps/postgres/templates/backup-cronjob.yaml +++ b/packages/apps/postgres/templates/backup-cronjob.yaml @@ -13,9 +13,6 @@ spec: jobTemplate: spec: backoffLimit: 2 - template: - spec: - restartPolicy: OnFailure template: metadata: annotations: @@ -24,7 +21,7 @@ spec: spec: imagePullSecrets: - name: {{ .Release.Name }}-regsecret - restartPolicy: Never + restartPolicy: OnFailure containers: - name: pgdump image: "{{ $.Files.Get "images/postgres-backup.tag" | trim }}" diff --git a/packages/apps/versions_map b/packages/apps/versions_map index d6f72293..749d92e0 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -89,7 +89,8 @@ postgres 0.7.0 4b90bf5a postgres 0.7.1 1ec10165 postgres 0.8.0 4e68e65c postgres 0.9.0 8267072d -postgres 0.10.0 HEAD +postgres 0.10.0 721c12a7 +postgres 0.10.1 HEAD rabbitmq 0.1.0 263e47be rabbitmq 0.2.0 53f2365e rabbitmq 0.3.0 6c5cf5bf From f9ec63050929e6f4c78862e9b8591fc83e39f9ef Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 11:39:45 +0200 Subject: [PATCH 009/120] [ci] get rid of ok-to-test label Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 2 +- .github/workflows/pull-requests.yaml | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 815ccb59..b8710be7 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -12,8 +12,8 @@ jobs: contents: read packages: write + # Run only when the PR carries the "release" label and not closed. if: | - contains(github.event.pull_request.labels.*.name, 'ok-to-test') && contains(github.event.pull_request.labels.*.name, 'release') && github.event.action != 'closed' diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 92226c2a..6c25d3cf 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -12,20 +12,9 @@ jobs: contents: read packages: write - # ───────────────────────────────────────────────────────────── - # Run automatically for internal PRs (same repo). - # For external PRs (forks) require the "ok‑to‑test" label. # Never run when the PR carries the "release" label. - # ───────────────────────────────────────────────────────────── if: | - !contains(github.event.pull_request.labels.*.name, 'release') && - ( - github.event.pull_request.head.repo.full_name == github.repository || - ( - github.event.pull_request.head.repo.full_name != github.repository && - contains(github.event.pull_request.labels.*.name, 'ok-to-test') - ) - ) + !contains(github.event.pull_request.labels.*.name, 'release') steps: - name: Checkout code From d54a407d68fee1a91316e723168c080fd5997fdb Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 11:46:26 +0200 Subject: [PATCH 010/120] [ci] Disable pre-commit for release branches Signed-off-by: Andrei Kvapil --- .github/workflows/pre-commit.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 535f483e..8556c2bd 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,14 +1,13 @@ name: Pre-Commit Checks on: - push: - branches: - - main pull_request: + types: [labeled, opened, synchronize, reopened] paths-ignore: - '**.md' + concurrency: - group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: From 9f5230a3424f6328d6bce4dce639f77b2b421173 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 23 Apr 2025 16:55:04 +0200 Subject: [PATCH 011/120] [kubernetes] Refactor controlPlane settings Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Makefile | 4 + packages/apps/kubernetes/README.md | 22 +- .../apps/kubernetes/templates/cluster.yaml | 32 +- .../templates/helmreleases/cert-manager.yaml | 18 +- .../templates/helmreleases/fluxcd.yaml | 19 +- .../templates/helmreleases/gpu-operator.yaml | 18 +- .../templates/helmreleases/ingress-nginx.yaml | 39 +- .../helmreleases/vertical-pod-autoscaler.yaml | 50 ++- packages/apps/kubernetes/values.schema.json | 406 ++++++++++-------- packages/apps/kubernetes/values.yaml | 84 ++-- 10 files changed, 326 insertions(+), 366 deletions(-) diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 03799c2b..1eb92226 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -6,6 +6,10 @@ include ../../../scripts/package.mk generate: readme-generator -v values.yaml -s values.schema.json -r README.md + yq -o json -i '.properties.controlPlane.properties.apiServer.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json + yq -o json -i '.properties.controlPlane.properties.controllerManager.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json + yq -o json -i '.properties.controlPlane.properties.scheduler.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json + yq -o json -i '.properties.controlPlane.properties.konnectivity.properties.server.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt-csi-driver image-cluster-autoscaler diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index 3067a323..94a4ff6e 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -55,18 +55,18 @@ kubectl get secret -n kubernetes--admin-kubeconfig -o g | `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` | | `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` | -### Kamaji control plane +### Kubernetes control plane configuration -| Name | Description | Value | -| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| `kamajiControlPlane.apiServer.resources` | Resources | `{}` | -| `kamajiControlPlane.apiServer.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | -| `kamajiControlPlane.controllerManager.resources` | Resources | `{}` | -| `kamajiControlPlane.controllerManager.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | -| `kamajiControlPlane.scheduler.resources` | Resources | `{}` | -| `kamajiControlPlane.scheduler.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | -| `kamajiControlPlane.addons.konnectivity.server.resources` | Resources | `{}` | -| `kamajiControlPlane.addons.konnectivity.server.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| Name | Description | Value | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `controlPlane.apiServer.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | +| `controlPlane.apiServer.resources` | Resources | `{}` | +| `controlPlane.controllerManager.resources` | Resources | `{}` | +| `controlPlane.controllerManager.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `controlPlane.scheduler.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `controlPlane.scheduler.resources` | Resources | `{}` | +| `controlPlane.konnectivity.server.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | +| `controlPlane.konnectivity.server.resources` | Resources | `{}` | ## U Series diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 385adacc..f6cbb7a0 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -110,22 +110,22 @@ metadata: kamaji.clastix.io/kubeconfig-secret-key: "super-admin.svc" spec: apiServer: - {{- if .Values.kamajiControlPlane.apiServer.resources }} - resources: {{- toYaml .Values.kamajiControlPlane.apiServer.resources | nindent 6 }} - {{- else if ne .Values.kamajiControlPlane.apiServer.resourcesPreset "none" }} - resources: {{- include "resources.preset" (dict "type" .Values.kamajiControlPlane.apiServer.resourcesPreset "Release" .Release) | nindent 6 }} + {{- if .Values.controlPlane.apiServer.resources }} + resources: {{- toYaml .Values.controlPlane.apiServer.resources | nindent 6 }} + {{- else if ne .Values.controlPlane.apiServer.resourcesPreset "none" }} + resources: {{- include "resources.preset" (dict "type" .Values.controlPlane.apiServer.resourcesPreset "Release" .Release) | nindent 6 }} {{- end }} controllerManager: - {{- if .Values.kamajiControlPlane.controllerManager.resources }} - resources: {{- toYaml .Values.kamajiControlPlane.controllerManager.resources | nindent 6 }} - {{- else if ne .Values.kamajiControlPlane.controllerManager.resourcesPreset "none" }} - resources: {{- include "resources.preset" (dict "type" .Values.kamajiControlPlane.controllerManager.resourcesPreset "Release" .Release) | nindent 6 }} + {{- if .Values.controlPlane.controllerManager.resources }} + resources: {{- toYaml .Values.controlPlane.controllerManager.resources | nindent 6 }} + {{- else if ne .Values.controlPlane.controllerManager.resourcesPreset "none" }} + resources: {{- include "resources.preset" (dict "type" .Values.controlPlane.controllerManager.resourcesPreset "Release" .Release) | nindent 6 }} {{- end }} scheduler: - {{- if .Values.kamajiControlPlane.scheduler.resources }} - resources: {{- toYaml .Values.kamajiControlPlane.scheduler.resources | nindent 6 }} - {{- else if ne .Values.kamajiControlPlane.scheduler.resourcesPreset "none" }} - resources: {{- include "resources.preset" (dict "type" .Values.kamajiControlPlane.scheduler.resourcesPreset "Release" .Release) | nindent 6 }} + {{- if .Values.controlPlane.scheduler.resources }} + resources: {{- toYaml .Values.controlPlane.scheduler.resources | nindent 6 }} + {{- else if ne .Values.controlPlane.scheduler.resourcesPreset "none" }} + resources: {{- include "resources.preset" (dict "type" .Values.controlPlane.scheduler.resourcesPreset "Release" .Release) | nindent 6 }} {{- end }} dataStoreName: "{{ $etcd }}" addons: @@ -135,10 +135,10 @@ spec: konnectivity: server: port: 8132 - {{- if .Values.kamajiControlPlane.addons.konnectivity.server.resources }} - resources: {{- toYaml .Values.kamajiControlPlane.addons.konnectivity.server.resources | nindent 10 }} - {{- else if ne .Values.kamajiControlPlane.addons.konnectivity.server.resourcesPreset "none" }} - resources: {{- include "resources.preset" (dict "type" .Values.kamajiControlPlane.addons.konnectivity.server.resourcesPreset "Release" .Release) | nindent 10 }} + {{- if .Values.controlPlane.konnectivity.server.resources }} + resources: {{- toYaml .Values.controlPlane.konnectivity.server.resources | nindent 10 }} + {{- else if ne .Values.controlPlane.konnectivity.server.resourcesPreset "none" }} + resources: {{- include "resources.preset" (dict "type" .Values.controlPlane.konnectivity.server.resourcesPreset "Release" .Release) | nindent 10 }} {{- end }} kubelet: cgroupfs: systemd diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index 3d8bbaa0..3eda96b3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -30,11 +30,9 @@ spec: upgrade: remediation: retries: -1 - {{- if .Values.addons.certManager.valuesOverride }} - valuesFrom: - - kind: Secret - name: {{ .Release.Name }}-cert-manager-values-override - valuesKey: values + {{- with .Values.addons.certManager.valuesOverride }} + values: + {{- toYaml . | nindent 4 }} {{- end }} dependsOn: @@ -47,13 +45,3 @@ spec: - name: {{ .Release.Name }}-cert-manager-crds namespace: {{ .Release.Namespace }} {{- end }} -{{- if .Values.addons.certManager.valuesOverride }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-cert-manager-values-override -stringData: - values: | - {{- toYaml .Values.addons.certManager.valuesOverride | nindent 4 }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index 1a4f982a..c6d514de 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -73,11 +73,9 @@ spec: upgrade: remediation: retries: -1 - {{- if .Values.addons.fluxcd.valuesOverride }} - valuesFrom: - - kind: Secret - name: {{ .Release.Name }}-fluxcd-values-override - valuesKey: values + {{- with .Values.addons.fluxcd.valuesOverride }} + values: + {{- toYaml . | nindent 4 }} {{- end }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} @@ -89,14 +87,3 @@ spec: - name: {{ .Release.Name }}-fluxcd-operator namespace: {{ .Release.Namespace }} {{- end }} - -{{- if .Values.addons.fluxcd.valuesOverride }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-fluxcd-values-override -stringData: - values: | - {{- toYaml .Values.addons.fluxcd.valuesOverride | nindent 4 }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml index 9a003e12..a013b866 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -30,11 +30,9 @@ spec: upgrade: remediation: retries: -1 - {{- if .Values.addons.gpuOperator.valuesOverride }} - valuesFrom: - - kind: Secret - name: {{ .Release.Name }}-gpu-operator-values-override - valuesKey: values + {{- with .Values.addons.gpuOperator.valuesOverride }} + values: + {{- toYaml . | nindent 4 }} {{- end }} dependsOn: @@ -45,13 +43,3 @@ spec: - name: {{ .Release.Name }}-cilium namespace: {{ .Release.Namespace }} {{- end }} -{{- if .Values.addons.gpuOperator.valuesOverride }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-gpu-operator-values-override -stringData: - values: | - {{- toYaml .Values.addons.gpuOperator.valuesOverride | nindent 4 }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index bedb876a..c312c217 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -1,3 +1,15 @@ +{{- define "cozystack.defaultIngressValues" -}} +ingress-nginx: + fullnameOverride: ingress-nginx + controller: + kind: DaemonSet + hostNetwork: true + service: + enabled: false + nodeSelector: + node-role.kubernetes.io/ingress-nginx: "" +{{- end }} + {{- if .Values.addons.ingressNginx.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease @@ -31,21 +43,7 @@ spec: remediation: retries: -1 values: - ingress-nginx: - fullnameOverride: ingress-nginx - controller: - kind: DaemonSet - hostNetwork: true - service: - enabled: false - nodeSelector: - node-role.kubernetes.io/ingress-nginx: "" - {{- if .Values.addons.ingressNginx.valuesOverride }} - valuesFrom: - - kind: Secret - name: {{ .Release.Name }}-ingress-nginx-values-override - valuesKey: values - {{- end }} + {{- toYaml (merge (fromYaml (include "cozystack.defaultIngressValues" .)) .Values.addons.ingressNginx.valuesOverride) | nindent 4 }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} @@ -54,14 +52,3 @@ spec: - name: {{ .Release.Name }}-cilium namespace: {{ .Release.Namespace }} {{- end }} - -{{- if .Values.addons.ingressNginx.valuesOverride }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-ingress-nginx-values-override -stringData: - values: | - {{- toYaml .Values.addons.ingressNginx.valuesOverride | nindent 4 }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index fff634e3..988cc7f2 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -1,5 +1,28 @@ +{{- define "cozystack.defaultVPAValues" -}} {{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} {{- $targetTenant := index $myNS.metadata.annotations "namespace.cozystack.io/monitoring" }} +vertical-pod-autoscaler: + recommender: + extraArgs: + container-name-label: container + container-namespace-label: namespace + container-pod-name-label: pod + storage: prometheus + memory-saver: true + pod-label-prefix: label_ + metric-for-pod-labels: kube_pod_labels{job="kube-state-metrics", tenant="{{ .Release.Namespace }}", cluster="{{ .Release.Name }}"}[8d] + pod-name-label: pod + pod-namespace-label: namespace + prometheus-address: http://vmselect-shortterm.{{ $targetTenant }}.svc.cozy.local:8481/select/0/prometheus/ + prometheus-cadvisor-job-name: cadvisor + resources: + limits: + memory: 1600Mi + requests: + cpu: 100m + memory: 1600Mi +{{- end }} + {{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease @@ -33,32 +56,7 @@ spec: remediation: retries: -1 values: - vertical-pod-autoscaler: - recommender: - extraArgs: - container-name-label: container - container-namespace-label: namespace - container-pod-name-label: pod - storage: prometheus - memory-saver: true - pod-label-prefix: label_ - metric-for-pod-labels: kube_pod_labels{job="kube-state-metrics", tenant="{{ .Release.Namespace }}", cluster="{{ .Release.Name }}"}[8d] - pod-name-label: pod - pod-namespace-label: namespace - prometheus-address: http://vmselect-shortterm.{{ $targetTenant }}.svc.cozy.local:8481/select/0/prometheus/ - prometheus-cadvisor-job-name: cadvisor - resources: - limits: - memory: 1600Mi - requests: - cpu: 100m - memory: 1600Mi - {{- if .Values.addons.verticalPodAutoscaler.valuesOverride }} - valuesFrom: - - kind: Secret - name: {{ .Release.Name }}-vertical-pod-autoscaler-values-override - valuesKey: values - {{- end }} + {{- toYaml (merge (fromYaml (include "cozystack.defaultVPAValues" .)) .Values.addons.verticalPodAutoscaler.valuesOverride) | nindent 4 }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index 58e63f1e..c69a30aa 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -1,197 +1,227 @@ { - "title": "Chart Values", - "type": "object", - "properties": { - "host": { - "type": "string", - "description": "The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host).", - "default": "" + "title": "Chart Values", + "type": "object", + "properties": { + "host": { + "type": "string", + "description": "The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host).", + "default": "" + }, + "controlPlane": { + "type": "object", + "properties": { + "replicas": { + "type": "number", + "description": "Number of replicas for Kubernetes control-plane components", + "default": 2 }, - "controlPlane": { - "type": "object", - "properties": { - "replicas": { - "type": "number", - "description": "Number of replicas for Kubernetes control-plane components", - "default": 2 - } + "apiServer": { + "type": "object", + "properties": { + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "small", + "enum": [ + "none", + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "resources": { + "type": "object", + "description": "Resources", + "default": {} } + } }, - "storageClass": { - "type": "string", - "description": "StorageClass used to store user data", - "default": "replicated" - }, - "addons": { - "type": "object", - "properties": { - "certManager": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enables the cert-manager", - "default": false - }, - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - } - } - }, - "ingressNginx": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role)", - "default": false - }, - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - }, - "hosts": { - "type": "array", - "description": "List of domain names that should be passed through to the cluster by upper cluster", - "default": [], - "items": {} - } - } - }, - "gpuOperator": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enables the gpu-operator", - "default": false - }, - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - } - } - }, - "fluxcd": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enables Flux CD", - "default": false - }, - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - } - } - }, - "monitoringAgents": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage", - "default": false - }, - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - } - } - }, - "verticalPodAutoscaler": { - "type": "object", - "properties": { - "valuesOverride": { - "type": "object", - "description": "Custom values to override", - "default": {} - } - } - } + "controllerManager": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "description": "Resources", + "default": {} + }, + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro", + "enum": [ + "none", + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] } + } }, - "kamajiControlPlane": { - "type": "object", - "properties": { - "apiServer": { - "type": "object", - "properties": { - "resources": { - "type": "object", - "description": "Resources", - "default": {} - }, - "resourcesPreset": { - "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", - "default": "small" - } - } - }, - "controllerManager": { - "type": "object", - "properties": { - "resources": { - "type": "object", - "description": "Resources", - "default": {} - }, - "resourcesPreset": { - "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", - "default": "micro" - } - } - }, - "scheduler": { - "type": "object", - "properties": { - "resources": { - "type": "object", - "description": "Resources", - "default": {} - }, - "resourcesPreset": { - "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", - "default": "micro" - } - } - }, - "addons": { - "type": "object", - "properties": { - "konnectivity": { - "type": "object", - "properties": { - "server": { - "type": "object", - "properties": { - "resources": { - "type": "object", - "description": "Resources", - "default": {} - }, - "resourcesPreset": { - "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", - "default": "micro" - } - } - } - } - } - } - } + "scheduler": { + "type": "object", + "properties": { + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro", + "enum": [ + "none", + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "resources": { + "type": "object", + "description": "Resources", + "default": {} } + } + }, + "konnectivity": { + "type": "object", + "properties": { + "server": { + "type": "object", + "properties": { + "resourcesPreset": { + "type": "string", + "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "default": "micro", + "enum": [ + "none", + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "resources": { + "type": "object", + "description": "Resources", + "default": {} + } + } + } + } } + } + }, + "storageClass": { + "type": "string", + "description": "StorageClass used to store user data", + "default": "replicated" + }, + "addons": { + "type": "object", + "properties": { + "certManager": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables the cert-manager", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, + "ingressNginx": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role)", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + }, + "hosts": { + "type": "array", + "description": "List of domain names that should be passed through to the cluster by upper cluster", + "default": [], + "items": {} + } + } + }, + "gpuOperator": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables the gpu-operator", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, + "fluxcd": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables Flux CD", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, + "monitoringAgents": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage", + "default": false + }, + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, + "verticalPodAutoscaler": { + "type": "object", + "properties": { + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + } + } } -} \ No newline at end of file + } +} diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index f18e43d2..388c465b 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -5,8 +5,6 @@ ## @param storageClass StorageClass used to store user data ## host: "" -controlPlane: - replicas: 2 storageClass: replicated ## @param nodeGroups [object] nodeGroups configuration @@ -93,62 +91,42 @@ addons: ## valuesOverride: {} -## @section Kamaji control plane +## @section Kubernetes control plane configuration ## -kamajiControlPlane: + +controlPlane: + replicas: 2 + apiServer: - ## @param kamajiControlPlane.apiServer.resources Resources - resources: {} - # resources: - # limits: - # cpu: 4000m - # memory: 4Gi - # requests: - # cpu: 100m - # memory: 512Mi - - ## @param kamajiControlPlane.apiServer.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.apiServer.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.apiServer.resources Resources + ## e.g: + ## resources: + ## limits: + ## cpu: 4000m + ## memory: 4Gi + ## requests: + ## cpu: 100m + ## memory: 512Mi + ## resourcesPreset: "small" + resources: {} controllerManager: - ## @param kamajiControlPlane.controllerManager.resources Resources - resources: {} - # resources: - # limits: - # cpu: 4000m - # memory: 4Gi - # requests: - # cpu: 100m - # memory: 512Mi - - ## @param kamajiControlPlane.controllerManager.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.controllerManager.resources Resources + ## @param controlPlane.controllerManager.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). resourcesPreset: "micro" + resources: {} + scheduler: - ## @param kamajiControlPlane.scheduler.resources Resources - resources: {} - # resources: - # limits: - # cpu: 4000m - # memory: 4Gi - # requests: - # cpu: 100m - # memory: 512Mi - - ## @param kamajiControlPlane.scheduler.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.scheduler.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.scheduler.resources Resources resourcesPreset: "micro" - addons: - konnectivity: - server: - ## @param kamajiControlPlane.addons.konnectivity.server.resources Resources - resources: {} - # resources: - # limits: - # cpu: 4000m - # memory: 4Gi - # requests: - # cpu: 100m - # memory: 512Mi - - ## @param kamajiControlPlane.addons.konnectivity.server.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). - resourcesPreset: "micro" - + resources: {} + + konnectivity: + server: + ## @param controlPlane.konnectivity.server.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.konnectivity.server.resources Resources + resourcesPreset: "micro" + resources: {} From 3ed0cdee1c28fd75e14779c3795bb119b1e3c3a3 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 10:36:55 +0200 Subject: [PATCH 012/120] [kubernetes] Update tenant Kubernetes to v1.32 Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Makefile | 7 ++++--- .../images/ubuntu-container-disk/Dockerfile | 11 ++++++++--- packages/apps/kubernetes/templates/cluster.yaml | 2 +- .../kubernetes/templates/helmreleases/delete.yaml | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 03799c2b..362161e9 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -1,4 +1,4 @@ -UBUNTU_CONTAINER_DISK_TAG = v1.30.1 +KUBERNETES_VERSION = v1.32 KUBERNETES_PKG_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) include ../../../scripts/common-envs.mk @@ -12,8 +12,9 @@ image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt- image-ubuntu-container-disk: docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/ubuntu-container-disk \ --provenance false \ - --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(UBUNTU_CONTAINER_DISK_TAG)) \ - --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(UBUNTU_CONTAINER_DISK_TAG)-$(TAG)) \ + --build-arg KUBERNETES_VERSION=${KUBERNETES_VERSION} \ + --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)) \ + --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/ubuntu-container-disk:latest \ --cache-to type=inline \ --metadata-file images/ubuntu-container-disk.json \ diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile index eb08ef10..395adeb0 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile +++ b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile @@ -1,3 +1,4 @@ +# TODO: Here we use ubuntu:22.04, as guestfish has some network issues running in ubuntu:24.04 FROM ubuntu:22.04 as guestfish ARG DEBIAN_FRONTEND=noninteractive @@ -5,6 +6,7 @@ RUN apt-get update \ && apt-get -y install \ libguestfs-tools \ linux-image-generic \ + wget \ make \ bash-completion \ && apt-get clean @@ -13,7 +15,10 @@ WORKDIR /build FROM guestfish as builder -RUN wget -O image.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img +# noble is a code name for the Ubuntu 24.04 LTS release +RUN wget -O image.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null + +ARG KUBERNETES_VERSION RUN qemu-img resize image.img 5G \ && eval "$(guestfish --listen --network)" \ @@ -26,8 +31,8 @@ RUN qemu-img resize image.img 5G \ && guestfish --remote sh "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg" \ && guestfish --remote sh 'echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list' \ # kubernetes repo - && guestfish --remote sh "curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg" \ - && guestfish --remote sh "echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list" \ + && guestfish --remote sh "curl -fsSL https://pkgs.k8s.io/core:/stable:/${KUBERNETES_VERSION}/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg" \ + && guestfish --remote sh "echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/${KUBERNETES_VERSION}/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list" \ # install containerd && guestfish --remote command "apt-get update -y" \ && guestfish --remote command "apt-get install -y containerd.io" \ diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 385adacc..031bf5c1 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -283,7 +283,7 @@ spec: kind: KubevirtMachineTemplate name: {{ $.Release.Name }}-{{ $groupName }}-{{ $kubevirtmachinetemplateHash }} namespace: {{ $.Release.Namespace }} - version: v1.30.1 + version: v1.32.3 --- apiVersion: cluster.x-k8s.io/v1beta1 kind: MachineHealthCheck diff --git a/packages/apps/kubernetes/templates/helmreleases/delete.yaml b/packages/apps/kubernetes/templates/helmreleases/delete.yaml index 10a8d995..6402617c 100644 --- a/packages/apps/kubernetes/templates/helmreleases/delete.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/delete.yaml @@ -20,7 +20,7 @@ spec: effect: "NoSchedule" containers: - name: kubectl - image: docker.io/clastix/kubectl:v1.30.1 + image: docker.io/clastix/kubectl:v1.32 command: - /bin/sh - -c From 59ef3296f0145c56d5ab460bae4f6d4ebf117722 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 13:55:56 +0200 Subject: [PATCH 013/120] [ci] Fix uploading assets to release Signed-off-by: Andrei Kvapil --- .github/workflows/tags.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index f50c9b0a..270aa717 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -170,7 +170,7 @@ jobs: if: steps.check_release.outputs.skip == 'false' run: | make assets - make upload_assets VERSION=${{ steps.tag.outputs.version }} + make upload_assets VERSION=${{ steps.tag.outputs.tag }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1ccd3074dcf89f9b328044d3abbcc9c416d06674 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 14:24:07 +0200 Subject: [PATCH 014/120] [kubernetes] Fix merging valuesOverride for tenant clusters Signed-off-by: Andrei Kvapil --- .../apps/kubernetes/templates/helmreleases/ingress-nginx.yaml | 2 +- .../templates/helmreleases/vertical-pod-autoscaler.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index c312c217..1bcbf422 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -43,7 +43,7 @@ spec: remediation: retries: -1 values: - {{- toYaml (merge (fromYaml (include "cozystack.defaultIngressValues" .)) .Values.addons.ingressNginx.valuesOverride) | nindent 4 }} + {{- toYaml (deepCopy .Values.addons.ingressNginx.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultIngressValues" .))) | nindent 4 }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index 988cc7f2..af83f4f3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -56,7 +56,7 @@ spec: remediation: retries: -1 values: - {{- toYaml (merge (fromYaml (include "cozystack.defaultVPAValues" .)) .Values.addons.verticalPodAutoscaler.valuesOverride) | nindent 4 }} + {{- toYaml (deepCopy .Values.addons.verticalPodAutoscaler.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultVPAValues" .))) | nindent 4 }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} From 44565dca884aa1f8e7ee1842f4a86c15ccbc27b2 Mon Sep 17 00:00:00 2001 From: Kingdon B Date: Thu, 24 Apr 2025 08:25:29 -0400 Subject: [PATCH 015/120] [fluxcd] update to flux-operator 0.19.0 Signed-off-by: Kingdon B --- .../charts/flux-operator/Chart.yaml | 4 +- .../charts/flux-operator/README.md | 3 +- .../templates/admin-clusterrole.yaml | 2 +- .../charts/flux-operator/templates/crds.yaml | 12 ++++++ .../flux-operator/templates/flowschema.yaml | 41 +++++++++++++++++++ .../charts/flux-operator/values.schema.json | 19 +++++++++ .../charts/flux-operator/values.yaml | 10 +++++ .../fluxcd/charts/flux-instance/Chart.yaml | 4 +- .../fluxcd/charts/flux-instance/README.md | 2 +- 9 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 packages/system/fluxcd-operator/charts/flux-operator/templates/flowschema.yaml diff --git a/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml b/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml index 93402076..95ce6ee5 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml +++ b/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml @@ -8,7 +8,7 @@ annotations: - name: Upstream Project url: https://github.com/controlplaneio-fluxcd/flux-operator apiVersion: v2 -appVersion: v0.18.0 +appVersion: v0.19.0 description: 'A Helm chart for deploying the Flux Operator. ' home: https://github.com/controlplaneio-fluxcd icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png @@ -25,4 +25,4 @@ sources: - https://github.com/controlplaneio-fluxcd/flux-operator - https://github.com/controlplaneio-fluxcd/charts type: application -version: 0.18.0 +version: 0.19.0 diff --git a/packages/system/fluxcd-operator/charts/flux-operator/README.md b/packages/system/fluxcd-operator/charts/flux-operator/README.md index 7a1090ac..627a81ab 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/README.md +++ b/packages/system/fluxcd-operator/charts/flux-operator/README.md @@ -1,6 +1,6 @@ # flux-operator -![Version: 0.18.0](https://img.shields.io/badge/Version-0.18.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.18.0](https://img.shields.io/badge/AppVersion-v0.18.0-informational?style=flat-square) +![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) The [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator) provides a declarative API for the installation and upgrade of CNCF [Flux](https://fluxcd.io) and the @@ -33,6 +33,7 @@ see the Flux Operator [documentation](https://fluxcd.control-plane.io/operator/) | Key | Type | Default | Description | |-----|------|---------|-------------| | affinity | object | `{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"kubernetes.io/os","operator":"In","values":["linux"]}]}]}}}` | Pod affinity and anti-affinity settings. | +| apiPriority | object | `{"enabled":false,"extraServiceAccounts":[],"level":"workload-high"}` | Kubernetes [API priority and fairness](https://kubernetes.io/docs/concepts/cluster-administration/flow-control/) settings. | | commonAnnotations | object | `{}` | Common annotations to add to all deployed objects including pods. | | commonLabels | object | `{}` | Common labels to add to all deployed objects including pods. | | extraArgs | list | `[]` | Container extra arguments. | diff --git a/packages/system/fluxcd-operator/charts/flux-operator/templates/admin-clusterrole.yaml b/packages/system/fluxcd-operator/charts/flux-operator/templates/admin-clusterrole.yaml index ae7382df..abbf8990 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/templates/admin-clusterrole.yaml +++ b/packages/system/fluxcd-operator/charts/flux-operator/templates/admin-clusterrole.yaml @@ -18,6 +18,6 @@ roleRef: name: cluster-admin subjects: - kind: ServiceAccount - name: {{ include "flux-operator.fullname" . }} + name: {{ include "flux-operator.serviceAccountName" . }} namespace: {{ .Release.Namespace }} {{- end }} diff --git a/packages/system/fluxcd-operator/charts/flux-operator/templates/crds.yaml b/packages/system/fluxcd-operator/charts/flux-operator/templates/crds.yaml index acdfed24..ff47d2c7 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/templates/crds.yaml +++ b/packages/system/fluxcd-operator/charts/flux-operator/templates/crds.yaml @@ -878,6 +878,18 @@ spec: required: - name type: object + skip: + description: Skip defines whether we need to skip input provider response + updates. + properties: + labels: + description: |- + Labels specifies list of labels to skip input provider response when any of the label conditions matched. + When prefixed with !, input provider response will be skipped if it does not have this label. + items: + type: string + type: array + type: object type: description: Type specifies the type of the input provider. enum: diff --git a/packages/system/fluxcd-operator/charts/flux-operator/templates/flowschema.yaml b/packages/system/fluxcd-operator/charts/flux-operator/templates/flowschema.yaml new file mode 100644 index 00000000..b01fab11 --- /dev/null +++ b/packages/system/fluxcd-operator/charts/flux-operator/templates/flowschema.yaml @@ -0,0 +1,41 @@ +{{- if .Values.apiPriority.enabled }} +apiVersion: flowcontrol.apiserver.k8s.io/v1 +kind: FlowSchema +metadata: + name: {{ include "flux-operator.fullname" . }} + annotations: + apf.kubernetes.io/autoupdate-spec: "false" +spec: + distinguisherMethod: + type: ByUser + matchingPrecedence: 950 + priorityLevelConfiguration: + name: {{ .Values.apiPriority.level }} + rules: + - nonResourceRules: + - nonResourceURLs: + - '*' + verbs: + - '*' + resourceRules: + - apiGroups: + - '*' + clusterScope: true + namespaces: + - '*' + resources: + - '*' + verbs: + - '*' + subjects: + - kind: ServiceAccount + serviceAccount: + name: {{ include "flux-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + {{- range .Values.apiPriority.extraServiceAccounts }} + - kind: ServiceAccount + serviceAccount: + name: {{ .name }} + namespace: {{ .namespace }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd-operator/charts/flux-operator/values.schema.json b/packages/system/fluxcd-operator/charts/flux-operator/values.schema.json index b033d9f6..dc277e55 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/values.schema.json +++ b/packages/system/fluxcd-operator/charts/flux-operator/values.schema.json @@ -63,6 +63,25 @@ }, "type": "object" }, + "apiPriority": { + "default": { + "enabled": false, + "extraServiceAccounts": [], + "level": "workload-high" + }, + "properties": { + "enabled": { + "type": "boolean" + }, + "extraServiceAccounts": { + "type": "array" + }, + "level": { + "type": "string" + } + }, + "type": "object" + }, "commonAnnotations": { "properties": {}, "type": "object" diff --git a/packages/system/fluxcd-operator/charts/flux-operator/values.yaml b/packages/system/fluxcd-operator/charts/flux-operator/values.yaml index f1accd65..91cad9d2 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/values.yaml +++ b/packages/system/fluxcd-operator/charts/flux-operator/values.yaml @@ -33,6 +33,16 @@ image: # Recommended value is system-cluster-critical. priorityClassName: "" # @schema default: "system-cluster-critical" +# -- Kubernetes [API priority and fairness](https://kubernetes.io/docs/concepts/cluster-administration/flow-control/) settings. +apiPriority: # @schema default: {"enabled":false,"level":"workload-high","extraServiceAccounts":[]} + enabled: false + level: workload-high + extraServiceAccounts: [] +# - name: kustomize-controller +# namespace: flux-system +# - name: helm-controller +# namespace: flux-system + # -- Container resources requests and limits settings. resources: # @schema required: true limits: diff --git a/packages/system/fluxcd/charts/flux-instance/Chart.yaml b/packages/system/fluxcd/charts/flux-instance/Chart.yaml index a065c181..be942dd5 100644 --- a/packages/system/fluxcd/charts/flux-instance/Chart.yaml +++ b/packages/system/fluxcd/charts/flux-instance/Chart.yaml @@ -8,7 +8,7 @@ annotations: - name: Upstream Project url: https://github.com/controlplaneio-fluxcd/flux-operator apiVersion: v2 -appVersion: v0.18.0 +appVersion: v0.19.0 description: 'A Helm chart for deploying a Flux instance managed by Flux Operator. ' home: https://github.com/controlplaneio-fluxcd icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png @@ -25,4 +25,4 @@ sources: - https://github.com/controlplaneio-fluxcd/flux-operator - https://github.com/controlplaneio-fluxcd/charts type: application -version: 0.18.0 +version: 0.19.0 diff --git a/packages/system/fluxcd/charts/flux-instance/README.md b/packages/system/fluxcd/charts/flux-instance/README.md index d56bb5f2..ccd29096 100644 --- a/packages/system/fluxcd/charts/flux-instance/README.md +++ b/packages/system/fluxcd/charts/flux-instance/README.md @@ -1,6 +1,6 @@ # flux-instance -![Version: 0.18.0](https://img.shields.io/badge/Version-0.18.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.18.0](https://img.shields.io/badge/AppVersion-v0.18.0-informational?style=flat-square) +![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) This chart is a thin wrapper around the `FluxInstance` custom resource, which is used by the [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator) From 7db727763610e7856f525f8d6582574d0a4bca4f Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 14:59:12 +0200 Subject: [PATCH 016/120] [ci] Do not run tests in release building pipeline Signed-off-by: Andrei Kvapil --- .github/workflows/tags.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index d0e61aa2..876766e5 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -248,8 +248,3 @@ jobs: } else { console.log(`PR already exists from ${head} to ${base}`); } - - # Run tests - - name: Test - if: steps.check_release.outputs.skip == 'false' - run: make test From e3e0b216122d2109a2c36887f3c7620798303219 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 15:36:25 +0200 Subject: [PATCH 017/120] [kube-ovn] fix versions mapping in Makefile Signed-off-by: Andrei Kvapil --- packages/system/kubeovn/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/system/kubeovn/Makefile b/packages/system/kubeovn/Makefile index e2fed120..be01e9c5 100644 --- a/packages/system/kubeovn/Makefile +++ b/packages/system/kubeovn/Makefile @@ -1,4 +1,4 @@ -KUBEOVN_TAG=$(shell awk '$$1 == "version:" {print $$2}' charts/kubeovn/Chart.yaml) +KUBEOVN_TAG=$(shell awk '$$1 == "version:" {print $$2}' charts/kube-ovn/Chart.yaml) export NAME=kubeovn export NAMESPACE=cozy-$(NAME) From de0c7b94f4b01291d9d98573083b4e3ccb087ad4 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 15:55:46 +0200 Subject: [PATCH 018/120] [ci] fix release branch creation Signed-off-by: Andrei Kvapil --- .github/workflows/tags.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 9f08f15c..5cc32c42 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -195,7 +195,7 @@ jobs: }); console.log(`Branch '${branch}' already exists`); } catch (_) { - await github.git.createRef({ + await github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: `refs/heads/${branch}`, From 590f14a6140f2ff757ad8e3dc781c38775479d9f Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 16:19:09 +0200 Subject: [PATCH 019/120] =?UTF-8?q?[ci]=20Create=20long=E2=80=91lived=20ma?= =?UTF-8?q?intenance=20branch=20after=20release=20published?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 30 ++++++++++++++++++++ .github/workflows/tags.yaml | 26 ----------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 8a863ea9..bc955f55 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -76,6 +76,36 @@ jobs: git tag -f ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} git push -f origin ${{ steps.get_tag.outputs.tag }} + # Ensure maintenance branch release-X.Y + - name: Ensure maintenance branch release-X.Y + uses: actions/github-script@v7 + with: + script: | + const tag = '${{ steps.get_tag.outputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 + const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); + if (!match) { + core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-suffix'`); + return; + } + const line = `${match[1]}.${match[2]}`; + const branch = `release-${line}`; + try { + await github.rest.repos.getBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + branch + }); + console.log(`Branch '${branch}' already exists`); + } catch (_) { + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/heads/${branch}`, + sha: context.sha + }); + console.log(`✅ Branch '${branch}' created at ${context.sha}`); + } + # Get the latest published release - name: Get the latest published release id: latest_release diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 5cc32c42..34e13a76 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -178,32 +178,6 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Ensure long‑lived maintenance branch release‑X.Y - - name: Ensure maintenance branch release‑${{ steps.tag.outputs.line }} - if: | - steps.check_release.outputs.skip == 'false' && - steps.get_base.outputs.branch == 'main' - uses: actions/github-script@v7 - with: - script: | - const branch = `release-${'${{ steps.tag.outputs.line }}'}`; - try { - await github.rest.repos.getBranch({ - owner: context.repo.owner, - repo: context.repo.repo, - branch - }); - console.log(`Branch '${branch}' already exists`); - } catch (_) { - await github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `refs/heads/${branch}`, - sha: context.sha - }); - console.log(`Branch '${branch}' created at ${context.sha}`); - } - # Create release‑X.Y.Z branch and push (force‑update) - name: Create release branch if: steps.check_release.outputs.skip == 'false' From a0935e9ae47ddf71f022f1f55aeaa665f6303564 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 24 Apr 2025 16:38:42 +0200 Subject: [PATCH 020/120] [kubernetes] Fix ubuntu-container-disk tag Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 2ce5cdfd..45b97f69 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -25,7 +25,7 @@ image-ubuntu-container-disk: --push=$(PUSH) \ --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \ --load=$(LOAD) - echo "$(REGISTRY)/ubuntu-container-disk:$(call settag,$(UBUNTU_CONTAINER_DISK_TAG))@$$(yq e '."containerimage.digest"' images/ubuntu-container-disk.json -o json -r)" \ + echo "$(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION))@$$(yq e '."containerimage.digest"' images/ubuntu-container-disk.json -o json -r)" \ > images/ubuntu-container-disk.tag rm -f images/ubuntu-container-disk.json From 076128c783280d55f87c6e65e5ecf17699004928 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 12:07:30 +0200 Subject: [PATCH 021/120] [platform] Fix installing release candidate versions Signed-off-by: Andrei Kvapil --- packages/apps/bucket/templates/helmrelease.yaml | 2 +- .../kubernetes/templates/helmreleases/cert-manager-crds.yaml | 1 + .../apps/kubernetes/templates/helmreleases/cert-manager.yaml | 1 + packages/apps/kubernetes/templates/helmreleases/cilium.yaml | 1 + packages/apps/kubernetes/templates/helmreleases/csi.yaml | 1 + packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml | 2 ++ .../apps/kubernetes/templates/helmreleases/gpu-operator.yaml | 1 + .../apps/kubernetes/templates/helmreleases/ingress-nginx.yaml | 1 + .../kubernetes/templates/helmreleases/monitoring-agents.yaml | 1 + .../templates/helmreleases/vertical-pod-autoscaler-crds.yaml | 1 + .../templates/helmreleases/vertical-pod-autoscaler.yaml | 1 + .../templates/helmreleases/victoria-metrics-operator.yaml | 1 + packages/apps/nats/templates/nats.yaml | 2 +- packages/core/platform/templates/helmreleases.yaml | 1 + packages/extra/ingress/templates/nginx-ingress.yaml | 2 +- packages/extra/seaweedfs/templates/seaweedfs.yaml | 2 +- 16 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/apps/bucket/templates/helmrelease.yaml b/packages/apps/bucket/templates/helmrelease.yaml index ac014e03..d51e3b36 100644 --- a/packages/apps/bucket/templates/helmrelease.yaml +++ b/packages/apps/bucket/templates/helmrelease.yaml @@ -11,7 +11,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system - version: '*' + version: '>= 0.0.0-0' interval: 1m0s timeout: 5m0s values: diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml index 04080631..21b7ba4d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml @@ -16,6 +16,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index 3eda96b3..3a6e4939 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -17,6 +17,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index 4edc3c24..6b03bdb3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -16,6 +16,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml index ec6092f0..8bbb1b9d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/csi.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -16,6 +16,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index c6d514de..944ce8cf 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -17,6 +17,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig @@ -61,6 +62,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml index a013b866..861c3657 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -17,6 +17,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index 1bcbf422..d81e16e6 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -29,6 +29,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index dac132fc..f046ff0d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -19,6 +19,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml index 9c901457..336c198b 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml @@ -17,6 +17,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index af83f4f3..a4b6c431 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -42,6 +42,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml index e47ea4f3..91445c45 100644 --- a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml @@ -17,6 +17,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/nats/templates/nats.yaml b/packages/apps/nats/templates/nats.yaml index 019c7984..0041379a 100644 --- a/packages/apps/nats/templates/nats.yaml +++ b/packages/apps/nats/templates/nats.yaml @@ -33,7 +33,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system - version: '*' + version: '>= 0.0.0-0' interval: 1m0s timeout: 5m0s values: diff --git a/packages/core/platform/templates/helmreleases.yaml b/packages/core/platform/templates/helmreleases.yaml index ef04d3cc..1298d74b 100644 --- a/packages/core/platform/templates/helmreleases.yaml +++ b/packages/core/platform/templates/helmreleases.yaml @@ -55,6 +55,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system + version: '>= 0.0.0-0' {{- with $x.valuesFiles }} valuesFiles: {{- toYaml $x.valuesFiles | nindent 6 }} diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index d0b67be4..cfc29d1f 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -11,7 +11,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system - version: '*' + version: '>= 0.0.0-0' interval: 1m0s timeout: 5m0s values: diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml index b9846aa1..a2fcb30c 100644 --- a/packages/extra/seaweedfs/templates/seaweedfs.yaml +++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml @@ -14,7 +14,7 @@ spec: kind: HelmRepository name: cozystack-system namespace: cozy-system - version: '*' + version: '>= 0.0.0-0' interval: 1m0s timeout: 5m0s values: From 79b5c6b5afdbe1a55a0cb54ad49ad8d1667c652e Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 12:13:40 +0200 Subject: [PATCH 022/120] [platform] Use devel versions notation for HelmCharts Signed-off-by: Andrei Kvapil --- packages/system/Makefile | 2 +- scripts/common-envs.mk | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/system/Makefile b/packages/system/Makefile index e40b0bf1..2031c3a0 100644 --- a/packages/system/Makefile +++ b/packages/system/Makefile @@ -5,7 +5,7 @@ include ../../scripts/common-envs.mk repo: rm -rf "$(OUT)" mkdir -p "$(OUT)" - helm package -d "$(OUT)" $$(find . -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")') --version $(VERSION) + helm package -d "$(OUT)" $$(find . -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")') --version $(COZYSTACK_VERSION) cd "$(OUT)" && helm repo index . fix-chartnames: diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index 78e5e8a1..99bc29eb 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -1,7 +1,7 @@ REGISTRY := ghcr.io/cozystack/cozystack PUSH := 1 LOAD := 0 -VERSION = $(patsubst v%,%,$(shell git describe --tags --abbrev=0)) +COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) TAG = $(shell git describe --tags --exact-match 2>/dev/null || echo latest) # Returns 'latest' if the git tag is not assigned, otherwise returns the provided value @@ -9,8 +9,8 @@ define settag $(if $(filter $(TAG),latest),latest,$(1)) endef -ifeq ($(VERSION),) +ifeq ($(COZYSTACK_VERSION),) $(shell git remote add upstream https://github.com/cozystack/cozystack.git || true) $(shell git fetch upstream --tags) - VERSION = $(patsubst v%,%,$(shell git describe --tags --abbrev=0)) + COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) endif From 69b3ddf71721b8bf3fed31a25540391f479c6808 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 12:21:49 +0200 Subject: [PATCH 023/120] [e2e] Better output in case of failed HelmReleases Signed-off-by: Andrei Kvapil --- hack/e2e.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hack/e2e.sh b/hack/e2e.sh index 26401225..b11717e7 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -231,8 +231,15 @@ timeout 60 sh -c 'until kubectl get hr -A | grep cozy; do sleep 1; done' sleep 5 +# Wait for all HelmReleases to be installed kubectl get hr -A | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n " $1 " hr/" $2 " &"} END{print "wait"}' | sh -x +failed_hrs=$(kubectl get hr -A | grep -v True) +if [ -n "$(echo "$failed_hrs" | grep -v NAME)" ]; then + printf 'Failed HelmReleases:\n%s\n' "$failed_hrs" >&2 + exit 1 +fi + # Wait for Cluster-API providers timeout 60 sh -c 'until kubectl get deploy -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager; do sleep 1; done' kubectl wait deploy --timeout=1m --for=condition=available -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager From 5d7e56bffe9bbfc8b634628a3e743cfad444bfcc Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 12:28:03 +0200 Subject: [PATCH 024/120] [tests] refactor tests and remove e2e.applications Signed-off-by: Andrei Kvapil --- Makefile | 1 - hack/e2e.application.sh | 165 --------------------------- hack/testdata/http-cache/check.sh | 1 - hack/testdata/http-cache/values.yaml | 2 - hack/testdata/kubernetes/check.sh | 1 - hack/testdata/kubernetes/values.yaml | 62 ---------- hack/testdata/nats/check.sh | 1 - hack/testdata/nats/values.yaml | 10 -- hack/testdata/tenant/check.sh | 1 - hack/testdata/tenant/values.yaml | 6 - packages/core/testing/Makefile | 25 +--- 11 files changed, 1 insertion(+), 274 deletions(-) delete mode 100755 hack/e2e.application.sh delete mode 100644 hack/testdata/http-cache/check.sh delete mode 100644 hack/testdata/http-cache/values.yaml delete mode 100644 hack/testdata/kubernetes/check.sh delete mode 100644 hack/testdata/kubernetes/values.yaml delete mode 100644 hack/testdata/nats/check.sh delete mode 100644 hack/testdata/nats/values.yaml delete mode 100644 hack/testdata/tenant/check.sh delete mode 100644 hack/testdata/tenant/values.yaml diff --git a/Makefile b/Makefile index 6ea3ffd5..99309f4e 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,6 @@ assets: test: make -C packages/core/testing apply make -C packages/core/testing test - #make -C packages/core/testing test-applications generate: hack/update-codegen.sh diff --git a/hack/e2e.application.sh b/hack/e2e.application.sh deleted file mode 100755 index 792630de..00000000 --- a/hack/e2e.application.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash - -RED='\033[0;31m' -GREEN='\033[0;32m' -RESET='\033[0m' -YELLOW='\033[0;33m' - - -ROOT_NS="tenant-root" -TEST_TENANT="tenant-e2e" - -values_base_path="/hack/testdata/" -checks_base_path="/hack/testdata/" - -function delete_hr() { - local release_name="$1" - local namespace="$2" - - if [[ -z "$release_name" ]]; then - echo -e "${RED}Error: Release name is required.${RESET}" - exit 1 - fi - - if [[ -z "$namespace" ]]; then - echo -e "${RED}Error: Namespace name is required.${RESET}" - exit 1 - fi - - if [[ "$release_name" == "tenant-e2e" ]]; then - echo -e "${YELLOW}Skipping deletion for release tenant-e2e.${RESET}" - return 0 - fi - - kubectl delete helmrelease $release_name -n $namespace -} - -function install_helmrelease() { - local release_name="$1" - local namespace="$2" - local chart_path="$3" - local repo_name="$4" - local repo_ns="$5" - local values_file="$6" - - if [[ -z "$release_name" ]]; then - echo -e "${RED}Error: Release name is required.${RESET}" - exit 1 - fi - - if [[ -z "$namespace" ]]; then - echo -e "${RED}Error: Namespace name is required.${RESET}" - exit 1 - fi - - if [[ -z "$chart_path" ]]; then - echo -e "${RED}Error: Chart path name is required.${RESET}" - exit 1 - fi - - if [[ -n "$values_file" && -f "$values_file" ]]; then - local values_section - values_section=$(echo " values:" && sed 's/^/ /' "$values_file") - fi - - local helmrelease_file=$(mktemp /tmp/HelmRelease.XXXXXX.yaml) - { - echo "apiVersion: helm.toolkit.fluxcd.io/v2" - echo "kind: HelmRelease" - echo "metadata:" - echo " labels:" - echo " cozystack.io/ui: \"true\"" - echo " name: \"$release_name\"" - echo " namespace: \"$namespace\"" - echo "spec:" - echo " chart:" - echo " spec:" - echo " chart: \"$chart_path\"" - echo " reconcileStrategy: Revision" - echo " sourceRef:" - echo " kind: HelmRepository" - echo " name: \"$repo_name\"" - echo " namespace: \"$repo_ns\"" - echo " version: '*'" - echo " interval: 1m0s" - echo " timeout: 5m0s" - [[ -n "$values_section" ]] && echo "$values_section" - } > "$helmrelease_file" - - kubectl apply -f "$helmrelease_file" - - rm -f "$helmrelease_file" -} - -function install_tenant (){ - local release_name="$1" - local namespace="$2" - local values_file="${values_base_path}tenant/values.yaml" - local repo_name="cozystack-apps" - local repo_ns="cozy-public" - install_helmrelease "$release_name" "$namespace" "tenant" "$repo_name" "$repo_ns" "$values_file" -} - -function make_extra_checks(){ - local checks_file="$1" - echo "after exec make $checks_file" - if [[ -n "$checks_file" && -f "$checks_file" ]]; then - echo -e "${YELLOW}Start extra checks with file: ${checks_file}${RESET}" - - fi -} - -function check_helmrelease_status() { - local release_name="$1" - local namespace="$2" - local checks_file="$3" - local timeout=300 # Timeout in seconds - local interval=5 # Interval between checks in seconds - local elapsed=0 - - - while [[ $elapsed -lt $timeout ]]; do - local status_output - status_output=$(kubectl get helmrelease "$release_name" -n "$namespace" -o json | jq -r '.status.conditions[-1].reason') - - if [[ "$status_output" == "InstallSucceeded" || "$status_output" == "UpgradeSucceeded" ]]; then - echo -e "${GREEN}Helm release '$release_name' is ready.${RESET}" - make_extra_checks "$checks_file" - delete_hr $release_name $namespace - return 0 - elif [[ "$status_output" == "InstallFailed" ]]; then - echo -e "${RED}Helm release '$release_name': InstallFailed${RESET}" - exit 1 - else - echo -e "${YELLOW}Helm release '$release_name' is not ready. Current status: $status_output${RESET}" - fi - - sleep "$interval" - elapsed=$((elapsed + interval)) - done - - echo -e "${RED}Timeout reached. Helm release '$release_name' is still not ready after $timeout seconds.${RESET}" - exit 1 -} - -chart_name="$1" - -if [ -z "$chart_name" ]; then - echo -e "${RED}No chart name provided. Exiting...${RESET}" - exit 1 -fi - - -checks_file="${checks_base_path}${chart_name}/check.sh" -repo_name="cozystack-apps" -repo_ns="cozy-public" -release_name="$chart_name-e2e" -values_file="${values_base_path}${chart_name}/values.yaml" - -install_tenant $TEST_TENANT $ROOT_NS -check_helmrelease_status $TEST_TENANT $ROOT_NS "${checks_base_path}tenant/check.sh" - -echo -e "${YELLOW}Running tests for chart: $chart_name${RESET}" - -install_helmrelease $release_name $TEST_TENANT $chart_name $repo_name $repo_ns $values_file -check_helmrelease_status $release_name $TEST_TENANT $checks_file diff --git a/hack/testdata/http-cache/check.sh b/hack/testdata/http-cache/check.sh deleted file mode 100644 index 61c7ebff..00000000 --- a/hack/testdata/http-cache/check.sh +++ /dev/null @@ -1 +0,0 @@ -return 0 diff --git a/hack/testdata/http-cache/values.yaml b/hack/testdata/http-cache/values.yaml deleted file mode 100644 index 2674c1c3..00000000 --- a/hack/testdata/http-cache/values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -endpoints: - - 8.8.8.8:443 diff --git a/hack/testdata/kubernetes/check.sh b/hack/testdata/kubernetes/check.sh deleted file mode 100644 index 61c7ebff..00000000 --- a/hack/testdata/kubernetes/check.sh +++ /dev/null @@ -1 +0,0 @@ -return 0 diff --git a/hack/testdata/kubernetes/values.yaml b/hack/testdata/kubernetes/values.yaml deleted file mode 100644 index 71e290c5..00000000 --- a/hack/testdata/kubernetes/values.yaml +++ /dev/null @@ -1,62 +0,0 @@ -## @section Common parameters - -## @param host The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). -## @param controlPlane.replicas Number of replicas for Kubernetes contorl-plane components -## @param storageClass StorageClass used to store user data -## -host: "" -controlPlane: - replicas: 2 -storageClass: replicated - -## @param nodeGroups [object] nodeGroups configuration -## -nodeGroups: - md0: - minReplicas: 0 - maxReplicas: 10 - instanceType: "u1.medium" - ephemeralStorage: 20Gi - roles: - - ingress-nginx - - resources: - cpu: "" - memory: "" - -## @section Cluster Addons -## -addons: - - ## Cert-manager: automatically creates and manages SSL/TLS certificate - ## - certManager: - ## @param addons.certManager.enabled Enables the cert-manager - ## @param addons.certManager.valuesOverride Custom values to override - enabled: true - valuesOverride: {} - - ## Ingress-NGINX Controller - ## - ingressNginx: - ## @param addons.ingressNginx.enabled Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) - ## @param addons.ingressNginx.valuesOverride Custom values to override - ## - enabled: true - ## @param addons.ingressNginx.hosts List of domain names that should be passed through to the cluster by upper cluster - ## e.g: - ## hosts: - ## - example.org - ## - foo.example.net - ## - hosts: [] - valuesOverride: {} - - ## Flux CD - ## - fluxcd: - ## @param addons.fluxcd.enabled Enables Flux CD - ## @param addons.fluxcd.valuesOverride Custom values to override - ## - enabled: true - valuesOverride: {} diff --git a/hack/testdata/nats/check.sh b/hack/testdata/nats/check.sh deleted file mode 100644 index 61c7ebff..00000000 --- a/hack/testdata/nats/check.sh +++ /dev/null @@ -1 +0,0 @@ -return 0 diff --git a/hack/testdata/nats/values.yaml b/hack/testdata/nats/values.yaml deleted file mode 100644 index 7044641c..00000000 --- a/hack/testdata/nats/values.yaml +++ /dev/null @@ -1,10 +0,0 @@ - -## @section Common parameters - -## @param external Enable external access from outside the cluster -## @param replicas Persistent Volume size for NATS -## @param storageClass StorageClass used to store the data -## -external: false -replicas: 2 -storageClass: "" diff --git a/hack/testdata/tenant/check.sh b/hack/testdata/tenant/check.sh deleted file mode 100644 index 61c7ebff..00000000 --- a/hack/testdata/tenant/check.sh +++ /dev/null @@ -1 +0,0 @@ -return 0 diff --git a/hack/testdata/tenant/values.yaml b/hack/testdata/tenant/values.yaml deleted file mode 100644 index 3e75d05b..00000000 --- a/hack/testdata/tenant/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -host: "" -etcd: false -monitoring: false -ingress: false -seaweedfs: false -isolated: true diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index 747d4507..7b1eb049 100755 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -11,14 +11,6 @@ include ../../../scripts/common-envs.mk help: ## Show this help. @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) -show: - helm template -n $(NAMESPACE) $(NAME) . - -apply: ## Create sandbox in existing Kubernetes cluster. - helm template -n $(NAMESPACE) $(NAME) . | kubectl apply -f - - -diff: - helm template -n $(NAMESPACE) $(NAME) . | kubectl diff -f - image: image-e2e-sandbox @@ -39,26 +31,11 @@ image-e2e-sandbox: test: ## Run the end-to-end tests in existing sandbox. docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/e2e.sh' -test-applications: ## Run the end-to-end tests in existing sandbox for applications. - for app in $(TESTING_APPS); do \ - docker exec ${SANDBOX_NAME} bash -c "/hack/e2e.application.sh $${app}"; \ - done - docker exec ${SANDBOX_NAME} bash -c "kubectl get hr -A | grep -v 'True'" - delete: ## Remove sandbox from existing Kubernetes cluster. docker rm -f "${SANDBOX_NAME}" || true exec: ## Opens an interactive shell in the sandbox container. - docker exec -ti "${SANDBOX_NAME}" -- bash - -proxy: sync-hosts ## Enable a SOCKS5 proxy server; mirrord and gost must be installed. - mirrord exec --target deploy/cozystack-e2e-sandbox --target-namespace cozy-e2e-tests -- gost -L=127.0.0.1:10080 - -login: ## Downloads the kubeconfig into a temporary directory and runs a shell with the sandbox environment; mirrord must be installed. - mirrord exec --target deploy/cozystack-e2e-sandbox --target-namespace cozy-e2e-tests -- "$$SHELL" - -sync-hosts: - kubectl exec -n $(NAMESPACE) deploy/cozystack-e2e-$(NAME) -- sh -c 'kubectl get ing -A -o go-template='\''{{ "127.0.0.1 localhost\n"}}{{ range .items }}{{ range .status.loadBalancer.ingress }}{{ .ip }}{{ end }} {{ range .spec.rules }}{{ .host }}{{ end }}{{ "\n" }}{{ end }}'\'' > /etc/hosts' + docker exec -ti "${SANDBOX_NAME}" bash apply: delete docker run -d --rm --name "${SANDBOX_NAME}" --privileged "$$(yq .e2e.image values.yaml)" sleep infinity From 637551eb338da4bbea217ae15d68d81bce9566ce Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Fri, 25 Apr 2025 11:19:25 +0300 Subject: [PATCH 025/120] [ci] Use dots in release candidtate versions, as per SemVer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: 0.31.0-rc1 After: 0.31.0-rc.1 Why this matters: we want to do things the right way from the start. Version patten affects how versions are parsed and sorted. For example, we have release candidates number 9 and 10: * In 'rc.9' and 'rc.10', the numeric parts are compared as numbers, so 9 comes before 10. * In 'rc9' and 'rc10', versions are compared lexicographically, so 10 comes before 9, which is wrong. Reference: SemVer items 9–11. https://semver.org/#spec-item-9 Signed-off-by: Nick Volynkin --- .github/workflows/tags.yaml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 34e13a76..7d88d188 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -3,7 +3,9 @@ name: Versioned Tag on: push: tags: - - 'v*.*.*' # vX.Y.Z or vX.Y.Z-rcN + - 'v*.*.*' # vX.Y.Z + - 'v*.*.*-rc.*' # vX.Y.Z-rc.N + concurrency: group: tags-${{ github.workflow }}-${{ github.ref }} @@ -46,18 +48,18 @@ jobs: uses: actions/github-script@v7 with: script: | - const ref = context.ref.replace('refs/tags/', ''); // e.g. v0.31.5-rc1 - const m = ref.match(/^v(\d+\.\d+\.\d+)(-rc\d+)?$/); + const ref = context.ref.replace('refs/tags/', ''); // e.g. v0.31.5-rc.1 + const m = ref.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/); // ['0.31.5', '-rc.1'] if (!m) { - core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-rcN'`); + core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`); return; } - const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc1 + const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc.1 const isRc = Boolean(m[2]); const [maj, min] = m[1].split('.'); - core.setOutput('tag', ref); - core.setOutput('version', version); - core.setOutput('is_rc', isRc); + core.setOutput('tag', ref); // v0.31.5-rc.1 + core.setOutput('version', version); // 0.31.5-rc.1 + core.setOutput('is_rc', isRc); // true core.setOutput('line', `${maj}.${min}`); // 0.31 # Detect base branch (main or release‑X.Y) the tag was pushed from From a29040faf7ab45e4fe2e5eacf3d8167e56d7ccdf Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 12:51:04 +0200 Subject: [PATCH 026/120] [ci] automatically trigger tests in releasing PR Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 15 ++++++++++--- .github/workflows/tags.yaml | 22 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index bc955f55..e266c0bd 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -3,6 +3,11 @@ name: Releasing PR on: pull_request: types: [labeled, opened, synchronize, reopened, closed] + workflow_dispatch: + inputs: + sha: + description: "Commit SHA to test" + required: true concurrency: group: pull-requests-release-${{ github.workflow }}-${{ github.event.pull_request.number }} @@ -16,15 +21,19 @@ jobs: contents: read packages: write - # Run only when the PR carries the "release" label and not closed. + # Run only when the PR carries the "release" label and not closed or via workflow_dispatch if: | - contains(github.event.pull_request.labels.*.name, 'release') && - github.event.action != 'closed' + (github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'release') && + github.event.action != 'closed') + || github.event_name == 'workflow_dispatch' steps: - name: Checkout code uses: actions/checkout@v4 with: + # for workflow_dispatch take a specific SHA, otherwise — head.sha PR + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || inputs.sha }} fetch-depth: 0 fetch-tags: true diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 34e13a76..f6b71108 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -222,3 +222,25 @@ jobs: } else { console.log(`PR already exists from ${head} to ${base}`); } + + # Run tests + - name: Trigger release-verify tests + if: steps.check_release.outputs.skip == 'false' + uses: actions/github-script@v7 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DISPATCH_REF: ${{ steps.get_base.outputs.branch }} # main or release-X.Y + DISPATCH_SHA: ${{ github.sha }} # commit for tests + with: + github-token: ${{ env.GH_TOKEN }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: '.github/workflows/pull-requests-release.yaml', + ref: process.env.DISPATCH_REF, + inputs: { + sha: process.env.DISPATCH_SHA + } + }); + console.log(`🔔 verify-job triggered on ${process.env.DISPATCH_SHA}`); From 255176c3216c51aa7360c438dd583f4bb110e8c6 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 14:33:29 +0200 Subject: [PATCH 027/120] [ci] fix triggering releasing pr tests Signed-off-by: Andrei Kvapil --- .github/workflows/tags.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 81ecf2b0..286b9354 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -19,6 +19,7 @@ jobs: contents: write packages: write pull-requests: write + actions: write steps: # Check if a non-draft release with this tag already exists @@ -239,7 +240,7 @@ jobs: await github.rest.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: context.repo.repo, - workflow_id: '.github/workflows/pull-requests-release.yaml', + workflow_id: 'pull-requests-release.yaml', ref: process.env.DISPATCH_REF, inputs: { sha: process.env.DISPATCH_SHA From 87a286fc740e668eef6e4877118e8083ba0878ea Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 25 Apr 2025 12:37:42 +0000 Subject: [PATCH 028/120] Prepare release v0.31.0-rc.1 Signed-off-by: github-actions --- packages/apps/ferretdb/images/postgres-backup.tag | 2 +- packages/apps/http-cache/images/nginx-cache.tag | 2 +- packages/apps/kubernetes/images/cluster-autoscaler.tag | 2 +- packages/apps/kubernetes/images/kubevirt-cloud-provider.tag | 2 +- packages/apps/kubernetes/images/kubevirt-csi-driver.tag | 2 +- packages/apps/kubernetes/images/ubuntu-container-disk.tag | 2 +- packages/apps/postgres/images/postgres-backup.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/extra/monitoring/images/grafana.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cilium/values.yaml | 4 ++-- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 4 ++-- .../charts/kubeapps/templates/dashboard/configmap.yaml | 2 +- packages/system/dashboard/values.yaml | 6 +++--- packages/system/kamaji/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- packages/system/kubeovn/values.yaml | 2 +- 20 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/apps/ferretdb/images/postgres-backup.tag b/packages/apps/ferretdb/images/postgres-backup.tag index 631a088b..b3bee261 100644 --- a/packages/apps/ferretdb/images/postgres-backup.tag +++ b/packages/apps/ferretdb/images/postgres-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/postgres-backup:0.10.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f +ghcr.io/cozystack/cozystack/postgres-backup:0.10.1@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index e8e62c73..74a2d1cc 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.4.0@sha256:bef7344da098c4dc400a9e20ffad10ac991df67d09a30026207454abbc91f28b +ghcr.io/cozystack/cozystack/nginx-cache:0.4.0@sha256:4e1f5153d2673a399b315252238f4dc3eb5d6c59295aef594691710cc5b72eb4 diff --git a/packages/apps/kubernetes/images/cluster-autoscaler.tag b/packages/apps/kubernetes/images/cluster-autoscaler.tag index 79b8f1fe..10efdc06 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler.tag +++ b/packages/apps/kubernetes/images/cluster-autoscaler.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/cluster-autoscaler:0.18.0@sha256:85371c6aabf5a7fea2214556deac930c600e362f92673464fe2443784e2869c3 +ghcr.io/cozystack/cozystack/cluster-autoscaler:0.19.0@sha256:85371c6aabf5a7fea2214556deac930c600e362f92673464fe2443784e2869c3 diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index 3da7f1c6..edf89c8d 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.18.0@sha256:795d8e1ef4b2b0df2aa1e09d96cd13476ebb545b4bf4b5779b7547a70ef64cf9 +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.19.0@sha256:795d8e1ef4b2b0df2aa1e09d96cd13476ebb545b4bf4b5779b7547a70ef64cf9 diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index a06f4311..0e421b76 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.18.0@sha256:6f9091c3e7e4951c5e43fdafd505705fcc9f1ead290ee3ae42e97e9ec2b87b20 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.19.0@sha256:5717919c75e609902c6d67138311a2a8fd07be822e2173f3802b67cf5f3486e9 diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag index 5c36c7ea..137cd52e 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk.tag +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.30.1@sha256:07392e7a87a3d4ef1c86c1b146e6c5de5c2b524aed5a53bf48870dc8a296f99a +ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:4a4f8bee150e04d1efcd5ff1ea83e12f495a98851cc5fd47ef41ac7aebce9b74 diff --git a/packages/apps/postgres/images/postgres-backup.tag b/packages/apps/postgres/images/postgres-backup.tag index 631a088b..b3bee261 100644 --- a/packages/apps/postgres/images/postgres-backup.tag +++ b/packages/apps/postgres/images/postgres-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/postgres-backup:0.10.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f +ghcr.io/cozystack/cozystack/postgres-backup:0.10.1@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index bc00caf1..acd4a38e 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.30.2@sha256:59996588b5d59b5593fb34442b2f2ed8ef466d138b229a8d37beb6f70141a690 + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.1@sha256:ab0e8fd97632ba784a42a3d0714806ea327440f82ffa5c4896a87c5fb7c1ec6e diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index ce5b1eeb..67c70250 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.30.2@sha256:31273d6b42dc88c2be2ff9ba64564d1b12e70ae8a5480953341b0d113ac7d4bd + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.1@sha256:a20a6834527ccfc8daf7413a15234f3f7dbbd7774810c8e1966736d487ef7d0c diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index 499055a6..709d0d2b 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.30.2@sha256:307d382f75f1dcb39820c73b93b2ce576cdb6d58032679bda7d926999c677900 +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.1@sha256:de69166fd6efec988cad7ad5be41bbb57c8134508c531d7496fc7f15772e4993 diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag index 73fca310..3a68139d 100644 --- a/packages/extra/monitoring/images/grafana.tag +++ b/packages/extra/monitoring/images/grafana.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399 +ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:66c4547efd18b4d7475ff73b2c4e2f39e9b4471d55e85237e2fe3e87af05c302 diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 779c0b7d..8fc97610 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:a47d2743d01bff0ce60aa745fdff54f9b7184dff8679b11ab4ecd08ac663012b +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:67e4a5da0ab43d93e8b75094d5a2db8159cb927a47b94f945f80d0ffb93d3301 diff --git a/packages/system/cilium/values.yaml b/packages/system/cilium/values.yaml index 32e14b1d..8e0dea78 100644 --- a/packages/system/cilium/values.yaml +++ b/packages/system/cilium/values.yaml @@ -14,7 +14,7 @@ cilium: mode: "kubernetes" image: repository: ghcr.io/cozystack/cozystack/cilium - tag: 1.17.2 - digest: "sha256:bc6a8ec326188960ac36584873e07801bcbc56cb862e2ec8bf87a7926f66abf1" + tag: 1.17.3 + digest: "sha256:f95e30fd8e7608f61c38344bb9f558f60f4d81bccb8e399836911e4feec2b40a" envoy: enabled: false diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index a669a153..23763428 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.30.2@sha256:7ef370dc8aeac0a6b2a50b7d949f070eb21d267ba0a70e7fc7c1564bfe6d4f83 + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.1@sha256:1dd9f3ec9d5630d5b49ffe9380d6a0131bf04e7e9bddcc3fd6f59089c6563b1c diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index fdfe2481..8e778250 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.30.2@sha256:5b87a8ea0dcde1671f44532c1ee6db11a5dd922d1a009078ecf6495ec193e52a + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.1@sha256:96492f384c07619c091764c759adde6ef91054b1223f03f7ddd62a56c40b06ac debug: false disableTelemetry: false - cozystackVersion: "v0.30.2" + cozystackVersion: "v0.31.0-rc.1" diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml index b1409d89..d591dfa0 100644 --- a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml @@ -76,7 +76,7 @@ data: "kubeappsNamespace": {{ .Release.Namespace | quote }}, "helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }}, "carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }}, - "appVersion": "v0.30.2", + "appVersion": "v0.31.0-rc.1", "authProxyEnabled": {{ .Values.authProxy.enabled }}, "oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }}, "oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }}, diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index a6b91769..3038124f 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -19,15 +19,15 @@ kubeapps: image: registry: ghcr.io/cozystack/cozystack repository: dashboard - tag: v0.30.2 + tag: v0.31.0-rc.1 digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93" kubeappsapis: resourcesPreset: "none" image: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis - tag: v0.30.2 - digest: "sha256:3b5805b56f2fb9fd25f4aa389cdfbbb28a3f2efb02245c52085a45d1dc62bf92" + tag: v0.31.0-rc.1 + digest: "sha256:ca65949e84c9a92436f47525ae92861984406644779cbb2ecdb8e2a1a133fabf" pluginConfig: flux: packages: diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index 7abe514e..ee781d0e 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,7 +3,7 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: v0.30.2@sha256:e04f68e4cc5b023ed39ce2242b32aee51f97235371602239d0c4a9cea97c8d0d + tag: v0.31.0-rc.1@sha256:3ae6f1b2e42dcb9dcfbf8213029eb731197ccdbf27fdc30539d975caf32184d4 repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index db3c347e..35f6fd3b 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.30.2@sha256:fa14fa7a0ffa628eb079ddcf6ce41d75b43de92e50f489422f8fb15c4dab2dbf +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.1@sha256:fa14fa7a0ffa628eb079ddcf6ce41d75b43de92e50f489422f8fb15c4dab2dbf diff --git a/packages/system/kubeovn/values.yaml b/packages/system/kubeovn/values.yaml index f66fc737..68044bab 100644 --- a/packages/system/kubeovn/values.yaml +++ b/packages/system/kubeovn/values.yaml @@ -22,4 +22,4 @@ global: images: kubeovn: repository: kubeovn - tag: v1.13.8@sha256:071a93df2dce484b347bbace75934ca9e1743668bfe6f1161ba307dee204767d + tag: v1.13.10@sha256:cc490d549353e2ee432568eb32631f8213e0f208193594b2f59de312607c9782 From 9239852ec8a362301d6a920125f035fe183bdd6f Mon Sep 17 00:00:00 2001 From: dtrdnk <4demenko@gmail.com> Date: Fri, 25 Apr 2025 15:44:02 +0300 Subject: [PATCH 029/120] Update permissions version for CRI containerd Signed-off-by: dtrdnk <4demenko@gmail.com> --- hack/e2e.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hack/e2e.sh b/hack/e2e.sh index b11717e7..e7c66534 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -60,7 +60,8 @@ done # Prepare system drive if [ ! -f nocloud-amd64.raw ]; then - wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz -O nocloud-amd64.raw.xz --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null + wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz \ + -O nocloud-amd64.raw.xz --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null rm -f nocloud-amd64.raw xz --decompress nocloud-amd64.raw.xz fi @@ -85,7 +86,8 @@ done # Start VMs for i in 1 2 3; do qemu-system-x86_64 -machine type=pc,accel=kvm -cpu host -smp 8 -m 16384 \ - -device virtio-net,netdev=net0,mac=52:54:00:12:34:5$i -netdev tap,id=net0,ifname=cozy-srv$i,script=no,downscript=no \ + -device virtio-net,netdev=net0,mac=52:54:00:12:34:5$i \ + -netdev tap,id=net0,ifname=cozy-srv$i,script=no,downscript=no \ -drive file=srv$i/system.img,if=virtio,format=raw \ -drive file=srv$i/seed.img,if=virtio,format=raw \ -drive file=srv$i/data.img,if=virtio,format=raw \ @@ -121,7 +123,7 @@ machine: files: - content: | [plugins] - [plugins."io.containerd.grpc.v1.cri"] + [plugins."io.containerd.cri.v1.runtime"] device_ownership_from_security_context = true path: /etc/cri/conf.d/20-customization.part op: create From f644bf20c578e9c2c4954a1809e044a7f4f647ad Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 16:46:16 +0200 Subject: [PATCH 030/120] Revert "[ci] automatically trigger tests in releasing PR" Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 15 +++---------- .github/workflows/tags.yaml | 22 -------------------- 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index e266c0bd..bc955f55 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -3,11 +3,6 @@ name: Releasing PR on: pull_request: types: [labeled, opened, synchronize, reopened, closed] - workflow_dispatch: - inputs: - sha: - description: "Commit SHA to test" - required: true concurrency: group: pull-requests-release-${{ github.workflow }}-${{ github.event.pull_request.number }} @@ -21,19 +16,15 @@ jobs: contents: read packages: write - # Run only when the PR carries the "release" label and not closed or via workflow_dispatch + # Run only when the PR carries the "release" label and not closed. if: | - (github.event_name == 'pull_request' && - contains(github.event.pull_request.labels.*.name, 'release') && - github.event.action != 'closed') - || github.event_name == 'workflow_dispatch' + contains(github.event.pull_request.labels.*.name, 'release') && + github.event.action != 'closed' steps: - name: Checkout code uses: actions/checkout@v4 with: - # for workflow_dispatch take a specific SHA, otherwise — head.sha PR - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || inputs.sha }} fetch-depth: 0 fetch-tags: true diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 286b9354..6efac7db 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -225,25 +225,3 @@ jobs: } else { console.log(`PR already exists from ${head} to ${base}`); } - - # Run tests - - name: Trigger release-verify tests - if: steps.check_release.outputs.skip == 'false' - uses: actions/github-script@v7 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DISPATCH_REF: ${{ steps.get_base.outputs.branch }} # main or release-X.Y - DISPATCH_SHA: ${{ github.sha }} # commit for tests - with: - github-token: ${{ env.GH_TOKEN }} - script: | - await github.rest.actions.createWorkflowDispatch({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: 'pull-requests-release.yaml', - ref: process.env.DISPATCH_REF, - inputs: { - sha: process.env.DISPATCH_SHA - } - }); - console.log(`🔔 verify-job triggered on ${process.env.DISPATCH_SHA}`); From a9b235048d359100a92f499159745d47a768d172 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 25 Apr 2025 16:53:55 +0200 Subject: [PATCH 031/120] [ci] Use dots in release candidtate versions, as per SemVer Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index e266c0bd..a0eae267 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -145,13 +145,13 @@ jobs: uses: actions/github-script@v7 with: script: | - const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc1 - const m = tag.match(/^v(\d+\.\d+\.\d+)(-rc\d+)?$/); + const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc.1 + const m = tag.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/); if (!m) { - core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-rcN'`); + core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`); return; } - const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc1 + const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc.1 const isRc = Boolean(m[2]); core.setOutput('is_rc', isRc); const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<'; From ec9e26c054ec32b1a86ea7c1f2b8a399be1759ad Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Tue, 29 Apr 2025 15:22:42 +0300 Subject: [PATCH 032/120] Fix virtual machine resource tracking * Count Workload resources for pods by requests, not limits * Do not count init container requests * Prefix Workloads for pods with `pod-`, just like the other types to prevent possible name collisions (closes #787) The previous version of the WorkloadMonitor controller incorrectly summed resource limits on pods, rather than requests. This prevented it from tracking the resource allocation for pods, which only had requests specified, which is particularly the case for kubevirt's virtual machine pods. Additionally, it counted the limits for all containers, including init containers, which are short-lived and do not contribute much to the total resource usage. Signed-off-by: Timofei Larkin --- internal/controller/workload_controller.go | 24 ++++++++++++----- .../controller/workload_controller_test.go | 26 +++++++++++++++++++ .../controller/workloadmonitor_controller.go | 13 ++++------ 3 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 internal/controller/workload_controller_test.go diff --git a/internal/controller/workload_controller.go b/internal/controller/workload_controller.go index 7b7f8406..3624e0e1 100644 --- a/internal/controller/workload_controller.go +++ b/internal/controller/workload_controller.go @@ -39,6 +39,15 @@ func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c } t := getMonitoredObject(w) + + if t == nil { + err = r.Delete(ctx, w) + if err != nil { + logger.Error(err, "failed to delete workload") + } + return ctrl.Result{}, err + } + err = r.Get(ctx, types.NamespacedName{Name: t.GetName(), Namespace: t.GetNamespace()}, t) // found object, nothing to do @@ -68,20 +77,23 @@ func (r *WorkloadReconciler) SetupWithManager(mgr ctrl.Manager) error { } func getMonitoredObject(w *cozyv1alpha1.Workload) client.Object { - if strings.HasPrefix(w.Name, "pvc-") { + switch { + case strings.HasPrefix(w.Name, "pvc-"): obj := &corev1.PersistentVolumeClaim{} obj.Name = strings.TrimPrefix(w.Name, "pvc-") obj.Namespace = w.Namespace return obj - } - if strings.HasPrefix(w.Name, "svc-") { + case strings.HasPrefix(w.Name, "svc-"): obj := &corev1.Service{} obj.Name = strings.TrimPrefix(w.Name, "svc-") obj.Namespace = w.Namespace return obj + case strings.HasPrefix(w.Name, "pod-"): + obj := &corev1.Pod{} + obj.Name = strings.TrimPrefix(w.Name, "pod-") + obj.Namespace = w.Namespace + return obj } - obj := &corev1.Pod{} - obj.Name = w.Name - obj.Namespace = w.Namespace + var obj client.Object return obj } diff --git a/internal/controller/workload_controller_test.go b/internal/controller/workload_controller_test.go new file mode 100644 index 00000000..816c135e --- /dev/null +++ b/internal/controller/workload_controller_test.go @@ -0,0 +1,26 @@ +package controller + +import ( + "testing" + + cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" + corev1 "k8s.io/api/core/v1" +) + +func TestUnprefixedMonitoredObjectReturnsNil(t *testing.T) { + w := &cozyv1alpha1.Workload{} + w.Name = "unprefixed-name" + obj := getMonitoredObject(w) + if obj != nil { + t.Errorf(`getMonitoredObject(&Workload{Name: "%s"}) == %v, want nil`, w.Name, obj) + } +} + +func TestPodMonitoredObject(t *testing.T) { + w := &cozyv1alpha1.Workload{} + w.Name = "pod-mypod" + obj := getMonitoredObject(w) + if pod, ok := obj.(*corev1.Pod); !ok || pod.Name != "mypod" { + t.Errorf(`getMonitoredObject(&Workload{Name: "%s"}) == %v, want &Pod{Name: "mypod"}`, w.Name, obj) + } +} diff --git a/internal/controller/workloadmonitor_controller.go b/internal/controller/workloadmonitor_controller.go index 330d1dc5..a1d4a501 100644 --- a/internal/controller/workloadmonitor_controller.go +++ b/internal/controller/workloadmonitor_controller.go @@ -212,15 +212,12 @@ func (r *WorkloadMonitorReconciler) reconcilePodForMonitor( ) error { logger := log.FromContext(ctx) - // Combine both init containers and normal containers to sum resources properly - combinedContainers := append(pod.Spec.InitContainers, pod.Spec.Containers...) - - // totalResources will store the sum of all container resource limits + // totalResources will store the sum of all container resource requests totalResources := make(map[string]resource.Quantity) - // Iterate over all containers to aggregate their Limits - for _, container := range combinedContainers { - for name, qty := range container.Resources.Limits { + // Iterate over all containers to aggregate their requests + for _, container := range pod.Spec.Containers { + for name, qty := range container.Resources.Requests { if existing, exists := totalResources[name.String()]; exists { existing.Add(qty) totalResources[name.String()] = existing @@ -249,7 +246,7 @@ func (r *WorkloadMonitorReconciler) reconcilePodForMonitor( workload := &cozyv1alpha1.Workload{ ObjectMeta: metav1.ObjectMeta{ - Name: pod.Name, + Name: fmt.Sprintf("pod-%s", pod.Name), Namespace: pod.Namespace, }, } From 6106a9fe51a721d85c14634572b8a85cfc469fe1 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Tue, 29 Apr 2025 16:13:15 +0300 Subject: [PATCH 033/120] Make kubevirt's CPU allocation ratio configurable Kubevirt's default cpu-to-vcpu ration is 1:10, which might be a bit extreme for some users. This patch introduces a new key in the Cozystack configmap, "cpu-allocation-ratio" where admins of Cozystack can specify an alternative value, if needed. Signed-off-by: Timofei Larkin --- packages/core/platform/bundles/paas-full.yaml | 5 +++++ packages/system/kubevirt/templates/kubevirt-cr.yaml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index 74806d9e..da5a0e8a 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -134,6 +134,11 @@ releases: namespace: cozy-kubevirt privileged: true dependsOn: [cilium,kubeovn,kubevirt-operator] + {{- $cpuAllocationRatio := index $cozyConfig.data "cpu-allocation-ratio" }} + {{- if $cpuAllocationRatio }} + values: + cpuAllocationRatio: {{ $cpuAllocationRatio }} + {{- end }} - name: kubevirt-instancetypes releaseName: kubevirt-instancetypes diff --git a/packages/system/kubevirt/templates/kubevirt-cr.yaml b/packages/system/kubevirt/templates/kubevirt-cr.yaml index 87889e42..b4ec5b70 100644 --- a/packages/system/kubevirt/templates/kubevirt-cr.yaml +++ b/packages/system/kubevirt/templates/kubevirt-cr.yaml @@ -10,6 +10,9 @@ spec: commonInstancetypesDeployment: enabled: false developerConfiguration: + {{- if .Values.cpuAllocationRatio }} + cpuAllocationRatio: {{ .Values.cpuAllocationRatio }} + {{- end }} featureGates: - HotplugVolumes - ExpandDisks From f61a7817e650cc14b1b08a4e966ddc7955c07166 Mon Sep 17 00:00:00 2001 From: kklinch0 Date: Mon, 5 May 2025 09:26:45 +0300 Subject: [PATCH 034/120] [platform] add hr reconciler Signed-off-by: kklinch0 --- .gitignore | 3 +- cmd/cozystack-controller/main.go | 11 ++ internal/controller/tenant_helm_reconciler.go | 158 ++++++++++++++++++ packages/core/platform/templates/apps.yaml | 4 +- packages/extra/info/Chart.yaml | 2 +- packages/extra/info/templates/kubeconfig.yaml | 7 + packages/extra/ingress/Chart.yaml | 2 +- .../extra/ingress/templates/dashboard.yaml | 9 + packages/extra/versions_map | 6 +- .../cozystack-controller/templates/rbac.yaml | 3 + .../templates/configure-kk.yaml | 9 + .../system/keycloak/templates/ingress.yaml | 9 + packages/system/keycloak/templates/sts.yaml | 9 + 13 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 internal/controller/tenant_helm_reconciler.go diff --git a/.gitignore b/.gitignore index 00d89825..de476be5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ _out .git .idea +.vscode # User-specific stuff .idea/**/workspace.xml @@ -75,4 +76,4 @@ fabric.properties .idea/caches/build_file_checksums.ser .DS_Store -**/.DS_Store \ No newline at end of file +**/.DS_Store diff --git a/cmd/cozystack-controller/main.go b/cmd/cozystack-controller/main.go index f1c10c10..a5624cd3 100644 --- a/cmd/cozystack-controller/main.go +++ b/cmd/cozystack-controller/main.go @@ -39,6 +39,8 @@ import ( cozystackiov1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" "github.com/cozystack/cozystack/internal/controller" "github.com/cozystack/cozystack/internal/telemetry" + + helmv2 "github.com/fluxcd/helm-controller/api/v2" // +kubebuilder:scaffold:imports ) @@ -51,6 +53,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(cozystackiov1alpha1.AddToScheme(scheme)) + utilruntime.Must(helmv2.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -182,6 +185,14 @@ func main() { if err = (&controller.WorkloadReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "WorkloadReconciler") + os.Exit(1) + } + + if err = (&controller.TenantHelmReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Workload") os.Exit(1) diff --git a/internal/controller/tenant_helm_reconciler.go b/internal/controller/tenant_helm_reconciler.go new file mode 100644 index 00000000..402ff5ba --- /dev/null +++ b/internal/controller/tenant_helm_reconciler.go @@ -0,0 +1,158 @@ +package controller + +import ( + "context" + "fmt" + "strings" + "time" + + e "errors" + + helmv2 "github.com/fluxcd/helm-controller/api/v2" + "gopkg.in/yaml.v2" + corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +type TenantHelmReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +func (r *TenantHelmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + + hr := &helmv2.HelmRelease{} + if err := r.Get(ctx, req.NamespacedName, hr); err != nil { + if errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + logger.Error(err, "unable to fetch HelmRelease") + return ctrl.Result{}, err + } + + if !strings.HasPrefix(hr.Name, "tenant-") { + return ctrl.Result{}, nil + } + + if len(hr.Status.Conditions) == 0 || hr.Status.Conditions[0].Type != "Ready" { + return ctrl.Result{}, nil + } + + if len(hr.Status.History) == 0 { + logger.Info("no history in HelmRelease status", "name", hr.Name) + return ctrl.Result{}, nil + } + + if hr.Status.History[0].Status != "deployed" { + return ctrl.Result{}, nil + } + + newDigest := hr.Status.History[0].Digest + var hrList helmv2.HelmReleaseList + childNamespace := getChildNamespace(hr.Namespace, hr.Name) + if childNamespace == "tenant-root" && hr.Name == "tenant-root" { + if hr.Spec.Values == nil { + logger.Error(e.New("hr.Spec.Values is nil"), "cant annotate tenant-root ns") + return ctrl.Result{}, nil + } + err := annotateTenantRootNs(*hr.Spec.Values, r.Client) + if err != nil { + logger.Error(err, "cant annotate tenant-root ns") + return ctrl.Result{}, nil + } + logger.Info("namespace 'tenant-root' annotated") + } + + if err := r.List(ctx, &hrList, client.InNamespace(childNamespace)); err != nil { + logger.Error(err, "unable to list HelmReleases in namespace", "namespace", hr.Name) + return ctrl.Result{}, err + } + + for _, item := range hrList.Items { + if item.Name == hr.Name { + continue + } + oldDigest := item.GetAnnotations()["cozystack.io/tenant-config-digest"] + if oldDigest == newDigest { + continue + } + patchTarget := item.DeepCopy() + + if patchTarget.Annotations == nil { + patchTarget.Annotations = map[string]string{} + } + ts := time.Now().Format(time.RFC3339Nano) + + patchTarget.Annotations["cozystack.io/tenant-config-digest"] = newDigest + patchTarget.Annotations["reconcile.fluxcd.io/forceAt"] = ts + patchTarget.Annotations["reconcile.fluxcd.io/requestedAt"] = ts + + patch := client.MergeFrom(item.DeepCopy()) + if err := r.Patch(ctx, patchTarget, patch); err != nil { + logger.Error(err, "failed to patch HelmRelease", "name", patchTarget.Name) + continue + } + + logger.Info("patched HelmRelease with new digest", "name", patchTarget.Name, "digest", newDigest, "version", hr.Status.History[0].Version) + } + + return ctrl.Result{}, nil +} + +func (r *TenantHelmReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&helmv2.HelmRelease{}). + Complete(r) +} + +func getChildNamespace(currentNamespace, hrName string) string { + tenantName := strings.TrimPrefix(hrName, "tenant-") + + switch { + case currentNamespace == "tenant-root" && hrName == "tenant-root": + // 1) root tenant inside root namespace + return "tenant-root" + + case currentNamespace == "tenant-root": + // 2) any other tenant in root namespace + return fmt.Sprintf("tenant-%s", tenantName) + + default: + // 3) tenant in a dedicated namespace + return fmt.Sprintf("%s-%s", currentNamespace, tenantName) + } +} + +func annotateTenantRootNs(values apiextensionsv1.JSON, c client.Client) error { + var data map[string]interface{} + if err := yaml.Unmarshal(values.Raw, &data); err != nil { + return fmt.Errorf("failed to parse HelmRelease values: %w", err) + } + + host, ok := data["host"].(string) + if !ok || host == "" { + return fmt.Errorf("host field not found or not a string") + } + + var ns corev1.Namespace + if err := c.Get(context.TODO(), client.ObjectKey{Name: "tenant-root"}, &ns); err != nil { + return fmt.Errorf("failed to get namespace tenant-root: %w", err) + } + + if ns.Annotations == nil { + ns.Annotations = map[string]string{} + } + ns.Annotations["namespace.cozystack.io/host"] = host + + if err := c.Update(context.TODO(), &ns); err != nil { + return fmt.Errorf("failed to update namespace: %w", err) + } + + return nil +} diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index f1872870..a24744b8 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -8,7 +8,7 @@ {{- $host = index $cozyConfig.data "root-host" }} {{- end }} {{- end }} -{{- $tenantRoot := list }} +{{- $tenantRoot := dict }} {{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} {{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} {{- end }} @@ -37,7 +37,7 @@ metadata: labels: cozystack.io/ui: "true" spec: - interval: 1m + interval: 0s releaseName: tenant-root install: remediation: diff --git a/packages/extra/info/Chart.yaml b/packages/extra/info/Chart.yaml index 2865c6df..d0a06e9f 100644 --- a/packages/extra/info/Chart.yaml +++ b/packages/extra/info/Chart.yaml @@ -3,4 +3,4 @@ name: info description: Info icon: /logos/info.svg type: application -version: 1.0.0 +version: 1.0.1 diff --git a/packages/extra/info/templates/kubeconfig.yaml b/packages/extra/info/templates/kubeconfig.yaml index ff8127d2..d960a587 100644 --- a/packages/extra/info/templates/kubeconfig.yaml +++ b/packages/extra/info/templates/kubeconfig.yaml @@ -11,6 +11,13 @@ {{- $k8sClient := index $k8sClientSecret.data "client-secret-key" | b64dec }} {{- $rootSaConfigMap := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} {{- $k8sCa := index $rootSaConfigMap.data "ca.crt" | b64enc }} + +{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} +{{- $tenantRoot := lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} +{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} +{{- $host = $tenantRoot.spec.values.host }} +{{- end }} +{{- end }} --- apiVersion: v1 kind: Secret diff --git a/packages/extra/ingress/Chart.yaml b/packages/extra/ingress/Chart.yaml index 25d86de0..e6001cc8 100644 --- a/packages/extra/ingress/Chart.yaml +++ b/packages/extra/ingress/Chart.yaml @@ -3,4 +3,4 @@ name: ingress description: NGINX Ingress Controller icon: /logos/ingress-nginx.svg type: application -version: 1.5.0 +version: 1.5.1 diff --git a/packages/extra/ingress/templates/dashboard.yaml b/packages/extra/ingress/templates/dashboard.yaml index 830e7a0a..28b6722c 100644 --- a/packages/extra/ingress/templates/dashboard.yaml +++ b/packages/extra/ingress/templates/dashboard.yaml @@ -4,6 +4,15 @@ {{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} {{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $tenantRoot := dict }} +{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} +{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} +{{- end }} +{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} +{{- $host = $tenantRoot.spec.values.host }} +{{- else }} +{{- end }} + {{- if .Values.dashboard }} apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/packages/extra/versions_map b/packages/extra/versions_map index 289b0cfe..a76418a5 100644 --- a/packages/extra/versions_map +++ b/packages/extra/versions_map @@ -11,13 +11,15 @@ etcd 2.5.0 24fa7222 etcd 2.6.0 8c460528 etcd 2.6.1 45a7416c etcd 2.7.0 HEAD -info 1.0.0 HEAD +info 1.0.0 93bdf411 +info 1.0.1 HEAD ingress 1.0.0 d7cfa53c ingress 1.1.0 5bbc488e ingress 1.2.0 28fca4ef ingress 1.3.0 fde4bcfa ingress 1.4.0 fd240701 -ingress 1.5.0 HEAD +ingress 1.5.0 93bdf411 +ingress 1.5.1 HEAD monitoring 1.0.0 d7cfa53c monitoring 1.1.0 25221fdc monitoring 1.2.0 f81be075 diff --git a/packages/system/cozystack-controller/templates/rbac.yaml b/packages/system/cozystack-controller/templates/rbac.yaml index af3dae33..64f1eaa1 100644 --- a/packages/system/cozystack-controller/templates/rbac.yaml +++ b/packages/system/cozystack-controller/templates/rbac.yaml @@ -9,3 +9,6 @@ rules: - apiGroups: ['cozystack.io'] resources: ['*'] verbs: ['*'] +- apiGroups: ["helm.toolkit.fluxcd.io"] + resources: ["helmreleases"] + verbs: ["get", "list", "watch", "patch", "update"] diff --git a/packages/system/keycloak-configure/templates/configure-kk.yaml b/packages/system/keycloak-configure/templates/configure-kk.yaml index adee11b6..b2d8db5b 100644 --- a/packages/system/keycloak-configure/templates/configure-kk.yaml +++ b/packages/system/keycloak-configure/templates/configure-kk.yaml @@ -4,6 +4,15 @@ {{- $rootSaConfigMap := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} {{- $k8sCa := index $rootSaConfigMap.data "ca.crt" | b64enc }} +{{- $tenantRoot := dict }} +{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} +{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} +{{- end }} +{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} +{{- $host = $tenantRoot.spec.values.host }} +{{- else }} +{{- end }} + {{- $existingK8sSecret := lookup "v1" "Secret" .Release.Namespace "k8s-client" }} {{- $existingKubeappsSecret := lookup "v1" "Secret" .Release.Namespace "kubeapps-client" }} {{- $existingAuthConfig := lookup "v1" "Secret" "cozy-dashboard" "kubeapps-auth-config" }} diff --git a/packages/system/keycloak/templates/ingress.yaml b/packages/system/keycloak/templates/ingress.yaml index 7618a9f5..6ae1384a 100644 --- a/packages/system/keycloak/templates/ingress.yaml +++ b/packages/system/keycloak/templates/ingress.yaml @@ -5,6 +5,15 @@ {{- $rootns := lookup "v1" "Namespace" "" "tenant-root" }} {{- $ingress := index $rootns.metadata.annotations "namespace.cozystack.io/ingress" }} +{{- $tenantRoot := dict }} +{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} +{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} +{{- end }} +{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} +{{- $host = $tenantRoot.spec.values.host }} +{{- else }} +{{- end }} + apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/packages/system/keycloak/templates/sts.yaml b/packages/system/keycloak/templates/sts.yaml index e625859b..cecb17a1 100644 --- a/packages/system/keycloak/templates/sts.yaml +++ b/packages/system/keycloak/templates/sts.yaml @@ -7,6 +7,15 @@ {{- $password = index $existingPassword.data "password" | b64dec }} {{- end }} +{{- $tenantRoot := dict }} +{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} +{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} +{{- end }} +{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} +{{- $host = $tenantRoot.spec.values.host }} +{{- else }} +{{- end }} + apiVersion: v1 kind: Secret metadata: From 12c6df83f505e866f98999b47897e06c0493a28a Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Fri, 25 Apr 2025 15:09:31 +0300 Subject: [PATCH 035/120] [docs] Update release policy: Release Candidate versions Signed-off-by: Nick Volynkin --- docs/release.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/release.md b/docs/release.md index 062b7a56..22366f6b 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,10 +1,37 @@ # Release Workflow -This section explains how Cozystack builds and releases are made. +This document describes Cozystack’s release process. + +## Introduction + +Cozystack uses a staged release process to ensure stability and flexibility during development. + +There are three types of releases: + +- **Release Candidates (RC)** – Preview versions (e.g., `v0.42.0-rc.1`) used for final testing and validation. +- **Regular Releases** – Final versions (e.g., `v0.42.0`) that are feature-complete and thoroughly tested. +- **Patch Releases** – Bugfix-only updates (e.g., `v0.42.1`) made after a stable release, based on a dedicated release branch. + +Each type plays a distinct role in delivering reliable and tested updates while allowing ongoing development to continue smoothly. + +## Release Candidates + +Release candidates are Cozystack versions that introduce new features and are published before a stable release. +Their purpose is to help validate stability before finalizing a new feature release. +They allow for final rounds of testing and bug fixes without freezing development. + +Release candidates are given numbers `vX.Y.0-rc.N`, for example, `v0.42.0-rc.1`. +They are created directly in the `main` branch. +An RC is typically tagged when all major features for the upcoming release have been merged into main and the release enters its testing phase. +However, new features and changes can still be added before the regular release `vX.Y.0`. + +Each RC contributes to a cumulative set of release notes that will be finalized when `vX.Y.0` is released. +After testing, if no critical issues remain, the regular release (`vX.Y.0`) is tagged from the last RC or a later commit in main. +This begins the regular release process, creates a dedicated `release-X.Y` branch, and opens the way for patch releases. ## Regular Releases -When making regular releases, we take a commit in `main` and decide to make it a release `x.y.0`. +When making a regular release, we tag the latest RC or a subsequent minimal-change commit as `vX.Y.0`. In this explanation, we'll use version `v0.42.0` as an example: ```mermaid From 70fed8148d2d7199ddd3cfdba783c05a153ef412 Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Mon, 5 May 2025 11:57:02 +0300 Subject: [PATCH 036/120] [ci] Run pre-commit checks even on doc changes Pre-commit is now required to merge PRs, so let it run even on documentation updates. An alternative is to merge with administrator permissions, bypassing rules, which is not a good practice. Signed-off-by: Nick Volynkin --- .github/workflows/pre-commit.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 8556c2bd..65c48051 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -3,8 +3,6 @@ name: Pre-Commit Checks on: pull_request: types: [labeled, opened, synchronize, reopened] - paths-ignore: - - '**.md' concurrency: group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number }} From a03cdeff0494ab538b36fb016857a0dd3aae96a8 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Mon, 5 May 2025 14:58:31 +0300 Subject: [PATCH 037/120] Enable user-added params in tenant cluster Cilium Users requested the possibility of passing custom values to the Cilium HelmRelease in tenant k8s clusters to enable its latest features, such as support for the Gateway API. This customization is now available via the `valuesOverride` field under `addons.cilium` in the kubernetes' app values. Additionally add dummy schema for S3 bucket, as it breaks the pre-commit checks. Signed-off-by: Timofei Larkin --- packages/apps/bucket/README.md | 3 +++ packages/apps/bucket/values.schema.json | 5 +++++ packages/apps/bucket/values.yaml | 1 + packages/apps/kubernetes/Chart.yaml | 2 +- packages/apps/kubernetes/README.md | 1 + .../templates/helmreleases/cilium.yaml | 16 ++++++++++------ packages/apps/kubernetes/values.schema.json | 10 ++++++++++ packages/apps/kubernetes/values.yaml | 6 ++++++ packages/apps/versions_map | 3 ++- 9 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 packages/apps/bucket/README.md create mode 100644 packages/apps/bucket/values.schema.json create mode 100644 packages/apps/bucket/values.yaml diff --git a/packages/apps/bucket/README.md b/packages/apps/bucket/README.md new file mode 100644 index 00000000..89749b1d --- /dev/null +++ b/packages/apps/bucket/README.md @@ -0,0 +1,3 @@ +# S3 bucket + +## Parameters diff --git a/packages/apps/bucket/values.schema.json b/packages/apps/bucket/values.schema.json new file mode 100644 index 00000000..decc79aa --- /dev/null +++ b/packages/apps/bucket/values.schema.json @@ -0,0 +1,5 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/packages/apps/bucket/values.yaml b/packages/apps/bucket/values.yaml new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/packages/apps/bucket/values.yaml @@ -0,0 +1 @@ +{} diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index 05076167..7daa8598 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.19.0 +version: 0.20.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index 94a4ff6e..79c01191 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -44,6 +44,7 @@ kubectl get secret -n kubernetes--admin-kubeconfig -o g | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `addons.certManager.enabled` | Enables the cert-manager | `false` | | `addons.certManager.valuesOverride` | Custom values to override | `{}` | +| `addons.cilium.valuesOverride` | Custom values to override | `{}` | | `addons.ingressNginx.enabled` | Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) | `false` | | `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | | `addons.ingressNginx.hosts` | List of domain names that should be passed through to the cluster by upper cluster | `[]` | diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index 6b03bdb3..448e5976 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -1,3 +1,12 @@ +{{- define "cozystack.defaultCiliumValues" -}} +cilium: + k8sServiceHost: {{ .Release.Name }}.{{ .Release.Namespace }}.svc + k8sServicePort: 6443 + routingMode: tunnel + enableIPv4Masquerade: true + ipv4NativeRoutingCIDR: "" +{{- end }} + apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -31,12 +40,7 @@ spec: remediation: retries: -1 values: - cilium: - k8sServiceHost: {{ .Release.Name }}.{{ .Release.Namespace }}.svc - k8sServicePort: 6443 - routingMode: tunnel - enableIPv4Masquerade: true - ipv4NativeRoutingCIDR: "" + {{- toYaml (deepCopy .Values.addons.cilium.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCiliumValues" .))) | nindent 4 }} dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index c69a30aa..7a2ac3d1 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -145,6 +145,16 @@ } } }, + "cilium": { + "type": "object", + "properties": { + "valuesOverride": { + "type": "object", + "description": "Custom values to override", + "default": {} + } + } + }, "ingressNginx": { "type": "object", "properties": { diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index 388c465b..805d5bec 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -42,6 +42,12 @@ addons: enabled: false valuesOverride: {} + ## Cilium CNI plugin + ## + cilium: + ## @param addons.cilium.valuesOverride Custom values to override + valuesOverride: {} + ## Ingress-NGINX Controller ## ingressNginx: diff --git a/packages/apps/versions_map b/packages/apps/versions_map index 749d92e0..b7c09ab7 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -59,7 +59,8 @@ kubernetes 0.16.0 077045b0 kubernetes 0.17.0 1fbbfcd0 kubernetes 0.17.1 fd240701 kubernetes 0.18.0 721c12a7 -kubernetes 0.19.0 HEAD +kubernetes 0.19.0 93bdf411 +kubernetes 0.20.0 HEAD mysql 0.1.0 263e47be mysql 0.2.0 c24a103f mysql 0.3.0 53f2365e From 3c27192d3e9181e2b3552a85c6928050944c9c25 Mon Sep 17 00:00:00 2001 From: kklinch0 Date: Mon, 5 May 2025 16:56:04 +0300 Subject: [PATCH 038/120] [platform] delete extra dependencies for piraeus operator Signed-off-by: kklinch0 --- packages/core/platform/bundles/distro-full.yaml | 2 +- packages/system/linstor/templates/podscrape.yaml | 2 ++ packages/system/piraeus-operator/templates/alerts.yaml | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core/platform/bundles/distro-full.yaml b/packages/core/platform/bundles/distro-full.yaml index 08c2da4a..8c37a023 100644 --- a/packages/core/platform/bundles/distro-full.yaml +++ b/packages/core/platform/bundles/distro-full.yaml @@ -161,7 +161,7 @@ releases: releaseName: piraeus-operator chart: cozy-piraeus-operator namespace: cozy-linstor - dependsOn: [cilium,cert-manager,victoria-metrics-operator] + dependsOn: [cilium,cert-manager] - name: snapshot-controller releaseName: snapshot-controller diff --git a/packages/system/linstor/templates/podscrape.yaml b/packages/system/linstor/templates/podscrape.yaml index 91b2de49..9c334527 100644 --- a/packages/system/linstor/templates/podscrape.yaml +++ b/packages/system/linstor/templates/podscrape.yaml @@ -1,3 +1,4 @@ +{{- if .Capabilities.APIVersions.Has "operator.victoriametrics.com/v1beta1" }} apiVersion: operator.victoriametrics.com/v1beta1 kind: VMPodScrape metadata: @@ -42,3 +43,4 @@ spec: selector: matchLabels: app.kubernetes.io/component: linstor-controller +{{- end }} diff --git a/packages/system/piraeus-operator/templates/alerts.yaml b/packages/system/piraeus-operator/templates/alerts.yaml index 70d47014..c8387a65 100644 --- a/packages/system/piraeus-operator/templates/alerts.yaml +++ b/packages/system/piraeus-operator/templates/alerts.yaml @@ -1,7 +1,8 @@ {{- $files := .Files.Glob "alerts/*.yaml" -}} +{{- if .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" }} {{- range $path, $file := $files }} --- # from: {{ $path }} {{ toString $file }} - +{{- end }} {{- end -}} From 3ac00ea4ecc1113a2561a732c011dd31e8b2a132 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Wed, 7 May 2025 14:34:51 +0300 Subject: [PATCH 039/120] Update kube-ovn to latest version This commit bumps kube-ovn to 1.13.11 and does away with patching the code now that the fixes necessary for kube-ovn to work properly in Talos have been released in the upstream. Signed-off-by: Timofei Larkin --- packages/system/kubeovn/charts/kube-ovn/Chart.yaml | 4 ++-- .../charts/kube-ovn/templates/controller-deploy.yaml | 3 +++ .../kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml | 12 ++++-------- .../kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml | 10 ++++++---- packages/system/kubeovn/charts/kube-ovn/values.yaml | 2 +- packages/system/kubeovn/images/kubeovn/Dockerfile | 9 +-------- packages/system/kubeovn/patches/cozyconfig.diff | 10 ++++++++-- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml index 4e0752a1..7444af6a 100644 --- a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml @@ -15,12 +15,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: v1.13.10 +version: v1.13.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.13.10" +appVersion: "1.13.11" kubeVersion: ">= 1.23.0-0" diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml index 5c6afffa..2f5ef406 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml @@ -83,6 +83,9 @@ spec: - --node-switch={{ .Values.networking.NODE_SUBNET }} - --node-switch-cidr={{ index $cozyConfig.data "ipv4-join-cidr" }} - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + {{- if .Values.global.logVerbosity }} + - --v={{ .Values.global.logVerbosity }} + {{- end }} - --network-type={{- .Values.networking.NETWORK_TYPE }} - --default-provider-name={{ .Values.networking.vlan.PROVIDER_NAME }} - --default-interface-name={{- .Values.networking.vlan.VLAN_INTERFACE_NAME }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml index 01136f89..3a749f84 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml @@ -35,11 +35,7 @@ spec: command: - sh - -xec - - {{ if not .Values.DISABLE_MODULES_MANAGEMENT -}} - iptables -V - {{- else -}} - echo "nothing to do" - {{- end }} + - iptables -V securityContext: allowPrivilegeEscalation: true capabilities: @@ -93,6 +89,9 @@ spec: - --node-switch={{ .Values.networking.NODE_SUBNET }} - --encap-checksum=true - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + {{- if .Values.global.logVerbosity }} + - --v={{ .Values.global.logVerbosity }} + {{- end }} {{- if eq .Values.networking.NETWORK_TYPE "vlan" }} - --iface= {{- else}} @@ -125,9 +124,6 @@ spec: - NET_RAW - SYS_ADMIN - SYS_PTRACE - {{- if not .Values.DISABLE_MODULES_MANAGEMENT }} - - SYS_MODULE - {{- end }} - SYS_NICE env: - name: ENABLE_SSL diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml index 33fa06d3..003d0c71 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml @@ -49,8 +49,9 @@ spec: - -xec - | chown -R nobody: /var/run/ovn /var/log/ovn /etc/openvswitch /var/run/openvswitch /var/log/openvswitch - {{- if not .Values.DISABLE_MODULES_MANAGEMENT }} iptables -V + {{- if not .Values.DISABLE_MODULES_MANAGEMENT }} + /usr/share/openvswitch/scripts/ovs-ctl load-kmod {{- else }} ln -sf /bin/true /usr/local/sbin/modprobe ln -sf /bin/true /usr/local/sbin/modinfo @@ -64,6 +65,9 @@ spec: privileged: true runAsUser: 0 volumeMounts: + - mountPath: /lib/modules + name: host-modules + readOnly: true - mountPath: /usr/local/sbin name: usr-local-sbin - mountPath: /var/log/ovn @@ -96,9 +100,7 @@ spec: add: - NET_ADMIN - NET_BIND_SERVICE - {{- if not .Values.DISABLE_MODULES_MANAGEMENT }} - - SYS_MODULE - {{- end }} + - NET_RAW - SYS_NICE - SYS_ADMIN env: diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml index 1ebbd3a8..d6185a9c 100644 --- a/packages/system/kubeovn/charts/kube-ovn/values.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml @@ -10,7 +10,7 @@ global: repository: kube-ovn dpdkRepository: kube-ovn-dpdk vpcRepository: vpc-nat-gateway - tag: v1.13.10 + tag: v1.13.11 support_arm: true thirdparty: true diff --git a/packages/system/kubeovn/images/kubeovn/Dockerfile b/packages/system/kubeovn/images/kubeovn/Dockerfile index 8914c18b..a3e85382 100644 --- a/packages/system/kubeovn/images/kubeovn/Dockerfile +++ b/packages/system/kubeovn/images/kubeovn/Dockerfile @@ -1,9 +1,2 @@ -ARG VERSION=v1.13.10 +ARG VERSION=v1.13.11 FROM kubeovn/kube-ovn:${VERSION} - -# Fix https://github.com/kubeovn/kube-ovn/issues/4526 -RUN setcap CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /usr/lib/openvswitch-switch/ovs-vswitchd \ - && setcap CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /usr/sbin/xtables-legacy-multi \ - && setcap CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /usr/sbin/xtables-nft-multi \ - && setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE,CAP_SYS_ADMIN+eip /usr/sbin/ipset \ - && setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_SYS_ADMIN+eip /usr/bin/ip diff --git a/packages/system/kubeovn/patches/cozyconfig.diff b/packages/system/kubeovn/patches/cozyconfig.diff index c5a14190..f7a683f7 100644 --- a/packages/system/kubeovn/patches/cozyconfig.diff +++ b/packages/system/kubeovn/patches/cozyconfig.diff @@ -3,7 +3,7 @@ diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/ index d9a9a67..b2e12dd 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml -@@ -51,18 +51,12 @@ spec: +@@ -51,18 +51,15 @@ spec: - bash - /kube-ovn/start-cniserver.sh args: @@ -21,6 +21,9 @@ index d9a9a67..b2e12dd 100644 - {{ .Values.ipv6.SVC_CIDR }} - {{- end }} + - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} ++ {{- if .Values.global.logVerbosity }} ++ - --v={{ .Values.global.logVerbosity }} ++ {{- end }} {{- if eq .Values.networking.NETWORK_TYPE "vlan" }} - --iface= {{- else}} @@ -28,7 +31,7 @@ diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy index 0e69494..756eb7c 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml -@@ -52,46 +52,19 @@ spec: +@@ -52,46 +52,22 @@ spec: image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} imagePullPolicy: {{ .Values.image.pullPolicy }} args: @@ -77,6 +80,9 @@ index 0e69494..756eb7c 100644 - {{- end }} + - --node-switch-cidr={{ index $cozyConfig.data "ipv4-join-cidr" }} + - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} ++ {{- if .Values.global.logVerbosity }} ++ - --v={{ .Values.global.logVerbosity }} ++ {{- end }} - --network-type={{- .Values.networking.NETWORK_TYPE }} - --default-provider-name={{ .Values.networking.vlan.PROVIDER_NAME }} - --default-interface-name={{- .Values.networking.vlan.VLAN_INTERFACE_NAME }} From 68c85ac9ef57eed5e41d271e45f63cc825bce675 Mon Sep 17 00:00:00 2001 From: Zdenek Deu Janda Date: Wed, 7 May 2025 07:43:00 +0200 Subject: [PATCH 040/120] [kubernetes] Enable Cilium Gateway API Signed-off-by: Zdenek Deu Janda --- .../templates/helmreleases/cilium.yaml | 10 + .../templates/helmreleases/gateway-api.yaml | 38 + packages/system/gateway-api/Chart.yaml | 3 + packages/system/gateway-api/Makefile | 10 + .../templates/crds-experimental.yaml | 14926 ++++++++++++++++ 5 files changed, 14987 insertions(+) create mode 100644 packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml create mode 100644 packages/system/gateway-api/Chart.yaml create mode 100644 packages/system/gateway-api/Makefile create mode 100644 packages/system/gateway-api/templates/crds-experimental.yaml diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index 448e5976..ee31d30e 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -5,6 +5,12 @@ cilium: routingMode: tunnel enableIPv4Masquerade: true ipv4NativeRoutingCIDR: "" + {{- if $.Values.addons.gatewayAPI.enabled }} + gatewayAPI: + enabled: true + envoy: + enabled: true + {{- end }} {{- end }} apiVersion: helm.toolkit.fluxcd.io/v2 @@ -46,3 +52,7 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} + {{- if $.Values.addons.gatewayAPI.enabled }} + - name: {{ .Release.Name }}-gateway-api + namespace: {{ .Release.Namespace }} + {{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml b/packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml new file mode 100644 index 00000000..c7e3ad7a --- /dev/null +++ b/packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml @@ -0,0 +1,38 @@ +{{- if $.Values.addons.gatewayAPI.enabled }} +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-gateway-api + labels: + cozystack.io/repository: system + cozystack.io/target-cluster-name: {{ .Release.Name }} +spec: + interval: 5m + releaseName: gateway-api + chart: + spec: + chart: cozy-gateway-api + reconcileStrategy: Revision + sourceRef: + kind: HelmRepository + name: cozystack-system + namespace: cozy-system + kubeConfig: + secretRef: + name: {{ .Release.Name }}-admin-kubeconfig + key: super-admin.svc + targetNamespace: kube-system + storageNamespace: kube-system + install: + createNamespace: false + remediation: + retries: -1 + upgrade: + remediation: + retries: -1 + dependsOn: + {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} + - name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + {{- end }} +{{- end }} diff --git a/packages/system/gateway-api/Chart.yaml b/packages/system/gateway-api/Chart.yaml new file mode 100644 index 00000000..1063b9f2 --- /dev/null +++ b/packages/system/gateway-api/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-gateway-api +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/gateway-api/Makefile b/packages/system/gateway-api/Makefile new file mode 100644 index 00000000..e6191a71 --- /dev/null +++ b/packages/system/gateway-api/Makefile @@ -0,0 +1,10 @@ +export NAME=gateway-api +export NAMESPACE=cozy-$(NAME) + +include ../../../scripts/package.mk + +update: + rm -rf templates + mkdir templates + kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.2.0" > templates/crds-experimental.yaml + diff --git a/packages/system/gateway-api/templates/crds-experimental.yaml b/packages/system/gateway-api/templates/crds-experimental.yaml new file mode 100644 index 00000000..88b3060e --- /dev/null +++ b/packages/system/gateway-api/templates/crds-experimental.yaml @@ -0,0 +1,14926 @@ +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.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + labels: + gateway.networking.k8s.io/policy: Direct + name: backendlbpolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendLBPolicy + listKind: BackendLBPolicyList + plural: backendlbpolicies + shortNames: + - blbpolicy + singular: backendlbpolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: |- + BackendLBPolicy provides a way to define load balancing rules + for a backend. + 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 BackendLBPolicy. + properties: + sessionPersistence: + description: |- + SessionPersistence defines and configures session persistence + for the backend. + + Support: Extended + properties: + absoluteTimeout: + description: |- + AbsoluteTimeout defines the absolute timeout of the persistent + session. Once the AbsoluteTimeout duration has elapsed, the + session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + description: |- + CookieConfig provides configuration settings that are specific + to cookie-based session persistence. + + Support: Core + properties: + lifetimeType: + default: Session + description: |- + LifetimeType specifies whether the cookie has a permanent or + session-based lifetime. A permanent cookie persists until its + specified expiry time, defined by the Expires or Max-Age cookie + attributes, while a session cookie is deleted when the current + session ends. + + When set to "Permanent", AbsoluteTimeout indicates the + cookie's lifetime via the Expires or Max-Age cookie attributes + and is required. + + When set to "Session", AbsoluteTimeout indicates the + absolute lifetime of the cookie tracked by the gateway and + is optional. + + Support: Core for "Session" type + + Support: Extended for "Permanent" type + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + description: |- + IdleTimeout defines the idle timeout of the persistent session. + Once the session has been idle for more than the specified + IdleTimeout duration, the session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + description: |- + SessionName defines the name of the persistent session token + which may be reflected in the cookie or the header. Users + should avoid reusing session names to prevent unintended + consequences, such as rejection or unpredictable behavior. + + Support: Implementation-specific + maxLength: 128 + type: string + type: + default: Cookie + description: |- + Type defines the type of session persistence such as through + the use a header or cookie. Defaults to cookie based session + persistence. + + Support: Core for "Cookie" type + + Support: Extended for "Header" type + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType + is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) + || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + targetRefs: + description: |- + TargetRef identifies an API object to apply policy to. + Currently, Backends (i.e. Service, ServiceImport, or any + implementation-specific backendRef) are the only valid API + target references. + items: + description: |- + LocalPolicyTargetReference identifies an API object to apply a direct or + inherited policy to. This should be used as part of Policy resources + that can target Gateway API resources. For more information on how this + policy attachment model works, and a sample Policy resource, refer to + the policy attachment documentation for Gateway API. + properties: + group: + description: Group is the group of the target resource. + 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 target resource. + 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 target resource. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - group + - kind + - name + x-kubernetes-list-type: map + required: + - targetRefs + type: object + status: + description: Status defines the current state of BackendLBPolicy. + properties: + ancestors: + description: |- + Ancestors is a list of ancestor resources (usually Gateways) that are + associated with the policy, and the status of the policy with respect to + each ancestor. When this policy attaches to a parent, the controller that + manages the parent and the ancestors MUST add an entry to this list when + the controller first sees the policy and SHOULD update the entry as + appropriate when the relevant ancestor is modified. + + Note that choosing the relevant ancestor is left to the Policy designers; + an important part of Policy design is designing the right object level at + which to namespace this status. + + Note also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations MUST + use the ControllerName field to uniquely identify the entries in this list + that they are responsible for. + + Note that to achieve this, the list of PolicyAncestorStatus structs + MUST be treated as a map with a composite key, made up of the AncestorRef + and ControllerName fields combined. + + A maximum of 16 ancestors will be represented in this list. An empty list + means the Policy is not relevant for any ancestors. + + If this slice is full, implementations MUST NOT add further entries. + Instead they MUST consider the policy unimplementable and signal that + on any related resources such as the ancestor that would be referenced + here. For example, if this list was full on BackendTLSPolicy, no + additional Gateways would be able to reference the Service targeted by + the BackendTLSPolicy. + items: + description: |- + PolicyAncestorStatus describes the status of a route with respect to an + associated Ancestor. + + Ancestors refer to objects that are either the Target of a policy or above it + in terms of object hierarchy. For example, if a policy targets a Service, the + Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and + the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most + useful object to place Policy status on, so we recommend that implementations + SHOULD use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. + + In the context of policy attachment, the Ancestor is used to distinguish which + resource results in a distinct application of this policy. For example, if a policy + targets a Service, it may have a distinct result per attached Gateway. + + Policies targeting the same resource may have different effects depending on the + ancestors of those resources. For example, different Gateways targeting the same + Service may have different capabilities, especially if they have different underlying + implementations. + + For example, in BackendTLSPolicy, the Policy attaches to a Service that is + used as a backend in a HTTPRoute that is itself attached to a Gateway. + In this case, the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. + + Note that a parent is also an ancestor, so for objects where the parent is the + relevant object for status, this struct SHOULD still be used. + + This struct is intended to be used in a slice that's effectively a map, + with a composite key made up of the AncestorRef and the ControllerName. + properties: + ancestorRef: + description: |- + AncestorRef corresponds with a ParentRef in the spec that this + PolicyAncestorStatus 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + 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 + required: + - ancestorRef + - controllerName + type: object + maxItems: 16 + type: array + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +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.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + labels: + gateway.networking.k8s.io/policy: Direct + name: backendtlspolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendTLSPolicy + listKind: BackendTLSPolicyList + plural: backendtlspolicies + shortNames: + - btlspolicy + singular: backendtlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha3 + schema: + openAPIV3Schema: + description: |- + BackendTLSPolicy provides a way to configure how a Gateway + connects to a Backend via TLS. + 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 BackendTLSPolicy. + properties: + 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 + targetRefs: + description: |- + TargetRefs identifies an API object to apply the policy to. + Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. + Note that this config applies to the entire referenced resource + by default, but this default may change in the future to provide + a more granular application of the policy. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + items: + description: |- + LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a + direct policy to. This should be used as part of Policy resources that can + target single resources. For more information on how this policy attachment + mode works, and a sample Policy resource, refer to the policy attachment + documentation for Gateway API. + + Note: This should only be used for direct policy attachment when references + to SectionName are actually needed. In all other cases, + LocalPolicyTargetReference should be used. + properties: + group: + description: Group is the group of the target resource. + 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 target resource. + 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 target resource. + maxLength: 253 + minLength: 1 + type: string + sectionName: + description: |- + SectionName is the name of a section within the target resource. When + unspecified, this targetRef targets the entire resource. In the following + resources, SectionName is interpreted as the following: + + * Gateway: Listener name + * HTTPRoute: HTTPRouteRule name + * Service: Port name + + If a SectionName is specified, but does not exist on the targeted object, + the Policy must fail to attach, and the policy implementation should record + a `ResolvedRefs` or similar Condition in the Policy's status. + 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: + - group + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + validation: + description: Validation contains backend TLS validation configuration. + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to Kubernetes objects that + contain a PEM-encoded TLS CA certificate bundle, which is used to + validate a TLS handshake between the Gateway and backend Pod. + + If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + not both. If CACertifcateRefs is empty or unspecified, the configuration for + WellKnownCACertificates MUST be honored instead if supported by the implementation. + + References to a resource in a different namespace are invalid for the + moment, although we will revisit this in the future. + + A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a backend, but this behavior is implementation-specific. + + Support: Core - An optional single reference to a Kubernetes ConfigMap, + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one reference, or other kinds + of resources). + items: + description: |- + LocalObjectReference identifies an API object within the namespace of the + referrer. + 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: + 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 + maxItems: 8 + type: array + hostname: + description: |- + Hostname is used for two purposes in the connection between Gateways and + backends: + + 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + 2. If SubjectAltNames is not specified, Hostname MUST be used for + authentication and MUST match the certificate served by the matching + backend. + + 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 + subjectAltNames: + description: |- + SubjectAltNames contains one or more Subject Alternative Names. + When specified, the certificate served from the backend MUST have at least one + Subject Alternate Name matching one of the specified SubjectAltNames. + + Support: Core + items: + description: SubjectAltName represents Subject Alternative Name. + properties: + hostname: + description: |- + Hostname contains Subject Alternative Name specified in DNS name format. + Required when Type is set to Hostname, ignored otherwise. + + 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 + type: + description: |- + Type determines the format of the Subject Alternative Name. Always required. + + Support: Core + enum: + - Hostname + - URI + type: string + uri: + description: |- + URI contains Subject Alternative Name specified in a full URI format. + It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + Required when Type is set to URI, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: SubjectAltName element must contain Hostname, if + Type is set to Hostname + rule: '!(self.type == "Hostname" && (!has(self.hostname) || + self.hostname == ""))' + - message: SubjectAltName element must not contain Hostname, + if Type is not set to Hostname + rule: '!(self.type != "Hostname" && has(self.hostname) && + self.hostname != "")' + - message: SubjectAltName element must contain URI, if Type + is set to URI + rule: '!(self.type == "URI" && (!has(self.uri) || self.uri + == ""))' + - message: SubjectAltName element must not contain URI, if Type + is not set to URI + rule: '!(self.type != "URI" && has(self.uri) && self.uri != + "")' + maxItems: 5 + type: array + wellKnownCACertificates: + description: |- + WellKnownCACertificates specifies whether system CA certificates may be used in + the TLS handshake between the gateway and backend pod. + + If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + must be specified with at least one entry for a valid configuration. Only one of + CACertificateRefs or WellKnownCACertificates may be specified, not both. If an + implementation does not support the WellKnownCACertificates field or the value + supplied is not supported, the Status Conditions on the Policy MUST be + updated to include an Accepted: False Condition with Reason: Invalid. + + Support: Implementation-specific + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertificateRefs and WellKnownCACertificates + rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "")' + - message: must specify either CACertificateRefs or WellKnownCACertificates + rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "") + required: + - targetRefs + - validation + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: |- + Ancestors is a list of ancestor resources (usually Gateways) that are + associated with the policy, and the status of the policy with respect to + each ancestor. When this policy attaches to a parent, the controller that + manages the parent and the ancestors MUST add an entry to this list when + the controller first sees the policy and SHOULD update the entry as + appropriate when the relevant ancestor is modified. + + Note that choosing the relevant ancestor is left to the Policy designers; + an important part of Policy design is designing the right object level at + which to namespace this status. + + Note also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations MUST + use the ControllerName field to uniquely identify the entries in this list + that they are responsible for. + + Note that to achieve this, the list of PolicyAncestorStatus structs + MUST be treated as a map with a composite key, made up of the AncestorRef + and ControllerName fields combined. + + A maximum of 16 ancestors will be represented in this list. An empty list + means the Policy is not relevant for any ancestors. + + If this slice is full, implementations MUST NOT add further entries. + Instead they MUST consider the policy unimplementable and signal that + on any related resources such as the ancestor that would be referenced + here. For example, if this list was full on BackendTLSPolicy, no + additional Gateways would be able to reference the Service targeted by + the BackendTLSPolicy. + items: + description: |- + PolicyAncestorStatus describes the status of a route with respect to an + associated Ancestor. + + Ancestors refer to objects that are either the Target of a policy or above it + in terms of object hierarchy. For example, if a policy targets a Service, the + Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and + the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most + useful object to place Policy status on, so we recommend that implementations + SHOULD use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. + + In the context of policy attachment, the Ancestor is used to distinguish which + resource results in a distinct application of this policy. For example, if a policy + targets a Service, it may have a distinct result per attached Gateway. + + Policies targeting the same resource may have different effects depending on the + ancestors of those resources. For example, different Gateways targeting the same + Service may have different capabilities, especially if they have different underlying + implementations. + + For example, in BackendTLSPolicy, the Policy attaches to a Service that is + used as a backend in a HTTPRoute that is itself attached to a Gateway. + In this case, the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. + + Note that a parent is also an ancestor, so for objects where the parent is the + relevant object for status, this struct SHOULD still be used. + + This struct is intended to be used in a slice that's effectively a map, + with a composite key made up of the AncestorRef and the ControllerName. + properties: + ancestorRef: + description: |- + AncestorRef corresponds with a ParentRef in the spec that this + PolicyAncestorStatus 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + 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 + required: + - ancestorRef + - controllerName + type: object + maxItems: 16 + type: array + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +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.0 + gateway.networking.k8s.io/channel: experimental + 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 + supportedFeatures: + description: | + SupportedFeatures is the set of features the GatewayClass support. + It MUST be sorted in ascending alphabetical order by the Name key. + items: + properties: + name: + description: |- + FeatureName is used to describe distinct features that are covered by + conformance tests. + type: string + required: + - name + 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.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 + supportedFeatures: + description: | + SupportedFeatures is the set of features the GatewayClass support. + It MUST be sorted in ascending alphabetical order by the Name key. + items: + properties: + name: + description: |- + FeatureName is used to describe distinct features that are covered by + conformance tests. + type: string + required: + - name + 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 +--- +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.0 + gateway.networking.k8s.io/channel: experimental + 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 )' + backendTLS: + description: |+ + BackendTLS configures TLS settings for when this Gateway is connecting to + backends with TLS. + + Support: Core + + properties: + clientCertificateRef: + description: |+ + ClientCertificateRef is a reference to an object that contains a Client + Certificate and the associated private key. + + 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. + + ClientCertificateRef can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + This setting can be overridden on the service level by use of BackendTLSPolicy. + + Support: Core + + 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 + type: object + 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 + frontendValidation: + description: |+ + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will require clients to send a client certificate + required for validation during the TLS handshake. In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Extended + + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one reference, or other kinds + of resources). + + References to a resource in a 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. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + 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: + 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 "ConfigMap" 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 + 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: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + type: object + 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 )' + backendTLS: + description: |+ + BackendTLS configures TLS settings for when this Gateway is connecting to + backends with TLS. + + Support: Core + + properties: + clientCertificateRef: + description: |+ + ClientCertificateRef is a reference to an object that contains a Client + Certificate and the associated private key. + + 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. + + ClientCertificateRef can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + This setting can be overridden on the service level by use of BackendTLSPolicy. + + Support: Core + + 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 + type: object + 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 + frontendValidation: + description: |+ + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will require clients to send a client certificate + required for validation during the TLS handshake. In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Extended + + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one reference, or other kinds + of resources). + + References to a resource in a 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. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + 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: + 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 "ConfigMap" 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 + 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: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + type: object + 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 +--- +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.0 + gateway.networking.k8s.io/channel: experimental + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal + to denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be + specified in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to + denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be specified + in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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 + name: + description: | + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + sessionPersistence: + description: |+ + SessionPersistence defines and configures session persistence + for the route rule. + + Support: Extended + + properties: + absoluteTimeout: + description: |- + AbsoluteTimeout defines the absolute timeout of the persistent + session. Once the AbsoluteTimeout duration has elapsed, the + session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + description: |- + CookieConfig provides configuration settings that are specific + to cookie-based session persistence. + + Support: Core + properties: + lifetimeType: + default: Session + description: |- + LifetimeType specifies whether the cookie has a permanent or + session-based lifetime. A permanent cookie persists until its + specified expiry time, defined by the Expires or Max-Age cookie + attributes, while a session cookie is deleted when the current + session ends. + + When set to "Permanent", AbsoluteTimeout indicates the + cookie's lifetime via the Expires or Max-Age cookie attributes + and is required. + + When set to "Session", AbsoluteTimeout indicates the + absolute lifetime of the cookie tracked by the gateway and + is optional. + + Support: Core for "Session" type + + Support: Extended for "Permanent" type + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + description: |- + IdleTimeout defines the idle timeout of the persistent session. + Once the session has been idle for more than the specified + IdleTimeout duration, the session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + description: |- + SessionName defines the name of the persistent session token + which may be reflected in the cookie or the header. Users + should avoid reusing session names to prevent unintended + consequences, such as rejection or unpredictable behavior. + + Support: Implementation-specific + maxLength: 128 + type: string + type: + default: Cookie + description: |- + Type defines the type of session persistence such as through + the use a header or cookie. Defaults to cookie based session + persistence. + + Support: Core for "Cookie" type + + Support: Extended for "Header" type + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType + is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) + || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + 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' + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 +--- +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.0 + gateway.networking.k8s.io/channel: experimental + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal + to denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be + specified in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to + denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be specified + in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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 + name: + description: | + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + retry: + description: |+ + Retry defines the configuration for when to retry an HTTP request. + + Support: Extended + + properties: + attempts: + description: |- + Attempts specifies the maxmimum number of times an individual request + from the gateway to a backend should be retried. + + If the maximum number of retries has been attempted without a successful + response from the backend, the Gateway MUST return an error. + + When this field is unspecified, the number of times to attempt to retry + a backend request is implementation-specific. + + Support: Extended + type: integer + backoff: + description: |- + Backoff specifies the minimum duration a Gateway should wait between + retry attempts and is represented in Gateway API Duration formatting. + + For example, setting the `rules[].retry.backoff` field to the value + `100ms` will cause a backend request to first be retried approximately + 100 milliseconds after timing out or receiving a response code configured + to be retryable. + + An implementation MAY use an exponential or alternative backoff strategy + for subsequent retry attempts, MAY cap the maximum backoff duration to + some amount greater than the specified minimum, and MAY add arbitrary + jitter to stagger requests, as long as unsuccessful backend requests are + not retried before the configured minimum duration. + + If a Request timeout (`rules[].timeouts.request`) is configured on the + route, the entire duration of the initial request and any retry attempts + MUST not exceed the Request timeout duration. If any retry attempts are + still in progress when the Request timeout duration has been reached, + these SHOULD be canceled if possible and the Gateway MUST immediately + return a timeout error. + + If a BackendRequest timeout (`rules[].timeouts.backendRequest`) is + configured on the route, any retry attempts which reach the configured + BackendRequest timeout duration without a response SHOULD be canceled if + possible and the Gateway should wait for at least the specified backoff + duration before attempting to retry the backend request again. + + If a BackendRequest timeout is _not_ configured on the route, retry + attempts MAY time out after an implementation default duration, or MAY + remain pending until a configured Request timeout or implementation + default duration for total request time is reached. + + When this field is unspecified, the time to wait between retry attempts + is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + codes: + description: |- + Codes defines the HTTP response status codes for which a backend request + should be retried. + + Support: Extended + items: + description: |- + HTTPRouteRetryStatusCode defines an HTTP response status code for + which a backend request should be retried. + + Implementations MUST support the following status codes as retryable: + + * 500 + * 502 + * 503 + * 504 + + Implementations MAY support specifying additional discrete values in the + 500-599 range. + + Implementations MAY support specifying discrete values in the 400-499 range, + which are often inadvisable to retry. + + + maximum: 599 + minimum: 400 + type: integer + type: array + type: object + sessionPersistence: + description: |+ + SessionPersistence defines and configures session persistence + for the route rule. + + Support: Extended + + properties: + absoluteTimeout: + description: |- + AbsoluteTimeout defines the absolute timeout of the persistent + session. Once the AbsoluteTimeout duration has elapsed, the + session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + description: |- + CookieConfig provides configuration settings that are specific + to cookie-based session persistence. + + Support: Core + properties: + lifetimeType: + default: Session + description: |- + LifetimeType specifies whether the cookie has a permanent or + session-based lifetime. A permanent cookie persists until its + specified expiry time, defined by the Expires or Max-Age cookie + attributes, while a session cookie is deleted when the current + session ends. + + When set to "Permanent", AbsoluteTimeout indicates the + cookie's lifetime via the Expires or Max-Age cookie attributes + and is required. + + When set to "Session", AbsoluteTimeout indicates the + absolute lifetime of the cookie tracked by the gateway and + is optional. + + Support: Core for "Session" type + + Support: Extended for "Permanent" type + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + description: |- + IdleTimeout defines the idle timeout of the persistent session. + Once the session has been idle for more than the specified + IdleTimeout duration, the session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + description: |- + SessionName defines the name of the persistent session token + which may be reflected in the cookie or the header. Users + should avoid reusing session names to prevent unintended + consequences, such as rejection or unpredictable behavior. + + Support: Implementation-specific + maxLength: 128 + type: string + type: + default: Cookie + description: |- + Type defines the type of session persistence such as through + the use a header or cookie. Defaults to cookie based session + persistence. + + Support: Core for "Cookie" type + + Support: Extended for "Header" type + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType + is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) + || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + 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' + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal + to denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be + specified in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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' + fraction: + description: |+ + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to + denominator + rule: self.numerator <= self.denominator + percent: + description: |+ + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + x-kubernetes-validations: + - message: Only one of percent or fraction may be specified + in HTTPRequestMirrorFilter + rule: '!(has(self.percent) && has(self.fraction))' + 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 + name: + description: | + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + retry: + description: |+ + Retry defines the configuration for when to retry an HTTP request. + + Support: Extended + + properties: + attempts: + description: |- + Attempts specifies the maxmimum number of times an individual request + from the gateway to a backend should be retried. + + If the maximum number of retries has been attempted without a successful + response from the backend, the Gateway MUST return an error. + + When this field is unspecified, the number of times to attempt to retry + a backend request is implementation-specific. + + Support: Extended + type: integer + backoff: + description: |- + Backoff specifies the minimum duration a Gateway should wait between + retry attempts and is represented in Gateway API Duration formatting. + + For example, setting the `rules[].retry.backoff` field to the value + `100ms` will cause a backend request to first be retried approximately + 100 milliseconds after timing out or receiving a response code configured + to be retryable. + + An implementation MAY use an exponential or alternative backoff strategy + for subsequent retry attempts, MAY cap the maximum backoff duration to + some amount greater than the specified minimum, and MAY add arbitrary + jitter to stagger requests, as long as unsuccessful backend requests are + not retried before the configured minimum duration. + + If a Request timeout (`rules[].timeouts.request`) is configured on the + route, the entire duration of the initial request and any retry attempts + MUST not exceed the Request timeout duration. If any retry attempts are + still in progress when the Request timeout duration has been reached, + these SHOULD be canceled if possible and the Gateway MUST immediately + return a timeout error. + + If a BackendRequest timeout (`rules[].timeouts.backendRequest`) is + configured on the route, any retry attempts which reach the configured + BackendRequest timeout duration without a response SHOULD be canceled if + possible and the Gateway should wait for at least the specified backoff + duration before attempting to retry the backend request again. + + If a BackendRequest timeout is _not_ configured on the route, retry + attempts MAY time out after an implementation default duration, or MAY + remain pending until a configured Request timeout or implementation + default duration for total request time is reached. + + When this field is unspecified, the time to wait between retry attempts + is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + codes: + description: |- + Codes defines the HTTP response status codes for which a backend request + should be retried. + + Support: Extended + items: + description: |- + HTTPRouteRetryStatusCode defines an HTTP response status code for + which a backend request should be retried. + + Implementations MUST support the following status codes as retryable: + + * 500 + * 502 + * 503 + * 504 + + Implementations MAY support specifying additional discrete values in the + 500-599 range. + + Implementations MAY support specifying discrete values in the 400-499 range, + which are often inadvisable to retry. + + + maximum: 599 + minimum: 400 + type: integer + type: array + type: object + sessionPersistence: + description: |+ + SessionPersistence defines and configures session persistence + for the route rule. + + Support: Extended + + properties: + absoluteTimeout: + description: |- + AbsoluteTimeout defines the absolute timeout of the persistent + session. Once the AbsoluteTimeout duration has elapsed, the + session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + description: |- + CookieConfig provides configuration settings that are specific + to cookie-based session persistence. + + Support: Core + properties: + lifetimeType: + default: Session + description: |- + LifetimeType specifies whether the cookie has a permanent or + session-based lifetime. A permanent cookie persists until its + specified expiry time, defined by the Expires or Max-Age cookie + attributes, while a session cookie is deleted when the current + session ends. + + When set to "Permanent", AbsoluteTimeout indicates the + cookie's lifetime via the Expires or Max-Age cookie attributes + and is required. + + When set to "Session", AbsoluteTimeout indicates the + absolute lifetime of the cookie tracked by the gateway and + is optional. + + Support: Core for "Session" type + + Support: Extended for "Permanent" type + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + description: |- + IdleTimeout defines the idle timeout of the persistent session. + Once the session has been idle for more than the specified + IdleTimeout duration, the session becomes invalid. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + description: |- + SessionName defines the name of the persistent session token + which may be reflected in the cookie or the header. Users + should avoid reusing session names to prevent unintended + consequences, such as rejection or unpredictable behavior. + + Support: Implementation-specific + maxLength: 128 + type: string + type: + default: Cookie + description: |- + Type defines the type of session persistence such as through + the use a header or cookie. Defaults to cookie based session + persistence. + + Support: Core for "Cookie" type + + Support: Extended for "Header" type + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType + is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) + || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + 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' + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 +--- +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.0 + gateway.networking.k8s.io/channel: experimental + 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 +--- +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.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: tcproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TCPRoute + listKind: TCPRouteList + plural: tcproutes + singular: tcproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: |- + TCPRoute provides a way to route TCP requests. When combined with a Gateway + listener, it can be used to forward connections on the port specified by the + listener to a set of backends specified by the TCPRoute. + 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 TCPRoute. + properties: + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + description: |+ + Rules are a list of TCP matchers and actions. + + items: + description: TCPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. If unspecified or invalid (refers to a non-existent resource or a + Service with no endpoints), the underlying implementation MUST actively + reject connection attempts to this backend. Connection rejections must + respect weight; if an invalid backend is requested to have 80% of + connections, then 80% of connections must be rejected instead. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Extended + items: + description: |- + BackendRef defines how a Route should forward a request to a Kubernetes + resource. + + 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. + + + + Note that when the BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. See the fields + where this struct is used for more information about the exact behavior. + 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 + 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 + minItems: 1 + type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-validations: + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + required: + - rules + type: object + status: + description: Status defines the current state of TCPRoute. + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +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.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: tlsroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TLSRoute + listKind: TLSRouteList + plural: tlsroutes + singular: tlsroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: |- + The TLSRoute resource is similar to TCPRoute, but can be configured + to match against TLS-specific metadata. This allows more flexibility + in matching streams for a given TLS listener. + + If you need to forward traffic to a single target for a TLS listener, you + could choose to use a TCPRoute with a TLS listener. + 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 TLSRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of SNI names that should match against the + SNI attribute of TLS ClientHello message in TLS handshake. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed in SNI names per RFC 6066. + 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 TLSRoute, there + must be at least one intersecting hostname for the TLSRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches TLSRoutes + 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 TLSRoutes + 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. + + If both the Listener and TLSRoute have specified hostnames, any + TLSRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + TLSRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and TLSRoute have specified hostnames, and none + match with the criteria above, then the TLSRoute is not accepted. The + implementation 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + description: |+ + Rules are a list of TLS matchers and actions. + + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. If unspecified or invalid (refers to a non-existent resource or + a Service with no endpoints), the rule performs no forwarding; if no + filters are specified that would result in a response being sent, the + underlying implementation must actively reject request attempts to this + backend, by rejecting the connection or returning a 500 status code. + Request rejections must respect weight; if an invalid backend is + requested to have 80% of requests, then 80% of requests must be rejected + instead. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Extended + items: + description: |- + BackendRef defines how a Route should forward a request to a Kubernetes + resource. + + 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. + + + + Note that when the BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. See the fields + where this struct is used for more information about the exact behavior. + 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 + 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 + minItems: 1 + type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-validations: + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +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.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: udproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: UDPRoute + listKind: UDPRouteList + plural: udproutes + singular: udproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: |- + UDPRoute provides a way to route UDP traffic. When combined with a Gateway + listener, it can be used to forward traffic on the port specified by the + listener to a set of backends specified by the UDPRoute. + 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 UDPRoute. + properties: + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + + + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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 or port 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 + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port 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)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + description: |+ + Rules are a list of UDP matchers and actions. + + items: + description: UDPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. If unspecified or invalid (refers to a non-existent resource or a + Service with no endpoints), the underlying implementation MUST actively + reject connection attempts to this backend. Packet drops must + respect weight; if an invalid backend is requested to have 80% of + the packets, then 80% of packets must be dropped instead. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Extended + items: + description: |- + BackendRef defines how a Route should forward a request to a Kubernetes + resource. + + 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. + + + + Note that when the BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. See the fields + where this struct is used for more information about the exact behavior. + 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 + 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 + minItems: 1 + type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + 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 + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-validations: + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + required: + - rules + type: object + status: + description: Status defines the current state of UDPRoute. + 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. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + 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. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null From 563c6438138e709c6c4962eb42c90373fe634886 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 8 May 2025 12:17:41 +0200 Subject: [PATCH 041/120] [kubernetes] refactor gatewayAPI option Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Chart.yaml | 2 +- packages/apps/kubernetes/README.md | 1 + .../apps/kubernetes/templates/helmreleases/cilium.yaml | 2 +- .../apps/kubernetes/templates/helmreleases/delete.yaml | 1 + .../{gateway-api.yaml => gateway-api-crds.yaml} | 6 +++--- packages/apps/kubernetes/values.schema.json | 10 ++++++++++ packages/apps/kubernetes/values.yaml | 6 ++++++ .../{gateway-api => gateway-api-crds}/Chart.yaml | 2 +- .../system/{gateway-api => gateway-api-crds}/Makefile | 3 +-- .../templates/crds-experimental.yaml | 0 10 files changed, 25 insertions(+), 8 deletions(-) rename packages/apps/kubernetes/templates/helmreleases/{gateway-api.yaml => gateway-api-crds.yaml} (88%) rename packages/system/{gateway-api => gateway-api-crds}/Chart.yaml (80%) rename packages/system/{gateway-api => gateway-api-crds}/Makefile (89%) rename packages/system/{gateway-api => gateway-api-crds}/templates/crds-experimental.yaml (100%) diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index 7daa8598..a74f0945 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -22,4 +22,4 @@ version: 0.20.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.30.1" +appVersion: 1.31.0 diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index 79c01191..71cee152 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -45,6 +45,7 @@ kubectl get secret -n kubernetes--admin-kubeconfig -o g | `addons.certManager.enabled` | Enables the cert-manager | `false` | | `addons.certManager.valuesOverride` | Custom values to override | `{}` | | `addons.cilium.valuesOverride` | Custom values to override | `{}` | +| `addons.gatewayAPI.enabled` | Enables the Gateway API | `false` | | `addons.ingressNginx.enabled` | Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) | `false` | | `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | | `addons.ingressNginx.hosts` | List of domain names that should be passed through to the cluster by upper cluster | `[]` | diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index ee31d30e..7e8c7480 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -53,6 +53,6 @@ spec: namespace: {{ .Release.Namespace }} {{- end }} {{- if $.Values.addons.gatewayAPI.enabled }} - - name: {{ .Release.Name }}-gateway-api + - name: {{ .Release.Name }}-gateway-api-crds namespace: {{ .Release.Namespace }} {{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/delete.yaml b/packages/apps/kubernetes/templates/helmreleases/delete.yaml index 6402617c..5b32588e 100644 --- a/packages/apps/kubernetes/templates/helmreleases/delete.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/delete.yaml @@ -30,6 +30,7 @@ spec: patch helmrelease {{ .Release.Name }}-cilium + {{ .Release.Name }}-gateway-api-crds {{ .Release.Name }}-csi {{ .Release.Name }}-cert-manager {{ .Release.Name }}-cert-manager-crds diff --git a/packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml similarity index 88% rename from packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml rename to packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml index c7e3ad7a..1cac6dd9 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gateway-api.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml @@ -2,16 +2,16 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: - name: {{ .Release.Name }}-gateway-api + name: {{ .Release.Name }}-gateway-api-crds labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} spec: interval: 5m - releaseName: gateway-api + releaseName: gateway-api-crds chart: spec: - chart: cozy-gateway-api + chart: cozy-gateway-api-crds reconcileStrategy: Revision sourceRef: kind: HelmRepository diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index 7a2ac3d1..adb29dbd 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -155,6 +155,16 @@ } } }, + "gatewayAPI": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables the Gateway API", + "default": false + } + } + }, "ingressNginx": { "type": "object", "properties": { diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index 805d5bec..d1330b5c 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -48,6 +48,12 @@ addons: ## @param addons.cilium.valuesOverride Custom values to override valuesOverride: {} + ## Gateway API + ## + gatewayAPI: + ## @param addons.gatewayAPI.enabled Enables the Gateway API + enabled: false + ## Ingress-NGINX Controller ## ingressNginx: diff --git a/packages/system/gateway-api/Chart.yaml b/packages/system/gateway-api-crds/Chart.yaml similarity index 80% rename from packages/system/gateway-api/Chart.yaml rename to packages/system/gateway-api-crds/Chart.yaml index 1063b9f2..a6c8d105 100644 --- a/packages/system/gateway-api/Chart.yaml +++ b/packages/system/gateway-api-crds/Chart.yaml @@ -1,3 +1,3 @@ apiVersion: v2 -name: cozy-gateway-api +name: cozy-gateway-api-crds version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/gateway-api/Makefile b/packages/system/gateway-api-crds/Makefile similarity index 89% rename from packages/system/gateway-api/Makefile rename to packages/system/gateway-api-crds/Makefile index e6191a71..c4311662 100644 --- a/packages/system/gateway-api/Makefile +++ b/packages/system/gateway-api-crds/Makefile @@ -1,4 +1,4 @@ -export NAME=gateway-api +export NAME=gateway-api-crds export NAMESPACE=cozy-$(NAME) include ../../../scripts/package.mk @@ -7,4 +7,3 @@ update: rm -rf templates mkdir templates kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.2.0" > templates/crds-experimental.yaml - diff --git a/packages/system/gateway-api/templates/crds-experimental.yaml b/packages/system/gateway-api-crds/templates/crds-experimental.yaml similarity index 100% rename from packages/system/gateway-api/templates/crds-experimental.yaml rename to packages/system/gateway-api-crds/templates/crds-experimental.yaml From 6ad30915eb456d0dec58607780b459a17641a05c Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:44:06 +0300 Subject: [PATCH 042/120] Add PLATFORM make variable; calculate it if undefined Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- scripts/common-envs.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index 99bc29eb..ff2ece4a 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -14,3 +14,16 @@ ifeq ($(COZYSTACK_VERSION),) $(shell git fetch upstream --tags) COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) endif + +# Calculate PLATFORM based on current docker daemon arch +ifndef PLATFORM + DOCKER_DAEMON_ARCH := $(shell docker info --format='{{.Architecture}}') + ifeq ($(DOCKER_DAEMON_ARCH),x86_64) + PLATFORM := linux/amd64 + else ifeq ($(DOCKER_DAEMON_ARCH),aarch64) + PLATFORM := linux/arm64 + else + $(error Unsupported architecture: "$(DOCKER_DAEMON_ARCH)") + endif + undefine DOCKER_DAEMON_ARCH +endif From 1e63b5e8ce150fbcdf5d16999d73203bbd78e4bc Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:46:12 +0300 Subject: [PATCH 043/120] system/cozystack-controller: add PLATFORM variable to Makefile Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/cozystack-controller/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/system/cozystack-controller/Makefile b/packages/system/cozystack-controller/Makefile index a1db9b0a..aafaf036 100644 --- a/packages/system/cozystack-controller/Makefile +++ b/packages/system/cozystack-controller/Makefile @@ -9,6 +9,7 @@ image: image-cozystack-controller update-version image-cozystack-controller: docker buildx build -f images/cozystack-controller/Dockerfile ../../.. \ --provenance false \ + --platform=$(PLATFORM) --tag $(REGISTRY)/cozystack-controller:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cozystack-controller:latest \ --cache-to type=inline \ From b4a04df6f3d9174efea1fb455b4e09cd66ff0dfc Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:54:45 +0300 Subject: [PATCH 044/120] system/cozystack-controller: add PLATFORM variable to Makefile: syntax Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/cozystack-controller/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/system/cozystack-controller/Makefile b/packages/system/cozystack-controller/Makefile index aafaf036..17aa2f9b 100644 --- a/packages/system/cozystack-controller/Makefile +++ b/packages/system/cozystack-controller/Makefile @@ -9,7 +9,7 @@ image: image-cozystack-controller update-version image-cozystack-controller: docker buildx build -f images/cozystack-controller/Dockerfile ../../.. \ --provenance false \ - --platform=$(PLATFORM) + --platform=$(PLATFORM) \ --tag $(REGISTRY)/cozystack-controller:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cozystack-controller:latest \ --cache-to type=inline \ From 57fefde732c21b3c5e6aea8c9e8f3fb307e2473a Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Fri, 2 May 2025 21:43:17 +0300 Subject: [PATCH 045/120] scrips/common-envs.mk: add BUILDER and PLATFORM calculation Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- scripts/common-envs.mk | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index ff2ece4a..b1f7e77e 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -15,15 +15,7 @@ ifeq ($(COZYSTACK_VERSION),) COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) endif -# Calculate PLATFORM based on current docker daemon arch -ifndef PLATFORM - DOCKER_DAEMON_ARCH := $(shell docker info --format='{{.Architecture}}') - ifeq ($(DOCKER_DAEMON_ARCH),x86_64) - PLATFORM := linux/amd64 - else ifeq ($(DOCKER_DAEMON_ARCH),aarch64) - PLATFORM := linux/arm64 - else - $(error Unsupported architecture: "$(DOCKER_DAEMON_ARCH)") - endif - undefine DOCKER_DAEMON_ARCH -endif +# Get the name of the default docker buildx builder +BUILDER ?= $(shell docker buildx inspect | head -n2 | awk '/^Name:/{print $$NF}') +# Get platforms supported by the builder +PLATFORM ?= $(shell docker buildx inspect $(BUILDER) | egrep '^Platforms:' | egrep -o 'linux/amd64|linux/arm64' | sort -u | xargs | sed 's/ /,/g') From 15c9c4a0689021f0626e40528bb5004ba5fc8cda Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Fri, 2 May 2025 21:43:55 +0300 Subject: [PATCH 046/120] system/cozystack-controller: add PLATFORM and BUILDER variables to Makefile Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/cozystack-controller/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/system/cozystack-controller/Makefile b/packages/system/cozystack-controller/Makefile index 17aa2f9b..a75faea9 100644 --- a/packages/system/cozystack-controller/Makefile +++ b/packages/system/cozystack-controller/Makefile @@ -9,6 +9,7 @@ image: image-cozystack-controller update-version image-cozystack-controller: docker buildx build -f images/cozystack-controller/Dockerfile ../../.. \ --provenance false \ + --builder=$(BUILDER) \ --platform=$(PLATFORM) \ --tag $(REGISTRY)/cozystack-controller:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cozystack-controller:latest \ From 951ba75d938e5df5b65ca20b34b97bdc4d15ba4f Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Fri, 2 May 2025 23:51:37 +0300 Subject: [PATCH 047/120] scripts/common-envs.mk: add --bootsrap flag to inspects Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- scripts/common-envs.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index b1f7e77e..79b08799 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -16,6 +16,6 @@ ifeq ($(COZYSTACK_VERSION),) endif # Get the name of the default docker buildx builder -BUILDER ?= $(shell docker buildx inspect | head -n2 | awk '/^Name:/{print $$NF}') +BUILDER ?= $(shell docker buildx inspect --bootstrap | head -n2 | awk '/^Name:/{print $$NF}') # Get platforms supported by the builder -PLATFORM ?= $(shell docker buildx inspect $(BUILDER) | egrep '^Platforms:' | egrep -o 'linux/amd64|linux/arm64' | sort -u | xargs | sed 's/ /,/g') +PLATFORM ?= $(shell docker buildx inspect --bootstrap $(BUILDER) | egrep '^Platforms:' | egrep -o 'linux/amd64|linux/arm64' | sort -u | xargs | sed 's/ /,/g') From bbb93c647d8cd23a3af3571aadc4aada7ea18ed8 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Tue, 6 May 2025 16:24:26 +0300 Subject: [PATCH 048/120] scripts/common-envs.mk: commit suggestions after a review Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- scripts/common-envs.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index 79b08799..a2a4c103 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -16,6 +16,9 @@ ifeq ($(COZYSTACK_VERSION),) endif # Get the name of the default docker buildx builder -BUILDER ?= $(shell docker buildx inspect --bootstrap | head -n2 | awk '/^Name:/{print $$NF}') +BUILDER ?= $(shell jq -r '.Name' ~/.docker/buildx/current) # Get platforms supported by the builder +# TODO: figure out how to get runners status dynamically, in json +# PLATFORM ?= $(shell jq -r '.Nodes[] | .Platforms | map(.os + "/" + .architecture) | join(",")' ~/.docker/buildx/instances/$(BUILDER)) PLATFORM ?= $(shell docker buildx inspect --bootstrap $(BUILDER) | egrep '^Platforms:' | egrep -o 'linux/amd64|linux/arm64' | sort -u | xargs | sed 's/ /,/g') + From 57ac6148655ec7648f02f8c414a3985afdcb47b0 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Tue, 6 May 2025 19:31:22 +0300 Subject: [PATCH 049/120] Makefile: add buildx version requirement Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 99309f4e..66efb02c 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ build-deps: @tar --version | grep -q GNU || (echo "GNU tar is required" && exit 1) @sed --version | grep -q GNU || (echo "GNU sed is required" && exit 1) @awk --version | grep -q GNU || (echo "GNU awk is required" && exit 1) + @docker info --format=json | jq -r '"v0.13.0\n\(.ClientInfo.Plugins[] | select(.Name == "buildx") | .Version)"' | sort -CV || (echo "docker buildx plugin version >=0.13.0 is required" && exit 1) build: build-deps make -C packages/apps/http-cache image From 13139dd71d4202c41c439d505d07f4e74c6dbf94 Mon Sep 17 00:00:00 2001 From: Ubuntu <166552198+nbykov0@users.noreply.github.com> Date: Wed, 7 May 2025 22:56:07 +0300 Subject: [PATCH 050/120] Revert "Makefile: add buildx version requirement" This reverts commit 8d367533550236fc587bd5f236046c15f6b7609a. The check it introduced is not needed. Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 66efb02c..99309f4e 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ build-deps: @tar --version | grep -q GNU || (echo "GNU tar is required" && exit 1) @sed --version | grep -q GNU || (echo "GNU sed is required" && exit 1) @awk --version | grep -q GNU || (echo "GNU awk is required" && exit 1) - @docker info --format=json | jq -r '"v0.13.0\n\(.ClientInfo.Plugins[] | select(.Name == "buildx") | .Version)"' | sort -CV || (echo "docker buildx plugin version >=0.13.0 is required" && exit 1) build: build-deps make -C packages/apps/http-cache image From 2349ff61c12ae9d04ce611c990fdfec5aee371e5 Mon Sep 17 00:00:00 2001 From: Ubuntu <166552198+nbykov0@users.noreply.github.com> Date: Wed, 7 May 2025 23:25:51 +0300 Subject: [PATCH 051/120] scripts/common-envs.mk: add PLATFORM calculation with json parsing Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- scripts/common-envs.mk | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/common-envs.mk b/scripts/common-envs.mk index a2a4c103..98f4652a 100644 --- a/scripts/common-envs.mk +++ b/scripts/common-envs.mk @@ -15,10 +15,8 @@ ifeq ($(COZYSTACK_VERSION),) COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) endif -# Get the name of the default docker buildx builder -BUILDER ?= $(shell jq -r '.Name' ~/.docker/buildx/current) +# Get the name of the selected docker buildx builder +BUILDER ?= $(shell docker buildx inspect --bootstrap | head -n2 | awk '/^Name:/{print $$NF}') # Get platforms supported by the builder -# TODO: figure out how to get runners status dynamically, in json -# PLATFORM ?= $(shell jq -r '.Nodes[] | .Platforms | map(.os + "/" + .architecture) | join(",")' ~/.docker/buildx/instances/$(BUILDER)) -PLATFORM ?= $(shell docker buildx inspect --bootstrap $(BUILDER) | egrep '^Platforms:' | egrep -o 'linux/amd64|linux/arm64' | sort -u | xargs | sed 's/ /,/g') +PLATFORM ?= $(shell docker buildx ls --format=json | jq -r 'select(.Name == "$(BUILDER)") | [.Nodes[].Platforms // []] | flatten | unique | map(select(test("^linux/amd64$$|^linux/arm64$$"))) | join(",")') From 1ad1b15a5befb82025179c1cc25678072f94c424 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 9 May 2025 14:55:54 +0200 Subject: [PATCH 052/120] [talos] Update Talos Linux v1.10.1 Signed-off-by: Andrei Kvapil --- .../images/talos/profiles/initramfs.yaml | 16 ++++++++-------- .../images/talos/profiles/installer.yaml | 16 ++++++++-------- .../installer/images/talos/profiles/iso.yaml | 16 ++++++++-------- .../installer/images/talos/profiles/kernel.yaml | 16 ++++++++-------- .../installer/images/talos/profiles/metal.yaml | 16 ++++++++-------- .../installer/images/talos/profiles/nocloud.yaml | 16 ++++++++-------- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/core/installer/images/talos/profiles/initramfs.yaml b/packages/core/installer/images/talos/profiles/initramfs.yaml index af5f34cc..2898ed61 100644 --- a/packages/core/installer/images/talos/profiles/initramfs.yaml +++ b/packages/core/installer/images/talos/profiles/initramfs.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: initramfs imageOptions: {} diff --git a/packages/core/installer/images/talos/profiles/installer.yaml b/packages/core/installer/images/talos/profiles/installer.yaml index b717ba3e..594c1e09 100644 --- a/packages/core/installer/images/talos/profiles/installer.yaml +++ b/packages/core/installer/images/talos/profiles/installer.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: installer imageOptions: {} diff --git a/packages/core/installer/images/talos/profiles/iso.yaml b/packages/core/installer/images/talos/profiles/iso.yaml index c10d43c6..5a416e99 100644 --- a/packages/core/installer/images/talos/profiles/iso.yaml +++ b/packages/core/installer/images/talos/profiles/iso.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: iso imageOptions: {} diff --git a/packages/core/installer/images/talos/profiles/kernel.yaml b/packages/core/installer/images/talos/profiles/kernel.yaml index 462aaaac..14f00f8b 100644 --- a/packages/core/installer/images/talos/profiles/kernel.yaml +++ b/packages/core/installer/images/talos/profiles/kernel.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: kernel imageOptions: {} diff --git a/packages/core/installer/images/talos/profiles/metal.yaml b/packages/core/installer/images/talos/profiles/metal.yaml index e3f5a8e9..e559318a 100644 --- a/packages/core/installer/images/talos/profiles/metal.yaml +++ b/packages/core/installer/images/talos/profiles/metal.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } diff --git a/packages/core/installer/images/talos/profiles/nocloud.yaml b/packages/core/installer/images/talos/profiles/nocloud.yaml index e781edc1..dab8ea38 100644 --- a/packages/core/installer/images/talos/profiles/nocloud.yaml +++ b/packages/core/installer/images/talos/profiles/nocloud.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: nocloud secureboot: false -version: v1.9.5 +version: v1.10.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: ghcr.io/siderolabs/installer:v1.9.5 + imageRef: ghcr.io/siderolabs/installer:v1.10.1 systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250311 + - imageRef: ghcr.io/siderolabs/amd-ucode:20250410 - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20241110 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250311 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250410 - imageRef: ghcr.io/siderolabs/i915-ucode:20241110 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250311 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250410 - imageRef: ghcr.io/siderolabs/intel-ucode:20250211 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250311 - - imageRef: ghcr.io/siderolabs/drbd:9.2.12-v1.9.5 - - imageRef: ghcr.io/siderolabs/zfs:2.2.7-v1.9.5 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250410 + - imageRef: ghcr.io/siderolabs/drbd:9.2.13-v1.10.1 + - imageRef: ghcr.io/siderolabs/zfs:2.3.1-v1.10.1 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } From ccbcaf633138a2adeef046dfe5789d6953024e38 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Fri, 9 May 2025 20:36:07 +0300 Subject: [PATCH 053/120] system/cozystack-controller: add multiarch options Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- .../images/cozystack-controller/Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile index c289c8d2..8933ffc0 100644 --- a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile +++ b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile @@ -1,4 +1,7 @@ -FROM golang:1.23-alpine as builder +FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder + +ARG TARGETOS +ARG TARGETARCH WORKDIR /workspace @@ -10,7 +13,7 @@ COPY pkg pkg/ COPY cmd cmd/ COPY internal internal/ -RUN CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /cozystack-controller cmd/cozystack-controller/main.go +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /cozystack-controller cmd/cozystack-controller/main.go FROM scratch From d0bd4b13297f8c2e22121609cc46f3e93a8098dd Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 17:42:08 +0300 Subject: [PATCH 054/120] system/bucket: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/bucket/Makefile | 7 ++++--- packages/system/bucket/images/s3manager/Dockerfile | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/system/bucket/Makefile b/packages/system/bucket/Makefile index 125e2e98..1f8d34b2 100644 --- a/packages/system/bucket/Makefile +++ b/packages/system/bucket/Makefile @@ -6,14 +6,15 @@ include ../../../scripts/common-envs.mk include ../../../scripts/package.mk update: - rm -rf charts - helm pull oci://ghcr.io/aenix-io/charts/etcd-operator --untar --untardir charts + @echo Nothing to update image: image-s3manager image-s3manager: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/s3manager \ + docker buildx build images/s3manager \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/s3manager:$(call settag,$(S3MANAGER_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/s3manager:latest \ --cache-to type=inline \ diff --git a/packages/system/bucket/images/s3manager/Dockerfile b/packages/system/bucket/images/s3manager/Dockerfile index de59229a..179acead 100644 --- a/packages/system/bucket/images/s3manager/Dockerfile +++ b/packages/system/bucket/images/s3manager/Dockerfile @@ -1,11 +1,15 @@ # Source: https://github.com/cloudlena/s3manager/blob/main/Dockerfile FROM docker.io/library/golang:1 AS builder + +ARG TARGETOS +ARG TARGETARCH + WORKDIR /usr/src/app RUN wget -O- https://github.com/cloudlena/s3manager/archive/9a7c8e446b422f8973b8c461990f39fdafee9c27.tar.gz | tar -xzf- --strip 1 ADD cozystack.patch / RUN git apply /cozystack.patch -RUN CGO_ENABLED=0 go build -ldflags="-s -w" -a -installsuffix cgo -o bin/s3manager +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-s -w" -a -installsuffix cgo -o bin/s3manager FROM docker.io/library/alpine:latest WORKDIR /usr/src/app From ac59b4540be2317dd27120a89582f67a30d2a613 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 17:42:54 +0300 Subject: [PATCH 055/120] system/bucket: add meaningful default to values.yaml Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/bucket/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/system/bucket/values.yaml b/packages/system/bucket/values.yaml index 4b57a59c..e1499c6e 100644 --- a/packages/system/bucket/values.yaml +++ b/packages/system/bucket/values.yaml @@ -1 +1 @@ -bucketName: "" +bucketName: "cozystack" From 1ca059406083a5de621019ef89410dc9a9461c77 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 17:44:32 +0300 Subject: [PATCH 056/120] system/cilium: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/cilium/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/system/cilium/Makefile b/packages/system/cilium/Makefile index e96d20ef..72502d12 100644 --- a/packages/system/cilium/Makefile +++ b/packages/system/cilium/Makefile @@ -18,6 +18,8 @@ update: image: docker buildx build images/cilium \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/cilium:$(call settag,$(CILIUM_TAG)) \ --tag $(REGISTRY)/cilium:$(call settag,$(CILIUM_TAG)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cilium:latest \ From f6e3188ab8653c34c197d6bcafe0138fd0651126 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 17:47:10 +0300 Subject: [PATCH 057/120] system/cozystack-api: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/cozystack-api/Makefile | 2 ++ .../system/cozystack-api/images/cozystack-api/Dockerfile | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/system/cozystack-api/Makefile b/packages/system/cozystack-api/Makefile index 053fe329..66853833 100644 --- a/packages/system/cozystack-api/Makefile +++ b/packages/system/cozystack-api/Makefile @@ -9,6 +9,8 @@ image: image-cozystack-api image-cozystack-api: docker buildx build -f images/cozystack-api/Dockerfile ../../.. \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/cozystack-api:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cozystack-api:latest \ --cache-to type=inline \ diff --git a/packages/system/cozystack-api/images/cozystack-api/Dockerfile b/packages/system/cozystack-api/images/cozystack-api/Dockerfile index 6b8e5cc1..c3f90f01 100644 --- a/packages/system/cozystack-api/images/cozystack-api/Dockerfile +++ b/packages/system/cozystack-api/images/cozystack-api/Dockerfile @@ -1,16 +1,19 @@ -FROM golang:1.23-alpine as builder +FROM golang:1.23-alpine AS builder + +ARG TARGETOS +ARG TARGETARCH WORKDIR /workspace COPY go.mod go.sum ./ -RUN go mod download +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download COPY api api/ COPY pkg pkg/ COPY cmd cmd/ COPY internal internal/ -RUN CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /cozystack-api cmd/cozystack-api/main.go +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /cozystack-api cmd/cozystack-api/main.go FROM scratch From 77e6db338162568eb788b40a2828c2fb0fc4378a Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 17:48:53 +0300 Subject: [PATCH 058/120] system/kamaji: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/kamaji/Makefile | 2 ++ packages/system/kamaji/images/kamaji/Dockerfile | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/system/kamaji/Makefile b/packages/system/kamaji/Makefile index 0956527d..aa864c1a 100644 --- a/packages/system/kamaji/Makefile +++ b/packages/system/kamaji/Makefile @@ -14,6 +14,8 @@ update: image: docker buildx build images/kamaji \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kamaji:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kamaji:latest \ --cache-to type=inline \ diff --git a/packages/system/kamaji/images/kamaji/Dockerfile b/packages/system/kamaji/images/kamaji/Dockerfile index 58007bd3..08fcd02e 100644 --- a/packages/system/kamaji/images/kamaji/Dockerfile +++ b/packages/system/kamaji/images/kamaji/Dockerfile @@ -1,8 +1,9 @@ # Build the manager binary -FROM golang:1.23 as builder +FROM golang:1.23 AS builder ARG VERSION=edge-25.3.2 -ARG TARGETOS TARGETARCH +ARG TARGETOS +ARG TARGETARCH WORKDIR /workspace @@ -11,7 +12,7 @@ RUN curl -sSL https://github.com/clastix/kamaji/archive/refs/tags/${VERSION}.tar COPY patches /patches RUN git apply /patches/*.diff -RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build \ +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build \ -ldflags "-X github.com/clastix/kamaji/internal.GitRepo=$GIT_REPO -X github.com/clastix/kamaji/internal.GitTag=$GIT_LAST_TAG -X github.com/clastix/kamaji/internal.GitCommit=$GIT_HEAD_COMMIT -X github.com/clastix/kamaji/internal.GitDirty=$GIT_MODIFIED -X github.com/clastix/kamaji/internal.BuildTime=$BUILD_DATE" \ -a -o kamaji main.go From 424aab4a834126c1adecdf7930eb683483e853a4 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 19:23:56 +0300 Subject: [PATCH 059/120] system/kubeovn: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/kubeovn/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/system/kubeovn/Makefile b/packages/system/kubeovn/Makefile index be01e9c5..62f0afae 100644 --- a/packages/system/kubeovn/Makefile +++ b/packages/system/kubeovn/Makefile @@ -19,6 +19,8 @@ update: image: docker buildx build images/kubeovn \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kubeovn:$(call settag,$(KUBEOVN_TAG)) \ --tag $(REGISTRY)/kubeovn:$(call settag,$(KUBEOVN_TAG)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kubeovn:latest \ From e81053f7ddae3808fa6fb8e90847f13745ffb702 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 19:24:53 +0300 Subject: [PATCH 060/120] system/dashboard: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/dashboard/Makefile | 7 ++++++- .../dashboard/images/kubeapps-apis/Dockerfile | 21 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/system/dashboard/Makefile b/packages/system/dashboard/Makefile index c0267da1..10df5382 100644 --- a/packages/system/dashboard/Makefile +++ b/packages/system/dashboard/Makefile @@ -17,7 +17,8 @@ update-chart: patch --no-backup-if-mismatch charts/kubeapps/templates/frontend/configmap.yaml < patches/logos.patch update-dockerfiles: - tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/vmware-tanzu/kubeapps | awk -F'[/^]' 'END{print $$3}') && \ + @echo Update dockerfiles manually + #tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/vmware-tanzu/kubeapps | awk -F'[/^]' 'END{print $$3}') && \ wget https://github.com/vmware-tanzu/kubeapps/raw/$${tag}/cmd/kubeapps-apis/Dockerfile -O images/kubeapps-apis/Dockerfile && \ patch --no-backup-if-mismatch images/kubeapps-apis/Dockerfile < images/kubeapps-apis/dockerfile.diff && \ node_image=$$(wget -O- https://github.com/vmware-tanzu/kubeapps/raw/main/dashboard/Dockerfile | awk '/FROM bitnami\/node/ {print $$2}') && \ @@ -28,6 +29,8 @@ update-dockerfiles: image-dashboard: update-version docker buildx build images/dashboard \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/dashboard:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/dashboard:latest \ --cache-to type=inline \ @@ -48,6 +51,8 @@ image-dashboard: update-version image-kubeapps-apis: update-version docker buildx build images/kubeapps-apis \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kubeapps-apis:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kubeapps-apis:latest \ --cache-to type=inline \ diff --git a/packages/system/dashboard/images/kubeapps-apis/Dockerfile b/packages/system/dashboard/images/kubeapps-apis/Dockerfile index 05add84b..4825fb41 100644 --- a/packages/system/dashboard/images/kubeapps-apis/Dockerfile +++ b/packages/system/dashboard/images/kubeapps-apis/Dockerfile @@ -3,7 +3,7 @@ # syntax = docker/dockerfile:1 -FROM alpine as source +FROM alpine AS source ARG COMMIT_REF=dd02680d796c962b8dcc4e5ea70960a846c1acdc RUN apk add --no-cache patch WORKDIR /source @@ -12,8 +12,9 @@ RUN wget -O- https://github.com/cozystack/kubeapps/archive/${COMMIT_REF}.tar.gz FROM bitnami/golang:1.23.4 AS builder WORKDIR /go/src/github.com/vmware-tanzu/kubeapps COPY --from=source /source/go.mod /source/go.sum ./ -ARG VERSION="devel" +ARG TARGETOS ARG TARGETARCH +ARG VERSION="devel" # If true, run golangci-lint to detect issues ARG lint @@ -29,10 +30,12 @@ ARG GRPC_HEALTH_PROBE_VERSION="0.4.34" # Install lint tools RUN if [ ! -z ${lint:-} ]; then \ - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$GOLANGCILINT_VERSION; \ + GOOS=$TARGETOS GOARCH=$TARGETARCH go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$GOLANGCILINT_VERSION; \ fi -RUN curl -sSL "https://github.com/bufbuild/buf/releases/download/v$BUF_VERSION/buf-Linux-x86_64" -o "/tmp/buf" && chmod +x "/tmp/buf" +RUN if [ $TARGETARCH = 'amd64' ]; then BUF_ARCH='x86_64'; elif [ $TARGETARCH = 'arm64' ]; then BUF_ARCH='aarch64'; fi && \ + if [ $TARGETOS = 'linux' ]; then BUF_PLATFORM='Linux'; fi && \ + curl -sSL "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/buf-${BUF_PLATFORM}-${BUF_ARCH}" -o "/tmp/buf" && chmod +x "/tmp/buf" # TODO: Remove and instead use built-in gRPC container probes once we're supporting >= 1.24 only. https://kubernetes.io/blog/2022/05/13/grpc-probes-now-in-beta/ RUN curl -sSL "https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-${TARGETARCH}" -o "/bin/grpc_health_probe" && chmod +x "/bin/grpc_health_probe" @@ -41,7 +44,7 @@ RUN curl -sSL "https://github.com/grpc-ecosystem/grpc-health-probe/releases/down # https://github.com/golang/go/issues/27719#issuecomment-514747274 RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - GOPROXY="https://proxy.golang.org,direct" go mod download + GOOS=$TARGETOS GOARCH=$TARGETARCH GOPROXY="https://proxy.golang.org,direct" go mod download # We don't copy the pkg and cmd directories until here so the above layers can # be reused. @@ -60,7 +63,7 @@ RUN /tmp/buf lint ./cmd/kubeapps-apis # Build the main grpc server RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - GOPROXY="https://proxy.golang.org,direct" \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GOPROXY="https://proxy.golang.org,direct" \ go build \ -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ ./cmd/kubeapps-apis @@ -68,7 +71,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \ ## Build 'fluxv2' plugin, version 'v1alpha1' RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - GOPROXY="https://proxy.golang.org,direct" \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GOPROXY="https://proxy.golang.org,direct" \ go build \ -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ -o /fluxv2-packages-v1alpha1-plugin.so -buildmode=plugin \ @@ -77,7 +80,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \ ## Build 'helm' plugin, version 'v1alpha1' RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - GOPROXY="https://proxy.golang.org,direct" \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GOPROXY="https://proxy.golang.org,direct" \ go build \ -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ -o /helm-packages-v1alpha1-plugin.so -buildmode=plugin \ @@ -86,7 +89,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \ ## Build 'resources' plugin, version 'v1alpha1' RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - GOPROXY="https://proxy.golang.org,direct" \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GOPROXY="https://proxy.golang.org,direct" \ go build \ -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ -o /resources-v1alpha1-plugin.so -buildmode=plugin \ From 58b5f6610d706ffdd860441312e0352c72daf52c Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 19:33:59 +0300 Subject: [PATCH 061/120] system/cozystack-controller: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- .../images/cozystack-controller/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile index 8933ffc0..b44d5ac8 100644 --- a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile +++ b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder +FROM golang:1.23-alpine AS builder ARG TARGETOS ARG TARGETARCH @@ -6,7 +6,7 @@ ARG TARGETARCH WORKDIR /workspace COPY go.mod go.sum ./ -RUN go mod download +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download COPY api api/ COPY pkg pkg/ From 7a7512da308eeb8559577bb9f901bebf04f29269 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sat, 10 May 2025 22:12:45 +0300 Subject: [PATCH 062/120] core/testing: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/core/testing/Makefile | 2 ++ .../testing/images/e2e-sandbox/Dockerfile | 24 ++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index 7b1eb049..b620c947 100755 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -17,6 +17,8 @@ image: image-e2e-sandbox image-e2e-sandbox: docker buildx build -f images/e2e-sandbox/Dockerfile ../../.. \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/e2e-sandbox:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/e2e-sandbox:latest \ --cache-to type=inline \ diff --git a/packages/core/testing/images/e2e-sandbox/Dockerfile b/packages/core/testing/images/e2e-sandbox/Dockerfile index 8318e982..3b25dfc6 100755 --- a/packages/core/testing/images/e2e-sandbox/Dockerfile +++ b/packages/core/testing/images/e2e-sandbox/Dockerfile @@ -4,14 +4,16 @@ ARG KUBECTL_VERSION=1.32.0 ARG TALOSCTL_VERSION=1.9.5 ARG HELM_VERSION=3.16.4 -RUN apt-get update -RUN apt-get -y install genisoimage qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git -RUN curl -LO "https://github.com/siderolabs/talos/releases/download/v${TALOSCTL_VERSION}/talosctl-linux-amd64" \ - && chmod +x talosctl-linux-amd64 \ - && mv talosctl-linux-amd64 /usr/local/bin/talosctl -RUN curl -LO "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl" \ - && chmod +x kubectl \ - && mv kubectl /usr/local/bin/kubectl -RUN curl -sSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash -s - --version "v${HELM_VERSION}" -RUN wget https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_amd64 -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq -RUN curl -s https://fluxcd.io/install.sh | bash +ARG TARGETOS +ARG TARGETARCH + +RUN apt update -q +RUN apt install -yq --no-install-recommends ca-certificates qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git +RUN curl -sSL "https://github.com/siderolabs/talos/releases/download/v${TALOSCTL_VERSION}/talosctl-${TARGETOS}-${TARGETARCH}" -o /usr/local/bin/talosctl \ + && chmod +x /usr/local/bin/talosctl +RUN curl -sSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" -o /usr/local/bin/kubectl \ + && chmod +x /usr/local/bin/kubectl +RUN curl -sSL "https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3" | bash -s - --version "v${HELM_VERSION}" +RUN curl -sSL "https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_${TARGETOS}_${TARGETARCH}" -o /usr/local/bin/yq \ + && chmod +x /usr/local/bin/yq +RUN curl -sSL "https://fluxcd.io/install.sh" | bash From e21c38c1036fb1f069f18feccc1c78370fc9c2f3 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sun, 11 May 2025 16:34:46 +0300 Subject: [PATCH 063/120] extra/monitoring: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/extra/monitoring/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/extra/monitoring/Makefile b/packages/extra/monitoring/Makefile index dd5b4386..912ea809 100644 --- a/packages/extra/monitoring/Makefile +++ b/packages/extra/monitoring/Makefile @@ -15,6 +15,8 @@ generate: image: docker buildx build --platform linux/amd64 images/grafana \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/grafana:$(call settag,$(GRAFANA_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/grafana:latest \ --cache-to type=inline \ From e6f3000b3c3f186ba88ca6116ea803985604785a Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sun, 11 May 2025 16:36:38 +0300 Subject: [PATCH 064/120] apps/postgres: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/postgres/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/apps/postgres/Makefile b/packages/apps/postgres/Makefile index 78639877..055329e4 100644 --- a/packages/apps/postgres/Makefile +++ b/packages/apps/postgres/Makefile @@ -9,6 +9,8 @@ generate: image: docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/postgres-backup \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/postgres-backup:$(call settag,$(POSTGRES_BACKUP_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/postgres-backup:latest \ --cache-to type=inline \ From 395cdc3af123b56becac06562a9376fc9f51871a Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sun, 11 May 2025 17:19:57 +0300 Subject: [PATCH 065/120] apps/http-cache: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/http-cache/Makefile | 4 ++- .../http-cache/images/nginx-cache/Dockerfile | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/apps/http-cache/Makefile b/packages/apps/http-cache/Makefile index 833a817d..c8270993 100644 --- a/packages/apps/http-cache/Makefile +++ b/packages/apps/http-cache/Makefile @@ -6,8 +6,10 @@ include ../../../scripts/package.mk image: image-nginx image-nginx: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/nginx-cache \ + docker buildx build images/nginx-cache \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/nginx-cache:$(call settag,$(NGINX_CACHE_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/nginx-cache:latest \ --cache-to type=inline \ diff --git a/packages/apps/http-cache/images/nginx-cache/Dockerfile b/packages/apps/http-cache/images/nginx-cache/Dockerfile index f121a3ab..2425acf7 100644 --- a/packages/apps/http-cache/images/nginx-cache/Dockerfile +++ b/packages/apps/http-cache/images/nginx-cache/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 as stage +FROM ubuntu:22.04 AS stage ARG NGINX_VERSION=1.25.3 ARG IP2LOCATION_C_VERSION=8.6.1 @@ -9,11 +9,15 @@ ARG FIFTYONEDEGREES_NGINX_VERSION=3.2.21.1 ARG NGINX_CACHE_PURGE_VERSION=2.5.3 ARG NGINX_VTS_VERSION=0.2.2 +ARG TARGETOS +ARG TARGETARCH + # Install required packages for development -RUN apt-get update -q \ - && apt-get install -yq \ +RUN apt update -q \ + && apt install -yq --no-install-recommends \ + ca-certificates \ unzip \ - autoconf \ + automake \ build-essential \ libtool \ libpcre3 \ @@ -68,7 +72,7 @@ RUN checkinstall \ --default \ --pkgname=ip2location-c \ --pkgversion=${IP2LOCATION_C_VERSION} \ - --pkgarch=amd64 \ + --pkgarch=${TARGETARCH} \ --pkggroup=lib \ --pkgsource="https://github.com/chrislim2888/IP2Location-C-Library" \ --maintainer="Eduard Generalov " \ @@ -97,7 +101,7 @@ RUN checkinstall \ --default \ --pkgname=ip2proxy-c \ --pkgversion=${IP2PROXY_C_VERSION} \ - --pkgarch=amd64 \ + --pkgarch=${TARGETARCH} \ --pkggroup=lib \ --pkgsource="https://github.com/ip2location/ip2proxy-c" \ --maintainer="Eduard Generalov " \ @@ -144,7 +148,7 @@ RUN checkinstall \ --default \ --pkgname=nginx \ --pkgversion=$VERS \ - --pkgarch=amd64 \ + --pkgarch=${TARGETARCH} \ --pkggroup=web \ --provides=nginx \ --requires=ip2location-c,ip2proxy-c,libssl3,libc-bin,libc6,libzstd1,libpcre++0v5,libpcre16-3,libpcre2-8-0,libpcre3,libpcre32-3,libpcrecpp0v5,libmaxminddb0 \ @@ -165,10 +169,9 @@ COPY nginx-reloader.sh /usr/bin/nginx-reloader.sh RUN set -x \ && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ - && apt update \ - && apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates inotify-tools \ - && apt -y install /packages/*.deb \ - && apt-get clean \ + && apt update -q \ + && apt install -yq --no-install-recommends --no-install-suggests gnupg1 ca-certificates inotify-tools \ + && apt install -y /packages/*.deb \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/lib/nginx /var/log/nginx \ && ln -sf /dev/stdout /var/log/nginx/access.log \ From 492aff5265c25dcb32af2cf9222d2848aa49a594 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sun, 11 May 2025 17:21:57 +0300 Subject: [PATCH 066/120] apps/clickhouse: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/clickhouse/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/apps/clickhouse/Makefile b/packages/apps/clickhouse/Makefile index 10460cb0..43b4c36c 100644 --- a/packages/apps/clickhouse/Makefile +++ b/packages/apps/clickhouse/Makefile @@ -9,6 +9,8 @@ generate: image: docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/clickhouse-backup \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/clickhouse-backup:$(call settag,$(CLICKHOUSE_BACKUP_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/clickhouse-backup:latest \ --cache-to type=inline \ From 4dd52290ea4dd0dea6d7238467f632f0f5dc1eee Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Sun, 11 May 2025 17:23:14 +0300 Subject: [PATCH 067/120] apps/mysql: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/mysql/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/apps/mysql/Makefile b/packages/apps/mysql/Makefile index d32df5dd..9241054f 100644 --- a/packages/apps/mysql/Makefile +++ b/packages/apps/mysql/Makefile @@ -9,6 +9,8 @@ generate: image: docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/mariadb-backup \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/mariadb-backup:$(call settag,$(MARIADB_BACKUP_TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/mariadb-backup:latest \ --cache-to type=inline \ From b00ba5317167b8d0383e970b1fbca49a57b062fd Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Mon, 12 May 2025 02:36:23 +0300 Subject: [PATCH 068/120] apps/clickhouse: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/clickhouse/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/clickhouse/Makefile b/packages/apps/clickhouse/Makefile index 43b4c36c..ae59ae22 100644 --- a/packages/apps/clickhouse/Makefile +++ b/packages/apps/clickhouse/Makefile @@ -7,7 +7,7 @@ generate: readme-generator -v values.yaml -s values.schema.json -r README.md image: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/clickhouse-backup \ + docker buildx build images/clickhouse-backup \ --provenance false \ --builder=$(BUILDER) \ --platform=$(PLATFORM) \ From 56fc08fab426996d4807142ad73a1d7b5688d87f Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Mon, 12 May 2025 02:36:39 +0300 Subject: [PATCH 069/120] apps/mysql: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/mysql/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/mysql/Makefile b/packages/apps/mysql/Makefile index 9241054f..8bc17337 100644 --- a/packages/apps/mysql/Makefile +++ b/packages/apps/mysql/Makefile @@ -7,7 +7,7 @@ generate: readme-generator -v values.yaml -s values.schema.json -r README.md image: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/mariadb-backup \ + docker buildx build images/mariadb-backup \ --provenance false \ --builder=$(BUILDER) \ --platform=$(PLATFORM) \ From 68fb7570f7d922a3b1a77b831e22206be6f52115 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Mon, 12 May 2025 02:37:28 +0300 Subject: [PATCH 070/120] apps/postgres: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/postgres/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/postgres/Makefile b/packages/apps/postgres/Makefile index 055329e4..c0a894c0 100644 --- a/packages/apps/postgres/Makefile +++ b/packages/apps/postgres/Makefile @@ -7,7 +7,7 @@ generate: readme-generator -v values.yaml -s values.schema.json -r README.md image: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/postgres-backup \ + docker buildx build images/postgres-backup \ --provenance false \ --builder=$(BUILDER) \ --platform=$(PLATFORM) \ From 4a2c67e0451a12126f7af0e7a875b24cbfdaf448 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Mon, 12 May 2025 02:38:13 +0300 Subject: [PATCH 071/120] apps/kubernetes: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/apps/kubernetes/Makefile | 16 ++++++++++---- .../images/cluster-autoscaler/Dockerfile | 13 +++++++++-- .../images/kubevirt-cloud-provider/Dockerfile | 9 ++++++-- .../images/kubevirt-csi-driver/Dockerfile | 5 +++++ .../images/ubuntu-container-disk/Dockerfile | 22 +++++++++++-------- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 45b97f69..10898e65 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -14,8 +14,10 @@ generate: image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt-csi-driver image-cluster-autoscaler image-ubuntu-container-disk: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/ubuntu-container-disk \ + docker buildx build images/ubuntu-container-disk \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --build-arg KUBERNETES_VERSION=${KUBERNETES_VERSION} \ --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)) \ --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)-$(TAG)) \ @@ -30,8 +32,10 @@ image-ubuntu-container-disk: rm -f images/ubuntu-container-disk.json image-kubevirt-cloud-provider: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/kubevirt-cloud-provider \ + docker buildx build images/kubevirt-cloud-provider \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kubevirt-cloud-provider:$(call settag,$(KUBERNETES_PKG_TAG)) \ --tag $(REGISTRY)/kubevirt-cloud-provider:$(call settag,$(KUBERNETES_PKG_TAG)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kubevirt-cloud-provider:latest \ @@ -45,8 +49,10 @@ image-kubevirt-cloud-provider: rm -f images/kubevirt-cloud-provider.json image-kubevirt-csi-driver: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/kubevirt-csi-driver \ + docker buildx build images/kubevirt-csi-driver \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kubevirt-csi-driver:$(call settag,$(KUBERNETES_PKG_TAG)) \ --tag $(REGISTRY)/kubevirt-csi-driver:$(call settag,$(KUBERNETES_PKG_TAG)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kubevirt-csi-driver:latest \ @@ -61,8 +67,10 @@ image-kubevirt-csi-driver: image-cluster-autoscaler: - docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/cluster-autoscaler \ + docker buildx build images/cluster-autoscaler \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/cluster-autoscaler:$(call settag,$(KUBERNETES_PKG_TAG)) \ --tag $(REGISTRY)/cluster-autoscaler:$(call settag,$(KUBERNETES_PKG_TAG)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cluster-autoscaler:latest \ diff --git a/packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile b/packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile index 17a5e501..7f9ff896 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile +++ b/packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile @@ -1,7 +1,14 @@ # Source: https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/cluster-autoscaler/Dockerfile.amd64 ARG builder_image=docker.io/library/golang:1.23.4 -ARG BASEIMAGE=gcr.io/distroless/static:nonroot-amd64 +ARG BASEIMAGE=gcr.io/distroless/static:nonroot-${TARGETARCH} + FROM ${builder_image} AS builder + +ARG TARGETOS +ARG TARGETARCH +ENV GOOS=$TARGETOS +ENV GOARCH=$TARGETARCH + RUN git clone https://github.com/kubernetes/autoscaler /src/autoscaler \ && cd /src/autoscaler/cluster-autoscaler \ && git checkout cluster-autoscaler-1.32.0 @@ -14,6 +21,8 @@ RUN make build FROM $BASEIMAGE LABEL maintainer="Marcin Wielgus " -COPY --from=builder /src/autoscaler/cluster-autoscaler/cluster-autoscaler-amd64 /cluster-autoscaler +ARG TARGETARCH + +COPY --from=builder /src/autoscaler/cluster-autoscaler/cluster-autoscaler-${TARGETARCH} /cluster-autoscaler WORKDIR / CMD ["/cluster-autoscaler"] diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider/Dockerfile b/packages/apps/kubernetes/images/kubevirt-cloud-provider/Dockerfile index 97760bd7..0e2c3a2f 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider/Dockerfile +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider/Dockerfile @@ -1,5 +1,10 @@ # Source: https://github.com/kubevirt/cloud-provider-kubevirt/blob/main/build/images/kubevirt-cloud-controller-manager/Dockerfile -FROM --platform=linux/amd64 golang:1.20.6 AS builder +FROM golang:1.20.6 AS builder + +ARG TARGETOS +ARG TARGETARCH +ENV GOOS=$TARGETOS +ENV GOARCH=$TARGETARCH RUN git clone https://github.com/kubevirt/cloud-provider-kubevirt /go/src/kubevirt.io/cloud-provider-kubevirt \ && cd /go/src/kubevirt.io/cloud-provider-kubevirt \ @@ -14,7 +19,7 @@ RUN go get 'k8s.io/endpointslice/util@v0.28' 'k8s.io/apiserver@v0.28' RUN go mod tidy RUN go mod vendor -RUN CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags="-s -w" -o bin/kubevirt-cloud-controller-manager ./cmd/kubevirt-cloud-controller-manager +RUN CGO_ENABLED=0 go build -mod=vendor -ldflags="-s -w" -o bin/kubevirt-cloud-controller-manager ./cmd/kubevirt-cloud-controller-manager FROM registry.access.redhat.com/ubi9/ubi-micro COPY --from=builder /go/src/kubevirt.io/cloud-provider-kubevirt/bin/kubevirt-cloud-controller-manager /bin/kubevirt-cloud-controller-manager diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile b/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile index b53c7b3d..27dda789 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile @@ -5,6 +5,11 @@ RUN git clone https://github.com/kubevirt/csi-driver /src/kubevirt-csi-driver \ && cd /src/kubevirt-csi-driver \ && git checkout 35836e0c8b68d9916d29a838ea60cdd3fc6199cf +ARG TARGETOS +ARG TARGETARCH +ENV GOOS=$TARGETOS +ENV GOARCH=$TARGETARCH + WORKDIR /src/kubevirt-csi-driver RUN make build diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile index 395adeb0..f5a7d54d 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile +++ b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile @@ -1,5 +1,5 @@ # TODO: Here we use ubuntu:22.04, as guestfish has some network issues running in ubuntu:24.04 -FROM ubuntu:22.04 as guestfish +FROM ubuntu:22.04 AS guestfish ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ @@ -8,15 +8,17 @@ RUN apt-get update \ linux-image-generic \ wget \ make \ - bash-completion \ - && apt-get clean + bash-completion WORKDIR /build -FROM guestfish as builder +FROM guestfish AS builder + +ARG TARGETOS +ARG TARGETARCH # noble is a code name for the Ubuntu 24.04 LTS release -RUN wget -O image.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null +RUN wget -O image.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-${TARGETARCH}.img --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null ARG KUBERNETES_VERSION @@ -29,19 +31,21 @@ RUN qemu-img resize image.img 5G \ && guestfish --remote command "resize2fs /dev/sda1" \ # docker repo && guestfish --remote sh "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg" \ - && guestfish --remote sh 'echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list' \ + && guestfish --remote sh 'echo "deb [signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list' \ # kubernetes repo && guestfish --remote sh "curl -fsSL https://pkgs.k8s.io/core:/stable:/${KUBERNETES_VERSION}/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg" \ && guestfish --remote sh "echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/${KUBERNETES_VERSION}/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list" \ + && guestfish --remote command "apt-get check -q" \ # install containerd - && guestfish --remote command "apt-get update -y" \ - && guestfish --remote command "apt-get install -y containerd.io" \ + && guestfish --remote command "apt-get update -q" \ + && guestfish --remote command "apt-get install -yq containerd.io" \ # configure containerd && guestfish --remote command "mkdir -p /etc/containerd" \ && guestfish --remote sh "containerd config default | tee /etc/containerd/config.toml" \ && guestfish --remote command "sed -i '/SystemdCgroup/ s/=.*/= true/' /etc/containerd/config.toml" \ + && guestfish --remote command "containerd config dump >/dev/null" \ # install kubernetes - && guestfish --remote command "apt-get install -y kubelet kubeadm" \ + && guestfish --remote command "apt-get install -yq kubelet kubeadm" \ # clean apt cache && guestfish --remote sh 'apt-get clean && rm -rf /var/lib/apt/lists/*' \ # write system configuration From 31ea5eeeb23c1e579cde1bc1ac189e90a3354530 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Mon, 12 May 2025 03:06:57 +0300 Subject: [PATCH 072/120] system/kubeovn-webhook: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/kubeovn-webhook/Makefile | 2 ++ .../kubeovn-webhook/images/kubeovn-webhook/Dockerfile | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/system/kubeovn-webhook/Makefile b/packages/system/kubeovn-webhook/Makefile index 2605ca5e..76bf5f5a 100644 --- a/packages/system/kubeovn-webhook/Makefile +++ b/packages/system/kubeovn-webhook/Makefile @@ -7,6 +7,8 @@ include ../../../scripts/package.mk image: docker buildx build images/kubeovn-webhook \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --tag $(REGISTRY)/kubeovn-webhook:$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/kubeovn-webhook:latest \ --cache-to type=inline \ diff --git a/packages/system/kubeovn-webhook/images/kubeovn-webhook/Dockerfile b/packages/system/kubeovn-webhook/images/kubeovn-webhook/Dockerfile index 337e72e4..73d5e99b 100644 --- a/packages/system/kubeovn-webhook/images/kubeovn-webhook/Dockerfile +++ b/packages/system/kubeovn-webhook/images/kubeovn-webhook/Dockerfile @@ -1,11 +1,14 @@ -FROM golang:1.23 as builder +FROM golang:1.23 AS builder + +ARG TARGETOS +ARG TARGETARCH WORKDIR /app COPY go.mod go.sum ./ -RUN go mod download +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -o webhook . +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o webhook . FROM alpine:3.21.3 WORKDIR /app From db34f31175812b79282fc9bada3185194ec70837 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Mon, 12 May 2025 14:29:11 +0300 Subject: [PATCH 073/120] Don't overcommit memory or throttle CPU This patch recreates the resource presets with a non-burstable memory allocation (request==limit) and without CPU limits. With the new presets the difference between the larger presets became meaningless, so their values were adjusted. Signed-off-by: Timofei Larkin --- .pre-commit-config.yaml | 1 + packages/apps/clickhouse/Chart.yaml | 2 +- .../apps/clickhouse/templates/_resources.tpl | 23 +++++++------ packages/apps/ferretdb/Chart.yaml | 2 +- .../apps/ferretdb/templates/_resources.tpl | 23 +++++++------ packages/apps/http-cache/Chart.yaml | 2 +- .../apps/http-cache/templates/_resources.tpl | 23 +++++++------ packages/apps/kafka/Chart.yaml | 2 +- packages/apps/kafka/templates/_resources.tpl | 23 +++++++------ .../apps/kubernetes/templates/_resources.tpl | 23 +++++++------ packages/apps/mysql/Chart.yaml | 2 +- packages/apps/mysql/templates/_resources.tpl | 23 +++++++------ packages/apps/nats/Chart.yaml | 2 +- packages/apps/nats/templates/_resources.tpl | 23 +++++++------ packages/apps/postgres/Chart.yaml | 2 +- .../apps/postgres/templates/_resources.tpl | 23 +++++++------ packages/apps/rabbitmq/Chart.yaml | 2 +- .../apps/rabbitmq/templates/_resources.tpl | 23 +++++++------ packages/apps/redis/Chart.yaml | 2 +- packages/apps/redis/templates/_resources.tpl | 23 +++++++------ packages/apps/tcp-balancer/Chart.yaml | 2 +- .../tcp-balancer/templates/_resources.tpl | 23 +++++++------ packages/apps/versions_map | 33 ++++++++++++------- packages/apps/vpn/Chart.yaml | 2 +- packages/apps/vpn/templates/_resources.tpl | 23 +++++++------ packages/system/dashboard/values.yaml | 9 +++++ 26 files changed, 175 insertions(+), 166 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d05ad6f..9f94db8e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,7 @@ repos: (cd "$dir" && make generate) fi done + git diff --color=always | cat ' language: script files: ^.*$ diff --git a/packages/apps/clickhouse/Chart.yaml b/packages/apps/clickhouse/Chart.yaml index 0466800b..935cf6af 100644 --- a/packages/apps/clickhouse/Chart.yaml +++ b/packages/apps/clickhouse/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.7.0 +version: 0.8.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/clickhouse/templates/_resources.tpl b/packages/apps/clickhouse/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/clickhouse/templates/_resources.tpl +++ b/packages/apps/clickhouse/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/ferretdb/Chart.yaml b/packages/apps/ferretdb/Chart.yaml index fa41dcbd..273d9d97 100644 --- a/packages/apps/ferretdb/Chart.yaml +++ b/packages/apps/ferretdb/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.0 +version: 0.6.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/ferretdb/templates/_resources.tpl b/packages/apps/ferretdb/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/ferretdb/templates/_resources.tpl +++ b/packages/apps/ferretdb/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/http-cache/Chart.yaml b/packages/apps/http-cache/Chart.yaml index 2224053c..151b3b42 100644 --- a/packages/apps/http-cache/Chart.yaml +++ b/packages/apps/http-cache/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.4.0 +version: 0.5.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/http-cache/templates/_resources.tpl b/packages/apps/http-cache/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/http-cache/templates/_resources.tpl +++ b/packages/apps/http-cache/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/kafka/Chart.yaml b/packages/apps/kafka/Chart.yaml index d4e910d4..00213f83 100644 --- a/packages/apps/kafka/Chart.yaml +++ b/packages/apps/kafka/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.0 +version: 0.6.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/kafka/templates/_resources.tpl b/packages/apps/kafka/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/kafka/templates/_resources.tpl +++ b/packages/apps/kafka/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/kubernetes/templates/_resources.tpl b/packages/apps/kubernetes/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/kubernetes/templates/_resources.tpl +++ b/packages/apps/kubernetes/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/mysql/Chart.yaml b/packages/apps/mysql/Chart.yaml index d8d04d0c..f9dcb7c6 100644 --- a/packages/apps/mysql/Chart.yaml +++ b/packages/apps/mysql/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.7.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/mysql/templates/_resources.tpl b/packages/apps/mysql/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/mysql/templates/_resources.tpl +++ b/packages/apps/mysql/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/nats/Chart.yaml b/packages/apps/nats/Chart.yaml index 2bae5c73..38f429fb 100644 --- a/packages/apps/nats/Chart.yaml +++ b/packages/apps/nats/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.0 +version: 0.6.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/nats/templates/_resources.tpl b/packages/apps/nats/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/nats/templates/_resources.tpl +++ b/packages/apps/nats/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/postgres/Chart.yaml b/packages/apps/postgres/Chart.yaml index 36842881..7c262043 100644 --- a/packages/apps/postgres/Chart.yaml +++ b/packages/apps/postgres/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.10.1 +version: 0.11.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/postgres/templates/_resources.tpl b/packages/apps/postgres/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/postgres/templates/_resources.tpl +++ b/packages/apps/postgres/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/rabbitmq/Chart.yaml b/packages/apps/rabbitmq/Chart.yaml index 2218642f..3aa54260 100644 --- a/packages/apps/rabbitmq/Chart.yaml +++ b/packages/apps/rabbitmq/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.0 +version: 0.6.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/rabbitmq/templates/_resources.tpl b/packages/apps/rabbitmq/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/rabbitmq/templates/_resources.tpl +++ b/packages/apps/rabbitmq/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/redis/Chart.yaml b/packages/apps/redis/Chart.yaml index 07556e67..2a07e2c0 100644 --- a/packages/apps/redis/Chart.yaml +++ b/packages/apps/redis/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.7.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/redis/templates/_resources.tpl b/packages/apps/redis/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/redis/templates/_resources.tpl +++ b/packages/apps/redis/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/tcp-balancer/Chart.yaml b/packages/apps/tcp-balancer/Chart.yaml index 9d701dcd..5955c5be 100644 --- a/packages/apps/tcp-balancer/Chart.yaml +++ b/packages/apps/tcp-balancer/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.0 +version: 0.4.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/tcp-balancer/templates/_resources.tpl b/packages/apps/tcp-balancer/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/tcp-balancer/templates/_resources.tpl +++ b/packages/apps/tcp-balancer/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/apps/versions_map b/packages/apps/versions_map index b7c09ab7..89d9990d 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -8,7 +8,8 @@ clickhouse 0.5.0 0f312d5c clickhouse 0.6.0 1ec10165 clickhouse 0.6.1 c62a83a7 clickhouse 0.6.2 8267072d -clickhouse 0.7.0 HEAD +clickhouse 0.7.0 93bdf411 +clickhouse 0.8.0 HEAD ferretdb 0.1.0 e9716091 ferretdb 0.1.1 91b0499a ferretdb 0.2.0 6c5cf5bf @@ -16,12 +17,14 @@ ferretdb 0.3.0 b8e33d19 ferretdb 0.4.0 b40e1b09 ferretdb 0.4.1 1ec10165 ferretdb 0.4.2 8267072d -ferretdb 0.5.0 HEAD +ferretdb 0.5.0 93bdf411 +ferretdb 0.6.0 HEAD http-cache 0.1.0 263e47be http-cache 0.2.0 53f2365e http-cache 0.3.0 6c5cf5bf http-cache 0.3.1 0f312d5c -http-cache 0.4.0 HEAD +http-cache 0.4.0 93bdf411 +http-cache 0.5.0 HEAD kafka 0.1.0 f7eaab0a kafka 0.2.0 c0685f43 kafka 0.2.1 dfbc210b @@ -32,7 +35,8 @@ kafka 0.3.1 c62a83a7 kafka 0.3.2 93c46161 kafka 0.3.3 8267072d kafka 0.4.0 85ec09b8 -kafka 0.5.0 HEAD +kafka 0.5.0 93bdf411 +kafka 0.6.0 HEAD kubernetes 0.1.0 263e47be kubernetes 0.2.0 53f2365e kubernetes 0.3.0 007d414f @@ -69,14 +73,16 @@ mysql 0.5.0 b40e1b09 mysql 0.5.1 0f312d5c mysql 0.5.2 1ec10165 mysql 0.5.3 8267072d -mysql 0.6.0 HEAD +mysql 0.6.0 93bdf411 +mysql 0.7.0 HEAD nats 0.1.0 e9716091 nats 0.2.0 6c5cf5bf nats 0.3.0 78366f19 nats 0.3.1 c62a83a7 nats 0.4.0 898374b5 nats 0.4.1 8267072d -nats 0.5.0 HEAD +nats 0.5.0 93bdf411 +nats 0.6.0 HEAD postgres 0.1.0 263e47be postgres 0.2.0 53f2365e postgres 0.2.1 d7cfa53c @@ -91,7 +97,8 @@ postgres 0.7.1 1ec10165 postgres 0.8.0 4e68e65c postgres 0.9.0 8267072d postgres 0.10.0 721c12a7 -postgres 0.10.1 HEAD +postgres 0.10.1 93bdf411 +postgres 0.11.0 HEAD rabbitmq 0.1.0 263e47be rabbitmq 0.2.0 53f2365e rabbitmq 0.3.0 6c5cf5bf @@ -100,17 +107,20 @@ rabbitmq 0.4.1 1128d0cb rabbitmq 0.4.2 4b90bf5a rabbitmq 0.4.3 1ec10165 rabbitmq 0.4.4 8267072d -rabbitmq 0.5.0 HEAD +rabbitmq 0.5.0 93bdf411 +rabbitmq 0.6.0 HEAD redis 0.1.1 263e47be redis 0.2.0 53f2365e redis 0.3.0 6c5cf5bf redis 0.3.1 c62a83a7 redis 0.4.0 84f3ccc0 redis 0.5.0 4e68e65c -redis 0.6.0 HEAD +redis 0.6.0 93bdf411 +redis 0.7.0 HEAD tcp-balancer 0.1.0 263e47be tcp-balancer 0.2.0 53f2365e -tcp-balancer 0.3.0 HEAD +tcp-balancer 0.3.0 93bdf411 +tcp-balancer 0.4.0 HEAD tenant 0.1.4 afc997ef tenant 0.1.5 e3ab858a tenant 1.0.0 263e47be @@ -163,4 +173,5 @@ vpn 0.1.0 263e47be vpn 0.2.0 53f2365e vpn 0.3.0 6c5cf5bf vpn 0.3.1 1ec10165 -vpn 0.4.0 HEAD +vpn 0.4.0 93bdf411 +vpn 0.5.0 HEAD diff --git a/packages/apps/vpn/Chart.yaml b/packages/apps/vpn/Chart.yaml index c82e77dd..4382233a 100644 --- a/packages/apps/vpn/Chart.yaml +++ b/packages/apps/vpn/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.4.0 +version: 0.5.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/vpn/templates/_resources.tpl b/packages/apps/vpn/templates/_resources.tpl index 7ada56d4..6539c99a 100644 --- a/packages/apps/vpn/templates/_resources.tpl +++ b/packages/apps/vpn/templates/_resources.tpl @@ -11,35 +11,34 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} {{- $presets := dict "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) "medium" (dict - "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) "large" (dict - "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) "xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) "2xlarge" (dict - "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") - "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) }} {{- if hasKey $presets .type -}} diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index 3038124f..a7103fc4 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -21,6 +21,15 @@ kubeapps: repository: dashboard tag: v0.31.0-rc.1 digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93" + redis: + master: + resourcesPreset: "none" + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + memory: 256Mi kubeappsapis: resourcesPreset: "none" image: From fd72d7c4862315737a6187490884d5d9c9a96aa4 Mon Sep 17 00:00:00 2001 From: Kingdon B Date: Mon, 12 May 2025 10:15:58 -0400 Subject: [PATCH 074/120] Flux Operator 0.20.0 Signed-off-by: Kingdon B --- .../system/fluxcd-operator/charts/flux-operator/Chart.yaml | 4 ++-- .../system/fluxcd-operator/charts/flux-operator/README.md | 2 +- packages/system/fluxcd/charts/flux-instance/Chart.yaml | 4 ++-- packages/system/fluxcd/charts/flux-instance/README.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml b/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml index 95ce6ee5..43caa7d9 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml +++ b/packages/system/fluxcd-operator/charts/flux-operator/Chart.yaml @@ -8,7 +8,7 @@ annotations: - name: Upstream Project url: https://github.com/controlplaneio-fluxcd/flux-operator apiVersion: v2 -appVersion: v0.19.0 +appVersion: v0.20.0 description: 'A Helm chart for deploying the Flux Operator. ' home: https://github.com/controlplaneio-fluxcd icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png @@ -25,4 +25,4 @@ sources: - https://github.com/controlplaneio-fluxcd/flux-operator - https://github.com/controlplaneio-fluxcd/charts type: application -version: 0.19.0 +version: 0.20.0 diff --git a/packages/system/fluxcd-operator/charts/flux-operator/README.md b/packages/system/fluxcd-operator/charts/flux-operator/README.md index 627a81ab..7cbbd492 100644 --- a/packages/system/fluxcd-operator/charts/flux-operator/README.md +++ b/packages/system/fluxcd-operator/charts/flux-operator/README.md @@ -1,6 +1,6 @@ # flux-operator -![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.20.0](https://img.shields.io/badge/AppVersion-v0.20.0-informational?style=flat-square) The [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator) provides a declarative API for the installation and upgrade of CNCF [Flux](https://fluxcd.io) and the diff --git a/packages/system/fluxcd/charts/flux-instance/Chart.yaml b/packages/system/fluxcd/charts/flux-instance/Chart.yaml index be942dd5..12d1d3b4 100644 --- a/packages/system/fluxcd/charts/flux-instance/Chart.yaml +++ b/packages/system/fluxcd/charts/flux-instance/Chart.yaml @@ -8,7 +8,7 @@ annotations: - name: Upstream Project url: https://github.com/controlplaneio-fluxcd/flux-operator apiVersion: v2 -appVersion: v0.19.0 +appVersion: v0.20.0 description: 'A Helm chart for deploying a Flux instance managed by Flux Operator. ' home: https://github.com/controlplaneio-fluxcd icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png @@ -25,4 +25,4 @@ sources: - https://github.com/controlplaneio-fluxcd/flux-operator - https://github.com/controlplaneio-fluxcd/charts type: application -version: 0.19.0 +version: 0.20.0 diff --git a/packages/system/fluxcd/charts/flux-instance/README.md b/packages/system/fluxcd/charts/flux-instance/README.md index ccd29096..b39c70fc 100644 --- a/packages/system/fluxcd/charts/flux-instance/README.md +++ b/packages/system/fluxcd/charts/flux-instance/README.md @@ -1,6 +1,6 @@ # flux-instance -![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.20.0](https://img.shields.io/badge/AppVersion-v0.20.0-informational?style=flat-square) This chart is a thin wrapper around the `FluxInstance` custom resource, which is used by the [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator) From d002879b0b0bf57cfbfe0b9ca773a8bed6e80859 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Wed, 14 May 2025 15:16:14 +0300 Subject: [PATCH 075/120] Downgrade CAPI operator Signed-off-by: Timofei Larkin --- packages/system/capi-operator/Makefile | 12 +- .../charts/cluster-api-operator/Chart.yaml | 4 +- .../cluster-api-operator/templates/addon.yaml | 45 ++-- .../templates/bootstrap.yaml | 45 ++-- .../templates/control-plane.yaml | 45 ++-- .../cluster-api-operator/templates/core.yaml | 45 ++-- .../cluster-api-operator/templates/infra.yaml | 47 ++-- .../cluster-api-operator/templates/ipam.yaml | 45 ++-- .../templates/operator-components.yaml | 241 +++--------------- .../cluster-api-operator/values.schema.json | 47 ---- .../charts/cluster-api-operator/values.yaml | 32 +-- scripts/package.mk | 8 + 12 files changed, 188 insertions(+), 428 deletions(-) delete mode 100644 packages/system/capi-operator/charts/cluster-api-operator/values.schema.json diff --git a/packages/system/capi-operator/Makefile b/packages/system/capi-operator/Makefile index baa4a5fc..20c083aa 100644 --- a/packages/system/capi-operator/Makefile +++ b/packages/system/capi-operator/Makefile @@ -1,11 +1,11 @@ export NAME=capi-operator export NAMESPACE=cozy-cluster-api +export REPO_NAME=capi-operator +export REPO_URL=https://kubernetes-sigs.github.io/cluster-api-operator +export CHART_NAME=cluster-api-operator +export CHART_VERSION=^0.18 include ../../../scripts/package.mk -update: - rm -rf charts - helm repo add capi-operator https://kubernetes-sigs.github.io/cluster-api-operator - helm repo update capi-operator - helm pull capi-operator/cluster-api-operator --untar --untardir charts - rm -rf charts/cluster-api-operator/charts +update: clean capi-operator-update + rm -rf charts/cluster-api-operator/charts/ diff --git a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml index 323a3594..5108c7dc 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: 0.19.0 +appVersion: 0.18.1 description: Cluster API Operator name: cluster-api-operator type: application -version: 0.19.0 +version: 0.18.1 diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml index 6a341496..a2eb8fb9 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml @@ -1,8 +1,26 @@ # Addon provider -{{- range $name, $addon := $.Values.addon }} - {{- $addonNamespace := default ( printf "%s-%s" $name "addon-system" ) (get $addon "namespace") }} - {{- $addonName := $name }} - {{- $addonVersion := get $addon "version" }} +{{- if .Values.addon }} +{{- $addons := split ";" .Values.addon }} +{{- $addonNamespace := "" }} +{{- $addonName := "" }} +{{- $addonVersion := "" }} +{{- range $addon := $addons }} +{{- $addonArgs := split ":" $addon }} +{{- $addonArgsLen := len $addonArgs }} +{{- if eq $addonArgsLen 3 }} + {{- $addonNamespace = $addonArgs._0 }} + {{- $addonName = $addonArgs._1 }} + {{- $addonVersion = $addonArgs._2 }} +{{- else if eq $addonArgsLen 2 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} + {{- $addonVersion = $addonArgs._1 }} +{{- else if eq $addonArgsLen 1 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} +{{- else }} + {{- fail "addon provider argument should have the following format helm:v1.0.0 or mynamespace:helm:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -38,24 +56,5 @@ spec: {{- if $.Values.secretNamespace }} secretNamespace: {{ $.Values.secretNamespace }} {{- end }} -{{- if $addon.manifestPatches }} - manifestPatches: {{ toYaml $addon.manifestPatches | nindent 4 }} {{- end }} -{{- if $addon.additionalManifests }} - additionalManifests: - name: {{ $addon.additionalManifests.name }} - {{- if $addon.additionalManifests.namespace }} - namespace: {{ $addon.additionalManifests.namespace }} - {{- end }} {{/* if $addon.additionalManifests.namespace */}} {{- end }} -{{- if $addon.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $addon.additionalManifests.name }} - namespace: {{ default $addonNamespace $addon.additionalManifests.namespace }} -data: - manifests: {{- toYaml $addon.additionalManifests.manifests | nindent 4 }} -{{- end }} -{{- end }} {{/* range $name, $addon := .Values.addon */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml index 78dad47e..ed5d7924 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml @@ -1,8 +1,26 @@ # Bootstrap provider -{{- range $name, $bootstrap := $.Values.bootstrap }} - {{- $bootstrapNamespace := default ( printf "%s-%s" $name "bootstrap-system" ) (get $bootstrap "namespace") }} - {{- $bootstrapName := $name }} - {{- $bootstrapVersion := get $bootstrap "version" }} +{{- if .Values.bootstrap }} +{{- $bootstraps := split ";" .Values.bootstrap }} +{{- $bootstrapNamespace := "" }} +{{- $bootstrapName := "" }} +{{- $bootstrapVersion := "" }} +{{- range $bootstrap := $bootstraps }} +{{- $bootstrapArgs := split ":" $bootstrap }} +{{- $bootstrapArgsLen := len $bootstrapArgs }} +{{- if eq $bootstrapArgsLen 3 }} + {{- $bootstrapNamespace = $bootstrapArgs._0 }} + {{- $bootstrapName = $bootstrapArgs._1 }} + {{- $bootstrapVersion = $bootstrapArgs._2 }} +{{- else if eq $bootstrapArgsLen 2 }} + {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} + {{- $bootstrapName = $bootstrapArgs._0 }} + {{- $bootstrapVersion = $bootstrapArgs._1 }} +{{- else if eq $bootstrapArgsLen 1 }} + {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} + {{- $bootstrapName = $bootstrapArgs._0 }} +{{- else }} + {{- fail "bootstrap provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -39,24 +57,5 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} -{{- if $bootstrap.manifestPatches }} - manifestPatches: {{ toYaml $bootstrap.manifestPatches | nindent 4 }} {{- end }} -{{- if $bootstrap.additionalManifests }} - additionalManifests: - name: {{ $bootstrap.additionalManifests.name }} - {{- if $bootstrap.additionalManifests.namespace }} - namespace: {{ $bootstrap.additionalManifests.namespace }} - {{- end }} {{/* if $bootstrap.additionalManifests.namespace */}} {{- end }} -{{- if $bootstrap.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $bootstrap.additionalManifests.name }} - namespace: {{ default $bootstrapNamespace $bootstrap.additionalManifests.namespace }} -data: - manifests: {{- toYaml $bootstrap.additionalManifests.manifests | nindent 4 }} -{{- end }} -{{- end }} {{/* range $name, $bootstrap := .Values.bootstrap */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml index 8a020afd..d72249d1 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml @@ -1,8 +1,26 @@ # Control plane provider -{{- range $name, $controlPlane := $.Values.controlPlane }} - {{- $controlPlaneNamespace := default ( printf "%s-%s" $name "control-plane-system" ) (get $controlPlane "namespace") }} - {{- $controlPlaneName := $name }} - {{- $controlPlaneVersion := get $controlPlane "version" }} +{{- if .Values.controlPlane }} +{{- $controlPlanes := split ";" .Values.controlPlane }} +{{- $controlPlaneNamespace := "" }} +{{- $controlPlaneName := "" }} +{{- $controlPlaneVersion := "" }} +{{- range $controlPlane := $controlPlanes }} +{{- $controlPlaneArgs := split ":" $controlPlane }} +{{- $controlPlaneArgsLen := len $controlPlaneArgs }} +{{- if eq $controlPlaneArgsLen 3 }} + {{- $controlPlaneNamespace = $controlPlaneArgs._0 }} + {{- $controlPlaneName = $controlPlaneArgs._1 }} + {{- $controlPlaneVersion = $controlPlaneArgs._2 }} +{{- else if eq $controlPlaneArgsLen 2 }} + {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} + {{- $controlPlaneName = $controlPlaneArgs._0 }} + {{- $controlPlaneVersion = $controlPlaneArgs._1 }} +{{- else if eq $controlPlaneArgsLen 1 }} + {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} + {{- $controlPlaneName = $controlPlaneArgs._0 }} +{{- else }} + {{- fail "controlplane provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -52,24 +70,5 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} -{{- if $controlPlane.manifestPatches }} - manifestPatches: {{ toYaml $controlPlane.manifestPatches | nindent 4 }} {{- end }} -{{- if $controlPlane.additionalManifests }} - additionalManifests: - name: {{ $controlPlane.additionalManifests.name }} - {{- if $controlPlane.additionalManifests.namespace }} - namespace: {{ $controlPlane.additionalManifests.namespace }} - {{- end }} {{/* if $controlPlane.additionalManifests.namespace */}} {{- end }} -{{- if $controlPlane.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $controlPlane.additionalManifests.name }} - namespace: {{ default $controlPlaneNamespace $controlPlane.additionalManifests.namespace }} -data: - manifests: {{- toYaml $controlPlane.additionalManifests.manifests | nindent 4 }} -{{- end }} -{{- end }} {{/* range $name, $controlPlane := .Values.controlPlane */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml index 648e1b60..828d2269 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml @@ -1,8 +1,25 @@ # Core provider -{{- range $name, $core := $.Values.core }} - {{- $coreNamespace := default "capi-system" (get $core "namespace") }} - {{- $coreName := $name }} - {{- $coreVersion := get $core "version" }} +{{- if .Values.core }} +{{- $coreArgs := split ":" .Values.core }} +{{- $coreArgsLen := len $coreArgs }} +{{- $coreVersion := "" }} +{{- $coreNamespace := "" }} +{{- $coreName := "" }} +{{- $coreVersion := "" }} +{{- if eq $coreArgsLen 3 }} + {{- $coreNamespace = $coreArgs._0 }} + {{- $coreName = $coreArgs._1 }} + {{- $coreVersion = $coreArgs._2 }} +{{- else if eq $coreArgsLen 2 }} + {{- $coreNamespace = "capi-system" }} + {{- $coreName = $coreArgs._0 }} + {{- $coreVersion = $coreArgs._1 }} +{{- else if eq $coreArgsLen 1 }} + {{- $coreNamespace = "capi-system" }} + {{- $coreName = $coreArgs._0 }} +{{- else }} + {{- fail "core provider argument should have the following format cluster-api:v1.0.0 or mynamespace:cluster-api:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -48,24 +65,4 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} -{{- if $core.manifestPatches }} - manifestPatches: {{ toYaml $core.manifestPatches | nindent 4 }} {{- end }} -{{- if $core.additionalManifests }} - additionalManifests: - name: {{ $core.additionalManifests.name }} - {{- if $core.additionalManifests.namespace }} - namespace: {{ $core.additionalManifests.namespace }} - {{- end }} -{{- end }} -{{- if $core.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $core.additionalManifests.name }} - namespace: {{ default $coreNamespace $core.additionalManifests.namespace }} -data: - manifests: {{- toYaml $core.additionalManifests.manifests | nindent 4 }} -{{- end }} -{{- end }} {{/* range $name, $core := .Values.core */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml index 835607d4..5841336c 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml @@ -1,8 +1,26 @@ # Infrastructure providers -{{- range $name, $infra := $.Values.infrastructure }} - {{- $infrastructureNamespace := default ( printf "%s-%s" $name "infrastructure-system" ) (get $infra "namespace") }} - {{- $infrastructureName := $name }} - {{- $infrastructureVersion := get $infra "version" }} +{{- if .Values.infrastructure }} +{{- $infrastructures := split ";" .Values.infrastructure }} +{{- $infrastructureNamespace := "" }} +{{- $infrastructureName := "" }} +{{- $infrastructureVersion := "" }} +{{- range $infrastructure := $infrastructures }} +{{- $infrastructureArgs := split ":" $infrastructure }} +{{- $infrastructureArgsLen := len $infrastructureArgs }} +{{- if eq $infrastructureArgsLen 3 }} + {{- $infrastructureNamespace = $infrastructureArgs._0 }} + {{- $infrastructureName = $infrastructureArgs._1 }} + {{- $infrastructureVersion = $infrastructureArgs._2 }} +{{- else if eq $infrastructureArgsLen 2 }} + {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} + {{- $infrastructureName = $infrastructureArgs._0 }} + {{- $infrastructureVersion = $infrastructureArgs._1 }} +{{- else if eq $infrastructureArgsLen 1 }} + {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} + {{- $infrastructureName = $infrastructureArgs._0 }} +{{- else }} + {{- fail "infrastructure provider argument should have the following format aws:v1.0.0 or mynamespace:aws:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -65,24 +83,5 @@ spec: {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} -{{- if $infra.manifestPatches }} - manifestPatches: {{- toYaml $infra.manifestPatches | nindent 4 }} -{{- end }} {{/* if $infra.manifestPatches */}} -{{- if $infra.additionalManifests }} - additionalManifests: - name: {{ $infra.additionalManifests.name }} - {{- if $infra.additionalManifests.namespace }} - namespace: {{ $infra.additionalManifests.namespace }} - {{- end }} {{/* if $infra.additionalManifests.namespace */}} -{{- end }} {{/* if $infra.additionalManifests */}} -{{- if $infra.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $infra.additionalManifests.name }} - namespace: {{ default $infrastructureNamespace $infra.additionalManifests.namespace }} -data: - manifests: {{- toYaml $infra.additionalManifests.manifests | nindent 4 }} {{- end }} -{{- end }} {{/* range $name, $infra := .Values.infrastructure */}} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml index 4a33c42f..06960afb 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml @@ -1,8 +1,26 @@ # IPAM providers -{{- range $name, $ipam := $.Values.ipam }} - {{- $ipamNamespace := default ( printf "%s-%s" $name "ipam-system" ) (get $ipam "namespace") }} - {{- $ipamName := $name }} - {{- $ipamVersion := get $ipam "version" }} +{{- if .Values.ipam }} +{{- $ipams := split ";" .Values.ipam }} +{{- $ipamNamespace := "" }} +{{- $ipamName := "" }} +{{- $ipamVersion := "" }} +{{- range $ipam := $ipams }} +{{- $ipamArgs := split ":" $ipam }} +{{- $ipamArgsLen := len $ipamArgs }} +{{- if eq $ipamArgsLen 3 }} + {{- $ipamNamespace = $ipamArgs._0 }} + {{- $ipamName = $ipamArgs._1 }} + {{- $ipamVersion = $ipamArgs._2 }} +{{- else if eq $ipamArgsLen 2 }} + {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} + {{- $ipamName = $ipamArgs._0 }} + {{- $ipamVersion = $ipamArgs._1 }} +{{- else if eq $ipamArgsLen 1 }} + {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} + {{- $ipamName = $ipamArgs._0 }} +{{- else }} + {{- fail "ipam provider argument should have the following format in-cluster:v1.0.0 or mynamespace:in-cluster:v1.0.0" }} +{{- end }} --- apiVersion: v1 kind: Namespace @@ -52,27 +70,8 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} -{{- if $ipam.manifestPatches }} - manifestPatches: {{ toYaml $ipam.manifestPatches | nindent 4 }} -{{- end }} {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} -{{- if $ipam.additionalManifests }} - additionalManifests: - name: {{ $ipam.additionalManifests.name }} - {{- if $ipam.additionalManifests.namespace }} - namespace: {{ $ipam.additionalManifests.namespace }} - {{- end }} {{/* if $ipam.additionalManifests.namespace */}} {{- end }} -{{- if $ipam.additionalManifests }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $ipam.additionalManifests.name }} - namespace: {{ default $ipamNamespace $ipam.additionalManifests.namespace }} -data: - manifests: {{- toYaml $ipam.additionalManifests.manifests | nindent 4 }} {{- end }} -{{- end }} {{/* range $name, $ipam := .Values.ipam */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml index 0ee82bfc..27b8bf80 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml @@ -1305,13 +1305,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -2843,13 +2836,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -3062,32 +3048,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -3097,8 +3078,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -4732,32 +4711,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -4767,8 +4741,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -6071,13 +6043,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7609,13 +7574,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7828,32 +7786,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -7863,8 +7816,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -9499,32 +9450,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -9534,8 +9480,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -10839,13 +10783,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12377,13 +12314,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12597,32 +12527,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -12632,8 +12557,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -14267,32 +14190,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -14302,8 +14220,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -15606,13 +15522,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17144,13 +17053,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17363,32 +17265,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -17398,8 +17295,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -19034,32 +18929,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -19069,8 +18959,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -20374,13 +20262,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -21912,13 +21793,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -22132,32 +22006,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -22167,8 +22036,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -23504,13 +23371,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -25042,13 +24902,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -25261,32 +25114,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -25296,8 +25144,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime @@ -26635,13 +26481,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28173,13 +28012,6 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: - additionalArgs: - additionalProperties: - type: string - description: |- - AdditionalArgs is a map of additional options that will be passed - in as container args to the provider's controller manager. - type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28393,32 +28225,27 @@ spec: properties: lastTransitionTime: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. + 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. + A human readable message indicating details about the transition. This field may be empty. - maxLength: 10240 - minLength: 1 type: string reason: description: |- - reason is the reason for the condition's last transition in CamelCase. + The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. - maxLength: 256 - minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. - maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -28428,8 +28255,6 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. - maxLength: 256 - minLength: 1 type: string required: - lastTransitionTime diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json b/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json deleted file mode 100644 index d22038fc..00000000 --- a/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "core": { - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - }, - "bootstrap": { - "type": "object", - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - }, - "controlPlane": { - "type": "object", - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - }, - "infrastructure": { - "type": "object", - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - }, - "addon": { - "type": "object", - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - }, - "ipam": { - "type": "object", - "oneOf": [ - { "type": "object" }, - { "type": "null" } - ] - } - } -} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml index 545bae39..12507a3c 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml @@ -1,30 +1,12 @@ --- # --- # Cluster API provider options -core: {} -# cluster-api: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional -bootstrap: {} -# kubeadm: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional -controlPlane: {} -# kubeadm: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional -infrastructure: {} -# docker: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional -addon: {} -# helm: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional -ipam: {} -# in-cluster: {} # Name, required -# namespace: "" # Optional -# version: "" # Optional +core: "" +bootstrap: "" +controlPlane: "" +infrastructure: "" +ipam: "" +addon: "" manager.featureGates: {} fetchConfig: {} # --- @@ -39,7 +21,7 @@ leaderElection: image: manager: repository: registry.k8s.io/capi-operator/cluster-api-operator - tag: v0.19.0 + tag: v0.18.1 pullPolicy: IfNotPresent env: manager: [] diff --git a/scripts/package.mk b/scripts/package.mk index ca537213..62702321 100644 --- a/scripts/package.mk +++ b/scripts/package.mk @@ -29,3 +29,11 @@ delete: check suspend ## Delete Helm release from a Kubernetes cluster check: @if [ -z "$(NAME)" ]; then echo "env NAME is not set!" >&2; exit 1; fi @if [ -z "$(NAMESPACE)" ]; then echo "env NAMESPACE is not set!" >&2; exit 1; fi + +clean: + rm -rf charts/ + +%-update: + helm repo add $(REPO_NAME) $(REPO_URL) + helm repo update $(REPO_NAME) + helm pull $(REPO_NAME)/$(CHART_NAME) --untar --untardir charts --version "$(CHART_VERSION)" From 15d7b6d99ea39e65d59003fcce66a49bd789bf7b Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Wed, 14 May 2025 18:30:15 +0300 Subject: [PATCH 076/120] extra/monitoring: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/extra/monitoring/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extra/monitoring/Makefile b/packages/extra/monitoring/Makefile index 912ea809..e2b8d330 100644 --- a/packages/extra/monitoring/Makefile +++ b/packages/extra/monitoring/Makefile @@ -13,7 +13,7 @@ generate: rm -f values.schema.json.tmp image: - docker buildx build --platform linux/amd64 images/grafana \ + docker buildx build images/grafana \ --provenance false \ --builder=$(BUILDER) \ --platform=$(PLATFORM) \ From 3780925a680798e1ddbfe364bb5f4669ba53cb65 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 8 May 2025 14:34:07 +0200 Subject: [PATCH 077/120] [platform] Introduce expose-services and expose-ingress options Signed-off-by: Andrei Kvapil --- hack/e2e.sh | 4 +- packages/extra/ingress/Chart.yaml | 2 +- packages/extra/ingress/README.md | 15 +++----- .../ingress/templates/cdi-uploadproxy.yaml | 37 ------------------- packages/extra/ingress/values.schema.json | 15 -------- packages/extra/ingress/values.yaml | 9 ----- packages/extra/ingress/vm-exportproxy.yaml | 37 ------------------- packages/extra/versions_map | 2 +- .../cozystack-api/templates/api-ingress.yaml | 28 ++++++++++++++ .../templates/dashboard-ingress.yaml} | 27 +++++--------- .../templates/configure-kk.yaml | 9 ----- .../system/keycloak/templates/ingress.yaml | 17 ++------- packages/system/keycloak/templates/sts.yaml | 9 ----- .../templates/cdi-uploadproxy-ingress.yaml | 29 +++++++++++++++ .../templates/vm-exportproxy-ingress.yaml | 28 ++++++++++++++ 15 files changed, 107 insertions(+), 161 deletions(-) delete mode 100644 packages/extra/ingress/templates/cdi-uploadproxy.yaml delete mode 100644 packages/extra/ingress/vm-exportproxy.yaml create mode 100644 packages/system/cozystack-api/templates/api-ingress.yaml rename packages/{extra/ingress/templates/dashboard.yaml => system/dashboard/templates/dashboard-ingress.yaml} (54%) create mode 100644 packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml create mode 100644 packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml diff --git a/hack/e2e.sh b/hack/e2e.sh index e7c66534..46c9ba5b 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -334,8 +334,8 @@ if ! kubectl wait --timeout=2m --for=condition=ready -n tenant-root hr monitorin kubectl wait --timeout=2m --for=condition=ready -n tenant-root hr monitoring fi -kubectl patch -n tenant-root ingresses.apps.cozystack.io ingress --type=merge -p '{"spec":{ - "dashboard": true +kubectl patch -n cozy-system cm cozystack --type=merge -p '{"data":{ + "expose-services": "api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak" }}' # Wait for nginx-ingress-controller diff --git a/packages/extra/ingress/Chart.yaml b/packages/extra/ingress/Chart.yaml index e6001cc8..93807c89 100644 --- a/packages/extra/ingress/Chart.yaml +++ b/packages/extra/ingress/Chart.yaml @@ -3,4 +3,4 @@ name: ingress description: NGINX Ingress Controller icon: /logos/ingress-nginx.svg type: application -version: 1.5.1 +version: 1.6.0 diff --git a/packages/extra/ingress/README.md b/packages/extra/ingress/README.md index af395dfe..ab4ed3d9 100644 --- a/packages/extra/ingress/README.md +++ b/packages/extra/ingress/README.md @@ -4,13 +4,10 @@ ### Common parameters -| Name | Description | Value | -| ----------------- | ----------------------------------------------------------------- | ------- | -| `replicas` | Number of ingress-nginx replicas | `2` | -| `externalIPs` | List of externalIPs for service. | `[]` | -| `whitelist` | List of client networks | `[]` | -| `clouflareProxy` | Restoring original visitor IPs when Cloudflare proxied is enabled | `false` | -| `dashboard` | Should ingress serve Cozystack service dashboard | `false` | -| `cdiUploadProxy` | Should ingress serve CDI upload proxy | `false` | -| `virtExportProxy` | Should ingress serve KubeVirt export proxy | `false` | +| Name | Description | Value | +| ---------------- | ----------------------------------------------------------------- | ------- | +| `replicas` | Number of ingress-nginx replicas | `2` | +| `externalIPs` | List of externalIPs for service. | `[]` | +| `whitelist` | List of client networks | `[]` | +| `clouflareProxy` | Restoring original visitor IPs when Cloudflare proxied is enabled | `false` | diff --git a/packages/extra/ingress/templates/cdi-uploadproxy.yaml b/packages/extra/ingress/templates/cdi-uploadproxy.yaml deleted file mode 100644 index e82e0d26..00000000 --- a/packages/extra/ingress/templates/cdi-uploadproxy.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} - -{{- if .Values.cdiUploadProxy }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - nginx.ingress.kubernetes.io/backend-protocol: HTTPS - cert-manager.io/cluster-issuer: letsencrypt-prod - {{- if eq $issuerType "cloudflare" }} - {{- else }} - acme.cert-manager.io/http01-ingress-class: {{ .Release.Namespace }} - {{- end }} - name: cdi-uploadproxy-{{ .Release.Namespace }} - namespace: cozy-kubevirt-cdi -spec: - ingressClassName: {{ .Release.Namespace }} - rules: - - host: cdi-uploadproxy.{{ $host }} - http: - paths: - - backend: - service: - name: cdi-uploadproxy - port: - number: 443 - path: / - pathType: Prefix - tls: - - hosts: - - cdi-uploadproxy.{{ $host }} - secretName: cdi-uploadproxy-{{ .Release.Namespace }}-tls -{{- end }} diff --git a/packages/extra/ingress/values.schema.json b/packages/extra/ingress/values.schema.json index 8005ac24..c956bac3 100644 --- a/packages/extra/ingress/values.schema.json +++ b/packages/extra/ingress/values.schema.json @@ -25,21 +25,6 @@ "type": "boolean", "description": "Restoring original visitor IPs when Cloudflare proxied is enabled", "default": false - }, - "dashboard": { - "type": "boolean", - "description": "Should ingress serve Cozystack service dashboard", - "default": false - }, - "cdiUploadProxy": { - "type": "boolean", - "description": "Should ingress serve CDI upload proxy", - "default": false - }, - "virtExportProxy": { - "type": "boolean", - "description": "Should ingress serve KubeVirt export proxy", - "default": false } } } \ No newline at end of file diff --git a/packages/extra/ingress/values.yaml b/packages/extra/ingress/values.yaml index 41571db9..669698f1 100644 --- a/packages/extra/ingress/values.yaml +++ b/packages/extra/ingress/values.yaml @@ -24,12 +24,3 @@ whitelist: [] ## @param clouflareProxy Restoring original visitor IPs when Cloudflare proxied is enabled clouflareProxy: false - -## @param dashboard Should ingress serve Cozystack service dashboard -dashboard: false - -## @param cdiUploadProxy Should ingress serve CDI upload proxy -cdiUploadProxy: false - -## @param virtExportProxy Should ingress serve KubeVirt export proxy -virtExportProxy: false diff --git a/packages/extra/ingress/vm-exportproxy.yaml b/packages/extra/ingress/vm-exportproxy.yaml deleted file mode 100644 index 0984bf6c..00000000 --- a/packages/extra/ingress/vm-exportproxy.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} - -{{- if .Values.virtExportProxy }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - nginx.ingress.kubernetes.io/backend-protocol: HTTPS - cert-manager.io/cluster-issuer: letsencrypt-prod - {{- if eq $issuerType "cloudflare" }} - {{- else }} - acme.cert-manager.io/http01-ingress-class: {{ .Release.Namespace }} - {{- end }} - name: virt-exportproxy-{{ .Release.Namespace }} - namespace: cozy-kubevirt -spec: - ingressClassName: {{ .Release.Namespace }} - rules: - - host: virt-exportproxy.{{ $host }} - http: - paths: - - backend: - service: - name: virt-exportproxy - port: - number: 443 - path: / - pathType: ImplementationSpecific - tls: - - hosts: - virt-exportproxy.{{ $host }} - secretName: virt-exportproxy-{{ .Release.Namespace }}-tls -{{- end }} diff --git a/packages/extra/versions_map b/packages/extra/versions_map index a76418a5..a7accda5 100644 --- a/packages/extra/versions_map +++ b/packages/extra/versions_map @@ -19,7 +19,7 @@ ingress 1.2.0 28fca4ef ingress 1.3.0 fde4bcfa ingress 1.4.0 fd240701 ingress 1.5.0 93bdf411 -ingress 1.5.1 HEAD +ingress 1.6.0 HEAD monitoring 1.0.0 d7cfa53c monitoring 1.1.0 25221fdc monitoring 1.2.0 f81be075 diff --git a/packages/system/cozystack-api/templates/api-ingress.yaml b/packages/system/cozystack-api/templates/api-ingress.yaml new file mode 100644 index 00000000..d7670e71 --- /dev/null +++ b/packages/system/cozystack-api/templates/api-ingress.yaml @@ -0,0 +1,28 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} + +{{- if and (has "api" $exposeServices) }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + name: kubernetes + namespace: default +spec: + ingressClassName: {{ $exposeIngress }} + rules: + - host: api.{{ $host }} + http: + paths: + - backend: + service: + name: kubernetes + port: + number: 443 + path: / + pathType: Prefix +{{- end }} diff --git a/packages/extra/ingress/templates/dashboard.yaml b/packages/system/dashboard/templates/dashboard-ingress.yaml similarity index 54% rename from packages/extra/ingress/templates/dashboard.yaml rename to packages/system/dashboard/templates/dashboard-ingress.yaml index 28b6722c..1fd7f85d 100644 --- a/packages/extra/ingress/templates/dashboard.yaml +++ b/packages/system/dashboard/templates/dashboard-ingress.yaml @@ -1,19 +1,10 @@ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} {{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} - -{{- $tenantRoot := dict }} -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- end }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- else }} -{{- end }} - -{{- if .Values.dashboard }} +{{- if and (has "dashboard" $exposeServices) }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -21,16 +12,16 @@ metadata: cert-manager.io/cluster-issuer: letsencrypt-prod {{- if eq $issuerType "cloudflare" }} {{- else }} - acme.cert-manager.io/http01-ingress-class: {{ .Release.Namespace }} + acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }} + {{- end }} nginx.ingress.kubernetes.io/proxy-body-size: 100m nginx.ingress.kubernetes.io/proxy-buffer-size: 100m nginx.ingress.kubernetes.io/proxy-buffers-number: "4" nginx.ingress.kubernetes.io/client-max-body-size: 100m - {{- end }} - name: dashboard-{{ .Release.Namespace }} + name: dashboard namespace: cozy-dashboard spec: - ingressClassName: {{ .Release.Namespace }} + ingressClassName: {{ $exposeIngress }} rules: - host: dashboard.{{ $host }} http: @@ -45,5 +36,5 @@ spec: tls: - hosts: - dashboard.{{ $host }} - secretName: dashboard-{{ .Release.Namespace }}-tls + secretName: dashboard-tls {{- end }} diff --git a/packages/system/keycloak-configure/templates/configure-kk.yaml b/packages/system/keycloak-configure/templates/configure-kk.yaml index b2d8db5b..adee11b6 100644 --- a/packages/system/keycloak-configure/templates/configure-kk.yaml +++ b/packages/system/keycloak-configure/templates/configure-kk.yaml @@ -4,15 +4,6 @@ {{- $rootSaConfigMap := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} {{- $k8sCa := index $rootSaConfigMap.data "ca.crt" | b64enc }} -{{- $tenantRoot := dict }} -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- end }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- else }} -{{- end }} - {{- $existingK8sSecret := lookup "v1" "Secret" .Release.Namespace "k8s-client" }} {{- $existingKubeappsSecret := lookup "v1" "Secret" .Release.Namespace "kubeapps-client" }} {{- $existingAuthConfig := lookup "v1" "Secret" "cozy-dashboard" "kubeapps-auth-config" }} diff --git a/packages/system/keycloak/templates/ingress.yaml b/packages/system/keycloak/templates/ingress.yaml index 6ae1384a..30120619 100644 --- a/packages/system/keycloak/templates/ingress.yaml +++ b/packages/system/keycloak/templates/ingress.yaml @@ -1,18 +1,7 @@ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} {{- $host := index $cozyConfig.data "root-host" }} {{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $rootns := lookup "v1" "Namespace" "" "tenant-root" }} -{{- $ingress := index $rootns.metadata.annotations "namespace.cozystack.io/ingress" }} - -{{- $tenantRoot := dict }} -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- end }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- else }} -{{- end }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} apiVersion: networking.k8s.io/v1 kind: Ingress @@ -21,13 +10,13 @@ metadata: {{- with .Values.ingress.annotations }} annotations: {{- if ne $issuerType "cloudflare" }} - acme.cert-manager.io/http01-ingress-class: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }} {{- end }} cert-manager.io/cluster-issuer: letsencrypt-prod {{- toYaml . | nindent 4 }} {{- end }} spec: - ingressClassName: {{ $ingress }} + ingressClassName: {{ $exposeIngress }} tls: - hosts: - keycloak.{{ $host }} diff --git a/packages/system/keycloak/templates/sts.yaml b/packages/system/keycloak/templates/sts.yaml index cecb17a1..e625859b 100644 --- a/packages/system/keycloak/templates/sts.yaml +++ b/packages/system/keycloak/templates/sts.yaml @@ -7,15 +7,6 @@ {{- $password = index $existingPassword.data "password" | b64dec }} {{- end }} -{{- $tenantRoot := dict }} -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- end }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- else }} -{{- end }} - apiVersion: v1 kind: Secret metadata: diff --git a/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml b/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml new file mode 100644 index 00000000..58eef4fa --- /dev/null +++ b/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml @@ -0,0 +1,29 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} + + +{{- if and (has "cdi-uploadproxy" $exposeServices) }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + name: cdi-uploadproxy + namespace: cozy-kubevirt-cdi +spec: + ingressClassName: {{ $exposeIngress }} + rules: + - host: cdi-uploadproxy.{{ $host }} + http: + paths: + - backend: + service: + name: cdi-uploadproxy + port: + number: 443 + path: / + pathType: Prefix +{{- end }} diff --git a/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml b/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml new file mode 100644 index 00000000..b77743d0 --- /dev/null +++ b/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml @@ -0,0 +1,28 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} + +{{- if and (has "vm-exportproxy" $exposeServices) }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + name: vm-exportproxy + namespace: cozy-kubevirt +spec: + ingressClassName: {{ $exposeIngress }} + rules: + - host: vm-exportproxy.{{ $host }} + http: + paths: + - backend: + service: + name: vm-exportproxy + port: + number: 443 + path: / + pathType: ImplementationSpecific +{{- end }} From 798ca12e43c9af0f6ee022b20550fb5912c7cf99 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 8 May 2025 15:27:36 +0200 Subject: [PATCH 078/120] [platform] Introduce expose-external-ips option Signed-off-by: Andrei Kvapil --- packages/extra/ingress/templates/nginx-ingress.yaml | 7 +++++-- packages/extra/ingress/values.yaml | 11 ----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index cfc29d1f..307095ff 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -1,3 +1,6 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $exposeExternalIPs := splitList "," ((index $cozyConfig.data "expose-external-ips") | default "") }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -31,9 +34,9 @@ spec: enabled: false {{- end }} service: - {{- if .Values.externalIPs }} + {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} externalIPs: - {{- toYaml .Values.externalIPs | nindent 12 }} + {{- toYaml $exposeExternalIPs | nindent 12 }} type: ClusterIP externalTrafficPolicy: Cluster {{- else }} diff --git a/packages/extra/ingress/values.yaml b/packages/extra/ingress/values.yaml index 669698f1..a5cee834 100644 --- a/packages/extra/ingress/values.yaml +++ b/packages/extra/ingress/values.yaml @@ -4,17 +4,6 @@ ## replicas: 2 -## @param externalIPs [array] List of externalIPs for service. -## Optional. If not specified will use LoadBalancer service by default. -## -## e.g: -## externalIPs: -## - "11.22.33.44" -## - "11.22.33.45" -## - "11.22.33.46" -## -externalIPs: [] - ## @param whitelist List of client networks ## Example: ## whitelist: From e9c463c86785b86f0a7fe75545e6f74ec8caf8d0 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 8 May 2025 15:28:10 +0200 Subject: [PATCH 079/120] [platform] Add migration for expose-* options Signed-off-by: Andrei Kvapil --- scripts/migrations/11 | 0 scripts/migrations/12 | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) mode change 100644 => 100755 scripts/migrations/11 create mode 100755 scripts/migrations/12 diff --git a/scripts/migrations/11 b/scripts/migrations/11 old mode 100644 new mode 100755 diff --git a/scripts/migrations/12 b/scripts/migrations/12 new file mode 100755 index 00000000..fcb951bc --- /dev/null +++ b/scripts/migrations/12 @@ -0,0 +1,35 @@ +#!/bin/sh +# Migration 12 --> 13 + +# Copy configuration from ingress to cozystack configmap +if kubectl get hr -n tenant-root tenant-root > /dev/null; then + expose_services=$( + kubectl get hr -n tenant-root ingress -o go-template='{{ with .spec }}{{ with .values }}{{ if .dashboard }}dashboard,{{ end }}{{ if .cdiUploadProxy }}cdi-uploadproxy,{{ end }}{{ if .virtExportProxy }}vm-exportproxy,{{ end }}{{ end }}{{ end }}' + ) + expose_services=$(echo "$expose_services" | awk '{sub(/,$/,""); print}') + + expose_external_ips=$( + kubectl get hr -n tenant-root ingress -o go-template='{{ with .spec }}{{ with .values }}{{ if .externalIPs }}{{ range .externalIPs }}{{ . }},{{ end }}{{ end }}{{ end }}{{ end }}' + ) + expose_external_ips=$(echo "$expose_external_ips" | awk '{sub(/,$/,""); print}') + + existing_expose_external_ips=$(kubectl get cm -n cozy-system cozystack -o go-template='{{ index .data "expose-external-ips" }}') + existing_expose_services=$(kubectl get cm -n cozy-system cozystack -o go-template='{{ index .data "expose-services" }}') + + if [ "$existing_expose_external_ips" == "" ]; then + kubectl patch cm -n cozy-system cozystack --type merge -p="{\"data\":{\"expose-external-ips\":\"$expose_external_ips\"}}" + fi + + if [ "$existing_expose_services" == "" ]; then + kubectl patch cm -n cozy-system cozystack --type merge -p="{\"data\":{\"expose-services\":\"$expose_services\"}}" + fi + + kubectl patch hr -n tenant-root ingress --type json -p='[{"op": "remove", "path": "/spec/values/dashboard"}]' || true + kubectl patch hr -n tenant-root ingress --type json -p='[{"op": "remove", "path": "/spec/values/cdiUploadProxy"}]' || true + kubectl patch hr -n tenant-root ingress --type json -p='[{"op": "remove", "path": "/spec/values/virtExportProxy"}]' || true + kubectl patch hr -n tenant-root ingress --type json -p='[{"op": "remove", "path": "/spec/values/externalIPs"}]' || true + kubectl patch hr -n tenant-root ingress --type merge -p='{"spec":{"chart":{"spec":{"version":"1.6.0"}}}}' +fi + +# Write version to cozystack-version config +kubectl create configmap -n cozy-system cozystack-version --from-literal=version=13 --dry-run=client -o yaml | kubectl apply -f- From 545e256695434c00587602403a18112823f7674a Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 7 May 2025 16:21:40 +0200 Subject: [PATCH 080/120] [platform] refactor dashboard values Signed-off-by: Andrei Kvapil --- packages/core/platform/bundles/paas-full.yaml | 71 ++----------------- .../core/platform/bundles/paas-hosted.yaml | 63 +--------------- packages/core/platform/templates/_helpers.tpl | 54 ++++++++++++++ .../core/platform/templates/helmreleases.yaml | 11 --- 4 files changed, 64 insertions(+), 135 deletions(-) diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index da5a0e8a..8686bb68 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -260,72 +260,15 @@ releases: releaseName: dashboard chart: cozy-dashboard namespace: cozy-dashboard - dependsOn: [cilium,kubeovn,keycloak-configure] values: - kubeapps: - {{- if .Capabilities.APIVersions.Has "source.toolkit.fluxcd.io/v1" }} - {{- with (lookup "source.toolkit.fluxcd.io/v1" "HelmRepository" "cozy-public" "").items }} - redis: - master: - podAnnotations: - {{- range $index, $repo := . }} - {{- with (($repo.status).artifact).revision }} - repository.cozystack.io/{{ $repo.metadata.name }}: {{ quote . }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - frontend: - resourcesPreset: "none" - dashboard: - resourcesPreset: "none" - {{- $cozystackBranding:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} - {{- $branding := dig "data" "branding" "" $cozystackBranding }} - {{- if $branding }} - customLocale: - "Kubeapps": {{ $branding }} - {{- end }} - customStyle: | - {{- $logoImage := dig "data" "logo" "" $cozystackBranding }} - {{- if $logoImage }} - .kubeapps-logo { - background-image: {{ $logoImage }} - } - {{- end }} - #serviceaccount-selector { - display: none; - } - .login-moreinfo { - display: none; - } - a[href="#/docs"] { - display: none; - } - .login-group .clr-form-control .clr-control-label { - display: none; - } - .appview-separator div.appview-first-row div.center { - display: none; - } - .appview-separator div.appview-first-row section[aria-labelledby="app-secrets"] { - display: none; - } - .appview-first-row section[aria-labelledby="access-urls-title"] { - width: 100%; - } - {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} - {{- $dashboardKCValues := dig "data" "values.yaml" "" $dashboardKCconfig }} - {{- if $dashboardKCValues }} - valuesFrom: - - kind: ConfigMap - name: kubeapps-auth-config - valuesKey: values.yaml - {{- end }} - + {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} + {{- $dashboardKCValues := dig "data" "values.yaml" (dict) $dashboardKCconfig | fromYaml }} + {{- toYaml (deepCopy $dashboardKCValues | mergeOverwrite (fromYaml (include "cozystack.defaultDashboardValues" .))) | nindent 4 }} + dependsOn: + - cilium + - kubeovn {{- if eq $oidcEnabled "true" }} - dependsOn: [keycloak-configure] - {{- else }} - dependsOn: [] + - keycloak-configure {{- end }} - name: kamaji diff --git a/packages/core/platform/bundles/paas-hosted.yaml b/packages/core/platform/bundles/paas-hosted.yaml index f082b3bb..12addedb 100644 --- a/packages/core/platform/bundles/paas-hosted.yaml +++ b/packages/core/platform/bundles/paas-hosted.yaml @@ -155,66 +155,9 @@ releases: chart: cozy-dashboard namespace: cozy-dashboard values: - kubeapps: - {{- if .Capabilities.APIVersions.Has "source.toolkit.fluxcd.io/v1" }} - {{- with (lookup "source.toolkit.fluxcd.io/v1" "HelmRepository" "cozy-public" "").items }} - redis: - master: - podAnnotations: - {{- range $index, $repo := . }} - {{- with (($repo.status).artifact).revision }} - repository.cozystack.io/{{ $repo.metadata.name }}: {{ quote . }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - frontend: - resourcesPreset: "none" - dashboard: - resourcesPreset: "none" - {{- $cozystackBranding:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} - {{- $branding := dig "data" "branding" "" $cozystackBranding }} - {{- if $branding }} - customLocale: - "Kubeapps": {{ $branding }} - {{- end }} - customStyle: | - {{- $logoImage := dig "data" "logo" "" $cozystackBranding }} - {{- if $logoImage }} - .kubeapps-logo { - background-image: {{ $logoImage }} - } - {{- end }} - #serviceaccount-selector { - display: none; - } - .login-moreinfo { - display: none; - } - a[href="#/docs"] { - display: none; - } - .login-group .clr-form-control .clr-control-label { - display: none; - } - .appview-separator div.appview-first-row div.center { - display: none; - } - .appview-separator div.appview-first-row section[aria-labelledby="app-secrets"] { - display: none; - } - .appview-first-row section[aria-labelledby="access-urls-title"] { - width: 100%; - } - {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} - {{- $dashboardKCValues := dig "data" "values.yaml" "" $dashboardKCconfig }} - {{- if $dashboardKCValues }} - valuesFrom: - - kind: ConfigMap - name: kubeapps-auth-config - valuesKey: values.yaml - {{- end }} - + {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} + {{- $dashboardKCValues := dig "data" "values.yaml" (dict) $dashboardKCconfig }} + {{- toYaml (deepCopy $dashboardKCValues | mergeOverwrite (fromYaml (include "cozystack.defaultDashboardValues" .))) | nindent 4 }} {{- if eq $oidcEnabled "true" }} dependsOn: [keycloak-configure] {{- else }} diff --git a/packages/core/platform/templates/_helpers.tpl b/packages/core/platform/templates/_helpers.tpl index b3ab6a86..94edb35b 100644 --- a/packages/core/platform/templates/_helpers.tpl +++ b/packages/core/platform/templates/_helpers.tpl @@ -16,3 +16,57 @@ Get IP-addresses of master nodes {{- end -}} {{ join "," $ips }} {{- end -}} + +{{- define "cozystack.defaultDashboardValues" -}} +kubeapps: +{{- if .Capabilities.APIVersions.Has "source.toolkit.fluxcd.io/v1" }} +{{- with (lookup "source.toolkit.fluxcd.io/v1" "HelmRepository" "cozy-public" "").items }} + redis: + master: + podAnnotations: + {{- range $index, $repo := . }} + {{- with (($repo.status).artifact).revision }} + repository.cozystack.io/{{ $repo.metadata.name }}: {{ quote . }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} + frontend: + resourcesPreset: "none" + dashboard: + resourcesPreset: "none" + {{- $cozystackBranding:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} + {{- $branding := dig "data" "branding" "" $cozystackBranding }} + {{- if $branding }} + customLocale: + "Kubeapps": {{ $branding }} + {{- end }} + customStyle: | + {{- $logoImage := dig "data" "logo" "" $cozystackBranding }} + {{- if $logoImage }} + .kubeapps-logo { + background-image: {{ $logoImage }} + } + {{- end }} + #serviceaccount-selector { + display: none; + } + .login-moreinfo { + display: none; + } + a[href="#/docs"] { + display: none; + } + .login-group .clr-form-control .clr-control-label { + display: none; + } + .appview-separator div.appview-first-row div.center { + display: none; + } + .appview-separator div.appview-first-row section[aria-labelledby="app-secrets"] { + display: none; + } + .appview-first-row section[aria-labelledby="access-urls-title"] { + width: 100%; + } +{{- end }} diff --git a/packages/core/platform/templates/helmreleases.yaml b/packages/core/platform/templates/helmreleases.yaml index 1298d74b..17b373be 100644 --- a/packages/core/platform/templates/helmreleases.yaml +++ b/packages/core/platform/templates/helmreleases.yaml @@ -72,17 +72,6 @@ spec: {{- toYaml . | nindent 4}} {{- end }} - {{- if $x.valuesFrom }} - valuesFrom: - {{- range $source := $x.valuesFrom }} - - kind: {{ $source.kind }} - name: {{ $source.name }} - {{- if $source.valuesKey }} - valuesKey: {{ $source.valuesKey }} - {{- end }} - {{- end }} - {{- end }} - {{- with $x.dependsOn }} dependsOn: {{- range $dep := . }} From 8ad010d3319883770798f33147f564c0b19d3ee9 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 15 May 2025 14:36:19 +0200 Subject: [PATCH 081/120] Revert "Downgrade CAPI operator" Signed-off-by: Andrei Kvapil --- packages/system/capi-operator/Makefile | 2 +- .../charts/cluster-api-operator/Chart.yaml | 4 +- .../cluster-api-operator/templates/addon.yaml | 45 ++-- .../templates/bootstrap.yaml | 45 ++-- .../templates/control-plane.yaml | 45 ++-- .../cluster-api-operator/templates/core.yaml | 45 ++-- .../cluster-api-operator/templates/infra.yaml | 47 ++-- .../cluster-api-operator/templates/ipam.yaml | 45 ++-- .../templates/operator-components.yaml | 241 +++++++++++++++--- .../cluster-api-operator/values.schema.json | 47 ++++ .../charts/cluster-api-operator/values.yaml | 32 ++- 11 files changed, 423 insertions(+), 175 deletions(-) create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/values.schema.json diff --git a/packages/system/capi-operator/Makefile b/packages/system/capi-operator/Makefile index 20c083aa..dc421cee 100644 --- a/packages/system/capi-operator/Makefile +++ b/packages/system/capi-operator/Makefile @@ -3,7 +3,7 @@ export NAMESPACE=cozy-cluster-api export REPO_NAME=capi-operator export REPO_URL=https://kubernetes-sigs.github.io/cluster-api-operator export CHART_NAME=cluster-api-operator -export CHART_VERSION=^0.18 +export CHART_VERSION=^0.19 include ../../../scripts/package.mk diff --git a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml index 5108c7dc..323a3594 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: 0.18.1 +appVersion: 0.19.0 description: Cluster API Operator name: cluster-api-operator type: application -version: 0.18.1 +version: 0.19.0 diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml index a2eb8fb9..6a341496 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml @@ -1,26 +1,8 @@ # Addon provider -{{- if .Values.addon }} -{{- $addons := split ";" .Values.addon }} -{{- $addonNamespace := "" }} -{{- $addonName := "" }} -{{- $addonVersion := "" }} -{{- range $addon := $addons }} -{{- $addonArgs := split ":" $addon }} -{{- $addonArgsLen := len $addonArgs }} -{{- if eq $addonArgsLen 3 }} - {{- $addonNamespace = $addonArgs._0 }} - {{- $addonName = $addonArgs._1 }} - {{- $addonVersion = $addonArgs._2 }} -{{- else if eq $addonArgsLen 2 }} - {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} - {{- $addonName = $addonArgs._0 }} - {{- $addonVersion = $addonArgs._1 }} -{{- else if eq $addonArgsLen 1 }} - {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} - {{- $addonName = $addonArgs._0 }} -{{- else }} - {{- fail "addon provider argument should have the following format helm:v1.0.0 or mynamespace:helm:v1.0.0" }} -{{- end }} +{{- range $name, $addon := $.Values.addon }} + {{- $addonNamespace := default ( printf "%s-%s" $name "addon-system" ) (get $addon "namespace") }} + {{- $addonName := $name }} + {{- $addonVersion := get $addon "version" }} --- apiVersion: v1 kind: Namespace @@ -56,5 +38,24 @@ spec: {{- if $.Values.secretNamespace }} secretNamespace: {{ $.Values.secretNamespace }} {{- end }} +{{- if $addon.manifestPatches }} + manifestPatches: {{ toYaml $addon.manifestPatches | nindent 4 }} {{- end }} +{{- if $addon.additionalManifests }} + additionalManifests: + name: {{ $addon.additionalManifests.name }} + {{- if $addon.additionalManifests.namespace }} + namespace: {{ $addon.additionalManifests.namespace }} + {{- end }} {{/* if $addon.additionalManifests.namespace */}} {{- end }} +{{- if $addon.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $addon.additionalManifests.name }} + namespace: {{ default $addonNamespace $addon.additionalManifests.namespace }} +data: + manifests: {{- toYaml $addon.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $addon := .Values.addon */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml index ed5d7924..78dad47e 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml @@ -1,26 +1,8 @@ # Bootstrap provider -{{- if .Values.bootstrap }} -{{- $bootstraps := split ";" .Values.bootstrap }} -{{- $bootstrapNamespace := "" }} -{{- $bootstrapName := "" }} -{{- $bootstrapVersion := "" }} -{{- range $bootstrap := $bootstraps }} -{{- $bootstrapArgs := split ":" $bootstrap }} -{{- $bootstrapArgsLen := len $bootstrapArgs }} -{{- if eq $bootstrapArgsLen 3 }} - {{- $bootstrapNamespace = $bootstrapArgs._0 }} - {{- $bootstrapName = $bootstrapArgs._1 }} - {{- $bootstrapVersion = $bootstrapArgs._2 }} -{{- else if eq $bootstrapArgsLen 2 }} - {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} - {{- $bootstrapName = $bootstrapArgs._0 }} - {{- $bootstrapVersion = $bootstrapArgs._1 }} -{{- else if eq $bootstrapArgsLen 1 }} - {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} - {{- $bootstrapName = $bootstrapArgs._0 }} -{{- else }} - {{- fail "bootstrap provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} -{{- end }} +{{- range $name, $bootstrap := $.Values.bootstrap }} + {{- $bootstrapNamespace := default ( printf "%s-%s" $name "bootstrap-system" ) (get $bootstrap "namespace") }} + {{- $bootstrapName := $name }} + {{- $bootstrapVersion := get $bootstrap "version" }} --- apiVersion: v1 kind: Namespace @@ -57,5 +39,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $bootstrap.manifestPatches }} + manifestPatches: {{ toYaml $bootstrap.manifestPatches | nindent 4 }} {{- end }} +{{- if $bootstrap.additionalManifests }} + additionalManifests: + name: {{ $bootstrap.additionalManifests.name }} + {{- if $bootstrap.additionalManifests.namespace }} + namespace: {{ $bootstrap.additionalManifests.namespace }} + {{- end }} {{/* if $bootstrap.additionalManifests.namespace */}} {{- end }} +{{- if $bootstrap.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $bootstrap.additionalManifests.name }} + namespace: {{ default $bootstrapNamespace $bootstrap.additionalManifests.namespace }} +data: + manifests: {{- toYaml $bootstrap.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $bootstrap := .Values.bootstrap */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml index d72249d1..8a020afd 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml @@ -1,26 +1,8 @@ # Control plane provider -{{- if .Values.controlPlane }} -{{- $controlPlanes := split ";" .Values.controlPlane }} -{{- $controlPlaneNamespace := "" }} -{{- $controlPlaneName := "" }} -{{- $controlPlaneVersion := "" }} -{{- range $controlPlane := $controlPlanes }} -{{- $controlPlaneArgs := split ":" $controlPlane }} -{{- $controlPlaneArgsLen := len $controlPlaneArgs }} -{{- if eq $controlPlaneArgsLen 3 }} - {{- $controlPlaneNamespace = $controlPlaneArgs._0 }} - {{- $controlPlaneName = $controlPlaneArgs._1 }} - {{- $controlPlaneVersion = $controlPlaneArgs._2 }} -{{- else if eq $controlPlaneArgsLen 2 }} - {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} - {{- $controlPlaneName = $controlPlaneArgs._0 }} - {{- $controlPlaneVersion = $controlPlaneArgs._1 }} -{{- else if eq $controlPlaneArgsLen 1 }} - {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} - {{- $controlPlaneName = $controlPlaneArgs._0 }} -{{- else }} - {{- fail "controlplane provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} -{{- end }} +{{- range $name, $controlPlane := $.Values.controlPlane }} + {{- $controlPlaneNamespace := default ( printf "%s-%s" $name "control-plane-system" ) (get $controlPlane "namespace") }} + {{- $controlPlaneName := $name }} + {{- $controlPlaneVersion := get $controlPlane "version" }} --- apiVersion: v1 kind: Namespace @@ -70,5 +52,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $controlPlane.manifestPatches }} + manifestPatches: {{ toYaml $controlPlane.manifestPatches | nindent 4 }} {{- end }} +{{- if $controlPlane.additionalManifests }} + additionalManifests: + name: {{ $controlPlane.additionalManifests.name }} + {{- if $controlPlane.additionalManifests.namespace }} + namespace: {{ $controlPlane.additionalManifests.namespace }} + {{- end }} {{/* if $controlPlane.additionalManifests.namespace */}} {{- end }} +{{- if $controlPlane.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $controlPlane.additionalManifests.name }} + namespace: {{ default $controlPlaneNamespace $controlPlane.additionalManifests.namespace }} +data: + manifests: {{- toYaml $controlPlane.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $controlPlane := .Values.controlPlane */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml index 828d2269..648e1b60 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml @@ -1,25 +1,8 @@ # Core provider -{{- if .Values.core }} -{{- $coreArgs := split ":" .Values.core }} -{{- $coreArgsLen := len $coreArgs }} -{{- $coreVersion := "" }} -{{- $coreNamespace := "" }} -{{- $coreName := "" }} -{{- $coreVersion := "" }} -{{- if eq $coreArgsLen 3 }} - {{- $coreNamespace = $coreArgs._0 }} - {{- $coreName = $coreArgs._1 }} - {{- $coreVersion = $coreArgs._2 }} -{{- else if eq $coreArgsLen 2 }} - {{- $coreNamespace = "capi-system" }} - {{- $coreName = $coreArgs._0 }} - {{- $coreVersion = $coreArgs._1 }} -{{- else if eq $coreArgsLen 1 }} - {{- $coreNamespace = "capi-system" }} - {{- $coreName = $coreArgs._0 }} -{{- else }} - {{- fail "core provider argument should have the following format cluster-api:v1.0.0 or mynamespace:cluster-api:v1.0.0" }} -{{- end }} +{{- range $name, $core := $.Values.core }} + {{- $coreNamespace := default "capi-system" (get $core "namespace") }} + {{- $coreName := $name }} + {{- $coreVersion := get $core "version" }} --- apiVersion: v1 kind: Namespace @@ -65,4 +48,24 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $core.manifestPatches }} + manifestPatches: {{ toYaml $core.manifestPatches | nindent 4 }} {{- end }} +{{- if $core.additionalManifests }} + additionalManifests: + name: {{ $core.additionalManifests.name }} + {{- if $core.additionalManifests.namespace }} + namespace: {{ $core.additionalManifests.namespace }} + {{- end }} +{{- end }} +{{- if $core.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $core.additionalManifests.name }} + namespace: {{ default $coreNamespace $core.additionalManifests.namespace }} +data: + manifests: {{- toYaml $core.additionalManifests.manifests | nindent 4 }} +{{- end }} +{{- end }} {{/* range $name, $core := .Values.core */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml index 5841336c..835607d4 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml @@ -1,26 +1,8 @@ # Infrastructure providers -{{- if .Values.infrastructure }} -{{- $infrastructures := split ";" .Values.infrastructure }} -{{- $infrastructureNamespace := "" }} -{{- $infrastructureName := "" }} -{{- $infrastructureVersion := "" }} -{{- range $infrastructure := $infrastructures }} -{{- $infrastructureArgs := split ":" $infrastructure }} -{{- $infrastructureArgsLen := len $infrastructureArgs }} -{{- if eq $infrastructureArgsLen 3 }} - {{- $infrastructureNamespace = $infrastructureArgs._0 }} - {{- $infrastructureName = $infrastructureArgs._1 }} - {{- $infrastructureVersion = $infrastructureArgs._2 }} -{{- else if eq $infrastructureArgsLen 2 }} - {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} - {{- $infrastructureName = $infrastructureArgs._0 }} - {{- $infrastructureVersion = $infrastructureArgs._1 }} -{{- else if eq $infrastructureArgsLen 1 }} - {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} - {{- $infrastructureName = $infrastructureArgs._0 }} -{{- else }} - {{- fail "infrastructure provider argument should have the following format aws:v1.0.0 or mynamespace:aws:v1.0.0" }} -{{- end }} +{{- range $name, $infra := $.Values.infrastructure }} + {{- $infrastructureNamespace := default ( printf "%s-%s" $name "infrastructure-system" ) (get $infra "namespace") }} + {{- $infrastructureName := $name }} + {{- $infrastructureVersion := get $infra "version" }} --- apiVersion: v1 kind: Namespace @@ -83,5 +65,24 @@ spec: {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} +{{- if $infra.manifestPatches }} + manifestPatches: {{- toYaml $infra.manifestPatches | nindent 4 }} +{{- end }} {{/* if $infra.manifestPatches */}} +{{- if $infra.additionalManifests }} + additionalManifests: + name: {{ $infra.additionalManifests.name }} + {{- if $infra.additionalManifests.namespace }} + namespace: {{ $infra.additionalManifests.namespace }} + {{- end }} {{/* if $infra.additionalManifests.namespace */}} +{{- end }} {{/* if $infra.additionalManifests */}} +{{- if $infra.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $infra.additionalManifests.name }} + namespace: {{ default $infrastructureNamespace $infra.additionalManifests.namespace }} +data: + manifests: {{- toYaml $infra.additionalManifests.manifests | nindent 4 }} {{- end }} -{{- end }} +{{- end }} {{/* range $name, $infra := .Values.infrastructure */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml index 06960afb..4a33c42f 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/ipam.yaml @@ -1,26 +1,8 @@ # IPAM providers -{{- if .Values.ipam }} -{{- $ipams := split ";" .Values.ipam }} -{{- $ipamNamespace := "" }} -{{- $ipamName := "" }} -{{- $ipamVersion := "" }} -{{- range $ipam := $ipams }} -{{- $ipamArgs := split ":" $ipam }} -{{- $ipamArgsLen := len $ipamArgs }} -{{- if eq $ipamArgsLen 3 }} - {{- $ipamNamespace = $ipamArgs._0 }} - {{- $ipamName = $ipamArgs._1 }} - {{- $ipamVersion = $ipamArgs._2 }} -{{- else if eq $ipamArgsLen 2 }} - {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} - {{- $ipamName = $ipamArgs._0 }} - {{- $ipamVersion = $ipamArgs._1 }} -{{- else if eq $ipamArgsLen 1 }} - {{- $ipamNamespace = print $ipamArgs._0 "-ipam-system" }} - {{- $ipamName = $ipamArgs._0 }} -{{- else }} - {{- fail "ipam provider argument should have the following format in-cluster:v1.0.0 or mynamespace:in-cluster:v1.0.0" }} -{{- end }} +{{- range $name, $ipam := $.Values.ipam }} + {{- $ipamNamespace := default ( printf "%s-%s" $name "ipam-system" ) (get $ipam "namespace") }} + {{- $ipamName := $name }} + {{- $ipamVersion := get $ipam "version" }} --- apiVersion: v1 kind: Namespace @@ -70,8 +52,27 @@ spec: namespace: {{ $.Values.configSecret.namespace }} {{- end }} {{- end }} +{{- if $ipam.manifestPatches }} + manifestPatches: {{ toYaml $ipam.manifestPatches | nindent 4 }} +{{- end }} {{- if $.Values.additionalDeployments }} additionalDeployments: {{ toYaml $.Values.additionalDeployments | nindent 4 }} {{- end }} +{{- if $ipam.additionalManifests }} + additionalManifests: + name: {{ $ipam.additionalManifests.name }} + {{- if $ipam.additionalManifests.namespace }} + namespace: {{ $ipam.additionalManifests.namespace }} + {{- end }} {{/* if $ipam.additionalManifests.namespace */}} {{- end }} +{{- if $ipam.additionalManifests }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $ipam.additionalManifests.name }} + namespace: {{ default $ipamNamespace $ipam.additionalManifests.namespace }} +data: + manifests: {{- toYaml $ipam.additionalManifests.manifests | nindent 4 }} {{- end }} +{{- end }} {{/* range $name, $ipam := .Values.ipam */}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml index 27b8bf80..0ee82bfc 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml @@ -1305,6 +1305,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -2836,6 +2843,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -3048,27 +3062,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -3078,6 +3097,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -4711,27 +4732,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -4741,6 +4767,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -6043,6 +6071,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7574,6 +7609,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -7786,27 +7828,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -7816,6 +7863,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -9450,27 +9499,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -9480,6 +9534,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -10783,6 +10839,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12314,6 +12377,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -12527,27 +12597,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -12557,6 +12632,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -14190,27 +14267,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -14220,6 +14302,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -15522,6 +15606,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17053,6 +17144,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -17265,27 +17363,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -17295,6 +17398,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -18929,27 +19034,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -18959,6 +19069,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -20262,6 +20374,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -21793,6 +21912,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -22006,27 +22132,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -22036,6 +22167,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -23371,6 +23504,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -24902,6 +25042,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -25114,27 +25261,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -25144,6 +25296,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime @@ -26481,6 +26635,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the additional provider deployment. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28012,6 +28173,13 @@ spec: description: Manager defines the properties that can be enabled on the controller manager for the provider. properties: + additionalArgs: + additionalProperties: + type: string + description: |- + AdditionalArgs is a map of additional options that will be passed + in as container args to the provider's controller manager. + type: object cacheNamespace: description: |- CacheNamespace if specified restricts the manager's cache to watch objects in @@ -28225,27 +28393,32 @@ spec: properties: lastTransitionTime: description: |- - Last time the condition transitioned from one status to another. + 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: |- - A human readable message indicating details about the transition. + message is a human readable message indicating details about the transition. This field may be empty. + maxLength: 10240 + minLength: 1 type: string reason: description: |- - The reason for the condition's last transition in CamelCase. + reason is the reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may be empty. + maxLength: 256 + minLength: 1 type: string severity: description: |- severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + maxLength: 32 type: string status: description: status of the condition, one of True, False, Unknown. @@ -28255,6 +28428,8 @@ spec: type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + maxLength: 256 + minLength: 1 type: string required: - lastTransitionTime diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json b/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json new file mode 100644 index 00000000..d22038fc --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "core": { + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "bootstrap": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "controlPlane": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "infrastructure": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "addon": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + }, + "ipam": { + "type": "object", + "oneOf": [ + { "type": "object" }, + { "type": "null" } + ] + } + } +} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml index 12507a3c..545bae39 100644 --- a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml @@ -1,12 +1,30 @@ --- # --- # Cluster API provider options -core: "" -bootstrap: "" -controlPlane: "" -infrastructure: "" -ipam: "" -addon: "" +core: {} +# cluster-api: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +bootstrap: {} +# kubeadm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +controlPlane: {} +# kubeadm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +infrastructure: {} +# docker: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +addon: {} +# helm: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional +ipam: {} +# in-cluster: {} # Name, required +# namespace: "" # Optional +# version: "" # Optional manager.featureGates: {} fetchConfig: {} # --- @@ -21,7 +39,7 @@ leaderElection: image: manager: repository: registry.k8s.io/capi-operator/cluster-api-operator - tag: v0.18.1 + tag: v0.19.0 pullPolicy: IfNotPresent env: manager: [] From 93b8dbb9ab3f756782ddab31c05b9eab5f2d0b24 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 15 May 2025 14:37:59 +0200 Subject: [PATCH 082/120] [cluster-api] Update capi-providers Signed-off-by: Andrei Kvapil --- packages/system/capi-providers/templates/providers.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/system/capi-providers/templates/providers.yaml b/packages/system/capi-providers/templates/providers.yaml index 7cb59f3b..b2accf40 100644 --- a/packages/system/capi-providers/templates/providers.yaml +++ b/packages/system/capi-providers/templates/providers.yaml @@ -5,7 +5,7 @@ metadata: name: cluster-api spec: # https://github.com/kubernetes-sigs/cluster-api - version: v1.10.0 + version: v1.10.1 --- apiVersion: operator.cluster.x-k8s.io/v1alpha2 kind: ControlPlaneProvider @@ -13,7 +13,7 @@ metadata: name: kamaji spec: # https://github.com/clastix/cluster-api-control-plane-provider-kamaji - version: v0.14.2 + version: v0.15.1 deployment: containers: - name: manager @@ -31,7 +31,7 @@ metadata: name: kubeadm spec: # https://github.com/kubernetes-sigs/cluster-api - version: v1.10.0 + version: v1.10.1 --- apiVersion: operator.cluster.x-k8s.io/v1alpha2 kind: InfrastructureProvider From 9d551cc69b0f103eb2c4622aa525df30a9117283 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 15 May 2025 16:49:07 +0200 Subject: [PATCH 083/120] [kubernetes] Update Kubernetes v1.32.4 Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Chart.yaml | 2 +- packages/apps/kubernetes/templates/cluster.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index a74f0945..47494b96 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -22,4 +22,4 @@ version: 0.20.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 1.31.0 +appVersion: 1.32.4 diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 1b2f395c..8b5e9bcd 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -157,7 +157,7 @@ spec: labels: policy.cozystack.io/allow-to-etcd: "true" replicas: 2 - version: 1.30.1 + version: {{ $.Chart.AppVersion }} --- apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor @@ -283,7 +283,7 @@ spec: kind: KubevirtMachineTemplate name: {{ $.Release.Name }}-{{ $groupName }}-{{ $kubevirtmachinetemplateHash }} namespace: {{ $.Release.Namespace }} - version: v1.32.3 + version: v{{ $.Chart.AppVersion }} --- apiVersion: cluster.x-k8s.io/v1beta1 kind: MachineHealthCheck From 6f55a66328be3b01919e2cbccbb894d56ba48117 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Fri, 16 May 2025 12:55:52 +0300 Subject: [PATCH 084/120] Hotfix: error in template Signed-off-by: Timofei Larkin --- packages/core/platform/bundles/paas-full.yaml | 2 +- packages/extra/ingress/templates/nginx-ingress.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index 8686bb68..71191025 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -262,7 +262,7 @@ releases: namespace: cozy-dashboard values: {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} - {{- $dashboardKCValues := dig "data" "values.yaml" (dict) $dashboardKCconfig | fromYaml }} + {{- $dashboardKCValues := dig "data" "values.yaml" "" $dashboardKCconfig | fromYaml }} {{- toYaml (deepCopy $dashboardKCValues | mergeOverwrite (fromYaml (include "cozystack.defaultDashboardValues" .))) | nindent 4 }} dependsOn: - cilium diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 307095ff..88d98b74 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -1,6 +1,6 @@ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} {{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} -{{- $exposeExternalIPs := splitList "," ((index $cozyConfig.data "expose-external-ips") | default "") }} +{{- $exposeExternalIPs := (index $cozyConfig.data "expose-external-ips") | default "" }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -36,7 +36,7 @@ spec: service: {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} externalIPs: - {{- toYaml $exposeExternalIPs | nindent 12 }} + {{- toYaml (splitList "," $exposeExternalIPs) | nindent 12 }} type: ClusterIP externalTrafficPolicy: Cluster {{- else }} From 4ecf492cd4fa8f74e63b24f69842e3df9e73f59b Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 16 May 2025 13:46:26 +0200 Subject: [PATCH 085/120] Update Kamaji to edge-25.4.1 Signed-off-by: Andrei Kvapil --- .../crds/kamaji.clastix.io_datastores.yaml | 18 +++++++ ...kamaji.clastix.io_tenantcontrolplanes.yaml | 49 ++++++++++++------- .../charts/kamaji/templates/controller.yaml | 4 -- .../kamaji/charts/kamaji/templates/rbac.yaml | 4 ++ .../system/kamaji/images/kamaji/Dockerfile | 4 +- packages/system/kamaji/values.yaml | 2 +- 6 files changed, 55 insertions(+), 26 deletions(-) diff --git a/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_datastores.yaml b/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_datastores.yaml index f3071767..aeb221e2 100644 --- a/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_datastores.yaml +++ b/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_datastores.yaml @@ -120,6 +120,9 @@ spec: - PostgreSQL - NATS type: string + x-kubernetes-validations: + - message: Datastore driver is immutable + rule: self == oldSelf endpoints: description: |- List of the endpoints to connect to the shared datastore. @@ -263,6 +266,21 @@ spec: - driver - endpoints type: object + x-kubernetes-validations: + - message: certificateAuthority privateKey must have secretReference or content when driver is etcd + rule: '(self.driver == "etcd") ? (self.tlsConfig != null && (has(self.tlsConfig.certificateAuthority.privateKey.secretReference) || has(self.tlsConfig.certificateAuthority.privateKey.content))) : true' + - message: clientCertificate must have secretReference or content when driver is etcd + rule: '(self.driver == "etcd") ? (self.tlsConfig != null && (has(self.tlsConfig.clientCertificate.certificate.secretReference) || has(self.tlsConfig.clientCertificate.certificate.content))) : true' + - message: clientCertificate privateKey must have secretReference or content when driver is etcd + rule: '(self.driver == "etcd") ? (self.tlsConfig != null && (has(self.tlsConfig.clientCertificate.privateKey.secretReference) || has(self.tlsConfig.clientCertificate.privateKey.content))) : true' + - message: When driver is not etcd and tlsConfig exists, clientCertificate must be null or contain valid content + rule: '(self.driver != "etcd" && has(self.tlsConfig) && has(self.tlsConfig.clientCertificate)) ? (((has(self.tlsConfig.clientCertificate.certificate.secretReference) || has(self.tlsConfig.clientCertificate.certificate.content)))) : true' + - message: When driver is not etcd and basicAuth exists, username must have secretReference or content + rule: '(self.driver != "etcd" && has(self.basicAuth)) ? ((has(self.basicAuth.username.secretReference) || has(self.basicAuth.username.content))) : true' + - message: When driver is not etcd and basicAuth exists, password must have secretReference or content + rule: '(self.driver != "etcd" && has(self.basicAuth)) ? ((has(self.basicAuth.password.secretReference) || has(self.basicAuth.password.content))) : true' + - message: When driver is not etcd, either tlsConfig or basicAuth must be provided + rule: '(self.driver != "etcd") ? (has(self.tlsConfig) || has(self.basicAuth)) : true' status: description: DataStoreStatus defines the observed state of DataStore. properties: diff --git a/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml b/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml index bb26cdcc..b3d3b668 100644 --- a/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml +++ b/packages/system/kamaji/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml @@ -427,7 +427,7 @@ spec: Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps + description: EnvFromSource represents the source of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -447,7 +447,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -696,6 +696,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -1792,7 +1798,7 @@ spec: Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps + description: EnvFromSource represents the source of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -1812,7 +1818,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -2061,6 +2067,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -4087,7 +4099,7 @@ spec: The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). + Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: @@ -5173,7 +5185,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5188,7 +5199,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5349,7 +5359,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5364,7 +5373,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5518,7 +5526,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5533,7 +5540,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5694,7 +5700,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5709,7 +5714,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6339,7 +6343,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -6350,7 +6353,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -7071,7 +7073,7 @@ spec: description: KubernetesDeploymentStatus defines the status for the Tenant Control Plane Deployment in the management cluster. properties: availableReplicas: - description: Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. + description: Total number of available non-terminating pods (ready for at least minReadySeconds) targeted by this deployment. format: int32 type: integer collisionCount: @@ -7129,16 +7131,24 @@ spec: format: int64 type: integer readyReplicas: - description: readyReplicas is the number of pods targeted by this Deployment with a Ready Condition. + description: Total number of non-terminating pods targeted by this Deployment with a Ready Condition. format: int32 type: integer replicas: - description: Total number of non-terminated pods targeted by this deployment (their labels match the selector). + description: Total number of non-terminating pods targeted by this deployment (their labels match the selector). format: int32 type: integer selector: description: Selector is the label selector used to group the Tenant Control Plane Pods used by the scale subresource. type: string + terminatingReplicas: + description: |- + Total number of terminating pods targeted by this deployment. Terminating pods have a non-null + .metadata.deletionTimestamp and have not yet reached the Failed or Succeeded .status.phase. + + This is an alpha field. Enable DeploymentReplicaSetTerminatingReplicas to be able to use this field. + format: int32 + type: integer unavailableReplicas: description: |- Total number of unavailable pods targeted by this deployment. This is the total number of @@ -7147,7 +7157,7 @@ spec: format: int32 type: integer updatedReplicas: - description: Total number of non-terminated pods targeted by this deployment that have the desired template spec. + description: Total number of non-terminating pods targeted by this deployment that have the desired template spec. format: int32 type: integer required: @@ -7379,6 +7389,7 @@ spec: - Migrating - Ready - NotReady + - Sleeping type: string version: description: Version is the running Kubernetes version of the Tenant Control Plane. diff --git a/packages/system/kamaji/charts/kamaji/templates/controller.yaml b/packages/system/kamaji/charts/kamaji/templates/controller.yaml index 38d635dd..63178382 100644 --- a/packages/system/kamaji/charts/kamaji/templates/controller.yaml +++ b/packages/system/kamaji/charts/kamaji/templates/controller.yaml @@ -19,10 +19,6 @@ spec: labels: {{- include "kamaji.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} serviceAccountName: {{ include "kamaji.serviceAccountName" . }} diff --git a/packages/system/kamaji/charts/kamaji/templates/rbac.yaml b/packages/system/kamaji/charts/kamaji/templates/rbac.yaml index aa4301db..43a1866f 100644 --- a/packages/system/kamaji/charts/kamaji/templates/rbac.yaml +++ b/packages/system/kamaji/charts/kamaji/templates/rbac.yaml @@ -9,6 +9,10 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} namespace: {{ .Release.Namespace }} +{{- with .Values.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role diff --git a/packages/system/kamaji/images/kamaji/Dockerfile b/packages/system/kamaji/images/kamaji/Dockerfile index 58007bd3..b607756b 100644 --- a/packages/system/kamaji/images/kamaji/Dockerfile +++ b/packages/system/kamaji/images/kamaji/Dockerfile @@ -1,7 +1,7 @@ # Build the manager binary -FROM golang:1.23 as builder +FROM golang:1.24 as builder -ARG VERSION=edge-25.3.2 +ARG VERSION=edge-25.4.1 ARG TARGETOS TARGETARCH WORKDIR /workspace diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index ee781d0e..f28c1408 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,7 +3,7 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: v0.31.0-rc.1@sha256:3ae6f1b2e42dcb9dcfbf8213029eb731197ccdbf27fdc30539d975caf32184d4 + tag: latest@sha256:f6a33408df8d3c4223005392bcd8bae9d8c02fd73e2540bbaa911dedb7880ea8 repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: From 5fe7b3bf165268a4ade5e83d4ccc6f67bec7c731 Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Thu, 15 May 2025 14:37:14 +0300 Subject: [PATCH 086/120] Build patched MetalLB Since it's taking a while for metallb/metallb#2726 to get released, the binaries with the fix are recompiled in-tree. Workaround for #909. Signed-off-by: Timofei Larkin --- Makefile | 1 + packages/system/metallb/Makefile | 23 +++++ .../system/metallb/charts/metallb/Chart.lock | 8 +- .../system/metallb/charts/metallb/Chart.yaml | 8 +- .../system/metallb/charts/metallb/README.md | 8 +- .../charts/metallb/charts/crds/Chart.yaml | 4 +- .../metallb/charts/crds/templates/crds.yaml | 40 ++++++--- .../charts/metallb/templates/controller.yaml | 2 +- .../charts/metallb/templates/podmonitor.yaml | 2 + .../metallb/templates/prometheusrules.yaml | 20 ++--- .../charts/metallb/templates/rbac.yaml | 12 ++- .../metallb/templates/service-accounts.yaml | 2 +- .../metallb/templates/servicemonitor.yaml | 7 +- .../system/metallb/charts/metallb/values.yaml | 12 +-- .../system/metallb/images/metallb/Dockerfile | 87 +++++++++++++++++++ packages/system/metallb/values.yaml | 11 ++- 16 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 packages/system/metallb/images/metallb/Dockerfile diff --git a/Makefile b/Makefile index 99309f4e..63f61458 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ build: build-deps make -C packages/system/kubeovn image make -C packages/system/kubeovn-webhook image make -C packages/system/dashboard image + make -C packages/system/metallb image make -C packages/system/kamaji image make -C packages/system/bucket image make -C packages/core/testing image diff --git a/packages/system/metallb/Makefile b/packages/system/metallb/Makefile index d01bf396..1cef5576 100644 --- a/packages/system/metallb/Makefile +++ b/packages/system/metallb/Makefile @@ -1,6 +1,7 @@ export NAME=metallb export NAMESPACE=cozy-$(NAME) +include ../../../scripts/common-envs.mk include ../../../scripts/package.mk update: @@ -9,3 +10,25 @@ update: helm repo update metallb helm pull metallb/metallb --untar --untardir charts rm -rf charts/metallb/charts/frr-k8s + +image-controller image-speaker: + $(eval TARGET := $(subst image-,,$@)) + $(eval VERSION := $(shell yq '.appVersion' charts/metallb/Chart.yaml)) + docker buildx build images/metallb \ + --provenance false \ + --target $(TARGET) \ + --build-arg VERSION=$(VERSION) \ + --tag $(REGISTRY)/metallb-$(TARGET):$(VERSION) \ + --cache-from type=registry,ref=$(REGISTRY)/metallb-$(TARGET):latest \ + --cache-to type=inline \ + --metadata-file images/$(TARGET).json \ + --push=$(PUSH) \ + --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" + --load=1 + REPOSITORY="$(REGISTRY)/metallb-$(TARGET)" \ + yq -i '.metallb.$(TARGET).image.repository = strenv(REPOSITORY)' values.yaml + TAG=$(VERSION)@$$(yq e '."containerimage.digest"' images/$(TARGET).json -o json -r) \ + yq -i '.metallb.$(TARGET).image.tag = strenv(TAG)' values.yaml + rm -f images/$(TARGET).json + +image: image-controller image-speaker diff --git a/packages/system/metallb/charts/metallb/Chart.lock b/packages/system/metallb/charts/metallb/Chart.lock index 81247366..79345580 100644 --- a/packages/system/metallb/charts/metallb/Chart.lock +++ b/packages/system/metallb/charts/metallb/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: crds repository: "" - version: 0.14.8 + version: 0.14.9 - name: frr-k8s repository: https://metallb.github.io/frr-k8s - version: 0.0.14 -digest: sha256:8dff488902a5b504a491bbd1a9ab0983a877ff214e163ed74106c73c939a9aa3 -generated: "2024-07-23T15:22:40.589621+03:00" + version: 0.0.16 +digest: sha256:20d9a53af12c82d35168e7524ae337341b2c7cb43e2169545185f750a718466e +generated: "2024-12-17T15:39:32.082324414+01:00" diff --git a/packages/system/metallb/charts/metallb/Chart.yaml b/packages/system/metallb/charts/metallb/Chart.yaml index a7f77b63..680ac9ba 100644 --- a/packages/system/metallb/charts/metallb/Chart.yaml +++ b/packages/system/metallb/charts/metallb/Chart.yaml @@ -1,14 +1,14 @@ apiVersion: v2 -appVersion: v0.14.8 +appVersion: v0.14.9 dependencies: - condition: crds.enabled name: crds repository: "" - version: 0.14.8 + version: 0.14.9 - condition: frrk8s.enabled name: frr-k8s repository: https://metallb.github.io/frr-k8s - version: 0.0.14 + version: 0.0.16 description: A network load-balancer implementation for Kubernetes using standard routing protocols home: https://metallb.universe.tf @@ -18,4 +18,4 @@ name: metallb sources: - https://github.com/metallb/metallb type: application -version: 0.14.8 +version: 0.14.9 diff --git a/packages/system/metallb/charts/metallb/README.md b/packages/system/metallb/charts/metallb/README.md index 202a9519..43f51ef7 100644 --- a/packages/system/metallb/charts/metallb/README.md +++ b/packages/system/metallb/charts/metallb/README.md @@ -17,7 +17,7 @@ Kubernetes: `>= 1.19.0-0` | Repository | Name | Version | |------------|------|---------| | | crds | 0.0.0 | -| https://metallb.github.io/frr-k8s | frr-k8s | 0.0.14 | +| https://metallb.github.io/frr-k8s | frr-k8s | 0.0.16 | ## Values @@ -79,17 +79,17 @@ Kubernetes: `>= 1.19.0-0` | prometheus.podMonitor.relabelings | list | `[]` | | | prometheus.prometheusRule.additionalLabels | object | `{}` | | | prometheus.prometheusRule.addressPoolExhausted.enabled | bool | `true` | | -| prometheus.prometheusRule.addressPoolExhausted.labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.addressPoolExhausted.labels.severity | string | `"critical"` | | | prometheus.prometheusRule.addressPoolUsage.enabled | bool | `true` | | | prometheus.prometheusRule.addressPoolUsage.thresholds[0].labels.severity | string | `"warning"` | | | prometheus.prometheusRule.addressPoolUsage.thresholds[0].percent | int | `75` | | | prometheus.prometheusRule.addressPoolUsage.thresholds[1].labels.severity | string | `"warning"` | | | prometheus.prometheusRule.addressPoolUsage.thresholds[1].percent | int | `85` | | -| prometheus.prometheusRule.addressPoolUsage.thresholds[2].labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[2].labels.severity | string | `"critical"` | | | prometheus.prometheusRule.addressPoolUsage.thresholds[2].percent | int | `95` | | | prometheus.prometheusRule.annotations | object | `{}` | | | prometheus.prometheusRule.bgpSessionDown.enabled | bool | `true` | | -| prometheus.prometheusRule.bgpSessionDown.labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.bgpSessionDown.labels.severity | string | `"critical"` | | | prometheus.prometheusRule.configNotLoaded.enabled | bool | `true` | | | prometheus.prometheusRule.configNotLoaded.labels.severity | string | `"warning"` | | | prometheus.prometheusRule.enabled | bool | `false` | | diff --git a/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml b/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml index 613d3182..e9fec846 100644 --- a/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml +++ b/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: v0.14.8 +appVersion: v0.14.9 description: MetalLB CRDs home: https://metallb.universe.tf icon: https://metallb.universe.tf/images/logo/metallb-white.png @@ -7,4 +7,4 @@ name: crds sources: - https://github.com/metallb/metallb type: application -version: 0.14.8 +version: 0.14.9 diff --git a/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml b/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml index 61f100ed..8f241477 100644 --- a/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml +++ b/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: bfdprofiles.metallb.io spec: group: metallb.io @@ -123,7 +123,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: bgpadvertisements.metallb.io spec: group: metallb.io @@ -329,7 +329,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: bgppeers.metallb.io spec: conversion: @@ -365,6 +365,8 @@ spec: - jsonPath: .spec.ebgpMultiHop name: Multi Hops type: string + deprecated: true + deprecationWarning: v1beta1 is deprecated, please use v1beta2 name: v1beta1 schema: openAPIV3Schema: @@ -526,15 +528,26 @@ spec: default: false description: To set if we want to disable MP BGP that will separate IPv4 and IPv6 route exchanges into distinct BGP sessions. type: boolean + dynamicASN: + description: |- + DynamicASN detects the AS number to use for the remote end of the session + without explicitly setting it via the ASN field. Limited to: + internal - if the neighbor's ASN is different than MyASN connection is denied. + external - if the neighbor's ASN is the same as MyASN the connection is denied. + ASN and DynamicASN are mutually exclusive and one of them must be specified. + enum: + - internal + - external + type: string ebgpMultiHop: description: To set if the BGPPeer is multi-hops away. Needed for FRR mode only. type: boolean enableGracefulRestart: description: |- - EnableGracefulRestart allows BGP peer to continue to forward data packets along - known routes while the routing protocol information is being restored. - This field is immutable because it requires restart of the BGP session - Supported for FRR mode only. + EnableGracefulRestart allows BGP peer to continue to forward data packets + along known routes while the routing protocol information is being + restored. This field is immutable because it requires restart of the BGP + session. Supported for FRR mode only. type: boolean x-kubernetes-validations: - message: EnableGracefulRestart cannot be changed after creation @@ -622,7 +635,9 @@ spec: type: object x-kubernetes-map-type: atomic peerASN: - description: AS number to expect from the remote end of the session. + description: |- + AS number to expect from the remote end of the session. + ASN and DynamicASN are mutually exclusive and one of them must be specified. format: int32 maximum: 4294967295 minimum: 0 @@ -649,7 +664,6 @@ spec: type: string required: - myASN - - peerASN - peerAddress type: object status: @@ -665,7 +679,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: communities.metallb.io spec: group: metallb.io @@ -730,7 +744,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: ipaddresspools.metallb.io spec: group: metallb.io @@ -940,7 +954,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: l2advertisements.metallb.io spec: group: metallb.io @@ -1120,7 +1134,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.16.3 name: servicel2statuses.metallb.io spec: group: metallb.io diff --git a/packages/system/metallb/charts/metallb/templates/controller.yaml b/packages/system/metallb/charts/metallb/templates/controller.yaml index 6129cd87..8fd9c477 100644 --- a/packages/system/metallb/charts/metallb/templates/controller.yaml +++ b/packages/system/metallb/charts/metallb/templates/controller.yaml @@ -84,7 +84,7 @@ spec: - name: METALLB_DEPLOYMENT value: {{ template "metallb.fullname" . }}-controller {{- end }} - {{- if .Values.speaker.frr.enabled }} + {{- if and .Values.speaker.enabled .Values.speaker.frr.enabled }} - name: METALLB_BGP_TYPE value: frr {{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/podmonitor.yaml b/packages/system/metallb/charts/metallb/templates/podmonitor.yaml index 93a7fd69..42de8818 100644 --- a/packages/system/metallb/charts/metallb/templates/podmonitor.yaml +++ b/packages/system/metallb/charts/metallb/templates/podmonitor.yaml @@ -36,6 +36,7 @@ spec: relabelings: {{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} {{- end }} +{{- if .Values.speaker.enabled }} --- apiVersion: monitoring.coreos.com/v1 kind: PodMonitor @@ -74,6 +75,7 @@ spec: relabelings: {{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} {{- end }} +{{- end }} --- {{- if .Values.prometheus.rbacPrometheus }} apiVersion: rbac.authorization.k8s.io/v1 diff --git a/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml b/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml index e811ef13..64e44c60 100644 --- a/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml +++ b/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml @@ -19,8 +19,8 @@ spec: {{- if .Values.prometheus.prometheusRule.staleConfig.enabled }} - alert: MetalLBStaleConfig annotations: - message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod - }} has a stale config for > 1 minute'`}} + summary: {{`'Stale config on {{ $labels.pod }}'`}} + description: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod }} has a stale config for > 1 minute'`}} expr: metallb_k8s_client_config_stale_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 1 for: 1m {{- with .Values.prometheus.prometheusRule.staleConfig.labels }} @@ -31,8 +31,8 @@ spec: {{- if .Values.prometheus.prometheusRule.configNotLoaded.enabled }} - alert: MetalLBConfigNotLoaded annotations: - message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod - }} has not loaded for > 1 minute'`}} + summary: {{`'Config on {{ $labels.pod }} has not been loaded'`}} + description: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod }} has not loaded for > 1 minute'`}} expr: metallb_k8s_client_config_loaded_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 0 for: 1m {{- with .Values.prometheus.prometheusRule.configNotLoaded.labels }} @@ -43,8 +43,8 @@ spec: {{- if .Values.prometheus.prometheusRule.addressPoolExhausted.enabled }} - alert: MetalLBAddressPoolExhausted annotations: - message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod - }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}} + summary: {{`'Exhausted address pool on {{ $labels.pod }}'`}} + description: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}} expr: metallb_allocator_addresses_in_use_total >= on(pool) metallb_allocator_addresses_total for: 1m {{- with .Values.prometheus.prometheusRule.addressPoolExhausted.labels }} @@ -57,8 +57,8 @@ spec: {{- range .Values.prometheus.prometheusRule.addressPoolUsage.thresholds }} - alert: MetalLBAddressPoolUsage{{ .percent }}Percent annotations: - message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod - }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}} + summary: {{`'Exhausted address pool on {{ $labels.pod }}'`}} + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}} expr: ( metallb_allocator_addresses_in_use_total / on(pool) metallb_allocator_addresses_total ) * 100 > {{ .percent }} {{- with .labels }} labels: @@ -69,8 +69,8 @@ spec: {{- if .Values.prometheus.prometheusRule.bgpSessionDown.enabled }} - alert: MetalLBBGPSessionDown annotations: - message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod - }} has BGP session {{ $labels.peer }} down for > 1 minute'`}} + summary: {{`'BGP session down on {{ $labels.pod }}'`}} + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod }} has BGP session {{ $labels.peer }} down for > 1 minute'`}} expr: metallb_bgp_session_up{job=~"{{ template "metallb.fullname" . }}.*"} == 0 for: 1m {{- with .Values.prometheus.prometheusRule.bgpSessionDown.labels }} diff --git a/packages/system/metallb/charts/metallb/templates/rbac.yaml b/packages/system/metallb/charts/metallb/templates/rbac.yaml index e7fc5d97..10ffbd8a 100644 --- a/packages/system/metallb/charts/metallb/templates/rbac.yaml +++ b/packages/system/metallb/charts/metallb/templates/rbac.yaml @@ -19,11 +19,11 @@ rules: resources: ["events"] verbs: ["create", "patch"] - apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + resources: ["validatingwebhookconfigurations"] resourceNames: ["metallb-webhook-configuration"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] - apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + resources: ["validatingwebhookconfigurations"] verbs: ["list", "watch"] - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] @@ -41,6 +41,7 @@ rules: resources: ["subjectaccessreviews"] verbs: ["create"] {{- end }} +{{- if .Values.speaker.enabled }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -72,7 +73,7 @@ rules: {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} - apiGroups: ["frrk8s.metallb.io"] resources: ["frrconfigurations"] - verbs: ["get", "list", "watch","create","update"] + verbs: ["get", "list", "watch","create","update","delete"] {{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 @@ -109,6 +110,7 @@ rules: - apiGroups: ["metallb.io"] resources: ["communities"] verbs: ["get", "list", "watch"] +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -117,7 +119,7 @@ metadata: namespace: {{ .Release.Namespace | quote }} labels: {{- include "metallb.labels" . | nindent 4 }} rules: -{{- if .Values.speaker.memberlist.enabled }} +{{- if and .Values.speaker.enabled .Values.speaker.memberlist.enabled }} - apiGroups: [""] resources: ["secrets"] verbs: ["create", "get", "list", "watch"] @@ -166,6 +168,7 @@ roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: {{ template "metallb.fullname" . }}:controller +{{- if .Values.speaker.enabled }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -195,6 +198,7 @@ roleRef: subjects: - kind: ServiceAccount name: {{ include "metallb.speaker.serviceAccountName" . }} +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/system/metallb/charts/metallb/templates/service-accounts.yaml b/packages/system/metallb/charts/metallb/templates/service-accounts.yaml index 9615acf3..8d92a040 100644 --- a/packages/system/metallb/charts/metallb/templates/service-accounts.yaml +++ b/packages/system/metallb/charts/metallb/templates/service-accounts.yaml @@ -13,7 +13,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} {{- end }} -{{- if .Values.speaker.serviceAccount.create }} +{{- if and .Values.speaker.enabled .Values.speaker.serviceAccount.create }} --- apiVersion: v1 kind: ServiceAccount diff --git a/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml b/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml index 8be88dd3..2a92e48a 100644 --- a/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml +++ b/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml @@ -1,4 +1,9 @@ +{{- if and .Values.prometheus.serviceMonitor.enabled .Values.prometheus.podMonitor.enabled }} +{{- fail "prometheus.serviceMonitor.enabled and prometheus.podMonitor.enabled cannot both be set" }} +{{- end }} + {{- if .Values.prometheus.serviceMonitor.enabled }} +{{- if .Values.speaker.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: @@ -89,6 +94,7 @@ spec: {{- end }} sessionAffinity: None type: ClusterIP +{{- end }} --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -97,7 +103,6 @@ metadata: namespace: {{ .Release.Namespace | quote }} labels: {{- include "metallb.labels" . | nindent 4 }} - app.kubernetes.io/component: speaker {{- if .Values.prometheus.serviceMonitor.controller.additionalLabels }} {{ toYaml .Values.prometheus.serviceMonitor.controller.additionalLabels | indent 4 }} {{- end }} diff --git a/packages/system/metallb/charts/metallb/values.yaml b/packages/system/metallb/charts/metallb/values.yaml index bc96d355..50d26bca 100644 --- a/packages/system/metallb/charts/metallb/values.yaml +++ b/packages/system/metallb/charts/metallb/values.yaml @@ -42,7 +42,7 @@ prometheus: # certificate to be used. controllerMetricsTLSSecret: "" - # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one + # prometheus doesn't have the permission to scrape all namespaces so we give it permission to scrape metallb's one rbacPrometheus: true # the service account used by prometheus @@ -64,7 +64,7 @@ prometheus: # enable support for Prometheus Operator enabled: false - # optional additionnal labels for podMonitors + # optional additional labels for podMonitors additionalLabels: {} # optional annotations for podMonitors @@ -143,7 +143,7 @@ prometheus: # enable alertmanager alerts enabled: false - # optional additionnal labels for prometheusRules + # optional additional labels for prometheusRules additionalLabels: {} # optional annotations for prometheusRules @@ -165,7 +165,7 @@ prometheus: addressPoolExhausted: enabled: true labels: - severity: alert + severity: critical addressPoolUsage: enabled: true @@ -178,13 +178,13 @@ prometheus: severity: warning - percent: 95 labels: - severity: alert + severity: critical # MetalLBBGPSessionDown bgpSessionDown: enabled: true labels: - severity: alert + severity: critical extraAlerts: [] diff --git a/packages/system/metallb/images/metallb/Dockerfile b/packages/system/metallb/images/metallb/Dockerfile new file mode 100644 index 00000000..477c3fc0 --- /dev/null +++ b/packages/system/metallb/images/metallb/Dockerfile @@ -0,0 +1,87 @@ +# syntax=docker/dockerfile:1.2 + +FROM --platform=$BUILDPLATFORM docker.io/golang:1.22.7 AS builder + +ARG VERSION +ARG GIT_COMMIT=dev +ARG GIT_BRANCH=dev +ARG TARGETARCH +ARG TARGETOS +ARG TARGETPLATFORM + +WORKDIR /go/go.universe.tf/metallb + +RUN --mount=type=cache,target=/go/pkg/mod \ + curl -sSL https://github.com/metallb/metallb/archive/refs/tags/${VERSION}.tar.gz \ + | tar -xzvf- --strip=1 + +RUN curl -sSLO https://github.com/metallb/metallb/pull/2726.diff && \ + git apply 2726.diff + +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go mod download -x + +RUN case ${TARGETPLATFORM} in \ + "linux/arm/v6") export VARIANT="6" ;; \ + "linux/arm/v7") export VARIANT="7" ;; \ + *) export VARIANT="" ;; \ + esac && \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=$VARIANT \ + go build -v -o /build/controller \ + -ldflags "-X 'go.universe.tf/metallb/internal/version.gitCommit=${GIT_COMMIT}' \ + -X 'go.universe.tf/metallb/internal/version.gitBranch=${GIT_BRANCH}'" \ + ./controller \ + && \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=$VARIANT \ + go build -v -o /build/frr-metrics \ + -ldflags "-X 'go.universe.tf/metallb/internal/version.gitCommit=${GIT_COMMIT}' \ + -X 'go.universe.tf/metallb/internal/version.gitBranch=${GIT_BRANCH}'" \ + frr-tools/metrics/exporter.go \ + && \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=$VARIANT \ + go build -v -o /build/cp-tool \ + -ldflags "-X 'go.universe.tf/metallb/internal/version.gitCommit=${GIT_COMMIT}' \ + -X 'go.universe.tf/metallb/internal/version.gitBranch=${GIT_BRANCH}'" \ + frr-tools/cp-tool/cp-tool.go \ + && \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=$VARIANT \ + go build -v -o /build/speaker \ + -ldflags "-X 'go.universe.tf/metallb/internal/version.gitCommit=${GIT_COMMIT}' \ + -X 'go.universe.tf/metallb/internal/version.gitBranch=${GIT_BRANCH}'" \ + ./speaker + +FROM gcr.io/distroless/static:latest as controller + +COPY --from=builder /build/controller /controller + +LABEL org.opencontainers.image.authors="metallb" \ + org.opencontainers.image.url="https://github.com/metallb/metallb" \ + org.opencontainers.image.documentation="https://metallb.universe.tf" \ + org.opencontainers.image.source="https://github.com/cozystack/cozystack" \ + org.opencontainers.image.vendor="metallb" \ + org.opencontainers.image.licenses="Apache-2.0" \ + org.opencontainers.image.description="Metallb Controller" \ + org.opencontainers.image.title="controller" \ + org.opencontainers.image.base.name="gcr.io/distroless/static:latest" + +ENTRYPOINT ["/controller"] + +FROM gcr.io/distroless/static:latest as speaker + +COPY --from=builder /build/cp-tool /cp-tool +COPY --from=builder /build/speaker /speaker +COPY --from=builder /build/frr-metrics /frr-metrics +COPY --from=builder /go/go.universe.tf/metallb/frr-tools/reloader/frr-reloader.sh /frr-reloader.sh + +LABEL org.opencontainers.image.authors="metallb" \ + org.opencontainers.image.url="https://github.com/metallb/metallb" \ + org.opencontainers.image.documentation="https://metallb.universe.tf" \ + org.opencontainers.image.source="https://github.com/cozystack/cozystack" \ + org.opencontainers.image.vendor="metallb" \ + org.opencontainers.image.licenses="Apache-2.0" \ + org.opencontainers.image.description="Metallb speaker" \ + org.opencontainers.image.title="speaker" \ + org.opencontainers.image.base.name="gcr.io/distroless/static:latest" + +ENTRYPOINT ["/speaker"] diff --git a/packages/system/metallb/values.yaml b/packages/system/metallb/values.yaml index 737f17cf..04c3a710 100644 --- a/packages/system/metallb/values.yaml +++ b/packages/system/metallb/values.yaml @@ -2,5 +2,12 @@ metallb: crds: enabled: true - #speaker: - # tolerateMaster: false + controller: + image: + repository: ghcr.io/cozystack/cozystack/metallb/controller + tag: v0.14.9@sha256:c86418d1072d6037341d731917d11a2f281fb17559d5bb650962512f9894fd50 + + speaker: + image: + repository: ghcr.io/cozystack/cozystack/metallb/speaker + tag: v0.14.9@sha256:60fddc8fd6c125180186db31990993b4ebea5023ad410bf08ca9537a956e8279 From 5e0b0167fcd3c0d8c68c89bc4fa13f4cef19b0b4 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 16 May 2025 16:24:45 +0200 Subject: [PATCH 087/120] [kubernetes] fix regression: return port specification Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/templates/cluster.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 1b2f395c..9aa16816 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -150,7 +150,7 @@ spec: ingress: extraAnnotations: nginx.ingress.kubernetes.io/ssl-passthrough: "true" - hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name $host) }} + hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name $host) }}:443 className: "{{ $ingress }}" deployment: podAdditionalMetadata: From 115497b73f39567ac9fdd1192f7f3ed47a91e794 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Sat, 17 May 2025 12:31:57 +0200 Subject: [PATCH 088/120] [ingress] avoid invalid externalIPs when config value is empty Signed-off-by: Andrei Kvapil --- packages/extra/ingress/templates/nginx-ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 88d98b74..50829605 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -34,7 +34,7 @@ spec: enabled: false {{- end }} service: - {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} + {{- if and (ne $exposeExternalIPs "") (eq $exposeIngress .Release.Namespace) }} externalIPs: {{- toYaml (splitList "," $exposeExternalIPs) | nindent 12 }} type: ClusterIP From b4da00f96f8b11afdec23ab79cdbc4bab69d8b90 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Sat, 17 May 2025 13:28:31 +0200 Subject: [PATCH 089/120] Revert "[ingress] avoid invalid externalIPs when config value is empty" --- packages/extra/ingress/templates/nginx-ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 50829605..88d98b74 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -34,7 +34,7 @@ spec: enabled: false {{- end }} service: - {{- if and (ne $exposeExternalIPs "") (eq $exposeIngress .Release.Namespace) }} + {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} externalIPs: {{- toYaml (splitList "," $exposeExternalIPs) | nindent 12 }} type: ClusterIP From 9698f3c9f4cb07ce9df509928fde4fde80c4cc03 Mon Sep 17 00:00:00 2001 From: Ahmad Murzahmatov Date: Mon, 19 May 2025 20:06:53 +0600 Subject: [PATCH 090/120] commit 7a7512da308eeb8559577bb9f901bebf04f29269 removed genisoimage package installation from Dockerfile which leds to test fail due to the fact that genisoimage is missing and runner enable to create image. issue reference - https://github.com/cozystack/cozystack/actions/runs/15084476654/job/42406141954. restored genisoimage package installation in Dockerfile Signed-off-by: Ahmad Murzahmatov --- packages/core/testing/images/e2e-sandbox/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/testing/images/e2e-sandbox/Dockerfile b/packages/core/testing/images/e2e-sandbox/Dockerfile index 3b25dfc6..9d948e7c 100755 --- a/packages/core/testing/images/e2e-sandbox/Dockerfile +++ b/packages/core/testing/images/e2e-sandbox/Dockerfile @@ -8,7 +8,7 @@ ARG TARGETOS ARG TARGETARCH RUN apt update -q -RUN apt install -yq --no-install-recommends ca-certificates qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git +RUN apt install -yq --no-install-recommends genisoimage ca-certificates qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git RUN curl -sSL "https://github.com/siderolabs/talos/releases/download/v${TALOSCTL_VERSION}/talosctl-${TARGETOS}-${TARGETARCH}" -o /usr/local/bin/talosctl \ && chmod +x /usr/local/bin/talosctl RUN curl -sSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" -o /usr/local/bin/kubectl \ From b753fd9fa8008d405491a84c75160256142332b1 Mon Sep 17 00:00:00 2001 From: kklinch0 Date: Tue, 20 May 2025 13:09:44 +0300 Subject: [PATCH 091/120] (air gapped): disable fluxcd artifact by default Signed-off-by: kklinch0 --- packages/system/fluxcd/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/system/fluxcd/values.yaml b/packages/system/fluxcd/values.yaml index 6318ebee..9eea6c6a 100644 --- a/packages/system/fluxcd/values.yaml +++ b/packages/system/fluxcd/values.yaml @@ -4,6 +4,7 @@ flux-instance: networkPolicy: true domain: cozy.local # -- default value is overriden in patches distribution: + artifact: "" version: 2.5.x registry: ghcr.io/fluxcd components: From 56bdaae2c9a4be1b139de262ba8926f2b2cbeaa2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 21 May 2025 11:52:29 +0000 Subject: [PATCH 092/120] Prepare release v0.31.0-rc.2 Signed-off-by: github-actions --- packages/apps/clickhouse/images/clickhouse-backup.tag | 2 +- packages/apps/ferretdb/images/postgres-backup.tag | 2 +- packages/apps/http-cache/images/nginx-cache.tag | 2 +- packages/apps/kubernetes/images/cluster-autoscaler.tag | 2 +- .../apps/kubernetes/images/kubevirt-cloud-provider.tag | 2 +- .../apps/kubernetes/images/kubevirt-csi-driver.tag | 2 +- .../apps/kubernetes/images/ubuntu-container-disk.tag | 2 +- packages/apps/mysql/images/mariadb-backup.tag | 2 +- packages/apps/postgres/images/postgres-backup.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/extra/monitoring/images/grafana.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 4 ++-- .../charts/kubeapps/templates/dashboard/configmap.yaml | 2 +- packages/system/dashboard/values.yaml | 6 +++--- packages/system/kamaji/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- packages/system/kubeovn/values.yaml | 2 +- packages/system/metallb/values.yaml | 10 ++++------ 22 files changed, 28 insertions(+), 30 deletions(-) diff --git a/packages/apps/clickhouse/images/clickhouse-backup.tag b/packages/apps/clickhouse/images/clickhouse-backup.tag index 82eb1df5..05e456bb 100644 --- a/packages/apps/clickhouse/images/clickhouse-backup.tag +++ b/packages/apps/clickhouse/images/clickhouse-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/clickhouse-backup:0.7.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205 +ghcr.io/cozystack/cozystack/clickhouse-backup:0.8.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205 diff --git a/packages/apps/ferretdb/images/postgres-backup.tag b/packages/apps/ferretdb/images/postgres-backup.tag index b3bee261..e47315f2 100644 --- a/packages/apps/ferretdb/images/postgres-backup.tag +++ b/packages/apps/ferretdb/images/postgres-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/postgres-backup:0.10.1@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f +ghcr.io/cozystack/cozystack/postgres-backup:0.11.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index 74a2d1cc..403fae84 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.4.0@sha256:4e1f5153d2673a399b315252238f4dc3eb5d6c59295aef594691710cc5b72eb4 +ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:785bd69cb593dc1509875d1e3128dac1a013b099fbb02f39330298d798706a0e diff --git a/packages/apps/kubernetes/images/cluster-autoscaler.tag b/packages/apps/kubernetes/images/cluster-autoscaler.tag index 10efdc06..df0570b6 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler.tag +++ b/packages/apps/kubernetes/images/cluster-autoscaler.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/cluster-autoscaler:0.19.0@sha256:85371c6aabf5a7fea2214556deac930c600e362f92673464fe2443784e2869c3 +ghcr.io/cozystack/cozystack/cluster-autoscaler:0.20.0@sha256:8dbbe95fe8b933a1d1a3c638120f386fec0c4950092d3be5ddd592375bb8a760 diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index edf89c8d..4a7d00d5 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.19.0@sha256:795d8e1ef4b2b0df2aa1e09d96cd13476ebb545b4bf4b5779b7547a70ef64cf9 +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.0@sha256:41fcdbd2f667f68bf554dd184ce362e65b88f350dc7b938c86079b719f5e5099 diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 0e421b76..fe5d6308 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.19.0@sha256:5717919c75e609902c6d67138311a2a8fd07be822e2173f3802b67cf5f3486e9 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.0@sha256:61580fea56b745580989d85e3ef2563e9bb1accc9c4185f8e636bacd02551319 diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag index 137cd52e..3622c20f 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk.tag +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:4a4f8bee150e04d1efcd5ff1ea83e12f495a98851cc5fd47ef41ac7aebce9b74 +ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:186af6f71891bfc6d6948454802c08922baa508c30e7f79e330b7d26ffceff03 diff --git a/packages/apps/mysql/images/mariadb-backup.tag b/packages/apps/mysql/images/mariadb-backup.tag index ad22d940..90a9bb59 100644 --- a/packages/apps/mysql/images/mariadb-backup.tag +++ b/packages/apps/mysql/images/mariadb-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/mariadb-backup:0.6.0@sha256:cfd1c37d8ad24e10681d82d6e6ce8a641b4602c1b0ffa8516ae15b4958bb12d4 +ghcr.io/cozystack/cozystack/mariadb-backup:0.7.0@sha256:cfd1c37d8ad24e10681d82d6e6ce8a641b4602c1b0ffa8516ae15b4958bb12d4 diff --git a/packages/apps/postgres/images/postgres-backup.tag b/packages/apps/postgres/images/postgres-backup.tag index b3bee261..e47315f2 100644 --- a/packages/apps/postgres/images/postgres-backup.tag +++ b/packages/apps/postgres/images/postgres-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/postgres-backup:0.10.1@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f +ghcr.io/cozystack/cozystack/postgres-backup:0.11.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index acd4a38e..9343532b 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.1@sha256:ab0e8fd97632ba784a42a3d0714806ea327440f82ffa5c4896a87c5fb7c1ec6e + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.2@sha256:05d812a6ac1df86c614b528e8d171af05c0080545ceee383d6cb043f415a4372 diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 67c70250..d087c964 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.1@sha256:a20a6834527ccfc8daf7413a15234f3f7dbbd7774810c8e1966736d487ef7d0c + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.2@sha256:2d35b2cce2f093c5c3145a08d9981e2bf28cf45a6804117d50bd6345a15ecd1a diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index 709d0d2b..777d572e 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.1@sha256:de69166fd6efec988cad7ad5be41bbb57c8134508c531d7496fc7f15772e4993 +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.2@sha256:78e5a28badd3c804e55e5c1376f12dad77e04b9f6f80637596939ba348f7104b diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag index 3a68139d..73fca310 100644 --- a/packages/extra/monitoring/images/grafana.tag +++ b/packages/extra/monitoring/images/grafana.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:66c4547efd18b4d7475ff73b2c4e2f39e9b4471d55e85237e2fe3e87af05c302 +ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399 diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 8fc97610..72ba28b3 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:67e4a5da0ab43d93e8b75094d5a2db8159cb927a47b94f945f80d0ffb93d3301 +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:a219040fed290492f047818e5c5a864a30112ff418ad4b12b24de9709302427a diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index 23763428..4240b0ac 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.1@sha256:1dd9f3ec9d5630d5b49ffe9380d6a0131bf04e7e9bddcc3fd6f59089c6563b1c + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.2@sha256:d3794a5ebd49ee28ef7108213d3bb5053f5247ef62855f4731c7cafb8059a635 diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 8e778250..1362175f 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.1@sha256:96492f384c07619c091764c759adde6ef91054b1223f03f7ddd62a56c40b06ac + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.2@sha256:fb7cfdf62a128103954f0cb711b2d21650c0d2f7ff639d41a56f68d454a1e4ea debug: false disableTelemetry: false - cozystackVersion: "v0.31.0-rc.1" + cozystackVersion: "v0.31.0-rc.2" diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml index d591dfa0..17b7263e 100644 --- a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml @@ -76,7 +76,7 @@ data: "kubeappsNamespace": {{ .Release.Namespace | quote }}, "helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }}, "carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }}, - "appVersion": "v0.31.0-rc.1", + "appVersion": "v0.31.0-rc.2", "authProxyEnabled": {{ .Values.authProxy.enabled }}, "oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }}, "oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }}, diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index a7103fc4..0342b829 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -19,7 +19,7 @@ kubeapps: image: registry: ghcr.io/cozystack/cozystack repository: dashboard - tag: v0.31.0-rc.1 + tag: v0.31.0-rc.2 digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93" redis: master: @@ -35,8 +35,8 @@ kubeapps: image: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis - tag: v0.31.0-rc.1 - digest: "sha256:ca65949e84c9a92436f47525ae92861984406644779cbb2ecdb8e2a1a133fabf" + tag: v0.31.0-rc.2 + digest: "sha256:db4f33e9ca6969459c9baf0131c2c342cb6c366df16df7361e7cbdeb4a854cea" pluginConfig: flux: packages: diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index f28c1408..b278fc6d 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,7 +3,7 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: latest@sha256:f6a33408df8d3c4223005392bcd8bae9d8c02fd73e2540bbaa911dedb7880ea8 + tag: v0.31.0-rc.2@sha256:beb066f5c45cda520e5028222ec26a5e39c2c3c63bc9016e8a6ec49a2379e00c repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 35f6fd3b..8b86e18e 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.1@sha256:fa14fa7a0ffa628eb079ddcf6ce41d75b43de92e50f489422f8fb15c4dab2dbf +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.2@sha256:f9b464a94bd1a1fa116bbf77c4bbece3931d03dac1489eb820f94d98176ed5c9 diff --git a/packages/system/kubeovn/values.yaml b/packages/system/kubeovn/values.yaml index 68044bab..c9283b54 100644 --- a/packages/system/kubeovn/values.yaml +++ b/packages/system/kubeovn/values.yaml @@ -22,4 +22,4 @@ global: images: kubeovn: repository: kubeovn - tag: v1.13.10@sha256:cc490d549353e2ee432568eb32631f8213e0f208193594b2f59de312607c9782 + tag: v1.13.11@sha256:bbae091631c3ac6dbdd346c19187322211a9afe397566f601393a2cb338b5aeb diff --git a/packages/system/metallb/values.yaml b/packages/system/metallb/values.yaml index 04c3a710..3fb0a10f 100644 --- a/packages/system/metallb/values.yaml +++ b/packages/system/metallb/values.yaml @@ -1,13 +1,11 @@ metallb: crds: enabled: true - controller: image: - repository: ghcr.io/cozystack/cozystack/metallb/controller - tag: v0.14.9@sha256:c86418d1072d6037341d731917d11a2f281fb17559d5bb650962512f9894fd50 - + repository: ghcr.io/cozystack/cozystack/metallb-controller + tag: v0.14.9@sha256:73c3156d913a2ff15a26ca42fcbeee6fa115602bcdb78870dcfab9359acd9cb3 speaker: image: - repository: ghcr.io/cozystack/cozystack/metallb/speaker - tag: v0.14.9@sha256:60fddc8fd6c125180186db31990993b4ebea5023ad410bf08ca9537a956e8279 + repository: ghcr.io/cozystack/cozystack/metallb-speaker + tag: v0.14.9@sha256:9af9f0a6922784f066653f2c0d940d5f2de7ffea132d2df488457b61465b7716 From 893818f64e4c64718c9e0b723fec7a6b36a0edea Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Tue, 20 May 2025 14:48:05 +0300 Subject: [PATCH 093/120] [docs] Add Release Notes from v0.31.0-RC.1 Add to v0.31.0.md, as we're acuumulating changelogs until a stable release. See https://github.com/cozystack/cozystack/blob/main/docs/release.md#release-candidates Signed-off-by: Nick Volynkin --- docs/changelogs/v0.31.0.md | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/changelogs/v0.31.0.md diff --git a/docs/changelogs/v0.31.0.md b/docs/changelogs/v0.31.0.md new file mode 100644 index 00000000..2bc21f15 --- /dev/null +++ b/docs/changelogs/v0.31.0.md @@ -0,0 +1,68 @@ +This is the first release candidate for the upcoming Cozystack v0.31.0 release. Starting with a release candidate is one of multiple steps to implementing a new release policy that takes a more thorough approach to release stability. + +Cozystack 0.31.0 further advances GPU support, monitoring, and all-around convenience features. + +## New Features and Changes + +* [kubernetes] Introduce GPU support for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/834) +* Add VerticalPodAutoscaler to a few more components: + * [kubernetes] Kubernetes clusters in user tenants. (@klinch0 in https://github.com/cozystack/cozystack/pull/806) + * [platform] Cozystack dashboard. (@klinch0 in https://github.com/cozystack/cozystack/pull/828) + * [platform] Cozystack etcd-operator (@klinch0 in https://github.com/cozystack/cozystack/pull/850) +* [kubevirt] Enable exporting VMs. (@kvaps in https://github.com/cozystack/cozystack/pull/808) +* [cozystack-controller] Record the IP address pool and storage class in Workload objects. (@lllamnyp in https://github.com/cozystack/cozystack/pull/831) +* Update the Cozystack release policy to include long-lived release branches and start with release candidates. Update CI workflows and docs accordingly. + * Use release branches `release-X.Y` for gathering and releasing fixes after initial `vX.Y.0` release. (@kvaps in https://github.com/cozystack/cozystack/pull/816) + * Automatically create release branches after initial `vX.Y.0` release is published. (@kvaps in https://github.com/cozystack/cozystack/pull/886) + * Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890) + * Commit changes in release pipelines under `github-actions `. (@kvaps in https://github.com/cozystack/cozystack/pull/823) + * Describe the Cozystack release workflow. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/817 and https://github.com/cozystack/cozystack/pull/897) + +## Fixes + +* [virtual-machine] Add GPU names to the virtual machine specifications. (@kvaps in https://github.com/cozystack/cozystack/pull/862) +* [platform] Fix installing HelmReleases on initial setup. (@kvaps in https://github.com/cozystack/cozystack/pull/833) +* [platform] Migration scripts update Kubernetes ConfigMap with the current stack version for improved version tracking. (@klinch0 in https://github.com/cozystack/cozystack/pull/840) +* [platform] Reduce requested CPU and RAM for the `kamaji` provider. (@klinch0 in https://github.com/cozystack/cozystack/pull/825) +* [platform] Improve the reconciliation loop for the Cozystack system HelmReleases logic. (@klinch0 in https://github.com/cozystack/cozystack/pull/809 and https://github.com/cozystack/cozystack/pull/810, @kvaps in https://github.com/cozystack/cozystack/pull/811) +* [kubernetes] Update garbage collection of HelmReleases in tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/835) +* [kubernetes] Fix merging `valuesOverride` for tenant clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/879) +* [kubernetes] Fix `ubuntu-container-disk` tag. (@kvaps in https://github.com/cozystack/cozystack/pull/887) +* [kubernetes] Refactor Helm manifests for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/866) +* [tenant] Fix an issue with accessing external IPs of a cluster from the cluster itself. (@kvaps in https://github.com/cozystack/cozystack/pull/854) +* [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867) +* [monitoring] Remove legacy label "POD" from the exclude filter in metrics. (@xy2 in https://github.com/cozystack/cozystack/pull/826) +* [monitoring] Refactor management etcd monitoring config. Introduce a migration script for updating monitoring resources (`kube-rbac-proxy` daemonset). (@lllamnyp in https://github.com/cozystack/cozystack/pull/799 and https://github.com/cozystack/cozystack/pull/830) +* [monitoring] Fix VerticalPodAutoscaler resource allocation for VMagent. (@klinch0 in https://github.com/cozystack/cozystack/pull/820) +* [postgres] Remove duplicated `template` entry from backup manifest. (@etoshutka in https://github.com/cozystack/cozystack/pull/872) +* [kube-ovn] Fix versions mapping in Makefile. (@kvaps in https://github.com/cozystack/cozystack/pull/883) +* [dx] Automatically detect version for migrations in the installer.sh. (@kvaps in https://github.com/cozystack/cozystack/pull/837) +* [e2e] Increase timeout durations for `capi` and `keycloak` to improve reliability during environment setup. (@kvaps in https://github.com/cozystack/cozystack/pull/858) +* [e2e] Fix `device_ownership_from_security_context` CRI. (@dtrdnk in https://github.com/cozystack/cozystack/pull/896) +* [ci] Improve the check for `versions_map` running on pull requests. (@kvaps and @klinch0 in https://github.com/cozystack/cozystack/pull/836, https://github.com/cozystack/cozystack/pull/842, and https://github.com/cozystack/cozystack/pull/845) +* [ci] If the release step was skipped on a tag, skip tests as well. (@kvaps in https://github.com/cozystack/cozystack/pull/822) +* [ci] Allow CI to cancel the previous job if a new one is scheduled. (@kvaps in https://github.com/cozystack/cozystack/pull/873) +* [ci] Use the correct version name when uploading build assets to the release page. (@kvaps in https://github.com/cozystack/cozystack/pull/876) +* [ci] Stop using `ok-to-test` label to trigger CI in pull requests. (@kvaps in https://github.com/cozystack/cozystack/pull/875) +* [ci] Do not run tests in the release building pipeline. (@kvaps in https://github.com/cozystack/cozystack/pull/882) +* [ci] Fix release branch creation. (@kvaps in https://github.com/cozystack/cozystack/pull/884) +* [ci, dx] Reduce noise in the test logs by suppressing the `wget` progress bar. (@lllamnyp in https://github.com/cozystack/cozystack/pull/865) + +## Dependencies +* Update Cilium to v1.17.3. (@kvaps in https://github.com/cozystack/cozystack/pull/848) +* Update LINSTOR to v1.31.0. (@kvaps in https://github.com/cozystack/cozystack/pull/846) +* Update Kube-OVN to v1.13.10. (@kvaps in https://github.com/cozystack/cozystack/pull/847) +* Update tenant Kubernetes to v1.32. (@kvaps in https://github.com/cozystack/cozystack/pull/871) +* Update flux-operator to 0.19.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880) +* Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867) + +## Maintenance + +* Add @klinch0 to CODEOWNERS. (@kvaps in https://github.com/cozystack/cozystack/pull/838) + +## New Contributors + +* @etoshutka made their first contribution in https://github.com/cozystack/cozystack/pull/872 +* @dtrdnk made their first contribution in https://github.com/cozystack/cozystack/pull/896 + +**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.1 From 013e1936ecc03f8cddaf7323b68d7f927433d12a Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Tue, 20 May 2025 15:32:06 +0300 Subject: [PATCH 094/120] [docs] Update changelogs for v0.31.0-RC.2 Add the changes accumulated since RC.1 to the changelog. Signed-off-by: Nick Volynkin --- docs/changelogs/v0.31.0.md | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/docs/changelogs/v0.31.0.md b/docs/changelogs/v0.31.0.md index 2bc21f15..dedf9d4e 100644 --- a/docs/changelogs/v0.31.0.md +++ b/docs/changelogs/v0.31.0.md @@ -1,4 +1,5 @@ -This is the first release candidate for the upcoming Cozystack v0.31.0 release. Starting with a release candidate is one of multiple steps to implementing a new release policy that takes a more thorough approach to release stability. +This is the second release candidate for the upcoming Cozystack v0.31.0 release. +The release notes show changes accumulated since the release of Cozystack v0.30.0. Cozystack 0.31.0 further advances GPU support, monitoring, and all-around convenience features. @@ -9,28 +10,40 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [kubernetes] Kubernetes clusters in user tenants. (@klinch0 in https://github.com/cozystack/cozystack/pull/806) * [platform] Cozystack dashboard. (@klinch0 in https://github.com/cozystack/cozystack/pull/828) * [platform] Cozystack etcd-operator (@klinch0 in https://github.com/cozystack/cozystack/pull/850) +* Introduce support for cross-architecture builds and Cozystack on ARM: + * [build] Refactor Makefiles introducing build variables. (@nbykov0 in https://github.com/cozystack/cozystack/pull/907) + * [build] Add support for multi-architecture and cross-platform image builds. (@nbykov0 in https://github.com/cozystack/cozystack/pull/932) +* [platform] Introduce a new controller to synchronize tenant HelmReleases and propagate configuration changes. (@klinch0 in https://github.com/cozystack/cozystack/pull/870) +* [platform] Introduce options `expose-services`, `expose-ingress` and `expose-external-ips` to the ingress service. (@kvaps in https://github.com/cozystack/cozystack/pull/929) * [kubevirt] Enable exporting VMs. (@kvaps in https://github.com/cozystack/cozystack/pull/808) +* [kubevirt] Make KubeVirt's CPU allocation ratio configurable. (@lllamnyp in https://github.com/cozystack/cozystack/pull/905) * [cozystack-controller] Record the IP address pool and storage class in Workload objects. (@lllamnyp in https://github.com/cozystack/cozystack/pull/831) +* [cilium] Enable Cilium Gateway API. (@zdenekjanda in https://github.com/cozystack/cozystack/pull/924) +* [cilium] Enable user-added parameters in a tenant cluster Cilium. (@lllamnyp in https://github.com/cozystack/cozystack/pull/917) * Update the Cozystack release policy to include long-lived release branches and start with release candidates. Update CI workflows and docs accordingly. * Use release branches `release-X.Y` for gathering and releasing fixes after initial `vX.Y.0` release. (@kvaps in https://github.com/cozystack/cozystack/pull/816) * Automatically create release branches after initial `vX.Y.0` release is published. (@kvaps in https://github.com/cozystack/cozystack/pull/886) - * Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890) + * Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841 and https://github.com/cozystack/cozystack/pull/901, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890) * Commit changes in release pipelines under `github-actions `. (@kvaps in https://github.com/cozystack/cozystack/pull/823) * Describe the Cozystack release workflow. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/817 and https://github.com/cozystack/cozystack/pull/897) ## Fixes * [virtual-machine] Add GPU names to the virtual machine specifications. (@kvaps in https://github.com/cozystack/cozystack/pull/862) +* [virtual-machine] Count Workload resources for pods by requests, not limits. Other improvements to VM resource tracking. (@lllamnyp in https://github.com/cozystack/cozystack/pull/904) * [platform] Fix installing HelmReleases on initial setup. (@kvaps in https://github.com/cozystack/cozystack/pull/833) * [platform] Migration scripts update Kubernetes ConfigMap with the current stack version for improved version tracking. (@klinch0 in https://github.com/cozystack/cozystack/pull/840) * [platform] Reduce requested CPU and RAM for the `kamaji` provider. (@klinch0 in https://github.com/cozystack/cozystack/pull/825) * [platform] Improve the reconciliation loop for the Cozystack system HelmReleases logic. (@klinch0 in https://github.com/cozystack/cozystack/pull/809 and https://github.com/cozystack/cozystack/pull/810, @kvaps in https://github.com/cozystack/cozystack/pull/811) +* [platform] Remove extra dependencies for the Piraeus operator. (@klinch0 in https://github.com/cozystack/cozystack/pull/856) +* [platform] Refactor dashboard values. (@kvaps in https://github.com/cozystack/cozystack/pull/928, patched by @llamnyp in https://github.com/cozystack/cozystack/pull/952) +* [platform] Make FluxCD artifact disabled by default. (@klinch0 in https://github.com/cozystack/cozystack/pull/964) * [kubernetes] Update garbage collection of HelmReleases in tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/835) * [kubernetes] Fix merging `valuesOverride` for tenant clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/879) * [kubernetes] Fix `ubuntu-container-disk` tag. (@kvaps in https://github.com/cozystack/cozystack/pull/887) * [kubernetes] Refactor Helm manifests for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/866) * [tenant] Fix an issue with accessing external IPs of a cluster from the cluster itself. (@kvaps in https://github.com/cozystack/cozystack/pull/854) -* [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867) +* [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867, patched in https://github.com/cozystack/cozystack/pull/956) * [monitoring] Remove legacy label "POD" from the exclude filter in metrics. (@xy2 in https://github.com/cozystack/cozystack/pull/826) * [monitoring] Refactor management etcd monitoring config. Introduce a migration script for updating monitoring resources (`kube-rbac-proxy` daemonset). (@lllamnyp in https://github.com/cozystack/cozystack/pull/799 and https://github.com/cozystack/cozystack/pull/830) * [monitoring] Fix VerticalPodAutoscaler resource allocation for VMagent. (@klinch0 in https://github.com/cozystack/cozystack/pull/820) @@ -39,6 +52,7 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [dx] Automatically detect version for migrations in the installer.sh. (@kvaps in https://github.com/cozystack/cozystack/pull/837) * [e2e] Increase timeout durations for `capi` and `keycloak` to improve reliability during environment setup. (@kvaps in https://github.com/cozystack/cozystack/pull/858) * [e2e] Fix `device_ownership_from_security_context` CRI. (@dtrdnk in https://github.com/cozystack/cozystack/pull/896) +* [e2e] Return `genisoimage` to the e2e-test Dockerfile (@gwynbleidd2106 in https://github.com/cozystack/cozystack/pull/962) * [ci] Improve the check for `versions_map` running on pull requests. (@kvaps and @klinch0 in https://github.com/cozystack/cozystack/pull/836, https://github.com/cozystack/cozystack/pull/842, and https://github.com/cozystack/cozystack/pull/845) * [ci] If the release step was skipped on a tag, skip tests as well. (@kvaps in https://github.com/cozystack/cozystack/pull/822) * [ci] Allow CI to cancel the previous job if a new one is scheduled. (@kvaps in https://github.com/cozystack/cozystack/pull/873) @@ -47,14 +61,20 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [ci] Do not run tests in the release building pipeline. (@kvaps in https://github.com/cozystack/cozystack/pull/882) * [ci] Fix release branch creation. (@kvaps in https://github.com/cozystack/cozystack/pull/884) * [ci, dx] Reduce noise in the test logs by suppressing the `wget` progress bar. (@lllamnyp in https://github.com/cozystack/cozystack/pull/865) +* [ci] Revert "automatically trigger tests in releasing PR". (@kvaps in https://github.com/cozystack/cozystack/pull/900) ## Dependencies + +* MetalLB s now included directly as a patched image based on version 0.14.9. (@lllamnyp in https://github.com/cozystack/cozystack/pull/945) +* Update Kubernetes to v1.32.4. (@kvaps in https://github.com/cozystack/cozystack/pull/949) +* Update Talos Linux to v1.10.1. (@kvaps in https://github.com/cozystack/cozystack/pull/931) * Update Cilium to v1.17.3. (@kvaps in https://github.com/cozystack/cozystack/pull/848) * Update LINSTOR to v1.31.0. (@kvaps in https://github.com/cozystack/cozystack/pull/846) -* Update Kube-OVN to v1.13.10. (@kvaps in https://github.com/cozystack/cozystack/pull/847) +* Update Kube-OVN to v1.13.11. (@kvaps in https://github.com/cozystack/cozystack/pull/847, @lllamnyp in https://github.com/cozystack/cozystack/pull/922) * Update tenant Kubernetes to v1.32. (@kvaps in https://github.com/cozystack/cozystack/pull/871) -* Update flux-operator to 0.19.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880) -* Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867) +* Update flux-operator to 0.20.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880 and https://github.com/cozystack/cozystack/pull/934) +* Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867 and https://github.com/cozystack/cozystack/pull/947) +* Update KamajiControlPlane to edge-25.4.1. (@kvaps in https://github.com/cozystack/cozystack/pull/953) ## Maintenance @@ -64,5 +84,7 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * @etoshutka made their first contribution in https://github.com/cozystack/cozystack/pull/872 * @dtrdnk made their first contribution in https://github.com/cozystack/cozystack/pull/896 +* @zdenekjanda made their first contribution in https://github.com/cozystack/cozystack/pull/924 +* @gwynbleidd2106 made their first contribution in https://github.com/cozystack/cozystack/pull/962 -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.1 +**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.2 From 5407ee01ee45ddd3acba97ea0c829ecb33f299c3 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Thu, 22 May 2025 02:48:21 +0300 Subject: [PATCH 095/120] system/metallb: multiarch support Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/metallb/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/system/metallb/Makefile b/packages/system/metallb/Makefile index 1cef5576..fbc3dfa0 100644 --- a/packages/system/metallb/Makefile +++ b/packages/system/metallb/Makefile @@ -16,6 +16,8 @@ image-controller image-speaker: $(eval VERSION := $(shell yq '.appVersion' charts/metallb/Chart.yaml)) docker buildx build images/metallb \ --provenance false \ + --builder=$(BUILDER) \ + --platform=$(PLATFORM) \ --target $(TARGET) \ --build-arg VERSION=$(VERSION) \ --tag $(REGISTRY)/metallb-$(TARGET):$(VERSION) \ @@ -23,8 +25,8 @@ image-controller image-speaker: --cache-to type=inline \ --metadata-file images/$(TARGET).json \ --push=$(PUSH) \ - --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" - --load=1 + --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \ + --load=$(LOAD) REPOSITORY="$(REGISTRY)/metallb-$(TARGET)" \ yq -i '.metallb.$(TARGET).image.repository = strenv(REPOSITORY)' values.yaml TAG=$(VERSION)@$$(yq e '."containerimage.digest"' images/$(TARGET).json -o json -r) \ From bca27dcfdcebdaa7d594083b715f727b5dccea23 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 22 May 2025 11:55:21 +0200 Subject: [PATCH 096/120] [virtual-machine] Add support for various storages Signed-off-by: Andrei Kvapil --- packages/apps/versions_map | 3 ++- packages/apps/virtual-machine/Chart.yaml | 4 ++-- packages/apps/virtual-machine/templates/vm.yaml | 5 +---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/apps/versions_map b/packages/apps/versions_map index 89d9990d..a34bb2aa 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -157,7 +157,8 @@ virtual-machine 0.8.0 3fa4dd3a virtual-machine 0.8.1 93c46161 virtual-machine 0.8.2 de19450f virtual-machine 0.9.0 721c12a7 -virtual-machine 0.9.1 HEAD +virtual-machine 0.9.1 93bdf411 +virtual-machine 0.9.2 HEAD vm-disk 0.1.0 d971f2ff vm-disk 0.1.1 HEAD vm-instance 0.1.0 1ec10165 diff --git a/packages/apps/virtual-machine/Chart.yaml b/packages/apps/virtual-machine/Chart.yaml index 225f9c24..87358d5b 100644 --- a/packages/apps/virtual-machine/Chart.yaml +++ b/packages/apps/virtual-machine/Chart.yaml @@ -17,10 +17,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.9.1 +version: 0.9.2 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.9.0 +appVersion: 0.9.2 diff --git a/packages/apps/virtual-machine/templates/vm.yaml b/packages/apps/virtual-machine/templates/vm.yaml index 21c07c3a..1d94799b 100644 --- a/packages/apps/virtual-machine/templates/vm.yaml +++ b/packages/apps/virtual-machine/templates/vm.yaml @@ -27,10 +27,7 @@ spec: - metadata: name: {{ include "virtual-machine.fullname" . }} spec: - pvc: - volumeMode: Block - accessModes: - - ReadWriteMany + storage: resources: requests: storage: {{ .Values.systemDisk.storage | quote }} From 1dccf9650634e9ea0672fce3bb221ab953cb2be1 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 22 May 2025 12:17:06 +0200 Subject: [PATCH 097/120] [cert-manager] Update Cert-manager to v1.17.2 Signed-off-by: Andrei Kvapil --- .../charts/cert-manager/Chart.yaml | 4 +- .../charts/cert-manager/README.md | 41 ++++++++++++------- .../templates/cainjector-deployment.yaml | 6 +++ .../templates/cainjector-service.yaml | 2 + .../charts/cert-manager/templates/crds.yaml | 37 +++++++++++++---- .../cert-manager/templates/deployment.yaml | 6 +++ .../templates/serviceaccount.yaml | 4 +- .../templates/webhook-deployment.yaml | 6 +++ .../charts/cert-manager/values.schema.json | 4 +- .../charts/cert-manager/values.yaml | 32 ++++++++++----- 10 files changed, 105 insertions(+), 37 deletions(-) diff --git a/packages/system/cert-manager/charts/cert-manager/Chart.yaml b/packages/system/cert-manager/charts/cert-manager/Chart.yaml index 300db669..2a49d00c 100644 --- a/packages/system/cert-manager/charts/cert-manager/Chart.yaml +++ b/packages/system/cert-manager/charts/cert-manager/Chart.yaml @@ -6,7 +6,7 @@ annotations: fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg apiVersion: v2 -appVersion: v1.16.3 +appVersion: v1.17.2 description: A Helm chart for cert-manager home: https://cert-manager.io icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png @@ -23,4 +23,4 @@ maintainers: name: cert-manager sources: - https://github.com/cert-manager/cert-manager -version: v1.16.3 +version: v1.17.2 diff --git a/packages/system/cert-manager/charts/cert-manager/README.md b/packages/system/cert-manager/charts/cert-manager/README.md index 6fa25cc9..1d502429 100644 --- a/packages/system/cert-manager/charts/cert-manager/README.md +++ b/packages/system/cert-manager/charts/cert-manager/README.md @@ -19,7 +19,7 @@ Before installing the chart, you must first install the cert-manager CustomResou This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. ```bash -$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml +$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml ``` To install the chart with the release name `cert-manager`: @@ -29,7 +29,7 @@ To install the chart with the release name `cert-manager`: $ helm repo add jetstack https://charts.jetstack.io --force-update ## Install the cert-manager helm chart -$ helm install cert-manager --namespace cert-manager --version v1.16.3 jetstack/cert-manager +$ helm install cert-manager --namespace cert-manager --version v1.17.2 jetstack/cert-manager ``` In order to begin issuing certificates, you will need to set up a ClusterIssuer @@ -65,7 +65,7 @@ If you want to completely uninstall cert-manager from your cluster, you will als delete the previously installed CustomResourceDefinition resources: ```console -$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml +$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml ``` ## Configuration @@ -316,7 +316,13 @@ If not set and create is true, a name is generated using the fullname template. #### **serviceAccount.annotations** ~ `object` -Optional additional annotations to add to the controller's Service Account. +Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values. +Example using templating: + +```yaml +annotations: + "{{ .Chart.Name }}-helm-chart/version": "{{ .Chart.Version }}" +``` #### **serviceAccount.labels** ~ `object` @@ -364,17 +370,24 @@ config: kubernetesAPIQPS: 9000 kubernetesAPIBurst: 9000 numberOfConcurrentWorkers: 200 + enableGatewayAPI: true + # Feature gates as of v1.17.0. Listed with their default values. + # See https://cert-manager.io/docs/cli/controller/ featureGates: - AdditionalCertificateOutputFormats: true - DisallowInsecureCSRUsageDefinition: true - ExperimentalCertificateSigningRequestControllers: true - ExperimentalGatewayAPISupport: true - LiteralCertificateSubject: true - SecretsFilteredCaching: true - ServerSideApply: true - StableCertificateRequestName: true - UseCertificateRequestBasicConstraints: true - ValidateCAA: true + AdditionalCertificateOutputFormats: true # BETA - default=true + AllAlpha: false # ALPHA - default=false + AllBeta: false # BETA - default=false + ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false + ExperimentalGatewayAPISupport: true # BETA - default=true + LiteralCertificateSubject: true # BETA - default=true + NameConstraints: true # BETA - default=true + OtherNames: false # ALPHA - default=false + SecretsFilteredCaching: true # BETA - default=true + ServerSideApply: false # ALPHA - default=false + StableCertificateRequestName: true # BETA - default=true + UseCertificateRequestBasicConstraints: false # ALPHA - default=false + UseDomainQualifiedFinalizer: true # BETA - default=false + ValidateCAA: false # ALPHA - default=false # Configure the metrics server for TLS # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls metricsTLSConfig: diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml index 65e65894..dc14ab02 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml @@ -53,6 +53,12 @@ spec: prometheus.io/port: '9402' {{- end }} spec: + {{- if not .Values.cainjector.serviceAccount.create }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} serviceAccountName: {{ template "cainjector.serviceAccountName" . }} {{- if hasKey .Values.cainjector "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-service.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-service.yaml index 2ed9178f..dd0e64db 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-service.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-service.yaml @@ -1,3 +1,4 @@ +{{- if .Values.cainjector.enabled }} {{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} apiVersion: v1 kind: Service @@ -28,3 +29,4 @@ spec: app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "cainjector" {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml index 00930f9c..f5f8ec43 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml @@ -514,7 +514,6 @@ spec: type: object required: - create - - passwordSecretRef properties: alias: description: |- @@ -526,17 +525,25 @@ spec: Create enables JKS keystore creation for the Certificate. If true, a file named `keystore.jks` will be created in the target Secret resource, encrypted using the password stored in - `passwordSecretRef`. + `passwordSecretRef` or `password`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.jks` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority type: boolean + password: + description: |- + Password provides a literal password used to encrypt the JKS keystore. + Mutually exclusive with passwordSecretRef. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: string passwordSecretRef: description: |- - PasswordSecretRef is a reference to a key in a Secret resource + PasswordSecretRef is a reference to a non-empty key in a Secret resource containing the password used to encrypt the JKS keystore. + Mutually exclusive with password. + One of password or passwordSecretRef must provide a password with a non-zero length. type: object required: - name @@ -559,24 +566,31 @@ spec: type: object required: - create - - passwordSecretRef properties: create: description: |- Create enables PKCS12 keystore creation for the Certificate. If true, a file named `keystore.p12` will be created in the target Secret resource, encrypted using the password stored in - `passwordSecretRef`. + `passwordSecretRef` or in `password`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.p12` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority type: boolean + password: + description: |- + Password provides a literal password used to encrypt the PKCS#12 keystore. + Mutually exclusive with passwordSecretRef. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: string passwordSecretRef: description: |- - PasswordSecretRef is a reference to a key in a Secret resource - containing the password used to encrypt the PKCS12 keystore. + PasswordSecretRef is a reference to a non-empty key in a Secret resource + containing the password used to encrypt the PKCS#12 keystore. + Mutually exclusive with password. + One of password or passwordSecretRef must provide a password with a non-zero length. type: object required: - name @@ -1376,6 +1390,9 @@ spec: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string resourceGroupName: description: resource group the DNS zone is located in type: string @@ -4689,6 +4706,9 @@ spec: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string resourceGroupName: description: resource group the DNS zone is located in type: string @@ -8415,6 +8435,9 @@ spec: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string resourceGroupName: description: resource group the DNS zone is located in type: string diff --git a/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml index e6f3f681..8a4a9734 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml @@ -52,6 +52,12 @@ spec: prometheus.io/port: '9402' {{- end }} spec: + {{- if not .Values.serviceAccount.create }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} serviceAccountName: {{ template "cert-manager.serviceAccountName" . }} {{- if hasKey .Values "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml index 87fc00ea..698ddef8 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml @@ -11,7 +11,9 @@ metadata: namespace: {{ include "cert-manager.namespace" . }} {{- with .Values.serviceAccount.annotations }} annotations: - {{- toYaml . | nindent 4 }} + {{- range $k, $v := . }} + {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} + {{- end }} {{- end }} labels: app: {{ include "cert-manager.name" . }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml index 1535589f..857cf353 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml @@ -52,6 +52,12 @@ spec: prometheus.io/port: '9402' {{- end }} spec: + {{- if not .Values.webhook.serviceAccount.create }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} serviceAccountName: {{ template "webhook.serviceAccountName" . }} {{- if hasKey .Values.webhook "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }} diff --git a/packages/system/cert-manager/charts/cert-manager/values.schema.json b/packages/system/cert-manager/charts/cert-manager/values.schema.json index d04da90c..36d1d0ca 100644 --- a/packages/system/cert-manager/charts/cert-manager/values.schema.json +++ b/packages/system/cert-manager/charts/cert-manager/values.schema.json @@ -579,7 +579,7 @@ }, "helm-values.config": { "default": {}, - "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.17.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # BETA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # BETA - default=false\n ValidateCAA: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", "type": "object" }, "helm-values.containerSecurityContext": { @@ -1223,7 +1223,7 @@ "type": "object" }, "helm-values.serviceAccount.annotations": { - "description": "Optional additional annotations to add to the controller's Service Account.", + "description": "Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values.\nExample using templating:\nannotations:\n \"{{ .Chart.Name }}-helm-chart/version\": \"{{ .Chart.Version }}\"", "type": "object" }, "helm-values.serviceAccount.automountServiceAccountToken": { diff --git a/packages/system/cert-manager/charts/cert-manager/values.yaml b/packages/system/cert-manager/charts/cert-manager/values.yaml index 7a1c2953..a8c94f8b 100644 --- a/packages/system/cert-manager/charts/cert-manager/values.yaml +++ b/packages/system/cert-manager/charts/cert-manager/values.yaml @@ -190,7 +190,10 @@ serviceAccount: # +docs:property # name: "" - # Optional additional annotations to add to the controller's Service Account. + # Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values. + # Example using templating: + # annotations: + # "{{ .Chart.Name }}-helm-chart/version": "{{ .Chart.Version }}" # +docs:property # annotations: {} @@ -227,17 +230,24 @@ enableCertificateOwnerRef: false # kubernetesAPIQPS: 9000 # kubernetesAPIBurst: 9000 # numberOfConcurrentWorkers: 200 +# enableGatewayAPI: true +# # Feature gates as of v1.17.0. Listed with their default values. +# # See https://cert-manager.io/docs/cli/controller/ # featureGates: -# AdditionalCertificateOutputFormats: true -# DisallowInsecureCSRUsageDefinition: true -# ExperimentalCertificateSigningRequestControllers: true -# ExperimentalGatewayAPISupport: true -# LiteralCertificateSubject: true -# SecretsFilteredCaching: true -# ServerSideApply: true -# StableCertificateRequestName: true -# UseCertificateRequestBasicConstraints: true -# ValidateCAA: true +# AdditionalCertificateOutputFormats: true # BETA - default=true +# AllAlpha: false # ALPHA - default=false +# AllBeta: false # BETA - default=false +# ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false +# ExperimentalGatewayAPISupport: true # BETA - default=true +# LiteralCertificateSubject: true # BETA - default=true +# NameConstraints: true # BETA - default=true +# OtherNames: false # ALPHA - default=false +# SecretsFilteredCaching: true # BETA - default=true +# ServerSideApply: false # ALPHA - default=false +# StableCertificateRequestName: true # BETA - default=true +# UseCertificateRequestBasicConstraints: false # ALPHA - default=false +# UseDomainQualifiedFinalizer: true # BETA - default=false +# ValidateCAA: false # ALPHA - default=false # # Configure the metrics server for TLS # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls # metricsTLSConfig: From 866b6e0a5ae5207e76f8f9a9601b63b6cbfc817a Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 22 May 2025 13:15:41 +0200 Subject: [PATCH 098/120] [kubernetes] Fix Ingress-NGINX depends on Cert-Manager Signed-off-by: Andrei Kvapil --- packages/apps/kubernetes/Chart.yaml | 2 +- .../kubernetes/templates/helmreleases/ingress-nginx.yaml | 5 +++++ packages/apps/versions_map | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index 47494b96..2164da8e 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.20.0 +version: 0.20.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index d81e16e6..68ad8e63 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -6,6 +6,11 @@ ingress-nginx: hostNetwork: true service: enabled: false + {{- if not .Values.addons.certManager.enabled }} + admissionWebhooks: + certManager: + enabled: false + {{- end }} nodeSelector: node-role.kubernetes.io/ingress-nginx: "" {{- end }} diff --git a/packages/apps/versions_map b/packages/apps/versions_map index 89d9990d..778a92a1 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -64,7 +64,8 @@ kubernetes 0.17.0 1fbbfcd0 kubernetes 0.17.1 fd240701 kubernetes 0.18.0 721c12a7 kubernetes 0.19.0 93bdf411 -kubernetes 0.20.0 HEAD +kubernetes 0.20.0 609e7ede +kubernetes 0.20.1 HEAD mysql 0.1.0 263e47be mysql 0.2.0 c24a103f mysql 0.3.0 53f2365e From 2461fcd53151f170cf4977ac3dab0a0e47ce6357 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 22 May 2025 15:12:15 +0200 Subject: [PATCH 099/120] [ci] Force-update release branch on tagged main commits Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 28 +++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index e51e766e..87850119 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -89,21 +89,41 @@ jobs: } const line = `${match[1]}.${match[2]}`; const branch = `release-${line}`; + + // Get main branch commit for the tag + const ref = await github.rest.git.getRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `tags/${tag}` + }); + const commitSha = ref.data.object.sha; + try { + // Check if branch exists await github.rest.repos.getBranch({ owner: context.repo.owner, repo: context.repo.repo, branch }); - console.log(`Branch '${branch}' already exists`); - } catch (_) { + + // Force update existing branch to the tag commit + await github.rest.git.updateRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${branch}`, + sha: commitSha, + force: true + }); + console.log(`🔁 Force-updated '${branch}' to ${commitSha}`); + } catch (err) { + // Branch doesn't exist, create it await github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: `refs/heads/${branch}`, - sha: context.sha + sha: commitSha }); - console.log(`✅ Branch '${branch}' created at ${context.sha}`); + console.log(`✅ Created branch '${branch}' at ${commitSha}`); } # Get the latest published release From 0fee3f280bb38c36571e3a2e5944394f80b92e4e Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Thu, 22 May 2025 16:08:51 +0200 Subject: [PATCH 100/120] [ci] Support alpha and beta pre-releases Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests-release.yaml | 6 +++--- .github/workflows/tags.yaml | 21 ++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index e51e766e..226d6351 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -137,12 +137,12 @@ jobs: with: script: | const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc.1 - const m = tag.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/); + const m = tag.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); if (!m) { - core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`); + core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); return; } - const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc.1 + const version = m[1] + (m[2] ?? ''); // 0.31.5-rc.1 const isRc = Boolean(m[2]); core.setOutput('is_rc', isRc); const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<'; diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 6efac7db..66376397 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -3,9 +3,10 @@ name: Versioned Tag on: push: tags: - - 'v*.*.*' # vX.Y.Z - - 'v*.*.*-rc.*' # vX.Y.Z-rc.N - + - 'v*.*.*' # vX.Y.Z + - 'v*.*.*-rc.*' # vX.Y.Z-rc.N + - 'v*.*.*-beta.*' # vX.Y.Z-beta.N + - 'v*.*.*-alpha.*' # vX.Y.Z-alpha.N concurrency: group: tags-${{ github.workflow }}-${{ github.ref }} @@ -42,7 +43,7 @@ jobs: if: steps.check_release.outputs.skip == 'true' run: echo "Release already exists, skipping workflow." - # Parse tag meta‑data (rc?, maintenance line, etc.) + # Parse tag meta-data (rc?, maintenance line, etc.) - name: Parse tag if: steps.check_release.outputs.skip == 'false' id: tag @@ -50,12 +51,12 @@ jobs: with: script: | const ref = context.ref.replace('refs/tags/', ''); // e.g. v0.31.5-rc.1 - const m = ref.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/); // ['0.31.5', '-rc.1'] + const m = ref.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); // ['0.31.5', '-rc.1' | '-beta.1' | …] if (!m) { - core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`); + core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); return; } - const version = m[1] + (m[2] ?? ''); // 0.31.5‑rc.1 + const version = m[1] + (m[2] ?? ''); // 0.31.5-rc.1 const isRc = Boolean(m[2]); const [maj, min] = m[1].split('.'); core.setOutput('tag', ref); // v0.31.5-rc.1 @@ -63,7 +64,7 @@ jobs: core.setOutput('is_rc', isRc); // true core.setOutput('line', `${maj}.${min}`); // 0.31 - # Detect base branch (main or release‑X.Y) the tag was pushed from + # Detect base branch (main or release-X.Y) the tag was pushed from - name: Get base branch if: steps.check_release.outputs.skip == 'false' id: get_base @@ -168,7 +169,7 @@ jobs: }); console.log(`Draft release created for ${tag}`); } else { - console.log(`Re‑using existing release ${tag}`); + console.log(`Re-using existing release ${tag}`); } core.setOutput('upload_url', rel.upload_url); @@ -181,7 +182,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Create release‑X.Y.Z branch and push (force‑update) + # Create release-X.Y.Z branch and push (force-update) - name: Create release branch if: steps.check_release.outputs.skip == 'false' run: | From 451267310bd228b8a9cb9b048d995a70dfc34330 Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Fri, 23 May 2025 14:36:20 +0300 Subject: [PATCH 101/120] [docs] Tenants cannot have dashes in the names Gave examples of tenant naming. Part of cozystack/cozystack#971 Signed-off-by: Nick Volynkin --- packages/apps/tenant/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md index f43db79a..bc33b6a3 100644 --- a/packages/apps/tenant/README.md +++ b/packages/apps/tenant/README.md @@ -4,13 +4,19 @@ A tenant is the main unit of security on the platform. The closest analogy would Tenants can be created recursively and are subject to the following rules: -### Higher-level tenants can access lower-level ones. +### Tenant naming -Higher-level tenants can view and manage the applications of all their children. +Tenant names must be alphanumeric. +Using dashes (`-`) in tenant names is not allowed, unlike with other services. +This limitation exists to keep consistent naming in tenants, nested tenants, and services deployed in them. + +For example: + +- The root tenant is named `root`, but internally it's referenced as `tenant-root`. +- A nested tenant could be named `foo`, which would result in `tenant-foo` in service names and URLs. +- However, a tenant can not be named `foo-bar`, because parsing names such as `tenant-foo-bar` would be ambiguous. -### Each tenant has its own domain -By default (unless otherwise specified), it inherits the domain of its parent with a prefix of its name, for example, if the parent had the domain `example.org`, then `tenant-foo` would get the domain `foo.example.org` by default. Kubernetes clusters created in this tenant namespace would get domains like: `kubernetes-cluster.foo.example.org` From 119d58237982a514bf10a90ba120b93336852987 Mon Sep 17 00:00:00 2001 From: Nick Volynkin Date: Fri, 23 May 2025 14:48:51 +0300 Subject: [PATCH 102/120] [docs] Review the Tenant app documentation * Brush up some formatting * Explain the relations of nested tenants in more detail Signed-off-by: Nick Volynkin --- packages/apps/tenant/README.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md index bc33b6a3..cc26c830 100644 --- a/packages/apps/tenant/README.md +++ b/packages/apps/tenant/README.md @@ -16,30 +16,43 @@ For example: - A nested tenant could be named `foo`, which would result in `tenant-foo` in service names and URLs. - However, a tenant can not be named `foo-bar`, because parsing names such as `tenant-foo-bar` would be ambiguous. +### Unique domains +Each tenant has its own domain. +By default, (unless otherwise specified), it inherits the domain of its parent with a prefix of its name. +For example, if the parent had the domain `example.org`, then `tenant-foo` would get the domain `foo.example.org` by default. Kubernetes clusters created in this tenant namespace would get domains like: `kubernetes-cluster.foo.example.org` Example: -``` +```text tenant-root (example.org) └── tenant-foo (foo.example.org) └── kubernetes-cluster1 (kubernetes-cluster1.foo.example.org) ``` -### Lower-level tenants can access the cluster services of their parent (provided they do not run their own) +### Nesting tenants and reusing parent services -Thus, you can create `tenant-u1` with a set of services like `etcd`, `ingress`, `monitoring`. And create another tenant namespace `tenant-u2` inside of `tenant-u1`. +Tenants can be nested. +A tenant administrator can create nested tenants using the "Tenant" application from the catalogue. + +Higher-level tenants can view and manage the applications of all their children tenants. +If a tenant does not run their own cluster services, it can access ones of its parent. + +For example, you create: +- Tenant `tenant-u1` with a set of services like `etcd`, `ingress`, `monitoring`. +- Tenant `tenant-u2` nested in `tenant-u1`. Let's see what will happen when you run Kubernetes and Postgres under `tenant-u2` namespace. -Since `tenant-u2` does not have its own cluster services like `etcd`, `ingress`, and `monitoring`, the applications will use the cluster services of the parent tenant. +Since `tenant-u2` does not have its own cluster services like `etcd`, `ingress`, and `monitoring`, +the applications running in `tenant-u2` will use the cluster services of the parent tenant. + This in turn means: -- The Kubernetes cluster data will be stored in etcd for `tenant-u1`. -- Access to the cluster will be through the common ingress of `tenant-u1`. -- Essentially, all metrics will be collected in the monitoring from `tenant-u1`, and only it will have access to them. - +- The Kubernetes cluster data will be stored in `etcd` for `tenant-u1`. +- Access to the cluster will be through the common `ingress` of `tenant-u1`. +- Essentially, all metrics will be collected in the `monitoring` from `tenant-u1`, and only that tenant will have access to them. Example: ``` From 9592f7fe463ff5cfa03b55ac4915bd6fb254cfcb Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Mon, 12 May 2025 18:52:32 +0300 Subject: [PATCH 103/120] Remove user-facing config of limits and requests This patch introduces reusable library charts that provide backward-compatibility for users that specify their resources as explicit requests and limits for cpu, however this input is processed so that limits are set equal to requests except for CPU which only gets requests. Users can now embrace the new form by directly specifying resources in the first level of nesting (e.g. resources.cpu=100m instead of .resources.requests.cpu=100m). The order of precedence is top-level, then requests, then limits, ensuring that nothing will break in terms of scheduling, however workloads that specified limits much higher than requests might get a performance hit, now that they cannot use all this excess capacity. This should only affect memory-hungry workloads in low-contention environments. Signed-off-by: Timofei Larkin --- Makefile | 2 + hack/gen_versions_map.sh | 8 ++- hack/package_chart.sh | 65 +++++++++++++++++++ packages/apps/Makefile | 12 +--- packages/apps/clickhouse/Chart.yaml | 2 +- packages/apps/clickhouse/charts/cozy-lib | 1 + .../apps/clickhouse/templates/clickhouse.yaml | 4 +- packages/apps/versions_map | 2 +- packages/extra/Makefile | 12 +--- packages/library/Makefile | 15 +++++ packages/library/cozy-lib/.helmignore | 23 +++++++ packages/library/cozy-lib/Chart.yaml | 18 +++++ packages/library/cozy-lib/Makefile | 6 ++ packages/library/cozy-lib/README.md | 1 + .../cozy-lib/templates/_resourcepresets.tpl | 49 ++++++++++++++ .../library/cozy-lib/templates/_resources.tpl | 53 +++++++++++++++ packages/library/cozy-lib/values.schema.json | 5 ++ packages/library/cozy-lib/values.yaml | 1 + packages/library/testfile | 0 packages/library/versions_map | 1 + 20 files changed, 255 insertions(+), 25 deletions(-) create mode 100755 hack/package_chart.sh create mode 120000 packages/apps/clickhouse/charts/cozy-lib create mode 100644 packages/library/Makefile create mode 100644 packages/library/cozy-lib/.helmignore create mode 100644 packages/library/cozy-lib/Chart.yaml create mode 100644 packages/library/cozy-lib/Makefile create mode 100644 packages/library/cozy-lib/README.md create mode 100644 packages/library/cozy-lib/templates/_resourcepresets.tpl create mode 100644 packages/library/cozy-lib/templates/_resources.tpl create mode 100644 packages/library/cozy-lib/values.schema.json create mode 100644 packages/library/cozy-lib/values.yaml create mode 100644 packages/library/testfile create mode 100644 packages/library/versions_map diff --git a/Makefile b/Makefile index 99309f4e..56609653 100644 --- a/Makefile +++ b/Makefile @@ -28,8 +28,10 @@ build: build-deps repos: rm -rf _out + make -C packages/library check-version-map make -C packages/apps check-version-map make -C packages/extra check-version-map + make -C packages/library repo make -C packages/system repo make -C packages/apps repo make -C packages/extra repo diff --git a/hack/gen_versions_map.sh b/hack/gen_versions_map.sh index 5169bc2f..60ede8ba 100755 --- a/hack/gen_versions_map.sh +++ b/hack/gen_versions_map.sh @@ -16,13 +16,15 @@ if [ ! -f "$file" ] || [ ! -s "$file" ]; then exit 0 fi -miss_map=$(echo "$new_map" | awk 'NR==FNR { nm[$1 " " $2] = $3; next } { if (!($1 " " $2 in nm)) print $1, $2, $3}' - "$file") +miss_map=$(mktemp) +trap 'rm -f "$miss_map"' EXIT +echo -n "$new_map" | awk 'NR==FNR { nm[$1 " " $2] = $3; next } { if (!($1 " " $2 in nm)) print $1, $2, $3}' - "$file" > $miss_map # search accross all tags sorted by version search_commits=$(git ls-remote --tags origin | awk -F/ '$3 ~ /v[0-9]+.[0-9]+.[0-9]+/ {print}' | sort -k2,2 -rV | awk '{print $1}') resolved_miss_map=$( - echo "$miss_map" | while read -r chart version commit; do + while read -r chart version commit; do # if version is found in HEAD, it's HEAD if [ "$(awk '$1 == "version:" {print $2}' ./${chart}/Chart.yaml)" = "${version}" ]; then echo "$chart $version HEAD" @@ -56,7 +58,7 @@ resolved_miss_map=$( fi echo "$chart $version $found_tag" - done + done < $miss_map ) printf "%s\n" "$new_map" "$resolved_miss_map" | sort -k1,1 -k2,2 -V | awk '$1' > "$file" diff --git a/hack/package_chart.sh b/hack/package_chart.sh new file mode 100755 index 00000000..f8ab297f --- /dev/null +++ b/hack/package_chart.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +set -e + +usage() { + printf "%s\n" "Usage:" >&2 ; + printf -- "%s\n" '---' >&2 ; + printf "%s %s\n" "$0" "INPUT_DIR OUTPUT_DIR TMP_DIR [DEPENDENCY_DIR]" >&2 ; + printf -- "%s\n" '---' >&2 ; + printf "%s\n" "Takes a helm repository from INPUT_DIR, with an optional library repository in" >&2 ; + printf "%s\n" "DEPENDENCY_DIR, prepares a view of the git archive at select points in history" >&2 ; + printf "%s\n" "in TMP_DIR and packages helm charts, outputting the tarballs to OUTPUT_DIR" >&2 ; +} + +if [ "x$(basename $PWD)" != "xpackages" ] +then + echo "Error: This script must run from the ./packages/ directory" >&2 + echo >&2 + usage + exit 1 +fi + +if [ "x$#" != "x3" ] && [ "x$#" != "x4" ] +then + echo "Error: This script takes 3 or 4 arguments" >&2 + echo "Got $# arguments:" "$@" >&2 + echo >&2 + usage + exit 1 +fi + +input_dir=$1 +output_dir=$2 +tmp_dir=$3 + +if [ "x$#" = "x4" ] +then + dependency_dir=$4 +fi + +rm -rf "${output_dir:?}" +mkdir -p "${output_dir}" +while read package _ commit +do + # this lets devs build the packages from a dirty repo for quick local testing + if [ "x$commit" = "xHEAD" ] + then + helm package "${input_dir}/${package}" -d "${output_dir}" + continue + fi + git archive --format tar "${commit}" "${input_dir}/${package}" | tar -xf- -C "${tmp_dir}/" + + # the library chart is not present in older commits and git archive doesn't fail gracefully if the path is not found + if [ "x${dependency_dir}" != "x" ] && git ls-tree --name-only "${commit}" "${dependency_dir}" | grep -qx "${dependency_dir}" + then + git archive --format tar "${commit}" "${dependency_dir}" | tar -xf- -C "${tmp_dir}/" + fi + helm package "${tmp_dir}/${input_dir}/${package}" -d "${output_dir}" + rm -rf "${tmp_dir:?}/${input_dir:?}/${package:?}" + if [ "x${dependency_dir}" != "x" ] + then + rm -rf "${tmp_dir:?}/${dependency_dir:?}" + fi +done < "${input_dir}/versions_map" +helm repo index "${output_dir}" diff --git a/packages/apps/Makefile b/packages/apps/Makefile index 506c8750..8751a048 100644 --- a/packages/apps/Makefile +++ b/packages/apps/Makefile @@ -1,14 +1,8 @@ -OUT=../../_out/repos/apps -TMP=../../_out/repos/apps/historical +OUT=../_out/repos/apps +TMP := $(shell mktemp -d) repo: - rm -rf "$(OUT)" - mkdir -p "$(OUT)" - awk '$$3 != "HEAD" {print "mkdir -p $(TMP)/" $$1 "-" $$2}' versions_map | sh -ex - awk '$$3 != "HEAD" {print "git archive " $$3 " " $$1 " | tar -xf- --strip-components=1 -C $(TMP)/" $$1 "-" $$2 }' versions_map | sh -ex - helm package -d "$(OUT)" $$(find . $(TMP) -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")' | sort -V) - cd "$(OUT)" && helm repo index . --url http://cozystack.cozy-system.svc/repos/apps - rm -rf "$(TMP)" + cd .. && ../hack/package_chart.sh apps $(OUT) $(TMP) library fix-chartnames: find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done diff --git a/packages/apps/clickhouse/Chart.yaml b/packages/apps/clickhouse/Chart.yaml index 935cf6af..bfb34b34 100644 --- a/packages/apps/clickhouse/Chart.yaml +++ b/packages/apps/clickhouse/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.8.0 +version: 0.9.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/packages/apps/clickhouse/charts/cozy-lib b/packages/apps/clickhouse/charts/cozy-lib new file mode 120000 index 00000000..e1813509 --- /dev/null +++ b/packages/apps/clickhouse/charts/cozy-lib @@ -0,0 +1 @@ +../../../library/cozy-lib \ No newline at end of file diff --git a/packages/apps/clickhouse/templates/clickhouse.yaml b/packages/apps/clickhouse/templates/clickhouse.yaml index dd4b0fdb..dd97188d 100644 --- a/packages/apps/clickhouse/templates/clickhouse.yaml +++ b/packages/apps/clickhouse/templates/clickhouse.yaml @@ -122,9 +122,9 @@ spec: - name: clickhouse image: clickhouse/clickhouse-server:24.9.2.42 {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 16 }} + resources: {{- include "cozy-lib.resources.sanitize" .Values.resources | nindent 16 }} {{- else if ne .Values.resourcesPreset "none" }} - resources: {{- include "resources.preset" (dict "type" .Values.resourcesPreset "Release" .Release) | nindent 16 }} + resources: {{- include "cozy-lib.resources.preset" .Values.resourcesPreset | nindent 16 }} {{- end }} volumeMounts: - name: data-volume-template diff --git a/packages/apps/versions_map b/packages/apps/versions_map index 89d9990d..776c897d 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -9,7 +9,7 @@ clickhouse 0.6.0 1ec10165 clickhouse 0.6.1 c62a83a7 clickhouse 0.6.2 8267072d clickhouse 0.7.0 93bdf411 -clickhouse 0.8.0 HEAD +clickhouse 0.9.0 HEAD ferretdb 0.1.0 e9716091 ferretdb 0.1.1 91b0499a ferretdb 0.2.0 6c5cf5bf diff --git a/packages/extra/Makefile b/packages/extra/Makefile index 5586c59e..e05e4985 100644 --- a/packages/extra/Makefile +++ b/packages/extra/Makefile @@ -1,14 +1,8 @@ -OUT=../../_out/repos/extra -TMP=../../_out/repos/extra/historical +OUT=../_out/repos/extra +TMP := $(shell mktemp -d) repo: - rm -rf "$(OUT)" - mkdir -p "$(OUT)" - awk '$$3 != "HEAD" {print "mkdir -p $(TMP)/" $$1 "-" $$2}' versions_map | sh -ex - awk '$$3 != "HEAD" {print "git archive " $$3 " " $$1 " | tar -xf- --strip-components=1 -C $(TMP)/" $$1 "-" $$2 }' versions_map | sh -ex - helm package -d "$(OUT)" $$(find . $(TMP) -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")' | sort -V) - cd "$(OUT)" && helm repo index . --url http://cozystack.cozy-system.svc/repos/extra - rm -rf "$(TMP)" + cd .. && ../hack/package_chart.sh extra $(OUT) $(TMP) library fix-chartnames: find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done diff --git a/packages/library/Makefile b/packages/library/Makefile new file mode 100644 index 00000000..664771cf --- /dev/null +++ b/packages/library/Makefile @@ -0,0 +1,15 @@ +OUT=../_out/repos/library +TMP := $(shell mktemp -d) + +repo: + cd .. && ../hack/package_chart.sh library $(OUT) $(TMP) + +fix-chartnames: + find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done + +gen-versions-map: fix-chartnames + ../../hack/gen_versions_map.sh + +check-version-map: gen-versions-map + git diff --exit-code -- versions_map + diff --git a/packages/library/cozy-lib/.helmignore b/packages/library/cozy-lib/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/library/cozy-lib/.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/packages/library/cozy-lib/Chart.yaml b/packages/library/cozy-lib/Chart.yaml new file mode 100644 index 00000000..81a3634d --- /dev/null +++ b/packages/library/cozy-lib/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: cozy-lib +description: Common Cozystack templates + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: library + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 diff --git a/packages/library/cozy-lib/Makefile b/packages/library/cozy-lib/Makefile new file mode 100644 index 00000000..fa0142de --- /dev/null +++ b/packages/library/cozy-lib/Makefile @@ -0,0 +1,6 @@ +include ../../../scripts/common-envs.mk +include ../../../scripts/package.mk + +generate: + readme-generator -v values.yaml -s values.schema.json -r README.md + diff --git a/packages/library/cozy-lib/README.md b/packages/library/cozy-lib/README.md new file mode 100644 index 00000000..d4bf18ad --- /dev/null +++ b/packages/library/cozy-lib/README.md @@ -0,0 +1 @@ +## Parameters diff --git a/packages/library/cozy-lib/templates/_resourcepresets.tpl b/packages/library/cozy-lib/templates/_resourcepresets.tpl new file mode 100644 index 00000000..f6ecef3f --- /dev/null +++ b/packages/library/cozy-lib/templates/_resourcepresets.tpl @@ -0,0 +1,49 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "cozy-lib.resources.preset" "nano" -}} +*/}} +{{- define "cozy-lib.resources.preset" -}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") + "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets . -}} +{{- index $presets . | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" . (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl new file mode 100644 index 00000000..34ed9ca2 --- /dev/null +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -0,0 +1,53 @@ +{{- /* + A sanitized resource map is a dict with resource-name => resource-quantity. + If not in such a form, requests are used, then limits. All resources are set + to have equal requests and limits, except CPU, that has only requests. The + template expects to receive a dict {"requests":{...}, "limits":{...}} as + input, e.g. {{ include "cozy-lib.resources.sanitize" .Values.resources }}. + Example input: + ============== + limits: + cpu: 100m + memory: 1024Mi + requests: + cpu: 200m + memory: 512Mi + memory: 256Mi + devices.com/nvidia: "1" + + Example output: + =============== + limits: + devices.com/nvidia: "1" + memory: 256Mi + requests: + cpu: 200m + devices.com/nvidia: "1" + memory: 256Mi +*/}} +{{- define "cozy-lib.resources.sanitize" }} +{{- $sanitizedMap := dict }} +{{- if hasKey . "limits" }} +{{- range $k, $v := .limits }} +{{- $_ := set $sanitizedMap $k $v }} +{{- end }} +{{- end }} +{{- if hasKey . "requests" }} +{{- range $k, $v := .requests }} +{{- $_ := set $sanitizedMap $k $v }} +{{- end }} +{{- end }} +{{- range $k, $v := . }} +{{- if not (or (eq $k "requests") (eq $k "limits")) }} +{{- $_ := set $sanitizedMap $k $v }} +{{- end }} +{{- end }} +{{- $output := dict "requests" dict "limits" dict }} +{{- range $k, $v := $sanitizedMap }} +{{- $_ := set $output.requests $k $v }} +{{- if not (eq $k "cpu") }} +{{- $_ := set $output.limits $k $v }} +{{- end }} +{{- end }} +{{- $output | toYaml }} +{{- end }} diff --git a/packages/library/cozy-lib/values.schema.json b/packages/library/cozy-lib/values.schema.json new file mode 100644 index 00000000..decc79aa --- /dev/null +++ b/packages/library/cozy-lib/values.schema.json @@ -0,0 +1,5 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/packages/library/cozy-lib/values.yaml b/packages/library/cozy-lib/values.yaml new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/packages/library/cozy-lib/values.yaml @@ -0,0 +1 @@ +{} diff --git a/packages/library/testfile b/packages/library/testfile new file mode 100644 index 00000000..e69de29b diff --git a/packages/library/versions_map b/packages/library/versions_map new file mode 100644 index 00000000..63834fdd --- /dev/null +++ b/packages/library/versions_map @@ -0,0 +1 @@ +cozy-lib 0.1.0 HEAD From 9fb6b41e03c74a5d0f3ed426cd5b30de62c7f401 Mon Sep 17 00:00:00 2001 From: nbykov0 <166552198+nbykov0@users.noreply.github.com> Date: Fri, 23 May 2025 22:22:12 +0300 Subject: [PATCH 104/120] Re-update kamaji to latest version Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com> --- packages/system/kamaji/images/kamaji/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/system/kamaji/images/kamaji/Dockerfile b/packages/system/kamaji/images/kamaji/Dockerfile index 1646262a..e7bd44be 100644 --- a/packages/system/kamaji/images/kamaji/Dockerfile +++ b/packages/system/kamaji/images/kamaji/Dockerfile @@ -1,7 +1,7 @@ # Build the manager binary FROM golang:1.24 as builder -ARG VERSION=edge-25.3.2 +ARG VERSION=edge-25.4.1 ARG TARGETOS ARG TARGETARCH @@ -23,4 +23,4 @@ WORKDIR / COPY --from=builder /workspace/kamaji . USER 65532:65532 -ENTRYPOINT ["/kamaji"] \ No newline at end of file +ENTRYPOINT ["/kamaji"] From 2bf4032d5b54991efb3d11eabdd4a508df245758 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 23 May 2025 20:58:56 +0200 Subject: [PATCH 105/120] [tests] Introduce cozytest - a new testing framework Signed-off-by: Andrei Kvapil --- hack/cozytest.sh | 117 ++++++++++ hack/e2e.bats | 387 +++++++++++++++++++++++++++++++++ hack/e2e.sh | 370 ------------------------------- packages/core/testing/Makefile | 2 +- 4 files changed, 505 insertions(+), 371 deletions(-) create mode 100755 hack/cozytest.sh create mode 100755 hack/e2e.bats delete mode 100755 hack/e2e.sh diff --git a/hack/cozytest.sh b/hack/cozytest.sh new file mode 100755 index 00000000..acf0db35 --- /dev/null +++ b/hack/cozytest.sh @@ -0,0 +1,117 @@ +#!/bin/sh +############################################################################### +# cozytest.sh - Bats-compatible test runner with live trace and enhanced # +# output, written in pure shell # +############################################################################### +set -eu + +TEST_FILE=${1:?Usage: ./cozytest.sh [pattern]} +PATTERN=${2:-*} +LINE='----------------------------------------------------------------' + +cols() { stty size 2>/dev/null | awk '{print $2}' || echo 80; } +MAXW=$(( $(cols) - 12 )); [ "$MAXW" -lt 40 ] && MAXW=70 +BEGIN=$(date +%s) +timestamp() { s=$(( $(date +%s) - BEGIN )); printf '[%02d:%02d]' $((s/60)) $((s%60)); } + +############################################################################### +# run_one # +############################################################################### +run_one() { + fn=$1 title=$2 + tmp=$(mktemp -d) || { echo "Failed to create temp directory" >&2; exit 1; } + log="$tmp/log" + + echo "╭ » Run test: $title" + START=$(date +%s) + skip_next="+ $fn" # первую строку трассировки с именем функции пропустим + + { + ( + PS4='+ ' # prefix for set -x + set -eu -x # strict + trace + "$fn" + ) + printf '__RC__%s\n' "$?" + } 2>&1 | tee "$log" | while IFS= read -r line; do + case "$line" in + '__RC__'*) : ;; + '+ '*) cmd=${line#'+ '} + [ "$cmd" = "${skip_next#+ }" ] && continue + case "$cmd" in + 'set -e'|'set -x'|'set -u'|'return 0') continue ;; + esac + out=$cmd ;; + *) out=$line ;; + esac + now=$(( $(date +%s) - START )) + [ ${#out} -gt "$MAXW" ] && out="$(printf '%.*s…' "$MAXW" "$out")" + printf '┊[%02d:%02d] %s\n' $((now/60)) $((now%60)) "$out" + done + + rc=$(awk '/^__RC__/ {print substr($0,7)}' "$log" | tail -n1) + [ -z "$rc" ] && rc=1 + now=$(( $(date +%s) - START )) + + if [ "$rc" -eq 0 ]; then + printf '╰[%02d:%02d] ✅ Test OK: %s\n' $((now/60)) $((now%60)) "$title" + else + printf '╰[%02d:%02d] ❌ Test failed: %s (exit %s)\n' \ + $((now/60)) $((now%60)) "$title" "$rc" + echo "----- captured output -----------------------------------------" + grep -v '^__RC__' "$log" + echo "$LINE" + exit "$rc" + fi + + rm -rf "$tmp" +} + +############################################################################### +# convert .bats -> shell-functions # +############################################################################### +TMP_SH=$(mktemp) || { echo "Failed to create temp file" >&2; exit 1; } +trap 'rm -f "$TMP_SH"' EXIT +awk ' + /^@test[[:space:]]+"/ { + line = substr($0, index($0, "\"") + 1) + title = substr(line, 1, index(line, "\"") - 1) + fname = "test_" + for (i = 1; i <= length(title); i++) { + c = substr(title, i, 1) + fname = fname (c ~ /[A-Za-z0-9]/ ? c : "_") + } + printf("### %s\n", title) + printf("%s() {\n", fname) + print " set -e" # ошибка → падение теста + next + } + /^}$/ { + print " return 0" # если автор не сделал exit 1 — тест ОК + print "}" + next + } + { print } +' "$TEST_FILE" > "$TMP_SH" + +[ -f "$TMP_SH" ] || { echo "Failed to generate test functions" >&2; exit 1; } +# shellcheck disable=SC1090 +. "$TMP_SH" + +############################################################################### +# run selected tests # +############################################################################### +awk -v pat="$PATTERN" ' + /^### / { + title = substr($0, 5) + name = "test_" + for (i = 1; i <= length(title); i++) { + c = substr(title, i, 1) + name = name (c ~ /[A-Za-z0-9]/ ? c : "_") + } + if (pat == "*" || index(title, pat) > 0) + printf("%s %s\n", name, title) + } +' "$TMP_SH" | while IFS=' ' read -r fn title; do + run_one "$fn" "$title" +done diff --git a/hack/e2e.bats b/hack/e2e.bats new file mode 100755 index 00000000..3e782162 --- /dev/null +++ b/hack/e2e.bats @@ -0,0 +1,387 @@ +#!/usr/bin/env bats +# ----------------------------------------------------------------------------- +# Cozystack end‑to‑end provisioning test (Bats) +# ----------------------------------------------------------------------------- + +export TALOSCONFIG=$PWD/talosconfig +export KUBECONFIG=$PWD/kubeconfig + +@test "Environment variable COZYSTACK_INSTALLER_YAML is defined" { + if [ -z "${COZYSTACK_INSTALLER_YAML:-}" ]; then + echo 'COZYSTACK_INSTALLER_YAML environment variable is not set!' >&2 + echo >&2 + echo 'Please export it with the following command:' >&2 + echo ' export COZYSTACK_INSTALLER_YAML=$(helm template -n cozy-system installer packages/core/installer)' >&2 + exit 1 + fi +} + +@test "IPv4 forwarding is enabled" { + if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != 1 ]; then + echo "IPv4 forwarding is disabled!" >&2 + echo >&2 + echo "Enable it with:" >&2 + echo " echo 1 > /proc/sys/net/ipv4/ip_forward" >&2 + exit 1 + fi +} + +@test "Clean previous VMs" { + kill $(cat srv1/qemu.pid srv2/qemu.pid srv3/qemu.pid 2>/dev/null) 2>/dev/null || true + rm -rf srv1 srv2 srv3 +} + +@test "Prepare networking and masquerading" { + ip link del cozy-br0 2>/dev/null || true + ip link add cozy-br0 type bridge + ip link set cozy-br0 up + ip address add 192.168.123.1/24 dev cozy-br0 + + # Masquerading rule – idempotent (delete first, then add) + iptables -t nat -D POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE 2>/dev/null || true + iptables -t nat -A POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE +} + +@test "Prepare cloud‑init drive for VMs" { + mkdir -p srv1 srv2 srv3 + + # Generate cloud‑init ISOs + for i in 1 2 3; do + echo "hostname: srv${i}" > "srv${i}/meta-data" + + cat > "srv${i}/user-data" <<'EOF' +#cloud-config +EOF + + cat > "srv${i}/network-config" <<EOF +version: 2 +ethernets: + eth0: + dhcp4: false + addresses: + - "192.168.123.1${i}/26" + gateway4: "192.168.123.1" + nameservers: + search: [cluster.local] + addresses: [8.8.8.8] +EOF + + ( cd "srv${i}" && genisoimage \ + -output seed.img \ + -volid cidata -rational-rock -joliet \ + user-data meta-data network-config ) + done +} + +@test "Download Talos NoCloud image" { + if [ ! -f nocloud-amd64.raw ]; then + wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz \ + -O nocloud-amd64.raw.xz --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null + rm -f nocloud-amd64.raw + xz --decompress nocloud-amd64.raw.xz + fi +} + +@test "Prepare VM disks" { + for i in 1 2 3; do + cp nocloud-amd64.raw srv${i}/system.img + qemu-img resize srv${i}/system.img 20G + qemu-img create srv${i}/data.img 100G + done +} + +@test "Create tap devices" { + for i in 1 2 3; do + ip link del cozy-srv${i} 2>/dev/null || true + ip tuntap add dev cozy-srv${i} mode tap + ip link set cozy-srv${i} up + ip link set cozy-srv${i} master cozy-br0 + done +} + +@test "Boot QEMU VMs" { + for i in 1 2 3; do + qemu-system-x86_64 -machine type=pc,accel=kvm -cpu host -smp 8 -m 16384 \ + -device virtio-net,netdev=net0,mac=52:54:00:12:34:5${i} \ + -netdev tap,id=net0,ifname=cozy-srv${i},script=no,downscript=no \ + -drive file=srv${i}/system.img,if=virtio,format=raw \ + -drive file=srv${i}/seed.img,if=virtio,format=raw \ + -drive file=srv${i}/data.img,if=virtio,format=raw \ + -display none -daemonize -pidfile srv${i}/qemu.pid + done + + # Give qemu a few seconds to start up networking + sleep 5 +} + +@test "Wait until Talos API port 50000 is reachable on all machines" { + timeout 60 sh -ec 'until nc -nz 192.168.123.11 50000 && nc -nz 192.168.123.12 50000 && nc -nz 192.168.123.13 50000; do sleep 1; done' +} + +@test "Generate Talos cluster configuration" { + # Cluster‑wide patches + cat > patch.yaml <<'EOF' +machine: + kubelet: + nodeIP: + validSubnets: + - 192.168.123.0/24 + extraConfig: + maxPods: 512 + kernel: + modules: + - name: openvswitch + - name: drbd + parameters: + - usermode_helper=disabled + - name: zfs + - name: spl + registries: + mirrors: + docker.io: + endpoints: + - https://mirror.gcr.io + files: + - content: | + [plugins] + [plugins."io.containerd.cri.v1.runtime"] + device_ownership_from_security_context = true + path: /etc/cri/conf.d/20-customization.part + op: create + +cluster: + apiServer: + extraArgs: + oidc-issuer-url: "https://keycloak.example.org/realms/cozy" + oidc-client-id: "kubernetes" + oidc-username-claim: "preferred_username" + oidc-groups-claim: "groups" + network: + cni: + name: none + dnsDomain: cozy.local + podSubnets: + - 10.244.0.0/16 + serviceSubnets: + - 10.96.0.0/16 +EOF + + # Control‑plane‑only patches + cat > patch-controlplane.yaml <<'EOF' +machine: + nodeLabels: + node.kubernetes.io/exclude-from-external-load-balancers: + $patch: delete + network: + interfaces: + - interface: eth0 + vip: + ip: 192.168.123.10 +cluster: + allowSchedulingOnControlPlanes: true + controllerManager: + extraArgs: + bind-address: 0.0.0.0 + scheduler: + extraArgs: + bind-address: 0.0.0.0 + apiServer: + certSANs: + - 127.0.0.1 + proxy: + disabled: true + discovery: + enabled: false + etcd: + advertisedSubnets: + - 192.168.123.0/24 +EOF + + # Generate secrets once + if [ ! -f secrets.yaml ]; then + talosctl gen secrets + fi + + rm -f controlplane.yaml worker.yaml talosconfig kubeconfig + talosctl gen config --with-secrets secrets.yaml cozystack https://192.168.123.10:6443 \ + --config-patch=@patch.yaml --config-patch-control-plane @patch-controlplane.yaml +} + +@test "Apply Talos configuration to the node" { + # Apply the configuration to all three nodes + for node in 11 12 13; do + talosctl apply -f controlplane.yaml -n 192.168.123.${node} -e 192.168.123.${node} -i + done + + # Wait for Talos services to come up again + timeout 60 sh -ec 'until nc -nz 192.168.123.11 50000 && nc -nz 192.168.123.12 50000 && nc -nz 192.168.123.13 50000; do sleep 1; done' +} + +@test "Bootstrap Talos cluster" { + # Bootstrap etcd on the first node + timeout 10 sh -ec 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 1; done' + + # Wait until etcd is healthy + timeout 180 sh -ec 'until talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 >/dev/null 2>&1; do sleep 1; done' + timeout 60 sh -ec 'while talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 2>&1 | grep -q "rpc error"; do sleep 1; done' + + # Retrieve kubeconfig + rm -f kubeconfig + talosctl kubeconfig kubeconfig -e 192.168.123.10 -n 192.168.123.10 + + # Wait until all three nodes register in Kubernetes + timeout 60 sh -ec 'until [ $(kubectl get node --no-headers | wc -l) -eq 3 ]; do sleep 1; done' +} + +@test "Install Cozystack" { + # Create namespace & configmap required by installer + kubectl create namespace cozy-system --dry-run=client -o yaml | kubectl apply -f - + kubectl create configmap cozystack -n cozy-system \ + --from-literal=bundle-name=paas-full \ + --from-literal=ipv4-pod-cidr=10.244.0.0/16 \ + --from-literal=ipv4-pod-gateway=10.244.0.1 \ + --from-literal=ipv4-svc-cidr=10.96.0.0/16 \ + --from-literal=ipv4-join-cidr=100.64.0.0/16 \ + --from-literal=root-host=example.org \ + --from-literal=api-server-endpoint=https://192.168.123.10:6443 \ + --dry-run=client -o yaml | kubectl apply -f - + + # Apply installer manifests from env variable + echo "$COZYSTACK_INSTALLER_YAML" | kubectl apply -f - + + # Wait for the installer deployment to become available + kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available + + # Wait until HelmReleases appear & reconcile them + timeout 60 sh -ec 'until kubectl get hr -A | grep -q cozys; do sleep 1; done' + sleep 5 + kubectl get hr -A | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n "$1" hr/"$2" &"} END {print "wait"}' | sh -ex + + # Fail the test if any HelmRelease is not Ready + if kubectl get hr -A | grep -v " True " | grep -v NAME; then + kubectl get hr -A + fail "Some HelmReleases failed to reconcile" + fi +} + +@test "Wait for Cluster‑API provider deployments" { + # Wait for Cluster‑API provider deployments + timeout 60 sh -ec 'until kubectl get deploy -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager >/dev/null 2>&1; do sleep 1; done' + kubectl wait deployment/capi-controller-manager deployment/capi-kamaji-controller-manager deployment/capi-kubeadm-bootstrap-controller-manager deployment/capi-operator-cluster-api-operator deployment/capk-controller-manager -n cozy-cluster-api --timeout=1m --for=condition=available +} + +@test "Wait for LINSTOR and configure storage" { + # Linstor controller and nodes + kubectl wait deployment/linstor-controller -n cozy-linstor --timeout=5m --for=condition=available + timeout 60 sh -ec 'until [ $(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor node list | grep -c Online) -eq 3 ]; do sleep 1; done' + + for node in srv1 srv2 srv3; do + kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data + done + + # Storage classes + kubectl apply -f - <<'EOF' +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: local + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: linstor.csi.linbit.com +parameters: + linstor.csi.linbit.com/storagePool: "data" + linstor.csi.linbit.com/layerList: "storage" + linstor.csi.linbit.com/allowRemoteVolumeAccess: "false" +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: replicated +provisioner: linstor.csi.linbit.com +parameters: + linstor.csi.linbit.com/storagePool: "data" + linstor.csi.linbit.com/autoPlace: "3" + linstor.csi.linbit.com/layerList: "drbd storage" + linstor.csi.linbit.com/allowRemoteVolumeAccess: "true" + property.linstor.csi.linbit.com/DrbdOptions/auto-quorum: suspend-io + property.linstor.csi.linbit.com/DrbdOptions/Resource/on-no-data-accessible: suspend-io + property.linstor.csi.linbit.com/DrbdOptions/Resource/on-suspended-primary-outdated: force-secondary + property.linstor.csi.linbit.com/DrbdOptions/Net/rr-conflict: retry-connect +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +EOF +} + +@test "Wait for MetalLB and configure address pool" { + # MetalLB address pool + kubectl apply -f - <<'EOF' +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: cozystack + namespace: cozy-metallb +spec: + ipAddressPools: [cozystack] +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: cozystack + namespace: cozy-metallb +spec: + addresses: [192.168.123.200-192.168.123.250] + autoAssign: true + avoidBuggyIPs: false +EOF +} + +@test "Check Cozystack API service" { + kubectl wait --for=condition=Available apiservices/v1alpha1.apps.cozystack.io --timeout=2m +} + +@test "Configure Tenant and wait for applications" { + # Patch root tenant and wait for its releases + kubectl patch tenants/root -n tenant-root --type merge -p '{"spec":{"host":"example.org","ingress":true,"monitoring":true,"etcd":true,"isolated":true}}' + + timeout 60 sh -ec 'until kubectl get hr -n tenant-root etcd ingress monitoring tenant-root >/dev/null 2>&1; do sleep 1; done' + kubectl wait hr/etcd hr/ingress hr/tenant-root -n tenant-root --timeout=2m --for=condition=ready + + if ! kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready; then + flux reconcile hr monitoring -n tenant-root --force + kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready + fi + + # Expose Cozystack services through ingress + kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"expose-services":"api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak"}}' + + # NGINX ingress controller + timeout 60 sh -ec 'until kubectl get deploy root-ingress-controller -n tenant-root >/dev/null 2>&1; do sleep 1; done' + kubectl wait deploy/root-ingress-controller -n tenant-root --timeout=5m --for=condition=available + + # etcd statefulset + kubectl wait sts/etcd -n tenant-root --for=jsonpath='{.status.readyReplicas}'=3 --timeout=5m + + # VictoriaMetrics components + kubectl wait vmalert/vmalert-shortterm vmalertmanager/alertmanager -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m + kubectl wait vlogs/generic -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m + kubectl wait vmcluster/shortterm vmcluster/longterm -n tenant-root --for=jsonpath='{.status.clusterStatus}'=operational --timeout=5m + + # Grafana + kubectl wait clusters.postgresql.cnpg.io/grafana-db -n tenant-root --for=condition=ready --timeout=5m + kubectl wait deploy/grafana-deployment -n tenant-root --for=condition=available --timeout=5m + + # Verify Grafana via ingress + ingress_ip=$(kubectl get svc root-ingress-controller -n tenant-root -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + curl -sS -k "https://${ingress_ip}" -H 'Host: grafana.example.org' | grep -q Found +} + +@test "Keycloak OIDC stack is healthy" { + kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"oidc-enabled":"true"}}' + + timeout 120 sh -ec 'until kubectl get hr -n cozy-keycloak keycloak keycloak-configure keycloak-operator >/dev/null 2>&1; do sleep 1; done' + kubectl wait hr/keycloak hr/keycloak-configure hr/keycloak-operator -n cozy-keycloak --timeout=10m --for=condition=ready +} diff --git a/hack/e2e.sh b/hack/e2e.sh deleted file mode 100755 index 46c9ba5b..00000000 --- a/hack/e2e.sh +++ /dev/null @@ -1,370 +0,0 @@ -#!/bin/bash -if [ "$COZYSTACK_INSTALLER_YAML" = "" ]; then - echo 'COZYSTACK_INSTALLER_YAML variable is not set!' >&2 - echo 'please set it with following command:' >&2 - echo >&2 - echo 'export COZYSTACK_INSTALLER_YAML=$(helm template -n cozy-system installer packages/core/installer)' >&2 - echo >&2 - exit 1 -fi - -if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != 1 ]; then - echo "IPv4 forwarding is not enabled!" >&2 - echo 'please enable forwarding with the following command:' >&2 - echo >&2 - echo 'echo 1 > /proc/sys/net/ipv4/ip_forward' >&2 - echo >&2 - exit 1 -fi - -set -x -set -e - -kill `cat srv1/qemu.pid srv2/qemu.pid srv3/qemu.pid` || true - -ip link del cozy-br0 || true -ip link add cozy-br0 type bridge -ip link set cozy-br0 up -ip addr add 192.168.123.1/24 dev cozy-br0 - -# Enable masquerading -iptables -t nat -D POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE 2>/dev/null || true -iptables -t nat -A POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE - -rm -rf srv1 srv2 srv3 -mkdir -p srv1 srv2 srv3 - -# Prepare cloud-init -for i in 1 2 3; do - echo "hostname: srv$i" > "srv$i/meta-data" - echo '#cloud-config' > "srv$i/user-data" - cat > "srv$i/network-config" <<EOT -version: 2 -ethernets: - eth0: - dhcp4: false - addresses: - - "192.168.123.1$i/26" - gateway4: "192.168.123.1" - nameservers: - search: [cluster.local] - addresses: [8.8.8.8] -EOT - - ( cd srv$i && genisoimage \ - -output seed.img \ - -volid cidata -rational-rock -joliet \ - user-data meta-data network-config - ) -done - -# Prepare system drive -if [ ! -f nocloud-amd64.raw ]; then - wget https://github.com/cozystack/cozystack/releases/latest/download/nocloud-amd64.raw.xz \ - -O nocloud-amd64.raw.xz --show-progress --output-file /dev/stdout --progress=dot:giga 2>/dev/null - rm -f nocloud-amd64.raw - xz --decompress nocloud-amd64.raw.xz -fi -for i in 1 2 3; do - cp nocloud-amd64.raw srv$i/system.img - qemu-img resize srv$i/system.img 20G -done - -# Prepare data drives -for i in 1 2 3; do - qemu-img create srv$i/data.img 100G -done - -# Prepare networking -for i in 1 2 3; do - ip link del cozy-srv$i || true - ip tuntap add dev cozy-srv$i mode tap - ip link set cozy-srv$i up - ip link set cozy-srv$i master cozy-br0 -done - -# Start VMs -for i in 1 2 3; do - qemu-system-x86_64 -machine type=pc,accel=kvm -cpu host -smp 8 -m 16384 \ - -device virtio-net,netdev=net0,mac=52:54:00:12:34:5$i \ - -netdev tap,id=net0,ifname=cozy-srv$i,script=no,downscript=no \ - -drive file=srv$i/system.img,if=virtio,format=raw \ - -drive file=srv$i/seed.img,if=virtio,format=raw \ - -drive file=srv$i/data.img,if=virtio,format=raw \ - -display none -daemonize -pidfile srv$i/qemu.pid -done - -sleep 5 - -# Wait for VM to start up -timeout 60 sh -c 'until nc -nzv 192.168.123.11 50000 && nc -nzv 192.168.123.12 50000 && nc -nzv 192.168.123.13 50000; do sleep 1; done' - -cat > patch.yaml <<\EOT -machine: - kubelet: - nodeIP: - validSubnets: - - 192.168.123.0/24 - extraConfig: - maxPods: 512 - kernel: - modules: - - name: openvswitch - - name: drbd - parameters: - - usermode_helper=disabled - - name: zfs - - name: spl - registries: - mirrors: - docker.io: - endpoints: - - https://mirror.gcr.io - files: - - content: | - [plugins] - [plugins."io.containerd.cri.v1.runtime"] - device_ownership_from_security_context = true - path: /etc/cri/conf.d/20-customization.part - op: create - -cluster: - apiServer: - extraArgs: - oidc-issuer-url: "https://keycloak.example.org/realms/cozy" - oidc-client-id: "kubernetes" - oidc-username-claim: "preferred_username" - oidc-groups-claim: "groups" - network: - cni: - name: none - dnsDomain: cozy.local - podSubnets: - - 10.244.0.0/16 - serviceSubnets: - - 10.96.0.0/16 -EOT - -cat > patch-controlplane.yaml <<\EOT -machine: - nodeLabels: - node.kubernetes.io/exclude-from-external-load-balancers: - $patch: delete - network: - interfaces: - - interface: eth0 - vip: - ip: 192.168.123.10 -cluster: - allowSchedulingOnControlPlanes: true - controllerManager: - extraArgs: - bind-address: 0.0.0.0 - scheduler: - extraArgs: - bind-address: 0.0.0.0 - apiServer: - certSANs: - - 127.0.0.1 - proxy: - disabled: true - discovery: - enabled: false - etcd: - advertisedSubnets: - - 192.168.123.0/24 -EOT - -# Gen configuration -if [ ! -f secrets.yaml ]; then - talosctl gen secrets -fi - -rm -f controlplane.yaml worker.yaml talosconfig kubeconfig -talosctl gen config --with-secrets secrets.yaml cozystack https://192.168.123.10:6443 --config-patch=@patch.yaml --config-patch-control-plane @patch-controlplane.yaml -export TALOSCONFIG=$PWD/talosconfig - -# Apply configuration -talosctl apply -f controlplane.yaml -n 192.168.123.11 -e 192.168.123.11 -i -talosctl apply -f controlplane.yaml -n 192.168.123.12 -e 192.168.123.12 -i -talosctl apply -f controlplane.yaml -n 192.168.123.13 -e 192.168.123.13 -i - -# Wait for VM to be configured -timeout 60 sh -c 'until nc -nzv 192.168.123.11 50000 && nc -nzv 192.168.123.12 50000 && nc -nzv 192.168.123.13 50000; do sleep 1; done' - -# Bootstrap -timeout 10 sh -c 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 1; done' - -# Wait for etcd -timeout 180 sh -c 'until timeout -s 9 2 talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 2>&1; do sleep 1; done' -timeout 60 sh -c 'while talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 2>&1 | grep "rpc error"; do sleep 1; done' - -rm -f kubeconfig -talosctl kubeconfig kubeconfig -e 192.168.123.10 -n 192.168.123.10 -export KUBECONFIG=$PWD/kubeconfig - -# Wait for kubernetes nodes appear -timeout 60 sh -c 'until [ $(kubectl get node -o name | wc -l) = 3 ]; do sleep 1; done' -kubectl create ns cozy-system -o yaml | kubectl apply -f - -kubectl create -f - <<\EOT -apiVersion: v1 -kind: ConfigMap -metadata: - name: cozystack - namespace: cozy-system -data: - bundle-name: "paas-full" - ipv4-pod-cidr: "10.244.0.0/16" - ipv4-pod-gateway: "10.244.0.1" - ipv4-svc-cidr: "10.96.0.0/16" - ipv4-join-cidr: "100.64.0.0/16" - root-host: example.org - api-server-endpoint: https://192.168.123.10:6443 -EOT - -# -echo "$COZYSTACK_INSTALLER_YAML" | kubectl apply -f - - -# wait for cozystack pod to start -kubectl wait deploy --timeout=1m --for=condition=available -n cozy-system cozystack - -# wait for helmreleases appear -timeout 60 sh -c 'until kubectl get hr -A | grep cozy; do sleep 1; done' - -sleep 5 - -# Wait for all HelmReleases to be installed -kubectl get hr -A | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n " $1 " hr/" $2 " &"} END{print "wait"}' | sh -x - -failed_hrs=$(kubectl get hr -A | grep -v True) -if [ -n "$(echo "$failed_hrs" | grep -v NAME)" ]; then - printf 'Failed HelmReleases:\n%s\n' "$failed_hrs" >&2 - exit 1 -fi - -# Wait for Cluster-API providers -timeout 60 sh -c 'until kubectl get deploy -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager; do sleep 1; done' -kubectl wait deploy --timeout=1m --for=condition=available -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager - -# Wait for linstor controller -kubectl wait deploy --timeout=5m --for=condition=available -n cozy-linstor linstor-controller - -# Wait for all linstor nodes become Online -timeout 60 sh -c 'until [ $(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor node list | grep -c Online) = 3 ]; do sleep 1; done' - -kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs srv1 /dev/vdc --pool-name data --storage-pool data -kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs srv2 /dev/vdc --pool-name data --storage-pool data -kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs srv3 /dev/vdc --pool-name data --storage-pool data - -kubectl create -f- <<EOT ---- -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: local - annotations: - storageclass.kubernetes.io/is-default-class: "true" -provisioner: linstor.csi.linbit.com -parameters: - linstor.csi.linbit.com/storagePool: "data" - linstor.csi.linbit.com/layerList: "storage" - linstor.csi.linbit.com/allowRemoteVolumeAccess: "false" -volumeBindingMode: WaitForFirstConsumer -allowVolumeExpansion: true ---- -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: replicated -provisioner: linstor.csi.linbit.com -parameters: - linstor.csi.linbit.com/storagePool: "data" - linstor.csi.linbit.com/autoPlace: "3" - linstor.csi.linbit.com/layerList: "drbd storage" - linstor.csi.linbit.com/allowRemoteVolumeAccess: "true" - property.linstor.csi.linbit.com/DrbdOptions/auto-quorum: suspend-io - property.linstor.csi.linbit.com/DrbdOptions/Resource/on-no-data-accessible: suspend-io - property.linstor.csi.linbit.com/DrbdOptions/Resource/on-suspended-primary-outdated: force-secondary - property.linstor.csi.linbit.com/DrbdOptions/Net/rr-conflict: retry-connect -volumeBindingMode: WaitForFirstConsumer -allowVolumeExpansion: true -EOT -kubectl create -f- <<EOT ---- -apiVersion: metallb.io/v1beta1 -kind: L2Advertisement -metadata: - name: cozystack - namespace: cozy-metallb -spec: - ipAddressPools: - - cozystack ---- -apiVersion: metallb.io/v1beta1 -kind: IPAddressPool -metadata: - name: cozystack - namespace: cozy-metallb -spec: - addresses: - - 192.168.123.200-192.168.123.250 - autoAssign: true - avoidBuggyIPs: false -EOT - -# Wait for cozystack-api -kubectl wait --for=condition=Available apiservices v1alpha1.apps.cozystack.io --timeout=2m - -kubectl patch -n tenant-root tenants.apps.cozystack.io root --type=merge -p '{"spec":{ - "host": "example.org", - "ingress": true, - "monitoring": true, - "etcd": true, - "isolated": true -}}' - -# Wait for HelmRelease be created -timeout 60 sh -c 'until kubectl get hr -n tenant-root etcd ingress monitoring tenant-root; do sleep 1; done' - -# Wait for HelmReleases be installed -kubectl wait --timeout=2m --for=condition=ready -n tenant-root hr etcd ingress tenant-root - -if ! kubectl wait --timeout=2m --for=condition=ready -n tenant-root hr monitoring; then - flux reconcile hr monitoring -n tenant-root --force - kubectl wait --timeout=2m --for=condition=ready -n tenant-root hr monitoring -fi - -kubectl patch -n cozy-system cm cozystack --type=merge -p '{"data":{ - "expose-services": "api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak" -}}' - -# Wait for nginx-ingress-controller -timeout 60 sh -c 'until kubectl get deploy -n tenant-root root-ingress-controller; do sleep 1; done' -kubectl wait --timeout=5m --for=condition=available -n tenant-root deploy root-ingress-controller - -# Wait for etcd -kubectl wait --timeout=5m --for=jsonpath=.status.readyReplicas=3 -n tenant-root sts etcd - -# Wait for Victoria metrics -kubectl wait --timeout=5m --for=jsonpath=.status.updateStatus=operational -n tenant-root vmalert/vmalert-shortterm vmalertmanager/alertmanager -kubectl wait --timeout=5m --for=jsonpath=.status.updateStatus=operational -n tenant-root vlogs/generic -kubectl wait --timeout=5m --for=jsonpath=.status.clusterStatus=operational -n tenant-root vmcluster/shortterm vmcluster/longterm - -# Wait for grafana -kubectl wait --timeout=5m --for=condition=ready -n tenant-root clusters.postgresql.cnpg.io grafana-db -kubectl wait --timeout=5m --for=condition=available -n tenant-root deploy grafana-deployment - -# Get IP of nginx-ingress -ip=$(kubectl get svc -n tenant-root root-ingress-controller -o jsonpath='{.status.loadBalancer.ingress..ip}') - -# Check Grafana -curl -sS -k "https://$ip" -H 'Host: grafana.example.org' | grep Found - - -# Test OIDC -kubectl patch -n cozy-system cm/cozystack --type=merge -p '{"data":{ - "oidc-enabled": "true" -}}' - -timeout 120 sh -c 'until kubectl get hr -n cozy-keycloak keycloak keycloak-configure keycloak-operator; do sleep 1; done' -kubectl wait --timeout=10m --for=condition=ready -n cozy-keycloak hr keycloak keycloak-configure keycloak-operator diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index b620c947..2b67da45 100755 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -31,7 +31,7 @@ image-e2e-sandbox: rm -f images/e2e-sandbox.json test: ## Run the end-to-end tests in existing sandbox. - docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/e2e.sh' + docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/cozytest.sh hack/e2e.bats' delete: ## Remove sandbox from existing Kubernetes cluster. docker rm -f "${SANDBOX_NAME}" || true From 74e7e5cdfb5c192c03a3a43ea564607014324aa1 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil <kvapss@gmail.com> Date: Sat, 24 May 2025 22:42:54 +0200 Subject: [PATCH 106/120] [tests] Add tests for tenant Kubernetes cluster Signed-off-by: Andrei Kvapil <kvapss@gmail.com> --- hack/e2e-apps.bats | 94 +++++++++++++++++++++++++++++ hack/{e2e.bats => e2e-cluster.bats} | 8 +-- packages/core/testing/Makefile | 16 ++++- 3 files changed, 111 insertions(+), 7 deletions(-) create mode 100755 hack/e2e-apps.bats rename hack/{e2e.bats => e2e-cluster.bats} (98%) diff --git a/hack/e2e-apps.bats b/hack/e2e-apps.bats new file mode 100755 index 00000000..9610a64a --- /dev/null +++ b/hack/e2e-apps.bats @@ -0,0 +1,94 @@ +#!/usr/bin/env bats +# ----------------------------------------------------------------------------- +# Cozystack end‑to‑end provisioning test (Bats) +# ----------------------------------------------------------------------------- + +@test "Create tenant with isolated mode enabled" { + kubectl create -f - <<EOF +apiVersion: apps.cozystack.io/v1alpha1 +kind: Tenant +metadata: + name: test + namespace: tenant-root +spec: + etcd: false + host: "" + ingress: false + isolated: true + monitoring: false + resourceQuotas: {} + seaweedfs: false +EOF + kubectl wait hr/tenant-test -n tenant-root --timeout=1m --for=condition=ready + kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active +} + +@test "Create a tenant Kubernetes control plane" { + kubectl create -f - <<EOF +apiVersion: apps.cozystack.io/v1alpha1 +kind: Kubernetes +metadata: + name: test + namespace: tenant-test +spec: + addons: + certManager: + enabled: false + valuesOverride: {} + cilium: + valuesOverride: {} + fluxcd: + enabled: false + valuesOverride: {} + gatewayAPI: + enabled: false + gpuOperator: + enabled: false + valuesOverride: {} + ingressNginx: + enabled: true + hosts: [] + valuesOverride: {} + monitoringAgents: + enabled: false + valuesOverride: {} + verticalPodAutoscaler: + valuesOverride: {} + controlPlane: + apiServer: + resources: {} + resourcesPreset: small + controllerManager: + resources: {} + resourcesPreset: micro + konnectivity: + server: + resources: {} + resourcesPreset: micro + replicas: 2 + scheduler: + resources: {} + resourcesPreset: micro + host: "" + nodeGroups: + md0: + ephemeralStorage: 20Gi + gpus: [] + instanceType: u1.medium + maxReplicas: 10 + minReplicas: 0 + resources: + cpu: "" + memory: "" + roles: + - ingress-nginx + storageClass: replicated +EOF + kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active + timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-test; do sleep 1; done' + kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-test --timeout=4m + kubectl wait tcp -n tenant-test kubernetes-test --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready + kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-test kubernetes-test-cluster-autoscaler kubernetes-test-kccm kubernetes-test-kcsi-controller + kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2 + kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=5m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2 +} diff --git a/hack/e2e.bats b/hack/e2e-cluster.bats similarity index 98% rename from hack/e2e.bats rename to hack/e2e-cluster.bats index 3e782162..39e2aff4 100755 --- a/hack/e2e.bats +++ b/hack/e2e-cluster.bats @@ -3,9 +3,6 @@ # Cozystack end‑to‑end provisioning test (Bats) # ----------------------------------------------------------------------------- -export TALOSCONFIG=$PWD/talosconfig -export KUBECONFIG=$PWD/kubeconfig - @test "Environment variable COZYSTACK_INSTALLER_YAML is defined" { if [ -z "${COZYSTACK_INSTALLER_YAML:-}" ]; then echo 'COZYSTACK_INSTALLER_YAML environment variable is not set!' >&2 @@ -376,7 +373,10 @@ EOF # Verify Grafana via ingress ingress_ip=$(kubectl get svc root-ingress-controller -n tenant-root -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - curl -sS -k "https://${ingress_ip}" -H 'Host: grafana.example.org' | grep -q Found + if ! curl -sS -k "https://${ingress_ip}" -H 'Host: grafana.example.org' --max-time 30 | grep -q Found; then + echo "Failed to access Grafana via ingress at ${ingress_ip}" >&2 + exit 1 + fi } @test "Keycloak OIDC stack is healthy" { diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index 2b67da45..f3a97eee 100755 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -30,8 +30,13 @@ image-e2e-sandbox: yq -i '.e2e.image = strenv(IMAGE)' values.yaml rm -f images/e2e-sandbox.json -test: ## Run the end-to-end tests in existing sandbox. - docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/cozytest.sh hack/e2e.bats' +test: test-cluster test-apps ## Run the end-to-end tests in existing sandbox + +test-cluster: ## Run the end-to-end for creating a cluster + docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/cozytest.sh hack/e2e-cluster.bats' + +test-apps: ## Run the end-to-end tests for apps + docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-apps.bats' delete: ## Remove sandbox from existing Kubernetes cluster. docker rm -f "${SANDBOX_NAME}" || true @@ -40,5 +45,10 @@ exec: ## Opens an interactive shell in the sandbox container. docker exec -ti "${SANDBOX_NAME}" bash apply: delete - docker run -d --rm --name "${SANDBOX_NAME}" --privileged "$$(yq .e2e.image values.yaml)" sleep infinity + docker run \ + -d --rm --name "${SANDBOX_NAME}" --privileged \ + -e TALOSCONFIG=/workspace/talosconfig \ + -e KUBECONFIG=/workspace/kubeconfig \ + "$$(yq .e2e.image values.yaml)" \ + sleep infinity docker cp "${ROOT_DIR}" "${SANDBOX_NAME}":/workspace From ae0549f78b7aeae1450221a7a15356e31e8558bb Mon Sep 17 00:00:00 2001 From: github-actions <github-actions@github.com> Date: Mon, 26 May 2025 08:26:01 +0000 Subject: [PATCH 107/120] Prepare release v0.31.0-rc.3 Signed-off-by: github-actions <github-actions@github.com> --- packages/apps/clickhouse/images/clickhouse-backup.tag | 2 +- packages/apps/kubernetes/images/cluster-autoscaler.tag | 2 +- packages/apps/kubernetes/images/kubevirt-cloud-provider.tag | 2 +- packages/apps/kubernetes/images/kubevirt-csi-driver.tag | 2 +- packages/apps/kubernetes/images/ubuntu-container-disk.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 4 ++-- .../charts/kubeapps/templates/dashboard/configmap.yaml | 2 +- packages/system/dashboard/values.yaml | 6 +++--- packages/system/kamaji/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/apps/clickhouse/images/clickhouse-backup.tag b/packages/apps/clickhouse/images/clickhouse-backup.tag index 05e456bb..1972c5d9 100644 --- a/packages/apps/clickhouse/images/clickhouse-backup.tag +++ b/packages/apps/clickhouse/images/clickhouse-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/clickhouse-backup:0.8.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205 +ghcr.io/cozystack/cozystack/clickhouse-backup:0.9.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205 diff --git a/packages/apps/kubernetes/images/cluster-autoscaler.tag b/packages/apps/kubernetes/images/cluster-autoscaler.tag index df0570b6..f14e64e5 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler.tag +++ b/packages/apps/kubernetes/images/cluster-autoscaler.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/cluster-autoscaler:0.20.0@sha256:8dbbe95fe8b933a1d1a3c638120f386fec0c4950092d3be5ddd592375bb8a760 +ghcr.io/cozystack/cozystack/cluster-autoscaler:0.20.1@sha256:720148128917fa10f860a8b7e74f9428de72481c466c880c5ad894e1f0026d43 diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index 4a7d00d5..1ada8d04 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.0@sha256:41fcdbd2f667f68bf554dd184ce362e65b88f350dc7b938c86079b719f5e5099 +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.1@sha256:1b48a4725a33ccb48604bb2e1be3171271e7daac2726d3119228212d8a9da5bb diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index fe5d6308..2c5b03b9 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.0@sha256:61580fea56b745580989d85e3ef2563e9bb1accc9c4185f8e636bacd02551319 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.1@sha256:61580fea56b745580989d85e3ef2563e9bb1accc9c4185f8e636bacd02551319 diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag index 3622c20f..c49750c8 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk.tag +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:186af6f71891bfc6d6948454802c08922baa508c30e7f79e330b7d26ffceff03 +ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:184b81529ae72684279799b12f436cc7a511d8ff5bd1e9a30478799c7707c625 diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index 9343532b..e1a5aa4d 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.2@sha256:05d812a6ac1df86c614b528e8d171af05c0080545ceee383d6cb043f415a4372 + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:a052681717a5dab9011076e8a6669b41b779ad519f88bf347f920a790ad26330 diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index d087c964..4d75ca9c 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.2@sha256:2d35b2cce2f093c5c3145a08d9981e2bf28cf45a6804117d50bd6345a15ecd1a + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:b305b8a640ad4eec94e6953cbfe23313b4b23c3a7df268c040c461d4cc0d28f5 diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index 777d572e..44790044 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.2@sha256:78e5a28badd3c804e55e5c1376f12dad77e04b9f6f80637596939ba348f7104b +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:aa14eb17415fdb5c86288f5d816c6ebb9e58720828df5d88be26c6d556b3ee0f diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 72ba28b3..fb318c00 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:a219040fed290492f047818e5c5a864a30112ff418ad4b12b24de9709302427a +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:42c6a88cac4a7661b002ab345fb0822ed275c38028da2112a7d7f863b50e9629 diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index 4240b0ac..1abd5bb9 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.2@sha256:d3794a5ebd49ee28ef7108213d3bb5053f5247ef62855f4731c7cafb8059a635 + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:36dad15a8dfab883476118ac0724c0e28007fceabfef8159c3d41b285cbbeb45 diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 1362175f..2a59e426 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.2@sha256:fb7cfdf62a128103954f0cb711b2d21650c0d2f7ff639d41a56f68d454a1e4ea + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:18e877ea53d41d91c8e666fea7fe039f392a6c4562f20722bdd20b893986c065 debug: false disableTelemetry: false - cozystackVersion: "v0.31.0-rc.2" + cozystackVersion: "v0.31.0-rc.3" diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml index 17b7263e..3d364d20 100644 --- a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml @@ -76,7 +76,7 @@ data: "kubeappsNamespace": {{ .Release.Namespace | quote }}, "helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }}, "carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }}, - "appVersion": "v0.31.0-rc.2", + "appVersion": "v0.31.0-rc.3", "authProxyEnabled": {{ .Values.authProxy.enabled }}, "oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }}, "oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }}, diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index 0342b829..bd058dec 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -19,7 +19,7 @@ kubeapps: image: registry: ghcr.io/cozystack/cozystack repository: dashboard - tag: v0.31.0-rc.2 + tag: v0.31.0-rc.3 digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93" redis: master: @@ -35,8 +35,8 @@ kubeapps: image: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis - tag: v0.31.0-rc.2 - digest: "sha256:db4f33e9ca6969459c9baf0131c2c342cb6c366df16df7361e7cbdeb4a854cea" + tag: v0.31.0-rc.3 + digest: "sha256:a41cbf5f1d3d23f2d1650cb471dd310f27e4f68df3801250f37fed593018151e" pluginConfig: flux: packages: diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index b278fc6d..828903ab 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,7 +3,7 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: v0.31.0-rc.2@sha256:beb066f5c45cda520e5028222ec26a5e39c2c3c63bc9016e8a6ec49a2379e00c + tag: v0.31.0-rc.3@sha256:5f828637ebd1717a5c2b828352fff7fc14c218c7bbfc2cb2ce55737f9b5bf500 repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 8b86e18e..e0545092 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.2@sha256:f9b464a94bd1a1fa116bbf77c4bbece3931d03dac1489eb820f94d98176ed5c9 +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:c046894c5ccc4af5a91e7088c4d0c3dee4a1ae5a0b1377cc06bc1a7e28a0b64f From e83bf379baa199c9df69c42f8b57fa9c86c44cf5 Mon Sep 17 00:00:00 2001 From: Nick Volynkin <nick.volynkin@gmail.com> Date: Mon, 26 May 2025 13:08:01 +0300 Subject: [PATCH 108/120] [docs] Update release notes for Cozystack v0.31.0-rc.3 Signed-off-by: Nick Volynkin <nick.volynkin@gmail.com> --- docs/changelogs/v0.31.0.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/changelogs/v0.31.0.md b/docs/changelogs/v0.31.0.md index dedf9d4e..2b556e16 100644 --- a/docs/changelogs/v0.31.0.md +++ b/docs/changelogs/v0.31.0.md @@ -1,5 +1,5 @@ -This is the second release candidate for the upcoming Cozystack v0.31.0 release. -The release notes show changes accumulated since the release of Cozystack v0.30.0. +This is the third release candidate for the upcoming Cozystack v0.31.0 release. +The release notes show changes accumulated since the release of previous version, Cozystack v0.30.0. Cozystack 0.31.0 further advances GPU support, monitoring, and all-around convenience features. @@ -12,18 +12,21 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [platform] Cozystack etcd-operator (@klinch0 in https://github.com/cozystack/cozystack/pull/850) * Introduce support for cross-architecture builds and Cozystack on ARM: * [build] Refactor Makefiles introducing build variables. (@nbykov0 in https://github.com/cozystack/cozystack/pull/907) - * [build] Add support for multi-architecture and cross-platform image builds. (@nbykov0 in https://github.com/cozystack/cozystack/pull/932) + * [build] Add support for multi-architecture and cross-platform image builds. (@nbykov0 in https://github.com/cozystack/cozystack/pull/932 and https://github.com/cozystack/cozystack/pull/970) * [platform] Introduce a new controller to synchronize tenant HelmReleases and propagate configuration changes. (@klinch0 in https://github.com/cozystack/cozystack/pull/870) * [platform] Introduce options `expose-services`, `expose-ingress` and `expose-external-ips` to the ingress service. (@kvaps in https://github.com/cozystack/cozystack/pull/929) * [kubevirt] Enable exporting VMs. (@kvaps in https://github.com/cozystack/cozystack/pull/808) * [kubevirt] Make KubeVirt's CPU allocation ratio configurable. (@lllamnyp in https://github.com/cozystack/cozystack/pull/905) +* [virtual-machine] Add support for various storages. (@kvaps in https://github.com/cozystack/cozystack/pull/974) * [cozystack-controller] Record the IP address pool and storage class in Workload objects. (@lllamnyp in https://github.com/cozystack/cozystack/pull/831) * [cilium] Enable Cilium Gateway API. (@zdenekjanda in https://github.com/cozystack/cozystack/pull/924) * [cilium] Enable user-added parameters in a tenant cluster Cilium. (@lllamnyp in https://github.com/cozystack/cozystack/pull/917) +* [apps] Remove user-facing config of limits and requests. (@lllamnyp in https://github.com/cozystack/cozystack/pull/935) * Update the Cozystack release policy to include long-lived release branches and start with release candidates. Update CI workflows and docs accordingly. * Use release branches `release-X.Y` for gathering and releasing fixes after initial `vX.Y.0` release. (@kvaps in https://github.com/cozystack/cozystack/pull/816) * Automatically create release branches after initial `vX.Y.0` release is published. (@kvaps in https://github.com/cozystack/cozystack/pull/886) * Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841 and https://github.com/cozystack/cozystack/pull/901, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890) + * Support alpha and beta pre-releases. (@kvaps in https://github.com/cozystack/cozystack/pull/978) * Commit changes in release pipelines under `github-actions <github-actions@github.com>`. (@kvaps in https://github.com/cozystack/cozystack/pull/823) * Describe the Cozystack release workflow. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/817 and https://github.com/cozystack/cozystack/pull/897) @@ -42,6 +45,7 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [kubernetes] Fix merging `valuesOverride` for tenant clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/879) * [kubernetes] Fix `ubuntu-container-disk` tag. (@kvaps in https://github.com/cozystack/cozystack/pull/887) * [kubernetes] Refactor Helm manifests for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/866) +* [kubernetes] Fix Ingress-NGINX depends on Cert-Manager . (@kvaps in https://github.com/cozystack/cozystack/pull/976) * [tenant] Fix an issue with accessing external IPs of a cluster from the cluster itself. (@kvaps in https://github.com/cozystack/cozystack/pull/854) * [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867, patched in https://github.com/cozystack/cozystack/pull/956) * [monitoring] Remove legacy label "POD" from the exclude filter in metrics. (@xy2 in https://github.com/cozystack/cozystack/pull/826) @@ -62,6 +66,8 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * [ci] Fix release branch creation. (@kvaps in https://github.com/cozystack/cozystack/pull/884) * [ci, dx] Reduce noise in the test logs by suppressing the `wget` progress bar. (@lllamnyp in https://github.com/cozystack/cozystack/pull/865) * [ci] Revert "automatically trigger tests in releasing PR". (@kvaps in https://github.com/cozystack/cozystack/pull/900) +* [ci] Force-update release branch on tagged main commits . (@kvaps in https://github.com/cozystack/cozystack/pull/977) +* [docs] Explain that tenants cannot have dashes in the names. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/980) ## Dependencies @@ -74,7 +80,8 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * Update tenant Kubernetes to v1.32. (@kvaps in https://github.com/cozystack/cozystack/pull/871) * Update flux-operator to 0.20.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880 and https://github.com/cozystack/cozystack/pull/934) * Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867 and https://github.com/cozystack/cozystack/pull/947) -* Update KamajiControlPlane to edge-25.4.1. (@kvaps in https://github.com/cozystack/cozystack/pull/953) +* Update KamajiControlPlane to edge-25.4.1. (@kvaps in https://github.com/cozystack/cozystack/pull/953, fixed by @nbykov0 in https://github.com/cozystack/cozystack/pull/983) +* Update cert-manager to v1.17.2. (@kvaps in https://github.com/cozystack/cozystack/pull/975) ## Maintenance @@ -87,4 +94,4 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven * @zdenekjanda made their first contribution in https://github.com/cozystack/cozystack/pull/924 * @gwynbleidd2106 made their first contribution in https://github.com/cozystack/cozystack/pull/962 -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.2 +**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.3 From bc294a0fe668faf138b0d224f8d1e95adbd9e47e Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Mon, 26 May 2025 14:06:20 +0300 Subject: [PATCH 109/120] Fix regression in release workflow Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .github/workflows/pull-requests-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 1514c022..49fc63c6 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -110,7 +110,7 @@ jobs: await github.rest.git.updateRef({ owner: context.repo.owner, repo: context.repo.repo, - ref: `heads/${branch}`, + ref: `refs/heads/${branch}`, sha: commitSha, force: true }); From 3a7d4c24ee7795f37221fe2696661d1bdebdc88d Mon Sep 17 00:00:00 2001 From: github-actions <github-actions@github.com> Date: Mon, 26 May 2025 11:40:21 +0000 Subject: [PATCH 110/120] Prepare release v0.31.0-rc.3 Signed-off-by: github-actions <github-actions@github.com> --- packages/apps/http-cache/images/nginx-cache.tag | 2 +- packages/apps/kubernetes/images/kubevirt-cloud-provider.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 2 +- packages/system/dashboard/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index 403fae84..c955ec3d 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:785bd69cb593dc1509875d1e3128dac1a013b099fbb02f39330298d798706a0e +ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:99cd04f09f80eb0c60cc0b2f6bc8180ada7ada00cb594606447674953dfa1b67 diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index 1ada8d04..95233d07 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.1@sha256:1b48a4725a33ccb48604bb2e1be3171271e7daac2726d3119228212d8a9da5bb +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.1@sha256:4bee0705f0e1a6c93f4f5b343c988f2e05031844656ca0ff9ef12c88738687d3 diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index e1a5aa4d..31ef4106 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:a052681717a5dab9011076e8a6669b41b779ad519f88bf347f920a790ad26330 + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:acb40a186eddc95d4c34d3c68aa67f46ded040f86e63d79c7d0df02e9261199b diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 4d75ca9c..87d309cd 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:b305b8a640ad4eec94e6953cbfe23313b4b23c3a7df268c040c461d4cc0d28f5 + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:427f069dbe118534c5edbf5e4be79975e6b5aea1324c6b83d973a7a043d6139f diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index 44790044..cbdfb4dd 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:aa14eb17415fdb5c86288f5d816c6ebb9e58720828df5d88be26c6d556b3ee0f +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:9fa6a771ba1fbaf1df9e4ea376f082c34762f8a122ba783b6920f764aa79fb62 diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index fb318c00..855d8e24 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:42c6a88cac4a7661b002ab345fb0822ed275c38028da2112a7d7f863b50e9629 +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:e4e9776c919323153b5d5f2e096b3943a47b19c2fa8b9614bf3b06940bc52c54 diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index 1abd5bb9..c8dbe350 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:36dad15a8dfab883476118ac0724c0e28007fceabfef8159c3d41b285cbbeb45 + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:e6b94364f89286bb02f6cb56cfc7473e2cc3a7efb0882ffc617c8812ff02eb57 diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 2a59e426..5405a05c 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:18e877ea53d41d91c8e666fea7fe039f392a6c4562f20722bdd20b893986c065 + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:ae45b98c973999095b73b5b94fa70c4ae2b490a7b04fe02ea495b9415e173b50 debug: false disableTelemetry: false cozystackVersion: "v0.31.0-rc.3" diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index bd058dec..0326a7f1 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -36,7 +36,7 @@ kubeapps: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis tag: v0.31.0-rc.3 - digest: "sha256:a41cbf5f1d3d23f2d1650cb471dd310f27e4f68df3801250f37fed593018151e" + digest: "sha256:bf0522511089b3653e40726b875b6b4edea7a2efa1f9ac13b10dd723b91b9525" pluginConfig: flux: packages: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index e0545092..0cf79659 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:c046894c5ccc4af5a91e7088c4d0c3dee4a1ae5a0b1377cc06bc1a7e28a0b64f +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:cb297ff2730c6389ccc0a8b03d46dd7dd3a704ecc3c71b8f51eb0d1aa8d5d828 From 7792e29065b94b9246ac70686c9cab08cb624ce5 Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Mon, 26 May 2025 16:44:48 +0300 Subject: [PATCH 111/120] Detail errors for workflows Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .github/workflows/pull-requests-release.yaml | 32 +++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 49fc63c6..1e82175c 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -96,34 +96,36 @@ jobs: repo: context.repo.repo, ref: `tags/${tag}` }); + const commitSha = ref.data.object.sha; try { - // Check if branch exists await github.rest.repos.getBranch({ owner: context.repo.owner, - repo: context.repo.repo, + repo: context.repo.repo, branch }); - - // Force update existing branch to the tag commit + await github.rest.git.updateRef({ owner: context.repo.owner, - repo: context.repo.repo, - ref: `refs/heads/${branch}`, - sha: commitSha, + repo: context.repo.repo, + ref: `heads/${branch}`, + sha: commitSha, force: true }); console.log(`🔁 Force-updated '${branch}' to ${commitSha}`); } catch (err) { - // Branch doesn't exist, create it - await github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `refs/heads/${branch}`, - sha: commitSha - }); - console.log(`✅ Created branch '${branch}' at ${commitSha}`); + if (err.status === 404) { + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/heads/${branch}`, + sha: commitSha + }); + console.log(`✅ Created branch '${branch}' at ${commitSha}`); + } else { + console.error('Unexpected error --', err); + } } # Get the latest published release From c267c7eb9afffb6482df8788e0dec1ab3f039d64 Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Tue, 27 May 2025 12:20:00 +0300 Subject: [PATCH 112/120] Update .github/workflows/pull-requests-release.yaml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .github/workflows/pull-requests-release.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 1e82175c..7f7c2fcd 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -125,8 +125,9 @@ jobs: console.log(`✅ Created branch '${branch}' at ${commitSha}`); } else { console.error('Unexpected error --', err); + core.setFailed(`Unexpected error creating/updating branch: ${err.message}`); + throw err; } - } # Get the latest published release - name: Get the latest published release From 4aad0fc8f22a03355866aadbee193849e09bb8fd Mon Sep 17 00:00:00 2001 From: github-actions <github-actions@github.com> Date: Tue, 27 May 2025 10:08:18 +0000 Subject: [PATCH 113/120] Prepare release v0.31.0-rc.3 Signed-off-by: github-actions <github-actions@github.com> --- packages/apps/kubernetes/images/kubevirt-cloud-provider.tag | 2 +- packages/apps/kubernetes/images/kubevirt-csi-driver.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/extra/monitoring/images/grafana.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 2 +- packages/system/dashboard/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index 95233d07..1ada8d04 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.1@sha256:4bee0705f0e1a6c93f4f5b343c988f2e05031844656ca0ff9ef12c88738687d3 +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.1@sha256:1b48a4725a33ccb48604bb2e1be3171271e7daac2726d3119228212d8a9da5bb diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 2c5b03b9..09c8a03f 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.1@sha256:61580fea56b745580989d85e3ef2563e9bb1accc9c4185f8e636bacd02551319 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.1@sha256:75a6b855eb055f32803674270171013833fd892cdaaad59a620375a61a2c90b5 diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index 31ef4106..b2f038d3 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:acb40a186eddc95d4c34d3c68aa67f46ded040f86e63d79c7d0df02e9261199b + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:9809778c30801eef13d6a0478abb267c31298163cb87c70199c0bd6210eeb93f diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 87d309cd..b6bd7c26 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:427f069dbe118534c5edbf5e4be79975e6b5aea1324c6b83d973a7a043d6139f + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:b3ac6e0b266b814b15efe354f80edbf960b8da926e721ff14e9d1e6641850152 diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index cbdfb4dd..af92a293 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:9fa6a771ba1fbaf1df9e4ea376f082c34762f8a122ba783b6920f764aa79fb62 +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:217c56d8d644d606faab414cdc45b682c4d86988b81548f8f05e8f56b1751f78 diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag index 73fca310..00b25854 100644 --- a/packages/extra/monitoring/images/grafana.tag +++ b/packages/extra/monitoring/images/grafana.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399 +ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:8ce0cd90c8f614cdabf5a41f8aa50b7dfbd02b31b9a0bd7897927e7f89968e07 diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 855d8e24..038f7b6f 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:e4e9776c919323153b5d5f2e096b3943a47b19c2fa8b9614bf3b06940bc52c54 +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:80851d3ef1552300e401864a96ffa369599bcb1e4e765c90170bc796554f369f diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index c8dbe350..eecaa632 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:e6b94364f89286bb02f6cb56cfc7473e2cc3a7efb0882ffc617c8812ff02eb57 + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:27ed1a1fc798e7432b8656e99061b114d7744f1d515f7b3cb874d4b25bd222bc diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 5405a05c..08a2ffd1 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:ae45b98c973999095b73b5b94fa70c4ae2b490a7b04fe02ea495b9415e173b50 + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:111152038d7b91ee914a58ef624ad89f1b12903c49135ecca29ea5a9cd8ba2a2 debug: false disableTelemetry: false cozystackVersion: "v0.31.0-rc.3" diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index 0326a7f1..67f50f5f 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -36,7 +36,7 @@ kubeapps: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis tag: v0.31.0-rc.3 - digest: "sha256:bf0522511089b3653e40726b875b6b4edea7a2efa1f9ac13b10dd723b91b9525" + digest: "sha256:dcd67227660e30dd86d3f91082d83e00b0670878816e3d398397460cab399afb" pluginConfig: flux: packages: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 0cf79659..5cd334bf 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:cb297ff2730c6389ccc0a8b03d46dd7dd3a704ecc3c71b8f51eb0d1aa8d5d828 +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:a11e2248daf0f78ccefe41caf91b503f49f3d5317103fe25c1b11bb84823d224 From 774697464454355210863a9a81dfeee571d47e1a Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Tue, 27 May 2025 13:57:37 +0300 Subject: [PATCH 114/120] Add manual workflow temporarily for quicker feedback Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .../pull-requests-release-manual.yaml | 84 +++++++++++++++++++ .github/workflows/pull-requests-release.yaml | 1 + 2 files changed, 85 insertions(+) create mode 100644 .github/workflows/pull-requests-release-manual.yaml diff --git a/.github/workflows/pull-requests-release-manual.yaml b/.github/workflows/pull-requests-release-manual.yaml new file mode 100644 index 00000000..13f23676 --- /dev/null +++ b/.github/workflows/pull-requests-release-manual.yaml @@ -0,0 +1,84 @@ +name: Manual Release + +on: + workflow_dispatch: + inputs: + tag: + description: 'Release tag (e.g. v0.1.3 or v0.1.3-rc1)' + required: true + type: string + +jobs: + finalize: + name: Finalize Release + runs-on: [self-hosted] + permissions: + contents: write + + if: | + github.event_name == 'workflow_dispatch' && github.ref_name == 'main' + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create tag on merge commit + run: | + git tag -f ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} + git push -f origin ${{ steps.get_tag.outputs.tag }} + + - name: Ensure maintenance branch release-X.Y + uses: actions/github-script@v7 + with: + script: | + const tag = '${{ inputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 + const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); + if (!match) { + core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-suffix'`); + return; + } + const line = `${match[1]}.${match[2]}`; + const branch = `release-${line}`; + + // Get main branch commit for the tag + const ref = await github.rest.git.getRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `tags/${tag}` + }); + + const commitSha = ref.data.object.sha; + + try { + await github.rest.repos.getBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + branch + }); + + await github.rest.git.updateRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${branch}`, + sha: commitSha, + force: true + }); + console.log(`🔁 Force-updated '${branch}' to ${commitSha}`); + } catch (err) { + if (err.status === 404) { + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/heads/${branch}`, + sha: commitSha + }); + console.log(`✅ Created branch '${branch}' at ${commitSha}`); + } else { + console.error('Unexpected error --', err); + core.setFailed(`Unexpected error creating/updating branch: ${err.message}`); + throw err; + } + } + diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 7f7c2fcd..b4ca30d0 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -128,6 +128,7 @@ jobs: core.setFailed(`Unexpected error creating/updating branch: ${err.message}`); throw err; } + } # Get the latest published release - name: Get the latest published release From 3e379e9697a42bdf6f3e1e5be48ec70303a3fc5b Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Tue, 27 May 2025 14:17:28 +0300 Subject: [PATCH 115/120] Add manual workflow temporarily for quicker feedback Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .github/workflows/pull-requests-release-manual.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull-requests-release-manual.yaml b/.github/workflows/pull-requests-release-manual.yaml index 13f23676..789a0dcf 100644 --- a/.github/workflows/pull-requests-release-manual.yaml +++ b/.github/workflows/pull-requests-release-manual.yaml @@ -32,6 +32,7 @@ jobs: - name: Ensure maintenance branch release-X.Y uses: actions/github-script@v7 with: + github-token: ${{ secrets.GH_PAT_TEST }} script: | const tag = '${{ inputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); From 1a872ca95c587e5b77e1bbcb6481696b5dda057d Mon Sep 17 00:00:00 2001 From: Timofei Larkin <lllamnyp@gmail.com> Date: Tue, 27 May 2025 14:50:39 +0300 Subject: [PATCH 116/120] Revert experiments with workflows Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> --- .../pull-requests-release-manual.yaml | 85 ------------------- .github/workflows/pull-requests-release.yaml | 1 + 2 files changed, 1 insertion(+), 85 deletions(-) delete mode 100644 .github/workflows/pull-requests-release-manual.yaml diff --git a/.github/workflows/pull-requests-release-manual.yaml b/.github/workflows/pull-requests-release-manual.yaml deleted file mode 100644 index 789a0dcf..00000000 --- a/.github/workflows/pull-requests-release-manual.yaml +++ /dev/null @@ -1,85 +0,0 @@ -name: Manual Release - -on: - workflow_dispatch: - inputs: - tag: - description: 'Release tag (e.g. v0.1.3 or v0.1.3-rc1)' - required: true - type: string - -jobs: - finalize: - name: Finalize Release - runs-on: [self-hosted] - permissions: - contents: write - - if: | - github.event_name == 'workflow_dispatch' && github.ref_name == 'main' - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Create tag on merge commit - run: | - git tag -f ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} - git push -f origin ${{ steps.get_tag.outputs.tag }} - - - name: Ensure maintenance branch release-X.Y - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GH_PAT_TEST }} - script: | - const tag = '${{ inputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 - const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); - if (!match) { - core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-suffix'`); - return; - } - const line = `${match[1]}.${match[2]}`; - const branch = `release-${line}`; - - // Get main branch commit for the tag - const ref = await github.rest.git.getRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `tags/${tag}` - }); - - const commitSha = ref.data.object.sha; - - try { - await github.rest.repos.getBranch({ - owner: context.repo.owner, - repo: context.repo.repo, - branch - }); - - await github.rest.git.updateRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `heads/${branch}`, - sha: commitSha, - force: true - }); - console.log(`🔁 Force-updated '${branch}' to ${commitSha}`); - } catch (err) { - if (err.status === 404) { - await github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `refs/heads/${branch}`, - sha: commitSha - }); - console.log(`✅ Created branch '${branch}' at ${commitSha}`); - } else { - console.error('Unexpected error --', err); - core.setFailed(`Unexpected error creating/updating branch: ${err.message}`); - throw err; - } - } - diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index b4ca30d0..5614f893 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -80,6 +80,7 @@ jobs: - name: Ensure maintenance branch release-X.Y uses: actions/github-script@v7 with: + github-token: ${{ secrets.GH_PAT }} script: | const tag = '${{ steps.get_tag.outputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); From 2ae8f2aa1908146e8e41f3971ba0b2c8dcd0c90e Mon Sep 17 00:00:00 2001 From: github-actions <github-actions@github.com> Date: Tue, 27 May 2025 12:01:54 +0000 Subject: [PATCH 117/120] Prepare release v0.31.0-rc.3 Signed-off-by: github-actions <github-actions@github.com> --- packages/apps/http-cache/images/nginx-cache.tag | 2 +- packages/apps/kubernetes/images/kubevirt-csi-driver.tag | 2 +- packages/core/installer/values.yaml | 2 +- packages/core/testing/values.yaml | 2 +- packages/extra/bootbox/images/matchbox.tag | 2 +- packages/extra/monitoring/images/grafana.tag | 2 +- packages/system/bucket/images/s3manager.tag | 2 +- packages/system/cozystack-api/values.yaml | 2 +- packages/system/cozystack-controller/values.yaml | 2 +- packages/system/dashboard/values.yaml | 2 +- packages/system/kubeovn-webhook/values.yaml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index c955ec3d..f5106b42 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:99cd04f09f80eb0c60cc0b2f6bc8180ada7ada00cb594606447674953dfa1b67 +ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:158c35dd6a512bd14e86a423be5c8c7ca91ac71999c73cce2714e4db60a2db43 diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 09c8a03f..21e11de9 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.1@sha256:75a6b855eb055f32803674270171013833fd892cdaaad59a620375a61a2c90b5 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.1@sha256:fb6d3ce9d6d948285a6d399c852e15259d6922162ec7c44177d2274243f59d1f diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index b2f038d3..d582a949 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,2 +1,2 @@ cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:9809778c30801eef13d6a0478abb267c31298163cb87c70199c0bd6210eeb93f + image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.3@sha256:5fc6b88de670878b66f2b5bf381b89b68253ab3e69ff1cb7359470bc65beb3fa diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index b6bd7c26..f511dab5 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:b3ac6e0b266b814b15efe354f80edbf960b8da926e721ff14e9d1e6641850152 + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.3@sha256:8de0a8900994cb55f74ba25d265eeecac9958b07cdb8f86b9284b9f23668d2bb diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index af92a293..662c044e 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:217c56d8d644d606faab414cdc45b682c4d86988b81548f8f05e8f56b1751f78 +ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.3@sha256:8b65a160333830bf4711246ae78f26095e3b33667440bf1bbdd36db60a7f92e2 diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag index 00b25854..e22b556a 100644 --- a/packages/extra/monitoring/images/grafana.tag +++ b/packages/extra/monitoring/images/grafana.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:8ce0cd90c8f614cdabf5a41f8aa50b7dfbd02b31b9a0bd7897927e7f89968e07 +ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:24382d445bf7a39ed988ef4dc7a0d9f084db891fcb5f42fd2e64622710b9457e diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 038f7b6f..c384dc90 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:80851d3ef1552300e401864a96ffa369599bcb1e4e765c90170bc796554f369f +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:4399c240ce1f99660d5d1be9d6d7b3e8157c50e4aba58345d51a1d9ac25779a3 diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index eecaa632..6f3a84a5 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,2 +1,2 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:27ed1a1fc798e7432b8656e99061b114d7744f1d515f7b3cb874d4b25bd222bc + image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.3@sha256:9940cffabedb510397e3c330887aee724c4d232c011df60f4c16891fcfe1d9bf diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 08a2ffd1..fc77f625 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,5 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:111152038d7b91ee914a58ef624ad89f1b12903c49135ecca29ea5a9cd8ba2a2 + image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.3@sha256:b2f0de3ae2d7f15956eb7cdec78d2267aeba7e56a7781c70473757df4989a05a debug: false disableTelemetry: false cozystackVersion: "v0.31.0-rc.3" diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index 67f50f5f..5d1a7ef4 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -36,7 +36,7 @@ kubeapps: registry: ghcr.io/cozystack/cozystack repository: kubeapps-apis tag: v0.31.0-rc.3 - digest: "sha256:dcd67227660e30dd86d3f91082d83e00b0670878816e3d398397460cab399afb" + digest: "sha256:1447c10fcc9a8de426ec381bce565aa56267d0c9f3bab8fe26ac502d433283c5" pluginConfig: flux: packages: diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 5cd334bf..b9df2b38 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:a11e2248daf0f78ccefe41caf91b503f49f3d5317103fe25c1b11bb84823d224 +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.3@sha256:f3acc1c6dd87cebd76be5afe1789c19780cb24f9518c8bdafa46f823ae4ba46e From 461f756c88d932de530a3ee337d9bd6a5259eb7d Mon Sep 17 00:00:00 2001 From: Andrei Kvapil <kvapss@gmail.com> Date: Wed, 28 May 2025 10:37:18 +0200 Subject: [PATCH 118/120] [virtual-machine] Set PortList method by default Signed-off-by: Andrei Kvapil <kvapss@gmail.com> --- packages/apps/versions_map | 4 ++-- packages/apps/virtual-machine/Chart.yaml | 4 ++-- packages/apps/virtual-machine/Makefile | 2 +- packages/apps/virtual-machine/README.md | 2 +- packages/apps/virtual-machine/values.schema.json | 6 +++--- packages/apps/virtual-machine/values.yaml | 2 +- packages/apps/vm-instance/Chart.yaml | 4 ++-- packages/apps/vm-instance/Makefile | 2 +- packages/apps/vm-instance/README.md | 2 +- packages/apps/vm-instance/values.schema.json | 6 +++--- packages/apps/vm-instance/values.yaml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/apps/versions_map b/packages/apps/versions_map index 74ccb112..be176c6a 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -159,7 +159,7 @@ virtual-machine 0.8.1 93c46161 virtual-machine 0.8.2 de19450f virtual-machine 0.9.0 721c12a7 virtual-machine 0.9.1 93bdf411 -virtual-machine 0.9.2 HEAD +virtual-machine 0.10.0 HEAD vm-disk 0.1.0 d971f2ff vm-disk 0.1.1 HEAD vm-instance 0.1.0 1ec10165 @@ -170,7 +170,7 @@ vm-instance 0.4.1 0ab39f20 vm-instance 0.5.0 3fa4dd3a vm-instance 0.5.1 de19450f vm-instance 0.6.0 721c12a7 -vm-instance 0.6.1 HEAD +vm-instance 0.7.0 HEAD vpn 0.1.0 263e47be vpn 0.2.0 53f2365e vpn 0.3.0 6c5cf5bf diff --git a/packages/apps/virtual-machine/Chart.yaml b/packages/apps/virtual-machine/Chart.yaml index 87358d5b..000ccba6 100644 --- a/packages/apps/virtual-machine/Chart.yaml +++ b/packages/apps/virtual-machine/Chart.yaml @@ -17,10 +17,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.9.2 +version: 0.10.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.9.2 +appVersion: 0.10.0 diff --git a/packages/apps/virtual-machine/Makefile b/packages/apps/virtual-machine/Makefile index f3de3546..5d31cacf 100644 --- a/packages/apps/virtual-machine/Makefile +++ b/packages/apps/virtual-machine/Makefile @@ -9,4 +9,4 @@ generate: && yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json yq -i -o json '.properties.systemDisk.properties.image.enum = ["ubuntu", "cirros", "alpine", "fedora", "talos"]' values.schema.json - yq -i -o json '.properties.externalMethod.enum = ["WholeIP", "PortList"]' values.schema.json + yq -i -o json '.properties.externalMethod.enum = ["PortList", "WholeIP"]' values.schema.json diff --git a/packages/apps/virtual-machine/README.md b/packages/apps/virtual-machine/README.md index bb33570b..8c9b382c 100644 --- a/packages/apps/virtual-machine/README.md +++ b/packages/apps/virtual-machine/README.md @@ -39,7 +39,7 @@ virtctl ssh <user>@<vm> | Name | Description | Value | | ------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------ | | `external` | Enable external access from outside the cluster | `false` | -| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `WholeIP` | +| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `PortList` | | `externalPorts` | Specify ports to forward from outside the cluster | `[]` | | `running` | Determines if the virtual machine should be running | `true` | | `instanceType` | Virtual Machine instance type | `u1.medium` | diff --git a/packages/apps/virtual-machine/values.schema.json b/packages/apps/virtual-machine/values.schema.json index 861d4da4..ea0efd4c 100644 --- a/packages/apps/virtual-machine/values.schema.json +++ b/packages/apps/virtual-machine/values.schema.json @@ -10,10 +10,10 @@ "externalMethod": { "type": "string", "description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`", - "default": "WholeIP", + "default": "PortList", "enum": [ - "WholeIP", - "PortList" + "PortList", + "WholeIP" ] }, "externalPorts": { diff --git a/packages/apps/virtual-machine/values.yaml b/packages/apps/virtual-machine/values.yaml index 6cccbad1..191a86a5 100644 --- a/packages/apps/virtual-machine/values.yaml +++ b/packages/apps/virtual-machine/values.yaml @@ -4,7 +4,7 @@ ## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` ## @param externalPorts [array] Specify ports to forward from outside the cluster external: false -externalMethod: WholeIP +externalMethod: PortList externalPorts: - 22 diff --git a/packages/apps/vm-instance/Chart.yaml b/packages/apps/vm-instance/Chart.yaml index b0b6a3b9..8011ca1f 100644 --- a/packages/apps/vm-instance/Chart.yaml +++ b/packages/apps/vm-instance/Chart.yaml @@ -17,10 +17,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.1 +version: 0.7.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.6.0 +appVersion: 0.7.0 diff --git a/packages/apps/vm-instance/Makefile b/packages/apps/vm-instance/Makefile index 5b2aebab..3a9a0fd8 100644 --- a/packages/apps/vm-instance/Makefile +++ b/packages/apps/vm-instance/Makefile @@ -9,4 +9,4 @@ generate: PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \ && yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json - yq -i -o json '.properties.externalMethod.enum = ["WholeIP", "PortList"]' values.schema.json + yq -i -o json '.properties.externalMethod.enum = ["PortList", "WholeIP"]' values.schema.json diff --git a/packages/apps/vm-instance/README.md b/packages/apps/vm-instance/README.md index 273c1f15..611595a0 100644 --- a/packages/apps/vm-instance/README.md +++ b/packages/apps/vm-instance/README.md @@ -39,7 +39,7 @@ virtctl ssh <user>@<vm> | Name | Description | Value | | ------------------ | ---------------------------------------------------------------------------------------------------------- | ----------- | | `external` | Enable external access from outside the cluster | `false` | -| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `WholeIP` | +| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `PortList` | | `externalPorts` | Specify ports to forward from outside the cluster | `[]` | | `running` | Determines if the virtual machine should be running | `true` | | `instanceType` | Virtual Machine instance type | `u1.medium` | diff --git a/packages/apps/vm-instance/values.schema.json b/packages/apps/vm-instance/values.schema.json index f4dd2076..8ce71cdb 100644 --- a/packages/apps/vm-instance/values.schema.json +++ b/packages/apps/vm-instance/values.schema.json @@ -10,10 +10,10 @@ "externalMethod": { "type": "string", "description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`", - "default": "WholeIP", + "default": "PortList", "enum": [ - "WholeIP", - "PortList" + "PortList", + "WholeIP" ] }, "externalPorts": { diff --git a/packages/apps/vm-instance/values.yaml b/packages/apps/vm-instance/values.yaml index eb68ced2..4b21423d 100644 --- a/packages/apps/vm-instance/values.yaml +++ b/packages/apps/vm-instance/values.yaml @@ -4,7 +4,7 @@ ## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` ## @param externalPorts [array] Specify ports to forward from outside the cluster external: false -externalMethod: WholeIP +externalMethod: PortList externalPorts: - 22 From 6cbfab9b2a34a904beb0c047db1f49f2bfa6eb66 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil <kvapss@gmail.com> Date: Wed, 28 May 2025 12:01:31 +0200 Subject: [PATCH 119/120] [dx] remove version_map and building for library charts Signed-off-by: Andrei Kvapil <kvapss@gmail.com> --- Makefile | 2 -- packages/library/Makefile | 7 ------- packages/library/versions_map | 1 - 3 files changed, 10 deletions(-) delete mode 100644 packages/library/versions_map diff --git a/Makefile b/Makefile index c1b4ed72..63f61458 100644 --- a/Makefile +++ b/Makefile @@ -29,10 +29,8 @@ build: build-deps repos: rm -rf _out - make -C packages/library check-version-map make -C packages/apps check-version-map make -C packages/extra check-version-map - make -C packages/library repo make -C packages/system repo make -C packages/apps repo make -C packages/extra repo diff --git a/packages/library/Makefile b/packages/library/Makefile index 664771cf..42651d03 100644 --- a/packages/library/Makefile +++ b/packages/library/Makefile @@ -6,10 +6,3 @@ repo: fix-chartnames: find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done - -gen-versions-map: fix-chartnames - ../../hack/gen_versions_map.sh - -check-version-map: gen-versions-map - git diff --exit-code -- versions_map - diff --git a/packages/library/versions_map b/packages/library/versions_map deleted file mode 100644 index 63834fdd..00000000 --- a/packages/library/versions_map +++ /dev/null @@ -1 +0,0 @@ -cozy-lib 0.1.0 HEAD From 8386e985f2aa4c4d25ca63779f234a1eadb5466a Mon Sep 17 00:00:00 2001 From: Nick Volynkin <nick.volynkin@gmail.com> Date: Wed, 21 May 2025 17:34:25 +0300 Subject: [PATCH 120/120] [docs] Review the tenant Kubernetes cluster docs Signed-off-by: Nick Volynkin <nick.volynkin@gmail.com> --- packages/apps/kubernetes/README.md | 296 ++++++++++++-------- packages/apps/kubernetes/values.schema.json | 60 ++-- packages/apps/kubernetes/values.yaml | 40 +-- 3 files changed, 232 insertions(+), 164 deletions(-) diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index 71cee152..8cd62b25 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -1,77 +1,199 @@ # Managed Kubernetes Service -## Overview +## Managed Kubernetes in Cozystack -The Managed Kubernetes Service offers a streamlined solution for efficiently managing server workloads. Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration. This means that teams can easily understand and work with Kubernetes, streamlining infrastructure management. +Whenever you want to deploy a custom containerized application in Cozystack, it's best to deploy it to a managed Kubernetes cluster. -The Kubernetes leverages robust software design patterns, enabling continuous recovery in any scenario through the reconciliation method. Additionally, it ensures seamless scaling across a multitude of servers, addressing the challenges posed by complex and outdated APIs found in traditional virtualization platforms. This managed service eliminates the need for developing custom solutions or modifying source code, saving valuable time and effort. +Cozystack deploys and manages Kubernetes-as-a-service as standalone applications within each tenant’s isolated environment. +In Cozystack, such clusters are named tenant Kubernetes clusters, while the base Cozystack cluster is called a management or root cluster. +Tenant clusters are fully separated from the management cluster and are intended for deploying tenant-specific or customer-developed applications. -## Deployment Details +Within a tenant cluster, users can take advantage of LoadBalancer services and easily provision physical volumes as needed. +The control-plane operates within containers, while the worker nodes are deployed as virtual machines, all seamlessly managed by the application. -The managed Kubernetes service deploys a standard Kubernetes cluster utilizing the Cluster API, Kamaji as control-plane provicer and the KubeVirt infrastructure provider. This ensures a consistent and reliable setup for workloads. +## Why Use a Managed Kubernetes Cluster? -Within this cluster, users can take advantage of LoadBalancer services and easily provision physical volumes as needed. The control-plane operates within containers, while the worker nodes are deployed as virtual machines, all seamlessly managed by the application. +Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration. +This means that teams can easily understand and work with Kubernetes, streamlining infrastructure management. -- Docs: https://github.com/clastix/kamaji -- Docs: https://cluster-api.sigs.k8s.io/ -- GitHub: https://github.com/clastix/kamaji -- GitHub: https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt -- GitHub: https://github.com/kubevirt/csi-driver +Kubernetes leverages robust software design patterns, enabling continuous recovery in any scenario through the reconciliation method. +Additionally, it ensures seamless scaling across a multitude of servers, +addressing the challenges posed by complex and outdated APIs found in traditional virtualization platforms. +This managed service eliminates the need for developing custom solutions or modifying source code, saving valuable time and effort. +The Managed Kubernetes Service in Cozystack offers a streamlined solution for efficiently managing server workloads. -## How-Tos +## Starting Work -How to access to deployed cluster: +Once the tenant Kubernetes cluster is ready, you can get a kubeconfig file to work with it. +It can be done via UI or a `kubectl` request: -``` -kubectl get secret -n <namespace> kubernetes-<clusterName>-admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "super-admin.conf" | base64decode) }}' > test -``` +- Open the Cozystack dashboard, switch to your tenant, find and open the application page. Copy one of the config files from the **Secrets** section. +- Run the following command (using the management cluster kubeconfig): + + ```bash + kubectl get secret -n tenant-<name> kubernetes-<clusterName>-admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "admin.conf" | base64decode) }}' > admin.conf + ``` + +There are several kubeconfig options available: + +- `admin.conf` — The standard kubeconfig for accessing your new cluster. + You can create additional Kubernetes users using this configuration. +- `admin.svc` — Same token as `admin.conf`, but with the API server address set to the internal service name. + Use it for applications running inside the cluster that need API access. +- `super-admin.conf` — Similar to `admin.conf`, but with extended administrative permissions. + Intended for troubleshooting and cluster maintenance tasks. +- `super-admin.svc` — Same as `super-admin.conf`, but pointing to the internal API server address. + +## Implementation Details + +A tenant Kubernetes cluster in Cozystack is essentially Kubernetes-in-Kubernetes. +Deploying it involves the following components: + +- **Kamaji Control Plane**: [Kamaji](https://kamaji.clastix.io/) is an open-source project that facilitates the deployment + of Kubernetes control planes as pods within a root cluster. + Each control plane pod includes essential components like `kube-apiserver`, `controller-manager`, and `scheduler`, + allowing for efficient multi-tenancy and resource utilization. + +- **Etcd Cluster**: A dedicated etcd cluster is deployed using Ænix's [etcd-operator](https://github.com/aenix-io/etcd-operator). + It provides reliable and scalable key-value storage for the Kubernetes control plane. + +- **Worker Nodes**: Virtual Machines are provisioned to serve as worker nodes using KubeVirt. + These nodes are configured to join the tenant Kubernetes cluster, enabling the deployment and management of workloads. + +- **Cluster API**: Cozystack is using the [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/) to provision the components of a cluster. + +This architecture ensures isolated, scalable, and efficient tenant Kubernetes environments. + +See the reference for components utilized in this service: + +- [Kamaji Control Plane](https://kamaji.clastix.io) +- [Kamaji — Cluster API](https://kamaji.clastix.io/cluster-api/) +- [github.com/clastix/kamaji](https://github.com/clastix/kamaji) +- [KubeVirt](https://kubevirt.io/) +- [github.com/kubevirt/kubevirt](https://github.com/kubevirt/kubevirt) +- [github.com/aenix-io/etcd-operator](https://github.com/aenix-io/etcd-operator) +- [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/) +- [github.com/kubernetes-sigs/cluster-api-provider-kubevirt](https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt) +- [github.com/kubevirt/csi-driver](https://github.com/kubevirt/csi-driver) ## Parameters -### Common parameters +### Common Parameters -| Name | Description | Value | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------ | -| `host` | The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). | `""` | -| `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components | `2` | -| `storageClass` | StorageClass used to store user data | `replicated` | -| `nodeGroups` | nodeGroups configuration | `{}` | +| Name | Description | Value | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------ | +| `host` | Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. | `""` | +| `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components. | `2` | +| `storageClass` | StorageClass used to store user data. | `replicated` | +| `nodeGroups` | nodeGroups configuration | `{}` | ### Cluster Addons -| Name | Description | Value | -| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| `addons.certManager.enabled` | Enables the cert-manager | `false` | -| `addons.certManager.valuesOverride` | Custom values to override | `{}` | -| `addons.cilium.valuesOverride` | Custom values to override | `{}` | -| `addons.gatewayAPI.enabled` | Enables the Gateway API | `false` | -| `addons.ingressNginx.enabled` | Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) | `false` | -| `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | -| `addons.ingressNginx.hosts` | List of domain names that should be passed through to the cluster by upper cluster | `[]` | -| `addons.gpuOperator.enabled` | Enables the gpu-operator | `false` | -| `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` | -| `addons.fluxcd.enabled` | Enables Flux CD | `false` | -| `addons.fluxcd.valuesOverride` | Custom values to override | `{}` | -| `addons.monitoringAgents.enabled` | Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage | `false` | -| `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` | -| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` | +| Name | Description | Value | +| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `false` | +| `addons.certManager.valuesOverride` | Custom values to override | `{}` | +| `addons.cilium.valuesOverride` | Custom values to override | `{}` | +| `addons.gatewayAPI.enabled` | Enable the Gateway API | `false` | +| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `false` | +| `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | +| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. | `[]` | +| `addons.gpuOperator.enabled` | Enable the GPU-operator | `false` | +| `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` | +| `addons.fluxcd.enabled` | Enable FluxCD | `false` | +| `addons.fluxcd.valuesOverride` | Custom values to override | `{}` | +| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `false` | +| `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` | +| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` | -### Kubernetes control plane configuration +### Kubernetes Control Plane Configuration -| Name | Description | Value | -| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| `controlPlane.apiServer.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | -| `controlPlane.apiServer.resources` | Resources | `{}` | -| `controlPlane.controllerManager.resources` | Resources | `{}` | -| `controlPlane.controllerManager.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | -| `controlPlane.scheduler.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | -| `controlPlane.scheduler.resources` | Resources | `{}` | -| `controlPlane.konnectivity.server.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` | -| `controlPlane.konnectivity.server.resources` | Resources | `{}` | +| Name | Description | Value | +| -------------------------------------------------- | ---------------------------------------------------------------------------- | ------- | +| `controlPlane.apiServer.resources` | Explicit CPU/memory resource requests and limits for the API server. | `{}` | +| `controlPlane.apiServer.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `small` | +| `controlPlane.controllerManager.resources` | Explicit CPU/memory resource requests and limits for the controller manager. | `{}` | +| `controlPlane.controllerManager.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | +| `controlPlane.scheduler.resources` | Explicit CPU/memory resource requests and limits for the scheduler. | `{}` | +| `controlPlane.scheduler.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | +| `controlPlane.konnectivity.server.resources` | Explicit CPU/memory resource requests and limits for the Konnectivity. | `{}` | +| `controlPlane.konnectivity.server.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | +In production environments, it's recommended to set `resources` explicitly. +Example of `controlPlane.*.resources`: -## U Series +```yaml +resources: + limits: + cpu: 4000m + memory: 4Gi + requests: + cpu: 100m + memory: 512Mi +``` + +Allowed values for `controlPlane.*.resourcesPreset` are `none`, `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. +This value is ignored if the corresponding `resources` value is set. + +## Resources Reference + +### instanceType Resources + +The following instanceType resources are provided by Cozystack: + +| Name | vCPUs | Memory | +|---------------|-------|--------| +| `cx1.2xlarge` | 8 | 16Gi | +| `cx1.4xlarge` | 16 | 32Gi | +| `cx1.8xlarge` | 32 | 64Gi | +| `cx1.large` | 2 | 4Gi | +| `cx1.medium` | 1 | 2Gi | +| `cx1.xlarge` | 4 | 8Gi | +| `gn1.2xlarge` | 8 | 32Gi | +| `gn1.4xlarge` | 16 | 64Gi | +| `gn1.8xlarge` | 32 | 128Gi | +| `gn1.xlarge` | 4 | 16Gi | +| `m1.2xlarge` | 8 | 64Gi | +| `m1.4xlarge` | 16 | 128Gi | +| `m1.8xlarge` | 32 | 256Gi | +| `m1.large` | 2 | 16Gi | +| `m1.xlarge` | 4 | 32Gi | +| `n1.2xlarge` | 16 | 32Gi | +| `n1.4xlarge` | 32 | 64Gi | +| `n1.8xlarge` | 64 | 128Gi | +| `n1.large` | 4 | 8Gi | +| `n1.medium` | 4 | 4Gi | +| `n1.xlarge` | 8 | 16Gi | +| `o1.2xlarge` | 8 | 32Gi | +| `o1.4xlarge` | 16 | 64Gi | +| `o1.8xlarge` | 32 | 128Gi | +| `o1.large` | 2 | 8Gi | +| `o1.medium` | 1 | 4Gi | +| `o1.micro` | 1 | 1Gi | +| `o1.nano` | 1 | 512Mi | +| `o1.small` | 1 | 2Gi | +| `o1.xlarge` | 4 | 16Gi | +| `rt1.2xlarge` | 8 | 32Gi | +| `rt1.4xlarge` | 16 | 64Gi | +| `rt1.8xlarge` | 32 | 128Gi | +| `rt1.large` | 2 | 8Gi | +| `rt1.medium` | 1 | 4Gi | +| `rt1.micro` | 1 | 1Gi | +| `rt1.small` | 1 | 2Gi | +| `rt1.xlarge` | 4 | 16Gi | +| `u1.2xlarge` | 8 | 32Gi | +| `u1.2xmedium` | 2 | 4Gi | +| `u1.4xlarge` | 16 | 64Gi | +| `u1.8xlarge` | 32 | 128Gi | +| `u1.large` | 2 | 8Gi | +| `u1.medium` | 1 | 4Gi | +| `u1.micro` | 1 | 1Gi | +| `u1.nano` | 1 | 512Mi | +| `u1.small` | 1 | 2Gi | +| `u1.xlarge` | 4 | 16Gi | + +### U Series: Universal The U Series is quite neutral and provides resources for general purpose applications. @@ -82,7 +204,7 @@ attitude towards workloads. VMs of instance types will share physical CPU cores on a time-slice basis with other VMs. -### U Series Characteristics +#### U Series Characteristics Specific characteristics of this series are: - *Burstable CPU performance* - The workload has a baseline compute @@ -91,14 +213,14 @@ Specific characteristics of this series are: - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less noise per node. -## O Series +### O Series: Overcommitted The O Series is based on the U Series, with the only difference being that memory is overcommitted. *O* is the abbreviation for "Overcommitted". -### UO Series Characteristics +#### O Series Characteristics Specific characteristics of this series are: - *Burstable CPU performance* - The workload has a baseline compute @@ -109,7 +231,7 @@ Specific characteristics of this series are: - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less noise per node. -## CX Series +### CX Series: Compute Exclusive The CX Series provides exclusive compute resources for compute intensive applications. @@ -123,7 +245,7 @@ the IO threading from cores dedicated to the workload. In addition, in this series, the NUMA topology of the used cores is provided to the VM. -### CX Series Characteristics +#### CX Series Characteristics Specific characteristics of this series are: - *Hugepages* - Hugepages are used in order to improve memory @@ -138,14 +260,14 @@ Specific characteristics of this series are: optimize guest sided cache utilization. - *vCPU-To-Memory Ratio (1:2)* - A vCPU-to-Memory ratio of 1:2. -## M Series +### M Series: Memory The M Series provides resources for memory intensive applications. *M* is the abbreviation of "Memory". -### M Series Characteristics +#### M Series Characteristics Specific characteristics of this series are: - *Hugepages* - Hugepages are used in order to improve memory @@ -156,7 +278,7 @@ Specific characteristics of this series are: - *vCPU-To-Memory Ratio (1:8)* - A vCPU-to-Memory ratio of 1:8, for much less noise per node. -## RT Series +### RT Series: RealTime The RT Series provides resources for realtime applications, like Oslat. @@ -165,7 +287,7 @@ The RT Series provides resources for realtime applications, like Oslat. This series of instance types requires nodes capable of running realtime applications. -### RT Series Characteristics +#### RT Series Characteristics Specific characteristics of this series are: - *Hugepages* - Hugepages are used in order to improve memory @@ -179,57 +301,3 @@ Specific characteristics of this series are: - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4 starting from the medium size. -## Resources - -The following instancetype resources are provided by Cozystack: - -Name | vCPUs | Memory ------|-------|------- -cx1.2xlarge | 8 | 16Gi -cx1.4xlarge | 16 | 32Gi -cx1.8xlarge | 32 | 64Gi -cx1.large | 2 | 4Gi -cx1.medium | 1 | 2Gi -cx1.xlarge | 4 | 8Gi -gn1.2xlarge | 8 | 32Gi -gn1.4xlarge | 16 | 64Gi -gn1.8xlarge | 32 | 128Gi -gn1.xlarge | 4 | 16Gi -m1.2xlarge | 8 | 64Gi -m1.4xlarge | 16 | 128Gi -m1.8xlarge | 32 | 256Gi -m1.large | 2 | 16Gi -m1.xlarge | 4 | 32Gi -n1.2xlarge | 16 | 32Gi -n1.4xlarge | 32 | 64Gi -n1.8xlarge | 64 | 128Gi -n1.large | 4 | 8Gi -n1.medium | 4 | 4Gi -n1.xlarge | 8 | 16Gi -o1.2xlarge | 8 | 32Gi -o1.4xlarge | 16 | 64Gi -o1.8xlarge | 32 | 128Gi -o1.large | 2 | 8Gi -o1.medium | 1 | 4Gi -o1.micro | 1 | 1Gi -o1.nano | 1 | 512Mi -o1.small | 1 | 2Gi -o1.xlarge | 4 | 16Gi -rt1.2xlarge | 8 | 32Gi -rt1.4xlarge | 16 | 64Gi -rt1.8xlarge | 32 | 128Gi -rt1.large | 2 | 8Gi -rt1.medium | 1 | 4Gi -rt1.micro | 1 | 1Gi -rt1.small | 1 | 2Gi -rt1.xlarge | 4 | 16Gi -u1.2xlarge | 8 | 32Gi -u1.2xmedium | 2 | 4Gi -u1.4xlarge | 16 | 64Gi -u1.8xlarge | 32 | 128Gi -u1.large | 2 | 8Gi -u1.medium | 1 | 4Gi -u1.micro | 1 | 1Gi -u1.nano | 1 | 512Mi -u1.small | 1 | 2Gi -u1.xlarge | 4 | 16Gi diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index adb29dbd..b96fadf0 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -4,7 +4,7 @@ "properties": { "host": { "type": "string", - "description": "The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host).", + "description": "Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty.", "default": "" }, "controlPlane": { @@ -12,15 +12,20 @@ "properties": { "replicas": { "type": "number", - "description": "Number of replicas for Kubernetes control-plane components", + "description": "Number of replicas for Kubernetes control-plane components.", "default": 2 }, "apiServer": { "type": "object", "properties": { + "resources": { + "type": "object", + "description": "Explicit CPU/memory resource requests and limits for the API server.", + "default": {} + }, "resourcesPreset": { "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "description": "Use a common resources preset when `resources` is not set explicitly.", "default": "small", "enum": [ "none", @@ -32,11 +37,6 @@ "xlarge", "2xlarge" ] - }, - "resources": { - "type": "object", - "description": "Resources", - "default": {} } } }, @@ -45,12 +45,12 @@ "properties": { "resources": { "type": "object", - "description": "Resources", + "description": "Explicit CPU/memory resource requests and limits for the controller manager.", "default": {} }, "resourcesPreset": { "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "description": "Use a common resources preset when `resources` is not set explicitly.", "default": "micro", "enum": [ "none", @@ -68,9 +68,14 @@ "scheduler": { "type": "object", "properties": { + "resources": { + "type": "object", + "description": "Explicit CPU/memory resource requests and limits for the scheduler.", + "default": {} + }, "resourcesPreset": { "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "description": "Use a common resources preset when `resources` is not set explicitly.", "default": "micro", "enum": [ "none", @@ -82,11 +87,6 @@ "xlarge", "2xlarge" ] - }, - "resources": { - "type": "object", - "description": "Resources", - "default": {} } } }, @@ -96,9 +96,14 @@ "server": { "type": "object", "properties": { + "resources": { + "type": "object", + "description": "Explicit CPU/memory resource requests and limits for the Konnectivity.", + "default": {} + }, "resourcesPreset": { "type": "string", - "description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).", + "description": "Use a common resources preset when `resources` is not set explicitly.", "default": "micro", "enum": [ "none", @@ -110,11 +115,6 @@ "xlarge", "2xlarge" ] - }, - "resources": { - "type": "object", - "description": "Resources", - "default": {} } } } @@ -124,7 +124,7 @@ }, "storageClass": { "type": "string", - "description": "StorageClass used to store user data", + "description": "StorageClass used to store user data.", "default": "replicated" }, "addons": { @@ -135,7 +135,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enables the cert-manager", + "description": "Enable cert-manager, which automatically creates and manages SSL/TLS certificates.", "default": false }, "valuesOverride": { @@ -160,7 +160,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enables the Gateway API", + "description": "Enable the Gateway API", "default": false } } @@ -170,7 +170,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role)", + "description": "Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role).", "default": false }, "valuesOverride": { @@ -180,7 +180,7 @@ }, "hosts": { "type": "array", - "description": "List of domain names that should be passed through to the cluster by upper cluster", + "description": "List of domain names that the parent cluster should route to this tenant cluster.", "default": [], "items": {} } @@ -191,7 +191,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enables the gpu-operator", + "description": "Enable the GPU-operator", "default": false }, "valuesOverride": { @@ -206,7 +206,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enables Flux CD", + "description": "Enable FluxCD", "default": false }, "valuesOverride": { @@ -221,7 +221,7 @@ "properties": { "enabled": { "type": "boolean", - "description": "Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage", + "description": "Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage.", "default": false }, "valuesOverride": { diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index d1330b5c..d0d7f36d 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -1,8 +1,8 @@ -## @section Common parameters +## @section Common Parameters -## @param host The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). -## @param controlPlane.replicas Number of replicas for Kubernetes control-plane components -## @param storageClass StorageClass used to store user data +## @param host Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. +## @param controlPlane.replicas Number of replicas for Kubernetes control-plane components. +## @param storageClass StorageClass used to store user data. ## host: "" storageClass: replicated @@ -37,7 +37,7 @@ addons: ## Cert-manager: automatically creates and manages SSL/TLS certificate ## certManager: - ## @param addons.certManager.enabled Enables the cert-manager + ## @param addons.certManager.enabled Enable cert-manager, which automatically creates and manages SSL/TLS certificates. ## @param addons.certManager.valuesOverride Custom values to override enabled: false valuesOverride: {} @@ -51,17 +51,17 @@ addons: ## Gateway API ## gatewayAPI: - ## @param addons.gatewayAPI.enabled Enables the Gateway API + ## @param addons.gatewayAPI.enabled Enable the Gateway API enabled: false ## Ingress-NGINX Controller ## ingressNginx: - ## @param addons.ingressNginx.enabled Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) + ## @param addons.ingressNginx.enabled Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). ## @param addons.ingressNginx.valuesOverride Custom values to override ## enabled: false - ## @param addons.ingressNginx.hosts List of domain names that should be passed through to the cluster by upper cluster + ## @param addons.ingressNginx.hosts List of domain names that the parent cluster should route to this tenant cluster. ## e.g: ## hosts: ## - example.org @@ -73,7 +73,7 @@ addons: ## GPU-operator: NVIDIA GPU Operator ## gpuOperator: - ## @param addons.gpuOperator.enabled Enables the gpu-operator + ## @param addons.gpuOperator.enabled Enable the GPU-operator ## @param addons.gpuOperator.valuesOverride Custom values to override enabled: false valuesOverride: {} @@ -81,7 +81,7 @@ addons: ## Flux CD ## fluxcd: - ## @param addons.fluxcd.enabled Enables Flux CD + ## @param addons.fluxcd.enabled Enable FluxCD ## @param addons.fluxcd.valuesOverride Custom values to override ## enabled: false @@ -90,7 +90,7 @@ addons: ## MonitoringAgents ## monitoringAgents: - ## @param addons.monitoringAgents.enabled Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage + ## @param addons.monitoringAgents.enabled Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. ## @param addons.monitoringAgents.valuesOverride Custom values to override ## enabled: false @@ -103,15 +103,15 @@ addons: ## valuesOverride: {} -## @section Kubernetes control plane configuration +## @section Kubernetes Control Plane Configuration ## controlPlane: replicas: 2 apiServer: - ## @param controlPlane.apiServer.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). - ## @param controlPlane.apiServer.resources Resources + ## @param controlPlane.apiServer.resources Explicit CPU/memory resource requests and limits for the API server. + ## @param controlPlane.apiServer.resourcesPreset Use a common resources preset when `resources` is not set explicitly. ## e.g: ## resources: ## limits: @@ -125,20 +125,20 @@ controlPlane: resources: {} controllerManager: - ## @param controlPlane.controllerManager.resources Resources - ## @param controlPlane.controllerManager.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## @param controlPlane.controllerManager.resources Explicit CPU/memory resource requests and limits for the controller manager. + ## @param controlPlane.controllerManager.resourcesPreset Use a common resources preset when `resources` is not set explicitly. resourcesPreset: "micro" resources: {} scheduler: - ## @param controlPlane.scheduler.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). - ## @param controlPlane.scheduler.resources Resources + ## @param controlPlane.scheduler.resources Explicit CPU/memory resource requests and limits for the scheduler. + ## @param controlPlane.scheduler.resourcesPreset Use a common resources preset when `resources` is not set explicitly. resourcesPreset: "micro" resources: {} konnectivity: server: - ## @param controlPlane.konnectivity.server.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). - ## @param controlPlane.konnectivity.server.resources Resources + ## @param controlPlane.konnectivity.server.resources Explicit CPU/memory resource requests and limits for the Konnectivity. + ## @param controlPlane.konnectivity.server.resourcesPreset Use a common resources preset when `resources` is not set explicitly. resourcesPreset: "micro" resources: {}