Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: add common resource path helpers; expose client transport as pr…
…operty (#37)
  • Loading branch information
yoshi-automation committed Nov 20, 2020
1 parent 4d1c8cf commit bc92bc2
Show file tree
Hide file tree
Showing 18 changed files with 2,075 additions and 1,052 deletions.
1 change: 1 addition & 0 deletions docs/errorreporting_v1beta1/types.rst
Expand Up @@ -3,3 +3,4 @@ Types for Google Cloud Errorreporting v1beta1 API

.. automodule:: google.cloud.errorreporting_v1beta1.types
:members:
:show-inheritance:
Expand Up @@ -45,10 +45,51 @@ class ErrorGroupServiceAsyncClient:
DEFAULT_MTLS_ENDPOINT = ErrorGroupServiceClient.DEFAULT_MTLS_ENDPOINT

error_group_path = staticmethod(ErrorGroupServiceClient.error_group_path)
parse_error_group_path = staticmethod(
ErrorGroupServiceClient.parse_error_group_path
)

common_billing_account_path = staticmethod(
ErrorGroupServiceClient.common_billing_account_path
)
parse_common_billing_account_path = staticmethod(
ErrorGroupServiceClient.parse_common_billing_account_path
)

common_folder_path = staticmethod(ErrorGroupServiceClient.common_folder_path)
parse_common_folder_path = staticmethod(
ErrorGroupServiceClient.parse_common_folder_path
)

common_organization_path = staticmethod(
ErrorGroupServiceClient.common_organization_path
)
parse_common_organization_path = staticmethod(
ErrorGroupServiceClient.parse_common_organization_path
)

common_project_path = staticmethod(ErrorGroupServiceClient.common_project_path)
parse_common_project_path = staticmethod(
ErrorGroupServiceClient.parse_common_project_path
)

common_location_path = staticmethod(ErrorGroupServiceClient.common_location_path)
parse_common_location_path = staticmethod(
ErrorGroupServiceClient.parse_common_location_path
)

from_service_account_file = ErrorGroupServiceClient.from_service_account_file
from_service_account_json = from_service_account_file

@property
def transport(self) -> ErrorGroupServiceTransport:
"""Return the transport used by the client instance.
Returns:
ErrorGroupServiceTransport: The transport used by the client instance.
"""
return self._client.transport

get_transport_class = functools.partial(
type(ErrorGroupServiceClient).get_transport_class, type(ErrorGroupServiceClient)
)
Expand All @@ -75,16 +116,19 @@ def __init__(
client_options (ClientOptions): Custom options for the client. It
won't take effect if a ``transport`` instance is provided.
(1) The ``api_endpoint`` property can be used to override the
default endpoint provided by the client. GOOGLE_API_USE_MTLS
default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
environment variable can also be used to override the endpoint:
"always" (always use the default mTLS endpoint), "never" (always
use the default regular endpoint, this is the default value for
the environment variable) and "auto" (auto switch to the default
mTLS endpoint if client SSL credentials is present). However,
the ``api_endpoint`` property takes precedence if provided.
(2) The ``client_cert_source`` property is used to provide client
SSL credentials for mutual TLS transport. If not provided, the
default SSL credentials will be used if present.
use the default regular endpoint) and "auto" (auto switch to the
default mTLS endpoint if client certificate is present, this is
the default value). However, the ``api_endpoint`` property takes
precedence if provided.
(2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
is "true", then the ``client_cert_source`` property can be used
to provide client certificate for mutual TLS transport. If
not provided, the default SSL client certificate will be used if
present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
set, no client certificate will be used.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
Expand Down Expand Up @@ -139,7 +183,8 @@ async def get_group(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
if request is not None and any([group_name]):
has_flattened_params = any([group_name])
if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
Expand Down Expand Up @@ -213,7 +258,8 @@ async def update_group(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
if request is not None and any([group]):
has_flattened_params = any([group])
if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
Expand Down
Expand Up @@ -16,17 +16,19 @@
#

from collections import OrderedDict
from distutils import util
import os
import re
from typing import Callable, Dict, Sequence, Tuple, Type, Union
from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union
import pkg_resources

import google.api_core.client_options as ClientOptions # type: ignore
from google.api_core import client_options as client_options_lib # type: ignore
from google.api_core import exceptions # type: ignore
from google.api_core import gapic_v1 # type: ignore
from google.api_core import retry as retries # type: ignore
from google.auth import credentials # type: ignore
from google.auth.transport import mtls # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.oauth2 import service_account # type: ignore

Expand Down Expand Up @@ -130,6 +132,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs):

from_service_account_json = from_service_account_file

@property
def transport(self) -> ErrorGroupServiceTransport:
"""Return the transport used by the client instance.
Returns:
ErrorGroupServiceTransport: The transport used by the client instance.
"""
return self._transport

@staticmethod
def error_group_path(project: str, group: str,) -> str:
"""Return a fully-qualified error_group string."""
Expand All @@ -141,12 +152,71 @@ def parse_error_group_path(path: str) -> Dict[str, str]:
m = re.match(r"^projects/(?P<project>.+?)/groups/(?P<group>.+?)$", path)
return m.groupdict() if m else {}

@staticmethod
def common_billing_account_path(billing_account: str,) -> str:
"""Return a fully-qualified billing_account string."""
return "billingAccounts/{billing_account}".format(
billing_account=billing_account,
)

@staticmethod
def parse_common_billing_account_path(path: str) -> Dict[str, str]:
"""Parse a billing_account path into its component segments."""
m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
return m.groupdict() if m else {}

@staticmethod
def common_folder_path(folder: str,) -> str:
"""Return a fully-qualified folder string."""
return "folders/{folder}".format(folder=folder,)

@staticmethod
def parse_common_folder_path(path: str) -> Dict[str, str]:
"""Parse a folder path into its component segments."""
m = re.match(r"^folders/(?P<folder>.+?)$", path)
return m.groupdict() if m else {}

@staticmethod
def common_organization_path(organization: str,) -> str:
"""Return a fully-qualified organization string."""
return "organizations/{organization}".format(organization=organization,)

@staticmethod
def parse_common_organization_path(path: str) -> Dict[str, str]:
"""Parse a organization path into its component segments."""
m = re.match(r"^organizations/(?P<organization>.+?)$", path)
return m.groupdict() if m else {}

@staticmethod
def common_project_path(project: str,) -> str:
"""Return a fully-qualified project string."""
return "projects/{project}".format(project=project,)

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

@staticmethod
def common_location_path(project: str, location: str,) -> str:
"""Return a fully-qualified location string."""
return "projects/{project}/locations/{location}".format(
project=project, location=location,
)

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

def __init__(
self,
*,
credentials: credentials.Credentials = None,
transport: Union[str, ErrorGroupServiceTransport] = None,
client_options: ClientOptions = None,
credentials: Optional[credentials.Credentials] = None,
transport: Union[str, ErrorGroupServiceTransport, None] = None,
client_options: Optional[client_options_lib.ClientOptions] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiate the error group service client.
Expand All @@ -160,53 +230,74 @@ def __init__(
transport (Union[str, ~.ErrorGroupServiceTransport]): The
transport to use. If set to None, a transport is chosen
automatically.
client_options (ClientOptions): Custom options for the client. It
won't take effect if a ``transport`` instance is provided.
client_options (client_options_lib.ClientOptions): Custom options for the
client. It won't take effect if a ``transport`` instance is provided.
(1) The ``api_endpoint`` property can be used to override the
default endpoint provided by the client. GOOGLE_API_USE_MTLS
default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
environment variable can also be used to override the endpoint:
"always" (always use the default mTLS endpoint), "never" (always
use the default regular endpoint, this is the default value for
the environment variable) and "auto" (auto switch to the default
mTLS endpoint if client SSL credentials is present). However,
the ``api_endpoint`` property takes precedence if provided.
(2) The ``client_cert_source`` property is used to provide client
SSL credentials for mutual TLS transport. If not provided, the
default SSL credentials will be used if present.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
use the default regular endpoint) and "auto" (auto switch to the
default mTLS endpoint if client certificate is present, this is
the default value). However, the ``api_endpoint`` property takes
precedence if provided.
(2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
is "true", then the ``client_cert_source`` property can be used
to provide client certificate for mutual TLS transport. If
not provided, the default SSL client certificate will be used if
present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
set, no client certificate will be used.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
your own client library.
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)
client_options = client_options_lib.from_dict(client_options)
if client_options is None:
client_options = ClientOptions.ClientOptions()
client_options = client_options_lib.ClientOptions()

# Create SSL credentials for mutual TLS if needed.
use_client_cert = bool(
util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"))
)

if client_options.api_endpoint is None:
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never")
ssl_credentials = None
is_mtls = False
if use_client_cert:
if client_options.client_cert_source:
import grpc # type: ignore

cert, key = client_options.client_cert_source()
ssl_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
is_mtls = True
else:
creds = SslCredentials()
is_mtls = creds.is_mtls
ssl_credentials = creds.ssl_credentials if is_mtls else None

# Figure out which api endpoint to use.
if client_options.api_endpoint is not None:
api_endpoint = client_options.api_endpoint
else:
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
if use_mtls_env == "never":
client_options.api_endpoint = self.DEFAULT_ENDPOINT
api_endpoint = self.DEFAULT_ENDPOINT
elif use_mtls_env == "always":
client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT
api_endpoint = self.DEFAULT_MTLS_ENDPOINT
elif use_mtls_env == "auto":
has_client_cert_source = (
client_options.client_cert_source is not None
or mtls.has_default_client_cert_source()
)
client_options.api_endpoint = (
self.DEFAULT_MTLS_ENDPOINT
if has_client_cert_source
else self.DEFAULT_ENDPOINT
api_endpoint = (
self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT
)
else:
raise MutualTLSChannelError(
"Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always"
"Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
)

# Save or instantiate the transport.
Expand All @@ -230,10 +321,9 @@ def __init__(
self._transport = Transport(
credentials=credentials,
credentials_file=client_options.credentials_file,
host=client_options.api_endpoint,
host=api_endpoint,
scopes=client_options.scopes,
api_mtls_endpoint=client_options.api_endpoint,
client_cert_source=client_options.client_cert_source,
ssl_channel_credentials=ssl_credentials,
quota_project_id=client_options.quota_project_id,
client_info=client_info,
)
Expand Down

0 comments on commit bc92bc2

Please sign in to comment.