apache-airflow-providers-google 10.7.0rc1__py3-none-any.whl → 10.8.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 (174) hide show
  1. airflow/providers/google/__init__.py +1 -1
  2. airflow/providers/google/ads/hooks/ads.py +10 -6
  3. airflow/providers/google/cloud/_internal_client/secret_manager_client.py +4 -1
  4. airflow/providers/google/cloud/example_dags/example_cloud_sql_query.py +31 -34
  5. airflow/providers/google/cloud/hooks/automl.py +11 -9
  6. airflow/providers/google/cloud/hooks/bigquery.py +30 -36
  7. airflow/providers/google/cloud/hooks/bigquery_dts.py +5 -3
  8. airflow/providers/google/cloud/hooks/bigtable.py +11 -8
  9. airflow/providers/google/cloud/hooks/cloud_batch.py +5 -3
  10. airflow/providers/google/cloud/hooks/cloud_build.py +6 -4
  11. airflow/providers/google/cloud/hooks/cloud_composer.py +14 -10
  12. airflow/providers/google/cloud/hooks/cloud_memorystore.py +5 -3
  13. airflow/providers/google/cloud/hooks/cloud_run.py +5 -3
  14. airflow/providers/google/cloud/hooks/cloud_sql.py +11 -14
  15. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +8 -6
  16. airflow/providers/google/cloud/hooks/compute.py +5 -3
  17. airflow/providers/google/cloud/hooks/compute_ssh.py +1 -1
  18. airflow/providers/google/cloud/hooks/datacatalog.py +5 -3
  19. airflow/providers/google/cloud/hooks/dataflow.py +8 -11
  20. airflow/providers/google/cloud/hooks/dataform.py +4 -2
  21. airflow/providers/google/cloud/hooks/datafusion.py +24 -6
  22. airflow/providers/google/cloud/hooks/dataplex.py +75 -6
  23. airflow/providers/google/cloud/hooks/dataproc.py +9 -7
  24. airflow/providers/google/cloud/hooks/dataproc_metastore.py +8 -6
  25. airflow/providers/google/cloud/hooks/dlp.py +139 -137
  26. airflow/providers/google/cloud/hooks/gcs.py +15 -20
  27. airflow/providers/google/cloud/hooks/kms.py +4 -2
  28. airflow/providers/google/cloud/hooks/kubernetes_engine.py +34 -34
  29. airflow/providers/google/cloud/hooks/looker.py +4 -1
  30. airflow/providers/google/cloud/hooks/mlengine.py +8 -6
  31. airflow/providers/google/cloud/hooks/natural_language.py +4 -2
  32. airflow/providers/google/cloud/hooks/os_login.py +9 -7
  33. airflow/providers/google/cloud/hooks/pubsub.py +13 -11
  34. airflow/providers/google/cloud/hooks/spanner.py +7 -5
  35. airflow/providers/google/cloud/hooks/speech_to_text.py +4 -2
  36. airflow/providers/google/cloud/hooks/stackdriver.py +6 -5
  37. airflow/providers/google/cloud/hooks/tasks.py +5 -3
  38. airflow/providers/google/cloud/hooks/text_to_speech.py +4 -2
  39. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +7 -5
  40. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +6 -4
  41. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +11 -9
  42. airflow/providers/google/cloud/hooks/vertex_ai/dataset.py +12 -10
  43. airflow/providers/google/cloud/hooks/vertex_ai/endpoint_service.py +8 -6
  44. airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +6 -4
  45. airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +7 -5
  46. airflow/providers/google/cloud/hooks/video_intelligence.py +5 -3
  47. airflow/providers/google/cloud/hooks/vision.py +5 -3
  48. airflow/providers/google/cloud/hooks/workflows.py +8 -6
  49. airflow/providers/google/cloud/links/bigquery.py +1 -1
  50. airflow/providers/google/cloud/links/bigquery_dts.py +1 -1
  51. airflow/providers/google/cloud/links/cloud_functions.py +1 -1
  52. airflow/providers/google/cloud/links/cloud_memorystore.py +1 -1
  53. airflow/providers/google/cloud/links/cloud_sql.py +1 -1
  54. airflow/providers/google/cloud/links/cloud_tasks.py +1 -1
  55. airflow/providers/google/cloud/links/compute.py +1 -1
  56. airflow/providers/google/cloud/links/datacatalog.py +1 -1
  57. airflow/providers/google/cloud/links/dataflow.py +1 -1
  58. airflow/providers/google/cloud/links/dataform.py +1 -1
  59. airflow/providers/google/cloud/links/pubsub.py +1 -1
  60. airflow/providers/google/cloud/links/spanner.py +1 -1
  61. airflow/providers/google/cloud/links/stackdriver.py +1 -1
  62. airflow/providers/google/cloud/links/workflows.py +2 -2
  63. airflow/providers/google/cloud/log/gcs_task_handler.py +5 -7
  64. airflow/providers/google/cloud/log/stackdriver_task_handler.py +8 -4
  65. airflow/providers/google/cloud/operators/automl.py +2 -1
  66. airflow/providers/google/cloud/operators/bigquery.py +6 -2
  67. airflow/providers/google/cloud/operators/bigquery_dts.py +2 -1
  68. airflow/providers/google/cloud/operators/bigtable.py +5 -3
  69. airflow/providers/google/cloud/operators/cloud_batch.py +6 -3
  70. airflow/providers/google/cloud/operators/cloud_build.py +2 -1
  71. airflow/providers/google/cloud/operators/cloud_composer.py +3 -2
  72. airflow/providers/google/cloud/operators/cloud_memorystore.py +3 -2
  73. airflow/providers/google/cloud/operators/cloud_run.py +3 -2
  74. airflow/providers/google/cloud/operators/cloud_sql.py +157 -152
  75. airflow/providers/google/cloud/operators/compute.py +59 -61
  76. airflow/providers/google/cloud/operators/datacatalog.py +3 -2
  77. airflow/providers/google/cloud/operators/dataflow.py +3 -1
  78. airflow/providers/google/cloud/operators/dataform.py +2 -1
  79. airflow/providers/google/cloud/operators/datafusion.py +1 -1
  80. airflow/providers/google/cloud/operators/dataplex.py +110 -8
  81. airflow/providers/google/cloud/operators/dataproc.py +39 -18
  82. airflow/providers/google/cloud/operators/dataproc_metastore.py +2 -1
  83. airflow/providers/google/cloud/operators/dlp.py +3 -2
  84. airflow/providers/google/cloud/operators/functions.py +46 -46
  85. airflow/providers/google/cloud/operators/gcs.py +4 -6
  86. airflow/providers/google/cloud/operators/kubernetes_engine.py +2 -1
  87. airflow/providers/google/cloud/operators/natural_language.py +3 -2
  88. airflow/providers/google/cloud/operators/pubsub.py +2 -1
  89. airflow/providers/google/cloud/operators/speech_to_text.py +3 -2
  90. airflow/providers/google/cloud/operators/stackdriver.py +2 -1
  91. airflow/providers/google/cloud/operators/tasks.py +3 -2
  92. airflow/providers/google/cloud/operators/text_to_speech.py +3 -2
  93. airflow/providers/google/cloud/operators/translate_speech.py +2 -1
  94. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +2 -1
  95. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +3 -2
  96. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +2 -1
  97. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +3 -2
  98. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +4 -4
  99. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +3 -2
  100. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +2 -1
  101. airflow/providers/google/cloud/operators/video_intelligence.py +2 -1
  102. airflow/providers/google/cloud/operators/vision.py +3 -2
  103. airflow/providers/google/cloud/operators/workflows.py +7 -5
  104. airflow/providers/google/cloud/secrets/secret_manager.py +2 -2
  105. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -1
  106. airflow/providers/google/cloud/sensors/dataplex.py +2 -1
  107. airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -2
  108. airflow/providers/google/cloud/sensors/gcs.py +2 -1
  109. airflow/providers/google/cloud/sensors/workflows.py +2 -1
  110. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +24 -10
  111. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +2 -1
  112. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +2 -1
  113. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +1 -4
  114. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +1 -4
  115. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -1
  116. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +4 -2
  117. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +1 -3
  118. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +2 -2
  119. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +2 -1
  120. airflow/providers/google/cloud/transfers/presto_to_gcs.py +5 -4
  121. airflow/providers/google/cloud/transfers/sql_to_gcs.py +1 -1
  122. airflow/providers/google/cloud/transfers/trino_to_gcs.py +5 -4
  123. airflow/providers/google/cloud/triggers/bigquery.py +30 -36
  124. airflow/providers/google/cloud/triggers/bigquery_dts.py +9 -10
  125. airflow/providers/google/cloud/triggers/cloud_batch.py +6 -8
  126. airflow/providers/google/cloud/triggers/cloud_build.py +5 -6
  127. airflow/providers/google/cloud/triggers/cloud_run.py +4 -3
  128. airflow/providers/google/cloud/triggers/cloud_sql.py +10 -10
  129. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +1 -1
  130. airflow/providers/google/cloud/triggers/dataflow.py +5 -6
  131. airflow/providers/google/cloud/triggers/datafusion.py +5 -6
  132. airflow/providers/google/cloud/triggers/dataplex.py +110 -0
  133. airflow/providers/google/cloud/triggers/dataproc.py +18 -20
  134. airflow/providers/google/cloud/triggers/kubernetes_engine.py +14 -13
  135. airflow/providers/google/cloud/triggers/mlengine.py +5 -5
  136. airflow/providers/google/cloud/triggers/pubsub.py +2 -2
  137. airflow/providers/google/cloud/utils/bigquery_get_data.py +6 -3
  138. airflow/providers/google/cloud/utils/credentials_provider.py +1 -1
  139. airflow/providers/google/cloud/utils/field_validator.py +13 -13
  140. airflow/providers/google/cloud/utils/mlengine_operator_utils.py +5 -3
  141. airflow/providers/google/cloud/utils/mlengine_prediction_summary.py +1 -1
  142. airflow/providers/google/common/hooks/base_google.py +10 -2
  143. airflow/providers/google/common/links/storage.py +1 -1
  144. airflow/providers/google/common/utils/id_token_credentials.py +4 -1
  145. airflow/providers/google/get_provider_info.py +5 -0
  146. airflow/providers/google/marketing_platform/hooks/campaign_manager.py +4 -2
  147. airflow/providers/google/marketing_platform/sensors/display_video.py +6 -3
  148. airflow/providers/google/suite/hooks/calendar.py +4 -2
  149. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/METADATA +8 -8
  150. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/RECORD +155 -173
  151. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/WHEEL +1 -1
  152. airflow/providers/google/ads/_vendor/__init__.py +0 -16
  153. airflow/providers/google/ads/_vendor/googleads/__init__.py +0 -16
  154. airflow/providers/google/ads/_vendor/googleads/interceptors/__init__.py +0 -16
  155. airflow/providers/google/ads/_vendor/googleads/v12/__init__.py +0 -16
  156. airflow/providers/google/ads/_vendor/googleads/v12/common/__init__.py +0 -16
  157. airflow/providers/google/ads/_vendor/googleads/v12/common/types/__init__.py +0 -16
  158. airflow/providers/google/ads/_vendor/googleads/v12/enums/__init__.py +0 -16
  159. airflow/providers/google/ads/_vendor/googleads/v12/enums/types/__init__.py +0 -16
  160. airflow/providers/google/ads/_vendor/googleads/v12/errors/__init__.py +0 -16
  161. airflow/providers/google/ads/_vendor/googleads/v12/errors/types/__init__.py +0 -16
  162. airflow/providers/google/ads/_vendor/googleads/v12/resources/__init__.py +0 -16
  163. airflow/providers/google/ads/_vendor/googleads/v12/resources/types/__init__.py +0 -16
  164. airflow/providers/google/ads/_vendor/googleads/v12/services/__init__.py +0 -16
  165. airflow/providers/google/ads/_vendor/googleads/v12/services/services/__init__.py +0 -16
  166. airflow/providers/google/ads/_vendor/googleads/v12/services/services/customer_service/__init__.py +0 -16
  167. airflow/providers/google/ads/_vendor/googleads/v12/services/services/customer_service/transports/__init__.py +0 -16
  168. airflow/providers/google/ads/_vendor/googleads/v12/services/services/google_ads_service/__init__.py +0 -16
  169. airflow/providers/google/ads/_vendor/googleads/v12/services/services/google_ads_service/transports/__init__.py +0 -16
  170. airflow/providers/google/ads/_vendor/googleads/v12/services/types/__init__.py +0 -16
  171. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/LICENSE +0 -0
  172. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/NOTICE +0 -0
  173. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/entry_points.txt +0 -0
  174. {apache_airflow_providers_google-10.7.0rc1.dist-info → apache_airflow_providers_google-10.8.0.dist-info}/top_level.txt +0 -0
@@ -75,8 +75,8 @@ class BigQueryInsertJobTrigger(BaseTrigger):
75
75
  """Gets current job execution status and yields a TriggerEvent."""
76
76
  """Gets current job execution status and yields a TriggerEvent."""
77
77
  hook = self._get_async_hook()
78
- while True:
79
- try:
78
+ try:
79
+ while True:
80
80
  job_status = await hook.get_job_status(job_id=self.job_id, project_id=self.project_id)
81
81
  if job_status == "success":
82
82
  yield TriggerEvent(
@@ -95,10 +95,9 @@ class BigQueryInsertJobTrigger(BaseTrigger):
95
95
  "Bigquery job status is %s. Sleeping for %s seconds.", job_status, self.poll_interval
96
96
  )
97
97
  await asyncio.sleep(self.poll_interval)
98
- except Exception as e:
99
- self.log.exception("Exception occurred while checking for query completion")
100
- yield TriggerEvent({"status": "error", "message": str(e)})
101
- return
98
+ except Exception as e:
99
+ self.log.exception("Exception occurred while checking for query completion")
100
+ yield TriggerEvent({"status": "error", "message": str(e)})
102
101
 
103
102
  def _get_async_hook(self) -> BigQueryAsyncHook:
104
103
  return BigQueryAsyncHook(gcp_conn_id=self.conn_id)
@@ -124,8 +123,8 @@ class BigQueryCheckTrigger(BigQueryInsertJobTrigger):
124
123
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
125
124
  """Gets current job execution status and yields a TriggerEvent."""
126
125
  hook = self._get_async_hook()
127
- while True:
128
- try:
126
+ try:
127
+ while True:
129
128
  # Poll for job execution status
130
129
  job_status = await hook.get_job_status(job_id=self.job_id, project_id=self.project_id)
131
130
  if job_status == "success":
@@ -160,10 +159,9 @@ class BigQueryCheckTrigger(BigQueryInsertJobTrigger):
160
159
  "Bigquery job status is %s. Sleeping for %s seconds.", job_status, self.poll_interval
161
160
  )
162
161
  await asyncio.sleep(self.poll_interval)
163
- except Exception as e:
164
- self.log.exception("Exception occurred while checking for query completion")
165
- yield TriggerEvent({"status": "error", "message": str(e)})
166
- return
162
+ except Exception as e:
163
+ self.log.exception("Exception occurred while checking for query completion")
164
+ yield TriggerEvent({"status": "error", "message": str(e)})
167
165
 
168
166
 
169
167
  class BigQueryGetDataTrigger(BigQueryInsertJobTrigger):
@@ -196,8 +194,8 @@ class BigQueryGetDataTrigger(BigQueryInsertJobTrigger):
196
194
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
197
195
  """Gets current job execution status and yields a TriggerEvent with response data."""
198
196
  hook = self._get_async_hook()
199
- while True:
200
- try:
197
+ try:
198
+ while True:
201
199
  # Poll for job execution status
202
200
  job_status = await hook.get_job_status(job_id=self.job_id, project_id=self.project_id)
203
201
  if job_status == "success":
@@ -220,10 +218,9 @@ class BigQueryGetDataTrigger(BigQueryInsertJobTrigger):
220
218
  "Bigquery job status is %s. Sleeping for %s seconds.", job_status, self.poll_interval
221
219
  )
222
220
  await asyncio.sleep(self.poll_interval)
223
- except Exception as e:
224
- self.log.exception("Exception occurred while checking for query completion")
225
- yield TriggerEvent({"status": "error", "message": str(e)})
226
- return
221
+ except Exception as e:
222
+ self.log.exception("Exception occurred while checking for query completion")
223
+ yield TriggerEvent({"status": "error", "message": str(e)})
227
224
 
228
225
 
229
226
  class BigQueryIntervalCheckTrigger(BigQueryInsertJobTrigger):
@@ -302,8 +299,8 @@ class BigQueryIntervalCheckTrigger(BigQueryInsertJobTrigger):
302
299
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
303
300
  """Gets current job execution status and yields a TriggerEvent."""
304
301
  hook = self._get_async_hook()
305
- while True:
306
- try:
302
+ try:
303
+ while True:
307
304
  first_job_response_from_hook = await hook.get_job_status(
308
305
  job_id=self.first_job_id, project_id=self.project_id
309
306
  )
@@ -365,10 +362,9 @@ class BigQueryIntervalCheckTrigger(BigQueryInsertJobTrigger):
365
362
  )
366
363
  return
367
364
 
368
- except Exception as e:
369
- self.log.exception("Exception occurred while checking for query completion")
370
- yield TriggerEvent({"status": "error", "message": str(e)})
371
- return
365
+ except Exception as e:
366
+ self.log.exception("Exception occurred while checking for query completion")
367
+ yield TriggerEvent({"status": "error", "message": str(e)})
372
368
 
373
369
 
374
370
  class BigQueryValueCheckTrigger(BigQueryInsertJobTrigger):
@@ -430,8 +426,8 @@ class BigQueryValueCheckTrigger(BigQueryInsertJobTrigger):
430
426
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
431
427
  """Gets current job execution status and yields a TriggerEvent."""
432
428
  hook = self._get_async_hook()
433
- while True:
434
- try:
429
+ try:
430
+ while True:
435
431
  # Poll for job execution status
436
432
  response_from_hook = await hook.get_job_status(job_id=self.job_id, project_id=self.project_id)
437
433
  if response_from_hook == "success":
@@ -448,10 +444,9 @@ class BigQueryValueCheckTrigger(BigQueryInsertJobTrigger):
448
444
  else:
449
445
  yield TriggerEvent({"status": "error", "message": response_from_hook, "records": None})
450
446
  return
451
- except Exception as e:
452
- self.log.exception("Exception occurred while checking for query completion")
453
- yield TriggerEvent({"status": "error", "message": str(e)})
454
- return
447
+ except Exception as e:
448
+ self.log.exception("Exception occurred while checking for query completion")
449
+ yield TriggerEvent({"status": "error", "message": str(e)})
455
450
 
456
451
 
457
452
  class BigQueryTableExistenceTrigger(BaseTrigger):
@@ -501,8 +496,8 @@ class BigQueryTableExistenceTrigger(BaseTrigger):
501
496
 
502
497
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
503
498
  """Will run until the table exists in the Google Big Query."""
504
- while True:
505
- try:
499
+ try:
500
+ while True:
506
501
  hook = self._get_async_hook()
507
502
  response = await self._table_exists(
508
503
  hook=hook, dataset=self.dataset_id, table_id=self.table_id, project_id=self.project_id
@@ -511,10 +506,9 @@ class BigQueryTableExistenceTrigger(BaseTrigger):
511
506
  yield TriggerEvent({"status": "success", "message": "success"})
512
507
  return
513
508
  await asyncio.sleep(self.poll_interval)
514
- except Exception as e:
515
- self.log.exception("Exception occurred while checking for Table existence")
516
- yield TriggerEvent({"status": "error", "message": str(e)})
517
- return
509
+ except Exception as e:
510
+ self.log.exception("Exception occurred while checking for Table existence")
511
+ yield TriggerEvent({"status": "error", "message": str(e)})
518
512
 
519
513
  async def _table_exists(
520
514
  self, hook: BigQueryTableAsyncHook, dataset: str, table_id: str, project_id: str
@@ -83,8 +83,8 @@ class BigQueryDataTransferRunTrigger(BaseTrigger):
83
83
  async def run(self) -> AsyncIterator[TriggerEvent]:
84
84
  """If the Transfer Run is in a terminal state, then yield TriggerEvent object."""
85
85
  hook = self._get_async_hook()
86
- while True:
87
- try:
86
+ try:
87
+ while True:
88
88
  transfer_run: TransferRun = await hook.get_transfer_run(
89
89
  project_id=self.project_id,
90
90
  config_id=self.config_id,
@@ -129,14 +129,13 @@ class BigQueryDataTransferRunTrigger(BaseTrigger):
129
129
  self.log.info("Job is still working...")
130
130
  self.log.info("Waiting for %s seconds", self.poll_interval)
131
131
  await asyncio.sleep(self.poll_interval)
132
- except Exception as e:
133
- yield TriggerEvent(
134
- {
135
- "status": "failed",
136
- "message": f"Trigger failed with exception: {e}",
137
- }
138
- )
139
- return
132
+ except Exception as e:
133
+ yield TriggerEvent(
134
+ {
135
+ "status": "failed",
136
+ "message": f"Trigger failed with exception: {e}",
137
+ }
138
+ )
140
139
 
141
140
  def _get_async_hook(self) -> AsyncBiqQueryDataTransferServiceHook:
142
141
  return AsyncBiqQueryDataTransferServiceHook(
@@ -92,9 +92,8 @@ class CloudBatchJobFinishedTrigger(BaseTrigger):
92
92
  """
93
93
  timeout = self.timeout
94
94
  hook = self._get_async_hook()
95
- while timeout is None or timeout > 0:
96
-
97
- try:
95
+ try:
96
+ while timeout is None or timeout > 0:
98
97
  job: Job = await hook.get_batch_job(job_name=self.job_name)
99
98
 
100
99
  status: JobStatus.State = job.status.state
@@ -134,10 +133,10 @@ class CloudBatchJobFinishedTrigger(BaseTrigger):
134
133
  if timeout is None or timeout > 0:
135
134
  await asyncio.sleep(self.polling_period_seconds)
136
135
 
137
- except Exception as e:
138
- self.log.exception("Exception occurred while checking for job completion.")
139
- yield TriggerEvent({"status": "error", "message": str(e)})
140
- return
136
+ except Exception as e:
137
+ self.log.exception("Exception occurred while checking for job completion.")
138
+ yield TriggerEvent({"status": "error", "message": str(e)})
139
+ return
141
140
 
142
141
  self.log.exception(f"Job with name [{self.job_name}] timed out")
143
142
  yield TriggerEvent(
@@ -147,7 +146,6 @@ class CloudBatchJobFinishedTrigger(BaseTrigger):
147
146
  "message": f"Batch job with name {self.job_name} timed out",
148
147
  }
149
148
  )
150
- return
151
149
 
152
150
  def _get_async_hook(self) -> CloudBatchAsyncHook:
153
151
  return CloudBatchAsyncHook(
@@ -78,8 +78,8 @@ class CloudBuildCreateBuildTrigger(BaseTrigger):
78
78
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
79
79
  """Gets current build execution status and yields a TriggerEvent."""
80
80
  hook = self._get_async_hook()
81
- while True:
82
- try:
81
+ try:
82
+ while True:
83
83
  # Poll for job execution status
84
84
  cloud_build_instance = await hook.get_cloud_build(
85
85
  id_=self.id_,
@@ -119,10 +119,9 @@ class CloudBuildCreateBuildTrigger(BaseTrigger):
119
119
  )
120
120
  return
121
121
 
122
- except Exception as e:
123
- self.log.exception("Exception occurred while checking for Cloud Build completion")
124
- yield TriggerEvent({"status": "error", "message": str(e)})
125
- return
122
+ except Exception as e:
123
+ self.log.exception("Exception occurred while checking for Cloud Build completion")
124
+ yield TriggerEvent({"status": "error", "message": str(e)})
126
125
 
127
126
  def _get_async_hook(self) -> CloudBuildAsyncHook:
128
127
  return CloudBuildAsyncHook(gcp_conn_id=self.gcp_conn_id)
@@ -18,14 +18,15 @@ from __future__ import annotations
18
18
 
19
19
  import asyncio
20
20
  from enum import Enum
21
- from typing import Any, AsyncIterator, Sequence
22
-
23
- from google.longrunning import operations_pb2
21
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Sequence
24
22
 
25
23
  from airflow.exceptions import AirflowException
26
24
  from airflow.providers.google.cloud.hooks.cloud_run import CloudRunAsyncHook
27
25
  from airflow.triggers.base import BaseTrigger, TriggerEvent
28
26
 
27
+ if TYPE_CHECKING:
28
+ from google.longrunning import operations_pb2
29
+
29
30
  DEFAULT_BATCH_LOCATION = "us-central1"
30
31
 
31
32
 
@@ -64,8 +64,8 @@ class CloudSQLExportTrigger(BaseTrigger):
64
64
  )
65
65
 
66
66
  async def run(self):
67
- while True:
68
- try:
67
+ try:
68
+ while True:
69
69
  operation = await self.hook.get_operation(
70
70
  project_id=self.project_id, operation_name=self.operation_name
71
71
  )
@@ -93,11 +93,11 @@ class CloudSQLExportTrigger(BaseTrigger):
93
93
  self.poke_interval,
94
94
  )
95
95
  await asyncio.sleep(self.poke_interval)
96
- except Exception as e:
97
- self.log.exception("Exception occurred while checking operation status.")
98
- yield TriggerEvent(
99
- {
100
- "status": "failed",
101
- "message": str(e),
102
- }
103
- )
96
+ except Exception as e:
97
+ self.log.exception("Exception occurred while checking operation status.")
98
+ yield TriggerEvent(
99
+ {
100
+ "status": "failed",
101
+ "message": str(e),
102
+ }
103
+ )
@@ -97,7 +97,7 @@ class CloudStorageTransferServiceCreateJobsTrigger(BaseTrigger):
97
97
  )
98
98
  return
99
99
  except (GoogleAPIError, AirflowException) as ex:
100
- yield TriggerEvent(dict(status="error", message=str(ex)))
100
+ yield TriggerEvent({"status": "error", "message": str(ex)})
101
101
  return
102
102
 
103
103
  jobs_total = len(self.job_names)
@@ -92,8 +92,8 @@ class TemplateJobStartTrigger(BaseTrigger):
92
92
  amount of time stored in self.poll_sleep variable.
93
93
  """
94
94
  hook = self._get_async_hook()
95
- while True:
96
- try:
95
+ try:
96
+ while True:
97
97
  status = await hook.get_job_status(
98
98
  project_id=self.project_id,
99
99
  job_id=self.job_id,
@@ -129,10 +129,9 @@ class TemplateJobStartTrigger(BaseTrigger):
129
129
  self.log.info("Current job status is: %s", status)
130
130
  self.log.info("Sleeping for %s seconds.", self.poll_sleep)
131
131
  await asyncio.sleep(self.poll_sleep)
132
- except Exception as e:
133
- self.log.exception("Exception occurred while checking for job completion.")
134
- yield TriggerEvent({"status": "error", "message": str(e)})
135
- return
132
+ except Exception as e:
133
+ self.log.exception("Exception occurred while checking for job completion.")
134
+ yield TriggerEvent({"status": "error", "message": str(e)})
136
135
 
137
136
  def _get_async_hook(self) -> AsyncDataflowHook:
138
137
  return AsyncDataflowHook(
@@ -83,8 +83,8 @@ class DataFusionStartPipelineTrigger(BaseTrigger):
83
83
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
84
84
  """Gets current pipeline status and yields a TriggerEvent."""
85
85
  hook = self._get_async_hook()
86
- while True:
87
- try:
86
+ try:
87
+ while True:
88
88
  # Poll for job execution status
89
89
  response_from_hook = await hook.get_pipeline_status(
90
90
  success_states=self.success_states,
@@ -109,10 +109,9 @@ class DataFusionStartPipelineTrigger(BaseTrigger):
109
109
  else:
110
110
  yield TriggerEvent({"status": "error", "message": response_from_hook})
111
111
  return
112
- except Exception as e:
113
- self.log.exception("Exception occurred while checking for pipeline state")
114
- yield TriggerEvent({"status": "error", "message": str(e)})
115
- return
112
+ except Exception as e:
113
+ self.log.exception("Exception occurred while checking for pipeline state")
114
+ yield TriggerEvent({"status": "error", "message": str(e)})
116
115
 
117
116
  def _get_async_hook(self) -> DataFusionAsyncHook:
118
117
  return DataFusionAsyncHook(
@@ -0,0 +1,110 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ """This module contains Google Dataplex triggers."""
19
+ from __future__ import annotations
20
+
21
+ import asyncio
22
+ from typing import AsyncIterator, Sequence
23
+
24
+ from google.cloud.dataplex_v1.types import DataScanJob
25
+
26
+ from airflow.providers.google.cloud.hooks.dataplex import DataplexAsyncHook
27
+ from airflow.triggers.base import BaseTrigger, TriggerEvent
28
+
29
+
30
+ class DataplexDataQualityJobTrigger(BaseTrigger):
31
+ """
32
+ DataplexDataQualityJobTrigger runs on the trigger worker and waits for the job to be `SUCCEEDED` state.
33
+
34
+ :param job_id: Optional. The ID of a Dataplex job.
35
+ :param data_scan_id: Required. DataScan identifier.
36
+ :param project_id: Google Cloud Project where the job is running.
37
+ :param region: The ID of the Google Cloud region that the job belongs to.
38
+ :param gcp_conn_id: Optional, the connection ID used to connect to Google Cloud Platform.
39
+ :param impersonation_chain: Optional service account to impersonate using short-term
40
+ credentials, or chained list of accounts required to get the access_token
41
+ of the last account in the list, which will be impersonated in the request.
42
+ If set as a string, the account must grant the originating account
43
+ the Service Account Token Creator IAM role.
44
+ If set as a sequence, the identities from the list must grant
45
+ Service Account Token Creator IAM role to the directly preceding identity, with first
46
+ account from the list granting this role to the originating account (templated).
47
+ :param polling_interval_seconds: polling period in seconds to check for the status.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ job_id: str | None,
53
+ data_scan_id: str,
54
+ project_id: str | None,
55
+ region: str,
56
+ gcp_conn_id: str = "google_cloud_default",
57
+ polling_interval_seconds: int = 10,
58
+ impersonation_chain: str | Sequence[str] | None = None,
59
+ **kwargs,
60
+ ):
61
+
62
+ super().__init__(**kwargs)
63
+ self.job_id = job_id
64
+ self.data_scan_id = data_scan_id
65
+ self.project_id = project_id
66
+ self.region = region
67
+ self.gcp_conn_id = gcp_conn_id
68
+ self.polling_interval_seconds = polling_interval_seconds
69
+ self.impersonation_chain = impersonation_chain
70
+
71
+ def serialize(self):
72
+ return (
73
+ "airflow.providers.google.cloud.triggers.dataplex.DataplexDataQualityJobTrigger",
74
+ {
75
+ "job_id": self.job_id,
76
+ "data_scan_id": self.data_scan_id,
77
+ "project_id": self.project_id,
78
+ "region": self.region,
79
+ "gcp_conn_id": self.gcp_conn_id,
80
+ "impersonation_chain": self.impersonation_chain,
81
+ "polling_interval_seconds": self.polling_interval_seconds,
82
+ },
83
+ )
84
+
85
+ async def run(self) -> AsyncIterator[TriggerEvent]:
86
+ hook = DataplexAsyncHook(
87
+ gcp_conn_id=self.gcp_conn_id,
88
+ impersonation_chain=self.impersonation_chain,
89
+ )
90
+ while True:
91
+ job = await hook.get_data_scan_job(
92
+ project_id=self.project_id,
93
+ region=self.region,
94
+ job_id=self.job_id,
95
+ data_scan_id=self.data_scan_id,
96
+ )
97
+ state = job.state
98
+ if state in (DataScanJob.State.FAILED, DataScanJob.State.SUCCEEDED, DataScanJob.State.CANCELLED):
99
+ break
100
+ self.log.info(
101
+ "Current state is: %s, sleeping for %s seconds.",
102
+ DataScanJob.State(state).name,
103
+ self.polling_interval_seconds,
104
+ )
105
+ await asyncio.sleep(self.polling_interval_seconds)
106
+ yield TriggerEvent({"job_id": self.job_id, "job_state": state, "job": self._convert_to_dict(job)})
107
+
108
+ def _convert_to_dict(self, job: DataScanJob) -> dict:
109
+ """Returns a representation of a DataScanJob instance as a dict."""
110
+ return DataScanJob.to_dict(job)
@@ -263,8 +263,8 @@ class DataprocDeleteClusterTrigger(DataprocBaseTrigger):
263
263
 
264
264
  async def run(self) -> AsyncIterator[TriggerEvent]:
265
265
  """Wait until cluster is deleted completely."""
266
- while self.end_time > time.time():
267
- try:
266
+ try:
267
+ while self.end_time > time.time():
268
268
  cluster = await self.get_async_hook().get_cluster(
269
269
  region=self.region, # type: ignore[arg-type]
270
270
  cluster_name=self.cluster_name,
@@ -277,13 +277,12 @@ class DataprocDeleteClusterTrigger(DataprocBaseTrigger):
277
277
  self.polling_interval_seconds,
278
278
  )
279
279
  await asyncio.sleep(self.polling_interval_seconds)
280
- except NotFound:
281
- yield TriggerEvent({"status": "success", "message": ""})
282
- return
283
- except Exception as e:
284
- yield TriggerEvent({"status": "error", "message": str(e)})
285
- return
286
- yield TriggerEvent({"status": "error", "message": "Timeout"})
280
+ except NotFound:
281
+ yield TriggerEvent({"status": "success", "message": ""})
282
+ except Exception as e:
283
+ yield TriggerEvent({"status": "error", "message": str(e)})
284
+ else:
285
+ yield TriggerEvent({"status": "error", "message": "Timeout"})
287
286
 
288
287
 
289
288
  class DataprocWorkflowTrigger(DataprocBaseTrigger):
@@ -312,8 +311,8 @@ class DataprocWorkflowTrigger(DataprocBaseTrigger):
312
311
 
313
312
  async def run(self) -> AsyncIterator[TriggerEvent]:
314
313
  hook = self.get_async_hook()
315
- while True:
316
- try:
314
+ try:
315
+ while True:
317
316
  operation = await hook.get_operation(region=self.region, operation_name=self.name)
318
317
  if operation.done:
319
318
  if operation.error.message:
@@ -338,12 +337,11 @@ class DataprocWorkflowTrigger(DataprocBaseTrigger):
338
337
  else:
339
338
  self.log.info("Sleeping for %s seconds.", self.polling_interval_seconds)
340
339
  await asyncio.sleep(self.polling_interval_seconds)
341
- except Exception as e:
342
- self.log.exception("Exception occurred while checking operation status.")
343
- yield TriggerEvent(
344
- {
345
- "status": "failed",
346
- "message": str(e),
347
- }
348
- )
349
- return
340
+ except Exception as e:
341
+ self.log.exception("Exception occurred while checking operation status.")
342
+ yield TriggerEvent(
343
+ {
344
+ "status": "failed",
345
+ "message": str(e),
346
+ }
347
+ )
@@ -19,8 +19,7 @@ from __future__ import annotations
19
19
 
20
20
  import asyncio
21
21
  import warnings
22
- from datetime import datetime
23
- from typing import Any, AsyncIterator, Sequence
22
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Sequence
24
23
 
25
24
  from google.cloud.container_v1.types import Operation
26
25
 
@@ -35,6 +34,9 @@ except ImportError:
35
34
  from airflow.providers.google.cloud.hooks.kubernetes_engine import GKEAsyncHook, GKEPodAsyncHook
36
35
  from airflow.triggers.base import BaseTrigger, TriggerEvent
37
36
 
37
+ if TYPE_CHECKING:
38
+ from datetime import datetime
39
+
38
40
 
39
41
  class GKEStartPodTrigger(KubernetesPodTrigger):
40
42
  """
@@ -182,8 +184,8 @@ class GKEOperationTrigger(BaseTrigger):
182
184
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
183
185
  """Gets operation status and yields corresponding event."""
184
186
  hook = self._get_hook()
185
- while True:
186
- try:
187
+ try:
188
+ while True:
187
189
  operation = await hook.get_operation(
188
190
  operation_name=self.operation_name,
189
191
  project_id=self.project_id,
@@ -212,15 +214,14 @@ class GKEOperationTrigger(BaseTrigger):
212
214
  }
213
215
  )
214
216
  return
215
- except Exception as e:
216
- self.log.exception("Exception occurred while checking operation status")
217
- yield TriggerEvent(
218
- {
219
- "status": "error",
220
- "message": str(e),
221
- }
222
- )
223
- return
217
+ except Exception as e:
218
+ self.log.exception("Exception occurred while checking operation status")
219
+ yield TriggerEvent(
220
+ {
221
+ "status": "error",
222
+ "message": str(e),
223
+ }
224
+ )
224
225
 
225
226
  def _get_hook(self) -> GKEAsyncHook:
226
227
  if self._hook is None:
@@ -91,8 +91,8 @@ class MLEngineStartTrainingJobTrigger(BaseTrigger):
91
91
  async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
92
92
  """Gets current job execution status and yields a TriggerEvent."""
93
93
  hook = self._get_async_hook()
94
- while True:
95
- try:
94
+ try:
95
+ while True:
96
96
  # Poll for job execution status
97
97
  response_from_hook = await hook.get_job_status(job_id=self.job_id, project_id=self.project_id)
98
98
  if response_from_hook == "success":
@@ -110,9 +110,9 @@ class MLEngineStartTrainingJobTrigger(BaseTrigger):
110
110
  else:
111
111
  yield TriggerEvent({"status": "error", "message": response_from_hook})
112
112
 
113
- except Exception as e:
114
- self.log.exception("Exception occurred while checking for query completion")
115
- yield TriggerEvent({"status": "error", "message": str(e)})
113
+ except Exception as e:
114
+ self.log.exception("Exception occurred while checking for query completion")
115
+ yield TriggerEvent({"status": "error", "message": str(e)})
116
116
 
117
117
  def _get_async_hook(self) -> MLEngineAsyncHook:
118
118
  return MLEngineAsyncHook(
@@ -20,12 +20,12 @@ from __future__ import annotations
20
20
  import asyncio
21
21
  from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Sequence
22
22
 
23
- from google.cloud.pubsub_v1.types import ReceivedMessage
24
-
25
23
  from airflow.providers.google.cloud.hooks.pubsub import PubSubAsyncHook
26
24
  from airflow.triggers.base import BaseTrigger, TriggerEvent
27
25
 
28
26
  if TYPE_CHECKING:
27
+ from google.cloud.pubsub_v1.types import ReceivedMessage
28
+
29
29
  from airflow.utils.context import Context
30
30
 
31
31
 
@@ -16,12 +16,15 @@
16
16
  # under the License.
17
17
  from __future__ import annotations
18
18
 
19
- from collections.abc import Iterator
20
- from logging import Logger
19
+ from typing import TYPE_CHECKING
21
20
 
22
21
  from google.cloud.bigquery.table import Row, RowIterator
23
22
 
24
- from airflow.providers.google.cloud.hooks.bigquery import BigQueryHook
23
+ if TYPE_CHECKING:
24
+ from collections.abc import Iterator
25
+ from logging import Logger
26
+
27
+ from airflow.providers.google.cloud.hooks.bigquery import BigQueryHook
25
28
 
26
29
 
27
30
  def bigquery_get_data(
@@ -21,7 +21,7 @@ from __future__ import annotations
21
21
 
22
22
  import json
23
23
  import logging
24
- import os.path
24
+ import os
25
25
  import tempfile
26
26
  from contextlib import ExitStack, contextmanager
27
27
  from typing import Collection, Generator, Sequence