apache-airflow-providers-google 16.0.0rc1__py3-none-any.whl → 16.1.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 +9 -5
- airflow/providers/google/ads/operators/ads.py +1 -1
- airflow/providers/google/ads/transfers/ads_to_gcs.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +2 -3
- airflow/providers/google/cloud/hooks/cloud_sql.py +8 -4
- airflow/providers/google/cloud/hooks/datacatalog.py +9 -1
- airflow/providers/google/cloud/hooks/dataflow.py +2 -2
- airflow/providers/google/cloud/hooks/dataplex.py +1 -1
- airflow/providers/google/cloud/hooks/dataprep.py +4 -1
- airflow/providers/google/cloud/hooks/gcs.py +2 -2
- airflow/providers/google/cloud/hooks/looker.py +5 -1
- airflow/providers/google/cloud/hooks/mlengine.py +2 -1
- airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
- airflow/providers/google/cloud/hooks/spanner.py +2 -2
- airflow/providers/google/cloud/hooks/translate.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +307 -7
- airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +43 -14
- airflow/providers/google/cloud/hooks/vertex_ai/ray.py +11 -2
- airflow/providers/google/cloud/hooks/vision.py +2 -2
- airflow/providers/google/cloud/links/alloy_db.py +0 -46
- airflow/providers/google/cloud/links/base.py +75 -11
- 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/cloud_run.py +1 -33
- airflow/providers/google/cloud/links/cloud_sql.py +0 -33
- airflow/providers/google/cloud/links/cloud_storage_transfer.py +16 -43
- airflow/providers/google/cloud/links/cloud_tasks.py +6 -25
- 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 +14 -90
- airflow/providers/google/cloud/links/datastore.py +0 -31
- airflow/providers/google/cloud/links/kubernetes_engine.py +5 -59
- airflow/providers/google/cloud/links/life_sciences.py +0 -19
- 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 +16 -186
- airflow/providers/google/cloud/links/vertex_ai.py +8 -224
- airflow/providers/google/cloud/links/workflows.py +0 -52
- airflow/providers/google/cloud/operators/alloy_db.py +69 -54
- airflow/providers/google/cloud/operators/automl.py +16 -14
- airflow/providers/google/cloud/operators/bigquery.py +0 -15
- airflow/providers/google/cloud/operators/bigquery_dts.py +2 -4
- airflow/providers/google/cloud/operators/bigtable.py +35 -6
- airflow/providers/google/cloud/operators/cloud_base.py +21 -1
- airflow/providers/google/cloud/operators/cloud_build.py +74 -31
- airflow/providers/google/cloud/operators/cloud_composer.py +34 -35
- airflow/providers/google/cloud/operators/cloud_memorystore.py +68 -42
- airflow/providers/google/cloud/operators/cloud_run.py +0 -1
- airflow/providers/google/cloud/operators/cloud_sql.py +11 -15
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +0 -2
- airflow/providers/google/cloud/operators/compute.py +7 -39
- airflow/providers/google/cloud/operators/datacatalog.py +156 -20
- airflow/providers/google/cloud/operators/dataflow.py +37 -14
- airflow/providers/google/cloud/operators/dataform.py +14 -4
- airflow/providers/google/cloud/operators/datafusion.py +4 -12
- airflow/providers/google/cloud/operators/dataplex.py +180 -96
- airflow/providers/google/cloud/operators/dataprep.py +0 -4
- airflow/providers/google/cloud/operators/dataproc.py +10 -16
- airflow/providers/google/cloud/operators/dataproc_metastore.py +95 -87
- airflow/providers/google/cloud/operators/datastore.py +21 -5
- airflow/providers/google/cloud/operators/dlp.py +3 -26
- airflow/providers/google/cloud/operators/functions.py +15 -6
- airflow/providers/google/cloud/operators/gcs.py +0 -7
- airflow/providers/google/cloud/operators/kubernetes_engine.py +50 -7
- airflow/providers/google/cloud/operators/life_sciences.py +0 -1
- airflow/providers/google/cloud/operators/managed_kafka.py +106 -51
- airflow/providers/google/cloud/operators/mlengine.py +0 -1
- airflow/providers/google/cloud/operators/pubsub.py +2 -4
- airflow/providers/google/cloud/operators/spanner.py +0 -4
- airflow/providers/google/cloud/operators/speech_to_text.py +0 -1
- airflow/providers/google/cloud/operators/stackdriver.py +0 -8
- airflow/providers/google/cloud/operators/tasks.py +0 -11
- airflow/providers/google/cloud/operators/text_to_speech.py +0 -1
- airflow/providers/google/cloud/operators/translate.py +37 -13
- airflow/providers/google/cloud/operators/translate_speech.py +0 -1
- airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +31 -18
- airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +28 -8
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +38 -25
- airflow/providers/google/cloud/operators/vertex_ai/dataset.py +69 -7
- airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +42 -8
- airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +531 -0
- airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +93 -25
- airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +10 -8
- airflow/providers/google/cloud/operators/vertex_ai/model_service.py +56 -10
- airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +25 -6
- airflow/providers/google/cloud/operators/vertex_ai/ray.py +9 -6
- airflow/providers/google/cloud/operators/workflows.py +1 -9
- airflow/providers/google/cloud/sensors/bigquery.py +1 -1
- airflow/providers/google/cloud/sensors/bigquery_dts.py +6 -1
- airflow/providers/google/cloud/sensors/bigtable.py +15 -3
- airflow/providers/google/cloud/sensors/cloud_composer.py +6 -1
- airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +6 -1
- airflow/providers/google/cloud/sensors/dataflow.py +3 -3
- airflow/providers/google/cloud/sensors/dataform.py +6 -1
- airflow/providers/google/cloud/sensors/datafusion.py +6 -1
- airflow/providers/google/cloud/sensors/dataplex.py +6 -1
- airflow/providers/google/cloud/sensors/dataprep.py +6 -1
- airflow/providers/google/cloud/sensors/dataproc.py +6 -1
- airflow/providers/google/cloud/sensors/dataproc_metastore.py +6 -1
- airflow/providers/google/cloud/sensors/gcs.py +9 -3
- airflow/providers/google/cloud/sensors/looker.py +6 -1
- airflow/providers/google/cloud/sensors/pubsub.py +8 -3
- airflow/providers/google/cloud/sensors/tasks.py +6 -1
- airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +6 -1
- airflow/providers/google/cloud/sensors/workflows.py +6 -1
- airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +1 -2
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -2
- airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +0 -1
- airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -1
- airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +1 -2
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/gcs_to_local.py +1 -1
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -1
- airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +5 -1
- airflow/providers/google/cloud/transfers/gdrive_to_local.py +1 -1
- airflow/providers/google/cloud/transfers/http_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/sheets_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/sql_to_gcs.py +1 -1
- airflow/providers/google/cloud/utils/field_validator.py +1 -2
- airflow/providers/google/common/auth_backend/google_openid.py +2 -1
- airflow/providers/google/common/deprecated.py +2 -1
- airflow/providers/google/common/hooks/base_google.py +7 -3
- airflow/providers/google/common/links/storage.py +0 -22
- airflow/providers/google/firebase/operators/firestore.py +1 -1
- airflow/providers/google/get_provider_info.py +0 -11
- airflow/providers/google/leveldb/hooks/leveldb.py +5 -1
- airflow/providers/google/leveldb/operators/leveldb.py +1 -1
- airflow/providers/google/marketing_platform/links/analytics_admin.py +3 -6
- airflow/providers/google/marketing_platform/operators/analytics_admin.py +0 -1
- airflow/providers/google/marketing_platform/operators/campaign_manager.py +4 -4
- airflow/providers/google/marketing_platform/operators/display_video.py +6 -6
- airflow/providers/google/marketing_platform/operators/search_ads.py +1 -1
- airflow/providers/google/marketing_platform/sensors/campaign_manager.py +6 -1
- airflow/providers/google/marketing_platform/sensors/display_video.py +6 -1
- airflow/providers/google/suite/operators/sheets.py +3 -3
- airflow/providers/google/suite/sensors/drive.py +6 -1
- airflow/providers/google/suite/transfers/gcs_to_gdrive.py +1 -1
- airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
- airflow/providers/google/suite/transfers/local_to_drive.py +1 -1
- airflow/providers/google/version_compat.py +28 -0
- {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/METADATA +27 -28
- {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/RECORD +166 -166
- {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/entry_points.txt +0 -0
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
|
|
29
29
|
|
30
30
|
__all__ = ["__version__"]
|
31
31
|
|
32
|
-
__version__ = "16.
|
32
|
+
__version__ = "16.1.0"
|
33
33
|
|
34
34
|
if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
|
35
35
|
"2.10.0"
|
@@ -28,14 +28,18 @@ from google.ads.googleads.errors import GoogleAdsException
|
|
28
28
|
from google.auth.exceptions import GoogleAuthError
|
29
29
|
|
30
30
|
from airflow.exceptions import AirflowException
|
31
|
-
from airflow.hooks.base import BaseHook
|
32
31
|
from airflow.providers.google.common.hooks.base_google import get_field
|
33
32
|
|
33
|
+
try:
|
34
|
+
from airflow.sdk import BaseHook
|
35
|
+
except ImportError:
|
36
|
+
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
37
|
+
|
34
38
|
if TYPE_CHECKING:
|
35
|
-
from google.ads.googleads.
|
36
|
-
from google.ads.googleads.
|
37
|
-
from google.ads.googleads.
|
38
|
-
from google.ads.googleads.
|
39
|
+
from google.ads.googleads.v20.services.services.customer_service import CustomerServiceClient
|
40
|
+
from google.ads.googleads.v20.services.services.google_ads_service import GoogleAdsServiceClient
|
41
|
+
from google.ads.googleads.v20.services.services.google_ads_service.pagers import SearchPager
|
42
|
+
from google.ads.googleads.v20.services.types.google_ads_service import GoogleAdsRow
|
39
43
|
|
40
44
|
|
41
45
|
class GoogleAdsHook(BaseHook):
|
@@ -24,9 +24,9 @@ from collections.abc import Sequence
|
|
24
24
|
from tempfile import NamedTemporaryFile
|
25
25
|
from typing import TYPE_CHECKING
|
26
26
|
|
27
|
-
from airflow.models import BaseOperator
|
28
27
|
from airflow.providers.google.ads.hooks.ads import GoogleAdsHook
|
29
28
|
from airflow.providers.google.cloud.hooks.gcs import GCSHook
|
29
|
+
from airflow.providers.google.version_compat import BaseOperator
|
30
30
|
|
31
31
|
if TYPE_CHECKING:
|
32
32
|
from airflow.utils.context import Context
|
@@ -22,9 +22,9 @@ from operator import attrgetter
|
|
22
22
|
from tempfile import NamedTemporaryFile
|
23
23
|
from typing import TYPE_CHECKING
|
24
24
|
|
25
|
-
from airflow.models import BaseOperator
|
26
25
|
from airflow.providers.google.ads.hooks.ads import GoogleAdsHook
|
27
26
|
from airflow.providers.google.cloud.hooks.gcs import GCSHook
|
27
|
+
from airflow.providers.google.version_compat import BaseOperator
|
28
28
|
|
29
29
|
if TYPE_CHECKING:
|
30
30
|
from airflow.utils.context import Context
|
@@ -29,7 +29,7 @@ import uuid
|
|
29
29
|
from collections.abc import Iterable, Mapping, Sequence
|
30
30
|
from copy import deepcopy
|
31
31
|
from datetime import datetime, timedelta
|
32
|
-
from typing import TYPE_CHECKING, Any,
|
32
|
+
from typing import TYPE_CHECKING, Any, Literal, NoReturn, cast, overload
|
33
33
|
|
34
34
|
from aiohttp import ClientSession as ClientSession
|
35
35
|
from gcloud.aio.bigquery import Job, Table as Table_async
|
@@ -57,7 +57,6 @@ from googleapiclient.discovery import build
|
|
57
57
|
from pandas_gbq import read_gbq
|
58
58
|
from pandas_gbq.gbq import GbqConnector # noqa: F401 used in ``airflow.contrib.hooks.bigquery``
|
59
59
|
from sqlalchemy import create_engine
|
60
|
-
from typing_extensions import Literal
|
61
60
|
|
62
61
|
from airflow.exceptions import (
|
63
62
|
AirflowException,
|
@@ -89,7 +88,7 @@ if TYPE_CHECKING:
|
|
89
88
|
|
90
89
|
log = logging.getLogger(__name__)
|
91
90
|
|
92
|
-
BigQueryJob =
|
91
|
+
BigQueryJob = CopyJob | QueryJob | LoadJob | ExtractJob
|
93
92
|
|
94
93
|
|
95
94
|
class BigQueryHook(GoogleBaseHook, DbApiHook):
|
@@ -38,7 +38,7 @@ from inspect import signature
|
|
38
38
|
from pathlib import Path
|
39
39
|
from subprocess import PIPE, Popen
|
40
40
|
from tempfile import NamedTemporaryFile, _TemporaryFileWrapper, gettempdir
|
41
|
-
from typing import TYPE_CHECKING, Any
|
41
|
+
from typing import TYPE_CHECKING, Any, cast
|
42
42
|
from urllib.parse import quote_plus
|
43
43
|
|
44
44
|
import httpx
|
@@ -50,7 +50,6 @@ from googleapiclient.errors import HttpError
|
|
50
50
|
# Number of retries - used by googleapiclient method calls to perform retries
|
51
51
|
# For requests that are "retriable"
|
52
52
|
from airflow.exceptions import AirflowException
|
53
|
-
from airflow.hooks.base import BaseHook
|
54
53
|
from airflow.models import Connection
|
55
54
|
from airflow.providers.google.cloud.hooks.secret_manager import (
|
56
55
|
GoogleCloudSecretManagerHook,
|
@@ -61,6 +60,11 @@ from airflow.providers.google.common.hooks.base_google import (
|
|
61
60
|
GoogleBaseHook,
|
62
61
|
get_field,
|
63
62
|
)
|
63
|
+
|
64
|
+
try:
|
65
|
+
from airflow.sdk import BaseHook
|
66
|
+
except ImportError:
|
67
|
+
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
64
68
|
from airflow.utils.log.logging_mixin import LoggingMixin
|
65
69
|
|
66
70
|
if TYPE_CHECKING:
|
@@ -847,8 +851,8 @@ class CloudSQLDatabaseHook(BaseHook):
|
|
847
851
|
self.user = self._get_iam_db_login()
|
848
852
|
self.password = self._generate_login_token(service_account=self.cloudsql_connection.login)
|
849
853
|
else:
|
850
|
-
self.user = self.cloudsql_connection.login
|
851
|
-
self.password = self.cloudsql_connection.password
|
854
|
+
self.user = cast("str", self.cloudsql_connection.login)
|
855
|
+
self.password = cast("str", self.cloudsql_connection.password)
|
852
856
|
self.public_ip = self.cloudsql_connection.host
|
853
857
|
self.public_port = self.cloudsql_connection.port
|
854
858
|
self.ssl_cert = ssl_cert
|
@@ -32,8 +32,9 @@ from google.cloud.datacatalog import (
|
|
32
32
|
TagTemplateField,
|
33
33
|
)
|
34
34
|
|
35
|
-
from airflow.exceptions import AirflowException
|
35
|
+
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
36
36
|
from airflow.providers.google.common.consts import CLIENT_INFO
|
37
|
+
from airflow.providers.google.common.deprecated import deprecated
|
37
38
|
from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
|
38
39
|
|
39
40
|
if TYPE_CHECKING:
|
@@ -41,6 +42,13 @@ if TYPE_CHECKING:
|
|
41
42
|
from google.protobuf.field_mask_pb2 import FieldMask
|
42
43
|
|
43
44
|
|
45
|
+
@deprecated(
|
46
|
+
planned_removal_date="January 30, 2026",
|
47
|
+
use_instead="airflow.providers.google.cloud.hooks.dataplex.DataplexHook",
|
48
|
+
reason="The Data Catalog will be discontinued on January 30, 2026 "
|
49
|
+
"in favor of Dataplex Universal Catalog.",
|
50
|
+
category=AirflowProviderDeprecationWarning,
|
51
|
+
)
|
44
52
|
class CloudDataCatalogHook(GoogleBaseHook):
|
45
53
|
"""
|
46
54
|
Hook for Google Cloud Data Catalog Service.
|
@@ -27,9 +27,9 @@ import subprocess
|
|
27
27
|
import time
|
28
28
|
import uuid
|
29
29
|
import warnings
|
30
|
-
from collections.abc import Generator, Sequence
|
30
|
+
from collections.abc import Callable, Generator, Sequence
|
31
31
|
from copy import deepcopy
|
32
|
-
from typing import TYPE_CHECKING, Any,
|
32
|
+
from typing import TYPE_CHECKING, Any, TypeVar, cast
|
33
33
|
|
34
34
|
from google.cloud.dataflow_v1beta3 import (
|
35
35
|
GetJobRequest,
|
@@ -515,7 +515,7 @@ class DataplexHook(GoogleBaseHook, OperationHelper):
|
|
515
515
|
fields are non-required and omitted in the request body, their values are emptied.
|
516
516
|
:param allow_missing: Optional. If set to true and entry doesn't exist, the service will create it.
|
517
517
|
:param delete_missing_aspects: Optional. If set to true and the aspect_keys specify aspect
|
518
|
-
ranges, the service deletes any existing aspects from that range that
|
518
|
+
ranges, the service deletes any existing aspects from that range that were not provided
|
519
519
|
in the request.
|
520
520
|
:param aspect_keys: Optional. The map keys of the Aspects which the service should modify.
|
521
521
|
It supports the following syntax:
|
@@ -28,7 +28,10 @@ import requests
|
|
28
28
|
from requests import HTTPError
|
29
29
|
from tenacity import retry, stop_after_attempt, wait_exponential
|
30
30
|
|
31
|
-
|
31
|
+
try:
|
32
|
+
from airflow.sdk import BaseHook
|
33
|
+
except ImportError:
|
34
|
+
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
32
35
|
|
33
36
|
|
34
37
|
def _get_field(extras: dict, field_name: str) -> str | None:
|
@@ -26,12 +26,12 @@ import os
|
|
26
26
|
import shutil
|
27
27
|
import time
|
28
28
|
import warnings
|
29
|
-
from collections.abc import Generator, Sequence
|
29
|
+
from collections.abc import Callable, Generator, Sequence
|
30
30
|
from contextlib import contextmanager
|
31
31
|
from functools import partial
|
32
32
|
from io import BytesIO
|
33
33
|
from tempfile import NamedTemporaryFile
|
34
|
-
from typing import IO, TYPE_CHECKING, Any,
|
34
|
+
from typing import IO, TYPE_CHECKING, Any, TypeVar, cast, overload
|
35
35
|
from urllib.parse import urlsplit
|
36
36
|
|
37
37
|
from gcloud.aio.storage import Storage
|
@@ -29,7 +29,11 @@ from looker_sdk.sdk.api40 import methods as methods40
|
|
29
29
|
from packaging.version import parse as parse_version
|
30
30
|
|
31
31
|
from airflow.exceptions import AirflowException
|
32
|
-
|
32
|
+
|
33
|
+
try:
|
34
|
+
from airflow.sdk import BaseHook
|
35
|
+
except ImportError:
|
36
|
+
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
33
37
|
from airflow.version import version
|
34
38
|
|
35
39
|
if TYPE_CHECKING:
|
@@ -23,7 +23,8 @@ import contextlib
|
|
23
23
|
import logging
|
24
24
|
import random
|
25
25
|
import time
|
26
|
-
from
|
26
|
+
from collections.abc import Callable
|
27
|
+
from typing import TYPE_CHECKING
|
27
28
|
|
28
29
|
from aiohttp import ClientSession
|
29
30
|
from gcloud.aio.auth import AioSession, Token
|
@@ -47,6 +47,10 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
47
47
|
See https://cloud.google.com/secret-manager
|
48
48
|
"""
|
49
49
|
|
50
|
+
def __init__(self, location: str | None = None, **kwargs) -> None:
|
51
|
+
super().__init__(**kwargs)
|
52
|
+
self.location = location
|
53
|
+
|
50
54
|
@cached_property
|
51
55
|
def client(self):
|
52
56
|
"""
|
@@ -54,7 +58,16 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
54
58
|
|
55
59
|
:return: Secret Manager client.
|
56
60
|
"""
|
57
|
-
|
61
|
+
if self.location is not None:
|
62
|
+
return SecretManagerServiceClient(
|
63
|
+
credentials=self.get_credentials(),
|
64
|
+
client_info=CLIENT_INFO,
|
65
|
+
client_options={"api_endpoint": f"secretmanager.{self.location}.rep.googleapis.com"},
|
66
|
+
)
|
67
|
+
return SecretManagerServiceClient(
|
68
|
+
credentials=self.get_credentials(),
|
69
|
+
client_info=CLIENT_INFO,
|
70
|
+
)
|
58
71
|
|
59
72
|
def get_conn(self) -> SecretManagerServiceClient:
|
60
73
|
"""
|
@@ -64,6 +77,60 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
64
77
|
"""
|
65
78
|
return self.client
|
66
79
|
|
80
|
+
def _get_parent(self, project_id: str, location: str | None = None) -> str:
|
81
|
+
"""
|
82
|
+
Return parent path.
|
83
|
+
|
84
|
+
:param project_id: Required. ID of the GCP project that owns the job.
|
85
|
+
:param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
86
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
87
|
+
|
88
|
+
:return: Parent path.
|
89
|
+
"""
|
90
|
+
_location = location or self.location
|
91
|
+
if _location is not None:
|
92
|
+
return self.client.common_location_path(project_id, _location)
|
93
|
+
return self.client.common_project_path(project_id)
|
94
|
+
|
95
|
+
def _get_secret_path(self, project_id: str, secret_id: str, location: str | None = None) -> str:
|
96
|
+
"""
|
97
|
+
Return secret path.
|
98
|
+
|
99
|
+
:param project_id: Required. ID of the GCP project that owns the job.
|
100
|
+
:param secret_id: Required. Secret ID for which path is required.
|
101
|
+
:param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
102
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
103
|
+
|
104
|
+
:return: Parent path.
|
105
|
+
"""
|
106
|
+
_location = location or self.location
|
107
|
+
if _location is not None:
|
108
|
+
# Google's client library does not provide a method to construct regional secret paths, so constructing manually.
|
109
|
+
return f"projects/{project_id}/locations/{_location}/secrets/{secret_id}"
|
110
|
+
return self.client.secret_path(project_id, secret_id)
|
111
|
+
|
112
|
+
def _get_secret_version_path(
|
113
|
+
self, project_id: str, secret_id: str, secret_version: str, location: str | None = None
|
114
|
+
) -> str:
|
115
|
+
"""
|
116
|
+
Return secret version path.
|
117
|
+
|
118
|
+
:param project_id: Required. ID of the GCP project that owns the job.
|
119
|
+
:param secret_id: Required. Secret ID for which path is required.
|
120
|
+
:param secret_version: Required. Secret version for which path is required.
|
121
|
+
:param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
122
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
123
|
+
|
124
|
+
:return: Parent path.
|
125
|
+
"""
|
126
|
+
_location = location or self.location
|
127
|
+
if _location is not None:
|
128
|
+
# Google's client library does not provide a method to construct regional secret version paths, so constructing manually.
|
129
|
+
return (
|
130
|
+
f"projects/{project_id}/locations/{_location}/secrets/{secret_id}/versions/{secret_version}"
|
131
|
+
)
|
132
|
+
return self.client.secret_version_path(project_id, secret_id, secret_version)
|
133
|
+
|
67
134
|
@GoogleBaseHook.fallback_to_default_project_id
|
68
135
|
def create_secret(
|
69
136
|
self,
|
@@ -73,6 +140,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
73
140
|
retry: Retry | _MethodDefault = DEFAULT,
|
74
141
|
timeout: float | None = None,
|
75
142
|
metadata: Sequence[tuple[str, str]] = (),
|
143
|
+
location: str | None = None,
|
76
144
|
) -> Secret:
|
77
145
|
"""
|
78
146
|
Create a secret.
|
@@ -88,12 +156,20 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
88
156
|
:param retry: Optional. Designation of what errors, if any, should be retried.
|
89
157
|
:param timeout: Optional. The timeout for this request.
|
90
158
|
:param metadata: Optional. Strings which should be sent along with the request as metadata.
|
159
|
+
:param location: Optional. Location where secret should be created. Used for creating regional secret. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
160
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
91
161
|
:return: Secret object.
|
92
162
|
"""
|
93
|
-
|
163
|
+
if not secret:
|
164
|
+
_secret: dict | Secret = {}
|
165
|
+
if (location or self.location) is None:
|
166
|
+
_secret["replication"] = {"automatic": {}}
|
167
|
+
else:
|
168
|
+
_secret = secret
|
169
|
+
|
94
170
|
response = self.client.create_secret(
|
95
171
|
request={
|
96
|
-
"parent":
|
172
|
+
"parent": self._get_parent(project_id, location),
|
97
173
|
"secret_id": secret_id,
|
98
174
|
"secret": _secret,
|
99
175
|
},
|
@@ -113,6 +189,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
113
189
|
retry: Retry | _MethodDefault = DEFAULT,
|
114
190
|
timeout: float | None = None,
|
115
191
|
metadata: Sequence[tuple[str, str]] = (),
|
192
|
+
location: str | None = None,
|
116
193
|
) -> SecretVersion:
|
117
194
|
"""
|
118
195
|
Add a version to the secret.
|
@@ -128,11 +205,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
128
205
|
:param retry: Optional. Designation of what errors, if any, should be retried.
|
129
206
|
:param timeout: Optional. The timeout for this request.
|
130
207
|
:param metadata: Optional. Strings which should be sent along with the request as metadata.
|
208
|
+
:param location: Optional. Location where secret is located. Used for adding version to regional secret. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
209
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
131
210
|
:return: Secret version object.
|
132
211
|
"""
|
133
212
|
response = self.client.add_secret_version(
|
134
213
|
request={
|
135
|
-
"parent":
|
214
|
+
"parent": self._get_secret_path(project_id, secret_id, location),
|
136
215
|
"payload": secret_payload,
|
137
216
|
},
|
138
217
|
retry=retry,
|
@@ -152,6 +231,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
152
231
|
retry: Retry | _MethodDefault = DEFAULT,
|
153
232
|
timeout: float | None = None,
|
154
233
|
metadata: Sequence[tuple[str, str]] = (),
|
234
|
+
location: str | None = None,
|
155
235
|
) -> ListSecretsPager:
|
156
236
|
"""
|
157
237
|
List secrets.
|
@@ -168,11 +248,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
168
248
|
:param retry: Optional. Designation of what errors, if any, should be retried.
|
169
249
|
:param timeout: Optional. The timeout for this request.
|
170
250
|
:param metadata: Optional. Strings which should be sent along with the request as metadata.
|
251
|
+
:param location: Optional. The regional secrets stored in the provided location will be listed. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
252
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
171
253
|
:return: Secret List object.
|
172
254
|
"""
|
173
255
|
response = self.client.list_secrets(
|
174
256
|
request={
|
175
|
-
"parent":
|
257
|
+
"parent": self._get_parent(project_id, location),
|
176
258
|
"page_size": page_size,
|
177
259
|
"page_token": page_token,
|
178
260
|
"filter": secret_filter,
|
@@ -185,18 +267,22 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
185
267
|
return response
|
186
268
|
|
187
269
|
@GoogleBaseHook.fallback_to_default_project_id
|
188
|
-
def secret_exists(self, project_id: str, secret_id: str) -> bool:
|
270
|
+
def secret_exists(self, project_id: str, secret_id: str, location: str | None = None) -> bool:
|
189
271
|
"""
|
190
272
|
Check whether secret exists.
|
191
273
|
|
192
274
|
:param project_id: Required. ID of the GCP project that owns the job.
|
193
275
|
If set to ``None`` or missing, the default project_id from the GCP connection is used.
|
194
276
|
:param secret_id: Required. ID of the secret to find.
|
277
|
+
:param location: Optional. Location where secret is expected to be stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
278
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
195
279
|
:return: True if the secret exists, False otherwise.
|
196
280
|
"""
|
197
281
|
secret_filter = f"name:{secret_id}"
|
198
|
-
secret_name = self.
|
199
|
-
for secret in self.list_secrets(
|
282
|
+
secret_name = self._get_secret_path(project_id, secret_id, location)
|
283
|
+
for secret in self.list_secrets(
|
284
|
+
project_id=project_id, page_size=100, secret_filter=secret_filter, location=location
|
285
|
+
):
|
200
286
|
if secret.name.split("/")[-1] == secret_id:
|
201
287
|
self.log.info("Secret %s exists.", secret_name)
|
202
288
|
return True
|
@@ -212,6 +298,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
212
298
|
retry: Retry | _MethodDefault = DEFAULT,
|
213
299
|
timeout: float | None = None,
|
214
300
|
metadata: Sequence[tuple[str, str]] = (),
|
301
|
+
location: str | None = None,
|
215
302
|
) -> AccessSecretVersionResponse:
|
216
303
|
"""
|
217
304
|
Access a secret version.
|
@@ -227,11 +314,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
227
314
|
:param retry: Optional. Designation of what errors, if any, should be retried.
|
228
315
|
:param timeout: Optional. The timeout for this request.
|
229
316
|
:param metadata: Optional. Strings which should be sent along with the request as metadata.
|
317
|
+
:param location: Optional. Location where secret is stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
|
318
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
230
319
|
:return: Access secret version response object.
|
231
320
|
"""
|
232
321
|
response = self.client.access_secret_version(
|
233
322
|
request={
|
234
|
-
"name": self.
|
323
|
+
"name": self._get_secret_version_path(project_id, secret_id, secret_version, location),
|
235
324
|
},
|
236
325
|
retry=retry,
|
237
326
|
timeout=timeout,
|
@@ -248,6 +337,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
248
337
|
retry: Retry | _MethodDefault = DEFAULT,
|
249
338
|
timeout: float | None = None,
|
250
339
|
metadata: Sequence[tuple[str, str]] = (),
|
340
|
+
location: str | None = None,
|
251
341
|
) -> None:
|
252
342
|
"""
|
253
343
|
Delete a secret.
|
@@ -262,9 +352,11 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
|
|
262
352
|
:param retry: Optional. Designation of what errors, if any, should be retried.
|
263
353
|
:param timeout: Optional. The timeout for this request.
|
264
354
|
:param metadata: Optional. Strings which should be sent along with the request as metadata.
|
355
|
+
:param location: Optional. Location where secret is stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used.
|
356
|
+
For more details : https://cloud.google.com/secret-manager/docs/locations
|
265
357
|
:return: Access secret version response object.
|
266
358
|
"""
|
267
|
-
name = self.
|
359
|
+
name = self._get_secret_path(project_id, secret_id, location)
|
268
360
|
self.client.delete_secret(
|
269
361
|
request={"name": name},
|
270
362
|
retry=retry,
|
@@ -19,8 +19,8 @@
|
|
19
19
|
|
20
20
|
from __future__ import annotations
|
21
21
|
|
22
|
-
from collections.abc import Sequence
|
23
|
-
from typing import TYPE_CHECKING,
|
22
|
+
from collections.abc import Callable, Sequence
|
23
|
+
from typing import TYPE_CHECKING, NamedTuple
|
24
24
|
|
25
25
|
from google.api_core.exceptions import AlreadyExists, GoogleAPICallError
|
26
26
|
from google.cloud.spanner_v1.client import Client
|
@@ -429,7 +429,7 @@ class TranslateHook(GoogleBaseHook, OperationHelper):
|
|
429
429
|
project_id: str,
|
430
430
|
location: str,
|
431
431
|
retry: Retry | _MethodDefault = DEFAULT,
|
432
|
-
timeout: float | _MethodDefault = DEFAULT,
|
432
|
+
timeout: float | None | _MethodDefault = DEFAULT,
|
433
433
|
metadata: Sequence[tuple[str, str]] = (),
|
434
434
|
) -> automl_translation.Dataset:
|
435
435
|
"""
|