2
2
3
3
{% block content %}
4
4
from collections import OrderedDict
5
- from typing import Dict, {% if service .any_server_streaming %} Iterable, {% endif %}{% if service .any_client_streaming %} Iterator, {% endif %} Sequence, Tuple, Type, Union
5
+ import re
6
+ from typing import Callable, Dict, {% if service .any_server_streaming %} Iterable, {% endif %}{% if service .any_client_streaming %} Iterator, {% endif %} Sequence, Tuple, Type, Union
6
7
import pkg_resources
7
8
8
9
import google.api_core.client_options as ClientOptions # type: ignore
@@ -57,7 +58,39 @@ class {{ service.client_name }}Meta(type):
57
58
class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
58
59
"""{{ service.meta.doc|rst(width=72, indent=4) }}"""
59
60
60
- DEFAULT_OPTIONS = ClientOptions.ClientOptions({% if service .host %} api_endpoint='{{ service.host }}'{% endif %} )
61
+ @staticmethod
62
+ def _get_default_mtls_endpoint(api_endpoint):
63
+ """Convert api endpoint to mTLS endpoint.
64
+ Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
65
+ "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
66
+ Args:
67
+ api_endpoint (Optional[str]): the api endpoint to convert.
68
+ Returns:
69
+ str: converted mTLS api endpoint.
70
+ """
71
+ if not api_endpoint:
72
+ return api_endpoint
73
+
74
+ mtls_endpoint_re = re.compile(
75
+ r"(?P<name >[^.]+)(?P<mtls >\.mtls)?(?P<sandbox >\.sandbox)?(?P<googledomain >\.googleapis\.com)?"
76
+ )
77
+
78
+ m = mtls_endpoint_re.match(api_endpoint)
79
+ name, mtls, sandbox, googledomain = m.groups()
80
+ if mtls or not googledomain:
81
+ return api_endpoint
82
+
83
+ if sandbox:
84
+ return api_endpoint.replace(
85
+ "sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
86
+ )
87
+
88
+ return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
89
+
90
+ DEFAULT_ENDPOINT = {% if service .host %} '{{ service.host }}'{% else %} None{% endif %}
91
+ DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
92
+ DEFAULT_ENDPOINT
93
+ )
61
94
62
95
@classmethod
63
96
def from_service_account_file(cls, filename: str, *args, **kwargs):
@@ -92,7 +125,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
92
125
def __init__(self, *,
93
126
credentials: credentials.Credentials = None,
94
127
transport: Union[str, {{ service.name }}Transport] = None,
95
- client_options: ClientOptions = DEFAULT_OPTIONS ,
128
+ client_options: ClientOptions = None ,
96
129
) -> None:
97
130
"""Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}.
98
131
@@ -106,6 +139,17 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
106
139
transport to use. If set to None, a transport is chosen
107
140
automatically.
108
141
client_options (ClientOptions): Custom options for the client.
142
+ (1) The ``api_endpoint`` property can be used to override the
143
+ default endpoint provided by the client.
144
+ (2) If ``transport`` argument is None, ``client_options`` can be
145
+ used to create a mutual TLS transport. If ``client_cert_source``
146
+ is provided, mutual TLS transport will be created with the given
147
+ ``api_endpoint`` or the default mTLS endpoint, and the client
148
+ SSL credentials obtained from ``client_cert_source``.
149
+
150
+ Raises:
151
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
152
+ creation failed for any reason.
109
153
"""
110
154
if isinstance(client_options, dict):
111
155
client_options = ClientOptions.from_dict(client_options)
@@ -114,16 +158,45 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
114
158
# Ordinarily, we provide the transport, but allowing a custom transport
115
159
# instance provides an extensibility point for unusual situations.
116
160
if isinstance(transport, {{ service.name }}Transport):
161
+ # transport is a {{ service.name }}Transport instance.
117
162
if credentials:
118
163
raise ValueError('When providing a transport instance, '
119
164
'provide its credentials directly.')
120
165
self._transport = transport
121
- else:
166
+ elif client_options is None or (
167
+ client_options.api_endpoint == None
168
+ and client_options.client_cert_source is None
169
+ ):
170
+ # Don't trigger mTLS if we get an empty ClientOptions.
122
171
Transport = type(self).get_transport_class(transport)
123
172
self._transport = Transport(
124
- credentials=credentials,
125
- host=client_options.api_endpoint{% if service .host %} or '{{ service.host }}'{% endif %} ,
173
+ credentials=credentials, host=self.DEFAULT_ENDPOINT
126
174
)
175
+ else:
176
+ # We have a non-empty ClientOptions. If client_cert_source is
177
+ # provided, trigger mTLS with user provided endpoint or the default
178
+ # mTLS endpoint.
179
+ if client_options.client_cert_source:
180
+ api_mtls_endpoint = (
181
+ client_options.api_endpoint
182
+ if client_options.api_endpoint
183
+ else self.DEFAULT_MTLS_ENDPOINT
184
+ )
185
+ else:
186
+ api_mtls_endpoint = None
187
+
188
+ api_endpoint = (
189
+ client_options.api_endpoint
190
+ if client_options.api_endpoint
191
+ else self.DEFAULT_ENDPOINT
192
+ )
193
+
194
+ self._transport = {{ service.name }}GrpcTransport(
195
+ credentials=credentials,
196
+ host=api_endpoint,
197
+ api_mtls_endpoint=api_mtls_endpoint,
198
+ client_cert_source=client_options.client_cert_source,
199
+ )
127
200
128
201
{% for method in service .methods .values () -%}
129
202
def {{ method.name|snake_case }}(self,
0 commit comments