apache-airflow-providers-google 15.1.0rc1__py3-none-any.whl → 19.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airflow/providers/google/3rd-party-licenses/NOTICE +2 -12
- airflow/providers/google/__init__.py +3 -3
- airflow/providers/google/ads/hooks/ads.py +39 -6
- airflow/providers/google/ads/operators/ads.py +2 -2
- airflow/providers/google/ads/transfers/ads_to_gcs.py +2 -2
- airflow/providers/google/assets/gcs.py +1 -11
- airflow/providers/google/cloud/bundles/__init__.py +16 -0
- airflow/providers/google/cloud/bundles/gcs.py +161 -0
- airflow/providers/google/cloud/hooks/alloy_db.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +176 -293
- airflow/providers/google/cloud/hooks/cloud_batch.py +1 -1
- airflow/providers/google/cloud/hooks/cloud_build.py +1 -1
- airflow/providers/google/cloud/hooks/cloud_composer.py +288 -15
- airflow/providers/google/cloud/hooks/cloud_logging.py +109 -0
- airflow/providers/google/cloud/hooks/cloud_memorystore.py +1 -1
- airflow/providers/google/cloud/hooks/cloud_run.py +18 -10
- airflow/providers/google/cloud/hooks/cloud_sql.py +102 -23
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +29 -7
- airflow/providers/google/cloud/hooks/compute.py +1 -1
- airflow/providers/google/cloud/hooks/compute_ssh.py +6 -2
- airflow/providers/google/cloud/hooks/datacatalog.py +10 -1
- airflow/providers/google/cloud/hooks/dataflow.py +72 -95
- airflow/providers/google/cloud/hooks/dataform.py +1 -1
- airflow/providers/google/cloud/hooks/datafusion.py +21 -19
- airflow/providers/google/cloud/hooks/dataplex.py +2 -2
- airflow/providers/google/cloud/hooks/dataprep.py +1 -1
- airflow/providers/google/cloud/hooks/dataproc.py +73 -72
- airflow/providers/google/cloud/hooks/dataproc_metastore.py +1 -1
- airflow/providers/google/cloud/hooks/dlp.py +1 -1
- airflow/providers/google/cloud/hooks/functions.py +1 -1
- airflow/providers/google/cloud/hooks/gcs.py +112 -15
- airflow/providers/google/cloud/hooks/gdm.py +1 -1
- airflow/providers/google/cloud/hooks/gen_ai.py +196 -0
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +3 -3
- airflow/providers/google/cloud/hooks/looker.py +6 -2
- airflow/providers/google/cloud/hooks/managed_kafka.py +1 -1
- airflow/providers/google/cloud/hooks/mlengine.py +4 -3
- airflow/providers/google/cloud/hooks/pubsub.py +3 -0
- airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
- airflow/providers/google/cloud/hooks/spanner.py +74 -9
- airflow/providers/google/cloud/hooks/stackdriver.py +11 -9
- airflow/providers/google/cloud/hooks/tasks.py +1 -1
- airflow/providers/google/cloud/hooks/translate.py +2 -2
- airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +2 -210
- airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +3 -3
- airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +28 -2
- airflow/providers/google/cloud/hooks/vertex_ai/experiment_service.py +202 -0
- airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +308 -8
- airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +79 -75
- airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/ray.py +223 -0
- airflow/providers/google/cloud/hooks/vision.py +3 -3
- airflow/providers/google/cloud/hooks/workflows.py +1 -1
- airflow/providers/google/cloud/links/alloy_db.py +0 -46
- airflow/providers/google/cloud/links/base.py +77 -13
- airflow/providers/google/cloud/links/bigquery.py +0 -47
- airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
- airflow/providers/google/cloud/links/bigtable.py +0 -48
- airflow/providers/google/cloud/links/cloud_build.py +0 -73
- airflow/providers/google/cloud/links/cloud_functions.py +0 -33
- airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
- airflow/providers/google/cloud/links/{life_sciences.py → cloud_run.py} +5 -27
- airflow/providers/google/cloud/links/cloud_sql.py +0 -33
- airflow/providers/google/cloud/links/cloud_storage_transfer.py +17 -44
- airflow/providers/google/cloud/links/cloud_tasks.py +7 -26
- airflow/providers/google/cloud/links/compute.py +0 -58
- airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
- airflow/providers/google/cloud/links/datacatalog.py +23 -54
- airflow/providers/google/cloud/links/dataflow.py +0 -34
- airflow/providers/google/cloud/links/dataform.py +0 -64
- airflow/providers/google/cloud/links/datafusion.py +1 -96
- airflow/providers/google/cloud/links/dataplex.py +0 -154
- airflow/providers/google/cloud/links/dataprep.py +0 -24
- airflow/providers/google/cloud/links/dataproc.py +11 -95
- airflow/providers/google/cloud/links/datastore.py +0 -31
- airflow/providers/google/cloud/links/kubernetes_engine.py +9 -60
- airflow/providers/google/cloud/links/managed_kafka.py +0 -70
- airflow/providers/google/cloud/links/mlengine.py +0 -70
- airflow/providers/google/cloud/links/pubsub.py +0 -32
- airflow/providers/google/cloud/links/spanner.py +0 -33
- airflow/providers/google/cloud/links/stackdriver.py +0 -30
- airflow/providers/google/cloud/links/translate.py +17 -187
- airflow/providers/google/cloud/links/vertex_ai.py +28 -195
- airflow/providers/google/cloud/links/workflows.py +0 -52
- airflow/providers/google/cloud/log/gcs_task_handler.py +58 -22
- airflow/providers/google/cloud/log/stackdriver_task_handler.py +9 -6
- airflow/providers/google/cloud/openlineage/CloudStorageTransferJobFacet.json +68 -0
- airflow/providers/google/cloud/openlineage/CloudStorageTransferRunFacet.json +60 -0
- airflow/providers/google/cloud/openlineage/DataFusionRunFacet.json +32 -0
- airflow/providers/google/cloud/openlineage/facets.py +102 -1
- airflow/providers/google/cloud/openlineage/mixins.py +10 -8
- airflow/providers/google/cloud/openlineage/utils.py +15 -1
- airflow/providers/google/cloud/operators/alloy_db.py +71 -56
- airflow/providers/google/cloud/operators/bigquery.py +73 -636
- airflow/providers/google/cloud/operators/bigquery_dts.py +4 -6
- airflow/providers/google/cloud/operators/bigtable.py +37 -8
- airflow/providers/google/cloud/operators/cloud_base.py +21 -1
- airflow/providers/google/cloud/operators/cloud_batch.py +3 -3
- airflow/providers/google/cloud/operators/cloud_build.py +76 -33
- airflow/providers/google/cloud/operators/cloud_composer.py +129 -41
- airflow/providers/google/cloud/operators/cloud_logging_sink.py +341 -0
- airflow/providers/google/cloud/operators/cloud_memorystore.py +69 -43
- airflow/providers/google/cloud/operators/cloud_run.py +24 -6
- airflow/providers/google/cloud/operators/cloud_sql.py +8 -17
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +93 -12
- airflow/providers/google/cloud/operators/compute.py +9 -41
- airflow/providers/google/cloud/operators/datacatalog.py +157 -21
- airflow/providers/google/cloud/operators/dataflow.py +40 -16
- airflow/providers/google/cloud/operators/dataform.py +15 -5
- airflow/providers/google/cloud/operators/datafusion.py +42 -21
- airflow/providers/google/cloud/operators/dataplex.py +194 -110
- airflow/providers/google/cloud/operators/dataprep.py +1 -5
- airflow/providers/google/cloud/operators/dataproc.py +80 -36
- airflow/providers/google/cloud/operators/dataproc_metastore.py +97 -89
- airflow/providers/google/cloud/operators/datastore.py +23 -7
- airflow/providers/google/cloud/operators/dlp.py +6 -29
- airflow/providers/google/cloud/operators/functions.py +17 -8
- airflow/providers/google/cloud/operators/gcs.py +12 -9
- airflow/providers/google/cloud/operators/gen_ai.py +389 -0
- airflow/providers/google/cloud/operators/kubernetes_engine.py +62 -100
- airflow/providers/google/cloud/operators/looker.py +2 -2
- airflow/providers/google/cloud/operators/managed_kafka.py +108 -53
- airflow/providers/google/cloud/operators/natural_language.py +1 -1
- airflow/providers/google/cloud/operators/pubsub.py +68 -15
- airflow/providers/google/cloud/operators/spanner.py +26 -13
- airflow/providers/google/cloud/operators/speech_to_text.py +2 -3
- airflow/providers/google/cloud/operators/stackdriver.py +1 -9
- airflow/providers/google/cloud/operators/tasks.py +1 -12
- airflow/providers/google/cloud/operators/text_to_speech.py +2 -3
- airflow/providers/google/cloud/operators/translate.py +41 -17
- airflow/providers/google/cloud/operators/translate_speech.py +2 -3
- airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +39 -19
- airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +30 -10
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +55 -27
- airflow/providers/google/cloud/operators/vertex_ai/dataset.py +70 -8
- airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +43 -9
- airflow/providers/google/cloud/operators/vertex_ai/experiment_service.py +435 -0
- airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +532 -1
- airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +135 -115
- airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +12 -10
- airflow/providers/google/cloud/operators/vertex_ai/model_service.py +57 -11
- airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +31 -8
- airflow/providers/google/cloud/operators/vertex_ai/ray.py +393 -0
- airflow/providers/google/cloud/operators/video_intelligence.py +1 -1
- airflow/providers/google/cloud/operators/vision.py +2 -2
- airflow/providers/google/cloud/operators/workflows.py +18 -15
- airflow/providers/google/cloud/secrets/secret_manager.py +3 -2
- airflow/providers/google/cloud/sensors/bigquery.py +3 -3
- airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -3
- airflow/providers/google/cloud/sensors/bigtable.py +11 -4
- airflow/providers/google/cloud/sensors/cloud_composer.py +533 -30
- airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -3
- airflow/providers/google/cloud/sensors/dataflow.py +26 -10
- airflow/providers/google/cloud/sensors/dataform.py +2 -3
- airflow/providers/google/cloud/sensors/datafusion.py +4 -5
- airflow/providers/google/cloud/sensors/dataplex.py +2 -3
- airflow/providers/google/cloud/sensors/dataprep.py +2 -2
- airflow/providers/google/cloud/sensors/dataproc.py +2 -3
- airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -3
- airflow/providers/google/cloud/sensors/gcs.py +4 -5
- airflow/providers/google/cloud/sensors/looker.py +2 -3
- airflow/providers/google/cloud/sensors/pubsub.py +4 -5
- airflow/providers/google/cloud/sensors/tasks.py +2 -2
- airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +2 -3
- airflow/providers/google/cloud/sensors/workflows.py +2 -3
- airflow/providers/google/cloud/transfers/adls_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +4 -3
- airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +11 -8
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +10 -5
- airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +7 -3
- airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +12 -1
- airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +24 -10
- airflow/providers/google/cloud/transfers/bigquery_to_sql.py +104 -5
- airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +3 -3
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +4 -4
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +21 -13
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +4 -3
- airflow/providers/google/cloud/transfers/gcs_to_local.py +6 -4
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +11 -5
- airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +6 -2
- airflow/providers/google/cloud/transfers/gdrive_to_local.py +2 -2
- airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
- airflow/providers/google/cloud/transfers/local_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/oracle_to_gcs.py +36 -11
- airflow/providers/google/cloud/transfers/postgres_to_gcs.py +42 -9
- airflow/providers/google/cloud/transfers/s3_to_gcs.py +13 -7
- airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/sftp_to_gcs.py +14 -5
- airflow/providers/google/cloud/transfers/sheets_to_gcs.py +3 -3
- airflow/providers/google/cloud/transfers/sql_to_gcs.py +10 -10
- airflow/providers/google/cloud/triggers/bigquery.py +76 -35
- airflow/providers/google/cloud/triggers/cloud_build.py +1 -1
- airflow/providers/google/cloud/triggers/cloud_composer.py +303 -47
- airflow/providers/google/cloud/triggers/cloud_run.py +3 -3
- airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +92 -2
- airflow/providers/google/cloud/triggers/dataflow.py +122 -0
- airflow/providers/google/cloud/triggers/datafusion.py +1 -1
- airflow/providers/google/cloud/triggers/dataplex.py +14 -2
- airflow/providers/google/cloud/triggers/dataproc.py +123 -53
- airflow/providers/google/cloud/triggers/kubernetes_engine.py +47 -28
- airflow/providers/google/cloud/triggers/mlengine.py +1 -1
- airflow/providers/google/cloud/triggers/pubsub.py +15 -19
- airflow/providers/google/cloud/triggers/vertex_ai.py +1 -1
- airflow/providers/google/cloud/utils/bigquery_get_data.py +1 -1
- airflow/providers/google/cloud/utils/credentials_provider.py +2 -2
- airflow/providers/google/cloud/utils/field_sanitizer.py +1 -1
- airflow/providers/google/cloud/utils/field_validator.py +2 -3
- airflow/providers/google/common/auth_backend/google_openid.py +4 -4
- airflow/providers/google/common/deprecated.py +2 -1
- airflow/providers/google/common/hooks/base_google.py +27 -9
- airflow/providers/google/common/hooks/operation_helpers.py +1 -1
- airflow/providers/google/common/links/storage.py +0 -22
- airflow/providers/google/common/utils/get_secret.py +31 -0
- airflow/providers/google/common/utils/id_token_credentials.py +3 -4
- airflow/providers/google/firebase/hooks/firestore.py +1 -1
- airflow/providers/google/firebase/operators/firestore.py +3 -3
- airflow/providers/google/get_provider_info.py +56 -52
- airflow/providers/google/go_module_utils.py +35 -3
- airflow/providers/google/leveldb/hooks/leveldb.py +27 -2
- airflow/providers/google/leveldb/operators/leveldb.py +2 -2
- airflow/providers/google/marketing_platform/hooks/campaign_manager.py +1 -1
- airflow/providers/google/marketing_platform/hooks/display_video.py +3 -109
- airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -1
- airflow/providers/google/marketing_platform/links/analytics_admin.py +5 -14
- airflow/providers/google/marketing_platform/operators/analytics_admin.py +2 -3
- airflow/providers/google/marketing_platform/operators/campaign_manager.py +6 -6
- airflow/providers/google/marketing_platform/operators/display_video.py +28 -489
- airflow/providers/google/marketing_platform/operators/search_ads.py +2 -2
- airflow/providers/google/marketing_platform/sensors/campaign_manager.py +2 -2
- airflow/providers/google/marketing_platform/sensors/display_video.py +3 -64
- airflow/providers/google/suite/hooks/calendar.py +2 -2
- airflow/providers/google/suite/hooks/sheets.py +16 -2
- airflow/providers/google/suite/operators/sheets.py +8 -3
- airflow/providers/google/suite/sensors/drive.py +2 -2
- airflow/providers/google/suite/transfers/gcs_to_gdrive.py +3 -3
- airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
- airflow/providers/google/suite/transfers/local_to_drive.py +3 -3
- airflow/providers/google/suite/transfers/sql_to_sheets.py +5 -4
- airflow/providers/google/version_compat.py +15 -1
- {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/METADATA +90 -46
- apache_airflow_providers_google-19.3.0.dist-info/RECORD +331 -0
- apache_airflow_providers_google-19.3.0.dist-info/licenses/NOTICE +5 -0
- airflow/providers/google/cloud/hooks/automl.py +0 -673
- airflow/providers/google/cloud/hooks/life_sciences.py +0 -159
- airflow/providers/google/cloud/links/automl.py +0 -193
- airflow/providers/google/cloud/operators/automl.py +0 -1362
- airflow/providers/google/cloud/operators/life_sciences.py +0 -119
- airflow/providers/google/cloud/operators/mlengine.py +0 -112
- apache_airflow_providers_google-15.1.0rc1.dist-info/RECORD +0 -321
- {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/entry_points.txt +0 -0
- {airflow/providers/google → apache_airflow_providers_google-19.3.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -28,7 +28,7 @@ from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
|
|
|
28
28
|
from google.cloud.aiplatform_v1 import types
|
|
29
29
|
|
|
30
30
|
from airflow.configuration import conf
|
|
31
|
-
from airflow.
|
|
31
|
+
from airflow.providers.common.compat.sdk import AirflowException
|
|
32
32
|
from airflow.providers.google.cloud.hooks.vertex_ai.pipeline_job import PipelineJobHook
|
|
33
33
|
from airflow.providers.google.cloud.links.vertex_ai import (
|
|
34
34
|
VertexAIPipelineJobLink,
|
|
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
|
|
|
42
42
|
from google.cloud.aiplatform import PipelineJob
|
|
43
43
|
from google.cloud.aiplatform.metadata import experiment_resources
|
|
44
44
|
|
|
45
|
-
from airflow.
|
|
45
|
+
from airflow.providers.common.compat.sdk import Context
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class RunPipelineJobOperator(GoogleCloudBaseOperator):
|
|
@@ -112,6 +112,10 @@ class RunPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
112
112
|
"project_id",
|
|
113
113
|
"input_artifacts",
|
|
114
114
|
"impersonation_chain",
|
|
115
|
+
"template_path",
|
|
116
|
+
"pipeline_root",
|
|
117
|
+
"parameter_values",
|
|
118
|
+
"service_account",
|
|
115
119
|
]
|
|
116
120
|
operator_extra_links = (VertexAIPipelineJobLink(),)
|
|
117
121
|
|
|
@@ -162,6 +166,13 @@ class RunPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
162
166
|
self.deferrable = deferrable
|
|
163
167
|
self.poll_interval = poll_interval
|
|
164
168
|
|
|
169
|
+
@property
|
|
170
|
+
def extra_links_params(self) -> dict[str, Any]:
|
|
171
|
+
return {
|
|
172
|
+
"region": self.region,
|
|
173
|
+
"project_id": self.project_id,
|
|
174
|
+
}
|
|
175
|
+
|
|
165
176
|
def execute(self, context: Context):
|
|
166
177
|
self.log.info("Running Pipeline job")
|
|
167
178
|
pipeline_job_obj: PipelineJob = self.hook.submit_pipeline_job(
|
|
@@ -184,8 +195,8 @@ class RunPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
184
195
|
)
|
|
185
196
|
pipeline_job_id = pipeline_job_obj.job_id
|
|
186
197
|
self.log.info("Pipeline job was created. Job id: %s", pipeline_job_id)
|
|
187
|
-
|
|
188
|
-
VertexAIPipelineJobLink.persist(context=context,
|
|
198
|
+
context["ti"].xcom_push(key="pipeline_job_id", value=pipeline_job_id)
|
|
199
|
+
VertexAIPipelineJobLink.persist(context=context, pipeline_id=pipeline_job_id)
|
|
189
200
|
|
|
190
201
|
if self.deferrable:
|
|
191
202
|
pipeline_job_obj.wait_for_resource_creation()
|
|
@@ -276,6 +287,13 @@ class GetPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
276
287
|
self.gcp_conn_id = gcp_conn_id
|
|
277
288
|
self.impersonation_chain = impersonation_chain
|
|
278
289
|
|
|
290
|
+
@property
|
|
291
|
+
def extra_links_params(self) -> dict[str, Any]:
|
|
292
|
+
return {
|
|
293
|
+
"region": self.region,
|
|
294
|
+
"project_id": self.project_id,
|
|
295
|
+
}
|
|
296
|
+
|
|
279
297
|
def execute(self, context: Context):
|
|
280
298
|
hook = PipelineJobHook(
|
|
281
299
|
gcp_conn_id=self.gcp_conn_id,
|
|
@@ -292,9 +310,7 @@ class GetPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
292
310
|
timeout=self.timeout,
|
|
293
311
|
metadata=self.metadata,
|
|
294
312
|
)
|
|
295
|
-
VertexAIPipelineJobLink.persist(
|
|
296
|
-
context=context, task_instance=self, pipeline_id=self.pipeline_job_id
|
|
297
|
-
)
|
|
313
|
+
VertexAIPipelineJobLink.persist(context=context, pipeline_id=self.pipeline_job_id)
|
|
298
314
|
self.log.info("Pipeline job was gotten.")
|
|
299
315
|
return types.PipelineJob.to_dict(result)
|
|
300
316
|
except NotFound:
|
|
@@ -408,6 +424,13 @@ class ListPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
408
424
|
self.gcp_conn_id = gcp_conn_id
|
|
409
425
|
self.impersonation_chain = impersonation_chain
|
|
410
426
|
|
|
427
|
+
@property
|
|
428
|
+
def extra_links_params(self) -> dict[str, Any]:
|
|
429
|
+
return {
|
|
430
|
+
"region": self.region,
|
|
431
|
+
"project_id": self.project_id,
|
|
432
|
+
}
|
|
433
|
+
|
|
411
434
|
def execute(self, context: Context):
|
|
412
435
|
hook = PipelineJobHook(
|
|
413
436
|
gcp_conn_id=self.gcp_conn_id,
|
|
@@ -424,7 +447,7 @@ class ListPipelineJobOperator(GoogleCloudBaseOperator):
|
|
|
424
447
|
timeout=self.timeout,
|
|
425
448
|
metadata=self.metadata,
|
|
426
449
|
)
|
|
427
|
-
VertexAIPipelineJobListLink.persist(context=context
|
|
450
|
+
VertexAIPipelineJobListLink.persist(context=context)
|
|
428
451
|
return [types.PipelineJob.to_dict(result) for result in results]
|
|
429
452
|
|
|
430
453
|
|
|
@@ -0,0 +1,393 @@
|
|
|
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 Vertex AI Ray operators."""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from collections.abc import Sequence
|
|
23
|
+
from functools import cached_property
|
|
24
|
+
from typing import TYPE_CHECKING, Literal
|
|
25
|
+
|
|
26
|
+
from google.api_core.exceptions import NotFound
|
|
27
|
+
from google.cloud.aiplatform.vertex_ray.util import resources
|
|
28
|
+
|
|
29
|
+
from airflow.providers.common.compat.sdk import AirflowException
|
|
30
|
+
from airflow.providers.google.cloud.hooks.vertex_ai.ray import RayHook
|
|
31
|
+
from airflow.providers.google.cloud.links.vertex_ai import (
|
|
32
|
+
VertexAIRayClusterLink,
|
|
33
|
+
VertexAIRayClusterListLink,
|
|
34
|
+
)
|
|
35
|
+
from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from airflow.providers.common.compat.sdk import Context
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class RayBaseOperator(GoogleCloudBaseOperator):
|
|
42
|
+
"""
|
|
43
|
+
Base class for Ray operators.
|
|
44
|
+
|
|
45
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
46
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
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: Sequence[str] = (
|
|
59
|
+
"location",
|
|
60
|
+
"gcp_conn_id",
|
|
61
|
+
"project_id",
|
|
62
|
+
"impersonation_chain",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
project_id: str,
|
|
68
|
+
location: str,
|
|
69
|
+
gcp_conn_id: str = "google_cloud_default",
|
|
70
|
+
impersonation_chain: str | Sequence[str] | None = None,
|
|
71
|
+
*args,
|
|
72
|
+
**kwargs,
|
|
73
|
+
) -> None:
|
|
74
|
+
super().__init__(*args, **kwargs)
|
|
75
|
+
self.location = location
|
|
76
|
+
self.project_id = project_id
|
|
77
|
+
self.gcp_conn_id = gcp_conn_id
|
|
78
|
+
self.impersonation_chain = impersonation_chain
|
|
79
|
+
|
|
80
|
+
@cached_property
|
|
81
|
+
def hook(self) -> RayHook:
|
|
82
|
+
return RayHook(
|
|
83
|
+
gcp_conn_id=self.gcp_conn_id,
|
|
84
|
+
impersonation_chain=self.impersonation_chain,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class CreateRayClusterOperator(RayBaseOperator):
|
|
89
|
+
"""
|
|
90
|
+
Create a Ray cluster on the Vertex AI.
|
|
91
|
+
|
|
92
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
93
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
94
|
+
:param head_node_type: The head node resource. Resources.node_count must be 1. If not set, default
|
|
95
|
+
value of Resources() class will be used.
|
|
96
|
+
:param python_version: Required. Python version for the ray cluster.
|
|
97
|
+
:param ray_version: Required. Ray version for the ray cluster.
|
|
98
|
+
Currently only 3 version are available: 2.9.3, 2.33, 2.42. For more information please refer to
|
|
99
|
+
https://github.com/googleapis/python-aiplatform/blob/main/setup.py#L101
|
|
100
|
+
:param network: Virtual private cloud (VPC) network. For Ray Client, VPC peering is required to
|
|
101
|
+
connect to the Ray Cluster managed in the Vertex API service. For Ray Job API, VPC network is not
|
|
102
|
+
required because Ray Cluster connection can be accessed through dashboard address.
|
|
103
|
+
:param service_account: Service account to be used for running Ray programs on the cluster.
|
|
104
|
+
:param cluster_name: This value may be up to 63 characters, and valid characters are `[a-z0-9_-]`.
|
|
105
|
+
The first character cannot be a number or hyphen.
|
|
106
|
+
:param worker_node_types: The list of Resources of the worker nodes. The same Resources object should
|
|
107
|
+
not appear multiple times in the list.
|
|
108
|
+
:param custom_images: The NodeImages which specifies head node and worker nodes images. All the
|
|
109
|
+
workers will share the same image. If each Resource has a specific custom image, use
|
|
110
|
+
`Resources.custom_image` for head/worker_node_type(s). Note that configuring
|
|
111
|
+
`Resources.custom_image` will override `custom_images` here. Allowlist only.
|
|
112
|
+
:param enable_metrics_collection: Enable Ray metrics collection for visualization.
|
|
113
|
+
:param enable_logging: Enable exporting Ray logs to Cloud Logging.
|
|
114
|
+
:param psc_interface_config: PSC-I config.
|
|
115
|
+
:param reserved_ip_ranges: A list of names for the reserved IP ranges under the VPC network that can
|
|
116
|
+
be used for this cluster. If set, we will deploy the cluster within the provided IP ranges.
|
|
117
|
+
Otherwise, the cluster is deployed to any IP ranges under the provided VPC network.
|
|
118
|
+
Example: ["vertex-ai-ip-range"].
|
|
119
|
+
:param labels: The labels with user-defined metadata to organize Ray cluster.
|
|
120
|
+
Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain
|
|
121
|
+
lowercase letters, numeric characters, underscores and dashes. International characters are allowed.
|
|
122
|
+
See https://goo.gl/xmQnxf for more information and examples of labels.
|
|
123
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
|
124
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
|
125
|
+
credentials, or chained list of accounts required to get the access_token
|
|
126
|
+
of the last account in the list, which will be impersonated in the request.
|
|
127
|
+
If set as a string, the account must grant the originating account
|
|
128
|
+
the Service Account Token Creator IAM role.
|
|
129
|
+
If set as a sequence, the identities from the list must grant
|
|
130
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
|
131
|
+
account from the list granting this role to the originating account (templated).
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
template_fields: Sequence[str] = tuple(
|
|
135
|
+
{"head_node_type", "worker_node_types"} | set(RayBaseOperator.template_fields)
|
|
136
|
+
)
|
|
137
|
+
operator_extra_links = (VertexAIRayClusterLink(),)
|
|
138
|
+
|
|
139
|
+
def __init__(
|
|
140
|
+
self,
|
|
141
|
+
python_version: str,
|
|
142
|
+
ray_version: Literal["2.9.3", "2.33", "2.42"],
|
|
143
|
+
head_node_type: resources.Resources = resources.Resources(),
|
|
144
|
+
network: str | None = None,
|
|
145
|
+
service_account: str | None = None,
|
|
146
|
+
cluster_name: str | None = None,
|
|
147
|
+
worker_node_types: list[resources.Resources] | None = None,
|
|
148
|
+
custom_images: resources.NodeImages | None = None,
|
|
149
|
+
enable_metrics_collection: bool = True,
|
|
150
|
+
enable_logging: bool = True,
|
|
151
|
+
psc_interface_config: resources.PscIConfig | None = None,
|
|
152
|
+
reserved_ip_ranges: list[str] | None = None,
|
|
153
|
+
labels: dict[str, str] | None = None,
|
|
154
|
+
*args,
|
|
155
|
+
**kwargs,
|
|
156
|
+
) -> None:
|
|
157
|
+
super().__init__(*args, **kwargs)
|
|
158
|
+
self.head_node_type = head_node_type
|
|
159
|
+
self.python_version = python_version
|
|
160
|
+
self.ray_version = ray_version
|
|
161
|
+
self.network = network
|
|
162
|
+
self.service_account = service_account
|
|
163
|
+
self.cluster_name = cluster_name
|
|
164
|
+
self.worker_node_types = worker_node_types
|
|
165
|
+
self.custom_images = custom_images
|
|
166
|
+
self.enable_metrics_collection = enable_metrics_collection
|
|
167
|
+
self.enable_logging = enable_logging
|
|
168
|
+
self.psc_interface_config = psc_interface_config
|
|
169
|
+
self.reserved_ip_ranges = reserved_ip_ranges
|
|
170
|
+
self.labels = labels
|
|
171
|
+
|
|
172
|
+
def execute(self, context: Context):
|
|
173
|
+
self.log.info("Creating a Ray cluster.")
|
|
174
|
+
try:
|
|
175
|
+
cluster_path = self.hook.create_ray_cluster(
|
|
176
|
+
project_id=self.project_id,
|
|
177
|
+
location=self.location,
|
|
178
|
+
head_node_type=self.head_node_type,
|
|
179
|
+
python_version=self.python_version,
|
|
180
|
+
ray_version=self.ray_version,
|
|
181
|
+
network=self.network,
|
|
182
|
+
service_account=self.service_account,
|
|
183
|
+
cluster_name=self.cluster_name,
|
|
184
|
+
worker_node_types=self.worker_node_types,
|
|
185
|
+
custom_images=self.custom_images,
|
|
186
|
+
enable_metrics_collection=self.enable_metrics_collection,
|
|
187
|
+
enable_logging=self.enable_logging,
|
|
188
|
+
psc_interface_config=self.psc_interface_config,
|
|
189
|
+
reserved_ip_ranges=self.reserved_ip_ranges,
|
|
190
|
+
labels=self.labels,
|
|
191
|
+
)
|
|
192
|
+
cluster_id = self.hook.extract_cluster_id(cluster_path)
|
|
193
|
+
context["ti"].xcom_push(
|
|
194
|
+
key="cluster_id",
|
|
195
|
+
value=cluster_id,
|
|
196
|
+
)
|
|
197
|
+
VertexAIRayClusterLink.persist(
|
|
198
|
+
context=context, location=self.location, cluster_id=cluster_id, project_id=self.project_id
|
|
199
|
+
)
|
|
200
|
+
self.log.info("Ray cluster was created.")
|
|
201
|
+
except Exception as error:
|
|
202
|
+
raise AirflowException(error)
|
|
203
|
+
return cluster_path
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class ListRayClustersOperator(RayBaseOperator):
|
|
207
|
+
"""
|
|
208
|
+
List Ray clusters under the currently authenticated project.
|
|
209
|
+
|
|
210
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
211
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
212
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
|
213
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
|
214
|
+
credentials, or chained list of accounts required to get the access_token
|
|
215
|
+
of the last account in the list, which will be impersonated in the request.
|
|
216
|
+
If set as a string, the account must grant the originating account
|
|
217
|
+
the Service Account Token Creator IAM role.
|
|
218
|
+
If set as a sequence, the identities from the list must grant
|
|
219
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
|
220
|
+
account from the list granting this role to the originating account (templated).
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
operator_extra_links = (VertexAIRayClusterListLink(),)
|
|
224
|
+
|
|
225
|
+
def execute(self, context: Context):
|
|
226
|
+
VertexAIRayClusterListLink.persist(context=context, project_id=self.project_id)
|
|
227
|
+
self.log.info("Listing Clusters from location %s.", self.location)
|
|
228
|
+
try:
|
|
229
|
+
ray_cluster_list = self.hook.list_ray_clusters(
|
|
230
|
+
project_id=self.project_id,
|
|
231
|
+
location=self.location,
|
|
232
|
+
)
|
|
233
|
+
ray_cluster_dict_list = [
|
|
234
|
+
self.hook.serialize_cluster_obj(ray_cluster) for ray_cluster in ray_cluster_list
|
|
235
|
+
]
|
|
236
|
+
except Exception as error:
|
|
237
|
+
raise AirflowException(error)
|
|
238
|
+
return ray_cluster_dict_list
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class GetRayClusterOperator(RayBaseOperator):
|
|
242
|
+
"""
|
|
243
|
+
Get Ray cluster.
|
|
244
|
+
|
|
245
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
246
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
247
|
+
:param cluster_id: Cluster resource ID.
|
|
248
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
|
249
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
|
250
|
+
credentials, or chained list of accounts required to get the access_token
|
|
251
|
+
of the last account in the list, which will be impersonated in the request.
|
|
252
|
+
If set as a string, the account must grant the originating account
|
|
253
|
+
the Service Account Token Creator IAM role.
|
|
254
|
+
If set as a sequence, the identities from the list must grant
|
|
255
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
|
256
|
+
account from the list granting this role to the originating account (templated).
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
template_fields: Sequence[str] = tuple({"cluster_id"} | set(RayBaseOperator.template_fields))
|
|
260
|
+
operator_extra_links = (VertexAIRayClusterLink(),)
|
|
261
|
+
|
|
262
|
+
def __init__(
|
|
263
|
+
self,
|
|
264
|
+
cluster_id: str,
|
|
265
|
+
*args,
|
|
266
|
+
**kwargs,
|
|
267
|
+
) -> None:
|
|
268
|
+
super().__init__(*args, **kwargs)
|
|
269
|
+
self.cluster_id = cluster_id
|
|
270
|
+
|
|
271
|
+
def execute(self, context: Context):
|
|
272
|
+
VertexAIRayClusterLink.persist(
|
|
273
|
+
context=context,
|
|
274
|
+
location=self.location,
|
|
275
|
+
cluster_id=self.cluster_id,
|
|
276
|
+
project_id=self.project_id,
|
|
277
|
+
)
|
|
278
|
+
self.log.info("Getting Cluster: %s", self.cluster_id)
|
|
279
|
+
try:
|
|
280
|
+
ray_cluster = self.hook.get_ray_cluster(
|
|
281
|
+
project_id=self.project_id,
|
|
282
|
+
location=self.location,
|
|
283
|
+
cluster_id=self.cluster_id,
|
|
284
|
+
)
|
|
285
|
+
self.log.info("Cluster data has been retrieved.")
|
|
286
|
+
ray_cluster_dict = self.hook.serialize_cluster_obj(ray_cluster)
|
|
287
|
+
return ray_cluster_dict
|
|
288
|
+
except NotFound as not_found_err:
|
|
289
|
+
self.log.info("The Cluster %s does not exist.", self.cluster_id)
|
|
290
|
+
raise AirflowException(not_found_err)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class UpdateRayClusterOperator(RayBaseOperator):
|
|
294
|
+
"""
|
|
295
|
+
Update Ray cluster (currently support resizing node counts for worker nodes).
|
|
296
|
+
|
|
297
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
298
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
299
|
+
:param cluster_id: Cluster resource ID.
|
|
300
|
+
:param worker_node_types: The list of Resources of the resized worker nodes. The same Resources
|
|
301
|
+
object should not appear multiple times in the list.
|
|
302
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
|
303
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
|
304
|
+
credentials, or chained list of accounts required to get the access_token
|
|
305
|
+
of the last account in the list, which will be impersonated in the request.
|
|
306
|
+
If set as a string, the account must grant the originating account
|
|
307
|
+
the Service Account Token Creator IAM role.
|
|
308
|
+
If set as a sequence, the identities from the list must grant
|
|
309
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
|
310
|
+
account from the list granting this role to the originating account (templated).
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
template_fields: Sequence[str] = tuple(
|
|
314
|
+
{"cluster_id", "worker_node_types"} | set(RayBaseOperator.template_fields)
|
|
315
|
+
)
|
|
316
|
+
operator_extra_links = (VertexAIRayClusterLink(),)
|
|
317
|
+
|
|
318
|
+
def __init__(
|
|
319
|
+
self,
|
|
320
|
+
cluster_id: str,
|
|
321
|
+
worker_node_types: list[resources.Resources],
|
|
322
|
+
*args,
|
|
323
|
+
**kwargs,
|
|
324
|
+
) -> None:
|
|
325
|
+
super().__init__(*args, **kwargs)
|
|
326
|
+
self.cluster_id = cluster_id
|
|
327
|
+
self.worker_node_types = worker_node_types
|
|
328
|
+
|
|
329
|
+
def execute(self, context: Context):
|
|
330
|
+
VertexAIRayClusterLink.persist(
|
|
331
|
+
context=context,
|
|
332
|
+
location=self.location,
|
|
333
|
+
cluster_id=self.cluster_id,
|
|
334
|
+
project_id=self.project_id,
|
|
335
|
+
)
|
|
336
|
+
self.log.info("Updating a Ray cluster.")
|
|
337
|
+
try:
|
|
338
|
+
cluster_path = self.hook.update_ray_cluster(
|
|
339
|
+
project_id=self.project_id,
|
|
340
|
+
location=self.location,
|
|
341
|
+
cluster_id=self.cluster_id,
|
|
342
|
+
worker_node_types=self.worker_node_types,
|
|
343
|
+
)
|
|
344
|
+
self.log.info("Ray cluster %s was updated.", self.cluster_id)
|
|
345
|
+
return cluster_path
|
|
346
|
+
except NotFound as not_found_err:
|
|
347
|
+
self.log.info("The Cluster %s does not exist.", self.cluster_id)
|
|
348
|
+
raise AirflowException(not_found_err)
|
|
349
|
+
except Exception as error:
|
|
350
|
+
raise AirflowException(error)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class DeleteRayClusterOperator(RayBaseOperator):
|
|
354
|
+
"""
|
|
355
|
+
Delete Ray cluster.
|
|
356
|
+
|
|
357
|
+
:param project_id: Required. The ID of the Google Cloud project that the service belongs to.
|
|
358
|
+
:param location: Required. The ID of the Google Cloud region that the service belongs to.
|
|
359
|
+
:param cluster_id: Cluster resource ID.
|
|
360
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
|
361
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
|
362
|
+
credentials, or chained list of accounts required to get the access_token
|
|
363
|
+
of the last account in the list, which will be impersonated in the request.
|
|
364
|
+
If set as a string, the account must grant the originating account
|
|
365
|
+
the Service Account Token Creator IAM role.
|
|
366
|
+
If set as a sequence, the identities from the list must grant
|
|
367
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
|
368
|
+
account from the list granting this role to the originating account (templated).
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
template_fields: Sequence[str] = tuple({"cluster_id"} | set(RayBaseOperator.template_fields))
|
|
372
|
+
|
|
373
|
+
def __init__(
|
|
374
|
+
self,
|
|
375
|
+
cluster_id: str,
|
|
376
|
+
*args,
|
|
377
|
+
**kwargs,
|
|
378
|
+
) -> None:
|
|
379
|
+
super().__init__(*args, **kwargs)
|
|
380
|
+
self.cluster_id = cluster_id
|
|
381
|
+
|
|
382
|
+
def execute(self, context: Context):
|
|
383
|
+
try:
|
|
384
|
+
self.log.info("Deleting Ray cluster: %s", self.cluster_id)
|
|
385
|
+
self.hook.delete_ray_cluster(
|
|
386
|
+
project_id=self.project_id,
|
|
387
|
+
location=self.location,
|
|
388
|
+
cluster_id=self.cluster_id,
|
|
389
|
+
)
|
|
390
|
+
self.log.info("Ray cluster was deleted.")
|
|
391
|
+
except NotFound as not_found_err:
|
|
392
|
+
self.log.info("The Ray cluster ID %s does not exist.", self.cluster_id)
|
|
393
|
+
raise AirflowException(not_found_err)
|
|
@@ -32,7 +32,7 @@ from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseO
|
|
|
32
32
|
if TYPE_CHECKING:
|
|
33
33
|
from google.api_core.retry import Retry
|
|
34
34
|
|
|
35
|
-
from airflow.
|
|
35
|
+
from airflow.providers.common.compat.sdk import Context
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class CloudVideoIntelligenceDetectVideoLabelsOperator(GoogleCloudBaseOperator):
|
|
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
|
|
|
41
41
|
from google.api_core.retry import Retry
|
|
42
42
|
from google.protobuf.field_mask_pb2 import FieldMask
|
|
43
43
|
|
|
44
|
-
from airflow.
|
|
44
|
+
from airflow.providers.common.compat.sdk import Context
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
MetaData = Sequence[tuple[str, str]]
|
|
@@ -693,7 +693,7 @@ class CloudVisionUpdateProductOperator(GoogleCloudBaseOperator):
|
|
|
693
693
|
location=self.location,
|
|
694
694
|
product_id=self.product_id,
|
|
695
695
|
project_id=self.project_id,
|
|
696
|
-
update_mask=self.update_mask,
|
|
696
|
+
update_mask=self.update_mask,
|
|
697
697
|
retry=self.retry,
|
|
698
698
|
timeout=self.timeout,
|
|
699
699
|
metadata=self.metadata,
|
|
@@ -20,9 +20,10 @@ import datetime
|
|
|
20
20
|
import json
|
|
21
21
|
import re
|
|
22
22
|
import uuid
|
|
23
|
-
from collections.abc import Sequence
|
|
23
|
+
from collections.abc import Collection, Sequence
|
|
24
24
|
from typing import TYPE_CHECKING
|
|
25
25
|
|
|
26
|
+
import pendulum
|
|
26
27
|
from google.api_core.exceptions import AlreadyExists
|
|
27
28
|
from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
|
|
28
29
|
from google.cloud.workflows.executions_v1beta import Execution
|
|
@@ -36,12 +37,13 @@ from airflow.providers.google.cloud.links.workflows import (
|
|
|
36
37
|
)
|
|
37
38
|
from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
|
|
38
39
|
from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
|
|
40
|
+
from airflow.providers.google.version_compat import AIRFLOW_V_3_0_PLUS
|
|
39
41
|
|
|
40
42
|
if TYPE_CHECKING:
|
|
41
43
|
from google.api_core.retry import Retry
|
|
42
44
|
from google.protobuf.field_mask_pb2 import FieldMask
|
|
43
45
|
|
|
44
|
-
from airflow.
|
|
46
|
+
from airflow.sdk import Context
|
|
45
47
|
|
|
46
48
|
from airflow.utils.hashlib_wrapper import md5
|
|
47
49
|
|
|
@@ -69,7 +71,7 @@ class WorkflowsCreateWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
69
71
|
:param metadata: Additional metadata that is provided to the method.
|
|
70
72
|
"""
|
|
71
73
|
|
|
72
|
-
template_fields:
|
|
74
|
+
template_fields: Collection[str] = ("location", "workflow", "workflow_id")
|
|
73
75
|
template_fields_renderers = {"workflow": "json"}
|
|
74
76
|
operator_extra_links = (WorkflowsWorkflowDetailsLink(),)
|
|
75
77
|
|
|
@@ -101,7 +103,7 @@ class WorkflowsCreateWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
101
103
|
self.impersonation_chain = impersonation_chain
|
|
102
104
|
self.force_rerun = force_rerun
|
|
103
105
|
|
|
104
|
-
def _workflow_id(self, context):
|
|
106
|
+
def _workflow_id(self, context: Context) -> str:
|
|
105
107
|
if self.workflow_id and not self.force_rerun:
|
|
106
108
|
# If users provide workflow id then assuring the idempotency
|
|
107
109
|
# is on their side
|
|
@@ -114,8 +116,17 @@ class WorkflowsCreateWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
114
116
|
|
|
115
117
|
# We are limited by allowed length of workflow_id so
|
|
116
118
|
# we use hash of whole information
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
if AIRFLOW_V_3_0_PLUS:
|
|
120
|
+
if dag_run := context.get("dag_run"):
|
|
121
|
+
run_after = pendulum.instance(dag_run.run_after)
|
|
122
|
+
else:
|
|
123
|
+
run_after = pendulum.now("UTC")
|
|
124
|
+
else:
|
|
125
|
+
if logical_date := context.get("logical_date"):
|
|
126
|
+
run_after = pendulum.instance(logical_date)
|
|
127
|
+
else:
|
|
128
|
+
run_after = pendulum.now("UTC")
|
|
129
|
+
base = f"airflow_{self.dag_id}_{self.task_id}_{run_after.isoformat()}_{hash_base}"
|
|
119
130
|
workflow_id = md5(base.encode()).hexdigest()
|
|
120
131
|
return re.sub(r"[:\-+.]", "_", workflow_id)
|
|
121
132
|
|
|
@@ -147,7 +158,6 @@ class WorkflowsCreateWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
147
158
|
|
|
148
159
|
WorkflowsWorkflowDetailsLink.persist(
|
|
149
160
|
context=context,
|
|
150
|
-
task_instance=self,
|
|
151
161
|
location_id=self.location,
|
|
152
162
|
workflow_id=self.workflow_id,
|
|
153
163
|
project_id=self.project_id or hook.project_id,
|
|
@@ -235,7 +245,6 @@ class WorkflowsUpdateWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
235
245
|
|
|
236
246
|
WorkflowsWorkflowDetailsLink.persist(
|
|
237
247
|
context=context,
|
|
238
|
-
task_instance=self,
|
|
239
248
|
location_id=self.location,
|
|
240
249
|
workflow_id=self.workflow_id,
|
|
241
250
|
project_id=self.project_id or hook.project_id,
|
|
@@ -368,7 +377,6 @@ class WorkflowsListWorkflowsOperator(GoogleCloudBaseOperator):
|
|
|
368
377
|
|
|
369
378
|
WorkflowsListOfWorkflowsLink.persist(
|
|
370
379
|
context=context,
|
|
371
|
-
task_instance=self,
|
|
372
380
|
project_id=self.project_id or hook.project_id,
|
|
373
381
|
)
|
|
374
382
|
|
|
@@ -434,7 +442,6 @@ class WorkflowsGetWorkflowOperator(GoogleCloudBaseOperator):
|
|
|
434
442
|
|
|
435
443
|
WorkflowsWorkflowDetailsLink.persist(
|
|
436
444
|
context=context,
|
|
437
|
-
task_instance=self,
|
|
438
445
|
location_id=self.location,
|
|
439
446
|
workflow_id=self.workflow_id,
|
|
440
447
|
project_id=self.project_id or hook.project_id,
|
|
@@ -505,11 +512,10 @@ class WorkflowsCreateExecutionOperator(GoogleCloudBaseOperator):
|
|
|
505
512
|
metadata=self.metadata,
|
|
506
513
|
)
|
|
507
514
|
execution_id = execution.name.split("/")[-1]
|
|
508
|
-
|
|
515
|
+
context["task_instance"].xcom_push(key="execution_id", value=execution_id)
|
|
509
516
|
|
|
510
517
|
WorkflowsExecutionLink.persist(
|
|
511
518
|
context=context,
|
|
512
|
-
task_instance=self,
|
|
513
519
|
location_id=self.location,
|
|
514
520
|
workflow_id=self.workflow_id,
|
|
515
521
|
execution_id=execution_id,
|
|
@@ -582,7 +588,6 @@ class WorkflowsCancelExecutionOperator(GoogleCloudBaseOperator):
|
|
|
582
588
|
|
|
583
589
|
WorkflowsExecutionLink.persist(
|
|
584
590
|
context=context,
|
|
585
|
-
task_instance=self,
|
|
586
591
|
location_id=self.location,
|
|
587
592
|
workflow_id=self.workflow_id,
|
|
588
593
|
execution_id=self.execution_id,
|
|
@@ -661,7 +666,6 @@ class WorkflowsListExecutionsOperator(GoogleCloudBaseOperator):
|
|
|
661
666
|
|
|
662
667
|
WorkflowsWorkflowDetailsLink.persist(
|
|
663
668
|
context=context,
|
|
664
|
-
task_instance=self,
|
|
665
669
|
location_id=self.location,
|
|
666
670
|
workflow_id=self.workflow_id,
|
|
667
671
|
project_id=self.project_id or hook.project_id,
|
|
@@ -737,7 +741,6 @@ class WorkflowsGetExecutionOperator(GoogleCloudBaseOperator):
|
|
|
737
741
|
|
|
738
742
|
WorkflowsExecutionLink.persist(
|
|
739
743
|
context=context,
|
|
740
|
-
task_instance=self,
|
|
741
744
|
location_id=self.location,
|
|
742
745
|
workflow_id=self.workflow_id,
|
|
743
746
|
execution_id=self.execution_id,
|
|
@@ -23,7 +23,7 @@ from collections.abc import Sequence
|
|
|
23
23
|
|
|
24
24
|
from google.auth.exceptions import DefaultCredentialsError
|
|
25
25
|
|
|
26
|
-
from airflow.
|
|
26
|
+
from airflow.providers.common.compat.sdk import AirflowException
|
|
27
27
|
from airflow.providers.google.cloud._internal_client.secret_manager_client import _SecretManagerClient
|
|
28
28
|
from airflow.providers.google.cloud.utils.credentials_provider import (
|
|
29
29
|
_get_target_principal_and_delegates,
|
|
@@ -160,11 +160,12 @@ class CloudSecretManagerBackend(BaseSecretsBackend, LoggingMixin):
|
|
|
160
160
|
|
|
161
161
|
return self._get_secret(self.connections_prefix, conn_id)
|
|
162
162
|
|
|
163
|
-
def get_variable(self, key: str) -> str | None:
|
|
163
|
+
def get_variable(self, key: str, team_name: str | None = None) -> str | None:
|
|
164
164
|
"""
|
|
165
165
|
Get Airflow Variable from Environment Variable.
|
|
166
166
|
|
|
167
167
|
:param key: Variable Key
|
|
168
|
+
:param team_name: Team name associated to the task trying to access the variable (if any)
|
|
168
169
|
:return: Variable Value
|
|
169
170
|
"""
|
|
170
171
|
if self.variables_prefix is None:
|