This is an automated email from the ASF dual-hosted git repository.
Miretpl pushed a commit to branch chart/v1-2x-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/chart/v1-2x-test by this push:
new 509c2fed309 [chart/v1-2x-test] Allow configuring key names in database
credential secrets (#69954) (#70646)
509c2fed309 is described below
commit 509c2fed309640c7732d4f657dbf698111544bda
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Jul 28 23:23:00 2026 +0200
[chart/v1-2x-test] Allow configuring key names in database credential
secrets (#69954) (#70646)
* Allow configuring key names in database credential secrets
The chart hardcoded 'key: connection' in the secretKeyRef for the metadata,
result backend, and broker URL env vars, so externally managed secrets using a
different key (e.g. CloudNativePG's 'uri') could not be used with
metadataSecretName and friends.
Add data.metadataSecretKey, data.resultBackendSecretKey and
data.brokerUrlSecretKey, defaulting to 'connection'. The custom key only
applies when the corresponding *SecretName is provided, since chart-created
secrets always write the 'connection' key.
* Address review comments: clarify values and docs wording
(cherry picked from commit dc75103d64cb2213ed2eed7c4dec40a755e585bf)
Co-authored-by: Preetham Sanji
<[email protected]>
---
chart/docs/production-guide.rst | 15 ++++
chart/templates/_helpers.yaml | 32 +++++++-
chart/values.schema.json | 25 ++++++
chart/values.yaml | 11 +++
.../helm_tests/airflow_aux/test_airflow_common.py | 95 ++++++++++++++++++++++
5 files changed, 174 insertions(+), 4 deletions(-)
diff --git a/chart/docs/production-guide.rst b/chart/docs/production-guide.rst
index 402088692eb..22f2f88923c 100644
--- a/chart/docs/production-guide.rst
+++ b/chart/docs/production-guide.rst
@@ -88,6 +88,21 @@ After secret creation, configure the chart to use the secret:
data:
metadataSecretName: mydatabase
+If your secret stores the connection string under a key other than
``connection`` (for
+example, `CloudNativePG <https://cloudnative-pg.io/>`_ generates credential
secrets with
+the connection URI under the ``uri`` key), set ``metadataSecretKey``
accordingly:
+
+.. code-block:: yaml
+ :caption: values.yaml
+
+ data:
+ metadataSecretName: mydatabase-app
+ metadataSecretKey: uri
+
+Similarly, ``resultBackendSecretKey`` and ``brokerUrlSecretKey`` configure the
key names
+used with ``resultBackendSecretName`` and ``brokerUrlSecretName``. All of
these default to
+``connection`` and only apply when the corresponding secret name is provided.
+
.. _production-guide:pgbouncer:
Metadata DB Cleanup
diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml
index 2f8bd7822cb..04f5516567a 100644
--- a/chart/templates/_helpers.yaml
+++ b/chart/templates/_helpers.yaml
@@ -75,14 +75,14 @@ If release name contains chart name it will be used as a
full name.
valueFrom:
secretKeyRef:
name: {{ template "airflow_metadata_secret" . }}
- key: connection
+ key: {{ template "airflow_metadata_secret_key" . }}
{{- end }}
{{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW_CONN_AIRFLOW_DB }}
- name: AIRFLOW_CONN_AIRFLOW_DB
valueFrom:
secretKeyRef:
name: {{ template "airflow_metadata_secret" . }}
- key: connection
+ key: {{ template "airflow_metadata_secret_key" . }}
{{- end }}
{{- $kedaEnabled := .Values.workers.keda.enabled }}
{{- $kedaUsePgBouncer := .Values.workers.keda.usePgbouncer }}
@@ -127,14 +127,14 @@ If release name contains chart name it will be used as a
full name.
valueFrom:
secretKeyRef:
name: {{ template "airflow_result_backend_secret" . }}
- key: connection
+ key: {{ template "airflow_result_backend_secret_key" . }}
{{- end }}
{{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__BROKER_URL }}
- name: AIRFLOW__CELERY__BROKER_URL
valueFrom:
secretKeyRef:
name: {{ template "airflow_broker_url_secret" . }}
- key: connection
+ key: {{ template "airflow_broker_url_secret_key" . }}
{{- end }}
{{- end }}
{{- if and .Values.elasticsearch.enabled
.Values.enableBuiltInSecretEnvVars.AIRFLOW__ELASTICSEARCH__HOST }}
@@ -486,6 +486,30 @@ If release name contains chart name it will be used as a
full name.
{{- default (printf "%s-result-backend" (include "airflow.fullname" .))
.Values.data.resultBackendSecretName }}
{{- end }}
+{{- define "airflow_metadata_secret_key" -}}
+ {{- if .Values.data.metadataSecretName -}}
+ {{- .Values.data.metadataSecretKey | default "connection" -}}
+ {{- else -}}
+ connection
+ {{- end -}}
+{{- end }}
+
+{{- define "airflow_result_backend_secret_key" -}}
+ {{- if .Values.data.resultBackendSecretName -}}
+ {{- .Values.data.resultBackendSecretKey | default "connection" -}}
+ {{- else -}}
+ connection
+ {{- end -}}
+{{- end }}
+
+{{- define "airflow_broker_url_secret_key" -}}
+ {{- if .Values.data.brokerUrlSecretName -}}
+ {{- .Values.data.brokerUrlSecretKey | default "connection" -}}
+ {{- else -}}
+ connection
+ {{- end -}}
+{{- end }}
+
{{- define "airflow_pod_template_file" -}}
{{- printf "%s/pod_templates" .Values.airflowHome }}
{{- end }}
diff --git a/chart/values.schema.json b/chart/values.schema.json
index e57cacdb7f0..236f63c8e2d 100644
--- a/chart/values.schema.json
+++ b/chart/values.schema.json
@@ -1447,6 +1447,14 @@
],
"default": null
},
+ "metadataSecretKey": {
+ "description": "Key in the metadata connection secret
containing the connection string. Only used when `metadataSecretName` is set.",
+ "type": [
+ "string",
+ "null"
+ ],
+ "default": null
+ },
"resultBackendSecretName": {
"description": "Result backend connection string secret.",
"type": [
@@ -1455,6 +1463,14 @@
],
"default": null
},
+ "resultBackendSecretKey": {
+ "description": "Key in the result backend connection
secret containing the connection string. Only used when
`resultBackendSecretName` is set.",
+ "type": [
+ "string",
+ "null"
+ ],
+ "default": null
+ },
"brokerUrlSecretName": {
"description": "Redis broker URL secret.",
"type": [
@@ -1464,6 +1480,15 @@
"x-docsSection": "Redis",
"default": null
},
+ "brokerUrlSecretKey": {
+ "description": "Key in the broker URL secret containing
the broker URL. Only used when `brokerUrlSecretName` is set.",
+ "type": [
+ "string",
+ "null"
+ ],
+ "x-docsSection": "Redis",
+ "default": null
+ },
"metadataConnection": {
"description": "Metadata connection configuration.",
"type": "object",
diff --git a/chart/values.yaml b/chart/values.yaml
index b9d4b708510..7d848823458 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -511,13 +511,24 @@ data:
# postgresql+psycopg2://airflow:password@postgres/airflow
metadataSecretName: ~
+ # When `metadataSecretName` is set, the key in that secret contains the
connection string.
+ # Useful when the secret is managed externally, e.g. CloudNativePG stores
the URI under the "uri" key.
+ metadataSecretKey: ~
+
# If not set, falls back to metadataSecretName. The secret must contain
'connection' key which is
# a base64-encoded connection string, e.g.:
# postgresql+psycopg2://user:password@host/db
resultBackendSecretName: ~
+ # When `resultBackendSecretName` is set, the key in that secret contains the
result backend
+ # connection string.
+ resultBackendSecretKey: ~
+
brokerUrlSecretName: ~
+ # When `brokerUrlSecretName` is set, the key in that secret contains the
broker URL.
+ brokerUrlSecretKey: ~
+
# If `metadataSecretName` is not specified, pass connection values below
metadataConnection:
user: postgres
diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
index adf348afa34..0f786a77fba 100644
--- a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
+++ b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
@@ -654,3 +654,98 @@ class TestAirflowCommon:
for doc in docs:
assert matcher(doc) == enable_service_links
+
+
+class TestDatabaseSecretKeys:
+ """Tests for configurable key names in database credential secrets."""
+
+ @staticmethod
+ def _secret_refs(doc):
+ env = jmespath.search("spec.template.spec.containers[0].env", doc)
+ return {
+ e["name"]: e["valueFrom"]["secretKeyRef"]
+ for e in env
+ if e.get("valueFrom", {}).get("secretKeyRef")
+ }
+
+ def test_metadata_secret_key_defaults_to_connection(self):
+ docs = render_chart(
+ values={"data": {"metadataSecretName": "my-metadata-secret"}},
+ show_only=["templates/scheduler/scheduler-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__DATABASE__SQL_ALCHEMY_CONN"]["key"] ==
"connection"
+ assert refs["AIRFLOW_CONN_AIRFLOW_DB"]["key"] == "connection"
+
+ def test_metadata_secret_key_custom(self):
+ docs = render_chart(
+ values={"data": {"metadataSecretName": "cnpg-cluster-app",
"metadataSecretKey": "uri"}},
+ show_only=["templates/scheduler/scheduler-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ for var in ("AIRFLOW__DATABASE__SQL_ALCHEMY_CONN",
"AIRFLOW_CONN_AIRFLOW_DB"):
+ assert refs[var]["name"] == "cnpg-cluster-app"
+ assert refs[var]["key"] == "uri"
+
+ def test_metadata_secret_key_ignored_for_chart_created_secret(self):
+ docs = render_chart(
+ values={"data": {"metadataSecretKey": "uri"}},
+ show_only=["templates/scheduler/scheduler-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__DATABASE__SQL_ALCHEMY_CONN"]["key"] ==
"connection"
+ assert refs["AIRFLOW_CONN_AIRFLOW_DB"]["key"] == "connection"
+
+ def test_result_backend_secret_key_custom(self):
+ docs = render_chart(
+ values={
+ "executor": "CeleryExecutor",
+ "data": {"resultBackendSecretName": "my-rb-secret",
"resultBackendSecretKey": "uri"},
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__CELERY__RESULT_BACKEND"]["name"] ==
"my-rb-secret"
+ assert refs["AIRFLOW__CELERY__RESULT_BACKEND"]["key"] == "uri"
+
+ def test_result_backend_secret_key_ignored_for_chart_created_secret(self):
+ docs = render_chart(
+ values={
+ "executor": "CeleryExecutor",
+ "data": {
+ "resultBackendConnection": {
+ "user": "postgres",
+ "pass": "postgres",
+ "protocol": "postgresql",
+ "host": "example",
+ "port": 5432,
+ "db": "postgres",
+ "sslmode": "disable",
+ },
+ "resultBackendSecretKey": "uri",
+ },
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__CELERY__RESULT_BACKEND"]["key"] == "connection"
+
+ def test_broker_url_secret_key_custom(self):
+ docs = render_chart(
+ values={
+ "executor": "CeleryExecutor",
+ "data": {"brokerUrlSecretName": "my-broker-secret",
"brokerUrlSecretKey": "url"},
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__CELERY__BROKER_URL"]["name"] ==
"my-broker-secret"
+ assert refs["AIRFLOW__CELERY__BROKER_URL"]["key"] == "url"
+
+ def test_broker_url_secret_key_ignored_for_chart_created_secret(self):
+ docs = render_chart(
+ values={"executor": "CeleryExecutor", "data":
{"brokerUrlSecretKey": "url"}},
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+ refs = self._secret_refs(docs[0])
+ assert refs["AIRFLOW__CELERY__BROKER_URL"]["key"] == "connection"