apache-airflow-providers-google 10.16.0rc1__py3-none-any.whl → 10.17.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/__init__.py +1 -1
- airflow/providers/google/ads/hooks/ads.py +5 -4
- airflow/providers/google/ads/operators/ads.py +1 -0
- airflow/providers/google/cloud/example_dags/example_cloud_sql_query.py +1 -0
- airflow/providers/google/cloud/example_dags/example_cloud_task.py +1 -0
- airflow/providers/google/cloud/example_dags/example_facebook_ads_to_gcs.py +1 -0
- airflow/providers/google/cloud/example_dags/example_looker.py +1 -0
- airflow/providers/google/cloud/example_dags/example_presto_to_gcs.py +1 -0
- airflow/providers/google/cloud/example_dags/example_salesforce_to_gcs.py +1 -0
- airflow/providers/google/cloud/fs/gcs.py +1 -2
- airflow/providers/google/cloud/hooks/automl.py +1 -0
- airflow/providers/google/cloud/hooks/bigquery.py +87 -24
- airflow/providers/google/cloud/hooks/bigquery_dts.py +1 -0
- airflow/providers/google/cloud/hooks/bigtable.py +1 -0
- airflow/providers/google/cloud/hooks/cloud_build.py +1 -0
- airflow/providers/google/cloud/hooks/cloud_memorystore.py +1 -0
- airflow/providers/google/cloud/hooks/cloud_sql.py +1 -0
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +9 -4
- airflow/providers/google/cloud/hooks/compute.py +1 -0
- airflow/providers/google/cloud/hooks/compute_ssh.py +2 -2
- airflow/providers/google/cloud/hooks/dataflow.py +6 -5
- airflow/providers/google/cloud/hooks/datafusion.py +1 -0
- airflow/providers/google/cloud/hooks/datapipeline.py +1 -0
- airflow/providers/google/cloud/hooks/dataplex.py +1 -0
- airflow/providers/google/cloud/hooks/dataprep.py +1 -0
- airflow/providers/google/cloud/hooks/dataproc.py +3 -2
- airflow/providers/google/cloud/hooks/dataproc_metastore.py +1 -0
- airflow/providers/google/cloud/hooks/datastore.py +1 -0
- airflow/providers/google/cloud/hooks/dlp.py +1 -0
- airflow/providers/google/cloud/hooks/functions.py +1 -0
- airflow/providers/google/cloud/hooks/gcs.py +12 -5
- airflow/providers/google/cloud/hooks/kms.py +1 -0
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +178 -300
- airflow/providers/google/cloud/hooks/life_sciences.py +1 -0
- airflow/providers/google/cloud/hooks/looker.py +1 -0
- airflow/providers/google/cloud/hooks/mlengine.py +1 -0
- airflow/providers/google/cloud/hooks/natural_language.py +1 -0
- airflow/providers/google/cloud/hooks/os_login.py +1 -0
- airflow/providers/google/cloud/hooks/pubsub.py +1 -0
- airflow/providers/google/cloud/hooks/secret_manager.py +1 -0
- airflow/providers/google/cloud/hooks/spanner.py +1 -0
- airflow/providers/google/cloud/hooks/speech_to_text.py +1 -0
- airflow/providers/google/cloud/hooks/stackdriver.py +1 -0
- airflow/providers/google/cloud/hooks/text_to_speech.py +1 -0
- airflow/providers/google/cloud/hooks/translate.py +1 -0
- airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +1 -0
- airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +255 -3
- airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +1 -0
- airflow/providers/google/cloud/hooks/vertex_ai/dataset.py +1 -0
- airflow/providers/google/cloud/hooks/vertex_ai/endpoint_service.py +1 -0
- airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +197 -0
- airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +9 -9
- airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +231 -12
- airflow/providers/google/cloud/hooks/video_intelligence.py +1 -0
- airflow/providers/google/cloud/hooks/vision.py +1 -0
- airflow/providers/google/cloud/links/automl.py +1 -0
- airflow/providers/google/cloud/links/bigquery.py +1 -0
- airflow/providers/google/cloud/links/bigquery_dts.py +1 -0
- airflow/providers/google/cloud/links/cloud_memorystore.py +1 -0
- airflow/providers/google/cloud/links/cloud_sql.py +1 -0
- airflow/providers/google/cloud/links/cloud_tasks.py +1 -0
- airflow/providers/google/cloud/links/compute.py +1 -0
- airflow/providers/google/cloud/links/datacatalog.py +1 -0
- airflow/providers/google/cloud/links/dataflow.py +1 -0
- airflow/providers/google/cloud/links/dataform.py +1 -0
- airflow/providers/google/cloud/links/datafusion.py +1 -0
- airflow/providers/google/cloud/links/dataplex.py +1 -0
- airflow/providers/google/cloud/links/dataproc.py +1 -0
- airflow/providers/google/cloud/links/kubernetes_engine.py +28 -0
- airflow/providers/google/cloud/links/mlengine.py +1 -0
- airflow/providers/google/cloud/links/pubsub.py +1 -0
- airflow/providers/google/cloud/links/spanner.py +1 -0
- airflow/providers/google/cloud/links/stackdriver.py +1 -0
- airflow/providers/google/cloud/links/workflows.py +1 -0
- airflow/providers/google/cloud/log/stackdriver_task_handler.py +18 -4
- airflow/providers/google/cloud/operators/automl.py +1 -0
- airflow/providers/google/cloud/operators/bigquery.py +21 -0
- airflow/providers/google/cloud/operators/bigquery_dts.py +1 -0
- airflow/providers/google/cloud/operators/bigtable.py +1 -0
- airflow/providers/google/cloud/operators/cloud_base.py +1 -0
- airflow/providers/google/cloud/operators/cloud_build.py +1 -0
- airflow/providers/google/cloud/operators/cloud_memorystore.py +1 -0
- airflow/providers/google/cloud/operators/cloud_sql.py +1 -0
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +11 -5
- airflow/providers/google/cloud/operators/compute.py +1 -0
- airflow/providers/google/cloud/operators/dataflow.py +1 -0
- airflow/providers/google/cloud/operators/datafusion.py +1 -0
- airflow/providers/google/cloud/operators/datapipeline.py +1 -0
- airflow/providers/google/cloud/operators/dataprep.py +1 -0
- airflow/providers/google/cloud/operators/dataproc.py +3 -2
- airflow/providers/google/cloud/operators/dataproc_metastore.py +1 -0
- airflow/providers/google/cloud/operators/datastore.py +1 -0
- airflow/providers/google/cloud/operators/functions.py +1 -0
- airflow/providers/google/cloud/operators/gcs.py +1 -0
- airflow/providers/google/cloud/operators/kubernetes_engine.py +600 -4
- airflow/providers/google/cloud/operators/life_sciences.py +1 -0
- airflow/providers/google/cloud/operators/looker.py +1 -0
- airflow/providers/google/cloud/operators/mlengine.py +283 -259
- airflow/providers/google/cloud/operators/natural_language.py +1 -0
- airflow/providers/google/cloud/operators/pubsub.py +1 -0
- airflow/providers/google/cloud/operators/spanner.py +1 -0
- airflow/providers/google/cloud/operators/speech_to_text.py +1 -0
- airflow/providers/google/cloud/operators/text_to_speech.py +1 -0
- airflow/providers/google/cloud/operators/translate.py +1 -0
- airflow/providers/google/cloud/operators/translate_speech.py +1 -0
- airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +14 -7
- airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +67 -13
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +26 -8
- airflow/providers/google/cloud/operators/vertex_ai/dataset.py +1 -0
- airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +306 -0
- airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +29 -48
- airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +52 -17
- airflow/providers/google/cloud/operators/video_intelligence.py +1 -0
- airflow/providers/google/cloud/operators/vision.py +1 -0
- airflow/providers/google/cloud/secrets/secret_manager.py +1 -0
- airflow/providers/google/cloud/sensors/bigquery.py +1 -0
- airflow/providers/google/cloud/sensors/bigquery_dts.py +1 -0
- airflow/providers/google/cloud/sensors/bigtable.py +1 -0
- airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +1 -0
- airflow/providers/google/cloud/sensors/dataflow.py +1 -0
- airflow/providers/google/cloud/sensors/dataform.py +1 -0
- airflow/providers/google/cloud/sensors/datafusion.py +1 -0
- airflow/providers/google/cloud/sensors/dataplex.py +1 -0
- airflow/providers/google/cloud/sensors/dataprep.py +1 -0
- airflow/providers/google/cloud/sensors/dataproc.py +1 -0
- airflow/providers/google/cloud/sensors/gcs.py +1 -0
- airflow/providers/google/cloud/sensors/looker.py +1 -0
- airflow/providers/google/cloud/sensors/pubsub.py +1 -0
- airflow/providers/google/cloud/sensors/tasks.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +1 -0
- airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -0
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +3 -2
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -0
- airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/mysql_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/postgres_to_gcs.py +19 -1
- airflow/providers/google/cloud/transfers/s3_to_gcs.py +3 -5
- airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/sql_to_gcs.py +4 -2
- airflow/providers/google/cloud/triggers/bigquery.py +4 -3
- airflow/providers/google/cloud/triggers/cloud_batch.py +1 -1
- airflow/providers/google/cloud/triggers/cloud_run.py +1 -0
- airflow/providers/google/cloud/triggers/cloud_sql.py +2 -0
- airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +14 -2
- airflow/providers/google/cloud/triggers/dataplex.py +1 -0
- airflow/providers/google/cloud/triggers/dataproc.py +1 -0
- airflow/providers/google/cloud/triggers/kubernetes_engine.py +72 -2
- airflow/providers/google/cloud/triggers/mlengine.py +2 -0
- airflow/providers/google/cloud/triggers/pubsub.py +3 -3
- airflow/providers/google/cloud/triggers/vertex_ai.py +107 -15
- airflow/providers/google/cloud/utils/field_sanitizer.py +2 -1
- airflow/providers/google/cloud/utils/field_validator.py +1 -0
- airflow/providers/google/cloud/utils/helpers.py +1 -0
- airflow/providers/google/cloud/utils/mlengine_operator_utils.py +1 -0
- airflow/providers/google/cloud/utils/mlengine_prediction_summary.py +1 -0
- airflow/providers/google/cloud/utils/openlineage.py +1 -0
- airflow/providers/google/common/auth_backend/google_openid.py +1 -0
- airflow/providers/google/common/hooks/base_google.py +2 -1
- airflow/providers/google/common/hooks/discovery_api.py +1 -0
- airflow/providers/google/common/links/storage.py +1 -0
- airflow/providers/google/common/utils/id_token_credentials.py +1 -0
- airflow/providers/google/firebase/hooks/firestore.py +1 -0
- airflow/providers/google/get_provider_info.py +9 -3
- airflow/providers/google/go_module_utils.py +1 -0
- airflow/providers/google/leveldb/hooks/leveldb.py +8 -7
- airflow/providers/google/marketing_platform/example_dags/example_display_video.py +1 -0
- airflow/providers/google/marketing_platform/hooks/analytics_admin.py +1 -0
- airflow/providers/google/marketing_platform/hooks/campaign_manager.py +1 -0
- airflow/providers/google/marketing_platform/hooks/display_video.py +1 -0
- airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -0
- airflow/providers/google/marketing_platform/operators/analytics.py +1 -0
- airflow/providers/google/marketing_platform/operators/analytics_admin.py +4 -2
- airflow/providers/google/marketing_platform/operators/campaign_manager.py +1 -0
- airflow/providers/google/marketing_platform/operators/display_video.py +1 -0
- airflow/providers/google/marketing_platform/operators/search_ads.py +1 -0
- airflow/providers/google/marketing_platform/sensors/campaign_manager.py +1 -0
- airflow/providers/google/marketing_platform/sensors/display_video.py +2 -1
- airflow/providers/google/marketing_platform/sensors/search_ads.py +1 -0
- airflow/providers/google/suite/hooks/calendar.py +1 -0
- airflow/providers/google/suite/hooks/drive.py +1 -0
- airflow/providers/google/suite/hooks/sheets.py +1 -0
- airflow/providers/google/suite/sensors/drive.py +1 -0
- airflow/providers/google/suite/transfers/gcs_to_gdrive.py +7 -0
- airflow/providers/google/suite/transfers/gcs_to_sheets.py +4 -1
- airflow/providers/google/suite/transfers/local_to_drive.py +1 -0
- {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/METADATA +18 -13
- {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/RECORD +196 -194
- {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/entry_points.txt +0 -0
@@ -16,19 +16,44 @@
|
|
16
16
|
# under the License.
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
from
|
19
|
+
from functools import cached_property
|
20
|
+
from typing import TYPE_CHECKING, Any, AsyncIterator, Sequence
|
20
21
|
|
21
|
-
from google.cloud.aiplatform_v1 import
|
22
|
+
from google.cloud.aiplatform_v1 import (
|
23
|
+
BatchPredictionJob,
|
24
|
+
HyperparameterTuningJob,
|
25
|
+
JobState,
|
26
|
+
PipelineState,
|
27
|
+
types,
|
28
|
+
)
|
22
29
|
|
23
30
|
from airflow.exceptions import AirflowException
|
31
|
+
from airflow.providers.google.cloud.hooks.vertex_ai.batch_prediction_job import BatchPredictionJobAsyncHook
|
24
32
|
from airflow.providers.google.cloud.hooks.vertex_ai.hyperparameter_tuning_job import (
|
25
33
|
HyperparameterTuningJobAsyncHook,
|
26
34
|
)
|
35
|
+
from airflow.providers.google.cloud.hooks.vertex_ai.pipeline_job import PipelineJobAsyncHook
|
27
36
|
from airflow.triggers.base import BaseTrigger, TriggerEvent
|
28
37
|
|
38
|
+
if TYPE_CHECKING:
|
39
|
+
from proto import Message
|
29
40
|
|
30
|
-
|
31
|
-
|
41
|
+
|
42
|
+
class BaseVertexAIJobTrigger(BaseTrigger):
|
43
|
+
"""Base class for Vertex AI job triggers.
|
44
|
+
|
45
|
+
This trigger polls the Vertex AI job and checks its status.
|
46
|
+
|
47
|
+
In order to use it properly, you must:
|
48
|
+
- implement the following methods `_wait_job()`.
|
49
|
+
- override required `job_type_verbose_name` attribute to provide meaningful message describing your
|
50
|
+
job type.
|
51
|
+
- override required `job_serializer_class` attribute to provide proto.Message class that will be used
|
52
|
+
to serialize your job with `to_dict()` class method.
|
53
|
+
"""
|
54
|
+
|
55
|
+
job_type_verbose_name: str = "Vertex AI Job"
|
56
|
+
job_serializer_class: Message = None
|
32
57
|
|
33
58
|
statuses_success = {
|
34
59
|
JobState.JOB_STATE_PAUSED,
|
@@ -51,10 +76,13 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
|
|
51
76
|
self.job_id = job_id
|
52
77
|
self.poll_interval = poll_interval
|
53
78
|
self.impersonation_chain = impersonation_chain
|
79
|
+
self.trigger_class_path = (
|
80
|
+
f"airflow.providers.google.cloud.triggers.vertex_ai.{self.__class__.__name__}"
|
81
|
+
)
|
54
82
|
|
55
83
|
def serialize(self) -> tuple[str, dict[str, Any]]:
|
56
84
|
return (
|
57
|
-
|
85
|
+
self.trigger_class_path,
|
58
86
|
{
|
59
87
|
"conn_id": self.conn_id,
|
60
88
|
"project_id": self.project_id,
|
@@ -66,14 +94,8 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
|
|
66
94
|
)
|
67
95
|
|
68
96
|
async def run(self) -> AsyncIterator[TriggerEvent]:
|
69
|
-
hook = self._get_async_hook()
|
70
97
|
try:
|
71
|
-
job = await
|
72
|
-
project_id=self.project_id,
|
73
|
-
location=self.location,
|
74
|
-
job_id=self.job_id,
|
75
|
-
poll_interval=self.poll_interval,
|
76
|
-
)
|
98
|
+
job = await self._wait_job()
|
77
99
|
except AirflowException as ex:
|
78
100
|
yield TriggerEvent(
|
79
101
|
{
|
@@ -84,16 +106,86 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
|
|
84
106
|
return
|
85
107
|
|
86
108
|
status = "success" if job.state in self.statuses_success else "error"
|
87
|
-
message = f"
|
109
|
+
message = f"{self.job_type_verbose_name} {job.name} completed with status {job.state.name}"
|
88
110
|
yield TriggerEvent(
|
89
111
|
{
|
90
112
|
"status": status,
|
91
113
|
"message": message,
|
92
|
-
"job":
|
114
|
+
"job": self._serialize_job(job),
|
93
115
|
}
|
94
116
|
)
|
95
117
|
|
96
|
-
def
|
118
|
+
async def _wait_job(self) -> Any:
|
119
|
+
"""Awaits a Vertex AI job instance for a status examination."""
|
120
|
+
raise NotImplementedError
|
121
|
+
|
122
|
+
def _serialize_job(self, job: Any) -> Any:
|
123
|
+
return self.job_serializer_class.to_dict(job)
|
124
|
+
|
125
|
+
|
126
|
+
class CreateHyperparameterTuningJobTrigger(BaseVertexAIJobTrigger):
|
127
|
+
"""CreateHyperparameterTuningJobTrigger run on the trigger worker to perform create operation."""
|
128
|
+
|
129
|
+
job_type_verbose_name = "Hyperparameter Tuning Job"
|
130
|
+
job_serializer_class = HyperparameterTuningJob
|
131
|
+
|
132
|
+
@cached_property
|
133
|
+
def async_hook(self) -> HyperparameterTuningJobAsyncHook:
|
97
134
|
return HyperparameterTuningJobAsyncHook(
|
98
135
|
gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain
|
99
136
|
)
|
137
|
+
|
138
|
+
async def _wait_job(self) -> types.HyperparameterTuningJob:
|
139
|
+
job: types.HyperparameterTuningJob = await self.async_hook.wait_hyperparameter_tuning_job(
|
140
|
+
project_id=self.project_id,
|
141
|
+
location=self.location,
|
142
|
+
job_id=self.job_id,
|
143
|
+
poll_interval=self.poll_interval,
|
144
|
+
)
|
145
|
+
return job
|
146
|
+
|
147
|
+
|
148
|
+
class CreateBatchPredictionJobTrigger(BaseVertexAIJobTrigger):
|
149
|
+
"""CreateBatchPredictionJobTrigger run on the trigger worker to perform create operation."""
|
150
|
+
|
151
|
+
job_type_verbose_name = "Batch Prediction Job"
|
152
|
+
job_serializer_class = BatchPredictionJob
|
153
|
+
|
154
|
+
@cached_property
|
155
|
+
def async_hook(self) -> BatchPredictionJobAsyncHook:
|
156
|
+
return BatchPredictionJobAsyncHook(
|
157
|
+
gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain
|
158
|
+
)
|
159
|
+
|
160
|
+
async def _wait_job(self) -> types.BatchPredictionJob:
|
161
|
+
job: types.BatchPredictionJob = await self.async_hook.wait_batch_prediction_job(
|
162
|
+
project_id=self.project_id,
|
163
|
+
location=self.location,
|
164
|
+
job_id=self.job_id,
|
165
|
+
poll_interval=self.poll_interval,
|
166
|
+
)
|
167
|
+
return job
|
168
|
+
|
169
|
+
|
170
|
+
class RunPipelineJobTrigger(BaseVertexAIJobTrigger):
|
171
|
+
"""Make async calls to Vertex AI to check the state of a Pipeline Job."""
|
172
|
+
|
173
|
+
job_type_verbose_name = "Pipeline Job"
|
174
|
+
job_serializer_class = types.PipelineJob
|
175
|
+
statuses_success = {
|
176
|
+
PipelineState.PIPELINE_STATE_PAUSED,
|
177
|
+
PipelineState.PIPELINE_STATE_SUCCEEDED,
|
178
|
+
}
|
179
|
+
|
180
|
+
@cached_property
|
181
|
+
def async_hook(self) -> PipelineJobAsyncHook:
|
182
|
+
return PipelineJobAsyncHook(gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain)
|
183
|
+
|
184
|
+
async def _wait_job(self) -> types.PipelineJob:
|
185
|
+
job: types.PipelineJob = await self.async_hook.wait_for_pipeline_job(
|
186
|
+
project_id=self.project_id,
|
187
|
+
location=self.location,
|
188
|
+
job_id=self.job_id,
|
189
|
+
poll_interval=self.poll_interval,
|
190
|
+
)
|
191
|
+
return job
|
@@ -67,7 +67,7 @@ specification of the path you should delete - separated with '.'
|
|
67
67
|
>>> },
|
68
68
|
>>> }
|
69
69
|
>>> }
|
70
|
-
>>> sanitizer=GcpBodyFieldSanitizer(FIELDS_TO_SANITIZE)
|
70
|
+
>>> sanitizer = GcpBodyFieldSanitizer(FIELDS_TO_SANITIZE)
|
71
71
|
>>> sanitizer.sanitize(body)
|
72
72
|
>>> json.dumps(body, indent=2)
|
73
73
|
{
|
@@ -96,6 +96,7 @@ In case they are dictionaries, subsequent component names key of the field, in
|
|
96
96
|
arrays - the sanitizer iterates through all dictionaries in the array and searches
|
97
97
|
components in all elements of the array.
|
98
98
|
"""
|
99
|
+
|
99
100
|
from __future__ import annotations
|
100
101
|
|
101
102
|
from airflow.exceptions import AirflowException
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# specific language governing permissions and limitations
|
17
17
|
# under the License.
|
18
18
|
"""This module contains a Google Cloud API base hook."""
|
19
|
+
|
19
20
|
from __future__ import annotations
|
20
21
|
|
21
22
|
import datetime
|
@@ -316,7 +317,7 @@ class GoogleBaseHook(BaseHook):
|
|
316
317
|
credentials.refresh(auth_req)
|
317
318
|
return credentials.token
|
318
319
|
|
319
|
-
@functools.
|
320
|
+
@functools.cached_property
|
320
321
|
def _get_credentials_email(self) -> str:
|
321
322
|
"""
|
322
323
|
Return the email address associated with the currently logged in account.
|
@@ -28,8 +28,9 @@ def get_provider_info():
|
|
28
28
|
"name": "Google",
|
29
29
|
"description": "Google services including:\n\n - `Google Ads <https://ads.google.com/>`__\n - `Google Cloud (GCP) <https://cloud.google.com/>`__\n - `Google Firebase <https://firebase.google.com/>`__\n - `Google LevelDB <https://github.com/google/leveldb/>`__\n - `Google Marketing Platform <https://marketingplatform.google.com/>`__\n - `Google Workspace <https://workspace.google.com/>`__ (formerly Google Suite)\n",
|
30
30
|
"state": "ready",
|
31
|
-
"source-date-epoch":
|
31
|
+
"source-date-epoch": 1712665855,
|
32
32
|
"versions": [
|
33
|
+
"10.17.0",
|
33
34
|
"10.16.0",
|
34
35
|
"10.15.0",
|
35
36
|
"10.14.0",
|
@@ -92,14 +93,15 @@ def get_provider_info():
|
|
92
93
|
"gcloud-aio-bigquery>=6.1.2",
|
93
94
|
"gcloud-aio-storage>=9.0.0",
|
94
95
|
"gcsfs>=2023.10.0",
|
95
|
-
"google-ads>=
|
96
|
+
"google-ads>=23.1.0",
|
96
97
|
"google-analytics-admin",
|
97
98
|
"google-api-core>=2.11.0,!=2.16.0",
|
98
99
|
"google-api-python-client>=1.6.0",
|
99
100
|
"google-auth>=1.0.0",
|
100
101
|
"google-auth-httplib2>=0.0.1",
|
101
|
-
"google-cloud-aiplatform>=1.
|
102
|
+
"google-cloud-aiplatform>=1.42.1",
|
102
103
|
"google-cloud-automl>=2.12.0",
|
104
|
+
"google-cloud-bigquery>=3.0.1",
|
103
105
|
"google-cloud-bigquery-datatransfer>=3.13.0",
|
104
106
|
"google-cloud-bigtable>=2.17.0",
|
105
107
|
"google-cloud-build>=3.22.0",
|
@@ -144,6 +146,7 @@ def get_provider_info():
|
|
144
146
|
"PyOpenSSL",
|
145
147
|
"sqlalchemy-bigquery>=1.2.1",
|
146
148
|
"sqlalchemy-spanner>=1.6.2",
|
149
|
+
"python-slugify>=5.0",
|
147
150
|
],
|
148
151
|
"additional-extras": [
|
149
152
|
{"name": "apache.beam", "dependencies": ["apache-beam[gcp]"]},
|
@@ -807,6 +810,7 @@ def get_provider_info():
|
|
807
810
|
"airflow.providers.google.cloud.operators.vertex_ai.hyperparameter_tuning_job",
|
808
811
|
"airflow.providers.google.cloud.operators.vertex_ai.model_service",
|
809
812
|
"airflow.providers.google.cloud.operators.vertex_ai.pipeline_job",
|
813
|
+
"airflow.providers.google.cloud.operators.vertex_ai.generative_model",
|
810
814
|
],
|
811
815
|
},
|
812
816
|
{
|
@@ -1141,6 +1145,7 @@ def get_provider_info():
|
|
1141
1145
|
"airflow.providers.google.cloud.hooks.vertex_ai.hyperparameter_tuning_job",
|
1142
1146
|
"airflow.providers.google.cloud.hooks.vertex_ai.model_service",
|
1143
1147
|
"airflow.providers.google.cloud.hooks.vertex_ai.pipeline_job",
|
1148
|
+
"airflow.providers.google.cloud.hooks.vertex_ai.generative_model",
|
1144
1149
|
],
|
1145
1150
|
},
|
1146
1151
|
{
|
@@ -1532,6 +1537,7 @@ def get_provider_info():
|
|
1532
1537
|
"airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineClusterLink",
|
1533
1538
|
"airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEnginePodLink",
|
1534
1539
|
"airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineJobLink",
|
1540
|
+
"airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineWorkloadsLink",
|
1535
1541
|
"airflow.providers.google.cloud.links.pubsub.PubSubSubscriptionLink",
|
1536
1542
|
"airflow.providers.google.cloud.links.pubsub.PubSubTopicLink",
|
1537
1543
|
"airflow.providers.google.cloud.links.cloud_memorystore.MemcachedInstanceDetailsLink",
|
@@ -15,6 +15,7 @@
|
|
15
15
|
# specific language governing permissions and limitations
|
16
16
|
# under the License.
|
17
17
|
"""Hook for Level DB."""
|
18
|
+
|
18
19
|
from __future__ import annotations
|
19
20
|
|
20
21
|
from airflow.exceptions import AirflowException, AirflowOptionalProviderFeatureException
|
@@ -93,7 +94,7 @@ class LevelDBHook(BaseHook):
|
|
93
94
|
"""
|
94
95
|
if command == "put":
|
95
96
|
if not value:
|
96
|
-
raise
|
97
|
+
raise ValueError("Please provide `value`!")
|
97
98
|
return self.put(key, value)
|
98
99
|
elif command == "get":
|
99
100
|
return self.get(key)
|
@@ -101,9 +102,9 @@ class LevelDBHook(BaseHook):
|
|
101
102
|
return self.delete(key)
|
102
103
|
elif command == "write_batch":
|
103
104
|
if not keys:
|
104
|
-
raise
|
105
|
+
raise ValueError("Please provide `keys`!")
|
105
106
|
if not values:
|
106
|
-
raise
|
107
|
+
raise ValueError("Please provide `values`!")
|
107
108
|
return self.write_batch(keys, values)
|
108
109
|
else:
|
109
110
|
raise LevelDBHookException("Unknown command for LevelDB hook")
|
@@ -116,7 +117,7 @@ class LevelDBHook(BaseHook):
|
|
116
117
|
:param value: value for put execution e.g. ``b'value'``, ``b'another-value'``
|
117
118
|
"""
|
118
119
|
if not self.db:
|
119
|
-
raise
|
120
|
+
raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
|
120
121
|
self.db.put(key, value)
|
121
122
|
|
122
123
|
def get(self, key: bytes) -> bytes:
|
@@ -127,7 +128,7 @@ class LevelDBHook(BaseHook):
|
|
127
128
|
:returns: value of key from db.get
|
128
129
|
"""
|
129
130
|
if not self.db:
|
130
|
-
raise
|
131
|
+
raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
|
131
132
|
return self.db.get(key)
|
132
133
|
|
133
134
|
def delete(self, key: bytes):
|
@@ -137,7 +138,7 @@ class LevelDBHook(BaseHook):
|
|
137
138
|
:param key: key for delete execution, e.g. ``b'key'``, ``b'another-key'``
|
138
139
|
"""
|
139
140
|
if not self.db:
|
140
|
-
raise
|
141
|
+
raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
|
141
142
|
self.db.delete(key)
|
142
143
|
|
143
144
|
def write_batch(self, keys: list[bytes], values: list[bytes]):
|
@@ -148,7 +149,7 @@ class LevelDBHook(BaseHook):
|
|
148
149
|
:param values: values for write_batch execution e.g. ``[b'value', b'another-value']``
|
149
150
|
"""
|
150
151
|
if not self.db:
|
151
|
-
raise
|
152
|
+
raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
|
152
153
|
with self.db.write_batch() as batch:
|
153
154
|
for i, key in enumerate(keys):
|
154
155
|
batch.put(key, values[i])
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# specific language governing permissions and limitations
|
17
17
|
# under the License.
|
18
18
|
"""This module contains Google Analytics 4 (GA4) operators."""
|
19
|
+
|
19
20
|
from __future__ import annotations
|
20
21
|
|
21
22
|
from typing import TYPE_CHECKING, Any, Sequence
|
@@ -105,8 +106,9 @@ class GoogleAnalyticsAdminListAccountsOperator(GoogleCloudBaseOperator):
|
|
105
106
|
impersonation_chain=self.impersonation_chain,
|
106
107
|
)
|
107
108
|
self.log.info(
|
108
|
-
"Requesting list of Google Analytics accounts. "
|
109
|
-
|
109
|
+
"Requesting list of Google Analytics accounts. Page size: %s, page token: %s",
|
110
|
+
self.page_size,
|
111
|
+
self.page_token,
|
110
112
|
)
|
111
113
|
accounts = hook.list_accounts(
|
112
114
|
page_size=self.page_size,
|
@@ -15,6 +15,7 @@
|
|
15
15
|
# specific language governing permissions and limitations
|
16
16
|
# under the License.
|
17
17
|
"""Sensor for detecting the completion of DV360 reports."""
|
18
|
+
|
18
19
|
from __future__ import annotations
|
19
20
|
|
20
21
|
from typing import TYPE_CHECKING, Sequence
|
@@ -157,7 +158,7 @@ class GoogleDisplayVideo360RunQuerySensor(BaseSensorOperator):
|
|
157
158
|
|
158
159
|
response = hook.get_report(query_id=self.query_id, report_id=self.report_id)
|
159
160
|
status = response.get("metadata", {}).get("status", {}).get("state")
|
160
|
-
self.log.info(
|
161
|
+
self.log.info("STATUS OF THE REPORT %s FOR QUERY %s: %s", self.report_id, self.query_id, status)
|
161
162
|
if response and status in ["DONE", "FAILED"]:
|
162
163
|
return True
|
163
164
|
return False
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# specific language governing permissions and limitations
|
17
17
|
# under the License.
|
18
18
|
"""This module contains a Google Cloud Storage to Google Drive transfer operator."""
|
19
|
+
|
19
20
|
from __future__ import annotations
|
20
21
|
|
21
22
|
import tempfile
|
@@ -79,6 +80,9 @@ class GCSToGoogleDriveOperator(BaseOperator):
|
|
79
80
|
If set as a sequence, the identities from the list must grant
|
80
81
|
Service Account Token Creator IAM role to the directly preceding identity, with first
|
81
82
|
account from the list granting this role to the originating account (templated).
|
83
|
+
:param delegate_to: (Optional) The account to impersonate using domain-wide delegation
|
84
|
+
of authority, if any. For this to work, the service account making the
|
85
|
+
request must have domain-wide delegation enabled. This only applies to the Google Drive connection.
|
82
86
|
"""
|
83
87
|
|
84
88
|
template_fields: Sequence[str] = (
|
@@ -99,6 +103,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
|
|
99
103
|
move_object: bool = False,
|
100
104
|
gcp_conn_id: str = "google_cloud_default",
|
101
105
|
impersonation_chain: str | Sequence[str] | None = None,
|
106
|
+
delegate_to: str | None = None,
|
102
107
|
**kwargs,
|
103
108
|
) -> None:
|
104
109
|
super().__init__(**kwargs)
|
@@ -110,6 +115,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
|
|
110
115
|
self.move_object = move_object
|
111
116
|
self.gcp_conn_id = gcp_conn_id
|
112
117
|
self.impersonation_chain = impersonation_chain
|
118
|
+
self.delegate_to = delegate_to
|
113
119
|
self.gcs_hook: GCSHook | None = None
|
114
120
|
self.gdrive_hook: GoogleDriveHook | None = None
|
115
121
|
|
@@ -121,6 +127,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
|
|
121
127
|
self.gdrive_hook = GoogleDriveHook(
|
122
128
|
gcp_conn_id=self.gcp_conn_id,
|
123
129
|
impersonation_chain=self.impersonation_chain,
|
130
|
+
delegate_to=self.delegate_to,
|
124
131
|
)
|
125
132
|
|
126
133
|
if WILDCARD in self.source_object:
|