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 84420e02156 Add binding for workers.kubernetes & condition workers SA
(#66730)
84420e02156 is described below
commit 84420e0215672d75d45bd7937a61ab11dff2fdeb
Author: Przemysław Mirowski <[email protected]>
AuthorDate: Tue May 12 00:10:12 2026 +0200
Add binding for workers.kubernetes & condition workers SA (#66730)
---
chart/templates/rbac/job-launcher-rolebinding.yaml | 7 +-
chart/templates/rbac/pod-launcher-rolebinding.yaml | 7 +-
.../security-context-constraint-rolebinding.yaml | 7 +-
.../airflow_aux/test_job_launcher_role.py | 101 +++++++++++++++++++++
.../airflow_aux/test_pod_launcher_role.py | 101 +++++++++++++++++++++
.../helm_tests/security/test_scc_rolebinding.py | 97 ++++++++++++++++++++
6 files changed, 317 insertions(+), 3 deletions(-)
diff --git a/chart/templates/rbac/job-launcher-rolebinding.yaml
b/chart/templates/rbac/job-launcher-rolebinding.yaml
index f918826663b..6749b139866 100644
--- a/chart/templates/rbac/job-launcher-rolebinding.yaml
+++ b/chart/templates/rbac/job-launcher-rolebinding.yaml
@@ -60,9 +60,14 @@ subjects:
name: {{ include "scheduler.serviceAccountName" $ }}
namespace: "{{ $.Release.Namespace }}"
{{- end }}
- {{- if or (contains "CeleryExecutor" .Values.executor) (contains
"KubernetesExecutor" .Values.executor) }}
+ {{- if or (contains "CeleryExecutor" .Values.executor) (and (contains
"KubernetesExecutor" .Values.executor) (eq
.Values.workers.kubernetes.serviceAccount.create nil)) }}
- kind: ServiceAccount
name: {{ include "worker.serviceAccountName" $ }}
namespace: "{{ $.Release.Namespace }}"
{{- end }}
+ {{- if and (or .Values.workers.kubernetes.serviceAccount.create
.Values.workers.kubernetes.serviceAccount.name) (contains "KubernetesExecutor"
.Values.executor) }}
+ - kind: ServiceAccount
+ name: {{ include "worker.kubernetes.serviceAccountName" $ }}
+ namespace: "{{ $.Release.Namespace }}"
+ {{- end }}
{{- end }}
diff --git a/chart/templates/rbac/pod-launcher-rolebinding.yaml
b/chart/templates/rbac/pod-launcher-rolebinding.yaml
index 5e71c251158..f05f897f728 100644
--- a/chart/templates/rbac/pod-launcher-rolebinding.yaml
+++ b/chart/templates/rbac/pod-launcher-rolebinding.yaml
@@ -60,11 +60,16 @@ subjects:
name: {{ include "scheduler.serviceAccountName" $ }}
namespace: "{{ $.Release.Namespace }}"
{{- end }}
- {{- if or (contains "CeleryExecutor" .Values.executor) (contains
"KubernetesExecutor" .Values.executor) }}
+ {{- if or (contains "CeleryExecutor" .Values.executor) (and (contains
"KubernetesExecutor" .Values.executor) (eq
.Values.workers.kubernetes.serviceAccount.create nil)) }}
- kind: ServiceAccount
name: {{ include "worker.serviceAccountName" $ }}
namespace: "{{ $.Release.Namespace }}"
{{- end }}
+ {{- if and (or .Values.workers.kubernetes.serviceAccount.create
.Values.workers.kubernetes.serviceAccount.name) (contains "KubernetesExecutor"
.Values.executor) }}
+ - kind: ServiceAccount
+ name: {{ include "worker.kubernetes.serviceAccountName" $ }}
+ namespace: "{{ $.Release.Namespace }}"
+ {{- end }}
{{- if .Values.triggerer.enabled }}
- kind: ServiceAccount
name: {{ include "triggerer.serviceAccountName" . }}
diff --git a/chart/templates/rbac/security-context-constraint-rolebinding.yaml
b/chart/templates/rbac/security-context-constraint-rolebinding.yaml
index ecb1aff506d..cccf2d9fa42 100644
--- a/chart/templates/rbac/security-context-constraint-rolebinding.yaml
+++ b/chart/templates/rbac/security-context-constraint-rolebinding.yaml
@@ -50,11 +50,16 @@ roleRef:
kind: ClusterRole
name: system:openshift:scc:anyuid
subjects:
- {{- if or (contains "CeleryExecutor" .Values.executor) (contains
"KubernetesExecutor" .Values.executor) }}
+ {{- if or (contains "CeleryExecutor" .Values.executor) (and (contains
"KubernetesExecutor" .Values.executor) (eq
.Values.workers.kubernetes.serviceAccount.create nil)) }}
- kind: ServiceAccount
name: {{ include "worker.serviceAccountName" . }}
namespace: "{{ .Release.Namespace }}"
{{- end }}
+ {{- if and (or .Values.workers.kubernetes.serviceAccount.create
.Values.workers.kubernetes.serviceAccount.name) (contains "KubernetesExecutor"
.Values.executor) }}
+ - kind: ServiceAccount
+ name: {{ include "worker.kubernetes.serviceAccountName" . }}
+ namespace: "{{ .Release.Namespace }}"
+ {{- end }}
{{- if .Values.scheduler.enabled }}
- kind: ServiceAccount
name: {{ include "scheduler.serviceAccountName" . }}
diff --git a/chart/tests/helm_tests/airflow_aux/test_job_launcher_role.py
b/chart/tests/helm_tests/airflow_aux/test_job_launcher_role.py
index acbc181ba66..18bac0e3a9e 100644
--- a/chart/tests/helm_tests/airflow_aux/test_job_launcher_role.py
+++ b/chart/tests/helm_tests/airflow_aux/test_job_launcher_role.py
@@ -156,6 +156,107 @@ class TestJobLauncher:
assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "CeleryExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize("create", [False, True, None])
+ def test_worker_role_binding_should_exists_with_kubernetes(self, executor,
create):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowJobLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+ show_only=["templates/rbac/job-launcher-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize(
+ "executor", ["KubernetesExecutor", "LocalExecutor",
"LocalExecutor,KubernetesExecutor"]
+ )
+ @pytest.mark.parametrize("create", [False, True])
+ def test_worker_role_binding_should_not_exists_with_kubernetes(self,
executor, create):
+ docs = render_chart(
+ name="prod",
+ values={
+ "rbac": {"create": True},
+ "allowJobLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+ show_only=["templates/rbac/job-launcher-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "KubernetesExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [
+ {"create": True},
+ {"name": "prod-airflow-worker-kubernetes"},
+ {"create": False, "name": "prod-airflow-worker-kubernetes"},
+ ],
+ )
+ def test_worker_kubernetes_role_binding_should_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowJobLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+ show_only=["templates/rbac/job-launcher-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker-kubernetes",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize("executor", ["LocalExecutor", "CeleryExecutor",
"KubernetesExecutor"])
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [{"create": False}, {"create": False, "name": None}, {"create": None,
"name": None}, {}],
+ )
+ def test_worker_kubernetes_role_binding_should_not_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowJobLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+ show_only=["templates/rbac/job-launcher-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes']", docs[0])
== []
+
def test_no_role_bindings(self):
docs = render_chart(
name="prod",
diff --git a/chart/tests/helm_tests/airflow_aux/test_pod_launcher_role.py
b/chart/tests/helm_tests/airflow_aux/test_pod_launcher_role.py
index 56bb333f238..bf66464bd50 100644
--- a/chart/tests/helm_tests/airflow_aux/test_pod_launcher_role.py
+++ b/chart/tests/helm_tests/airflow_aux/test_pod_launcher_role.py
@@ -157,6 +157,107 @@ class TestPodLauncher:
assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "CeleryExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize("create", [False, True, None])
+ def test_worker_role_binding_should_exists_with_kubernetes(self, executor,
create):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowPodLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+ show_only=["templates/rbac/pod-launcher-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize(
+ "executor", ["KubernetesExecutor", "LocalExecutor",
"LocalExecutor,KubernetesExecutor"]
+ )
+ @pytest.mark.parametrize("create", [False, True])
+ def test_worker_role_binding_should_not_exists_with_kubernetes(self,
executor, create):
+ docs = render_chart(
+ name="prod",
+ values={
+ "rbac": {"create": True},
+ "allowPodLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+ show_only=["templates/rbac/pod-launcher-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "KubernetesExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [
+ {"create": True},
+ {"name": "prod-airflow-worker-kubernetes"},
+ {"create": False, "name": "prod-airflow-worker-kubernetes"},
+ ],
+ )
+ def test_worker_kubernetes_role_binding_should_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowPodLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+ show_only=["templates/rbac/pod-launcher-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker-kubernetes",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize("executor", ["LocalExecutor", "CeleryExecutor",
"KubernetesExecutor"])
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [{"create": False}, {"create": False, "name": None}, {"create": None,
"name": None}, {}],
+ )
+ def test_worker_kubernetes_role_binding_should_not_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True},
+ "allowPodLaunching": True,
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+ show_only=["templates/rbac/pod-launcher-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes']", docs[0])
== []
+
@pytest.mark.parametrize(
"executor",
["LocalExecutor", "CeleryExecutor", "KubernetesExecutor",
"CeleryExecutor,KubernetesExecutor"],
diff --git a/chart/tests/helm_tests/security/test_scc_rolebinding.py
b/chart/tests/helm_tests/security/test_scc_rolebinding.py
index 6c50b1cb04e..a9b1719a2da 100644
--- a/chart/tests/helm_tests/security/test_scc_rolebinding.py
+++ b/chart/tests/helm_tests/security/test_scc_rolebinding.py
@@ -139,6 +139,103 @@ class TestSCCActivation:
assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "CeleryExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize("create", [False, True, None])
+ def test_worker_role_binding_should_exists_with_kubernetes(self, executor,
create):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True, "createSCCRoleBinding": True},
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+
show_only=["templates/rbac/security-context-constraint-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize(
+ "executor", ["KubernetesExecutor", "LocalExecutor",
"LocalExecutor,KubernetesExecutor"]
+ )
+ @pytest.mark.parametrize("create", [False, True])
+ def test_worker_role_binding_should_not_exists_with_kubernetes(self,
executor, create):
+ docs = render_chart(
+ name="prod",
+ values={
+ "rbac": {"create": True, "createSCCRoleBinding": True},
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount": {"create":
create}}},
+ },
+
show_only=["templates/rbac/security-context-constraint-rolebinding.yaml"],
+ )
+
+ assert jmespath.search("subjects[?name=='prod-airflow-worker']",
docs[0]) == []
+
+ @pytest.mark.parametrize(
+ "executor",
+ [
+ "KubernetesExecutor",
+ "CeleryExecutor,KubernetesExecutor",
+ "LocalExecutor,CeleryExecutor,KubernetesExecutor",
+ ],
+ )
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [
+ {"create": True},
+ {"name": "prod-airflow-worker-kubernetes"},
+ {"create": False, "name": "prod-airflow-worker-kubernetes"},
+ ],
+ )
+ def test_worker_kubernetes_role_binding_should_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True, "createSCCRoleBinding": True},
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+
show_only=["templates/rbac/security-context-constraint-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes'] | [0]",
docs[0]) == {
+ "kind": "ServiceAccount",
+ "name": "prod-airflow-worker-kubernetes",
+ "namespace": "airflow",
+ }
+
+ @pytest.mark.parametrize("executor", ["LocalExecutor", "CeleryExecutor",
"KubernetesExecutor"])
+ @pytest.mark.parametrize(
+ "service_account_values",
+ [{"create": False}, {"create": False, "name": None}, {"create": None,
"name": None}, {}],
+ )
+ def test_worker_kubernetes_role_binding_should_not_exists(self, executor,
service_account_values):
+ docs = render_chart(
+ name="prod",
+ namespace="airflow",
+ values={
+ "rbac": {"create": True, "createSCCRoleBinding": True},
+ "executor": executor,
+ "workers": {"kubernetes": {"serviceAccount":
service_account_values}},
+ },
+
show_only=["templates/rbac/security-context-constraint-rolebinding.yaml"],
+ )
+
+ assert
jmespath.search("subjects[?name=='prod-airflow-worker-kubernetes']", docs[0])
== []
+
@pytest.mark.parametrize("executor", ["CeleryExecutor",
"LocalExecutor,CeleryExecutor"])
def test_flower_role_binding_should_exists(self, executor):
docs = render_chart(