This is an automated email from the ASF dual-hosted git repository.
jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 9f8d27c445f Move triggerer from pod-log-reader-role to
pod-launcher-role (#56872)
9f8d27c445f is described below
commit 9f8d27c445fa349d5221111442d49dc74ee6833e
Author: AutomationDev85 <[email protected]>
AuthorDate: Wed Oct 29 09:40:15 2025 +0100
Move triggerer from pod-log-reader-role to pod-launcher-role (#56872)
* Enable triggerer with pod-launcher-role
* Improve unit tests
---------
Co-authored-by: AutomationDev85 <AutomationDev85>
---
chart/templates/rbac/pod-launcher-rolebinding.yaml | 5 +
chart/templates/rbac/pod-log-reader-role.yaml | 2 +-
.../templates/rbac/pod-log-reader-rolebinding.yaml | 7 +-
.../helm_tests/security/test_rbac_pod_launcher.py | 125 +++++++++++++++++++++
.../security/test_rbac_pod_log_reader.py | 27 ++---
5 files changed, 142 insertions(+), 24 deletions(-)
diff --git a/chart/templates/rbac/pod-launcher-rolebinding.yaml
b/chart/templates/rbac/pod-launcher-rolebinding.yaml
index b70cc03b413..ec84f036191 100644
--- a/chart/templates/rbac/pod-launcher-rolebinding.yaml
+++ b/chart/templates/rbac/pod-launcher-rolebinding.yaml
@@ -86,4 +86,9 @@ subjects:
{{- end }}
{{- end }}
{{- end }}
+ {{- if .Values.triggerer.enabled }}
+ - kind: ServiceAccount
+ name: {{ include "triggerer.serviceAccountName" . }}
+ namespace: "{{ .Release.Namespace }}"
+ {{- end }}
{{- end }}
diff --git a/chart/templates/rbac/pod-log-reader-role.yaml
b/chart/templates/rbac/pod-log-reader-role.yaml
index dbc9386af48..59563e8860f 100644
--- a/chart/templates/rbac/pod-log-reader-role.yaml
+++ b/chart/templates/rbac/pod-log-reader-role.yaml
@@ -20,7 +20,7 @@
################################
## Airflow Pod Reader Role
#################################
-{{- if and .Values.rbac.create (or .Values.webserver.allowPodLogReading
.Values.triggerer.enabled) }}
+{{- if and .Values.rbac.create .Values.webserver.allowPodLogReading }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.multiNamespaceMode }}
kind: ClusterRole
diff --git a/chart/templates/rbac/pod-log-reader-rolebinding.yaml
b/chart/templates/rbac/pod-log-reader-rolebinding.yaml
index ba770b20c5b..c9f787601e0 100644
--- a/chart/templates/rbac/pod-log-reader-rolebinding.yaml
+++ b/chart/templates/rbac/pod-log-reader-rolebinding.yaml
@@ -20,7 +20,7 @@
################################
## Airflow Pod Reader Role Binding
#################################
-{{- if and .Values.rbac.create (or (and .Values.webserver.allowPodLogReading
(semverCompare "<3.0.0" .Values.airflowVersion)) (and
.Values.apiServer.allowPodLogReading (semverCompare ">=3.0.0"
.Values.airflowVersion)) .Values.triggerer.enabled) }}
+{{- if and .Values.rbac.create (or (and .Values.webserver.allowPodLogReading
(semverCompare "<3.0.0" .Values.airflowVersion)) (and
.Values.apiServer.allowPodLogReading (semverCompare ">=3.0.0"
.Values.airflowVersion))) }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.multiNamespaceMode }}
kind: ClusterRoleBinding
@@ -65,9 +65,4 @@ subjects:
name: {{ include "apiServer.serviceAccountName" . }}
namespace: "{{ .Release.Namespace }}"
{{- end }}
- {{- if .Values.triggerer.enabled }}
- - kind: ServiceAccount
- name: {{ include "triggerer.serviceAccountName" . }}
- namespace: "{{ .Release.Namespace }}"
- {{- end }}
{{- end }}
diff --git a/helm-tests/tests/helm_tests/security/test_rbac_pod_launcher.py
b/helm-tests/tests/helm_tests/security/test_rbac_pod_launcher.py
new file mode 100644
index 00000000000..11d185e47c2
--- /dev/null
+++ b/helm-tests/tests/helm_tests/security/test_rbac_pod_launcher.py
@@ -0,0 +1,125 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import jmespath
+import pytest
+from chart_utils.helm_template_generator import render_chart
+
+
+class TestPodLauncher:
+ """Tests RBAC Pod Launcher."""
+
+ @pytest.mark.parametrize(
+ "rbac_create, allow_pod_launching, multi_ns, expected_kind,
expected_name",
+ [
+ (True, True, False, "Role", "release-name-pod-launcher-role"),
+ (True, True, True, "ClusterRole",
"default-release-name-pod-launcher-role"),
+ (True, False, False, None, None),
+ (False, True, False, None, None),
+ ],
+ )
+ def test_pod_launcher_role(
+ self, rbac_create, allow_pod_launching, multi_ns, expected_kind,
expected_name
+ ):
+ docs = render_chart(
+ values={
+ "rbac": {"create": rbac_create},
+ "allowPodLaunching": allow_pod_launching,
+ "multiNamespaceMode": multi_ns,
+ },
+ show_only=["templates/rbac/pod-launcher-role.yaml"],
+ )
+ if expected_kind is None:
+ assert docs == []
+ else:
+ assert docs[0]["kind"] == expected_kind
+ assert docs[0]["metadata"]["name"] == expected_name
+
+ @pytest.mark.parametrize(
+ "rbac_create, allow_pod_launching, executor, dedicated_sa,
triggerer_enabled, multi_ns, expected_subjects",
+ [
+ # Only scheduler and worker SAs for KubernetesExecutor,
CeleryExecutor
+ (
+ True,
+ True,
+ "CeleryExecutor,KubernetesExecutor",
+ False,
+ False,
+ False,
+ ["release-name-airflow-scheduler",
"release-name-airflow-worker"],
+ ),
+ # Dedicated worker SAs
+ (
+ True,
+ True,
+ "CeleryExecutor,KubernetesExecutor",
+ True,
+ False,
+ False,
+ [
+ "release-name-airflow-scheduler",
+ "release-name-airflow-worker-kubernetes",
+ "release-name-airflow-worker-celery",
+ ],
+ ),
+ # Add triggerer SA if enabled
+ (
+ True,
+ True,
+ "CeleryExecutor,KubernetesExecutor",
+ False,
+ True,
+ False,
+ [
+ "release-name-airflow-scheduler",
+ "release-name-airflow-worker",
+ "release-name-airflow-triggerer",
+ ],
+ ),
+ # RoleBinding not created if allowPodLaunching is False
+ (True, False, "CeleryExecutor,KubernetesExecutor", False, False,
False, []),
+ # RoleBinding not created if rbac.create is False
+ (False, True, "CeleryExecutor,KubernetesExecutor", False, False,
False, []),
+ ],
+ )
+ def test_pod_launcher_rolebinding(
+ self,
+ rbac_create,
+ allow_pod_launching,
+ executor,
+ dedicated_sa,
+ triggerer_enabled,
+ multi_ns,
+ expected_subjects,
+ ):
+ docs = render_chart(
+ values={
+ "rbac": {"create": rbac_create},
+ "allowPodLaunching": allow_pod_launching,
+ "executor": executor,
+ "workers": {"useWorkerDedicatedServiceAccounts": dedicated_sa},
+ "triggerer": {"enabled": triggerer_enabled},
+ "multiNamespaceMode": multi_ns,
+ },
+ show_only=["templates/rbac/pod-launcher-rolebinding.yaml"],
+ )
+ if not (rbac_create and allow_pod_launching):
+ assert docs == []
+ else:
+ actual = jmespath.search("subjects[*].name", docs[0]) if docs else
[]
+ assert sorted(actual) == sorted(expected_subjects)
diff --git a/helm-tests/tests/helm_tests/security/test_rbac_pod_log_reader.py
b/helm-tests/tests/helm_tests/security/test_rbac_pod_log_reader.py
index 47b7a8bd1c0..3cd500cd550 100644
--- a/helm-tests/tests/helm_tests/security/test_rbac_pod_log_reader.py
+++ b/helm-tests/tests/helm_tests/security/test_rbac_pod_log_reader.py
@@ -25,21 +25,17 @@ class TestPodReader:
"""Tests RBAC Pod Reader."""
@pytest.mark.parametrize(
- "triggerer, webserver, airflow_version, expected",
+ "webserver, airflow_version, expected",
[
- (True, True, "2.9.0", ["release-name-airflow-webserver",
"release-name-airflow-triggerer"]),
- (True, False, "2.9.0", ["release-name-airflow-triggerer"]),
- (False, True, "2.9.0", ["release-name-airflow-webserver"]),
- (False, False, "2.9.0", []),
- (True, True, "3.0.0", ["release-name-airflow-api-server",
"release-name-airflow-triggerer"]),
- (True, False, "3.0.0", ["release-name-airflow-api-server",
"release-name-airflow-triggerer"]),
- (False, True, "3.0.0", ["release-name-airflow-api-server"]),
+ (True, "2.9.0", ["release-name-airflow-webserver"]),
+ (False, "2.9.0", []),
+ (True, "3.0.0", ["release-name-airflow-api-server"]),
+ (False, "3.0.0", ["release-name-airflow-api-server"]),
],
)
- def test_pod_log_reader_rolebinding(self, triggerer, webserver,
airflow_version, expected):
+ def test_pod_log_reader_rolebinding(self, webserver, airflow_version,
expected):
docs = render_chart(
values={
- "triggerer": {"enabled": triggerer},
"webserver": {"allowPodLogReading": webserver},
"apiServer": {"allowPodLogReading": airflow_version >=
"3.0.0"},
"airflowVersion": airflow_version,
@@ -50,18 +46,15 @@ class TestPodReader:
assert actual == expected
@pytest.mark.parametrize(
- "triggerer, webserver, expected",
+ "webserver, expected",
[
- (True, True, "release-name-pod-log-reader-role"),
- (True, False, "release-name-pod-log-reader-role"),
- (False, True, "release-name-pod-log-reader-role"),
- (False, False, None),
+ (True, "release-name-pod-log-reader-role"),
+ (False, None),
],
)
- def test_pod_log_reader_role(self, triggerer, webserver, expected):
+ def test_pod_log_reader_role(self, webserver, expected):
docs = render_chart(
values={
- "triggerer": {"enabled": triggerer},
"webserver": {"allowPodLogReading": webserver},
},
show_only=["templates/rbac/pod-log-reader-role.yaml"],