1616#
1717
1818from collections import OrderedDict
19- from typing import Dict , Sequence , Tuple , Type , Union
19+ import re
20+ from typing import Callable , Dict , Sequence , Tuple , Type , Union
2021import pkg_resources
2122
2223import google .api_core .client_options as ClientOptions # type: ignore
@@ -90,8 +91,38 @@ class CloudMemcacheClient(metaclass=CloudMemcacheClientMeta):
9091 - ``projects/my-memcached-project/locations/us-central1/instances/my-memcached``
9192 """
9293
93- DEFAULT_OPTIONS = ClientOptions .ClientOptions (
94- api_endpoint = "memcache.googleapis.com"
94+ @staticmethod
95+ def _get_default_mtls_endpoint (api_endpoint ):
96+ """Convert api endpoint to mTLS endpoint.
97+ Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
98+ "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
99+ Args:
100+ api_endpoint (Optional[str]): the api endpoint to convert.
101+ Returns:
102+ str: converted mTLS api endpoint.
103+ """
104+ if not api_endpoint :
105+ return api_endpoint
106+
107+ mtls_endpoint_re = re .compile (
108+ r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
109+ )
110+
111+ m = mtls_endpoint_re .match (api_endpoint )
112+ name , mtls , sandbox , googledomain = m .groups ()
113+ if mtls or not googledomain :
114+ return api_endpoint
115+
116+ if sandbox :
117+ return api_endpoint .replace (
118+ "sandbox.googleapis.com" , "mtls.sandbox.googleapis.com"
119+ )
120+
121+ return api_endpoint .replace (".googleapis.com" , ".mtls.googleapis.com" )
122+
123+ DEFAULT_ENDPOINT = "memcache.googleapis.com"
124+ DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint .__func__ ( # type: ignore
125+ DEFAULT_ENDPOINT
95126 )
96127
97128 @classmethod
@@ -121,12 +152,21 @@ def instance_path(project: str, location: str, instance: str) -> str:
121152 project = project , location = location , instance = instance
122153 )
123154
155+ @staticmethod
156+ def parse_instance_path (path : str ) -> Dict [str , str ]:
157+ """Parse a instance path into its component segments."""
158+ m = re .match (
159+ r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)/instances/(?P<instance>.+?)$" ,
160+ path ,
161+ )
162+ return m .groupdict () if m else {}
163+
124164 def __init__ (
125165 self ,
126166 * ,
127167 credentials : credentials .Credentials = None ,
128168 transport : Union [str , CloudMemcacheTransport ] = None ,
129- client_options : ClientOptions = DEFAULT_OPTIONS ,
169+ client_options : ClientOptions = None ,
130170 ) -> None :
131171 """Instantiate the cloud memcache client.
132172
@@ -140,6 +180,17 @@ def __init__(
140180 transport to use. If set to None, a transport is chosen
141181 automatically.
142182 client_options (ClientOptions): Custom options for the client.
183+ (1) The ``api_endpoint`` property can be used to override the
184+ default endpoint provided by the client.
185+ (2) If ``transport`` argument is None, ``client_options`` can be
186+ used to create a mutual TLS transport. If ``client_cert_source``
187+ is provided, mutual TLS transport will be created with the given
188+ ``api_endpoint`` or the default mTLS endpoint, and the client
189+ SSL credentials obtained from ``client_cert_source``.
190+
191+ Raises:
192+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
193+ creation failed for any reason.
143194 """
144195 if isinstance (client_options , dict ):
145196 client_options = ClientOptions .from_dict (client_options )
@@ -148,17 +199,46 @@ def __init__(
148199 # Ordinarily, we provide the transport, but allowing a custom transport
149200 # instance provides an extensibility point for unusual situations.
150201 if isinstance (transport , CloudMemcacheTransport ):
202+ # transport is a CloudMemcacheTransport instance.
151203 if credentials :
152204 raise ValueError (
153205 "When providing a transport instance, "
154206 "provide its credentials directly."
155207 )
156208 self ._transport = transport
157- else :
209+ elif client_options is None or (
210+ client_options .api_endpoint is None
211+ and client_options .client_cert_source is None
212+ ):
213+ # Don't trigger mTLS if we get an empty ClientOptions.
158214 Transport = type (self ).get_transport_class (transport )
159215 self ._transport = Transport (
216+ credentials = credentials , host = self .DEFAULT_ENDPOINT
217+ )
218+ else :
219+ # We have a non-empty ClientOptions. If client_cert_source is
220+ # provided, trigger mTLS with user provided endpoint or the default
221+ # mTLS endpoint.
222+ if client_options .client_cert_source :
223+ api_mtls_endpoint = (
224+ client_options .api_endpoint
225+ if client_options .api_endpoint
226+ else self .DEFAULT_MTLS_ENDPOINT
227+ )
228+ else :
229+ api_mtls_endpoint = None
230+
231+ api_endpoint = (
232+ client_options .api_endpoint
233+ if client_options .api_endpoint
234+ else self .DEFAULT_ENDPOINT
235+ )
236+
237+ self ._transport = CloudMemcacheGrpcTransport (
160238 credentials = credentials ,
161- host = client_options .api_endpoint or "memcache.googleapis.com" ,
239+ host = api_endpoint ,
240+ api_mtls_endpoint = api_mtls_endpoint ,
241+ client_cert_source = client_options .client_cert_source ,
162242 )
163243
164244 def list_instances (
0 commit comments