apache-airflow-providers-google 15.1.0rc1__py3-none-any.whl → 19.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. airflow/providers/google/3rd-party-licenses/NOTICE +2 -12
  2. airflow/providers/google/__init__.py +3 -3
  3. airflow/providers/google/ads/hooks/ads.py +39 -6
  4. airflow/providers/google/ads/operators/ads.py +2 -2
  5. airflow/providers/google/ads/transfers/ads_to_gcs.py +2 -2
  6. airflow/providers/google/assets/gcs.py +1 -11
  7. airflow/providers/google/cloud/bundles/__init__.py +16 -0
  8. airflow/providers/google/cloud/bundles/gcs.py +161 -0
  9. airflow/providers/google/cloud/hooks/alloy_db.py +1 -1
  10. airflow/providers/google/cloud/hooks/bigquery.py +176 -293
  11. airflow/providers/google/cloud/hooks/cloud_batch.py +1 -1
  12. airflow/providers/google/cloud/hooks/cloud_build.py +1 -1
  13. airflow/providers/google/cloud/hooks/cloud_composer.py +288 -15
  14. airflow/providers/google/cloud/hooks/cloud_logging.py +109 -0
  15. airflow/providers/google/cloud/hooks/cloud_memorystore.py +1 -1
  16. airflow/providers/google/cloud/hooks/cloud_run.py +18 -10
  17. airflow/providers/google/cloud/hooks/cloud_sql.py +102 -23
  18. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +29 -7
  19. airflow/providers/google/cloud/hooks/compute.py +1 -1
  20. airflow/providers/google/cloud/hooks/compute_ssh.py +6 -2
  21. airflow/providers/google/cloud/hooks/datacatalog.py +10 -1
  22. airflow/providers/google/cloud/hooks/dataflow.py +72 -95
  23. airflow/providers/google/cloud/hooks/dataform.py +1 -1
  24. airflow/providers/google/cloud/hooks/datafusion.py +21 -19
  25. airflow/providers/google/cloud/hooks/dataplex.py +2 -2
  26. airflow/providers/google/cloud/hooks/dataprep.py +1 -1
  27. airflow/providers/google/cloud/hooks/dataproc.py +73 -72
  28. airflow/providers/google/cloud/hooks/dataproc_metastore.py +1 -1
  29. airflow/providers/google/cloud/hooks/dlp.py +1 -1
  30. airflow/providers/google/cloud/hooks/functions.py +1 -1
  31. airflow/providers/google/cloud/hooks/gcs.py +112 -15
  32. airflow/providers/google/cloud/hooks/gdm.py +1 -1
  33. airflow/providers/google/cloud/hooks/gen_ai.py +196 -0
  34. airflow/providers/google/cloud/hooks/kubernetes_engine.py +3 -3
  35. airflow/providers/google/cloud/hooks/looker.py +6 -2
  36. airflow/providers/google/cloud/hooks/managed_kafka.py +1 -1
  37. airflow/providers/google/cloud/hooks/mlengine.py +4 -3
  38. airflow/providers/google/cloud/hooks/pubsub.py +3 -0
  39. airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
  40. airflow/providers/google/cloud/hooks/spanner.py +74 -9
  41. airflow/providers/google/cloud/hooks/stackdriver.py +11 -9
  42. airflow/providers/google/cloud/hooks/tasks.py +1 -1
  43. airflow/providers/google/cloud/hooks/translate.py +2 -2
  44. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +2 -210
  45. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +3 -3
  46. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +28 -2
  47. airflow/providers/google/cloud/hooks/vertex_ai/experiment_service.py +202 -0
  48. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +308 -8
  49. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +79 -75
  50. airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +1 -1
  51. airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +1 -1
  52. airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +1 -1
  53. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +223 -0
  54. airflow/providers/google/cloud/hooks/vision.py +3 -3
  55. airflow/providers/google/cloud/hooks/workflows.py +1 -1
  56. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  57. airflow/providers/google/cloud/links/base.py +77 -13
  58. airflow/providers/google/cloud/links/bigquery.py +0 -47
  59. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  60. airflow/providers/google/cloud/links/bigtable.py +0 -48
  61. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  62. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  63. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  64. airflow/providers/google/cloud/links/{life_sciences.py → cloud_run.py} +5 -27
  65. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  66. airflow/providers/google/cloud/links/cloud_storage_transfer.py +17 -44
  67. airflow/providers/google/cloud/links/cloud_tasks.py +7 -26
  68. airflow/providers/google/cloud/links/compute.py +0 -58
  69. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  70. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  71. airflow/providers/google/cloud/links/dataflow.py +0 -34
  72. airflow/providers/google/cloud/links/dataform.py +0 -64
  73. airflow/providers/google/cloud/links/datafusion.py +1 -96
  74. airflow/providers/google/cloud/links/dataplex.py +0 -154
  75. airflow/providers/google/cloud/links/dataprep.py +0 -24
  76. airflow/providers/google/cloud/links/dataproc.py +11 -95
  77. airflow/providers/google/cloud/links/datastore.py +0 -31
  78. airflow/providers/google/cloud/links/kubernetes_engine.py +9 -60
  79. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  80. airflow/providers/google/cloud/links/mlengine.py +0 -70
  81. airflow/providers/google/cloud/links/pubsub.py +0 -32
  82. airflow/providers/google/cloud/links/spanner.py +0 -33
  83. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  84. airflow/providers/google/cloud/links/translate.py +17 -187
  85. airflow/providers/google/cloud/links/vertex_ai.py +28 -195
  86. airflow/providers/google/cloud/links/workflows.py +0 -52
  87. airflow/providers/google/cloud/log/gcs_task_handler.py +58 -22
  88. airflow/providers/google/cloud/log/stackdriver_task_handler.py +9 -6
  89. airflow/providers/google/cloud/openlineage/CloudStorageTransferJobFacet.json +68 -0
  90. airflow/providers/google/cloud/openlineage/CloudStorageTransferRunFacet.json +60 -0
  91. airflow/providers/google/cloud/openlineage/DataFusionRunFacet.json +32 -0
  92. airflow/providers/google/cloud/openlineage/facets.py +102 -1
  93. airflow/providers/google/cloud/openlineage/mixins.py +10 -8
  94. airflow/providers/google/cloud/openlineage/utils.py +15 -1
  95. airflow/providers/google/cloud/operators/alloy_db.py +71 -56
  96. airflow/providers/google/cloud/operators/bigquery.py +73 -636
  97. airflow/providers/google/cloud/operators/bigquery_dts.py +4 -6
  98. airflow/providers/google/cloud/operators/bigtable.py +37 -8
  99. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  100. airflow/providers/google/cloud/operators/cloud_batch.py +3 -3
  101. airflow/providers/google/cloud/operators/cloud_build.py +76 -33
  102. airflow/providers/google/cloud/operators/cloud_composer.py +129 -41
  103. airflow/providers/google/cloud/operators/cloud_logging_sink.py +341 -0
  104. airflow/providers/google/cloud/operators/cloud_memorystore.py +69 -43
  105. airflow/providers/google/cloud/operators/cloud_run.py +24 -6
  106. airflow/providers/google/cloud/operators/cloud_sql.py +8 -17
  107. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +93 -12
  108. airflow/providers/google/cloud/operators/compute.py +9 -41
  109. airflow/providers/google/cloud/operators/datacatalog.py +157 -21
  110. airflow/providers/google/cloud/operators/dataflow.py +40 -16
  111. airflow/providers/google/cloud/operators/dataform.py +15 -5
  112. airflow/providers/google/cloud/operators/datafusion.py +42 -21
  113. airflow/providers/google/cloud/operators/dataplex.py +194 -110
  114. airflow/providers/google/cloud/operators/dataprep.py +1 -5
  115. airflow/providers/google/cloud/operators/dataproc.py +80 -36
  116. airflow/providers/google/cloud/operators/dataproc_metastore.py +97 -89
  117. airflow/providers/google/cloud/operators/datastore.py +23 -7
  118. airflow/providers/google/cloud/operators/dlp.py +6 -29
  119. airflow/providers/google/cloud/operators/functions.py +17 -8
  120. airflow/providers/google/cloud/operators/gcs.py +12 -9
  121. airflow/providers/google/cloud/operators/gen_ai.py +389 -0
  122. airflow/providers/google/cloud/operators/kubernetes_engine.py +62 -100
  123. airflow/providers/google/cloud/operators/looker.py +2 -2
  124. airflow/providers/google/cloud/operators/managed_kafka.py +108 -53
  125. airflow/providers/google/cloud/operators/natural_language.py +1 -1
  126. airflow/providers/google/cloud/operators/pubsub.py +68 -15
  127. airflow/providers/google/cloud/operators/spanner.py +26 -13
  128. airflow/providers/google/cloud/operators/speech_to_text.py +2 -3
  129. airflow/providers/google/cloud/operators/stackdriver.py +1 -9
  130. airflow/providers/google/cloud/operators/tasks.py +1 -12
  131. airflow/providers/google/cloud/operators/text_to_speech.py +2 -3
  132. airflow/providers/google/cloud/operators/translate.py +41 -17
  133. airflow/providers/google/cloud/operators/translate_speech.py +2 -3
  134. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +39 -19
  135. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +30 -10
  136. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +55 -27
  137. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +70 -8
  138. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +43 -9
  139. airflow/providers/google/cloud/operators/vertex_ai/experiment_service.py +435 -0
  140. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +532 -1
  141. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +135 -115
  142. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +12 -10
  143. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +57 -11
  144. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +31 -8
  145. airflow/providers/google/cloud/operators/vertex_ai/ray.py +393 -0
  146. airflow/providers/google/cloud/operators/video_intelligence.py +1 -1
  147. airflow/providers/google/cloud/operators/vision.py +2 -2
  148. airflow/providers/google/cloud/operators/workflows.py +18 -15
  149. airflow/providers/google/cloud/secrets/secret_manager.py +3 -2
  150. airflow/providers/google/cloud/sensors/bigquery.py +3 -3
  151. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -3
  152. airflow/providers/google/cloud/sensors/bigtable.py +11 -4
  153. airflow/providers/google/cloud/sensors/cloud_composer.py +533 -30
  154. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -3
  155. airflow/providers/google/cloud/sensors/dataflow.py +26 -10
  156. airflow/providers/google/cloud/sensors/dataform.py +2 -3
  157. airflow/providers/google/cloud/sensors/datafusion.py +4 -5
  158. airflow/providers/google/cloud/sensors/dataplex.py +2 -3
  159. airflow/providers/google/cloud/sensors/dataprep.py +2 -2
  160. airflow/providers/google/cloud/sensors/dataproc.py +2 -3
  161. airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -3
  162. airflow/providers/google/cloud/sensors/gcs.py +4 -5
  163. airflow/providers/google/cloud/sensors/looker.py +2 -3
  164. airflow/providers/google/cloud/sensors/pubsub.py +4 -5
  165. airflow/providers/google/cloud/sensors/tasks.py +2 -2
  166. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +2 -3
  167. airflow/providers/google/cloud/sensors/workflows.py +2 -3
  168. airflow/providers/google/cloud/transfers/adls_to_gcs.py +1 -1
  169. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +2 -2
  170. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +4 -3
  171. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +11 -8
  172. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +10 -5
  173. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +7 -3
  174. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +12 -1
  175. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +24 -10
  176. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +104 -5
  177. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  178. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +3 -3
  179. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +4 -4
  180. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +21 -13
  181. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +4 -3
  182. airflow/providers/google/cloud/transfers/gcs_to_local.py +6 -4
  183. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +11 -5
  184. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +6 -2
  185. airflow/providers/google/cloud/transfers/gdrive_to_local.py +2 -2
  186. airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
  187. airflow/providers/google/cloud/transfers/local_to_gcs.py +2 -2
  188. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
  189. airflow/providers/google/cloud/transfers/oracle_to_gcs.py +36 -11
  190. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +42 -9
  191. airflow/providers/google/cloud/transfers/s3_to_gcs.py +13 -7
  192. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +2 -2
  193. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +14 -5
  194. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +3 -3
  195. airflow/providers/google/cloud/transfers/sql_to_gcs.py +10 -10
  196. airflow/providers/google/cloud/triggers/bigquery.py +76 -35
  197. airflow/providers/google/cloud/triggers/cloud_build.py +1 -1
  198. airflow/providers/google/cloud/triggers/cloud_composer.py +303 -47
  199. airflow/providers/google/cloud/triggers/cloud_run.py +3 -3
  200. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +92 -2
  201. airflow/providers/google/cloud/triggers/dataflow.py +122 -0
  202. airflow/providers/google/cloud/triggers/datafusion.py +1 -1
  203. airflow/providers/google/cloud/triggers/dataplex.py +14 -2
  204. airflow/providers/google/cloud/triggers/dataproc.py +123 -53
  205. airflow/providers/google/cloud/triggers/kubernetes_engine.py +47 -28
  206. airflow/providers/google/cloud/triggers/mlengine.py +1 -1
  207. airflow/providers/google/cloud/triggers/pubsub.py +15 -19
  208. airflow/providers/google/cloud/triggers/vertex_ai.py +1 -1
  209. airflow/providers/google/cloud/utils/bigquery_get_data.py +1 -1
  210. airflow/providers/google/cloud/utils/credentials_provider.py +2 -2
  211. airflow/providers/google/cloud/utils/field_sanitizer.py +1 -1
  212. airflow/providers/google/cloud/utils/field_validator.py +2 -3
  213. airflow/providers/google/common/auth_backend/google_openid.py +4 -4
  214. airflow/providers/google/common/deprecated.py +2 -1
  215. airflow/providers/google/common/hooks/base_google.py +27 -9
  216. airflow/providers/google/common/hooks/operation_helpers.py +1 -1
  217. airflow/providers/google/common/links/storage.py +0 -22
  218. airflow/providers/google/common/utils/get_secret.py +31 -0
  219. airflow/providers/google/common/utils/id_token_credentials.py +3 -4
  220. airflow/providers/google/firebase/hooks/firestore.py +1 -1
  221. airflow/providers/google/firebase/operators/firestore.py +3 -3
  222. airflow/providers/google/get_provider_info.py +56 -52
  223. airflow/providers/google/go_module_utils.py +35 -3
  224. airflow/providers/google/leveldb/hooks/leveldb.py +27 -2
  225. airflow/providers/google/leveldb/operators/leveldb.py +2 -2
  226. airflow/providers/google/marketing_platform/hooks/campaign_manager.py +1 -1
  227. airflow/providers/google/marketing_platform/hooks/display_video.py +3 -109
  228. airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -1
  229. airflow/providers/google/marketing_platform/links/analytics_admin.py +5 -14
  230. airflow/providers/google/marketing_platform/operators/analytics_admin.py +2 -3
  231. airflow/providers/google/marketing_platform/operators/campaign_manager.py +6 -6
  232. airflow/providers/google/marketing_platform/operators/display_video.py +28 -489
  233. airflow/providers/google/marketing_platform/operators/search_ads.py +2 -2
  234. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +2 -2
  235. airflow/providers/google/marketing_platform/sensors/display_video.py +3 -64
  236. airflow/providers/google/suite/hooks/calendar.py +2 -2
  237. airflow/providers/google/suite/hooks/sheets.py +16 -2
  238. airflow/providers/google/suite/operators/sheets.py +8 -3
  239. airflow/providers/google/suite/sensors/drive.py +2 -2
  240. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +3 -3
  241. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  242. airflow/providers/google/suite/transfers/local_to_drive.py +3 -3
  243. airflow/providers/google/suite/transfers/sql_to_sheets.py +5 -4
  244. airflow/providers/google/version_compat.py +15 -1
  245. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/METADATA +90 -46
  246. apache_airflow_providers_google-19.3.0.dist-info/RECORD +331 -0
  247. apache_airflow_providers_google-19.3.0.dist-info/licenses/NOTICE +5 -0
  248. airflow/providers/google/cloud/hooks/automl.py +0 -673
  249. airflow/providers/google/cloud/hooks/life_sciences.py +0 -159
  250. airflow/providers/google/cloud/links/automl.py +0 -193
  251. airflow/providers/google/cloud/operators/automl.py +0 -1362
  252. airflow/providers/google/cloud/operators/life_sciences.py +0 -119
  253. airflow/providers/google/cloud/operators/mlengine.py +0 -112
  254. apache_airflow_providers_google-15.1.0rc1.dist-info/RECORD +0 -321
  255. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/WHEEL +0 -0
  256. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/entry_points.txt +0 -0
  257. {airflow/providers/google → apache_airflow_providers_google-19.3.0.dist-info/licenses}/LICENSE +0 -0
@@ -27,7 +27,7 @@ Operators for Google Cloud Memorystore service.
27
27
  from __future__ import annotations
28
28
 
29
29
  from collections.abc import Sequence
30
- from typing import TYPE_CHECKING
30
+ from typing import TYPE_CHECKING, Any
31
31
 
32
32
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
33
33
  from google.cloud.memcache_v1beta2.types import cloud_memcache
@@ -50,7 +50,7 @@ if TYPE_CHECKING:
50
50
  from google.api_core.retry import Retry
51
51
  from google.protobuf.field_mask_pb2 import FieldMask
52
52
 
53
- from airflow.utils.context import Context
53
+ from airflow.providers.common.compat.sdk import Context
54
54
 
55
55
 
56
56
  class CloudMemorystoreCreateInstanceOperator(GoogleCloudBaseOperator):
@@ -133,6 +133,13 @@ class CloudMemorystoreCreateInstanceOperator(GoogleCloudBaseOperator):
133
133
  self.gcp_conn_id = gcp_conn_id
134
134
  self.impersonation_chain = impersonation_chain
135
135
 
136
+ @property
137
+ def extra_links_params(self) -> dict[str, Any]:
138
+ return {
139
+ "instance_id": self.instance_id,
140
+ "location_id": self.location,
141
+ }
142
+
136
143
  def execute(self, context: Context):
137
144
  hook = CloudMemorystoreHook(
138
145
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -148,9 +155,6 @@ class CloudMemorystoreCreateInstanceOperator(GoogleCloudBaseOperator):
148
155
  )
149
156
  RedisInstanceDetailsLink.persist(
150
157
  context=context,
151
- task_instance=self,
152
- instance_id=self.instance_id,
153
- location_id=self.location,
154
158
  project_id=self.project_id or hook.project_id,
155
159
  )
156
160
  return Instance.to_dict(result)
@@ -304,6 +308,13 @@ class CloudMemorystoreExportInstanceOperator(GoogleCloudBaseOperator):
304
308
  self.gcp_conn_id = gcp_conn_id
305
309
  self.impersonation_chain = impersonation_chain
306
310
 
311
+ @property
312
+ def extra_links_params(self) -> dict[str, Any]:
313
+ return {
314
+ "instance_id": self.instance,
315
+ "location_id": self.location,
316
+ }
317
+
307
318
  def execute(self, context: Context) -> None:
308
319
  hook = CloudMemorystoreHook(
309
320
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -320,9 +331,6 @@ class CloudMemorystoreExportInstanceOperator(GoogleCloudBaseOperator):
320
331
  )
321
332
  RedisInstanceDetailsLink.persist(
322
333
  context=context,
323
- task_instance=self,
324
- instance_id=self.instance,
325
- location_id=self.location,
326
334
  project_id=self.project_id or hook.project_id,
327
335
  )
328
336
 
@@ -397,6 +405,13 @@ class CloudMemorystoreFailoverInstanceOperator(GoogleCloudBaseOperator):
397
405
  self.gcp_conn_id = gcp_conn_id
398
406
  self.impersonation_chain = impersonation_chain
399
407
 
408
+ @property
409
+ def extra_links_params(self) -> dict[str, Any]:
410
+ return {
411
+ "instance_id": self.instance,
412
+ "location_id": self.location,
413
+ }
414
+
400
415
  def execute(self, context: Context) -> None:
401
416
  hook = CloudMemorystoreHook(
402
417
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -412,9 +427,6 @@ class CloudMemorystoreFailoverInstanceOperator(GoogleCloudBaseOperator):
412
427
  )
413
428
  RedisInstanceDetailsLink.persist(
414
429
  context=context,
415
- task_instance=self,
416
- instance_id=self.instance,
417
- location_id=self.location,
418
430
  project_id=self.project_id or hook.project_id,
419
431
  )
420
432
 
@@ -482,6 +494,13 @@ class CloudMemorystoreGetInstanceOperator(GoogleCloudBaseOperator):
482
494
  self.gcp_conn_id = gcp_conn_id
483
495
  self.impersonation_chain = impersonation_chain
484
496
 
497
+ @property
498
+ def extra_links_params(self) -> dict[str, Any]:
499
+ return {
500
+ "instance_id": self.instance,
501
+ "location_id": self.location,
502
+ }
503
+
485
504
  def execute(self, context: Context):
486
505
  hook = CloudMemorystoreHook(
487
506
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -496,9 +515,6 @@ class CloudMemorystoreGetInstanceOperator(GoogleCloudBaseOperator):
496
515
  )
497
516
  RedisInstanceDetailsLink.persist(
498
517
  context=context,
499
- task_instance=self,
500
- instance_id=self.instance,
501
- location_id=self.location,
502
518
  project_id=self.project_id or hook.project_id,
503
519
  )
504
520
  return Instance.to_dict(result)
@@ -577,6 +593,13 @@ class CloudMemorystoreImportOperator(GoogleCloudBaseOperator):
577
593
  self.gcp_conn_id = gcp_conn_id
578
594
  self.impersonation_chain = impersonation_chain
579
595
 
596
+ @property
597
+ def extra_links_params(self) -> dict[str, Any]:
598
+ return {
599
+ "instance_id": self.instance,
600
+ "location_id": self.location,
601
+ }
602
+
580
603
  def execute(self, context: Context) -> None:
581
604
  hook = CloudMemorystoreHook(
582
605
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -592,9 +615,6 @@ class CloudMemorystoreImportOperator(GoogleCloudBaseOperator):
592
615
  )
593
616
  RedisInstanceDetailsLink.persist(
594
617
  context=context,
595
- task_instance=self,
596
- instance_id=self.instance,
597
- location_id=self.location,
598
618
  project_id=self.project_id or hook.project_id,
599
619
  )
600
620
 
@@ -680,7 +700,6 @@ class CloudMemorystoreListInstancesOperator(GoogleCloudBaseOperator):
680
700
  )
681
701
  RedisInstanceListLink.persist(
682
702
  context=context,
683
- task_instance=self,
684
703
  project_id=self.project_id or hook.project_id,
685
704
  )
686
705
  instances = [Instance.to_dict(a) for a in result]
@@ -789,7 +808,6 @@ class CloudMemorystoreUpdateInstanceOperator(GoogleCloudBaseOperator):
789
808
  location_id, instance_id = res.name.split("/")[-3::2]
790
809
  RedisInstanceDetailsLink.persist(
791
810
  context=context,
792
- task_instance=self,
793
811
  instance_id=self.instance_id or instance_id,
794
812
  location_id=self.location or location_id,
795
813
  project_id=self.project_id or hook.project_id,
@@ -882,7 +900,6 @@ class CloudMemorystoreScaleInstanceOperator(GoogleCloudBaseOperator):
882
900
  location_id, instance_id = res.name.split("/")[-3::2]
883
901
  RedisInstanceDetailsLink.persist(
884
902
  context=context,
885
- task_instance=self,
886
903
  instance_id=self.instance_id or instance_id,
887
904
  location_id=self.location or location_id,
888
905
  project_id=self.project_id or hook.project_id,
@@ -1002,7 +1019,6 @@ class CloudMemorystoreCreateInstanceAndImportOperator(GoogleCloudBaseOperator):
1002
1019
  )
1003
1020
  RedisInstanceDetailsLink.persist(
1004
1021
  context=context,
1005
- task_instance=self,
1006
1022
  instance_id=self.instance_id,
1007
1023
  location_id=self.location,
1008
1024
  project_id=self.project_id or hook.project_id,
@@ -1171,6 +1187,14 @@ class CloudMemorystoreMemcachedApplyParametersOperator(GoogleCloudBaseOperator):
1171
1187
  self.gcp_conn_id = gcp_conn_id
1172
1188
  self.impersonation_chain = impersonation_chain
1173
1189
 
1190
+ @property
1191
+ def extra_links_params(self) -> dict[str, Any]:
1192
+ return {
1193
+ "instance_id": self.instance_id,
1194
+ "location_id": self.location,
1195
+ "project_id": self.project_id,
1196
+ }
1197
+
1174
1198
  def execute(self, context: Context):
1175
1199
  hook = CloudMemorystoreMemcachedHook(
1176
1200
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -1185,13 +1209,7 @@ class CloudMemorystoreMemcachedApplyParametersOperator(GoogleCloudBaseOperator):
1185
1209
  timeout=self.timeout,
1186
1210
  metadata=self.metadata,
1187
1211
  )
1188
- MemcachedInstanceDetailsLink.persist(
1189
- context=context,
1190
- task_instance=self,
1191
- instance_id=self.instance_id,
1192
- location_id=self.location,
1193
- project_id=self.project_id,
1194
- )
1212
+ MemcachedInstanceDetailsLink.persist(context=context)
1195
1213
 
1196
1214
 
1197
1215
  class CloudMemorystoreMemcachedCreateInstanceOperator(GoogleCloudBaseOperator):
@@ -1263,6 +1281,13 @@ class CloudMemorystoreMemcachedCreateInstanceOperator(GoogleCloudBaseOperator):
1263
1281
  self.metadata = metadata
1264
1282
  self.gcp_conn_id = gcp_conn_id
1265
1283
 
1284
+ @property
1285
+ def extra_links_params(self) -> dict[str, Any]:
1286
+ return {
1287
+ "instance_id": self.instance_id,
1288
+ "location_id": self.location,
1289
+ }
1290
+
1266
1291
  def execute(self, context: Context):
1267
1292
  hook = CloudMemorystoreMemcachedHook(gcp_conn_id=self.gcp_conn_id)
1268
1293
  result = hook.create_instance(
@@ -1276,9 +1301,6 @@ class CloudMemorystoreMemcachedCreateInstanceOperator(GoogleCloudBaseOperator):
1276
1301
  )
1277
1302
  MemcachedInstanceDetailsLink.persist(
1278
1303
  context=context,
1279
- task_instance=self,
1280
- instance_id=self.instance_id,
1281
- location_id=self.location,
1282
1304
  project_id=self.project_id or hook.project_id,
1283
1305
  )
1284
1306
  return cloud_memcache.Instance.to_dict(result)
@@ -1410,6 +1432,13 @@ class CloudMemorystoreMemcachedGetInstanceOperator(GoogleCloudBaseOperator):
1410
1432
  self.gcp_conn_id = gcp_conn_id
1411
1433
  self.impersonation_chain = impersonation_chain
1412
1434
 
1435
+ @property
1436
+ def extra_links_params(self) -> dict[str, Any]:
1437
+ return {
1438
+ "instance_id": self.instance,
1439
+ "location_id": self.location,
1440
+ }
1441
+
1413
1442
  def execute(self, context: Context):
1414
1443
  hook = CloudMemorystoreMemcachedHook(
1415
1444
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -1424,9 +1453,6 @@ class CloudMemorystoreMemcachedGetInstanceOperator(GoogleCloudBaseOperator):
1424
1453
  )
1425
1454
  MemcachedInstanceDetailsLink.persist(
1426
1455
  context=context,
1427
- task_instance=self,
1428
- instance_id=self.instance,
1429
- location_id=self.location,
1430
1456
  project_id=self.project_id or hook.project_id,
1431
1457
  )
1432
1458
  return cloud_memcache.Instance.to_dict(result)
@@ -1506,7 +1532,6 @@ class CloudMemorystoreMemcachedListInstancesOperator(GoogleCloudBaseOperator):
1506
1532
  )
1507
1533
  MemcachedInstanceListLink.persist(
1508
1534
  context=context,
1509
- task_instance=self,
1510
1535
  project_id=self.project_id or hook.project_id,
1511
1536
  )
1512
1537
  instances = [cloud_memcache.Instance.to_dict(a) for a in result]
@@ -1612,7 +1637,6 @@ class CloudMemorystoreMemcachedUpdateInstanceOperator(GoogleCloudBaseOperator):
1612
1637
  location_id, instance_id = res.name.split("/")[-3::2]
1613
1638
  MemcachedInstanceDetailsLink.persist(
1614
1639
  context=context,
1615
- task_instance=self,
1616
1640
  instance_id=self.instance_id or instance_id,
1617
1641
  location_id=self.location or location_id,
1618
1642
  project_id=self.project_id or hook.project_id,
@@ -1688,6 +1712,14 @@ class CloudMemorystoreMemcachedUpdateParametersOperator(GoogleCloudBaseOperator)
1688
1712
  self.gcp_conn_id = gcp_conn_id
1689
1713
  self.impersonation_chain = impersonation_chain
1690
1714
 
1715
+ @property
1716
+ def extra_links_params(self) -> dict[str, Any]:
1717
+ return {
1718
+ "instance_id": self.instance_id,
1719
+ "location_id": self.location,
1720
+ "project_id": self.project_id,
1721
+ }
1722
+
1691
1723
  def execute(self, context: Context):
1692
1724
  hook = CloudMemorystoreMemcachedHook(
1693
1725
  gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain
@@ -1702,10 +1734,4 @@ class CloudMemorystoreMemcachedUpdateParametersOperator(GoogleCloudBaseOperator)
1702
1734
  timeout=self.timeout,
1703
1735
  metadata=self.metadata,
1704
1736
  )
1705
- MemcachedInstanceDetailsLink.persist(
1706
- context=context,
1707
- task_instance=self,
1708
- instance_id=self.instance_id,
1709
- location_id=self.location,
1710
- project_id=self.project_id,
1711
- )
1737
+ MemcachedInstanceDetailsLink.persist(context=context)
@@ -25,8 +25,9 @@ from google.api_core.exceptions import AlreadyExists
25
25
  from google.cloud.run_v2 import Job, Service
26
26
 
27
27
  from airflow.configuration import conf
28
- from airflow.exceptions import AirflowException
28
+ from airflow.providers.common.compat.sdk import AirflowException
29
29
  from airflow.providers.google.cloud.hooks.cloud_run import CloudRunHook, CloudRunServiceHook
30
+ from airflow.providers.google.cloud.links.cloud_run import CloudRunJobLoggingLink
30
31
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
31
32
  from airflow.providers.google.cloud.triggers.cloud_run import CloudRunJobFinishedTrigger, RunJobStatus
32
33
 
@@ -34,7 +35,7 @@ if TYPE_CHECKING:
34
35
  from google.api_core import operation
35
36
  from google.cloud.run_v2.types import Execution
36
37
 
37
- from airflow.utils.context import Context
38
+ from airflow.providers.common.compat.sdk import Context
38
39
 
39
40
 
40
41
  class CloudRunCreateJobOperator(GoogleCloudBaseOperator):
@@ -140,7 +141,7 @@ class CloudRunUpdateJobOperator(GoogleCloudBaseOperator):
140
141
 
141
142
  class CloudRunDeleteJobOperator(GoogleCloudBaseOperator):
142
143
  """
143
- Deletes a job and wait for the the operation to be completed. Pushes the deleted job to xcom.
144
+ Deletes a job and wait for the operation to be completed. Pushes the deleted job to xcom.
144
145
 
145
146
  :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
146
147
  :param region: Required. The ID of the Google Cloud region that the service belongs to.
@@ -248,7 +249,7 @@ class CloudRunExecuteJobOperator(GoogleCloudBaseOperator):
248
249
 
249
250
  :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
250
251
  :param region: Required. The ID of the Google Cloud region that the service belongs to.
251
- :param job_name: Required. The name of the job to update.
252
+ :param job_name: Required. The name of the job to execute.
252
253
  :param overrides: Optional map of override values.
253
254
  :param gcp_conn_id: The connection ID used to connect to Google Cloud.
254
255
  :param polling_period_seconds: Optional. Control the rate of the poll for the result of deferrable run.
@@ -265,7 +266,17 @@ class CloudRunExecuteJobOperator(GoogleCloudBaseOperator):
265
266
  :param deferrable: Run the operator in deferrable mode.
266
267
  """
267
268
 
268
- template_fields = ("project_id", "region", "gcp_conn_id", "impersonation_chain", "job_name", "overrides")
269
+ operator_extra_links = (CloudRunJobLoggingLink(),)
270
+ template_fields = (
271
+ "project_id",
272
+ "region",
273
+ "gcp_conn_id",
274
+ "impersonation_chain",
275
+ "job_name",
276
+ "overrides",
277
+ "polling_period_seconds",
278
+ "timeout_seconds",
279
+ )
269
280
 
270
281
  def __init__(
271
282
  self,
@@ -303,6 +314,12 @@ class CloudRunExecuteJobOperator(GoogleCloudBaseOperator):
303
314
  if self.operation is None:
304
315
  raise AirflowException("Operation is None")
305
316
 
317
+ if self.operation.metadata.log_uri:
318
+ CloudRunJobLoggingLink.persist(
319
+ context=context,
320
+ log_uri=self.operation.metadata.log_uri,
321
+ )
322
+
306
323
  if not self.deferrable:
307
324
  result: Execution = self._wait_for_operation(self.operation)
308
325
  self._fail_if_execution_failed(result)
@@ -424,9 +441,10 @@ class CloudRunCreateServiceOperator(GoogleCloudBaseOperator):
424
441
  self.service_name,
425
442
  self.region,
426
443
  )
427
- return hook.get_service(
444
+ service = hook.get_service(
428
445
  service_name=self.service_name, region=self.region, project_id=self.project_id
429
446
  )
447
+ return Service.to_dict(service)
430
448
  except google.cloud.exceptions.GoogleCloudError as e:
431
449
  self.log.error("An error occurred. Exiting.")
432
450
  raise e
@@ -27,8 +27,7 @@ from typing import TYPE_CHECKING, Any
27
27
  from googleapiclient.errors import HttpError
28
28
 
29
29
  from airflow.configuration import conf
30
- from airflow.exceptions import AirflowException
31
- from airflow.hooks.base import BaseHook
30
+ from airflow.providers.common.compat.sdk import AirflowException, BaseHook
32
31
  from airflow.providers.google.cloud.hooks.cloud_sql import CloudSQLDatabaseHook, CloudSQLHook
33
32
  from airflow.providers.google.cloud.links.cloud_sql import CloudSQLInstanceDatabaseLink, CloudSQLInstanceLink
34
33
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
@@ -39,8 +38,8 @@ from airflow.providers.google.common.links.storage import FileDetailsLink
39
38
 
40
39
  if TYPE_CHECKING:
41
40
  from airflow.models import Connection
41
+ from airflow.providers.common.compat.sdk import Context
42
42
  from airflow.providers.openlineage.extractors import OperatorLineage
43
- from airflow.utils.context import Context
44
43
 
45
44
 
46
45
  SETTINGS = "settings"
@@ -285,6 +284,12 @@ class CloudSQLBaseOperator(GoogleCloudBaseOperator):
285
284
  return False
286
285
  raise e
287
286
 
287
+ @property
288
+ def extra_links_params(self) -> dict[str, Any]:
289
+ return {
290
+ "instance": self.instance,
291
+ }
292
+
288
293
  def execute(self, context: Context):
289
294
  pass
290
295
 
@@ -384,8 +389,6 @@ class CloudSQLCreateInstanceOperator(CloudSQLBaseOperator):
384
389
 
385
390
  CloudSQLInstanceLink.persist(
386
391
  context=context,
387
- task_instance=self,
388
- cloud_sql_instance=self.instance,
389
392
  project_id=self.project_id or hook.project_id,
390
393
  )
391
394
 
@@ -479,8 +482,6 @@ class CloudSQLInstancePatchOperator(CloudSQLBaseOperator):
479
482
  )
480
483
  CloudSQLInstanceLink.persist(
481
484
  context=context,
482
- task_instance=self,
483
- cloud_sql_instance=self.instance,
484
485
  project_id=self.project_id or hook.project_id,
485
486
  )
486
487
 
@@ -714,8 +715,6 @@ class CloudSQLCreateInstanceDatabaseOperator(CloudSQLBaseOperator):
714
715
  )
715
716
  CloudSQLInstanceDatabaseLink.persist(
716
717
  context=context,
717
- task_instance=self,
718
- cloud_sql_instance=self.instance,
719
718
  project_id=self.project_id or hook.project_id,
720
719
  )
721
720
  if self._check_if_db_exists(database, hook):
@@ -822,8 +821,6 @@ class CloudSQLPatchInstanceDatabaseOperator(CloudSQLBaseOperator):
822
821
  )
823
822
  CloudSQLInstanceDatabaseLink.persist(
824
823
  context=context,
825
- task_instance=self,
826
- cloud_sql_instance=self.instance,
827
824
  project_id=self.project_id or hook.project_id,
828
825
  )
829
826
  return hook.patch_database(
@@ -1004,13 +1001,10 @@ class CloudSQLExportInstanceOperator(CloudSQLBaseOperator):
1004
1001
  )
1005
1002
  CloudSQLInstanceLink.persist(
1006
1003
  context=context,
1007
- task_instance=self,
1008
- cloud_sql_instance=self.instance,
1009
1004
  project_id=self.project_id or hook.project_id,
1010
1005
  )
1011
1006
  FileDetailsLink.persist(
1012
1007
  context=context,
1013
- task_instance=self,
1014
1008
  uri=self.body["exportContext"]["uri"][5:],
1015
1009
  project_id=self.project_id or hook.project_id,
1016
1010
  )
@@ -1147,13 +1141,10 @@ class CloudSQLImportInstanceOperator(CloudSQLBaseOperator):
1147
1141
  )
1148
1142
  CloudSQLInstanceLink.persist(
1149
1143
  context=context,
1150
- task_instance=self,
1151
- cloud_sql_instance=self.instance,
1152
1144
  project_id=self.project_id or hook.project_id,
1153
1145
  )
1154
1146
  FileDetailsLink.persist(
1155
1147
  context=context,
1156
- task_instance=self,
1157
1148
  uri=self.body["importContext"]["uri"][5:],
1158
1149
  project_id=self.project_id or hook.project_id,
1159
1150
  )
@@ -25,8 +25,8 @@ from datetime import date, time, timedelta
25
25
  from typing import TYPE_CHECKING, Any
26
26
 
27
27
  from airflow.configuration import conf
28
- from airflow.exceptions import AirflowException
29
28
  from airflow.providers.amazon.aws.hooks.base_aws import AwsBaseHook
29
+ from airflow.providers.common.compat.sdk import AirflowException
30
30
  from airflow.providers.google.cloud.hooks.cloud_storage_transfer_service import (
31
31
  ACCESS_KEY_ID,
32
32
  AWS_ACCESS_KEY,
@@ -65,13 +65,15 @@ from airflow.providers.google.cloud.links.cloud_storage_transfer import (
65
65
  )
66
66
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
67
67
  from airflow.providers.google.cloud.triggers.cloud_storage_transfer_service import (
68
+ CloudDataTransferServiceRunJobTrigger,
68
69
  CloudStorageTransferServiceCheckJobStatusTrigger,
69
70
  )
70
71
  from airflow.providers.google.cloud.utils.helpers import normalize_directory_path
71
72
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
72
73
 
73
74
  if TYPE_CHECKING:
74
- from airflow.utils.context import Context
75
+ from airflow.providers.common.compat.sdk import Context
76
+ from airflow.providers.openlineage.extractors import OperatorLineage
75
77
 
76
78
 
77
79
  class TransferJobPreprocessor:
@@ -96,8 +98,8 @@ class TransferJobPreprocessor:
96
98
 
97
99
  aws_hook = AwsBaseHook(self.aws_conn_id, resource_type="s3")
98
100
  aws_credentials = aws_hook.get_credentials()
99
- aws_access_key_id = aws_credentials.access_key # type: ignore[attr-defined]
100
- aws_secret_access_key = aws_credentials.secret_key # type: ignore[attr-defined]
101
+ aws_access_key_id = aws_credentials.access_key
102
+ aws_secret_access_key = aws_credentials.secret_key
101
103
  self.body[TRANSFER_SPEC][AWS_S3_DATA_SOURCE][AWS_ACCESS_KEY] = {
102
104
  ACCESS_KEY_ID: aws_access_key_id,
103
105
  SECRET_ACCESS_KEY: aws_secret_access_key,
@@ -468,6 +470,8 @@ class CloudDataTransferServiceRunJobOperator(GoogleCloudBaseOperator):
468
470
  If set as a sequence, the identities from the list must grant
469
471
  Service Account Token Creator IAM role to the directly preceding identity, with first
470
472
  account from the list granting this role to the originating account (templated).
473
+ :param timeout: Time to wait for the operation to end in seconds. Defaults to 60 seconds if not specified.
474
+ :param deferrable: Run operator in the deferrable mode.
471
475
  """
472
476
 
473
477
  # [START gcp_transfer_job_run_template_fields]
@@ -489,6 +493,8 @@ class CloudDataTransferServiceRunJobOperator(GoogleCloudBaseOperator):
489
493
  api_version: str = "v1",
490
494
  project_id: str = PROVIDE_PROJECT_ID,
491
495
  google_impersonation_chain: str | Sequence[str] | None = None,
496
+ timeout: float | None = None,
497
+ deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
492
498
  **kwargs,
493
499
  ) -> None:
494
500
  super().__init__(**kwargs)
@@ -497,6 +503,8 @@ class CloudDataTransferServiceRunJobOperator(GoogleCloudBaseOperator):
497
503
  self.gcp_conn_id = gcp_conn_id
498
504
  self.api_version = api_version
499
505
  self.google_impersonation_chain = google_impersonation_chain
506
+ self.timeout = timeout
507
+ self.deferrable = deferrable
500
508
 
501
509
  def _validate_inputs(self) -> None:
502
510
  if not self.job_name:
@@ -518,8 +526,32 @@ class CloudDataTransferServiceRunJobOperator(GoogleCloudBaseOperator):
518
526
  job_name=self.job_name,
519
527
  )
520
528
 
529
+ if self.deferrable:
530
+ self.defer(
531
+ timeout=timedelta(seconds=self.timeout or 60),
532
+ trigger=CloudDataTransferServiceRunJobTrigger(
533
+ job_name=self.job_name,
534
+ project_id=project_id,
535
+ gcp_conn_id=self.gcp_conn_id,
536
+ impersonation_chain=self.google_impersonation_chain,
537
+ ),
538
+ method_name="execute_complete",
539
+ )
540
+
521
541
  return hook.run_transfer_job(job_name=self.job_name, project_id=project_id)
522
542
 
543
+ def execute_complete(self, context: Context, event: dict[str, Any]) -> Any:
544
+ """
545
+ Act as a callback for when the trigger fires.
546
+
547
+ This returns immediately. It relies on trigger to throw an exception,
548
+ otherwise it assumes execution was successful.
549
+ """
550
+ if event["status"] == "error":
551
+ raise AirflowException(event["message"])
552
+
553
+ return event["job_result"]
554
+
523
555
 
524
556
  class CloudDataTransferServiceGetOperationOperator(GoogleCloudBaseOperator):
525
557
  """
@@ -586,7 +618,6 @@ class CloudDataTransferServiceGetOperationOperator(GoogleCloudBaseOperator):
586
618
  if project_id:
587
619
  CloudStorageTransferDetailsLink.persist(
588
620
  context=context,
589
- task_instance=self,
590
621
  project_id=project_id,
591
622
  operation_name=self.operation_name,
592
623
  )
@@ -663,7 +694,6 @@ class CloudDataTransferServiceListOperationsOperator(GoogleCloudBaseOperator):
663
694
  if project_id:
664
695
  CloudStorageTransferListLink.persist(
665
696
  context=context,
666
- task_instance=self,
667
697
  project_id=project_id,
668
698
  )
669
699
 
@@ -966,6 +996,7 @@ class CloudDataTransferServiceS3ToGCSOperator(GoogleCloudBaseOperator):
966
996
  self.aws_role_arn = aws_role_arn
967
997
  self.deferrable = deferrable
968
998
  self._validate_inputs()
999
+ self._transfer_job: dict[str, Any] | None = None
969
1000
 
970
1001
  def _validate_inputs(self) -> None:
971
1002
  if self.delete_job_after_completion and not self.wait:
@@ -980,19 +1011,18 @@ class CloudDataTransferServiceS3ToGCSOperator(GoogleCloudBaseOperator):
980
1011
 
981
1012
  TransferJobPreprocessor(body=body, aws_conn_id=self.aws_conn_id, default_schedule=True).process_body()
982
1013
 
983
- job = hook.create_transfer_job(body=body)
984
-
1014
+ self._transfer_job = hook.create_transfer_job(body=body)
985
1015
  if self.wait:
986
1016
  if not self.deferrable:
987
- hook.wait_for_transfer_job(job, timeout=self.timeout)
1017
+ hook.wait_for_transfer_job(self._transfer_job, timeout=self.timeout)
988
1018
  if self.delete_job_after_completion:
989
- hook.delete_transfer_job(job_name=job[NAME], project_id=self.project_id)
1019
+ hook.delete_transfer_job(job_name=self._transfer_job[NAME], project_id=self.project_id)
990
1020
  else:
991
1021
  self.defer(
992
1022
  timeout=timedelta(seconds=self.timeout or 60),
993
1023
  trigger=CloudStorageTransferServiceCheckJobStatusTrigger(
994
- job_name=job[NAME],
995
- project_id=job[PROJECT_ID],
1024
+ job_name=self._transfer_job[NAME],
1025
+ project_id=self._transfer_job[PROJECT_ID],
996
1026
  gcp_conn_id=self.gcp_conn_id,
997
1027
  impersonation_chain=self.google_impersonation_chain,
998
1028
  ),
@@ -1042,6 +1072,57 @@ class CloudDataTransferServiceS3ToGCSOperator(GoogleCloudBaseOperator):
1042
1072
 
1043
1073
  return body
1044
1074
 
1075
+ def get_openlineage_facets_on_complete(self, task_instance) -> OperatorLineage | None:
1076
+ """Provide OpenLineage OperatorLineage for the S3->GCS transfer."""
1077
+ from airflow.providers.common.compat.openlineage.facet import Dataset
1078
+ from airflow.providers.google.cloud.openlineage.facets import (
1079
+ CloudStorageTransferJobFacet,
1080
+ CloudStorageTransferRunFacet,
1081
+ )
1082
+ from airflow.providers.openlineage.extractors import OperatorLineage
1083
+
1084
+ input_ds = Dataset(
1085
+ namespace=f"s3://{self.s3_bucket}",
1086
+ name=normalize_directory_path(self.s3_path) or "",
1087
+ )
1088
+
1089
+ output_ds = Dataset(
1090
+ namespace=f"gs://{self.gcs_bucket}",
1091
+ name=normalize_directory_path(self.gcs_path) or "",
1092
+ )
1093
+
1094
+ job = self._transfer_job or {}
1095
+ job_facet = CloudStorageTransferJobFacet(
1096
+ jobName=job.get(NAME),
1097
+ projectId=job.get(PROJECT_ID, self.project_id),
1098
+ description=job.get(DESCRIPTION, self.description),
1099
+ status=job.get(STATUS),
1100
+ sourceBucket=job.get(TRANSFER_SPEC, {})
1101
+ .get(AWS_S3_DATA_SOURCE, {})
1102
+ .get(BUCKET_NAME, self.s3_bucket),
1103
+ sourcePath=job.get(TRANSFER_SPEC, {}).get(AWS_S3_DATA_SOURCE, {}).get(PATH, self.s3_path),
1104
+ targetBucket=job.get(TRANSFER_SPEC, {}).get(GCS_DATA_SINK, {}).get(BUCKET_NAME, self.gcs_bucket),
1105
+ targetPath=job.get(TRANSFER_SPEC, {}).get(GCS_DATA_SINK, {}).get(PATH, self.gcs_path),
1106
+ objectConditions=job.get(TRANSFER_SPEC, {}).get("objectConditions", self.object_conditions),
1107
+ transferOptions=job.get(TRANSFER_SPEC, {}).get("transferOptions", self.transfer_options),
1108
+ schedule=job.get(SCHEDULE, self.schedule),
1109
+ )
1110
+
1111
+ run_facet = CloudStorageTransferRunFacet(
1112
+ jobName=job.get(NAME),
1113
+ wait=self.wait,
1114
+ timeout=self.timeout,
1115
+ deferrable=self.deferrable,
1116
+ deleteJobAfterCompletion=self.delete_job_after_completion,
1117
+ )
1118
+
1119
+ return OperatorLineage(
1120
+ inputs=[input_ds],
1121
+ outputs=[output_ds],
1122
+ job_facets={"cloudStorageTransferJob": job_facet},
1123
+ run_facets={"cloudStorageTransferRun": run_facet},
1124
+ )
1125
+
1045
1126
 
1046
1127
  class CloudDataTransferServiceGCSToGCSOperator(GoogleCloudBaseOperator):
1047
1128
  """