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
@@ -21,7 +21,7 @@
21
21
  from __future__ import annotations
22
22
 
23
23
  from collections.abc import Sequence
24
- from typing import TYPE_CHECKING
24
+ from typing import TYPE_CHECKING, Any
25
25
 
26
26
  from google.api_core.exceptions import NotFound
27
27
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
@@ -39,7 +39,7 @@ if TYPE_CHECKING:
39
39
  from google.api_core.retry import Retry
40
40
  from google.protobuf.field_mask_pb2 import FieldMask
41
41
 
42
- from airflow.utils.context import Context
42
+ from airflow.providers.common.compat.sdk import Context
43
43
 
44
44
 
45
45
  class CreateEndpointOperator(GoogleCloudBaseOperator):
@@ -93,6 +93,13 @@ class CreateEndpointOperator(GoogleCloudBaseOperator):
93
93
  self.gcp_conn_id = gcp_conn_id
94
94
  self.impersonation_chain = impersonation_chain
95
95
 
96
+ @property
97
+ def extra_links_params(self) -> dict[str, Any]:
98
+ return {
99
+ "region": self.region,
100
+ "project_id": self.project_id,
101
+ }
102
+
96
103
  def execute(self, context: Context):
97
104
  hook = EndpointServiceHook(
98
105
  gcp_conn_id=self.gcp_conn_id,
@@ -115,8 +122,8 @@ class CreateEndpointOperator(GoogleCloudBaseOperator):
115
122
  endpoint_id = hook.extract_endpoint_id(endpoint)
116
123
  self.log.info("Endpoint was created. Endpoint ID: %s", endpoint_id)
117
124
 
118
- self.xcom_push(context, key="endpoint_id", value=endpoint_id)
119
- VertexAIEndpointLink.persist(context=context, task_instance=self, endpoint_id=endpoint_id)
125
+ context["ti"].xcom_push(key="endpoint_id", value=endpoint_id)
126
+ VertexAIEndpointLink.persist(context=context, endpoint_id=endpoint_id)
120
127
  return endpoint
121
128
 
122
129
 
@@ -255,6 +262,13 @@ class DeployModelOperator(GoogleCloudBaseOperator):
255
262
  self.gcp_conn_id = gcp_conn_id
256
263
  self.impersonation_chain = impersonation_chain
257
264
 
265
+ @property
266
+ def extra_links_params(self) -> dict[str, Any]:
267
+ return {
268
+ "region": self.region,
269
+ "project_id": self.project_id,
270
+ }
271
+
258
272
  def execute(self, context: Context):
259
273
  hook = EndpointServiceHook(
260
274
  gcp_conn_id=self.gcp_conn_id,
@@ -278,8 +292,8 @@ class DeployModelOperator(GoogleCloudBaseOperator):
278
292
  deployed_model_id = hook.extract_deployed_model_id(deploy_model)
279
293
  self.log.info("Model was deployed. Deployed Model ID: %s", deployed_model_id)
280
294
 
281
- self.xcom_push(context, key="deployed_model_id", value=deployed_model_id)
282
- VertexAIModelLink.persist(context=context, task_instance=self, model_id=deployed_model_id)
295
+ context["ti"].xcom_push(key="deployed_model_id", value=deployed_model_id)
296
+ VertexAIModelLink.persist(context=context, model_id=deployed_model_id)
283
297
  return deploy_model
284
298
 
285
299
 
@@ -330,6 +344,13 @@ class GetEndpointOperator(GoogleCloudBaseOperator):
330
344
  self.gcp_conn_id = gcp_conn_id
331
345
  self.impersonation_chain = impersonation_chain
332
346
 
347
+ @property
348
+ def extra_links_params(self) -> dict[str, Any]:
349
+ return {
350
+ "region": self.region,
351
+ "project_id": self.project_id,
352
+ }
353
+
333
354
  def execute(self, context: Context):
334
355
  hook = EndpointServiceHook(
335
356
  gcp_conn_id=self.gcp_conn_id,
@@ -346,7 +367,7 @@ class GetEndpointOperator(GoogleCloudBaseOperator):
346
367
  timeout=self.timeout,
347
368
  metadata=self.metadata,
348
369
  )
349
- VertexAIEndpointLink.persist(context=context, task_instance=self, endpoint_id=self.endpoint_id)
370
+ VertexAIEndpointLink.persist(context=context, endpoint_id=self.endpoint_id)
350
371
  self.log.info("Endpoint was gotten.")
351
372
  return Endpoint.to_dict(endpoint_obj)
352
373
  except NotFound:
@@ -429,6 +450,12 @@ class ListEndpointsOperator(GoogleCloudBaseOperator):
429
450
  self.gcp_conn_id = gcp_conn_id
430
451
  self.impersonation_chain = impersonation_chain
431
452
 
453
+ @property
454
+ def extra_links_params(self) -> dict[str, Any]:
455
+ return {
456
+ "project_id": self.project_id,
457
+ }
458
+
432
459
  def execute(self, context: Context):
433
460
  hook = EndpointServiceHook(
434
461
  gcp_conn_id=self.gcp_conn_id,
@@ -446,7 +473,7 @@ class ListEndpointsOperator(GoogleCloudBaseOperator):
446
473
  timeout=self.timeout,
447
474
  metadata=self.metadata,
448
475
  )
449
- VertexAIEndpointListLink.persist(context=context, task_instance=self)
476
+ VertexAIEndpointListLink.persist(context=context)
450
477
  return [Endpoint.to_dict(result) for result in results]
451
478
 
452
479
 
@@ -582,6 +609,13 @@ class UpdateEndpointOperator(GoogleCloudBaseOperator):
582
609
  self.gcp_conn_id = gcp_conn_id
583
610
  self.impersonation_chain = impersonation_chain
584
611
 
612
+ @property
613
+ def extra_links_params(self) -> dict[str, Any]:
614
+ return {
615
+ "region": self.region,
616
+ "project_id": self.project_id,
617
+ }
618
+
585
619
  def execute(self, context: Context):
586
620
  hook = EndpointServiceHook(
587
621
  gcp_conn_id=self.gcp_conn_id,
@@ -599,5 +633,5 @@ class UpdateEndpointOperator(GoogleCloudBaseOperator):
599
633
  metadata=self.metadata,
600
634
  )
601
635
  self.log.info("Endpoint was updated")
602
- VertexAIEndpointLink.persist(context=context, task_instance=self, endpoint_id=self.endpoint_id)
636
+ VertexAIEndpointLink.persist(context=context, endpoint_id=self.endpoint_id)
603
637
  return Endpoint.to_dict(result)
@@ -0,0 +1,435 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ from __future__ import annotations
19
+
20
+ from collections.abc import Sequence
21
+ from typing import TYPE_CHECKING
22
+
23
+ from google.api_core import exceptions
24
+
25
+ from airflow.exceptions import AirflowException
26
+ from airflow.providers.google.cloud.hooks.vertex_ai.experiment_service import (
27
+ ExperimentHook,
28
+ ExperimentRunHook,
29
+ )
30
+ from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
31
+
32
+ if TYPE_CHECKING:
33
+ from airflow.providers.common.compat.sdk import Context
34
+
35
+
36
+ class CreateExperimentOperator(GoogleCloudBaseOperator):
37
+ """
38
+ Use the Vertex AI SDK to create experiment.
39
+
40
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
41
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
42
+ :param experiment_name: Required. The name of the evaluation experiment.
43
+ :param experiment_description: Optional. Description of the evaluation experiment.
44
+ :param experiment_tensorboard: Optional. The Vertex TensorBoard instance to use as a backing
45
+ TensorBoard for the provided experiment. If no TensorBoard is provided, a default TensorBoard
46
+ instance is created and used by this experiment.
47
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
48
+ :param impersonation_chain: Optional service account to impersonate using short-term
49
+ credentials, or chained list of accounts required to get the access_token
50
+ of the last account in the list, which will be impersonated in the request.
51
+ If set as a string, the account must grant the originating account
52
+ the Service Account Token Creator IAM role.
53
+ If set as a sequence, the identities from the list must grant
54
+ Service Account Token Creator IAM role to the directly preceding identity, with first
55
+ account from the list granting this role to the originating account (templated).
56
+ """
57
+
58
+ template_fields = (
59
+ "location",
60
+ "project_id",
61
+ "impersonation_chain",
62
+ "experiment_name",
63
+ )
64
+
65
+ def __init__(
66
+ self,
67
+ *,
68
+ project_id: str,
69
+ location: str,
70
+ experiment_name: str,
71
+ experiment_description: str = "",
72
+ gcp_conn_id: str = "google_cloud_default",
73
+ impersonation_chain: str | Sequence[str] | None = None,
74
+ experiment_tensorboard: str | None = None,
75
+ **kwargs,
76
+ ) -> None:
77
+ super().__init__(**kwargs)
78
+ self.project_id = project_id
79
+ self.location = location
80
+ self.experiment_name = experiment_name
81
+ self.experiment_description = experiment_description
82
+ self.experiment_tensorboard = experiment_tensorboard
83
+ self.gcp_conn_id = gcp_conn_id
84
+ self.impersonation_chain = impersonation_chain
85
+
86
+ def execute(self, context: Context) -> None:
87
+ self.hook = ExperimentHook(
88
+ gcp_conn_id=self.gcp_conn_id,
89
+ impersonation_chain=self.impersonation_chain,
90
+ )
91
+
92
+ try:
93
+ self.hook.create_experiment(
94
+ project_id=self.project_id,
95
+ location=self.location,
96
+ experiment_name=self.experiment_name,
97
+ experiment_description=self.experiment_description,
98
+ experiment_tensorboard=self.experiment_tensorboard,
99
+ )
100
+ except exceptions.AlreadyExists:
101
+ raise AirflowException(f"Experiment with name {self.experiment_name} already exist")
102
+
103
+ self.log.info("Created experiment: %s", self.experiment_name)
104
+
105
+
106
+ class DeleteExperimentOperator(GoogleCloudBaseOperator):
107
+ """
108
+ Use the Vertex AI SDK to delete experiment.
109
+
110
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
111
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
112
+ :param experiment_name: Required. The name of the evaluation experiment.
113
+ :param delete_backing_tensorboard_runs: Optional. If True will also delete the Vertex AI TensorBoard
114
+ runs associated with the experiment runs under this experiment that we used to store time series
115
+ metrics.
116
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
117
+ :param impersonation_chain: Optional service account to impersonate using short-term
118
+ credentials, or chained list of accounts required to get the access_token
119
+ of the last account in the list, which will be impersonated in the request.
120
+ If set as a string, the account must grant the originating account
121
+ the Service Account Token Creator IAM role.
122
+ If set as a sequence, the identities from the list must grant
123
+ Service Account Token Creator IAM role to the directly preceding identity, with first
124
+ account from the list granting this role to the originating account (templated).
125
+ """
126
+
127
+ template_fields = (
128
+ "location",
129
+ "project_id",
130
+ "impersonation_chain",
131
+ "experiment_name",
132
+ )
133
+
134
+ def __init__(
135
+ self,
136
+ *,
137
+ project_id: str,
138
+ location: str,
139
+ experiment_name: str,
140
+ delete_backing_tensorboard_runs: bool = False,
141
+ gcp_conn_id: str = "google_cloud_default",
142
+ impersonation_chain: str | Sequence[str] | None = None,
143
+ **kwargs,
144
+ ) -> None:
145
+ super().__init__(**kwargs)
146
+ self.project_id = project_id
147
+ self.location = location
148
+ self.experiment_name = experiment_name
149
+ self.delete_backing_tensorboard_runs = delete_backing_tensorboard_runs
150
+ self.gcp_conn_id = gcp_conn_id
151
+ self.impersonation_chain = impersonation_chain
152
+
153
+ def execute(self, context: Context) -> None:
154
+ self.hook = ExperimentHook(
155
+ gcp_conn_id=self.gcp_conn_id,
156
+ impersonation_chain=self.impersonation_chain,
157
+ )
158
+
159
+ try:
160
+ self.hook.delete_experiment(
161
+ project_id=self.project_id,
162
+ location=self.location,
163
+ experiment_name=self.experiment_name,
164
+ delete_backing_tensorboard_runs=self.delete_backing_tensorboard_runs,
165
+ )
166
+ except exceptions.NotFound:
167
+ raise AirflowException(f"Experiment with name {self.experiment_name} not found")
168
+
169
+ self.log.info("Deleted experiment: %s", self.experiment_name)
170
+
171
+
172
+ class CreateExperimentRunOperator(GoogleCloudBaseOperator):
173
+ """
174
+ Use the Vertex AI SDK to create experiment run.
175
+
176
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
177
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
178
+ :param experiment_name: Required. The name of the evaluation experiment.
179
+ :param experiment_run_name: Required. The specific run name or ID for this experiment.
180
+ :param experiment_run_tensorboard: Optional. A backing TensorBoard resource to enable and store time series
181
+ metrics logged to this experiment run using log_time_series_metrics.
182
+ :param run_after_creation: Optional. If True experiment run will be created with state running.
183
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
184
+ :param impersonation_chain: Optional service account to impersonate using short-term
185
+ credentials, or chained list of accounts required to get the access_token
186
+ of the last account in the list, which will be impersonated in the request.
187
+ If set as a string, the account must grant the originating account
188
+ the Service Account Token Creator IAM role.
189
+ If set as a sequence, the identities from the list must grant
190
+ Service Account Token Creator IAM role to the directly preceding identity, with first
191
+ account from the list granting this role to the originating account (templated).
192
+ """
193
+
194
+ template_fields = (
195
+ "location",
196
+ "project_id",
197
+ "impersonation_chain",
198
+ "experiment_name",
199
+ "experiment_run_name",
200
+ )
201
+
202
+ def __init__(
203
+ self,
204
+ *,
205
+ project_id: str,
206
+ location: str,
207
+ experiment_name: str,
208
+ experiment_run_name: str,
209
+ experiment_run_tensorboard: str | None = None,
210
+ run_after_creation: bool = False,
211
+ gcp_conn_id: str = "google_cloud_default",
212
+ impersonation_chain: str | Sequence[str] | None = None,
213
+ **kwargs,
214
+ ) -> None:
215
+ super().__init__(**kwargs)
216
+ self.project_id = project_id
217
+ self.location = location
218
+ self.experiment_name = experiment_name
219
+ self.experiment_run_name = experiment_run_name
220
+ self.experiment_run_tensorboard = experiment_run_tensorboard
221
+ self.run_after_creation = run_after_creation
222
+ self.gcp_conn_id = gcp_conn_id
223
+ self.impersonation_chain = impersonation_chain
224
+
225
+ def execute(self, context: Context) -> None:
226
+ self.hook = ExperimentRunHook(
227
+ gcp_conn_id=self.gcp_conn_id,
228
+ impersonation_chain=self.impersonation_chain,
229
+ )
230
+
231
+ try:
232
+ self.hook.create_experiment_run(
233
+ project_id=self.project_id,
234
+ location=self.location,
235
+ experiment_name=self.experiment_name,
236
+ experiment_run_name=self.experiment_run_name,
237
+ experiment_run_tensorboard=self.experiment_run_tensorboard,
238
+ run_after_creation=self.run_after_creation,
239
+ )
240
+ except exceptions.AlreadyExists:
241
+ raise AirflowException(f"Experiment Run with name {self.experiment_run_name} already exist")
242
+
243
+ self.log.info("Created experiment run: %s", self.experiment_run_name)
244
+
245
+
246
+ class ListExperimentRunsOperator(GoogleCloudBaseOperator):
247
+ """
248
+ Use the Vertex AI SDK to list experiment runs in experiment.
249
+
250
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
251
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
252
+ :param experiment_name: Required. The name of the evaluation experiment.
253
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
254
+ :param impersonation_chain: Optional service account to impersonate using short-term
255
+ credentials, or chained list of accounts required to get the access_token
256
+ of the last account in the list, which will be impersonated in the request.
257
+ If set as a string, the account must grant the originating account
258
+ the Service Account Token Creator IAM role.
259
+ If set as a sequence, the identities from the list must grant
260
+ Service Account Token Creator IAM role to the directly preceding identity, with first
261
+ account from the list granting this role to the originating account (templated).
262
+ """
263
+
264
+ template_fields = (
265
+ "location",
266
+ "project_id",
267
+ "impersonation_chain",
268
+ "experiment_name",
269
+ )
270
+
271
+ def __init__(
272
+ self,
273
+ *,
274
+ project_id: str,
275
+ location: str,
276
+ experiment_name: str,
277
+ gcp_conn_id: str = "google_cloud_default",
278
+ impersonation_chain: str | Sequence[str] | None = None,
279
+ **kwargs,
280
+ ):
281
+ super().__init__(**kwargs)
282
+ self.project_id = project_id
283
+ self.location = location
284
+ self.experiment_name = experiment_name
285
+ self.gcp_conn_id = gcp_conn_id
286
+ self.impersonation_chain = impersonation_chain
287
+
288
+ def execute(self, context: Context) -> list[str]:
289
+ self.hook = ExperimentRunHook(
290
+ gcp_conn_id=self.gcp_conn_id,
291
+ impersonation_chain=self.impersonation_chain,
292
+ )
293
+
294
+ try:
295
+ experiment_runs = self.hook.list_experiment_runs(
296
+ project_id=self.project_id, experiment_name=self.experiment_name, location=self.location
297
+ )
298
+ except exceptions.NotFound:
299
+ raise AirflowException("Experiment %s not found", self.experiment_name)
300
+
301
+ return [er.name for er in experiment_runs]
302
+
303
+
304
+ class UpdateExperimentRunStateOperator(GoogleCloudBaseOperator):
305
+ """
306
+ Use the Vertex AI SDK to update state of the experiment run.
307
+
308
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
309
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
310
+ :param experiment_name: Required. The name of the evaluation experiment.
311
+ :param experiment_run_name: Required. The specific run name or ID for this experiment.
312
+ :param new_state: Required. The specific state of experiment run.
313
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
314
+ :param impersonation_chain: Optional service account to impersonate using short-term
315
+ credentials, or chained list of accounts required to get the access_token
316
+ of the last account in the list, which will be impersonated in the request.
317
+ If set as a string, the account must grant the originating account
318
+ the Service Account Token Creator IAM role.
319
+ If set as a sequence, the identities from the list must grant
320
+ Service Account Token Creator IAM role to the directly preceding identity, with first
321
+ account from the list granting this role to the originating account (templated).
322
+ """
323
+
324
+ template_fields = (
325
+ "location",
326
+ "project_id",
327
+ "impersonation_chain",
328
+ "experiment_name",
329
+ "experiment_run_name",
330
+ "new_state",
331
+ )
332
+
333
+ def __init__(
334
+ self,
335
+ *,
336
+ project_id: str,
337
+ location: str,
338
+ experiment_name: str,
339
+ experiment_run_name: str,
340
+ new_state: int,
341
+ gcp_conn_id: str = "google_cloud_default",
342
+ impersonation_chain: str | Sequence[str] | None = None,
343
+ **kwargs,
344
+ ):
345
+ super().__init__(**kwargs)
346
+ self.project_id = project_id
347
+ self.location = location
348
+ self.experiment_name = experiment_name
349
+ self.experiment_run_name = experiment_run_name
350
+ self.gcp_conn_id = gcp_conn_id
351
+ self.impersonation_chain = impersonation_chain
352
+ self.new_state = new_state
353
+
354
+ def execute(self, context: Context) -> None:
355
+ self.hook = ExperimentRunHook(
356
+ gcp_conn_id=self.gcp_conn_id,
357
+ impersonation_chain=self.impersonation_chain,
358
+ )
359
+
360
+ try:
361
+ self.hook.update_experiment_run_state(
362
+ project_id=self.project_id,
363
+ experiment_name=self.experiment_name,
364
+ experiment_run_name=self.experiment_run_name,
365
+ new_state=self.new_state,
366
+ location=self.location,
367
+ )
368
+ self.log.info("New state of the %s is: %s", self.experiment_run_name, self.new_state)
369
+ except exceptions.NotFound:
370
+ raise AirflowException("Experiment or experiment run not found")
371
+
372
+
373
+ class DeleteExperimentRunOperator(GoogleCloudBaseOperator):
374
+ """
375
+ Use the Vertex AI SDK to delete experiment run.
376
+
377
+ :param project_id: Required. The ID of the Google Cloud project that the service belongs to.
378
+ :param location: Required. The ID of the Google Cloud location that the service belongs to.
379
+ :param experiment_name: Required. The name of the evaluation experiment.
380
+ :param experiment_run_name: Required. The specific run name or ID for this experiment.
381
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
382
+ :param impersonation_chain: Optional service account to impersonate using short-term
383
+ credentials, or chained list of accounts required to get the access_token
384
+ of the last account in the list, which will be impersonated in the request.
385
+ If set as a string, the account must grant the originating account
386
+ the Service Account Token Creator IAM role.
387
+ If set as a sequence, the identities from the list must grant
388
+ Service Account Token Creator IAM role to the directly preceding identity, with first
389
+ account from the list granting this role to the originating account (templated).
390
+ """
391
+
392
+ template_fields = (
393
+ "location",
394
+ "project_id",
395
+ "impersonation_chain",
396
+ "experiment_name",
397
+ "experiment_run_name",
398
+ )
399
+
400
+ def __init__(
401
+ self,
402
+ *,
403
+ project_id: str,
404
+ location: str,
405
+ experiment_name: str,
406
+ experiment_run_name: str,
407
+ gcp_conn_id: str = "google_cloud_default",
408
+ impersonation_chain: str | Sequence[str] | None = None,
409
+ **kwargs,
410
+ ) -> None:
411
+ super().__init__(**kwargs)
412
+ self.project_id = project_id
413
+ self.location = location
414
+ self.experiment_name = experiment_name
415
+ self.experiment_run_name = experiment_run_name
416
+ self.gcp_conn_id = gcp_conn_id
417
+ self.impersonation_chain = impersonation_chain
418
+
419
+ def execute(self, context: Context) -> None:
420
+ self.hook = ExperimentRunHook(
421
+ gcp_conn_id=self.gcp_conn_id,
422
+ impersonation_chain=self.impersonation_chain,
423
+ )
424
+
425
+ try:
426
+ self.hook.delete_experiment_run(
427
+ project_id=self.project_id,
428
+ location=self.location,
429
+ experiment_name=self.experiment_name,
430
+ experiment_run_name=self.experiment_run_name,
431
+ )
432
+ except exceptions.NotFound:
433
+ raise AirflowException(f"Experiment Run with name {self.experiment_run_name} not found")
434
+
435
+ self.log.info("Deleted experiment run: %s", self.experiment_run_name)