Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: add mtls support and resource path parse methods (#10)
  • Loading branch information
yoshi-automation committed May 28, 2020
1 parent bdadd8e commit dabeec7
Show file tree
Hide file tree
Showing 15 changed files with 1,370 additions and 134 deletions.
5 changes: 1 addition & 4 deletions docs/conf.py
Expand Up @@ -38,6 +38,7 @@
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"recommonmark",
]

# autodoc/autosummary flags
Expand All @@ -49,10 +50,6 @@
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# Allow markdown includes (so releases.md can include CHANGLEOG.md)
# http://www.sphinx-doc.org/en/master/markdown.html
source_parsers = {".md": "recommonmark.parser.CommonMarkParser"}

# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
Expand Down
Expand Up @@ -16,7 +16,8 @@
#

from collections import OrderedDict
from typing import Dict, Sequence, Tuple, Type, Union
import re
from typing import Callable, Dict, Sequence, Tuple, Type, Union
import pkg_resources

import google.api_core.client_options as ClientOptions # type: ignore
Expand Down Expand Up @@ -76,8 +77,38 @@ class GameServerClustersServiceClient(metaclass=GameServerClustersServiceClientM
Agones and is used to manage fleets within clusters.
"""

DEFAULT_OPTIONS = ClientOptions.ClientOptions(
api_endpoint="gameservices.googleapis.com"
@staticmethod
def _get_default_mtls_endpoint(api_endpoint):
"""Convert api endpoint to mTLS endpoint.
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
Args:
api_endpoint (Optional[str]): the api endpoint to convert.
Returns:
str: converted mTLS api endpoint.
"""
if not api_endpoint:
return api_endpoint

mtls_endpoint_re = re.compile(
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
)

m = mtls_endpoint_re.match(api_endpoint)
name, mtls, sandbox, googledomain = m.groups()
if mtls or not googledomain:
return api_endpoint

if sandbox:
return api_endpoint.replace(
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
)

return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")

DEFAULT_ENDPOINT = "gameservices.googleapis.com"
DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
DEFAULT_ENDPOINT
)

@classmethod
Expand Down Expand Up @@ -109,12 +140,21 @@ def game_server_cluster_path(
project=project, location=location, realm=realm, cluster=cluster
)

@staticmethod
def parse_game_server_cluster_path(path: str) -> Dict[str, str]:
"""Parse a game_server_cluster path into its component segments."""
m = re.match(
r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)/realms/(?P<realm>.+?)/gameServerClusters/(?P<cluster>.+?)$",
path,
)
return m.groupdict() if m else {}

def __init__(
self,
*,
credentials: credentials.Credentials = None,
transport: Union[str, GameServerClustersServiceTransport] = None,
client_options: ClientOptions = DEFAULT_OPTIONS,
client_options: ClientOptions = None,
) -> None:
"""Instantiate the game server clusters service client.
Expand All @@ -128,6 +168,17 @@ def __init__(
transport to use. If set to None, a transport is chosen
automatically.
client_options (ClientOptions): Custom options for the client.
(1) The ``api_endpoint`` property can be used to override the
default endpoint provided by the client.
(2) If ``transport`` argument is None, ``client_options`` can be
used to create a mutual TLS transport. If ``client_cert_source``
is provided, mutual TLS transport will be created with the given
``api_endpoint`` or the default mTLS endpoint, and the client
SSL credentials obtained from ``client_cert_source``.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
creation failed for any reason.
"""
if isinstance(client_options, dict):
client_options = ClientOptions.from_dict(client_options)
Expand All @@ -136,17 +187,46 @@ def __init__(
# Ordinarily, we provide the transport, but allowing a custom transport
# instance provides an extensibility point for unusual situations.
if isinstance(transport, GameServerClustersServiceTransport):
# transport is a GameServerClustersServiceTransport instance.
if credentials:
raise ValueError(
"When providing a transport instance, "
"provide its credentials directly."
)
self._transport = transport
else:
elif client_options is None or (
client_options.api_endpoint is None
and client_options.client_cert_source is None
):
# Don't trigger mTLS if we get an empty ClientOptions.
Transport = type(self).get_transport_class(transport)
self._transport = Transport(
credentials=credentials, host=self.DEFAULT_ENDPOINT
)
else:
# We have a non-empty ClientOptions. If client_cert_source is
# provided, trigger mTLS with user provided endpoint or the default
# mTLS endpoint.
if client_options.client_cert_source:
api_mtls_endpoint = (
client_options.api_endpoint
if client_options.api_endpoint
else self.DEFAULT_MTLS_ENDPOINT
)
else:
api_mtls_endpoint = None

api_endpoint = (
client_options.api_endpoint
if client_options.api_endpoint
else self.DEFAULT_ENDPOINT
)

self._transport = GameServerClustersServiceGrpcTransport(
credentials=credentials,
host=client_options.api_endpoint or "gameservices.googleapis.com",
host=api_endpoint,
api_mtls_endpoint=api_mtls_endpoint,
client_cert_source=client_options.client_cert_source,
)

def list_game_server_clusters(
Expand Down
Expand Up @@ -15,11 +15,13 @@
# limitations under the License.
#

from typing import Callable, Dict
from typing import Callable, Dict, Tuple

from google.api_core import grpc_helpers # type: ignore
from google.api_core import operations_v1 # type: ignore
from google.auth import credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore


import grpc # type: ignore

Expand Down Expand Up @@ -48,7 +50,9 @@ def __init__(
*,
host: str = "gameservices.googleapis.com",
credentials: credentials.Credentials = None,
channel: grpc.Channel = None
channel: grpc.Channel = None,
api_mtls_endpoint: str = None,
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None
) -> None:
"""Instantiate the transport.
Expand All @@ -62,20 +66,55 @@ def __init__(
This argument is ignored if ``channel`` is provided.
channel (Optional[grpc.Channel]): A ``Channel`` instance through
which to make calls.
api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If
provided, it overrides the ``host`` argument and tries to create
a mutual TLS channel with client SSL credentials from
``client_cert_source`` or applicatin default SSL credentials.
client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A
callback to provide client SSL certificate bytes and private key
bytes, both in PEM format. It is ignored if ``api_mtls_endpoint``
is None.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
creation failed for any reason.
"""
# Sanity check: Ensure that channel and credentials are not both
# provided.
if channel:
# Sanity check: Ensure that channel and credentials are not both
# provided.
credentials = False

# If a channel was explicitly provided, set it.
self._grpc_channel = channel
elif api_mtls_endpoint:
host = (
api_mtls_endpoint
if ":" in api_mtls_endpoint
else api_mtls_endpoint + ":443"
)

# Create SSL credentials with client_cert_source or application
# default SSL credentials.
if client_cert_source:
cert, key = client_cert_source()
ssl_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
else:
ssl_credentials = SslCredentials().ssl_credentials

# create a new channel. The provided one is ignored.
self._grpc_channel = grpc_helpers.create_channel(
host,
credentials=credentials,
ssl_credentials=ssl_credentials,
scopes=self.AUTH_SCOPES,
)

# Run the base constructor.
super().__init__(host=host, credentials=credentials)
self._stubs = {} # type: Dict[str, Callable]

# If a channel was explicitly provided, set it.
if channel:
self._grpc_channel = channel

@classmethod
def create_channel(
cls,
Expand Down
Expand Up @@ -16,7 +16,8 @@
#

from collections import OrderedDict
from typing import Dict, Sequence, Tuple, Type, Union
import re
from typing import Callable, Dict, Sequence, Tuple, Type, Union
import pkg_resources

import google.api_core.client_options as ClientOptions # type: ignore
Expand Down Expand Up @@ -75,8 +76,38 @@ class GameServerConfigsServiceClient(metaclass=GameServerConfigsServiceClientMet
Agones fleet.
"""

DEFAULT_OPTIONS = ClientOptions.ClientOptions(
api_endpoint="gameservices.googleapis.com"
@staticmethod
def _get_default_mtls_endpoint(api_endpoint):
"""Convert api endpoint to mTLS endpoint.
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
Args:
api_endpoint (Optional[str]): the api endpoint to convert.
Returns:
str: converted mTLS api endpoint.
"""
if not api_endpoint:
return api_endpoint

mtls_endpoint_re = re.compile(
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
)

m = mtls_endpoint_re.match(api_endpoint)
name, mtls, sandbox, googledomain = m.groups()
if mtls or not googledomain:
return api_endpoint

if sandbox:
return api_endpoint.replace(
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
)

return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")

DEFAULT_ENDPOINT = "gameservices.googleapis.com"
DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
DEFAULT_ENDPOINT
)

@classmethod
Expand Down Expand Up @@ -108,12 +139,21 @@ def game_server_config_path(
project=project, location=location, deployment=deployment, config=config
)

@staticmethod
def parse_game_server_config_path(path: str) -> Dict[str, str]:
"""Parse a game_server_config path into its component segments."""
m = re.match(
r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)/gameServerDeployments/(?P<deployment>.+?)/configs/(?P<config>.+?)$",
path,
)
return m.groupdict() if m else {}

def __init__(
self,
*,
credentials: credentials.Credentials = None,
transport: Union[str, GameServerConfigsServiceTransport] = None,
client_options: ClientOptions = DEFAULT_OPTIONS,
client_options: ClientOptions = None,
) -> None:
"""Instantiate the game server configs service client.
Expand All @@ -127,6 +167,17 @@ def __init__(
transport to use. If set to None, a transport is chosen
automatically.
client_options (ClientOptions): Custom options for the client.
(1) The ``api_endpoint`` property can be used to override the
default endpoint provided by the client.
(2) If ``transport`` argument is None, ``client_options`` can be
used to create a mutual TLS transport. If ``client_cert_source``
is provided, mutual TLS transport will be created with the given
``api_endpoint`` or the default mTLS endpoint, and the client
SSL credentials obtained from ``client_cert_source``.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
creation failed for any reason.
"""
if isinstance(client_options, dict):
client_options = ClientOptions.from_dict(client_options)
Expand All @@ -135,17 +186,46 @@ def __init__(
# Ordinarily, we provide the transport, but allowing a custom transport
# instance provides an extensibility point for unusual situations.
if isinstance(transport, GameServerConfigsServiceTransport):
# transport is a GameServerConfigsServiceTransport instance.
if credentials:
raise ValueError(
"When providing a transport instance, "
"provide its credentials directly."
)
self._transport = transport
else:
elif client_options is None or (
client_options.api_endpoint is None
and client_options.client_cert_source is None
):
# Don't trigger mTLS if we get an empty ClientOptions.
Transport = type(self).get_transport_class(transport)
self._transport = Transport(
credentials=credentials, host=self.DEFAULT_ENDPOINT
)
else:
# We have a non-empty ClientOptions. If client_cert_source is
# provided, trigger mTLS with user provided endpoint or the default
# mTLS endpoint.
if client_options.client_cert_source:
api_mtls_endpoint = (
client_options.api_endpoint
if client_options.api_endpoint
else self.DEFAULT_MTLS_ENDPOINT
)
else:
api_mtls_endpoint = None

api_endpoint = (
client_options.api_endpoint
if client_options.api_endpoint
else self.DEFAULT_ENDPOINT
)

self._transport = GameServerConfigsServiceGrpcTransport(
credentials=credentials,
host=client_options.api_endpoint or "gameservices.googleapis.com",
host=api_endpoint,
api_mtls_endpoint=api_mtls_endpoint,
client_cert_source=client_options.client_cert_source,
)

def list_game_server_configs(
Expand Down

0 comments on commit dabeec7

Please sign in to comment.