apache-airflow-providers-google 10.14.0rc1__py3-none-any.whl → 10.15.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 +1 -2
- airflow/providers/google/cloud/hooks/automl.py +13 -13
- airflow/providers/google/cloud/hooks/bigquery.py +208 -256
- airflow/providers/google/cloud/hooks/bigquery_dts.py +6 -6
- airflow/providers/google/cloud/hooks/bigtable.py +8 -8
- airflow/providers/google/cloud/hooks/cloud_batch.py +1 -1
- airflow/providers/google/cloud/hooks/cloud_build.py +19 -20
- airflow/providers/google/cloud/hooks/cloud_composer.py +4 -4
- airflow/providers/google/cloud/hooks/cloud_memorystore.py +10 -10
- airflow/providers/google/cloud/hooks/cloud_run.py +1 -1
- airflow/providers/google/cloud/hooks/cloud_sql.py +18 -19
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +3 -3
- airflow/providers/google/cloud/hooks/compute.py +16 -16
- airflow/providers/google/cloud/hooks/compute_ssh.py +1 -1
- airflow/providers/google/cloud/hooks/datacatalog.py +22 -22
- airflow/providers/google/cloud/hooks/dataflow.py +48 -49
- airflow/providers/google/cloud/hooks/dataform.py +16 -16
- airflow/providers/google/cloud/hooks/datafusion.py +15 -15
- airflow/providers/google/cloud/hooks/datapipeline.py +3 -3
- airflow/providers/google/cloud/hooks/dataplex.py +19 -19
- airflow/providers/google/cloud/hooks/dataprep.py +10 -10
- airflow/providers/google/cloud/hooks/dataproc.py +132 -14
- airflow/providers/google/cloud/hooks/dataproc_metastore.py +13 -13
- airflow/providers/google/cloud/hooks/datastore.py +3 -3
- airflow/providers/google/cloud/hooks/dlp.py +25 -25
- airflow/providers/google/cloud/hooks/gcs.py +39 -27
- airflow/providers/google/cloud/hooks/gdm.py +3 -3
- airflow/providers/google/cloud/hooks/kms.py +3 -3
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +63 -48
- airflow/providers/google/cloud/hooks/life_sciences.py +13 -12
- airflow/providers/google/cloud/hooks/looker.py +8 -9
- airflow/providers/google/cloud/hooks/mlengine.py +12 -12
- airflow/providers/google/cloud/hooks/natural_language.py +2 -2
- airflow/providers/google/cloud/hooks/os_login.py +1 -1
- airflow/providers/google/cloud/hooks/pubsub.py +9 -9
- airflow/providers/google/cloud/hooks/secret_manager.py +1 -1
- airflow/providers/google/cloud/hooks/spanner.py +11 -11
- airflow/providers/google/cloud/hooks/speech_to_text.py +1 -1
- airflow/providers/google/cloud/hooks/stackdriver.py +7 -7
- airflow/providers/google/cloud/hooks/tasks.py +11 -11
- airflow/providers/google/cloud/hooks/text_to_speech.py +1 -1
- airflow/providers/google/cloud/hooks/translate.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +13 -13
- airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +6 -6
- airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +45 -50
- airflow/providers/google/cloud/hooks/vertex_ai/dataset.py +13 -13
- airflow/providers/google/cloud/hooks/vertex_ai/endpoint_service.py +9 -9
- airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +128 -11
- airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +10 -10
- airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +8 -8
- airflow/providers/google/cloud/hooks/video_intelligence.py +2 -2
- airflow/providers/google/cloud/hooks/vision.py +1 -1
- airflow/providers/google/cloud/hooks/workflows.py +10 -10
- airflow/providers/google/cloud/links/datafusion.py +12 -5
- airflow/providers/google/cloud/operators/bigquery.py +11 -11
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +3 -1
- airflow/providers/google/cloud/operators/dataflow.py +16 -16
- airflow/providers/google/cloud/operators/datafusion.py +9 -1
- airflow/providers/google/cloud/operators/dataproc.py +444 -69
- airflow/providers/google/cloud/operators/kubernetes_engine.py +6 -6
- airflow/providers/google/cloud/operators/life_sciences.py +10 -9
- airflow/providers/google/cloud/operators/mlengine.py +96 -96
- airflow/providers/google/cloud/operators/pubsub.py +2 -0
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +33 -3
- airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +59 -2
- airflow/providers/google/cloud/secrets/secret_manager.py +8 -7
- airflow/providers/google/cloud/sensors/bigquery.py +20 -16
- airflow/providers/google/cloud/sensors/cloud_composer.py +11 -8
- airflow/providers/google/cloud/sensors/dataproc_metastore.py +12 -2
- airflow/providers/google/cloud/sensors/gcs.py +8 -7
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -0
- airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +4 -4
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +1 -0
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -1
- airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/mysql_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/oracle_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/postgres_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/presto_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/s3_to_gcs.py +3 -3
- airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/sql_to_gcs.py +3 -3
- airflow/providers/google/cloud/transfers/trino_to_gcs.py +1 -1
- airflow/providers/google/cloud/triggers/bigquery.py +12 -12
- airflow/providers/google/cloud/triggers/bigquery_dts.py +1 -1
- airflow/providers/google/cloud/triggers/cloud_batch.py +3 -1
- airflow/providers/google/cloud/triggers/cloud_build.py +2 -2
- airflow/providers/google/cloud/triggers/cloud_run.py +1 -1
- airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +6 -6
- airflow/providers/google/cloud/triggers/dataflow.py +3 -1
- airflow/providers/google/cloud/triggers/datafusion.py +2 -2
- airflow/providers/google/cloud/triggers/dataplex.py +2 -2
- airflow/providers/google/cloud/triggers/dataproc.py +34 -14
- airflow/providers/google/cloud/triggers/gcs.py +12 -8
- airflow/providers/google/cloud/triggers/kubernetes_engine.py +2 -2
- airflow/providers/google/cloud/triggers/mlengine.py +2 -2
- airflow/providers/google/cloud/triggers/pubsub.py +1 -1
- airflow/providers/google/cloud/triggers/vertex_ai.py +99 -0
- airflow/providers/google/cloud/utils/bigquery.py +2 -2
- airflow/providers/google/cloud/utils/credentials_provider.py +2 -2
- airflow/providers/google/cloud/utils/dataform.py +1 -1
- airflow/providers/google/cloud/utils/dataproc.py +25 -0
- airflow/providers/google/cloud/utils/field_validator.py +2 -2
- airflow/providers/google/cloud/utils/helpers.py +2 -2
- airflow/providers/google/cloud/utils/mlengine_operator_utils.py +1 -1
- airflow/providers/google/cloud/utils/mlengine_prediction_summary.py +1 -1
- airflow/providers/google/common/auth_backend/google_openid.py +2 -2
- airflow/providers/google/common/hooks/base_google.py +87 -23
- airflow/providers/google/common/hooks/discovery_api.py +2 -2
- airflow/providers/google/common/utils/id_token_credentials.py +5 -5
- airflow/providers/google/firebase/hooks/firestore.py +3 -3
- airflow/providers/google/get_provider_info.py +7 -2
- airflow/providers/google/leveldb/hooks/leveldb.py +4 -4
- airflow/providers/google/marketing_platform/hooks/analytics.py +11 -14
- airflow/providers/google/marketing_platform/hooks/campaign_manager.py +11 -11
- airflow/providers/google/marketing_platform/hooks/display_video.py +13 -13
- airflow/providers/google/marketing_platform/hooks/search_ads.py +4 -4
- airflow/providers/google/marketing_platform/operators/analytics.py +37 -32
- airflow/providers/google/suite/hooks/calendar.py +2 -2
- airflow/providers/google/suite/hooks/drive.py +7 -7
- airflow/providers/google/suite/hooks/sheets.py +8 -8
- {apache_airflow_providers_google-10.14.0rc1.dist-info → apache_airflow_providers_google-10.15.0rc1.dist-info}/METADATA +11 -11
- {apache_airflow_providers_google-10.14.0rc1.dist-info → apache_airflow_providers_google-10.15.0rc1.dist-info}/RECORD +126 -124
- {apache_airflow_providers_google-10.14.0rc1.dist-info → apache_airflow_providers_google-10.15.0rc1.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-10.14.0rc1.dist-info → apache_airflow_providers_google-10.15.0rc1.dist-info}/entry_points.txt +0 -0
@@ -74,7 +74,9 @@ def _fallback_object_url_to_object_name_and_bucket_name(
|
|
74
74
|
object_name_keyword_arg_name="object_name",
|
75
75
|
) -> Callable[[T], T]:
|
76
76
|
"""
|
77
|
-
|
77
|
+
Convert object URL parameter to object name and bucket name parameter.
|
78
|
+
|
79
|
+
This method is a Decorator factory.
|
78
80
|
|
79
81
|
:param object_url_keyword_arg_name: Name of the object URL parameter
|
80
82
|
:param bucket_name_keyword_arg_name: Name of the bucket name parameter
|
@@ -160,7 +162,7 @@ class GCSHook(GoogleBaseHook):
|
|
160
162
|
)
|
161
163
|
|
162
164
|
def get_conn(self) -> storage.Client:
|
163
|
-
"""
|
165
|
+
"""Return a Google Cloud Storage service object."""
|
164
166
|
if not self._conn:
|
165
167
|
self._conn = storage.Client(
|
166
168
|
credentials=self.get_credentials(), client_info=CLIENT_INFO, project=self.project_id
|
@@ -176,7 +178,7 @@ class GCSHook(GoogleBaseHook):
|
|
176
178
|
destination_object: str | None = None,
|
177
179
|
) -> None:
|
178
180
|
"""
|
179
|
-
|
181
|
+
Copy an object from a bucket to another, with renaming if requested.
|
180
182
|
|
181
183
|
destination_bucket or destination_object can be omitted, in which case
|
182
184
|
source bucket/object is used, but not both.
|
@@ -304,7 +306,7 @@ class GCSHook(GoogleBaseHook):
|
|
304
306
|
user_project: str | None = None,
|
305
307
|
) -> str | bytes:
|
306
308
|
"""
|
307
|
-
|
309
|
+
Download a file from Google Cloud Storage.
|
308
310
|
|
309
311
|
When no filename is supplied, the operator loads the file into memory and returns its
|
310
312
|
content. When a filename is supplied, it writes the file to the specified location and
|
@@ -366,7 +368,7 @@ class GCSHook(GoogleBaseHook):
|
|
366
368
|
num_max_attempts: int | None = 1,
|
367
369
|
) -> bytes:
|
368
370
|
"""
|
369
|
-
|
371
|
+
Download a file from Google Cloud Storage.
|
370
372
|
|
371
373
|
When no filename is supplied, the operator loads the file into memory and returns its
|
372
374
|
content. When a filename is supplied, it writes the file to the specified location and
|
@@ -399,7 +401,7 @@ class GCSHook(GoogleBaseHook):
|
|
399
401
|
user_project: str | None = None,
|
400
402
|
) -> Generator[IO[bytes], None, None]:
|
401
403
|
"""
|
402
|
-
|
404
|
+
Download the file to a temporary directory and returns a file handle.
|
403
405
|
|
404
406
|
You can use this method by passing the bucket_name and object_name parameters
|
405
407
|
or just object_url parameter.
|
@@ -435,7 +437,7 @@ class GCSHook(GoogleBaseHook):
|
|
435
437
|
user_project: str | None = None,
|
436
438
|
) -> Generator[IO[bytes], None, None]:
|
437
439
|
"""
|
438
|
-
|
440
|
+
Create temporary file, returns a file handle and uploads the files content on close.
|
439
441
|
|
440
442
|
You can use this method by passing the bucket_name and object_name parameters
|
441
443
|
or just object_url parameter.
|
@@ -478,7 +480,7 @@ class GCSHook(GoogleBaseHook):
|
|
478
480
|
user_project: str | None = None,
|
479
481
|
) -> None:
|
480
482
|
"""
|
481
|
-
|
483
|
+
Upload a local file or file data as string or bytes to Google Cloud Storage.
|
482
484
|
|
483
485
|
:param bucket_name: The bucket to upload to.
|
484
486
|
:param object_name: The object name to set when uploading the file.
|
@@ -498,7 +500,7 @@ class GCSHook(GoogleBaseHook):
|
|
498
500
|
|
499
501
|
def _call_with_retry(f: Callable[[], None]) -> None:
|
500
502
|
"""
|
501
|
-
|
503
|
+
Upload a file or a string with a retry mechanism and exponential back-off.
|
502
504
|
|
503
505
|
:param f: Callable that should be retried.
|
504
506
|
"""
|
@@ -572,7 +574,7 @@ class GCSHook(GoogleBaseHook):
|
|
572
574
|
|
573
575
|
def exists(self, bucket_name: str, object_name: str, retry: Retry = DEFAULT_RETRY) -> bool:
|
574
576
|
"""
|
575
|
-
|
577
|
+
Check for the existence of a file in Google Cloud Storage.
|
576
578
|
|
577
579
|
:param bucket_name: The Google Cloud Storage bucket where the object is.
|
578
580
|
:param object_name: The name of the blob_name to check in the Google cloud
|
@@ -601,7 +603,7 @@ class GCSHook(GoogleBaseHook):
|
|
601
603
|
|
602
604
|
def is_updated_after(self, bucket_name: str, object_name: str, ts: datetime) -> bool:
|
603
605
|
"""
|
604
|
-
|
606
|
+
Check if an blob_name is updated in Google Cloud Storage.
|
605
607
|
|
606
608
|
:param bucket_name: The Google Cloud Storage bucket where the object is.
|
607
609
|
:param object_name: The name of the object to check in the Google cloud
|
@@ -621,7 +623,7 @@ class GCSHook(GoogleBaseHook):
|
|
621
623
|
self, bucket_name: str, object_name: str, min_ts: datetime, max_ts: datetime
|
622
624
|
) -> bool:
|
623
625
|
"""
|
624
|
-
|
626
|
+
Check if an blob_name is updated in Google Cloud Storage.
|
625
627
|
|
626
628
|
:param bucket_name: The Google Cloud Storage bucket where the object is.
|
627
629
|
:param object_name: The name of the object to check in the Google cloud
|
@@ -642,7 +644,7 @@ class GCSHook(GoogleBaseHook):
|
|
642
644
|
|
643
645
|
def is_updated_before(self, bucket_name: str, object_name: str, ts: datetime) -> bool:
|
644
646
|
"""
|
645
|
-
|
647
|
+
Check if an blob_name is updated before given time in Google Cloud Storage.
|
646
648
|
|
647
649
|
:param bucket_name: The Google Cloud Storage bucket where the object is.
|
648
650
|
:param object_name: The name of the object to check in the Google cloud
|
@@ -680,7 +682,7 @@ class GCSHook(GoogleBaseHook):
|
|
680
682
|
|
681
683
|
def delete(self, bucket_name: str, object_name: str) -> None:
|
682
684
|
"""
|
683
|
-
|
685
|
+
Delete an object from the bucket.
|
684
686
|
|
685
687
|
:param bucket_name: name of the bucket, where the object resides
|
686
688
|
:param object_name: name of the object to delete
|
@@ -954,7 +956,7 @@ class GCSHook(GoogleBaseHook):
|
|
954
956
|
|
955
957
|
def get_size(self, bucket_name: str, object_name: str) -> int:
|
956
958
|
"""
|
957
|
-
|
959
|
+
Get the size of a file in Google Cloud Storage.
|
958
960
|
|
959
961
|
:param bucket_name: The Google Cloud Storage bucket where the blob_name is.
|
960
962
|
:param object_name: The name of the object to check in the Google
|
@@ -971,7 +973,7 @@ class GCSHook(GoogleBaseHook):
|
|
971
973
|
|
972
974
|
def get_crc32c(self, bucket_name: str, object_name: str):
|
973
975
|
"""
|
974
|
-
|
976
|
+
Get the CRC32c checksum of an object in Google Cloud Storage.
|
975
977
|
|
976
978
|
:param bucket_name: The Google Cloud Storage bucket where the blob_name is.
|
977
979
|
:param object_name: The name of the object to check in the Google cloud
|
@@ -991,7 +993,7 @@ class GCSHook(GoogleBaseHook):
|
|
991
993
|
|
992
994
|
def get_md5hash(self, bucket_name: str, object_name: str) -> str:
|
993
995
|
"""
|
994
|
-
|
996
|
+
Get the MD5 hash of an object in Google Cloud Storage.
|
995
997
|
|
996
998
|
:param bucket_name: The Google Cloud Storage bucket where the blob_name is.
|
997
999
|
:param object_name: The name of the object to check in the Google cloud
|
@@ -1016,7 +1018,7 @@ class GCSHook(GoogleBaseHook):
|
|
1016
1018
|
labels: dict | None = None,
|
1017
1019
|
) -> str:
|
1018
1020
|
"""
|
1019
|
-
|
1021
|
+
Create a new bucket.
|
1020
1022
|
|
1021
1023
|
Google Cloud Storage uses a flat namespace, so you can't
|
1022
1024
|
create a bucket with a name that is already in use.
|
@@ -1076,7 +1078,7 @@ class GCSHook(GoogleBaseHook):
|
|
1076
1078
|
self, bucket_name: str, entity: str, role: str, user_project: str | None = None
|
1077
1079
|
) -> None:
|
1078
1080
|
"""
|
1079
|
-
|
1081
|
+
Create a new ACL entry on the specified bucket_name.
|
1080
1082
|
|
1081
1083
|
See: https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert
|
1082
1084
|
|
@@ -1111,7 +1113,7 @@ class GCSHook(GoogleBaseHook):
|
|
1111
1113
|
user_project: str | None = None,
|
1112
1114
|
) -> None:
|
1113
1115
|
"""
|
1114
|
-
|
1116
|
+
Create a new ACL entry on the specified object.
|
1115
1117
|
|
1116
1118
|
See: https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert
|
1117
1119
|
|
@@ -1184,7 +1186,7 @@ class GCSHook(GoogleBaseHook):
|
|
1184
1186
|
delete_extra_files: bool = False,
|
1185
1187
|
) -> None:
|
1186
1188
|
"""
|
1187
|
-
|
1189
|
+
Synchronize the contents of the buckets.
|
1188
1190
|
|
1189
1191
|
Parameters ``source_object`` and ``destination_object`` describe the root sync directories. If they
|
1190
1192
|
are not passed, the entire bucket will be synchronized. If they are passed, they should point
|
@@ -1336,15 +1338,22 @@ def gcs_object_is_directory(bucket: str) -> bool:
|
|
1336
1338
|
return len(blob) == 0 or blob.endswith("/")
|
1337
1339
|
|
1338
1340
|
|
1339
|
-
def parse_json_from_gcs(
|
1341
|
+
def parse_json_from_gcs(
|
1342
|
+
gcp_conn_id: str,
|
1343
|
+
file_uri: str,
|
1344
|
+
impersonation_chain: str | Sequence[str] | None = None,
|
1345
|
+
) -> Any:
|
1340
1346
|
"""
|
1341
|
-
|
1347
|
+
Download and parses json file from Google cloud Storage.
|
1342
1348
|
|
1343
1349
|
:param gcp_conn_id: Airflow Google Cloud connection ID.
|
1344
1350
|
:param file_uri: full path to json file
|
1345
1351
|
example: ``gs://test-bucket/dir1/dir2/file``
|
1346
1352
|
"""
|
1347
|
-
gcs_hook = GCSHook(
|
1353
|
+
gcs_hook = GCSHook(
|
1354
|
+
gcp_conn_id=gcp_conn_id,
|
1355
|
+
impersonation_chain=impersonation_chain,
|
1356
|
+
)
|
1348
1357
|
bucket, blob = _parse_gcs_url(file_uri)
|
1349
1358
|
with NamedTemporaryFile(mode="w+b") as file:
|
1350
1359
|
try:
|
@@ -1390,6 +1399,9 @@ class GCSAsyncHook(GoogleBaseAsyncHook):
|
|
1390
1399
|
sync_hook_class = GCSHook
|
1391
1400
|
|
1392
1401
|
async def get_storage_client(self, session: ClientSession) -> Storage:
|
1393
|
-
"""
|
1394
|
-
|
1395
|
-
|
1402
|
+
"""Return a Google Cloud Storage service object."""
|
1403
|
+
token = await self.get_token(session=session)
|
1404
|
+
return Storage(
|
1405
|
+
token=token,
|
1406
|
+
session=cast(Session, session),
|
1407
|
+
)
|
@@ -49,7 +49,7 @@ class GoogleDeploymentManagerHook(GoogleBaseHook):
|
|
49
49
|
)
|
50
50
|
|
51
51
|
def get_conn(self) -> Resource:
|
52
|
-
"""
|
52
|
+
"""Return a Google Deployment Manager service object."""
|
53
53
|
http_authorized = self._authorize()
|
54
54
|
return build("deploymentmanager", "v2", http=http_authorized, cache_discovery=False)
|
55
55
|
|
@@ -61,7 +61,7 @@ class GoogleDeploymentManagerHook(GoogleBaseHook):
|
|
61
61
|
order_by: str | None = None,
|
62
62
|
) -> list[dict[str, Any]]:
|
63
63
|
"""
|
64
|
-
|
64
|
+
List deployments in a google cloud project.
|
65
65
|
|
66
66
|
:param project_id: The project ID for this request.
|
67
67
|
:param deployment_filter: A filter expression which limits resources returned in the response.
|
@@ -84,7 +84,7 @@ class GoogleDeploymentManagerHook(GoogleBaseHook):
|
|
84
84
|
self, project_id: str | None, deployment: str | None = None, delete_policy: str | None = None
|
85
85
|
) -> None:
|
86
86
|
"""
|
87
|
-
|
87
|
+
Delete a deployment and all associated resources in a google cloud project.
|
88
88
|
|
89
89
|
:param project_id: The project ID for this request.
|
90
90
|
:param deployment: The name of the deployment for this request.
|
@@ -32,12 +32,12 @@ if TYPE_CHECKING:
|
|
32
32
|
|
33
33
|
|
34
34
|
def _b64encode(s: bytes) -> str:
|
35
|
-
"""
|
35
|
+
"""Encode a Base64 bytes object to a string."""
|
36
36
|
return base64.b64encode(s).decode("ascii")
|
37
37
|
|
38
38
|
|
39
39
|
def _b64decode(s: str) -> bytes:
|
40
|
-
"""
|
40
|
+
"""Decode a Base64 string to bytes."""
|
41
41
|
return base64.b64decode(s.encode("utf-8"))
|
42
42
|
|
43
43
|
|
@@ -75,7 +75,7 @@ class CloudKMSHook(GoogleBaseHook):
|
|
75
75
|
|
76
76
|
def get_conn(self) -> KeyManagementServiceClient:
|
77
77
|
"""
|
78
|
-
|
78
|
+
Retrieve connection to Cloud Key Management service.
|
79
79
|
|
80
80
|
:return: Cloud Key Management service object
|
81
81
|
"""
|
@@ -28,10 +28,10 @@ from __future__ import annotations
|
|
28
28
|
import contextlib
|
29
29
|
import json
|
30
30
|
import time
|
31
|
-
import warnings
|
32
31
|
from functools import cached_property
|
33
32
|
from typing import TYPE_CHECKING, Sequence
|
34
33
|
|
34
|
+
from deprecated import deprecated
|
35
35
|
from gcloud.aio.auth import Token
|
36
36
|
from google.api_core.exceptions import NotFound
|
37
37
|
from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
|
@@ -48,6 +48,7 @@ from urllib3.exceptions import HTTPError
|
|
48
48
|
|
49
49
|
from airflow import version
|
50
50
|
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
51
|
+
from airflow.providers.cncf.kubernetes.kube_client import _enable_tcp_keepalive
|
51
52
|
from airflow.providers.cncf.kubernetes.utils.pod_manager import PodOperatorHookProtocol
|
52
53
|
from airflow.providers.google.common.consts import CLIENT_INFO
|
53
54
|
from airflow.providers.google.common.hooks.base_google import (
|
@@ -98,22 +99,23 @@ class GKEHook(GoogleBaseHook):
|
|
98
99
|
|
99
100
|
# To preserve backward compatibility
|
100
101
|
# TODO: remove one day
|
102
|
+
@deprecated(
|
103
|
+
reason=(
|
104
|
+
"The get_conn method has been deprecated. "
|
105
|
+
"You should use the get_cluster_manager_client method."
|
106
|
+
),
|
107
|
+
category=AirflowProviderDeprecationWarning,
|
108
|
+
)
|
101
109
|
def get_conn(self) -> container_v1.ClusterManagerClient:
|
102
|
-
warnings.warn(
|
103
|
-
"The get_conn method has been deprecated. You should use the get_cluster_manager_client method.",
|
104
|
-
AirflowProviderDeprecationWarning,
|
105
|
-
stacklevel=2,
|
106
|
-
)
|
107
110
|
return self.get_cluster_manager_client()
|
108
111
|
|
109
112
|
# To preserve backward compatibility
|
110
113
|
# TODO: remove one day
|
114
|
+
@deprecated(
|
115
|
+
reason="The get_client method has been deprecated. You should use the get_conn method.",
|
116
|
+
category=AirflowProviderDeprecationWarning,
|
117
|
+
)
|
111
118
|
def get_client(self) -> ClusterManagerClient:
|
112
|
-
warnings.warn(
|
113
|
-
"The get_client method has been deprecated. You should use the get_conn method.",
|
114
|
-
AirflowProviderDeprecationWarning,
|
115
|
-
stacklevel=2,
|
116
|
-
)
|
117
119
|
return self.get_conn()
|
118
120
|
|
119
121
|
def wait_for_operation(self, operation: Operation, project_id: str | None = None) -> Operation:
|
@@ -176,7 +178,7 @@ class GKEHook(GoogleBaseHook):
|
|
176
178
|
retry: Retry | _MethodDefault = DEFAULT,
|
177
179
|
timeout: float | None = None,
|
178
180
|
) -> Operation | None:
|
179
|
-
"""
|
181
|
+
"""Delete the cluster, the Kubernetes endpoint, and all worker nodes.
|
180
182
|
|
181
183
|
Firewalls and routes that were configured during cluster creation are
|
182
184
|
also deleted. Other Google Compute Engine resources that might be in use
|
@@ -352,6 +354,7 @@ class GKEPodHook(GoogleBaseHook, PodOperatorHookProtocol):
|
|
352
354
|
self,
|
353
355
|
cluster_url: str,
|
354
356
|
ssl_ca_cert: str,
|
357
|
+
disable_tcp_keepalive: bool | None = None,
|
355
358
|
gcp_conn_id: str = "google_cloud_default",
|
356
359
|
impersonation_chain: str | Sequence[str] | None = None,
|
357
360
|
**kwargs,
|
@@ -363,6 +366,7 @@ class GKEPodHook(GoogleBaseHook, PodOperatorHookProtocol):
|
|
363
366
|
)
|
364
367
|
self._cluster_url = cluster_url
|
365
368
|
self._ssl_ca_cert = ssl_ca_cert
|
369
|
+
self.disable_tcp_keepalive = disable_tcp_keepalive
|
366
370
|
|
367
371
|
@cached_property
|
368
372
|
def api_client(self) -> client.ApiClient:
|
@@ -397,6 +401,10 @@ class GKEPodHook(GoogleBaseHook, PodOperatorHookProtocol):
|
|
397
401
|
def get_conn(self) -> client.ApiClient:
|
398
402
|
configuration = self._get_config()
|
399
403
|
configuration.refresh_api_key_hook = self._refresh_api_key_hook
|
404
|
+
|
405
|
+
if self.disable_tcp_keepalive is not True:
|
406
|
+
_enable_tcp_keepalive()
|
407
|
+
|
400
408
|
return client.ApiClient(configuration)
|
401
409
|
|
402
410
|
def _refresh_api_key_hook(self, configuration: client.configuration.Configuration):
|
@@ -500,14 +508,15 @@ class GKEPodAsyncHook(GoogleBaseAsyncHook):
|
|
500
508
|
:param name: Name of the pod.
|
501
509
|
:param namespace: Name of the pod's namespace.
|
502
510
|
"""
|
503
|
-
|
504
|
-
async with self.
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
+
with await self.service_file_as_context() as service_file: # type: ignore[attr-defined]
|
512
|
+
async with Token(scopes=self.scopes, service_file=service_file) as token:
|
513
|
+
async with self.get_conn(token) as connection:
|
514
|
+
v1_api = async_client.CoreV1Api(connection)
|
515
|
+
pod: V1Pod = await v1_api.read_namespaced_pod(
|
516
|
+
name=name,
|
517
|
+
namespace=namespace,
|
518
|
+
)
|
519
|
+
return pod
|
511
520
|
|
512
521
|
async def delete_pod(self, name: str, namespace: str):
|
513
522
|
"""Delete a pod.
|
@@ -515,18 +524,21 @@ class GKEPodAsyncHook(GoogleBaseAsyncHook):
|
|
515
524
|
:param name: Name of the pod.
|
516
525
|
:param namespace: Name of the pod's namespace.
|
517
526
|
"""
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
527
|
+
with await self.service_file_as_context() as service_file: # type: ignore[attr-defined]
|
528
|
+
async with Token(scopes=self.scopes, service_file=service_file) as token, self.get_conn(
|
529
|
+
token
|
530
|
+
) as connection:
|
531
|
+
try:
|
532
|
+
v1_api = async_client.CoreV1Api(connection)
|
533
|
+
await v1_api.delete_namespaced_pod(
|
534
|
+
name=name,
|
535
|
+
namespace=namespace,
|
536
|
+
body=client.V1DeleteOptions(),
|
537
|
+
)
|
538
|
+
except async_client.ApiException as e:
|
539
|
+
# If the pod is already deleted
|
540
|
+
if e.status != 404:
|
541
|
+
raise
|
530
542
|
|
531
543
|
async def read_logs(self, name: str, namespace: str):
|
532
544
|
"""Read logs inside the pod while starting containers inside.
|
@@ -539,19 +551,22 @@ class GKEPodAsyncHook(GoogleBaseAsyncHook):
|
|
539
551
|
:param name: Name of the pod.
|
540
552
|
:param namespace: Name of the pod's namespace.
|
541
553
|
"""
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
554
|
+
with await self.service_file_as_context() as service_file: # type: ignore[attr-defined]
|
555
|
+
async with Token(scopes=self.scopes, service_file=service_file) as token, self.get_conn(
|
556
|
+
token
|
557
|
+
) as connection:
|
558
|
+
try:
|
559
|
+
v1_api = async_client.CoreV1Api(connection)
|
560
|
+
logs = await v1_api.read_namespaced_pod_log(
|
561
|
+
name=name,
|
562
|
+
namespace=namespace,
|
563
|
+
follow=False,
|
564
|
+
timestamps=True,
|
565
|
+
)
|
566
|
+
logs = logs.splitlines()
|
567
|
+
for line in logs:
|
568
|
+
self.log.info("Container logs from %s", line)
|
569
|
+
return logs
|
570
|
+
except HTTPError:
|
571
|
+
self.log.exception("There was an error reading the kubernetes API.")
|
572
|
+
raise
|
@@ -19,10 +19,10 @@
|
|
19
19
|
from __future__ import annotations
|
20
20
|
|
21
21
|
import time
|
22
|
-
import warnings
|
23
22
|
from typing import Sequence
|
24
23
|
|
25
24
|
import google.api_core.path_template
|
25
|
+
from deprecated import deprecated
|
26
26
|
from googleapiclient.discovery import build
|
27
27
|
|
28
28
|
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
@@ -32,6 +32,15 @@ from airflow.providers.google.common.hooks.base_google import GoogleBaseHook
|
|
32
32
|
TIME_TO_SLEEP_IN_SECONDS = 5
|
33
33
|
|
34
34
|
|
35
|
+
@deprecated(
|
36
|
+
reason=(
|
37
|
+
"This hook is deprecated. Consider using "
|
38
|
+
"Google Cloud Batch Operators' hook instead. "
|
39
|
+
"The Life Sciences API (beta) will be discontinued "
|
40
|
+
"on July 8, 2025 in favor of Google Cloud Batch."
|
41
|
+
),
|
42
|
+
category=AirflowProviderDeprecationWarning,
|
43
|
+
)
|
35
44
|
class LifeSciencesHook(GoogleBaseHook):
|
36
45
|
"""
|
37
46
|
Hook for the Google Cloud Life Sciences APIs.
|
@@ -76,17 +85,9 @@ class LifeSciencesHook(GoogleBaseHook):
|
|
76
85
|
)
|
77
86
|
self.api_version = api_version
|
78
87
|
|
79
|
-
warnings.warn(
|
80
|
-
"""This hook is deprecated. Consider using Google Cloud Batch Operators' hook instead.
|
81
|
-
The Life Sciences API (beta) will be discontinued on July 8, 2025 in favor
|
82
|
-
of Google Cloud Batch.""",
|
83
|
-
AirflowProviderDeprecationWarning,
|
84
|
-
stacklevel=3,
|
85
|
-
)
|
86
|
-
|
87
88
|
def get_conn(self) -> build:
|
88
89
|
"""
|
89
|
-
|
90
|
+
Retrieve the connection to Cloud Life Sciences.
|
90
91
|
|
91
92
|
:return: Google Cloud Life Sciences service object.
|
92
93
|
"""
|
@@ -98,7 +99,7 @@ class LifeSciencesHook(GoogleBaseHook):
|
|
98
99
|
@GoogleBaseHook.fallback_to_default_project_id
|
99
100
|
def run_pipeline(self, body: dict, location: str, project_id: str) -> dict:
|
100
101
|
"""
|
101
|
-
|
102
|
+
Run a pipeline.
|
102
103
|
|
103
104
|
:param body: The request body.
|
104
105
|
:param location: The location of the project. For example: "us-east1".
|
@@ -136,7 +137,7 @@ class LifeSciencesHook(GoogleBaseHook):
|
|
136
137
|
|
137
138
|
def _wait_for_operation_to_complete(self, operation_name: str) -> None:
|
138
139
|
"""
|
139
|
-
|
140
|
+
Wait for the named operation to complete - checks status of the asynchronous call.
|
140
141
|
|
141
142
|
:param operation_name: The name of the operation.
|
142
143
|
:return: The response returned by the operation.
|
@@ -41,9 +41,8 @@ class LookerHook(BaseHook):
|
|
41
41
|
def __init__(
|
42
42
|
self,
|
43
43
|
looker_conn_id: str,
|
44
|
-
**kwargs,
|
45
44
|
) -> None:
|
46
|
-
super().__init__(
|
45
|
+
super().__init__()
|
47
46
|
self.looker_conn_id = looker_conn_id
|
48
47
|
# source is used to track origin of the requests
|
49
48
|
self.source = f"airflow:{version}"
|
@@ -55,7 +54,7 @@ class LookerHook(BaseHook):
|
|
55
54
|
query_params: dict | None = None,
|
56
55
|
):
|
57
56
|
"""
|
58
|
-
|
57
|
+
Submit a PDT materialization job to Looker.
|
59
58
|
|
60
59
|
:param model: Required. The model of the PDT to start building.
|
61
60
|
:param view: Required. The view of the PDT to start building.
|
@@ -84,7 +83,7 @@ class LookerHook(BaseHook):
|
|
84
83
|
materialization_id: str,
|
85
84
|
):
|
86
85
|
"""
|
87
|
-
|
86
|
+
Get the PDT materialization job status from Looker.
|
88
87
|
|
89
88
|
:param materialization_id: Required. The materialization id to check status for.
|
90
89
|
"""
|
@@ -101,7 +100,7 @@ class LookerHook(BaseHook):
|
|
101
100
|
materialization_id: str,
|
102
101
|
) -> dict:
|
103
102
|
"""
|
104
|
-
|
103
|
+
Get the PDT materialization job status.
|
105
104
|
|
106
105
|
:param materialization_id: Required. The materialization id to check status for.
|
107
106
|
"""
|
@@ -121,7 +120,7 @@ class LookerHook(BaseHook):
|
|
121
120
|
materialization_id: str,
|
122
121
|
):
|
123
122
|
"""
|
124
|
-
|
123
|
+
Start a PDT materialization job cancellation request.
|
125
124
|
|
126
125
|
:param materialization_id: Required. The materialization id to stop.
|
127
126
|
"""
|
@@ -141,7 +140,7 @@ class LookerHook(BaseHook):
|
|
141
140
|
timeout: int | None = None,
|
142
141
|
) -> None:
|
143
142
|
"""
|
144
|
-
|
143
|
+
Poll a PDT materialization job to check if it finishes.
|
145
144
|
|
146
145
|
:param materialization_id: Required. The materialization id to wait for.
|
147
146
|
:param wait_time: Optional. Number of seconds between checks.
|
@@ -186,7 +185,7 @@ class LookerHook(BaseHook):
|
|
186
185
|
self.log.info("PDT materialization job completed successfully. Job id: %s.", materialization_id)
|
187
186
|
|
188
187
|
def get_looker_sdk(self):
|
189
|
-
"""
|
188
|
+
"""Return Looker SDK client for Looker API 4.0."""
|
190
189
|
conn = self.get_connection(self.looker_conn_id)
|
191
190
|
settings = LookerApiSettings(conn)
|
192
191
|
|
@@ -212,7 +211,7 @@ class LookerApiSettings(api_settings.ApiSettings):
|
|
212
211
|
|
213
212
|
def read_config(self):
|
214
213
|
"""
|
215
|
-
|
214
|
+
Fetch the connection settings from Airflow's connection object.
|
216
215
|
|
217
216
|
Overrides the default logic of getting connection settings.
|
218
217
|
"""
|