Skip to content

Commit 05fb32e

Browse files
committed
refactor(generator): use routing helper from api_core in templates and goldens
1 parent 0fe63b5 commit 05fb32e

26 files changed

Lines changed: 338 additions & 1440 deletions

File tree

packages/gapic-generator/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2

Lines changed: 26 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ from google.api_core import exceptions as core_exceptions
3030
from google.api_core import extended_operation
3131
{% endif %}
3232
from google.api_core import gapic_v1
33+
from google.api_core.gapic_v1 import routing
3334
from google.api_core import retry as retries
3435
from google.auth import credentials as ga_credentials # type: ignore
3536
from google.auth.transport import mtls # type: ignore
@@ -144,38 +145,9 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
144145
This class implements API version {{ service.version }}.{% endif %}"""
145146

146147
@staticmethod
147-
def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]:
148-
"""Converts api endpoint to mTLS endpoint.
149-
150-
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
151-
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
152-
Args:
153-
api_endpoint (Optional[str]): the api endpoint to convert.
154-
Returns:
155-
Optional[str]: converted mTLS api endpoint.
156-
"""
157-
if not api_endpoint:
158-
return api_endpoint
159-
160-
mtls_endpoint_re = re.compile(
161-
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
162-
)
163-
164-
m = mtls_endpoint_re.match(api_endpoint)
165-
if m is None:
166-
# Could not parse api_endpoint; return as-is.
167-
return api_endpoint
168-
169-
name, mtls, sandbox, googledomain = m.groups()
170-
if mtls or not googledomain:
171-
return api_endpoint
172-
173-
if sandbox:
174-
return api_endpoint.replace(
175-
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
176-
)
177-
178-
return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
148+
def _get_default_mtls_endpoint(api_endpoint: Optional[str]) -> Optional[str]:
149+
"""Converts api endpoint to mTLS endpoint."""
150+
return routing.get_default_mtls_endpoint(api_endpoint)
179151

180152
# Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
181153
DEFAULT_ENDPOINT = {% if service.host %}"{{ service.host }}"{% else %}None{% endif %}
@@ -392,53 +364,31 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
392364
return client_cert_source
393365

394366
@staticmethod
395-
def _get_api_endpoint(api_override, client_cert_source, universe_domain, use_mtls_endpoint) -> str:
396-
"""Return the API endpoint used by the client.
397-
398-
Args:
399-
api_override (str): The API endpoint override. If specified, this is always
400-
the return value of this function and the other arguments are not used.
401-
client_cert_source (bytes): The client certificate source used by the client.
402-
universe_domain (str): The universe domain used by the client.
403-
use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters.
404-
Possible values are "always", "auto", or "never".
405-
406-
Returns:
407-
str: The API endpoint to be used by the client.
408-
"""
409-
if api_override is not None:
410-
api_endpoint = api_override
411-
elif use_mtls_endpoint == "always" or (use_mtls_endpoint == "auto" and client_cert_source):
412-
_default_universe = {{ service.client_name }}._DEFAULT_UNIVERSE
413-
if universe_domain != _default_universe:
414-
raise MutualTLSChannelError(f"mTLS is not supported in any universe other than {_default_universe}.")
415-
api_endpoint = {{ service.client_name }}.DEFAULT_MTLS_ENDPOINT
416-
else:
417-
api_endpoint = {{ service.client_name }}._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=universe_domain)
418-
return api_endpoint
367+
def _get_api_endpoint(
368+
api_override: Optional[str],
369+
client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]],
370+
universe_domain: str,
371+
use_mtls_endpoint: str,
372+
) -> str:
373+
"""Return the API endpoint used by the client."""
374+
return routing.get_api_endpoint(
375+
api_override,
376+
client_cert_source,
377+
universe_domain,
378+
use_mtls_endpoint,
379+
{{ service.client_name }}._DEFAULT_UNIVERSE,
380+
{{ service.client_name }}.DEFAULT_MTLS_ENDPOINT,
381+
{{ service.client_name }}._DEFAULT_ENDPOINT_TEMPLATE,
382+
)
419383

420384
@staticmethod
421385
def _get_universe_domain(client_universe_domain: Optional[str], universe_domain_env: Optional[str]) -> str:
422-
"""Return the universe domain used by the client.
423-
424-
Args:
425-
client_universe_domain (Optional[str]): The universe domain configured via the client options.
426-
universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable.
427-
428-
Returns:
429-
str: The universe domain to be used by the client.
430-
431-
Raises:
432-
ValueError: If the universe domain is an empty string.
433-
"""
434-
universe_domain = {{ service.client_name }}._DEFAULT_UNIVERSE
435-
if client_universe_domain is not None:
436-
universe_domain = client_universe_domain
437-
elif universe_domain_env is not None:
438-
universe_domain = universe_domain_env
439-
if len(universe_domain.strip()) == 0:
440-
raise ValueError("Universe Domain cannot be an empty string.")
441-
return universe_domain
386+
"""Return the universe domain used by the client."""
387+
return routing.get_universe_domain(
388+
client_universe_domain,
389+
universe_domain_env,
390+
{{ service.client_name }}._DEFAULT_UNIVERSE,
391+
)
442392

443393
def _validate_universe_domain(self):
444394
"""Validates client's and credentials' universe domains are consistent.

packages/gapic-generator/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -313,29 +313,7 @@ def test__get_client_cert_source():
313313
assert {{ service.client_name }}._get_client_cert_source(None, True) is mock_default_cert_source
314314
assert {{ service.client_name }}._get_client_cert_source(mock_provided_cert_source, "true") is mock_provided_cert_source
315315

316-
@mock.patch.object({{ service.client_name }}, "_DEFAULT_ENDPOINT_TEMPLATE", modify_default_endpoint_template({{ service.client_name }}))
317-
{% if 'grpc' in opts.transport %}
318-
@mock.patch.object({{ service.async_client_name }}, "_DEFAULT_ENDPOINT_TEMPLATE", modify_default_endpoint_template({{ service.async_client_name }}))
319-
{% endif %}
320-
def test__get_api_endpoint():
321-
api_override = "foo.com"
322-
mock_client_cert_source = mock.Mock()
323-
default_universe = {{ service.client_name }}._DEFAULT_UNIVERSE
324-
default_endpoint = {{ service.client_name }}._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=default_universe)
325-
mock_universe = "bar.com"
326-
mock_endpoint = {{ service.client_name }}._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=mock_universe)
327-
328-
assert {{ service.client_name }}._get_api_endpoint(api_override, mock_client_cert_source, default_universe, "always") == api_override
329-
assert {{ service.client_name }}._get_api_endpoint(None, mock_client_cert_source, default_universe, "auto") == {{ service.client_name }}.DEFAULT_MTLS_ENDPOINT
330-
assert {{ service.client_name }}._get_api_endpoint(None, None, default_universe, "auto") == default_endpoint
331-
assert {{ service.client_name }}._get_api_endpoint(None, None, default_universe, "always") == {{ service.client_name }}.DEFAULT_MTLS_ENDPOINT
332-
assert {{ service.client_name }}._get_api_endpoint(None, mock_client_cert_source, default_universe, "always") == {{ service.client_name }}.DEFAULT_MTLS_ENDPOINT
333-
assert {{ service.client_name }}._get_api_endpoint(None, None, mock_universe, "never") == mock_endpoint
334-
assert {{ service.client_name }}._get_api_endpoint(None, None, default_universe, "never") == default_endpoint
335316

336-
with pytest.raises(MutualTLSChannelError) as excinfo:
337-
{{ service.client_name }}._get_api_endpoint(None, mock_client_cert_source, mock_universe, "auto")
338-
assert str(excinfo.value) == "mTLS is not supported in any universe other than googleapis.com."
339317

340318
{% if service.version %}
341319
{% for method in service.methods.values() %}{% with method_name = method.name|snake_case %}
@@ -384,17 +362,7 @@ def test_{{ method_name }}_api_version_header(transport_name):
384362
{% endfor %}
385363
{% endif %}{# service.version #}
386364

387-
def test__get_universe_domain():
388-
client_universe_domain = "foo.com"
389-
universe_domain_env = "bar.com"
390-
391-
assert {{ service.client_name }}._get_universe_domain(client_universe_domain, universe_domain_env) == client_universe_domain
392-
assert {{ service.client_name }}._get_universe_domain(None, universe_domain_env) == universe_domain_env
393-
assert {{ service.client_name }}._get_universe_domain(None, None) == {{ service.client_name }}._DEFAULT_UNIVERSE
394365

395-
with pytest.raises(ValueError) as excinfo:
396-
{{ service.client_name }}._get_universe_domain("", None)
397-
assert str(excinfo.value) == "Universe Domain cannot be an empty string."
398366

399367
@pytest.mark.parametrize("error_code,cred_info_json,show_cred_info", [
400368
(401, CRED_INFO_JSON, True),

packages/gapic-generator/tests/integration/goldens/asset/google/cloud/asset_v1/services/asset_service/client.py

Lines changed: 26 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from google.api_core import client_options as client_options_lib
2828
from google.api_core import exceptions as core_exceptions
2929
from google.api_core import gapic_v1
30+
from google.api_core.gapic_v1 import routing
3031
from google.api_core import retry as retries
3132
from google.auth import credentials as ga_credentials # type: ignore
3233
from google.auth.transport import mtls # type: ignore
@@ -101,38 +102,9 @@ class AssetServiceClient(metaclass=AssetServiceClientMeta):
101102
"""Asset service definition."""
102103

103104
@staticmethod
104-
def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]:
105-
"""Converts api endpoint to mTLS endpoint.
106-
107-
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
108-
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
109-
Args:
110-
api_endpoint (Optional[str]): the api endpoint to convert.
111-
Returns:
112-
Optional[str]: converted mTLS api endpoint.
113-
"""
114-
if not api_endpoint:
115-
return api_endpoint
116-
117-
mtls_endpoint_re = re.compile(
118-
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
119-
)
120-
121-
m = mtls_endpoint_re.match(api_endpoint)
122-
if m is None:
123-
# Could not parse api_endpoint; return as-is.
124-
return api_endpoint
125-
126-
name, mtls, sandbox, googledomain = m.groups()
127-
if mtls or not googledomain:
128-
return api_endpoint
129-
130-
if sandbox:
131-
return api_endpoint.replace(
132-
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
133-
)
134-
135-
return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
105+
def _get_default_mtls_endpoint(api_endpoint: Optional[str]) -> Optional[str]:
106+
"""Converts api endpoint to mTLS endpoint."""
107+
return routing.get_default_mtls_endpoint(api_endpoint)
136108

137109
# Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
138110
DEFAULT_ENDPOINT = "cloudasset.googleapis.com"
@@ -450,53 +422,31 @@ def _get_client_cert_source(provided_cert_source, use_cert_flag):
450422
return client_cert_source
451423

452424
@staticmethod
453-
def _get_api_endpoint(api_override, client_cert_source, universe_domain, use_mtls_endpoint) -> str:
454-
"""Return the API endpoint used by the client.
455-
456-
Args:
457-
api_override (str): The API endpoint override. If specified, this is always
458-
the return value of this function and the other arguments are not used.
459-
client_cert_source (bytes): The client certificate source used by the client.
460-
universe_domain (str): The universe domain used by the client.
461-
use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters.
462-
Possible values are "always", "auto", or "never".
463-
464-
Returns:
465-
str: The API endpoint to be used by the client.
466-
"""
467-
if api_override is not None:
468-
api_endpoint = api_override
469-
elif use_mtls_endpoint == "always" or (use_mtls_endpoint == "auto" and client_cert_source):
470-
_default_universe = AssetServiceClient._DEFAULT_UNIVERSE
471-
if universe_domain != _default_universe:
472-
raise MutualTLSChannelError(f"mTLS is not supported in any universe other than {_default_universe}.")
473-
api_endpoint = AssetServiceClient.DEFAULT_MTLS_ENDPOINT
474-
else:
475-
api_endpoint = AssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=universe_domain)
476-
return api_endpoint
425+
def _get_api_endpoint(
426+
api_override: Optional[str],
427+
client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]],
428+
universe_domain: str,
429+
use_mtls_endpoint: str,
430+
) -> str:
431+
"""Return the API endpoint used by the client."""
432+
return routing.get_api_endpoint(
433+
api_override,
434+
client_cert_source,
435+
universe_domain,
436+
use_mtls_endpoint,
437+
AssetServiceClient._DEFAULT_UNIVERSE,
438+
AssetServiceClient.DEFAULT_MTLS_ENDPOINT,
439+
AssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE,
440+
)
477441

478442
@staticmethod
479443
def _get_universe_domain(client_universe_domain: Optional[str], universe_domain_env: Optional[str]) -> str:
480-
"""Return the universe domain used by the client.
481-
482-
Args:
483-
client_universe_domain (Optional[str]): The universe domain configured via the client options.
484-
universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable.
485-
486-
Returns:
487-
str: The universe domain to be used by the client.
488-
489-
Raises:
490-
ValueError: If the universe domain is an empty string.
491-
"""
492-
universe_domain = AssetServiceClient._DEFAULT_UNIVERSE
493-
if client_universe_domain is not None:
494-
universe_domain = client_universe_domain
495-
elif universe_domain_env is not None:
496-
universe_domain = universe_domain_env
497-
if len(universe_domain.strip()) == 0:
498-
raise ValueError("Universe Domain cannot be an empty string.")
499-
return universe_domain
444+
"""Return the universe domain used by the client."""
445+
return routing.get_universe_domain(
446+
client_universe_domain,
447+
universe_domain_env,
448+
AssetServiceClient._DEFAULT_UNIVERSE,
449+
)
500450

501451
def _validate_universe_domain(self):
502452
"""Validates client's and credentials' universe domains are consistent.

packages/gapic-generator/tests/integration/goldens/asset/tests/unit/gapic/asset_v1/test_asset_service.py

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -278,41 +278,6 @@ def test__get_client_cert_source():
278278
assert AssetServiceClient._get_client_cert_source(None, True) is mock_default_cert_source
279279
assert AssetServiceClient._get_client_cert_source(mock_provided_cert_source, "true") is mock_provided_cert_source
280280

281-
@mock.patch.object(AssetServiceClient, "_DEFAULT_ENDPOINT_TEMPLATE", modify_default_endpoint_template(AssetServiceClient))
282-
@mock.patch.object(AssetServiceAsyncClient, "_DEFAULT_ENDPOINT_TEMPLATE", modify_default_endpoint_template(AssetServiceAsyncClient))
283-
def test__get_api_endpoint():
284-
api_override = "foo.com"
285-
mock_client_cert_source = mock.Mock()
286-
default_universe = AssetServiceClient._DEFAULT_UNIVERSE
287-
default_endpoint = AssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=default_universe)
288-
mock_universe = "bar.com"
289-
mock_endpoint = AssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(UNIVERSE_DOMAIN=mock_universe)
290-
291-
assert AssetServiceClient._get_api_endpoint(api_override, mock_client_cert_source, default_universe, "always") == api_override
292-
assert AssetServiceClient._get_api_endpoint(None, mock_client_cert_source, default_universe, "auto") == AssetServiceClient.DEFAULT_MTLS_ENDPOINT
293-
assert AssetServiceClient._get_api_endpoint(None, None, default_universe, "auto") == default_endpoint
294-
assert AssetServiceClient._get_api_endpoint(None, None, default_universe, "always") == AssetServiceClient.DEFAULT_MTLS_ENDPOINT
295-
assert AssetServiceClient._get_api_endpoint(None, mock_client_cert_source, default_universe, "always") == AssetServiceClient.DEFAULT_MTLS_ENDPOINT
296-
assert AssetServiceClient._get_api_endpoint(None, None, mock_universe, "never") == mock_endpoint
297-
assert AssetServiceClient._get_api_endpoint(None, None, default_universe, "never") == default_endpoint
298-
299-
with pytest.raises(MutualTLSChannelError) as excinfo:
300-
AssetServiceClient._get_api_endpoint(None, mock_client_cert_source, mock_universe, "auto")
301-
assert str(excinfo.value) == "mTLS is not supported in any universe other than googleapis.com."
302-
303-
304-
def test__get_universe_domain():
305-
client_universe_domain = "foo.com"
306-
universe_domain_env = "bar.com"
307-
308-
assert AssetServiceClient._get_universe_domain(client_universe_domain, universe_domain_env) == client_universe_domain
309-
assert AssetServiceClient._get_universe_domain(None, universe_domain_env) == universe_domain_env
310-
assert AssetServiceClient._get_universe_domain(None, None) == AssetServiceClient._DEFAULT_UNIVERSE
311-
312-
with pytest.raises(ValueError) as excinfo:
313-
AssetServiceClient._get_universe_domain("", None)
314-
assert str(excinfo.value) == "Universe Domain cannot be an empty string."
315-
316281
@pytest.mark.parametrize("error_code,cred_info_json,show_cred_info", [
317282
(401, CRED_INFO_JSON, True),
318283
(403, CRED_INFO_JSON, True),

0 commit comments

Comments
 (0)