This is an automated email from the ASF dual-hosted git repository.

potiuk 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 71a1f29213e Fix dataflow_config service_account for Beam Python and Go 
pipelines (#73236)
71a1f29213e is described below

commit 71a1f29213e244f9f7b351d9f08df11c47cd259e
Author: PoAn Yang <[email protected]>
AuthorDate: Mon Sep 21 01:15:32 2026 +0800

    Fix dataflow_config service_account for Beam Python and Go pipelines 
(#73236)
    
    Signed-off-by: PoAn Yang <[email protected]>
---
 .../src/airflow/providers/apache/beam/operators/beam.py |  7 ++++++-
 .../beam/tests/unit/apache/beam/operators/test_beam.py  | 17 ++++++++++++++---
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git 
a/providers/apache/beam/src/airflow/providers/apache/beam/operators/beam.py 
b/providers/apache/beam/src/airflow/providers/apache/beam/operators/beam.py
index e840940dad5..06de0c0e5b2 100644
--- a/providers/apache/beam/src/airflow/providers/apache/beam/operators/beam.py
+++ b/providers/apache/beam/src/airflow/providers/apache/beam/operators/beam.py
@@ -82,6 +82,9 @@ class BeamDataflowMixin(metaclass=ABCMeta):
     dataflow_config: DataflowConfiguration
     gcp_conn_id: str
     dataflow_support_impersonation: bool = True
+    # Beam Java reads --serviceAccount, but the Python and Go SDKs read 
--service_account_email.
+    # Java and Go reject any flag they do not define, so each operator sends 
only the name its SDK reads.
+    dataflow_service_account_option: str = "serviceAccount"
 
     def __init__(self):
         if not GOOGLE_PROVIDER:
@@ -129,7 +132,7 @@ class BeamDataflowMixin(metaclass=ABCMeta):
         if job_name_key is not None:
             pipeline_options[job_name_key] = job_name
         if self.dataflow_config.service_account:
-            pipeline_options["serviceAccount"] = 
self.dataflow_config.service_account
+            pipeline_options[self.dataflow_service_account_option] = 
self.dataflow_config.service_account
         if self.dataflow_support_impersonation and 
self.dataflow_config.impersonation_chain:
             if isinstance(self.dataflow_config.impersonation_chain, list):
                 pipeline_options["impersonateServiceAccount"] = ",".join(
@@ -351,6 +354,7 @@ class 
BeamRunPythonPipelineOperator(BeamBasePipelineOperator):
     )
     template_fields_renderers = {"dataflow_config": "json", 
"pipeline_options": "json"}
     operator_extra_links = (DataflowJobLink(),) if GOOGLE_PROVIDER else ()
+    dataflow_service_account_option = "service_account_email"
 
     def __init__(
         self,
@@ -756,6 +760,7 @@ class BeamRunGoPipelineOperator(BeamBasePipelineOperator):
     ]
     template_fields_renderers = {"dataflow_config": "json", 
"pipeline_options": "json"}
     operator_extra_links = (DataflowJobLink(),) if GOOGLE_PROVIDER else ()
+    dataflow_service_account_option = "service_account_email"
 
     def __init__(
         self,
diff --git 
a/providers/apache/beam/tests/unit/apache/beam/operators/test_beam.py 
b/providers/apache/beam/tests/unit/apache/beam/operators/test_beam.py
index 08176afab51..7e8fe2a1d51 100644
--- a/providers/apache/beam/tests/unit/apache/beam/operators/test_beam.py
+++ b/providers/apache/beam/tests/unit/apache/beam/operators/test_beam.py
@@ -54,6 +54,7 @@ OUTPUT_LOCATION = "gs://test/output"
 TEST_VERSION = f"v{version.replace('.', '-').replace('+', '-')}"
 TEST_IMPERSONATION_ACCOUNT = "[email protected]"
 TEST_POLL_SLEEP = 30
+TEST_SERVICE_ACCOUNT = "[email protected]"
 BEAM_OPERATOR_PATH = "airflow.providers.apache.beam.operators.beam.{}"
 
 
@@ -219,7 +220,10 @@ class TestBeamRunPythonPipelineOperator:
         """
         gcs_provide_file = gcs_hook.return_value.provide_file
         op = BeamRunPythonPipelineOperator(
-            dataflow_config={"impersonation_chain": 
TEST_IMPERSONATION_ACCOUNT},
+            dataflow_config={
+                "impersonation_chain": TEST_IMPERSONATION_ACCOUNT,
+                "service_account": TEST_SERVICE_ACCOUNT,
+            },
             runner="DataflowRunner",
             **self.default_op_kwargs,
         )
@@ -244,6 +248,7 @@ class TestBeamRunPythonPipelineOperator:
             "output": "gs://test/output",
             "labels": {"foo": "bar", "airflow-version": TEST_VERSION},
             "region": "us-central1",
+            "service_account_email": TEST_SERVICE_ACCOUNT,
             "impersonate_service_account": TEST_IMPERSONATION_ACCOUNT,
             "requirements_file": 
gcs_provide_file.return_value.__enter__.return_value.name,
         }
@@ -446,7 +451,9 @@ class TestBeamRunJavaPipelineOperator:
         """Test DataflowHook is created and the right args are passed to
         start_java_dataflow.
         """
-        dataflow_config = 
DataflowConfiguration(impersonation_chain="[email protected]")
+        dataflow_config = DataflowConfiguration(
+            impersonation_chain="[email protected]", 
service_account=TEST_SERVICE_ACCOUNT
+        )
         op = BeamRunJavaPipelineOperator(
             **self.default_op_kwargs, dataflow_config=dataflow_config, 
runner="DataflowRunner"
         )
@@ -473,6 +480,7 @@ class TestBeamRunJavaPipelineOperator:
             "region": "us-central1",
             "labels": {"foo": "bar"},
             "output": "gs://test/output",
+            "serviceAccount": TEST_SERVICE_ACCOUNT,
             "impersonateServiceAccount": TEST_IMPERSONATION_ACCOUNT,
         }
         persist_link_mock.assert_called_once_with(
@@ -777,7 +785,9 @@ class TestBeamRunGoPipelineOperator:
         start_go_dataflow.
         """
         gcs_download_method = gcs_hook.return_value.download
-        dataflow_config = 
DataflowConfiguration(impersonation_chain="[email protected]")
+        dataflow_config = DataflowConfiguration(
+            impersonation_chain="[email protected]", 
service_account=TEST_SERVICE_ACCOUNT
+        )
         op = BeamRunGoPipelineOperator(
             runner="DataflowRunner",
             dataflow_config=dataflow_config,
@@ -803,6 +813,7 @@ class TestBeamRunGoPipelineOperator:
             "output": "gs://test/output",
             "labels": {"foo": "bar", "airflow-version": TEST_VERSION},
             "region": "us-central1",
+            "service_account_email": TEST_SERVICE_ACCOUNT,
         }
         persist_link_mock.assert_called_once_with(context={})
         expected_go_file = "/tmp/apache-beam-go/main.go"

Reply via email to