diff --git a/charts/matrix-stack/source/haproxy.yaml.j2 b/charts/matrix-stack/source/haproxy.yaml.j2 index 4bed4cf2f..f125b049a 100644 --- a/charts/matrix-stack/source/haproxy.yaml.j2 +++ b/charts/matrix-stack/source/haproxy.yaml.j2 @@ -11,6 +11,7 @@ replicas: 1 {{- sub_schema_values.labels() }} {{- sub_schema_values.workloadAnnotations() }} {{- sub_schema_values.containersSecurityContext() }} +{{- sub_schema_values.extraEnv() }} {{- sub_schema_values.nodeSelector() }} {{- sub_schema_values.podSecurityContext(user_id='10001', group_id='10001') }} {{- sub_schema_values.resources(requests_memory='100Mi', requests_cpu='100m', limits_memory='200Mi') }} diff --git a/charts/matrix-stack/source/matrix-rtc.yaml.j2 b/charts/matrix-stack/source/matrix-rtc.yaml.j2 index 40b542d61..f3eb60d9e 100644 --- a/charts/matrix-stack/source/matrix-rtc.yaml.j2 +++ b/charts/matrix-stack/source/matrix-rtc.yaml.j2 @@ -17,14 +17,13 @@ enabled: true {#- We set `initSecret=false` because we are describing the mechanism in the comment parameter #} {{- sub_schema_values.credential("The secret for the LiveKit SFU.\n## This is required if `sfu.enabled` and `keysYaml` is not used. It will be generated by the `initSecrets` job if it is empty", "secret", initIfAbsent=False, commented=True) | indent(2) }} -{{- sub_schema_values.ingress() -}} -{{- sub_schema_values.extraEnv() }} - replicas: 1 +{{- sub_schema_values.ingress() }} {{- sub_schema_values.image(registry='ghcr.io', repository='element-hq/lk-jwt-service', tag='0.2.3') }} {{- sub_schema_values.labels() }} {{- sub_schema_values.workloadAnnotations() }} {{- sub_schema_values.containersSecurityContext() }} +{{- sub_schema_values.extraEnv() }} {{- sub_schema_values.nodeSelector() }} {{- sub_schema_values.podSecurityContext(user_id='10033', group_id='10033') }} {{- sub_schema_values.resources(requests_memory='20Mi', requests_cpu='50m', limits_memory='20Mi') }} diff --git a/charts/matrix-stack/source/matrixAuthenticationService.yaml.j2 b/charts/matrix-stack/source/matrixAuthenticationService.yaml.j2 index d308712c5..26d70ce9f 100644 --- a/charts/matrix-stack/source/matrixAuthenticationService.yaml.j2 +++ b/charts/matrix-stack/source/matrixAuthenticationService.yaml.j2 @@ -68,6 +68,7 @@ syn2mas: {{- sub_schema_values.podSecurityContext(user_id='10005', group_id='10005') | indent(2) -}} {{- sub_schema_values.resources(requests_memory='50Mi', requests_cpu='50m', limits_memory='350Mi') | indent(2) -}} {{- sub_schema_values.serviceAccount() | indent(2) -}} + {{- sub_schema_values.extraEnv() | indent(2) -}} {{- sub_schema_values.tolerations() | indent(2) }} ## Runs the syn2mas process in dryRun mode. diff --git a/charts/matrix-stack/source/postgres.yaml.j2 b/charts/matrix-stack/source/postgres.yaml.j2 index fe5c69243..67b34303f 100644 --- a/charts/matrix-stack/source/postgres.yaml.j2 +++ b/charts/matrix-stack/source/postgres.yaml.j2 @@ -8,7 +8,8 @@ enabled: true postgresExporter: {{- sub_schema_values.image(registry='docker.io', repository='prometheuscommunity/postgres-exporter', tag='v0.17.0') | indent(2) }} {{- sub_schema_values.resources(requests_memory='10Mi', requests_cpu='10m', limits_memory='500Mi')| indent(2) }} - {{- sub_schema_values.containersSecurityContext()| indent(2) }} + {{- sub_schema_values.containersSecurityContext() | indent(2) }} + {{- sub_schema_values.extraEnv() | indent(2) }} {{- sub_schema_values.probe("liveness", periodSeconds=6, timeoutSeconds=2) | indent(2) }} {{- sub_schema_values.probe("readiness", periodSeconds=2, successThreshold=2, timeoutSeconds=2) | indent(2) }} {{- sub_schema_values.probe("startup", failureThreshold=20, periodSeconds=2) | indent(2) }} diff --git a/charts/matrix-stack/templates/deployment-markers/_helpers.tpl b/charts/matrix-stack/templates/deployment-markers/_helpers.tpl index 438abaed6..24d7dbb2f 100644 --- a/charts/matrix-stack/templates/deployment-markers/_helpers.tpl +++ b/charts/matrix-stack/templates/deployment-markers/_helpers.tpl @@ -77,19 +77,11 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" $ {{- end }} {{- end }} -{{- define "element-io.deployment-markers.env" }} +{{- define "element-io.deployment-markers.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.deployment-markers.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- $overrideEnv := dict "NAMESPACE" $root.Release.Namespace --}} -{{- $resultEnv := mustMergeOverwrite $resultEnv $overrideEnv -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} +{{- with required "element-io.deployment-markers.overrideEnv missing context" .context -}} +env: +- name: "NAMESPACE" + value: {{ $root.Release.Namespace | quote }} {{- end -}} {{- end -}} diff --git a/charts/matrix-stack/templates/deployment-markers/job.yaml b/charts/matrix-stack/templates/deployment-markers/job.yaml index 048e4a6e8..431911b1d 100644 --- a/charts/matrix-stack/templates/deployment-markers/job.yaml +++ b/charts/matrix-stack/templates/deployment-markers/job.yaml @@ -57,8 +57,7 @@ spec: resources: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.deployment-markers.env" (dict "root" $ "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "deployment-markers")) | nindent 8 }} command: - "/matrix-tools" - "deployment-markers" diff --git a/charts/matrix-stack/templates/element-web/_helpers.tpl b/charts/matrix-stack/templates/element-web/_helpers.tpl index 9e2944cc1..128701c79 100644 --- a/charts/matrix-stack/templates/element-web/_helpers.tpl +++ b/charts/matrix-stack/templates/element-web/_helpers.tpl @@ -26,24 +26,18 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} {{- end }} -{{- define "element-io.element-web.env" -}} +{{- define "element-io.element-web.overrideEnv" -}} {{- $root := .root -}} -{{- with required "element-io.element-web.env missing context" .context -}} -{{- $resultEnv := dict -}} +{{- with required "element-io.element-web.overrideEnv missing context" .context -}} {{- /* https://github.com/nginxinc/docker-nginx/blob/1.26.1/entrypoint/20-envsubst-on-templates.sh#L31-L45 If pods run with a GID of 0 this makes $output_dir to appear writable to sh, however due to running with a read-only FS the actual writing later fails. We short circuit this by using an invalid template directory and so templating as a whole is skipped by the script */ -}} -{{- $_ := set $resultEnv "NGINX_ENVSUBST_TEMPLATE_DIR" "/non-existant-so-that-this-works-with-read-only-root-filesystem" -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} +env: +- name: "NGINX_ENVSUBST_TEMPLATE_DIR" + value: "/non-existant-so-that-this-works-with-read-only-root-filesystem" {{- end -}} {{- end -}} diff --git a/charts/matrix-stack/templates/element-web/deployment.yaml b/charts/matrix-stack/templates/element-web/deployment.yaml index 1d4126ebc..d8fa71cc8 100644 --- a/charts/matrix-stack/templates/element-web/deployment.yaml +++ b/charts/matrix-stack/templates/element-web/deployment.yaml @@ -43,8 +43,7 @@ spec: imagePullPolicy: {{ .pullPolicy | default "Always" }} {{- end }} {{- end }} - env: - {{- include "element-io.element-web.env" (dict "root" $ "context" .) | nindent 10 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "element-web")) | nindent 8 }} {{- with .containersSecurityContext }} securityContext: {{- toYaml . | nindent 10 }} diff --git a/charts/matrix-stack/templates/ess-library/_pods.tpl b/charts/matrix-stack/templates/ess-library/_pods.tpl index 0b1da5256..2e53f5482 100644 --- a/charts/matrix-stack/templates/ess-library/_pods.tpl +++ b/charts/matrix-stack/templates/ess-library/_pods.tpl @@ -118,3 +118,27 @@ successThreshold: {{ . }} timeoutSeconds: {{ . }} {{- end }} {{- end }} + +{{- define "element-io.ess-library.pods.env" -}} +{{- $root := .root -}} +{{- with required "element-io.ess-library.pods.env missing context" .context -}} +{{- $componentValues := required "element-io.ess-library.pods.env missing context.componentValues" .componentValues -}} +{{- $resultEnv := dict -}} +{{- range $envEntry := $componentValues.extraEnv -}} +{{- $_ := set $resultEnv $envEntry.name $envEntry -}} +{{- end -}} +{{- $componentName := required "element-io.ess-library.pods.env missing context.componentName" .componentName -}} +{{- $overrideEnvType := .overrideEnvSuffix | default "overrideEnv" -}} +{{- $overrideEnvDocument := include (printf "element-io.%s.%s" $componentName $overrideEnvType) (dict "root" $root "context" $componentValues) -}} +{{- $overrideEnvYaml := $overrideEnvDocument | fromYaml -}} +{{- range $envEntry := $overrideEnvYaml.env -}} +{{- $_ := set $resultEnv $envEntry.name $envEntry -}} +{{- end -}} +{{- with $resultEnv }} +env: +{{- range $key, $fullEnvEntry := . }} +- {{ $fullEnvEntry | toYaml | indent 2 | trim }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/matrix-stack/templates/ess-library/_render_config.tpl b/charts/matrix-stack/templates/ess-library/_render_config.tpl index 22fc15415..62d7be991 100644 --- a/charts/matrix-stack/templates/ess-library/_render_config.tpl +++ b/charts/matrix-stack/templates/ess-library/_render_config.tpl @@ -53,9 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{- range $overrides }} - /config-templates/{{ . }} {{- end }} - env: - {{- include (printf "element-io.%s.matrixToolsEnv" $nameSuffix) (dict "root" $root "context" .) | nindent 2 }} - {{- include (printf "element-io.%s.env" $nameSuffix) (dict "root" $root "context" .) | nindent 2 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $root "context" (dict "componentValues" . "componentName" $nameSuffix "overrideEnvSuffix" "renderConfigOverrideEnv")) | nindent 2 }} {{- with .resources }} resources: {{- toYaml . | nindent 4 }} diff --git a/charts/matrix-stack/templates/haproxy/_helpers.tpl b/charts/matrix-stack/templates/haproxy/_helpers.tpl index 6e9ba30e9..05e74d837 100644 --- a/charts/matrix-stack/templates/haproxy/_helpers.tpl +++ b/charts/matrix-stack/templates/haproxy/_helpers.tpl @@ -1,5 +1,5 @@ {{- /* -Copyright 2024 New Vector Ltd +Copyright 2024-2025 New Vector Ltd SPDX-License-Identifier: AGPL-3.0-only */ -}} @@ -24,3 +24,7 @@ haproxy.cfg: | {{- (tpl ($root.Files.Get "configs/haproxy/429.http.tpl") dict) | nindent 2 }} {{- end -}} {{- end -}} + +{{- define "element-io.haproxy.overrideEnv" }} +env: [] +{{- end -}} diff --git a/charts/matrix-stack/templates/haproxy/deployment.yaml b/charts/matrix-stack/templates/haproxy/deployment.yaml index d4ee66ed8..aa949efaf 100644 --- a/charts/matrix-stack/templates/haproxy/deployment.yaml +++ b/charts/matrix-stack/templates/haproxy/deployment.yaml @@ -63,10 +63,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} -{{- with .extraEnv }} - env: - {{- toYaml . | nindent 10 }} -{{- end }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "haproxy")) | nindent 8 }} ports: {{- if $.Values.synapse.enabled }} - containerPort: 8008 diff --git a/charts/matrix-stack/templates/init-secrets/_helpers.tpl b/charts/matrix-stack/templates/init-secrets/_helpers.tpl index e00d3f893..6acee2d32 100644 --- a/charts/matrix-stack/templates/init-secrets/_helpers.tpl +++ b/charts/matrix-stack/templates/init-secrets/_helpers.tpl @@ -85,19 +85,11 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" $ {{- end }} {{- end }} -{{- define "element-io.init-secrets.env" }} +{{- define "element-io.init-secrets.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.init-secrets.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- $overrideEnv := dict "NAMESPACE" $root.Release.Namespace --}} -{{- $resultEnv := mustMergeOverwrite $resultEnv $overrideEnv -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} +{{- with required "element-io.init-secrets.overrideEnv missing context" .context -}} +env: +- name: "NAMESPACE" + value: {{ $root.Release.Namespace | quote }} {{- end -}} {{- end -}} diff --git a/charts/matrix-stack/templates/init-secrets/job.yaml b/charts/matrix-stack/templates/init-secrets/job.yaml index a4a866ce7..a4a127c3a 100644 --- a/charts/matrix-stack/templates/init-secrets/job.yaml +++ b/charts/matrix-stack/templates/init-secrets/job.yaml @@ -57,8 +57,7 @@ spec: resources: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.init-secrets.env" (dict "root" $ "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "init-secrets")) | nindent 8 }} command: - "/matrix-tools" - "generate-secrets" diff --git a/charts/matrix-stack/templates/matrix-authentication-service/_helpers.tpl b/charts/matrix-stack/templates/matrix-authentication-service/_helpers.tpl index f1352e4a2..89770308e 100644 --- a/charts/matrix-stack/templates/matrix-authentication-service/_helpers.tpl +++ b/charts/matrix-stack/templates/matrix-authentication-service/_helpers.tpl @@ -92,20 +92,12 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} {{- end }} -{{- define "element-io.matrix-authentication-service.env" }} + +{{- define "element-io.matrix-authentication-service.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.matrix-authentication-service.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- $overrideEnv := dict "MAS_CONFIG" "/conf/config.yaml" -}} -{{- $resultEnv := mustMergeOverwrite $resultEnv $overrideEnv -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} -{{- end -}} +env: +- name: "MAS_CONFIG" + value: "/conf/config.yaml" {{- end -}} {{- /* The filesystem structure is `/secrets`/<< secret name>>/<< secret key >>. @@ -115,9 +107,10 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . These could be done as env vars with valueFrom.secretKeyRef, but that triggers CKV_K8S_35. Environment variables values found in the config file as ${VARNAME} are parsed through go template engine before being replaced in the target file. */}} -{{- define "element-io.matrix-authentication-service.matrixToolsEnv" }} +{{- define "element-io.matrix-authentication-service.renderConfigOverrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.matrix-authentication-service.matrixToolsEnv missing context" .context -}} +{{- with required "element-io.matrix-authentication-service.renderConfigOverrideEnv missing context" .context -}} +env: - name: POSTGRES_PASSWORD value: >- {{ @@ -343,7 +336,7 @@ true {{- define "element-io.syn2mas.configSecrets" -}} {{- $root := .root -}} -{{- with required "element-io..matrix-authentication-service.syn2mas.configSecrets missing context" .context -}} +{{- with required "element-io.syn2mas.configSecrets missing context" .context -}} {{- $masSecrets := include "element-io.matrix-authentication-service.configSecrets" (dict "root" $root "context" .masContext) | fromJsonArray }} {{- $synapseSecrets := include "element-io.synapse.configSecrets" (dict "root" $root "context" .synapseContext) | fromJsonArray }} {{- $syn2masSecrets := concat $masSecrets $synapseSecrets | uniq | sortAlpha }} @@ -351,3 +344,11 @@ true {{- end -}} {{- end -}} +{{- define "element-io.syn2mas.overrideEnv" -}} +{{- $root := .root -}} +{{- with required "element-io.syn2mas.overrideEnv missing context" .context -}} +env: +- name: "NAMESPACE" + value: {{ $root.Release.Namespace | quote }} +{{- end -}} +{{- end -}} diff --git a/charts/matrix-stack/templates/matrix-authentication-service/deployment.yaml b/charts/matrix-stack/templates/matrix-authentication-service/deployment.yaml index 8443820a2..6c31a48c6 100644 --- a/charts/matrix-stack/templates/matrix-authentication-service/deployment.yaml +++ b/charts/matrix-stack/templates/matrix-authentication-service/deployment.yaml @@ -83,8 +83,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.matrix-authentication-service.env" (dict "root" $ "context" .) | nindent 10 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "matrix-authentication-service")) | nindent 8 }} {{- with .resources }} resources: {{- toYaml . | nindent 10 }} @@ -118,8 +117,7 @@ We don't want background jobs to get failed use up their retries because MAS has securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.matrix-authentication-service.env" (dict "root" $ "context" .) | nindent 10 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "matrix-authentication-service")) | nindent 8 }} ports: - containerPort: 8080 protocol: TCP diff --git a/charts/matrix-stack/templates/matrix-authentication-service/syn2mas_job.yaml b/charts/matrix-stack/templates/matrix-authentication-service/syn2mas_job.yaml index bff437a80..94fb688aa 100644 --- a/charts/matrix-stack/templates/matrix-authentication-service/syn2mas_job.yaml +++ b/charts/matrix-stack/templates/matrix-authentication-service/syn2mas_job.yaml @@ -220,12 +220,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - - name: NAMESPACE - value: {{ $.Release.Namespace }} -{{- with .extraEnv }} - {{- toYaml . | nindent 8 }} -{{- end }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "syn2mas")) | nindent 8 }} {{- with .resources }} resources: {{- toYaml . | nindent 10 }} diff --git a/charts/matrix-stack/templates/matrix-rtc/_helpers.tpl b/charts/matrix-stack/templates/matrix-rtc/_helpers.tpl index e0dc3fba5..ff896e79e 100644 --- a/charts/matrix-stack/templates/matrix-rtc/_helpers.tpl +++ b/charts/matrix-stack/templates/matrix-rtc/_helpers.tpl @@ -38,25 +38,25 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} -{{- define "element-io.matrix-rtc-authorisation-service.env" }} +{{- define "element-io.matrix-rtc-authorisation-service.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.matrix-rtc-authorisation-service.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} +{{- with required "element-io.matrix-rtc-authorisation-service.overrideEnv missing context" .context -}} +env: {{- if (.livekitAuth).keysYaml }} -{{- $_ := set $resultEnv "LIVEKIT_KEY_FILE" (printf "/secrets/%s" +- name: "LIVEKIT_KEY_FILE" + value: {{ printf "/secrets/%s" (include "element-io.ess-library.provided-secret-path" ( dict "root" $root "context" ( dict "secretPath" "matrixRTC.livekitAuth.keysYaml" "defaultSecretName" (printf "%s-matrix-rtc-authorisation-service" $root.Release.Name) "defaultSecretKey" "LIVEKIT_KEYS_YAML" ) - ))) }} + )) }} {{- else }} -{{- $_ := set $resultEnv "LIVEKIT_KEY" ((.livekitAuth).key | default "matrix-rtc") -}} -{{- $_ := set $resultEnv "LIVEKIT_SECRET_FROM_FILE" (printf "/secrets/%s" +- name: "LIVEKIT_KEY" + value: {{ (.livekitAuth).key | default "matrix-rtc" }} +- name: "LIVEKIT_SECRET_FROM_FILE" + value: {{ printf "/secrets/%s" (include "element-io.ess-library.init-secret-path" ( dict "root" $root "context" ( dict "secretPath" "matrixRTC.livekitAuth.secret" @@ -64,14 +64,11 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . "defaultSecretName" (printf "%s-matrix-rtc-authorisation-service" $root.Release.Name) "defaultSecretKey" "LIVEKIT_SECRET" ) - ))) }} + )) }} {{- end }} -{{- if .sfu.enabled -}} -{{- $_ := set $resultEnv "LIVEKIT_URL" (printf "wss://%s" (tpl .ingress.host $root)) -}} -{{- end -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} +{{- if .sfu.enabled }} +- name: "LIVEKIT_URL" + value: {{ printf "wss://%s" (tpl .ingress.host $root) }} {{- end -}} {{- end -}} {{- end -}} diff --git a/charts/matrix-stack/templates/matrix-rtc/_sfu_helpers.tpl b/charts/matrix-stack/templates/matrix-rtc/_sfu_helpers.tpl index b7c3c05ad..c21278765 100644 --- a/charts/matrix-stack/templates/matrix-rtc/_sfu_helpers.tpl +++ b/charts/matrix-stack/templates/matrix-rtc/_sfu_helpers.tpl @@ -26,23 +26,14 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} {{- end }} -{{- define "element-io.matrix-rtc-sfu.env" }} -{{- $root := .root -}} -{{- with required "element-io.matrix-rtc-authorisation-service missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} -{{- end -}} +{{- define "element-io.matrix-rtc-sfu.overrideEnv" }} +env: [] {{- end -}} -{{- define "element-io.matrix-rtc-sfu.matrixToolsEnv" }} +{{- define "element-io.matrix-rtc-sfu.renderConfigOverrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.matrix-rtc-sfu.matrixToolsEnv missing context" .context -}} +{{- with required "element-io.matrix-rtc-sfu.renderConfigOverrideEnv missing context" .context -}} +env: - name: "LIVEKIT_KEY" value: "{{ (.livekitAuth).key | default "matrix-rtc" }}" - name: LIVEKIT_SECRET diff --git a/charts/matrix-stack/templates/matrix-rtc/authorisation_deployment.yaml b/charts/matrix-stack/templates/matrix-rtc/authorisation_deployment.yaml index 605e152e9..6e2b95913 100644 --- a/charts/matrix-stack/templates/matrix-rtc/authorisation_deployment.yaml +++ b/charts/matrix-stack/templates/matrix-rtc/authorisation_deployment.yaml @@ -50,8 +50,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.matrix-rtc-authorisation-service.env" (dict "root" $ "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "matrix-rtc-authorisation-service")) | nindent 8 }} ports: - containerPort: 8080 name: http diff --git a/charts/matrix-stack/templates/matrix-rtc/sfu_deployment.yaml b/charts/matrix-stack/templates/matrix-rtc/sfu_deployment.yaml index 10a5279db..c8de09b6a 100644 --- a/charts/matrix-stack/templates/matrix-rtc/sfu_deployment.yaml +++ b/charts/matrix-stack/templates/matrix-rtc/sfu_deployment.yaml @@ -78,10 +78,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} -{{- with (include "element-io.matrix-rtc-sfu.env" (dict "root" $ "context" .)) }} - env: - {{- . | nindent 10 }} - {{- end }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "matrix-rtc-sfu")) | nindent 8 }} ports: - containerPort: 6789 name: metrics diff --git a/charts/matrix-stack/templates/postgres/_helpers.tpl b/charts/matrix-stack/templates/postgres/_helpers.tpl index d109fedb7..f1e7df6e5 100644 --- a/charts/matrix-stack/templates/postgres/_helpers.tpl +++ b/charts/matrix-stack/templates/postgres/_helpers.tpl @@ -91,52 +91,41 @@ true {{- end -}} {{- end -}} -{{- define "element-io.postgres.env" }} +{{- define "element-io.postgres.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.postgres.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- $overrideEnv := dict "POSTGRES_PASSWORD_FILE" (printf "/secrets/%s" - (include "element-io.ess-library.init-secret-path" ( - dict "root" $root "context" ( - dict "secretPath" "postgres.adminPassword" - "initSecretKey" "POSTGRES_ADMIN_PASSWORD" - "defaultSecretName" (include "element-io.postgres.secret-name" (dict "root" $root "context" (dict "isHook" false))) - "defaultSecretKey" "ADMIN_PASSWORD" - ) - ) - ) - ) - "PGDATA" "/var/lib/postgres/data/pgdata" - "POSTGRES_INITDB_ARGS" "-E UTF8" - "LC_COLLATE" "C" - "LC_CTYPE" "C" --}} -{{- $resultEnv := mustMergeOverwrite $resultEnv $overrideEnv -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} +{{- with required "element-io.postgres.overrideEnv missing context" .context -}} +env: +- name: "POSTGRES_PASSWORD_FILE" + value: {{ printf "/secrets/%s" ( + include "element-io.ess-library.init-secret-path" (dict + "root" $root + "context" (dict + "secretPath" "postgres.adminPassword" + "initSecretKey" "POSTGRES_ADMIN_PASSWORD" + "defaultSecretName" (include "element-io.postgres.secret-name" (dict "root" $root "context" (dict "isHook" false))) + "defaultSecretKey" "ADMIN_PASSWORD" + ) + ) + ) }} +- name: "PGDATA" + value: "/var/lib/postgres/data/pgdata" +- name: "POSTGRES_INITDB_ARGS" + value: "-E UTF8" +- name: "LC_COLLATE" + value: "C" +- name: "LC_CTYPE" + value: "C" {{- end -}} {{- end -}} -{{- define "element-io.postgres.exporter-env" }} +{{- define "element-io.postgres-exporter.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.postgres.exporter-env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- $overrideEnv := dict "DATA_SOURCE_URI" "localhost?sslmode=disable" - "DATA_SOURCE_USER" "postgres" --}} -{{- $resultEnv := mustMergeOverwrite $resultEnv $overrideEnv -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} +{{- with required "element-io.postgres-exporter.overrideEnv missing context" .context -}} +env: +- name: "DATA_SOURCE_URI" + value: "localhost?sslmode=disable" +- name: "DATA_SOURCE_USER" + value: "postgres" {{- end -}} {{- end -}} diff --git a/charts/matrix-stack/templates/postgres/statefulset.yaml b/charts/matrix-stack/templates/postgres/statefulset.yaml index 19f4c6f68..f82d0a260 100644 --- a/charts/matrix-stack/templates/postgres/statefulset.yaml +++ b/charts/matrix-stack/templates/postgres/statefulset.yaml @@ -53,8 +53,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.postgres.env" (dict "root" $ "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "postgres")) | nindent 8 }} args: {{ include "element-io.postgres.args" (dict "root" $ "context" .) | nindent 8 }} {{- with .resources }} @@ -126,8 +125,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} - env: - {{- include "element-io.postgres.env" (dict "root" $ "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "postgres")) | nindent 8 }} args: {{ include "element-io.postgres.args" (dict "root" $ "context" .) | nindent 8 }} {{- with .resources }} @@ -189,11 +187,10 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "postgres-exporter")) | nindent 8 }} ports: - name: metrics containerPort: 9187 - env: - {{- include "element-io.postgres.exporter-env" (dict "root" $ "context" .) | nindent 8 }} startupProbe: {{- include "element-io.ess-library.pods.probe" .startupProbe | nindent 10 }} httpGet: path: /metrics diff --git a/charts/matrix-stack/templates/synapse/_helpers.tpl b/charts/matrix-stack/templates/synapse/_helpers.tpl index 1f50e7adb..75ee9e401 100644 --- a/charts/matrix-stack/templates/synapse/_helpers.tpl +++ b/charts/matrix-stack/templates/synapse/_helpers.tpl @@ -85,6 +85,10 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} {{- end }} +{{- define "element-io.synapse-redis.overrideEnv" }} +env: [] +{{- end -}} + {{- define "element-io.synapse.enabledWorkers" -}} {{- $root := .root -}} {{ $enabledWorkers := dict }} @@ -107,23 +111,10 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . {{- end }} {{- end }} -{{- define "element-io.synapse.env" }} -{{- $root := .root -}} -{{- with required "element-io.synapse.env missing context" .context -}} -{{- $resultEnv := dict -}} -{{- range $envEntry := .extraEnv -}} -{{- $_ := set $resultEnv $envEntry.name $envEntry.value -}} -{{- end -}} -{{- range $key, $value := $resultEnv }} -- name: {{ $key | quote }} - value: {{ $value | quote }} -{{- end -}} -{{- end -}} -{{- end -}} - -{{- define "element-io.synapse.pythonEnv" }} +{{- define "element-io.synapse-python.overrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.synapse.pythonEnv missing context" .context -}} +{{- with required "element-io.synapse-python.overrideEnv missing context" .context -}} +env: - name: "LD_PRELOAD" value: "libjemalloc.so.2" {{- end -}} @@ -158,10 +149,11 @@ app.kubernetes.io/version: {{ include "element-io.ess-library.labels.makeSafe" . These could be done as env vars with valueFrom.secretKeyRef, but that triggers CKV_K8S_35. Environment variables values found in the config file as ${VARNAME} are parsed through go template engine before being replaced in the target file. */}} -{{- define "element-io.synapse.matrixToolsEnv" }} +{{- define "element-io.synapse.renderConfigOverrideEnv" }} {{- $root := .root -}} -{{- with required "element-io.synapse.matrixToolsEnv missing context" .context -}} -{{- $isHook := required "element-io.synapse.matrixToolsEnv requires context.isHook" .isHook }} +{{- with required "element-io.synapse.renderConfigOverrideEnv missing context" .context -}} +{{- $isHook := required "element-io.synapse.renderConfigOverrideEnv requires context.isHook" .isHook }} +env: - name: SYNAPSE_POSTGRES_PASSWORD value: >- {{ diff --git a/charts/matrix-stack/templates/synapse/_synapse_pod.tpl b/charts/matrix-stack/templates/synapse/_synapse_pod.tpl index 7ecdeb9c7..4ef60dc95 100644 --- a/charts/matrix-stack/templates/synapse/_synapse_pod.tpl +++ b/charts/matrix-stack/templates/synapse/_synapse_pod.tpl @@ -110,9 +110,7 @@ We have an init container to render & merge the config for several reasons: {{- range .extraArgs }} - {{ . | quote }} {{- end }} - env: - {{- include "element-io.synapse.pythonEnv" (dict "root" $root "context" .) | nindent 8 }} - {{- include "element-io.synapse.env" (dict "root" $root "context" .) | nindent 8 }} + {{- include "element-io.ess-library.pods.env" (dict "root" $root "context" (dict "componentValues" . "componentName" "synapse-python")) | nindent 6 }} {{- if not $isHook }} ports: {{- if (include "element-io.synapse.process.hasHttp" (dict "root" $root "context" $processType)) }} diff --git a/charts/matrix-stack/templates/synapse/redis_deployment.yaml b/charts/matrix-stack/templates/synapse/redis_deployment.yaml index 63b571bf7..002999176 100644 --- a/charts/matrix-stack/templates/synapse/redis_deployment.yaml +++ b/charts/matrix-stack/templates/synapse/redis_deployment.yaml @@ -50,10 +50,7 @@ spec: securityContext: {{- toYaml . | nindent 10 }} {{- end }} -{{- with .extraEnv }} - env: - {{- toYaml . | nindent 10 }} -{{- end }} + {{- include "element-io.ess-library.pods.env" (dict "root" $ "context" (dict "componentValues" . "componentName" "synapse-redis")) | nindent 8 }} ports: - containerPort: 6379 name: redis diff --git a/charts/matrix-stack/values.yaml b/charts/matrix-stack/values.yaml index 44e530d8f..cca8f01ea 100644 --- a/charts/matrix-stack/values.yaml +++ b/charts/matrix-stack/values.yaml @@ -395,6 +395,8 @@ matrixRTC: ## secret: existing-secret ## secretKey: key-in-secret # secret: {} + + replicas: 1 ## How this ingress should be constructed ingress: ## What hostname should be used for this Ingress @@ -417,14 +419,6 @@ matrixRTC: ## If set, some tweaks will be applied automatically to ingresses based on the controller type here. ## This can be set to `ingress-nginx`. # controllerType: - ## Defines additional environment variables to be injected onto this workload - ## e.g. - ## extraEnv: - ## - name: FOO - ## value: "bar" - extraEnv: [] - - replicas: 1 # Details of the image to be used image: ## The host and (optional) port of the container image registry for this component. @@ -478,6 +472,12 @@ matrixRTC: ## localhostProfile must only be set set if type Localhost. It indicates the path of the pre-configured profile on the node, relative to the kubelet's configured Seccomp profile location (configured with the --root-dir flag). # seccompProfile: # type: RuntimeDefault + ## Defines additional environment variables to be injected onto this workload + ## e.g. + ## extraEnv: + ## - name: FOO + ## value: "bar" + extraEnv: [] ## NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # nodeSelector: {} ## A subset of PodSecurityContext. PodSecurityContext holds pod-level security attributes and common container settings @@ -1181,6 +1181,12 @@ haproxy: ## localhostProfile must only be set set if type Localhost. It indicates the path of the pre-configured profile on the node, relative to the kubelet's configured Seccomp profile location (configured with the --root-dir flag). # seccompProfile: # type: RuntimeDefault + ## Defines additional environment variables to be injected onto this workload + ## e.g. + ## extraEnv: + ## - name: FOO + ## value: "bar" + extraEnv: [] ## NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # nodeSelector: {} ## A subset of PodSecurityContext. PodSecurityContext holds pod-level security attributes and common container settings @@ -1883,6 +1889,12 @@ matrixAuthenticationService: ## Annotations to add to the service account annotations: {} + ## Defines additional environment variables to be injected onto this workload + ## e.g. + ## extraEnv: + ## - name: FOO + ## value: "bar" + extraEnv: [] ## Workload tolerations allows Pods that are part of this (sub)component to 'tolerate' any taint that matches the triple using the matching operator . ## ## * effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. @@ -1969,6 +1981,12 @@ postgres: ## localhostProfile must only be set set if type Localhost. It indicates the path of the pre-configured profile on the node, relative to the kubelet's configured Seccomp profile location (configured with the --root-dir flag). # seccompProfile: # type: RuntimeDefault + ## Defines additional environment variables to be injected onto this workload + ## e.g. + ## extraEnv: + ## - name: FOO + ## value: "bar" + extraEnv: [] ## Configuration of the thresholds and frequencies of the livenessProbe livenessProbe: ## How many consecutive failures for the probe to be considered failed diff --git a/newsfragments/559.changed.1.md b/newsfragments/559.changed.1.md new file mode 100644 index 000000000..ff186ef69 --- /dev/null +++ b/newsfragments/559.changed.1.md @@ -0,0 +1,3 @@ +Consistently handle user provided `extraEnv` versus chart configured `env`. + +Chart configured `env` should win. diff --git a/newsfragments/559.changed.md b/newsfragments/559.changed.md new file mode 100644 index 000000000..8cecd2a43 --- /dev/null +++ b/newsfragments/559.changed.md @@ -0,0 +1 @@ +Document `extraEnv` in `values.yaml` for every workload. diff --git a/newsfragments/559.fixed.md b/newsfragments/559.fixed.md new file mode 100644 index 000000000..efc7df866 --- /dev/null +++ b/newsfragments/559.fixed.md @@ -0,0 +1 @@ +Fix `extraEnv` with duplicate keys not being correctly merged. diff --git a/tests/manifests/test_pod_env.py b/tests/manifests/test_pod_env.py index 45b1ff5c5..2f510a4de 100644 --- a/tests/manifests/test_pod_env.py +++ b/tests/manifests/test_pod_env.py @@ -2,33 +2,54 @@ # # SPDX-License-Identifier: AGPL-3.0-only -import pytest +from collections import defaultdict -from . import DeployableDetails, PropertyType, values_files_to_test -from .utils import iterate_deployables_workload_parts, template_id +import pytest -extra_env = {"a_string": "a", "b_boolean": True, "c_integer": 1, "d_float": 1.1} +from . import DeployableDetails, PropertyType, all_deployables_details, values_files_to_test +from .utils import iterate_deployables_workload_parts, template_id, template_to_deployable_details @pytest.mark.parametrize("values_file", values_files_to_test) @pytest.mark.asyncio_cooperative -async def test_unique_env_name_in_containers(values, make_templates): +async def test_sets_extra_env(values, make_templates): + extra_envs = [ + {"name": "a_string", "value": "first"}, + {"name": "a_string", "value": "second"}, + {"name": "b_boolean", "value": str(True)}, + {"name": "c_integer", "value": str(1)}, + {"name": "d_float", "value": str(1.1)}, + ] + def set_extra_env(deployable_details: DeployableDetails): - deployable_details.set_helm_values( - values, PropertyType.Env, [{"name": k, "value": str(v)} for k, v in extra_env.items()] - ) + deployable_details.set_helm_values(values, PropertyType.Env, extra_envs) iterate_deployables_workload_parts(set_extra_env) for template in await make_templates(values): if template["kind"] in ["Deployment", "Job", "StatefulSet"]: - for container in template["spec"]["template"]["spec"]["containers"]: + pod_spec = template["spec"]["template"]["spec"] + for container in pod_spec.get("initContainers", []) + pod_spec["containers"]: env_keys = [env["name"] for env in container.get("env", [])] assert len(env_keys) == len(set(env_keys)), ( f"{template_id(template)} has container {container['name']} " - "with env keys are not unique: {env_keys}" + f"with env keys are not unique: {env_keys}" ) - for key in extra_env: + + for env in container.get("env", []): + assert type(env["value"]) is str, ( + f"{template_id(template)} has container {container['name']} " + f"which has an non-string value: {env}" + ) + + command = " ".join(container.get("command", [])) + # We only provide extraEnv to specific matrix-tools init containers + if command.startswith("/matrix-tools") and container["command"][1] not in ["render-config", "syn2mas"]: + continue + if container["name"] in ["copy-mas-cli", "syn2mas-check"]: + continue + + for key in [extra_env["name"] for extra_env in extra_envs]: assert key in env_keys, ( f"{template_id(template)} has container {container['name']} " "that is missing some of the extra env that's being injected" @@ -37,19 +58,45 @@ def set_extra_env(deployable_details: DeployableDetails): @pytest.mark.parametrize("values_file", values_files_to_test) @pytest.mark.asyncio_cooperative -async def test_env_values_are_strings_in_containers(values, make_templates): - def set_extra_env(deployable_details: DeployableDetails): - deployable_details.set_helm_values( - values, PropertyType.Env, [{"name": k, "value": str(v)} for k, v in extra_env.items()] - ) +async def test_built_in_env_cant_be_overwritten(values, make_templates): + built_in_env = defaultdict(lambda: defaultdict(None)) - iterate_deployables_workload_parts(set_extra_env) + # Unset any env in the values file under test as this env can be overridden + for deployable_details in all_deployables_details: + if deployable_details.has_workloads: + deployable_details.get_helm_values(values, PropertyType.Env, default_value=[]).clear() + # Collect the env set for each and every container for template in await make_templates(values): if template["kind"] in ["Deployment", "Job", "StatefulSet"]: - for container in template["spec"]["template"]["spec"]["containers"]: - for env in container.get("env", []): - assert type(env["value"]) is str, ( - f"{template_id(template)} has container {container['name']} " - "which has an non-string value: {env}" - ) + pod_spec = template["spec"]["template"]["spec"] + for container in pod_spec.get("initContainers", []) + pod_spec["containers"]: + deployable_details = template_to_deployable_details(template, container["name"]) + built_in_env[deployable_details][container["name"]] = [env["name"] for env in container.get("env", [])] + + def override_env(deployable_details: DeployableDetails): + # For all env vars used across all containers for this deployable details attempt to overwrite the value + user_env = [] + for container_name in built_in_env[deployable_details]: + for env_key in built_in_env[deployable_details][container_name]: + user_env.append({"name": env_key, "value": "from-user"}) + deployable_details.set_helm_values(values, PropertyType.Env, user_env) + + iterate_deployables_workload_parts(override_env) + + for template in await make_templates(values): + if template["kind"] in ["Deployment", "Job", "StatefulSet"]: + pod_spec = template["spec"]["template"]["spec"] + for container in pod_spec.get("initContainers", []) + pod_spec["containers"]: + deployable_details = template_to_deployable_details(template, container["name"]) + + env_keys_from_chart = built_in_env[deployable_details][container["name"]] + for env_var in container.get("env", []): + # We can't just look for the value being 'from-user' as a deployable_details may have multiple + # containers each setting different env vars. We'll have provided a 'from-user' env var override + # for all of those env vars and so 'from-user' will legitimately be present on some containers + if env_var["name"] in env_keys_from_chart: + assert env_var["value"] != "from-user", ( + f"{template_id(template)}/{container['name']} allowed env var " + f"{env_var['name']} to be overwritten" + )