Skip to content

Commit 819be92

Browse files
feat: add database dialect (#671)
- [ ] Regenerate this pull request now. PiperOrigin-RevId: 423930262 Source-Link: googleapis/googleapis@b0c104f Source-Link: googleapis/googleapis-gen@4289d82 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNDI4OWQ4MjAwMGQ1NTQ1NjM1N2YwNWJlMDFiNzc2MzA4MmJiNzdiNiJ9 feat: add api key support
1 parent 979442c commit 819be92

File tree

22 files changed

+929
-234
lines changed

22 files changed

+929
-234
lines changed

google/cloud/spanner_admin_database_v1/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from .types.common import EncryptionConfig
3333
from .types.common import EncryptionInfo
3434
from .types.common import OperationProgress
35+
from .types.common import DatabaseDialect
3536
from .types.spanner_database_admin import CreateDatabaseMetadata
3637
from .types.spanner_database_admin import CreateDatabaseRequest
3738
from .types.spanner_database_admin import Database
@@ -63,6 +64,7 @@
6364
"CreateDatabaseRequest",
6465
"Database",
6566
"DatabaseAdminClient",
67+
"DatabaseDialect",
6668
"DeleteBackupRequest",
6769
"DropDatabaseRequest",
6870
"EncryptionConfig",

google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py

+46-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from collections import OrderedDict
1717
import functools
1818
import re
19-
from typing import Dict, Sequence, Tuple, Type, Union
19+
from typing import Dict, Optional, Sequence, Tuple, Type, Union
2020
import pkg_resources
2121

2222
from google.api_core.client_options import ClientOptions
@@ -51,11 +51,13 @@
5151

5252
class DatabaseAdminAsyncClient:
5353
"""Cloud Spanner Database Admin API
54-
The Cloud Spanner Database Admin API can be used to create,
55-
drop, and list databases. It also enables updating the schema of
56-
pre-existing databases. It can be also used to create, delete
57-
and list backups for a database and to restore from an existing
58-
backup.
54+
55+
The Cloud Spanner Database Admin API can be used to:
56+
57+
- create, drop, and list databases
58+
- update the schema of pre-existing databases
59+
- create, delete and list backups for a database
60+
- restore a database from an existing backup
5961
"""
6062

6163
_client: DatabaseAdminClient
@@ -133,6 +135,42 @@ def from_service_account_file(cls, filename: str, *args, **kwargs):
133135

134136
from_service_account_json = from_service_account_file
135137

138+
@classmethod
139+
def get_mtls_endpoint_and_cert_source(
140+
cls, client_options: Optional[ClientOptions] = None
141+
):
142+
"""Return the API endpoint and client cert source for mutual TLS.
143+
144+
The client cert source is determined in the following order:
145+
(1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
146+
client cert source is None.
147+
(2) if `client_options.client_cert_source` is provided, use the provided one; if the
148+
default client cert source exists, use the default one; otherwise the client cert
149+
source is None.
150+
151+
The API endpoint is determined in the following order:
152+
(1) if `client_options.api_endpoint` if provided, use the provided one.
153+
(2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
154+
default mTLS endpoint; if the environment variabel is "never", use the default API
155+
endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
156+
use the default API endpoint.
157+
158+
More details can be found at https://google.aip.dev/auth/4114.
159+
160+
Args:
161+
client_options (google.api_core.client_options.ClientOptions): Custom options for the
162+
client. Only the `api_endpoint` and `client_cert_source` properties may be used
163+
in this method.
164+
165+
Returns:
166+
Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
167+
client cert source to use.
168+
169+
Raises:
170+
google.auth.exceptions.MutualTLSChannelError: If any errors happen.
171+
"""
172+
return DatabaseAdminClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore
173+
136174
@property
137175
def transport(self) -> DatabaseAdminTransport:
138176
"""Returns the transport used by the client instance.
@@ -617,7 +655,8 @@ async def drop_database(
617655
) -> None:
618656
r"""Drops (aka deletes) a Cloud Spanner database. Completed backups
619657
for the database will be retained according to their
620-
``expire_time``.
658+
``expire_time``. Note: Cloud Spanner might continue to accept
659+
requests for a few seconds after the database has been deleted.
621660
622661
Args:
623662
request (Union[google.cloud.spanner_admin_database_v1.types.DropDatabaseRequest, dict]):

google/cloud/spanner_admin_database_v1/services/database_admin/client.py

+93-49
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ def get_transport_class(cls, label: str = None,) -> Type[DatabaseAdminTransport]
8585

8686
class DatabaseAdminClient(metaclass=DatabaseAdminClientMeta):
8787
"""Cloud Spanner Database Admin API
88-
The Cloud Spanner Database Admin API can be used to create,
89-
drop, and list databases. It also enables updating the schema of
90-
pre-existing databases. It can be also used to create, delete
91-
and list backups for a database and to restore from an existing
92-
backup.
88+
89+
The Cloud Spanner Database Admin API can be used to:
90+
91+
- create, drop, and list databases
92+
- update the schema of pre-existing databases
93+
- create, delete and list backups for a database
94+
- restore a database from an existing backup
9395
"""
9496

9597
@staticmethod
@@ -325,6 +327,73 @@ def parse_common_location_path(path: str) -> Dict[str, str]:
325327
m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
326328
return m.groupdict() if m else {}
327329

330+
@classmethod
331+
def get_mtls_endpoint_and_cert_source(
332+
cls, client_options: Optional[client_options_lib.ClientOptions] = None
333+
):
334+
"""Return the API endpoint and client cert source for mutual TLS.
335+
336+
The client cert source is determined in the following order:
337+
(1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
338+
client cert source is None.
339+
(2) if `client_options.client_cert_source` is provided, use the provided one; if the
340+
default client cert source exists, use the default one; otherwise the client cert
341+
source is None.
342+
343+
The API endpoint is determined in the following order:
344+
(1) if `client_options.api_endpoint` if provided, use the provided one.
345+
(2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
346+
default mTLS endpoint; if the environment variabel is "never", use the default API
347+
endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
348+
use the default API endpoint.
349+
350+
More details can be found at https://google.aip.dev/auth/4114.
351+
352+
Args:
353+
client_options (google.api_core.client_options.ClientOptions): Custom options for the
354+
client. Only the `api_endpoint` and `client_cert_source` properties may be used
355+
in this method.
356+
357+
Returns:
358+
Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
359+
client cert source to use.
360+
361+
Raises:
362+
google.auth.exceptions.MutualTLSChannelError: If any errors happen.
363+
"""
364+
if client_options is None:
365+
client_options = client_options_lib.ClientOptions()
366+
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
367+
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
368+
if use_client_cert not in ("true", "false"):
369+
raise ValueError(
370+
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
371+
)
372+
if use_mtls_endpoint not in ("auto", "never", "always"):
373+
raise MutualTLSChannelError(
374+
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
375+
)
376+
377+
# Figure out the client cert source to use.
378+
client_cert_source = None
379+
if use_client_cert == "true":
380+
if client_options.client_cert_source:
381+
client_cert_source = client_options.client_cert_source
382+
elif mtls.has_default_client_cert_source():
383+
client_cert_source = mtls.default_client_cert_source()
384+
385+
# Figure out which api endpoint to use.
386+
if client_options.api_endpoint is not None:
387+
api_endpoint = client_options.api_endpoint
388+
elif use_mtls_endpoint == "always" or (
389+
use_mtls_endpoint == "auto" and client_cert_source
390+
):
391+
api_endpoint = cls.DEFAULT_MTLS_ENDPOINT
392+
else:
393+
api_endpoint = cls.DEFAULT_ENDPOINT
394+
395+
return api_endpoint, client_cert_source
396+
328397
def __init__(
329398
self,
330399
*,
@@ -375,57 +444,22 @@ def __init__(
375444
if client_options is None:
376445
client_options = client_options_lib.ClientOptions()
377446

378-
# Create SSL credentials for mutual TLS if needed.
379-
if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in (
380-
"true",
381-
"false",
382-
):
383-
raise ValueError(
384-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
385-
)
386-
use_client_cert = (
387-
os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true"
447+
api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source(
448+
client_options
388449
)
389450

390-
client_cert_source_func = None
391-
is_mtls = False
392-
if use_client_cert:
393-
if client_options.client_cert_source:
394-
is_mtls = True
395-
client_cert_source_func = client_options.client_cert_source
396-
else:
397-
is_mtls = mtls.has_default_client_cert_source()
398-
if is_mtls:
399-
client_cert_source_func = mtls.default_client_cert_source()
400-
else:
401-
client_cert_source_func = None
402-
403-
# Figure out which api endpoint to use.
404-
if client_options.api_endpoint is not None:
405-
api_endpoint = client_options.api_endpoint
406-
else:
407-
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
408-
if use_mtls_env == "never":
409-
api_endpoint = self.DEFAULT_ENDPOINT
410-
elif use_mtls_env == "always":
411-
api_endpoint = self.DEFAULT_MTLS_ENDPOINT
412-
elif use_mtls_env == "auto":
413-
if is_mtls:
414-
api_endpoint = self.DEFAULT_MTLS_ENDPOINT
415-
else:
416-
api_endpoint = self.DEFAULT_ENDPOINT
417-
else:
418-
raise MutualTLSChannelError(
419-
"Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted "
420-
"values: never, auto, always"
421-
)
451+
api_key_value = getattr(client_options, "api_key", None)
452+
if api_key_value and credentials:
453+
raise ValueError(
454+
"client_options.api_key and credentials are mutually exclusive"
455+
)
422456

423457
# Save or instantiate the transport.
424458
# Ordinarily, we provide the transport, but allowing a custom transport
425459
# instance provides an extensibility point for unusual situations.
426460
if isinstance(transport, DatabaseAdminTransport):
427461
# transport is a DatabaseAdminTransport instance.
428-
if credentials or client_options.credentials_file:
462+
if credentials or client_options.credentials_file or api_key_value:
429463
raise ValueError(
430464
"When providing a transport instance, "
431465
"provide its credentials directly."
@@ -437,6 +471,15 @@ def __init__(
437471
)
438472
self._transport = transport
439473
else:
474+
import google.auth._default # type: ignore
475+
476+
if api_key_value and hasattr(
477+
google.auth._default, "get_api_key_credentials"
478+
):
479+
credentials = google.auth._default.get_api_key_credentials(
480+
api_key_value
481+
)
482+
440483
Transport = type(self).get_transport_class(transport)
441484
self._transport = Transport(
442485
credentials=credentials,
@@ -843,7 +886,8 @@ def drop_database(
843886
) -> None:
844887
r"""Drops (aka deletes) a Cloud Spanner database. Completed backups
845888
for the database will be retained according to their
846-
``expire_time``.
889+
``expire_time``. Note: Cloud Spanner might continue to accept
890+
requests for a few seconds after the database has been deleted.
847891
848892
Args:
849893
request (Union[google.cloud.spanner_admin_database_v1.types.DropDatabaseRequest, dict]):

google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ class DatabaseAdminGrpcTransport(DatabaseAdminTransport):
3939
"""gRPC backend transport for DatabaseAdmin.
4040
4141
Cloud Spanner Database Admin API
42-
The Cloud Spanner Database Admin API can be used to create,
43-
drop, and list databases. It also enables updating the schema of
44-
pre-existing databases. It can be also used to create, delete
45-
and list backups for a database and to restore from an existing
46-
backup.
42+
43+
The Cloud Spanner Database Admin API can be used to:
44+
45+
- create, drop, and list databases
46+
- update the schema of pre-existing databases
47+
- create, delete and list backups for a database
48+
- restore a database from an existing backup
4749
4850
This class defines the same methods as the primary client, so the
4951
primary client can load the underlying transport implementation
@@ -390,7 +392,8 @@ def drop_database(
390392
391393
Drops (aka deletes) a Cloud Spanner database. Completed backups
392394
for the database will be retained according to their
393-
``expire_time``.
395+
``expire_time``. Note: Cloud Spanner might continue to accept
396+
requests for a few seconds after the database has been deleted.
394397
395398
Returns:
396399
Callable[[~.DropDatabaseRequest],

google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ class DatabaseAdminGrpcAsyncIOTransport(DatabaseAdminTransport):
4040
"""gRPC AsyncIO backend transport for DatabaseAdmin.
4141
4242
Cloud Spanner Database Admin API
43-
The Cloud Spanner Database Admin API can be used to create,
44-
drop, and list databases. It also enables updating the schema of
45-
pre-existing databases. It can be also used to create, delete
46-
and list backups for a database and to restore from an existing
47-
backup.
43+
44+
The Cloud Spanner Database Admin API can be used to:
45+
46+
- create, drop, and list databases
47+
- update the schema of pre-existing databases
48+
- create, delete and list backups for a database
49+
- restore a database from an existing backup
4850
4951
This class defines the same methods as the primary client, so the
5052
primary client can load the underlying transport implementation
@@ -399,7 +401,8 @@ def drop_database(
399401
400402
Drops (aka deletes) a Cloud Spanner database. Completed backups
401403
for the database will be retained according to their
402-
``expire_time``.
404+
``expire_time``. Note: Cloud Spanner might continue to accept
405+
requests for a few seconds after the database has been deleted.
403406
404407
Returns:
405408
Callable[[~.DropDatabaseRequest],

google/cloud/spanner_admin_database_v1/types/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
EncryptionConfig,
3232
EncryptionInfo,
3333
OperationProgress,
34+
DatabaseDialect,
3435
)
3536
from .spanner_database_admin import (
3637
CreateDatabaseMetadata,
@@ -70,6 +71,7 @@
7071
"EncryptionConfig",
7172
"EncryptionInfo",
7273
"OperationProgress",
74+
"DatabaseDialect",
7375
"CreateDatabaseMetadata",
7476
"CreateDatabaseRequest",
7577
"Database",

google/cloud/spanner_admin_database_v1/types/backup.py

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class Backup(proto.Message):
104104
encryption_info (google.cloud.spanner_admin_database_v1.types.EncryptionInfo):
105105
Output only. The encryption information for
106106
the backup.
107+
database_dialect (google.cloud.spanner_admin_database_v1.types.DatabaseDialect):
108+
Output only. The database dialect information
109+
for the backup.
107110
"""
108111

109112
class State(proto.Enum):
@@ -125,6 +128,7 @@ class State(proto.Enum):
125128
encryption_info = proto.Field(
126129
proto.MESSAGE, number=8, message=common.EncryptionInfo,
127130
)
131+
database_dialect = proto.Field(proto.ENUM, number=10, enum=common.DatabaseDialect,)
128132

129133

130134
class CreateBackupRequest(proto.Message):

google/cloud/spanner_admin_database_v1/types/common.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,22 @@
2121

2222
__protobuf__ = proto.module(
2323
package="google.spanner.admin.database.v1",
24-
manifest={"OperationProgress", "EncryptionConfig", "EncryptionInfo",},
24+
manifest={
25+
"DatabaseDialect",
26+
"OperationProgress",
27+
"EncryptionConfig",
28+
"EncryptionInfo",
29+
},
2530
)
2631

2732

33+
class DatabaseDialect(proto.Enum):
34+
r"""Indicates the dialect type of a database."""
35+
DATABASE_DIALECT_UNSPECIFIED = 0
36+
GOOGLE_STANDARD_SQL = 1
37+
POSTGRESQL = 2
38+
39+
2840
class OperationProgress(proto.Message):
2941
r"""Encapsulates progress related information for a Cloud Spanner
3042
long running operation.

0 commit comments

Comments
 (0)