Skip to content

Commit 099c490

Browse files
authored
Override project in dataprocSubmitJobOperator (#14981)
1 parent ec962b0 commit 099c490

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

airflow/providers/google/cloud/operators/dataproc.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,9 @@ class DataprocJobBaseOperator(BaseOperator):
858858
:type job_name: str
859859
:param cluster_name: The name of the DataProc cluster.
860860
:type cluster_name: str
861+
:param project_id: The ID of the Google Cloud project the cluster belongs to,
862+
if not specified the project will be inferred from the provided GCP connection.
863+
:type project_id: str
861864
:param dataproc_properties: Map for the Hive properties. Ideal to put in
862865
default arguments (templated)
863866
:type dataproc_properties: dict
@@ -912,6 +915,7 @@ def __init__(
912915
*,
913916
job_name: str = '{{task.task_id}}_{{ds_nodash}}',
914917
cluster_name: str = "cluster-1",
918+
project_id: Optional[str] = None,
915919
dataproc_properties: Optional[Dict] = None,
916920
dataproc_jars: Optional[List[str]] = None,
917921
gcp_conn_id: str = 'google_cloud_default',
@@ -943,9 +947,8 @@ def __init__(
943947

944948
self.job_error_states = job_error_states if job_error_states is not None else {'ERROR'}
945949
self.impersonation_chain = impersonation_chain
946-
947950
self.hook = DataprocHook(gcp_conn_id=gcp_conn_id, impersonation_chain=impersonation_chain)
948-
self.project_id = self.hook.project_id
951+
self.project_id = self.hook.project_id if project_id is None else project_id
949952
self.job_template = None
950953
self.job = None
951954
self.dataproc_job_id = None

tests/providers/google/cloud/operators/test_dataproc.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,12 @@ class TestDataProcSparkSqlOperator(unittest.TestCase):
781781
"labels": {"airflow-version": AIRFLOW_VERSION},
782782
"spark_sql_job": {"query_list": {"queries": [query]}, "script_variables": variables},
783783
}
784+
other_project_job = {
785+
"reference": {"project_id": "other-project", "job_id": "{{task.task_id}}_{{ds_nodash}}_" + job_id},
786+
"placement": {"cluster_name": "cluster-1"},
787+
"labels": {"airflow-version": AIRFLOW_VERSION},
788+
"spark_sql_job": {"query_list": {"queries": [query]}, "script_variables": variables},
789+
}
784790

785791
@mock.patch(DATAPROC_PATH.format("DataprocHook"))
786792
def test_deprecation_warning(self, mock_hook):
@@ -813,6 +819,32 @@ def test_execute(self, mock_hook, mock_uuid):
813819
job_id=self.job_id, location=GCP_LOCATION, project_id=GCP_PROJECT
814820
)
815821

822+
@mock.patch(DATAPROC_PATH.format("uuid.uuid4"))
823+
@mock.patch(DATAPROC_PATH.format("DataprocHook"))
824+
def test_execute_override_project_id(self, mock_hook, mock_uuid):
825+
mock_uuid.return_value = self.job_id
826+
mock_hook.return_value.project_id = GCP_PROJECT
827+
mock_hook.return_value.wait_for_job.return_value = None
828+
mock_hook.return_value.submit_job.return_value.reference.job_id = self.job_id
829+
830+
op = DataprocSubmitSparkSqlJobOperator(
831+
project_id="other-project",
832+
task_id=TASK_ID,
833+
region=GCP_LOCATION,
834+
gcp_conn_id=GCP_CONN_ID,
835+
query=self.query,
836+
variables=self.variables,
837+
impersonation_chain=IMPERSONATION_CHAIN,
838+
)
839+
op.execute(context={})
840+
mock_hook.assert_called_once_with(gcp_conn_id=GCP_CONN_ID, impersonation_chain=IMPERSONATION_CHAIN)
841+
mock_hook.return_value.submit_job.assert_called_once_with(
842+
project_id="other-project", job=self.other_project_job, location=GCP_LOCATION
843+
)
844+
mock_hook.return_value.wait_for_job.assert_called_once_with(
845+
job_id=self.job_id, location=GCP_LOCATION, project_id="other-project"
846+
)
847+
816848
@mock.patch(DATAPROC_PATH.format("uuid.uuid4"))
817849
@mock.patch(DATAPROC_PATH.format("DataprocHook"))
818850
def test_builder(self, mock_hook, mock_uuid):

0 commit comments

Comments
 (0)