From a8ff7f2066f8b8e4ff37a0ac1e39cf5eb50d808a Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Tue, 21 Apr 2026 18:10:24 +0200 Subject: [PATCH] save work with traefik --- bin/start-kind.sh | 203 +++++++++++++++++- bin/traefik-values.yaml | 96 +++++++++ src/frontend/apps/impress/next.config.js | 1 + .../env.d/dev/values.dev-backend.yaml.gotmpl | 9 +- src/helm/env.d/dev/values.impress.yaml.gotmpl | 4 - src/helm/impress/templates/media_svc.yaml | 13 +- 6 files changed, 314 insertions(+), 12 deletions(-) create mode 100644 bin/traefik-values.yaml diff --git a/bin/start-kind.sh b/bin/start-kind.sh index f07ab368a..46b924c5a 100755 --- a/bin/start-kind.sh +++ b/bin/start-kind.sh @@ -1,2 +1,203 @@ #!/bin/sh -curl https://raw.githubusercontent.com/numerique-gouv/tools/refs/heads/main/kind/create_cluster.sh | bash -s -- impress +set -o errexit + +CURRENT_DIR=$(pwd) +APPLICATION=${1:-app} +CLUSTERNAME=${2:-suite} + +echo "0. Create ca" +# 0. Create ca +mkcert -install +cd /tmp +mkcert "127.0.0.1.nip.io" "*.127.0.0.1.nip.io" +cd $CURRENT_DIR + +echo "1. Create registry container unless it already exists" +# 1. Create registry container unless it already exists +reg_name='kind-registry' +reg_port='5001' +if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \ + registry:2 +fi + +echo "2. Create kind cluster with containerd registry config dir enabled" +# 2. Create kind cluster with containerd registry config dir enabled +# TODO: kind will eventually enable this by default and this patch will +# be unnecessary. +# +# See: +# https://github.com/kubernetes-sigs/kind/issues/2875 +# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration +# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md +if ! kind get clusters | grep ${CLUSTERNAME}; then + cat <>/tmp/cacert.pem + kubectl -n ${APPLICATION} create configmap certifi --from-file=cacert.pem=/tmp/cacert.pem + kubectl -n ${APPLICATION} create secret generic certifi --from-file=/tmp/cacert.pem +fi + +echo "9. Check pod readiness across all namespaces..." + +sleep_interval=10 + +echo "Initial wait time: $((sleep_interval * 2)) seconds…" +sleep $((sleep_interval * 2)) + +check_pods_ready() { + local max_attempts=60 # Maximum number of attempts (10 minutes with 10s intervals) + local attempt=1 + + while [ $attempt -le $max_attempts ]; do + echo "Attempt $attempt/$max_attempts - Checking pod status..." + + not_ready_count=$( kubectl get po -A --no-headers | grep -v -E "Running|Completed"| wc -l | tr -d ' ') + + if [ "$not_ready_count" -eq 0 ]; then + echo "✅ All pods are ready!" + return 0 + else + echo "⏳ $not_ready_count pod(s) still not ready. Waiting $sleep_interval seconds…" + sleep $sleep_interval + ((attempt++)) + fi + done + + echo "❌ Timeout: Some pods are still not ready after 10 minutes" + echo "Final pod status:" + kubectl get po -A + return 1 +} + +if check_pods_ready; then + echo "🎉 Cluster is fully ready!" +else + echo "⚠️ Some pods may need manual intervention" + exit 1 +fi diff --git a/bin/traefik-values.yaml b/bin/traefik-values.yaml new file mode 100644 index 000000000..82b4f3c48 --- /dev/null +++ b/bin/traefik-values.yaml @@ -0,0 +1,96 @@ +# Configure Network Ports and EntryPoints +# EntryPoints are the network listeners for incoming traffic. +ports: + # Defines the HTTP entry point named 'web' + web: + port: 80 + nodePort: 30000 + # Instructs this entry point to redirect all traffic to the 'websecure' entry point + http: + redirections: + entryPoint: + to: websecure + scheme: https + permanent: true + + # Defines the HTTPS entry point named 'websecure' + websecure: + port: 443 + nodePort: 30001 + +# Enables the dashboard in Secure Mode +api: + dashboard: true + insecure: false + +ingressRoute: + dashboard: + enabled: true + matchRule: Host(`traefik.127.0.0.1.nip.io`) + entryPoints: + - websecure + middlewares: + - name: dashboard-auth + +# Creates a BasicAuth Middleware and Secret for the Dashboard Security +extraObjects: + - apiVersion: v1 + kind: Secret + metadata: + name: dashboard-auth-secret + type: kubernetes.io/basic-auth + stringData: + username: admin + password: "P@ssw0rd" # Replace with an Actual Password + - apiVersion: traefik.io/v1alpha1 + kind: Middleware + metadata: + name: dashboard-auth + spec: + basicAuth: + secret: dashboard-auth-secret + +# We will route with Gateway API instead. +ingressClass: + enabled: true + +# Enable Gateway API Provider & Disables the KubernetesIngress provider +# Providers tell Traefik where to find routing configuration. +providers: + kubernetesIngress: + enabled: true + kubernetesGateway: + enabled: false + +## Gateway Listeners +gateway: + listeners: + web: # HTTP listener that matches entryPoint `web` + port: 80 + protocol: HTTP + namespacePolicy: + from: All + + websecure: # HTTPS listener that matches entryPoint `websecure` + port: 443 + protocol: HTTPS # TLS terminates inside Traefik + namespacePolicy: + from: All + mode: Terminate + certificateRefs: + - kind: Secret + name: local-selfsigned-tls # the Secret we created before the installation + group: "" + +# Enable Observability +logs: + general: + level: INFO + # This enables access logs, outputting them to Traefik's standard output by default. The [Access Logs Documentation](https://doc.traefik.io/traefik/observability/access-logs/) covers formatting, filtering, and output options. + access: + enabled: true + +# Enables Prometheus for Metrics +metrics: + prometheus: + enabled: true diff --git a/src/frontend/apps/impress/next.config.js b/src/frontend/apps/impress/next.config.js index e836341cc..4692f1d7d 100644 --- a/src/frontend/apps/impress/next.config.js +++ b/src/frontend/apps/impress/next.config.js @@ -7,6 +7,7 @@ const buildId = crypto.randomBytes(256).toString('hex').slice(0, 8); /** @type {import('next').NextConfig} */ const nextConfig = { output: 'export', + allowedDevOrigins: ['docs.127.0.0.1.nip.io'], trailingSlash: true, images: { unoptimized: true, diff --git a/src/helm/env.d/dev/values.dev-backend.yaml.gotmpl b/src/helm/env.d/dev/values.dev-backend.yaml.gotmpl index 76ab8badd..f9d1f9711 100644 --- a/src/helm/env.d/dev/values.dev-backend.yaml.gotmpl +++ b/src/helm/env.d/dev/values.dev-backend.yaml.gotmpl @@ -22,13 +22,13 @@ minio: hostname: docs-minio.127.0.0.1.nip.io tls: enabled: true - secretName: docs-tls + secretName: impress-docs-tls consoleIngress: enabled: true hostname: docs-minio-console.127.0.0.1.nip.io tls: enabled: true - secretName: docs-tls + secretName: impress-docs-tls username: dinum password: password bucket: docs-media-storage @@ -44,16 +44,15 @@ keycloak: password: pass tls: enabled: true - secretName: docs-tls + secretName: impress-docs-tls db: username: dinum password: pass database: keycloak size: 1Gi image: postgres:16-alpine - realm: + realm: name: docs username: docs password: docs email: docs@example.com - diff --git a/src/helm/env.d/dev/values.impress.yaml.gotmpl b/src/helm/env.d/dev/values.impress.yaml.gotmpl index 1c222b1c5..7f6e3c887 100644 --- a/src/helm/env.d/dev/values.impress.yaml.gotmpl +++ b/src/helm/env.d/dev/values.impress.yaml.gotmpl @@ -121,10 +121,6 @@ backend: python manage.py createsuperuser --email admin@example.com --password admin restartPolicy: Never - themeCustomization: - enabled: true - file_content: {{ readFile "./configuration/theme/demo.json" }} - # Extra volume mounts to manage our local custom CA and avoid to set ssl_verify: false extraVolumeMounts: - name: certs diff --git a/src/helm/impress/templates/media_svc.yaml b/src/helm/impress/templates/media_svc.yaml index dc7bf0353..dafc052f5 100644 --- a/src/helm/impress/templates/media_svc.yaml +++ b/src/helm/impress/templates/media_svc.yaml @@ -10,5 +10,14 @@ metadata: annotations: {{- toYaml $.Values.serviceMedia.annotations | nindent 4 }} spec: - type: ExternalName - externalName: {{ $.Values.serviceMedia.host }} + ports: + - name: http + port: 9000 + protocol: TCP + targetPort: 9000 + selector: + app.kubernetes.io/component: frontend + app.kubernetes.io/instance: impress + app.kubernetes.io/name: docs + sessionAffinity: None + type: ClusterIP