Skip to content

Commit c5ecf0f

Browse files
jroachgolf84Subham-KRLX
authored andcommitted
Returning destination_cloud_storage_uris from BigQueryToGCSOperator (apache#59367)
1 parent 5b05a3f commit c5ecf0f

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

providers/google/src/airflow/providers/google/cloud/transfers/bigquery_to_gcs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class BigQueryToGCSOperator(BaseOperator):
8787
:param reattach_states: Set of BigQuery job's states in case of which we should reattach
8888
to the job. Should be other than final states.
8989
:param deferrable: Run operator in the deferrable mode
90+
:return: URIs for the objects created in Google Cloud Storage
9091
"""
9192

9293
template_fields: Sequence[str] = (
@@ -275,6 +276,8 @@ def execute(self, context: Context):
275276
else:
276277
job.result(timeout=self.result_timeout, retry=self.result_retry)
277278

279+
return self.destination_cloud_storage_uris
280+
278281
def execute_complete(self, context: Context, event: dict[str, Any]):
279282
"""
280283
Return immediately and relies on trigger to throw a success event. Callback for the trigger.
@@ -291,6 +294,8 @@ def execute_complete(self, context: Context, event: dict[str, Any]):
291294
# Save job_id as an attribute to be later used by listeners
292295
self.job_id = event.get("job_id")
293296

297+
return self.destination_cloud_storage_uris
298+
294299
def get_openlineage_facets_on_complete(self, task_instance):
295300
"""Implement on_complete as we will include final BQ job id."""
296301
from airflow.providers.common.compat.openlineage.facet import (

providers/google/tests/unit/google/cloud/transfers/test_bigquery_to_gcs.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ def test_execute(self, mock_hook):
112112
labels=labels,
113113
project_id=JOB_PROJECT_ID,
114114
)
115-
operator.execute(context=mock.MagicMock())
115+
result = operator.execute(context=mock.MagicMock())
116+
117+
assert result is not None
118+
assert isinstance(result, list)
119+
assert result == ["gs://some-bucket/some-file.txt"]
116120

117121
mock_hook.return_value.insert_job.assert_called_once_with(
118122
job_id="123456_hash",
@@ -207,6 +211,27 @@ def test_execute_complete_reassigns_job_id(self):
207211
)
208212
assert operator.job_id == job_id
209213

214+
def test_execute_complete_returns_destination_cloud_storage_uris(self):
215+
"""Assert that self.destination_cloud_storage_uris is returned by execute_complete."""
216+
217+
operator = BigQueryToGCSOperator(
218+
project_id=JOB_PROJECT_ID,
219+
task_id=TASK_ID,
220+
source_project_dataset_table=f"{PROJECT_ID}.{TEST_DATASET}.{TEST_TABLE_ID}",
221+
destination_cloud_storage_uris=[f"gs://{TEST_BUCKET}/{TEST_FOLDER}/"],
222+
deferrable=True,
223+
job_id=None,
224+
)
225+
226+
result = operator.execute_complete(
227+
context=MagicMock(),
228+
event={"status": "success", "message": "Job completed", "job_id": None},
229+
)
230+
231+
assert result is not None
232+
assert isinstance(result, list)
233+
assert result == [f"gs://{TEST_BUCKET}/{TEST_FOLDER}/"]
234+
210235
@pytest.mark.parametrize(
211236
("gcs_uri", "expected_dataset_name"),
212237
(

0 commit comments

Comments
 (0)