apache-airflow-providers-google 15.1.0rc1__py3-none-any.whl → 19.1.0rc1__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 (234) 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 -5
  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/bigquery.py +166 -281
  10. airflow/providers/google/cloud/hooks/cloud_composer.py +287 -14
  11. airflow/providers/google/cloud/hooks/cloud_logging.py +109 -0
  12. airflow/providers/google/cloud/hooks/cloud_run.py +17 -9
  13. airflow/providers/google/cloud/hooks/cloud_sql.py +101 -22
  14. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +27 -6
  15. airflow/providers/google/cloud/hooks/compute_ssh.py +5 -1
  16. airflow/providers/google/cloud/hooks/datacatalog.py +9 -1
  17. airflow/providers/google/cloud/hooks/dataflow.py +71 -94
  18. airflow/providers/google/cloud/hooks/datafusion.py +1 -1
  19. airflow/providers/google/cloud/hooks/dataplex.py +1 -1
  20. airflow/providers/google/cloud/hooks/dataprep.py +1 -1
  21. airflow/providers/google/cloud/hooks/dataproc.py +72 -71
  22. airflow/providers/google/cloud/hooks/gcs.py +111 -14
  23. airflow/providers/google/cloud/hooks/gen_ai.py +196 -0
  24. airflow/providers/google/cloud/hooks/kubernetes_engine.py +2 -2
  25. airflow/providers/google/cloud/hooks/looker.py +6 -1
  26. airflow/providers/google/cloud/hooks/mlengine.py +3 -2
  27. airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
  28. airflow/providers/google/cloud/hooks/spanner.py +73 -8
  29. airflow/providers/google/cloud/hooks/stackdriver.py +10 -8
  30. airflow/providers/google/cloud/hooks/translate.py +1 -1
  31. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +0 -209
  32. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +2 -2
  33. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +27 -1
  34. airflow/providers/google/cloud/hooks/vertex_ai/experiment_service.py +202 -0
  35. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +307 -7
  36. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +79 -75
  37. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +223 -0
  38. airflow/providers/google/cloud/hooks/vision.py +2 -2
  39. airflow/providers/google/cloud/hooks/workflows.py +1 -1
  40. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  41. airflow/providers/google/cloud/links/base.py +77 -13
  42. airflow/providers/google/cloud/links/bigquery.py +0 -47
  43. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  44. airflow/providers/google/cloud/links/bigtable.py +0 -48
  45. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  46. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  47. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  48. airflow/providers/google/cloud/links/{life_sciences.py → cloud_run.py} +5 -27
  49. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  50. airflow/providers/google/cloud/links/cloud_storage_transfer.py +17 -44
  51. airflow/providers/google/cloud/links/cloud_tasks.py +7 -26
  52. airflow/providers/google/cloud/links/compute.py +0 -58
  53. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  54. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  55. airflow/providers/google/cloud/links/dataflow.py +0 -34
  56. airflow/providers/google/cloud/links/dataform.py +0 -64
  57. airflow/providers/google/cloud/links/datafusion.py +1 -96
  58. airflow/providers/google/cloud/links/dataplex.py +0 -154
  59. airflow/providers/google/cloud/links/dataprep.py +0 -24
  60. airflow/providers/google/cloud/links/dataproc.py +11 -95
  61. airflow/providers/google/cloud/links/datastore.py +0 -31
  62. airflow/providers/google/cloud/links/kubernetes_engine.py +9 -60
  63. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  64. airflow/providers/google/cloud/links/mlengine.py +0 -70
  65. airflow/providers/google/cloud/links/pubsub.py +0 -32
  66. airflow/providers/google/cloud/links/spanner.py +0 -33
  67. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  68. airflow/providers/google/cloud/links/translate.py +17 -187
  69. airflow/providers/google/cloud/links/vertex_ai.py +28 -195
  70. airflow/providers/google/cloud/links/workflows.py +0 -52
  71. airflow/providers/google/cloud/log/gcs_task_handler.py +17 -9
  72. airflow/providers/google/cloud/log/stackdriver_task_handler.py +9 -6
  73. airflow/providers/google/cloud/openlineage/CloudStorageTransferJobFacet.json +68 -0
  74. airflow/providers/google/cloud/openlineage/CloudStorageTransferRunFacet.json +60 -0
  75. airflow/providers/google/cloud/openlineage/DataFusionRunFacet.json +32 -0
  76. airflow/providers/google/cloud/openlineage/facets.py +102 -1
  77. airflow/providers/google/cloud/openlineage/mixins.py +10 -8
  78. airflow/providers/google/cloud/openlineage/utils.py +15 -1
  79. airflow/providers/google/cloud/operators/alloy_db.py +70 -55
  80. airflow/providers/google/cloud/operators/bigquery.py +73 -636
  81. airflow/providers/google/cloud/operators/bigquery_dts.py +3 -5
  82. airflow/providers/google/cloud/operators/bigtable.py +36 -7
  83. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  84. airflow/providers/google/cloud/operators/cloud_batch.py +2 -2
  85. airflow/providers/google/cloud/operators/cloud_build.py +75 -32
  86. airflow/providers/google/cloud/operators/cloud_composer.py +128 -40
  87. airflow/providers/google/cloud/operators/cloud_logging_sink.py +341 -0
  88. airflow/providers/google/cloud/operators/cloud_memorystore.py +69 -43
  89. airflow/providers/google/cloud/operators/cloud_run.py +23 -5
  90. airflow/providers/google/cloud/operators/cloud_sql.py +8 -16
  91. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +92 -11
  92. airflow/providers/google/cloud/operators/compute.py +8 -40
  93. airflow/providers/google/cloud/operators/datacatalog.py +157 -21
  94. airflow/providers/google/cloud/operators/dataflow.py +38 -15
  95. airflow/providers/google/cloud/operators/dataform.py +15 -5
  96. airflow/providers/google/cloud/operators/datafusion.py +41 -20
  97. airflow/providers/google/cloud/operators/dataplex.py +193 -109
  98. airflow/providers/google/cloud/operators/dataprep.py +1 -5
  99. airflow/providers/google/cloud/operators/dataproc.py +78 -35
  100. airflow/providers/google/cloud/operators/dataproc_metastore.py +96 -88
  101. airflow/providers/google/cloud/operators/datastore.py +22 -6
  102. airflow/providers/google/cloud/operators/dlp.py +6 -29
  103. airflow/providers/google/cloud/operators/functions.py +16 -7
  104. airflow/providers/google/cloud/operators/gcs.py +10 -8
  105. airflow/providers/google/cloud/operators/gen_ai.py +389 -0
  106. airflow/providers/google/cloud/operators/kubernetes_engine.py +60 -99
  107. airflow/providers/google/cloud/operators/looker.py +1 -1
  108. airflow/providers/google/cloud/operators/managed_kafka.py +107 -52
  109. airflow/providers/google/cloud/operators/natural_language.py +1 -1
  110. airflow/providers/google/cloud/operators/pubsub.py +60 -14
  111. airflow/providers/google/cloud/operators/spanner.py +25 -12
  112. airflow/providers/google/cloud/operators/speech_to_text.py +1 -2
  113. airflow/providers/google/cloud/operators/stackdriver.py +1 -9
  114. airflow/providers/google/cloud/operators/tasks.py +1 -12
  115. airflow/providers/google/cloud/operators/text_to_speech.py +1 -2
  116. airflow/providers/google/cloud/operators/translate.py +40 -16
  117. airflow/providers/google/cloud/operators/translate_speech.py +1 -2
  118. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +39 -19
  119. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +29 -9
  120. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +54 -26
  121. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +70 -8
  122. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +43 -9
  123. airflow/providers/google/cloud/operators/vertex_ai/experiment_service.py +435 -0
  124. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +532 -1
  125. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +135 -116
  126. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +11 -9
  127. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +57 -11
  128. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +30 -7
  129. airflow/providers/google/cloud/operators/vertex_ai/ray.py +393 -0
  130. airflow/providers/google/cloud/operators/video_intelligence.py +1 -1
  131. airflow/providers/google/cloud/operators/vision.py +2 -2
  132. airflow/providers/google/cloud/operators/workflows.py +18 -15
  133. airflow/providers/google/cloud/sensors/bigquery.py +2 -2
  134. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -2
  135. airflow/providers/google/cloud/sensors/bigtable.py +11 -4
  136. airflow/providers/google/cloud/sensors/cloud_composer.py +533 -29
  137. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -2
  138. airflow/providers/google/cloud/sensors/dataflow.py +26 -9
  139. airflow/providers/google/cloud/sensors/dataform.py +2 -2
  140. airflow/providers/google/cloud/sensors/datafusion.py +4 -4
  141. airflow/providers/google/cloud/sensors/dataplex.py +2 -2
  142. airflow/providers/google/cloud/sensors/dataprep.py +2 -2
  143. airflow/providers/google/cloud/sensors/dataproc.py +2 -2
  144. airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -2
  145. airflow/providers/google/cloud/sensors/gcs.py +4 -4
  146. airflow/providers/google/cloud/sensors/looker.py +2 -2
  147. airflow/providers/google/cloud/sensors/pubsub.py +4 -4
  148. airflow/providers/google/cloud/sensors/tasks.py +2 -2
  149. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +2 -2
  150. airflow/providers/google/cloud/sensors/workflows.py +2 -2
  151. airflow/providers/google/cloud/transfers/adls_to_gcs.py +1 -1
  152. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +2 -2
  153. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +2 -2
  154. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +11 -8
  155. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +4 -4
  156. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +7 -3
  157. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +12 -1
  158. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +24 -10
  159. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +104 -5
  160. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  161. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +2 -2
  162. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +3 -3
  163. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +20 -12
  164. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +2 -2
  165. airflow/providers/google/cloud/transfers/gcs_to_local.py +5 -3
  166. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +10 -4
  167. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +6 -2
  168. airflow/providers/google/cloud/transfers/gdrive_to_local.py +2 -2
  169. airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
  170. airflow/providers/google/cloud/transfers/local_to_gcs.py +2 -2
  171. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
  172. airflow/providers/google/cloud/transfers/oracle_to_gcs.py +36 -11
  173. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +42 -9
  174. airflow/providers/google/cloud/transfers/s3_to_gcs.py +12 -6
  175. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +2 -2
  176. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +13 -4
  177. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +3 -3
  178. airflow/providers/google/cloud/transfers/sql_to_gcs.py +10 -10
  179. airflow/providers/google/cloud/triggers/bigquery.py +75 -34
  180. airflow/providers/google/cloud/triggers/cloud_build.py +1 -1
  181. airflow/providers/google/cloud/triggers/cloud_composer.py +302 -46
  182. airflow/providers/google/cloud/triggers/cloud_run.py +2 -2
  183. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +91 -1
  184. airflow/providers/google/cloud/triggers/dataflow.py +122 -0
  185. airflow/providers/google/cloud/triggers/datafusion.py +1 -1
  186. airflow/providers/google/cloud/triggers/dataplex.py +14 -2
  187. airflow/providers/google/cloud/triggers/dataproc.py +122 -52
  188. airflow/providers/google/cloud/triggers/kubernetes_engine.py +45 -27
  189. airflow/providers/google/cloud/triggers/mlengine.py +1 -1
  190. airflow/providers/google/cloud/triggers/pubsub.py +15 -19
  191. airflow/providers/google/cloud/utils/bigquery_get_data.py +1 -1
  192. airflow/providers/google/cloud/utils/credentials_provider.py +1 -1
  193. airflow/providers/google/cloud/utils/field_validator.py +1 -2
  194. airflow/providers/google/common/auth_backend/google_openid.py +4 -4
  195. airflow/providers/google/common/deprecated.py +2 -1
  196. airflow/providers/google/common/hooks/base_google.py +27 -8
  197. airflow/providers/google/common/links/storage.py +0 -22
  198. airflow/providers/google/common/utils/get_secret.py +31 -0
  199. airflow/providers/google/common/utils/id_token_credentials.py +3 -4
  200. airflow/providers/google/firebase/operators/firestore.py +2 -2
  201. airflow/providers/google/get_provider_info.py +56 -52
  202. airflow/providers/google/go_module_utils.py +35 -3
  203. airflow/providers/google/leveldb/hooks/leveldb.py +26 -1
  204. airflow/providers/google/leveldb/operators/leveldb.py +2 -2
  205. airflow/providers/google/marketing_platform/hooks/display_video.py +3 -109
  206. airflow/providers/google/marketing_platform/links/analytics_admin.py +5 -14
  207. airflow/providers/google/marketing_platform/operators/analytics_admin.py +1 -2
  208. airflow/providers/google/marketing_platform/operators/campaign_manager.py +5 -5
  209. airflow/providers/google/marketing_platform/operators/display_video.py +28 -489
  210. airflow/providers/google/marketing_platform/operators/search_ads.py +2 -2
  211. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +2 -2
  212. airflow/providers/google/marketing_platform/sensors/display_video.py +3 -63
  213. airflow/providers/google/suite/hooks/calendar.py +1 -1
  214. airflow/providers/google/suite/hooks/sheets.py +15 -1
  215. airflow/providers/google/suite/operators/sheets.py +8 -3
  216. airflow/providers/google/suite/sensors/drive.py +2 -2
  217. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +2 -2
  218. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  219. airflow/providers/google/suite/transfers/local_to_drive.py +3 -3
  220. airflow/providers/google/suite/transfers/sql_to_sheets.py +5 -4
  221. airflow/providers/google/version_compat.py +15 -1
  222. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/METADATA +92 -48
  223. apache_airflow_providers_google-19.1.0rc1.dist-info/RECORD +331 -0
  224. apache_airflow_providers_google-19.1.0rc1.dist-info/licenses/NOTICE +5 -0
  225. airflow/providers/google/cloud/hooks/automl.py +0 -673
  226. airflow/providers/google/cloud/hooks/life_sciences.py +0 -159
  227. airflow/providers/google/cloud/links/automl.py +0 -193
  228. airflow/providers/google/cloud/operators/automl.py +0 -1362
  229. airflow/providers/google/cloud/operators/life_sciences.py +0 -119
  230. airflow/providers/google/cloud/operators/mlengine.py +0 -112
  231. apache_airflow_providers_google-15.1.0rc1.dist-info/RECORD +0 -321
  232. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/WHEEL +0 -0
  233. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/entry_points.txt +0 -0
  234. {airflow/providers/google → apache_airflow_providers_google-19.1.0rc1.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)
@@ -27,6 +27,7 @@ from google.cloud.run_v2 import Job, Service
27
27
  from airflow.configuration import conf
28
28
  from airflow.exceptions 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
@@ -28,7 +28,7 @@ from googleapiclient.errors import HttpError
28
28
 
29
29
  from airflow.configuration import conf
30
30
  from airflow.exceptions import AirflowException
31
- from airflow.hooks.base import BaseHook
31
+ from airflow.providers.common.compat.sdk import BaseHook
32
32
  from airflow.providers.google.cloud.hooks.cloud_sql import CloudSQLDatabaseHook, CloudSQLHook
33
33
  from airflow.providers.google.cloud.links.cloud_sql import CloudSQLInstanceDatabaseLink, CloudSQLInstanceLink
34
34
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
@@ -39,8 +39,8 @@ from airflow.providers.google.common.links.storage import FileDetailsLink
39
39
 
40
40
  if TYPE_CHECKING:
41
41
  from airflow.models import Connection
42
+ from airflow.providers.common.compat.sdk import Context
42
43
  from airflow.providers.openlineage.extractors import OperatorLineage
43
- from airflow.utils.context import Context
44
44
 
45
45
 
46
46
  SETTINGS = "settings"
@@ -285,6 +285,12 @@ class CloudSQLBaseOperator(GoogleCloudBaseOperator):
285
285
  return False
286
286
  raise e
287
287
 
288
+ @property
289
+ def extra_links_params(self) -> dict[str, Any]:
290
+ return {
291
+ "instance": self.instance,
292
+ }
293
+
288
294
  def execute(self, context: Context):
289
295
  pass
290
296
 
@@ -384,8 +390,6 @@ class CloudSQLCreateInstanceOperator(CloudSQLBaseOperator):
384
390
 
385
391
  CloudSQLInstanceLink.persist(
386
392
  context=context,
387
- task_instance=self,
388
- cloud_sql_instance=self.instance,
389
393
  project_id=self.project_id or hook.project_id,
390
394
  )
391
395
 
@@ -479,8 +483,6 @@ class CloudSQLInstancePatchOperator(CloudSQLBaseOperator):
479
483
  )
480
484
  CloudSQLInstanceLink.persist(
481
485
  context=context,
482
- task_instance=self,
483
- cloud_sql_instance=self.instance,
484
486
  project_id=self.project_id or hook.project_id,
485
487
  )
486
488
 
@@ -714,8 +716,6 @@ class CloudSQLCreateInstanceDatabaseOperator(CloudSQLBaseOperator):
714
716
  )
715
717
  CloudSQLInstanceDatabaseLink.persist(
716
718
  context=context,
717
- task_instance=self,
718
- cloud_sql_instance=self.instance,
719
719
  project_id=self.project_id or hook.project_id,
720
720
  )
721
721
  if self._check_if_db_exists(database, hook):
@@ -822,8 +822,6 @@ class CloudSQLPatchInstanceDatabaseOperator(CloudSQLBaseOperator):
822
822
  )
823
823
  CloudSQLInstanceDatabaseLink.persist(
824
824
  context=context,
825
- task_instance=self,
826
- cloud_sql_instance=self.instance,
827
825
  project_id=self.project_id or hook.project_id,
828
826
  )
829
827
  return hook.patch_database(
@@ -1004,13 +1002,10 @@ class CloudSQLExportInstanceOperator(CloudSQLBaseOperator):
1004
1002
  )
1005
1003
  CloudSQLInstanceLink.persist(
1006
1004
  context=context,
1007
- task_instance=self,
1008
- cloud_sql_instance=self.instance,
1009
1005
  project_id=self.project_id or hook.project_id,
1010
1006
  )
1011
1007
  FileDetailsLink.persist(
1012
1008
  context=context,
1013
- task_instance=self,
1014
1009
  uri=self.body["exportContext"]["uri"][5:],
1015
1010
  project_id=self.project_id or hook.project_id,
1016
1011
  )
@@ -1147,13 +1142,10 @@ class CloudSQLImportInstanceOperator(CloudSQLBaseOperator):
1147
1142
  )
1148
1143
  CloudSQLInstanceLink.persist(
1149
1144
  context=context,
1150
- task_instance=self,
1151
- cloud_sql_instance=self.instance,
1152
1145
  project_id=self.project_id or hook.project_id,
1153
1146
  )
1154
1147
  FileDetailsLink.persist(
1155
1148
  context=context,
1156
- task_instance=self,
1157
1149
  uri=self.body["importContext"]["uri"][5:],
1158
1150
  project_id=self.project_id or hook.project_id,
1159
1151
  )
@@ -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
  """