Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,7 @@ def connect(
ca_certificate=None,
client_certificate=None,
client_key=None,
instance_type=None,
**kwargs,
):
"""Creates a connection to a Google Cloud Spanner database.
Expand Down Expand Up @@ -802,26 +803,29 @@ def connect(
resource.

:type experimental_host: str
:param experimental_host: (Optional) The endpoint for a spanner experimental host deployment.
This is intended only for experimental host spanner endpoints.
:param experimental_host: (Deprecated) Use `client_options` with `api_endpoint` and `instance_type="omni"` instead.

:type instance_type: str
:param instance_type: (Optional) The type of Spanner instance to connect to.
Supported values are `"cloud"` or `"omni"`. Connecting to Spanner Omni requires setting instance_type=`"omni"`.

:type use_plain_text: bool
:param use_plain_text: (Optional) Whether to use plain text for the connection.
This is intended only for experimental host spanner endpoints.
This is intended only for Spanner Omni endpoints.
If not set, the default behavior is to use TLS.

:type ca_certificate: str
:param ca_certificate: (Optional) The path to the CA certificate file used for TLS connection.
This is intended only for experimental host spanner endpoints.
This is mandatory if the experimental_host requires a TLS connection.
This is intended only for Spanner Omni endpoints.
This is mandatory if Spanner Omni requires a TLS connection.
:type client_certificate: str
:param client_certificate: (Optional) The path to the client certificate file used for mTLS connection.
This is intended only for experimental host spanner endpoints.
This is mandatory if the experimental_host requires an mTLS connection.
This is intended only for Spanner Omni endpoints.
This is mandatory if Spanner Omni requires an mTLS connection.
:type client_key: str
:param client_key: (Optional) The path to the client key file used for mTLS connection.
This is intended only for experimental host spanner endpoints.
This is mandatory if the experimental_host requires an mTLS connection.
This is intended only for Spanner Omni endpoints.
This is mandatory if Spanner Omni requires an mTLS connection.
"""
if client is None:
client_info = ClientInfo(
Expand All @@ -840,10 +844,48 @@ def connect(
client_options = None
if isinstance(credentials, AnonymousCredentials):
client_options = kwargs.get("client_options")

if experimental_host is not None:
warnings.warn(
"experimental_host is deprecated. Please use client_options with api_endpoint instead, along with instance_type='omni'.",
DeprecationWarning,
stacklevel=2,
)
instance_type = "omni"

if instance_type is not None:
instance_type = instance_type.lower()
if instance_type not in ("cloud", "omni"):
raise ValueError("instance_type must be one of 'cloud' or 'omni'")

if instance_type == "omni":
host_endpoint = experimental_host
if not host_endpoint and "client_options" in kwargs:
opts = kwargs["client_options"]
if hasattr(opts, "api_endpoint"):
host_endpoint = opts.api_endpoint
elif isinstance(opts, dict):
host_endpoint = opts.get("api_endpoint")

if not host_endpoint:
raise ValueError(
"Host must be set for connecting to Spanner Omni instances"
)

project = "default"
credentials = AnonymousCredentials()
client_options = ClientOptions(api_endpoint=experimental_host)
client_options = kwargs.get("client_options")
if client_options is None:
client_options = ClientOptions(api_endpoint=host_endpoint)
elif isinstance(client_options, dict):
client_options = client_options.copy()
client_options["api_endpoint"] = host_endpoint
else:
import copy

client_options = copy.copy(client_options)
client_options.api_endpoint = host_endpoint

client = spanner.Client(
project=project,
credentials=credentials,
Expand All @@ -854,6 +896,7 @@ def connect(
ca_certificate=ca_certificate,
client_certificate=client_certificate,
client_key=client_key,
instance_type=instance_type,
)
else:
if project is not None and client.project != project:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,21 @@ async def _retry(
retries += 1


def _create_experimental_host_transport(
def _create_spanner_omni_transport(
transport_factory,
experimental_host,
host,
use_plain_text,
ca_certificate,
client_certificate,
client_key,
interceptors=None,
):
"""Creates an experimental host transport for Spanner in async mode.
"""Creates a Spanner Omni transport in async mode.

Args:
transport_factory (type): The transport class to instantiate (e.g.
`SpannerGrpcAsyncIOTransport`).
experimental_host (str): The endpoint for the experimental host.
host (str): The endpoint for Spanner Omni.
use_plain_text (bool): Whether to use a plain text (insecure) connection.
ca_certificate (str): Path to the CA certificate file for TLS.
client_certificate (str): Path to the client certificate file for mTLS.
Expand All @@ -99,9 +99,7 @@ def _create_experimental_host_transport(

channel = None
if use_plain_text:
channel = grpc.aio.insecure_channel(
target=experimental_host, interceptors=interceptors
)
channel = grpc.aio.insecure_channel(target=host, interceptors=interceptors)
elif ca_certificate:
with open(ca_certificate, "rb") as f:
ca_cert = f.read()
Expand All @@ -121,11 +119,37 @@ def _create_experimental_host_transport(
)
else:
ssl_creds = grpc.ssl_channel_credentials(root_certificates=ca_cert)
channel = grpc.aio.secure_channel(
experimental_host, ssl_creds, interceptors=interceptors
)
channel = grpc.aio.secure_channel(host, ssl_creds, interceptors=interceptors)
else:
raise ValueError(
"TLS/mTLS connection requires ca_certificate to be set for experimental_host"
"TLS/mTLS connection requires ca_certificate to be set for Spanner Omni"
)
return transport_factory(channel=channel, credentials=AnonymousCredentials())


def _create_experimental_host_transport(
transport_factory,
experimental_host,
use_plain_text,
ca_certificate,
client_certificate,
client_key,
interceptors=None,
):
"""Deprecated alias for _create_spanner_omni_transport."""
import warnings

warnings.warn(
"_create_experimental_host_transport is deprecated. Please use _create_spanner_omni_transport instead.",
DeprecationWarning,
stacklevel=2,
)
return _create_spanner_omni_transport(
transport_factory,
experimental_host,
use_plain_text,
ca_certificate,
client_certificate,
client_key,
interceptors=interceptors,
)
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ def _initialize_metrics(project, credentials):
)


class InstanceType:
CLOUD = "cloud"
OMNI = "omni"
EMULATOR = "emulator"


@CrossSync.convert_class(
docstring_format_vars={
"experimental_api": (
Expand Down Expand Up @@ -254,9 +260,11 @@ class Client(ClientWithProject):
:param default_transaction_options: (Optional) Default options to use for all transactions.

:type experimental_host: str
:param experimental_host: (Optional) The endpoint for a spanner experimental host deployment.
This is intended only for experimental host spanner endpoints.
If set, this will override the `api_endpoint` in `client_options`.
:param experimental_host: (Deprecated) Use `client_options` with `api_endpoint` and `instance_type="omni"` instead.

:type instance_type: str
:param instance_type: (Optional) The type of Spanner instance to connect to.
Supported values are `"cloud"` or `"omni"`. Connecting to Spanner Omni requires setting instance_type="omni".

:type disable_builtin_metrics: bool
:param disable_builtin_metrics: (Optional) Default False. Set to True to disable
Expand Down Expand Up @@ -293,9 +301,9 @@ def __init__(
ca_certificate=None,
client_certificate=None,
client_key=None,
instance_type=None,
):
self._emulator_host = _get_spanner_emulator_host()
self._experimental_host = experimental_host
self._use_plain_text = use_plain_text
self._ca_certificate = ca_certificate
self._client_certificate = client_certificate
Expand All @@ -308,10 +316,38 @@ def __init__(
else:
self._client_options = client_options

host_endpoint = None
if experimental_host is not None:
warnings.warn(
"experimental_host is deprecated. Please use client_options with api_endpoint instead, along with instance_type='omni'.",
DeprecationWarning,
stacklevel=2,
)
instance_type = "omni"
host_endpoint = experimental_host

if instance_type is not None:
instance_type = instance_type.lower()
if instance_type not in ("cloud", "omni"):
raise ValueError("instance_type must be one of 'cloud' or 'omni'")
self._instance_type = instance_type

if self._emulator_host:
credentials = AnonymousCredentials()
Comment thread
sagnghos marked this conversation as resolved.
elif self._experimental_host:
# For all experimental host endpoints project is default
elif self._instance_type == "omni":
if not host_endpoint:
if self._client_options:
if hasattr(self._client_options, "api_endpoint"):
host_endpoint = self._client_options.api_endpoint
elif isinstance(self._client_options, dict):
host_endpoint = self._client_options.get("api_endpoint")

if not host_endpoint:
raise ValueError(
"Host must be set for connecting to Spanner Omni instances"
)

# For all spanner omni endpoints project is default
project = "default"
self._use_plain_text = use_plain_text
self._ca_certificate = ca_certificate
Expand Down Expand Up @@ -372,8 +408,8 @@ def __init__(
self._host = "spanner.googleapis.com"
if self._emulator_host:
self._host = self._emulator_host
elif self._experimental_host:
self._host = self._experimental_host
elif self._instance_type == "omni":
self._host = host_endpoint
elif self._client_options and self._client_options.api_endpoint:
self._host = self._client_options.api_endpoint

Expand Down Expand Up @@ -414,6 +450,14 @@ def credentials(self):
"""
return self._credentials

@property
def instance_type(self):
"""Getter for client's instance type.

:rtype: str
:returns: The instance type of the client."""
return self._instance_type

@property
def project_name(self):
"""Project name to be used with Spanner APIs.
Expand Down Expand Up @@ -449,28 +493,28 @@ def instance_admin_api(self):
transport=transport,
)

elif self._experimental_host:
elif self._instance_type == "omni":
from google.cloud.spanner_v1._async._helpers import (
_create_experimental_host_transport as _create_experimental_host_transport_async,
_create_spanner_omni_transport as _create_spanner_omni_transport_async,
)
from google.cloud.spanner_v1._helpers import (
_create_experimental_host_transport as _create_experimental_host_transport_sync,
_create_spanner_omni_transport as _create_spanner_omni_transport_sync,
)

if CrossSync.is_async:
transport = _create_experimental_host_transport_async(
transport = _create_spanner_omni_transport_async(
InstanceAdminGrpcTransport,
self._experimental_host,
self._host,
self._use_plain_text,
self._ca_certificate,
self._client_certificate,
self._client_key,
)

else:
transport = _create_experimental_host_transport_sync(
transport = _create_spanner_omni_transport_sync(
InstanceAdminGrpcTransport,
self._experimental_host,
self._host,
self._use_plain_text,
self._ca_certificate,
self._client_certificate,
Expand Down Expand Up @@ -507,28 +551,28 @@ def database_admin_api(self):
transport=transport,
)

elif self._experimental_host:
elif self._instance_type == "omni":
from google.cloud.spanner_v1._async._helpers import (
_create_experimental_host_transport as _create_experimental_host_transport_async,
_create_spanner_omni_transport as _create_spanner_omni_transport_async,
)
from google.cloud.spanner_v1._helpers import (
_create_experimental_host_transport as _create_experimental_host_transport_sync,
_create_spanner_omni_transport as _create_spanner_omni_transport_sync,
)

if CrossSync.is_async:
transport = _create_experimental_host_transport_async(
transport = _create_spanner_omni_transport_async(
DatabaseAdminGrpcTransport,
self._experimental_host,
self._host,
self._use_plain_text,
self._ca_certificate,
self._client_certificate,
self._client_key,
)

else:
transport = _create_experimental_host_transport_sync(
transport = _create_spanner_omni_transport_sync(
DatabaseAdminGrpcTransport,
self._experimental_host,
self._host,
self._use_plain_text,
self._ca_certificate,
self._client_certificate,
Expand Down Expand Up @@ -682,7 +726,6 @@ def instance(
self._emulator_host,
labels,
processing_units,
self._experimental_host,
)

@CrossSync.convert
Expand Down
Loading
Loading