apache-airflow-providers-google 10.2.0rc1__py3-none-any.whl → 10.3.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.
- airflow/providers/google/__init__.py +1 -1
- airflow/providers/google/ads/hooks/ads.py +38 -39
- airflow/providers/google/ads/transfers/ads_to_gcs.py +4 -4
- airflow/providers/google/cloud/_internal_client/secret_manager_client.py +6 -9
- airflow/providers/google/cloud/hooks/bigquery.py +328 -318
- airflow/providers/google/cloud/hooks/cloud_sql.py +66 -22
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +46 -70
- airflow/providers/google/cloud/hooks/dataflow.py +11 -15
- airflow/providers/google/cloud/hooks/dataform.py +3 -3
- airflow/providers/google/cloud/hooks/dataproc.py +577 -573
- airflow/providers/google/cloud/hooks/functions.py +60 -76
- airflow/providers/google/cloud/hooks/gcs.py +108 -18
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +69 -90
- airflow/providers/google/cloud/links/datafusion.py +4 -3
- airflow/providers/google/cloud/operators/bigquery.py +201 -191
- airflow/providers/google/cloud/operators/bigquery_dts.py +2 -1
- airflow/providers/google/cloud/operators/cloud_build.py +2 -1
- airflow/providers/google/cloud/operators/cloud_composer.py +4 -3
- airflow/providers/google/cloud/operators/cloud_sql.py +62 -28
- airflow/providers/google/cloud/operators/dataflow.py +6 -4
- airflow/providers/google/cloud/operators/dataform.py +3 -2
- airflow/providers/google/cloud/operators/dataproc.py +127 -123
- airflow/providers/google/cloud/operators/dataproc_metastore.py +18 -26
- airflow/providers/google/cloud/operators/gcs.py +35 -13
- airflow/providers/google/cloud/operators/kubernetes_engine.py +92 -42
- airflow/providers/google/cloud/operators/mlengine.py +2 -6
- airflow/providers/google/cloud/operators/vision.py +47 -56
- airflow/providers/google/cloud/sensors/bigquery.py +3 -2
- airflow/providers/google/cloud/sensors/gcs.py +5 -7
- airflow/providers/google/cloud/sensors/pubsub.py +2 -2
- airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +3 -2
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +2 -1
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +4 -4
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +6 -5
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +46 -7
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +5 -2
- airflow/providers/google/cloud/triggers/cloud_sql.py +102 -0
- airflow/providers/google/cloud/triggers/kubernetes_engine.py +28 -6
- airflow/providers/google/cloud/utils/bigquery.py +17 -0
- airflow/providers/google/get_provider_info.py +7 -2
- airflow/providers/google/suite/transfers/gcs_to_gdrive.py +4 -0
- airflow/providers/google/suite/transfers/local_to_drive.py +28 -26
- apache_airflow_providers_google-10.3.0rc1.dist-info/METADATA +289 -0
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/RECORD +49 -48
- apache_airflow_providers_google-10.2.0rc1.dist-info/METADATA +0 -1824
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/LICENSE +0 -0
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/NOTICE +0 -0
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/entry_points.txt +0 -0
- {apache_airflow_providers_google-10.2.0rc1.dist-info → apache_airflow_providers_google-10.3.0rc1.dist-info}/top_level.txt +0 -0
@@ -39,16 +39,18 @@ from typing import Any, Sequence
|
|
39
39
|
from urllib.parse import quote_plus
|
40
40
|
|
41
41
|
import httpx
|
42
|
+
from aiohttp import ClientSession
|
43
|
+
from gcloud.aio.auth import AioSession, Token
|
42
44
|
from googleapiclient.discovery import Resource, build
|
43
45
|
from googleapiclient.errors import HttpError
|
44
|
-
|
45
|
-
from airflow.exceptions import AirflowException
|
46
|
+
from requests import Session
|
46
47
|
|
47
48
|
# Number of retries - used by googleapiclient method calls to perform retries
|
48
49
|
# For requests that are "retriable"
|
50
|
+
from airflow.exceptions import AirflowException
|
49
51
|
from airflow.hooks.base import BaseHook
|
50
52
|
from airflow.models import Connection
|
51
|
-
from airflow.providers.google.common.hooks.base_google import GoogleBaseHook, get_field
|
53
|
+
from airflow.providers.google.common.hooks.base_google import GoogleBaseAsyncHook, GoogleBaseHook, get_field
|
52
54
|
from airflow.providers.mysql.hooks.mysql import MySqlHook
|
53
55
|
from airflow.providers.postgres.hooks.postgres import PostgresHook
|
54
56
|
from airflow.utils.log.logging_mixin import LoggingMixin
|
@@ -300,8 +302,7 @@ class CloudSQLHook(GoogleBaseHook):
|
|
300
302
|
self._wait_for_operation_to_complete(project_id=project_id, operation_name=operation_name)
|
301
303
|
|
302
304
|
@GoogleBaseHook.fallback_to_default_project_id
|
303
|
-
|
304
|
-
def export_instance(self, instance: str, body: dict, project_id: str) -> None:
|
305
|
+
def export_instance(self, instance: str, body: dict, project_id: str):
|
305
306
|
"""
|
306
307
|
Exports data from a Cloud SQL instance to a Cloud Storage bucket as a SQL dump
|
307
308
|
or CSV file.
|
@@ -321,7 +322,7 @@ class CloudSQLHook(GoogleBaseHook):
|
|
321
322
|
.execute(num_retries=self.num_retries)
|
322
323
|
)
|
323
324
|
operation_name = response["name"]
|
324
|
-
|
325
|
+
return operation_name
|
325
326
|
|
326
327
|
@GoogleBaseHook.fallback_to_default_project_id
|
327
328
|
def import_instance(self, instance: str, body: dict, project_id: str) -> None:
|
@@ -376,6 +377,7 @@ class CloudSQLHook(GoogleBaseHook):
|
|
376
377
|
except HttpError as ex:
|
377
378
|
raise AirflowException(f"Cloning of instance {instance} failed: {ex.content}")
|
378
379
|
|
380
|
+
@GoogleBaseHook.fallback_to_default_project_id
|
379
381
|
def _wait_for_operation_to_complete(
|
380
382
|
self, project_id: str, operation_name: str, time_to_sleep: int = TIME_TO_SLEEP_IN_SECONDS
|
381
383
|
) -> None:
|
@@ -412,6 +414,42 @@ CLOUD_SQL_PROXY_VERSION_DOWNLOAD_URL = (
|
|
412
414
|
)
|
413
415
|
|
414
416
|
|
417
|
+
class CloudSQLAsyncHook(GoogleBaseAsyncHook):
|
418
|
+
"""Class to get asynchronous hook for Google Cloud SQL."""
|
419
|
+
|
420
|
+
sync_hook_class = CloudSQLHook
|
421
|
+
|
422
|
+
async def _get_conn(self, session: Session, url: str):
|
423
|
+
scopes = [
|
424
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
425
|
+
"https://www.googleapis.com/auth/sqlservice.admin",
|
426
|
+
]
|
427
|
+
|
428
|
+
async with Token(scopes=scopes) as token:
|
429
|
+
session_aio = AioSession(session)
|
430
|
+
headers = {
|
431
|
+
"Authorization": f"Bearer {await token.get()}",
|
432
|
+
}
|
433
|
+
return await session_aio.get(url=url, headers=headers)
|
434
|
+
|
435
|
+
async def get_operation_name(self, project_id: str, operation_name: str, session):
|
436
|
+
url = f"https://sqladmin.googleapis.com/sql/v1beta4/projects/{project_id}/operations/{operation_name}"
|
437
|
+
return await self._get_conn(url=str(url), session=session)
|
438
|
+
|
439
|
+
async def get_operation(self, project_id: str, operation_name: str):
|
440
|
+
async with ClientSession() as session:
|
441
|
+
try:
|
442
|
+
operation = await self.get_operation_name(
|
443
|
+
project_id=project_id,
|
444
|
+
operation_name=operation_name,
|
445
|
+
session=session,
|
446
|
+
)
|
447
|
+
operation = await operation.json(content_type=None)
|
448
|
+
except HttpError as e:
|
449
|
+
raise e
|
450
|
+
return operation
|
451
|
+
|
452
|
+
|
415
453
|
class CloudSqlProxyRunner(LoggingMixin):
|
416
454
|
"""
|
417
455
|
Downloads and runs cloud-sql-proxy as subprocess of the Python process.
|
@@ -840,12 +878,13 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
840
878
|
|
841
879
|
@staticmethod
|
842
880
|
def _generate_unique_path() -> str:
|
843
|
-
"""
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
881
|
+
"""Generate a unique path.
|
882
|
+
|
883
|
+
We don't using mkdtemp here since it can generate paths close to 60
|
884
|
+
characters. We append project/location/instance to the path, Postgres
|
885
|
+
will then appends its own prefix, making the resulting path exceed the
|
886
|
+
100 character length limitation of a socket path. This generates a
|
887
|
+
shorter path ``${tempdir()}[8 random characters]``.
|
849
888
|
"""
|
850
889
|
random.seed()
|
851
890
|
while True:
|
@@ -926,9 +965,10 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
926
965
|
return instance_specification
|
927
966
|
|
928
967
|
def create_connection(self) -> Connection:
|
929
|
-
"""
|
930
|
-
|
931
|
-
Connection ID will be randomly generated
|
968
|
+
"""Create a connection.
|
969
|
+
|
970
|
+
Connection ID will be randomly generated according to whether it uses
|
971
|
+
proxy, TCP, UNIX sockets, SSL.
|
932
972
|
"""
|
933
973
|
uri = self._generate_connection_uri()
|
934
974
|
connection = Connection(conn_id=self.db_conn_id, uri=uri)
|
@@ -936,9 +976,9 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
936
976
|
return connection
|
937
977
|
|
938
978
|
def get_sqlproxy_runner(self) -> CloudSqlProxyRunner:
|
939
|
-
"""
|
940
|
-
|
941
|
-
lifecycle per task.
|
979
|
+
"""Retrieve Cloud SQL Proxy runner.
|
980
|
+
|
981
|
+
It is used to manage the proxy lifecycle per task.
|
942
982
|
|
943
983
|
:return: The Cloud SQL Proxy runner.
|
944
984
|
"""
|
@@ -956,9 +996,10 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
956
996
|
)
|
957
997
|
|
958
998
|
def get_database_hook(self, connection: Connection) -> PostgresHook | MySqlHook:
|
959
|
-
"""
|
960
|
-
|
961
|
-
|
999
|
+
"""Retrieve database hook.
|
1000
|
+
|
1001
|
+
This is the actual Postgres or MySQL database hook that uses proxy or
|
1002
|
+
connects directly to the Google Cloud SQL database.
|
962
1003
|
"""
|
963
1004
|
if self.database_type == "postgres":
|
964
1005
|
db_hook: PostgresHook | MySqlHook = PostgresHook(connection=connection, schema=self.database)
|
@@ -986,7 +1027,10 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
986
1027
|
self.sql_proxy_tcp_port = self.reserved_tcp_socket.getsockname()[1]
|
987
1028
|
|
988
1029
|
def free_reserved_port(self) -> None:
|
989
|
-
"""Free TCP port.
|
1030
|
+
"""Free TCP port.
|
1031
|
+
|
1032
|
+
Makes it immediately ready to be used by Cloud SQL Proxy.
|
1033
|
+
"""
|
990
1034
|
if self.reserved_tcp_socket:
|
991
1035
|
self.reserved_tcp_socket.close()
|
992
1036
|
self.reserved_tcp_socket = None
|
@@ -39,7 +39,7 @@ TIME_TO_SLEEP_IN_SECONDS = 10
|
|
39
39
|
|
40
40
|
|
41
41
|
class GcpTransferJobsStatus:
|
42
|
-
"""
|
42
|
+
"""Google Cloud Transfer job status."""
|
43
43
|
|
44
44
|
ENABLED = "ENABLED"
|
45
45
|
DISABLED = "DISABLED"
|
@@ -47,7 +47,7 @@ class GcpTransferJobsStatus:
|
|
47
47
|
|
48
48
|
|
49
49
|
class GcpTransferOperationStatus:
|
50
|
-
"""
|
50
|
+
"""Google Cloud Transfer operation status."""
|
51
51
|
|
52
52
|
IN_PROGRESS = "IN_PROGRESS"
|
53
53
|
PAUSED = "PAUSED"
|
@@ -104,9 +104,7 @@ NEGATIVE_STATUSES = {GcpTransferOperationStatus.FAILED, GcpTransferOperationStat
|
|
104
104
|
|
105
105
|
|
106
106
|
def gen_job_name(job_name: str) -> str:
|
107
|
-
"""
|
108
|
-
Adds unique suffix to job name. If suffix already exists, updates it.
|
109
|
-
Suffix — current timestamp.
|
107
|
+
"""Add a unique suffix to the job name.
|
110
108
|
|
111
109
|
:param job_name:
|
112
110
|
:return: job_name with suffix
|
@@ -116,11 +114,10 @@ def gen_job_name(job_name: str) -> str:
|
|
116
114
|
|
117
115
|
|
118
116
|
class CloudDataTransferServiceHook(GoogleBaseHook):
|
119
|
-
"""
|
120
|
-
Hook for Google Storage Transfer Service.
|
117
|
+
"""Google Storage Transfer Service functionalities.
|
121
118
|
|
122
|
-
All
|
123
|
-
keyword arguments rather than positional.
|
119
|
+
All methods in the hook with *project_id* in the signature must be called
|
120
|
+
with keyword arguments rather than positional.
|
124
121
|
"""
|
125
122
|
|
126
123
|
def __init__(
|
@@ -130,10 +127,11 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
130
127
|
impersonation_chain: str | Sequence[str] | None = None,
|
131
128
|
**kwargs,
|
132
129
|
) -> None:
|
133
|
-
if
|
130
|
+
if "delegate_to" in kwargs:
|
134
131
|
raise RuntimeError(
|
135
|
-
"The `delegate_to` parameter has been deprecated before and
|
136
|
-
" of Google Provider. You MUST
|
132
|
+
"The `delegate_to` parameter has been deprecated before and "
|
133
|
+
"finally removed in this version of Google Provider. You MUST "
|
134
|
+
"convert it to `impersonate_chain`."
|
137
135
|
)
|
138
136
|
super().__init__(
|
139
137
|
gcp_conn_id=gcp_conn_id,
|
@@ -143,8 +141,7 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
143
141
|
self._conn = None
|
144
142
|
|
145
143
|
def get_conn(self) -> Resource:
|
146
|
-
"""
|
147
|
-
Retrieves connection to Google Storage Transfer service.
|
144
|
+
"""Retrieve connection to Google Storage Transfer service.
|
148
145
|
|
149
146
|
:return: Google Storage Transfer service object
|
150
147
|
"""
|
@@ -156,13 +153,11 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
156
153
|
return self._conn
|
157
154
|
|
158
155
|
def create_transfer_job(self, body: dict) -> dict:
|
159
|
-
"""
|
160
|
-
Creates a transfer job that runs periodically.
|
156
|
+
"""Create a transfer job that runs periodically.
|
161
157
|
|
162
|
-
:param body: (Required)
|
158
|
+
:param body: (Required) The request body, as described in
|
163
159
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/patch#request-body
|
164
|
-
:return: transfer job.
|
165
|
-
See:
|
160
|
+
:return: The transfer job. See:
|
166
161
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs#TransferJob
|
167
162
|
"""
|
168
163
|
body = self._inject_project_id(body, BODY, PROJECT_ID)
|
@@ -200,9 +195,7 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
200
195
|
|
201
196
|
@GoogleBaseHook.fallback_to_default_project_id
|
202
197
|
def get_transfer_job(self, job_name: str, project_id: str) -> dict:
|
203
|
-
"""
|
204
|
-
Gets the latest state of a long-running operation in Google Storage
|
205
|
-
Transfer Service.
|
198
|
+
"""Get latest state of a long-running Google Storage Transfer Service job.
|
206
199
|
|
207
200
|
:param job_name: (Required) Name of the job to be fetched
|
208
201
|
:param project_id: (Optional) the ID of the project that owns the Transfer
|
@@ -218,9 +211,9 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
218
211
|
)
|
219
212
|
|
220
213
|
def list_transfer_job(self, request_filter: dict | None = None, **kwargs) -> list[dict]:
|
221
|
-
"""
|
222
|
-
|
223
|
-
|
214
|
+
"""List long-running operations in Google Storage Transfer Service.
|
215
|
+
|
216
|
+
A filter can be specified to match only certain entries.
|
224
217
|
|
225
218
|
:param request_filter: (Required) A request filter, as described in
|
226
219
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/list#body.QUERY_PARAMETERS.filter
|
@@ -252,8 +245,7 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
252
245
|
|
253
246
|
@GoogleBaseHook.fallback_to_default_project_id
|
254
247
|
def enable_transfer_job(self, job_name: str, project_id: str) -> dict:
|
255
|
-
"""
|
256
|
-
New transfers will be performed based on the schedule.
|
248
|
+
"""Make new transfers be performed based on the schedule.
|
257
249
|
|
258
250
|
:param job_name: (Required) Name of the job to be updated
|
259
251
|
:param project_id: (Optional) the ID of the project that owns the Transfer
|
@@ -276,8 +268,7 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
276
268
|
)
|
277
269
|
|
278
270
|
def update_transfer_job(self, job_name: str, body: dict) -> dict:
|
279
|
-
"""
|
280
|
-
Updates a transfer job that runs periodically.
|
271
|
+
"""Update a transfer job that runs periodically.
|
281
272
|
|
282
273
|
:param job_name: (Required) Name of the job to be updated
|
283
274
|
:param body: A request body, as described in
|
@@ -294,11 +285,11 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
294
285
|
|
295
286
|
@GoogleBaseHook.fallback_to_default_project_id
|
296
287
|
def delete_transfer_job(self, job_name: str, project_id: str) -> None:
|
297
|
-
"""
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
30 days after soft delete.
|
288
|
+
"""Delete a transfer job.
|
289
|
+
|
290
|
+
This is a soft delete. After a transfer job is deleted, the job and all
|
291
|
+
the transfer executions are subject to garbage collection. Transfer jobs
|
292
|
+
become eligible for garbage collection 30 days after soft delete.
|
302
293
|
|
303
294
|
:param job_name: (Required) Name of the job to be deleted
|
304
295
|
:param project_id: (Optional) the ID of the project that owns the Transfer
|
@@ -320,21 +311,19 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
320
311
|
)
|
321
312
|
|
322
313
|
def cancel_transfer_operation(self, operation_name: str) -> None:
|
323
|
-
"""
|
324
|
-
Cancels an transfer operation in Google Storage Transfer Service.
|
314
|
+
"""Cancel a transfer operation in Google Storage Transfer Service.
|
325
315
|
|
326
316
|
:param operation_name: Name of the transfer operation.
|
327
317
|
"""
|
328
318
|
self.get_conn().transferOperations().cancel(name=operation_name).execute(num_retries=self.num_retries)
|
329
319
|
|
330
320
|
def get_transfer_operation(self, operation_name: str) -> dict:
|
331
|
-
"""
|
332
|
-
Gets an transfer operation in Google Storage Transfer Service.
|
321
|
+
"""Get a transfer operation in Google Storage Transfer Service.
|
333
322
|
|
334
323
|
:param operation_name: (Required) Name of the transfer operation.
|
335
324
|
:return: transfer operation
|
336
|
-
|
337
|
-
|
325
|
+
|
326
|
+
.. seealso:: https://cloud.google.com/storage-transfer/docs/reference/rest/v1/Operation
|
338
327
|
"""
|
339
328
|
return (
|
340
329
|
self.get_conn()
|
@@ -344,18 +333,15 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
344
333
|
)
|
345
334
|
|
346
335
|
def list_transfer_operations(self, request_filter: dict | None = None, **kwargs) -> list[dict]:
|
347
|
-
"""
|
348
|
-
Gets an transfer operation in Google Storage Transfer Service.
|
336
|
+
"""Get a transfer operation in Google Storage Transfer Service.
|
349
337
|
|
350
338
|
:param request_filter: (Required) A request filter, as described in
|
351
339
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/list#body.QUERY_PARAMETERS.filter
|
352
340
|
With one additional improvement:
|
353
|
-
|
354
|
-
* project_id is optional if you have a project id defined
|
355
|
-
in the connection
|
356
|
-
See: :doc:`/connections/gcp`
|
357
|
-
|
358
341
|
:return: transfer operation
|
342
|
+
|
343
|
+
The ``project_id`` parameter is optional if you have a project ID
|
344
|
+
defined in the connection. See: :doc:`/connections/gcp`
|
359
345
|
"""
|
360
346
|
# To preserve backward compatibility
|
361
347
|
# TODO: remove one day
|
@@ -390,16 +376,14 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
390
376
|
return operations
|
391
377
|
|
392
378
|
def pause_transfer_operation(self, operation_name: str) -> None:
|
393
|
-
"""
|
394
|
-
Pauses an transfer operation in Google Storage Transfer Service.
|
379
|
+
"""Pause a transfer operation in Google Storage Transfer Service.
|
395
380
|
|
396
381
|
:param operation_name: (Required) Name of the transfer operation.
|
397
382
|
"""
|
398
383
|
self.get_conn().transferOperations().pause(name=operation_name).execute(num_retries=self.num_retries)
|
399
384
|
|
400
385
|
def resume_transfer_operation(self, operation_name: str) -> None:
|
401
|
-
"""
|
402
|
-
Resumes an transfer operation in Google Storage Transfer Service.
|
386
|
+
"""Resume a transfer operation in Google Storage Transfer Service.
|
403
387
|
|
404
388
|
:param operation_name: (Required) Name of the transfer operation.
|
405
389
|
"""
|
@@ -411,17 +395,14 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
411
395
|
expected_statuses: set[str] | None = None,
|
412
396
|
timeout: float | timedelta | None = None,
|
413
397
|
) -> None:
|
414
|
-
"""
|
415
|
-
Waits until the job reaches the expected state.
|
398
|
+
"""Wait until the job reaches the expected state.
|
416
399
|
|
417
|
-
:param job:
|
418
|
-
See:
|
400
|
+
:param job: The transfer job to wait for. See:
|
419
401
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs#TransferJob
|
420
|
-
:param expected_statuses:
|
421
|
-
See:
|
402
|
+
:param expected_statuses: The expected state. See:
|
422
403
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferOperations#Status
|
423
|
-
:param timeout: Time in which the operation must end in seconds. If not
|
424
|
-
seconds.
|
404
|
+
:param timeout: Time in which the operation must end in seconds. If not
|
405
|
+
specified, defaults to 60 seconds.
|
425
406
|
"""
|
426
407
|
expected_statuses = (
|
427
408
|
{GcpTransferOperationStatus.SUCCESS} if not expected_statuses else expected_statuses
|
@@ -458,20 +439,15 @@ class CloudDataTransferServiceHook(GoogleBaseHook):
|
|
458
439
|
def operations_contain_expected_statuses(
|
459
440
|
operations: list[dict], expected_statuses: set[str] | str
|
460
441
|
) -> bool:
|
461
|
-
"""
|
462
|
-
Checks whether the operation list has an operation with the
|
463
|
-
expected status, then returns true
|
464
|
-
If it encounters operations in FAILED or ABORTED state
|
465
|
-
throw :class:`airflow.exceptions.AirflowException`.
|
442
|
+
"""Check whether an operation exists with the expected status.
|
466
443
|
|
467
444
|
:param operations: (Required) List of transfer operations to check.
|
468
|
-
:param expected_statuses: (Required)
|
469
|
-
See:
|
445
|
+
:param expected_statuses: (Required) The expected status. See:
|
470
446
|
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferOperations#Status
|
471
|
-
:return: If there is an operation with the expected state
|
472
|
-
|
473
|
-
:raises
|
474
|
-
|
447
|
+
:return: If there is an operation with the expected state in the
|
448
|
+
operation list, returns true,
|
449
|
+
:raises AirflowException: If it encounters operations with state FAILED
|
450
|
+
or ABORTED in the list.
|
475
451
|
"""
|
476
452
|
expected_statuses_set = (
|
477
453
|
{expected_statuses} if isinstance(expected_statuses, str) else set(expected_statuses)
|
@@ -57,29 +57,25 @@ T = TypeVar("T", bound=Callable)
|
|
57
57
|
def process_line_and_extract_dataflow_job_id_callback(
|
58
58
|
on_new_job_id_callback: Callable[[str], None] | None
|
59
59
|
) -> Callable[[str], None]:
|
60
|
-
"""
|
61
|
-
|
62
|
-
|
60
|
+
"""Build callback that triggers the specified function.
|
61
|
+
|
62
|
+
The returned callback is intended to be used as ``process_line_callback`` in
|
63
63
|
:py:class:`~airflow.providers.apache.beam.hooks.beam.BeamCommandRunner`.
|
64
64
|
|
65
65
|
:param on_new_job_id_callback: Callback called when the job ID is known
|
66
66
|
"""
|
67
67
|
|
68
|
-
def _process_line_and_extract_job_id(
|
69
|
-
line: str,
|
70
|
-
# on_new_job_id_callback: Callable[[str], None] | None
|
71
|
-
) -> None:
|
68
|
+
def _process_line_and_extract_job_id(line: str) -> None:
|
72
69
|
# Job id info: https://goo.gl/SE29y9.
|
70
|
+
if on_new_job_id_callback is None:
|
71
|
+
return
|
73
72
|
matched_job = JOB_ID_PATTERN.search(line)
|
74
|
-
if matched_job:
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def wrap(line: str):
|
80
|
-
return _process_line_and_extract_job_id(line)
|
73
|
+
if matched_job is None:
|
74
|
+
return
|
75
|
+
job_id = matched_job.group("job_id_java") or matched_job.group("job_id_python")
|
76
|
+
on_new_job_id_callback(job_id)
|
81
77
|
|
82
|
-
return
|
78
|
+
return _process_line_and_extract_job_id
|
83
79
|
|
84
80
|
|
85
81
|
def _fallback_variable_parameter(parameter_name: str, variable_key_name: str) -> Callable[[T], T]:
|
@@ -604,9 +604,9 @@ class DataformHook(GoogleBaseHook):
|
|
604
604
|
timeout: float | None = None,
|
605
605
|
metadata: Sequence[tuple[str, str]] = (),
|
606
606
|
) -> InstallNpmPackagesResponse:
|
607
|
-
"""
|
608
|
-
|
609
|
-
to be created in workspace.
|
607
|
+
"""Install NPM dependencies in the provided workspace.
|
608
|
+
|
609
|
+
Requires "package.json" to be created in the workspace.
|
610
610
|
|
611
611
|
:param project_id: Required. The ID of the Google Cloud project where workspace located.
|
612
612
|
:param region: Required. The ID of the Google Cloud region where workspace located.
|