google-cloud-container 2.61.0__tar.gz → 2.62.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {google_cloud_container-2.61.0/google_cloud_container.egg-info → google_cloud_container-2.62.0}/PKG-INFO +1 -1
  2. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/gapic_version.py +1 -1
  3. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/__init__.py +104 -0
  4. {google_cloud_container-2.61.0/google/cloud/container_v1beta1 → google_cloud_container-2.62.0/google/cloud/container_v1}/gapic_version.py +1 -1
  5. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/client.py +32 -14
  6. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/__init__.py +104 -0
  7. {google_cloud_container-2.61.0/google/cloud/container_v1 → google_cloud_container-2.62.0/google/cloud/container_v1beta1}/gapic_version.py +1 -1
  8. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/client.py +32 -14
  9. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0/google_cloud_container.egg-info}/PKG-INFO +1 -1
  10. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1/test_cluster_manager.py +226 -29
  11. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1beta1/test_cluster_manager.py +226 -29
  12. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/LICENSE +0 -0
  13. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/MANIFEST.in +0 -0
  14. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/README.rst +0 -0
  15. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/__init__.py +0 -0
  16. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/py.typed +0 -0
  17. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/gapic_metadata.json +0 -0
  18. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/py.typed +0 -0
  19. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/__init__.py +0 -0
  20. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/__init__.py +0 -0
  21. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/async_client.py +0 -0
  22. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/pagers.py +0 -0
  23. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/__init__.py +0 -0
  24. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/base.py +0 -0
  25. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/grpc.py +0 -0
  26. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/grpc_asyncio.py +0 -0
  27. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/rest.py +0 -0
  28. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/rest_base.py +0 -0
  29. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/types/__init__.py +0 -0
  30. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/types/cluster_service.py +0 -0
  31. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/gapic_metadata.json +0 -0
  32. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/py.typed +0 -0
  33. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/__init__.py +0 -0
  34. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/__init__.py +0 -0
  35. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/async_client.py +0 -0
  36. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/pagers.py +0 -0
  37. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/__init__.py +0 -0
  38. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/base.py +0 -0
  39. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/grpc.py +0 -0
  40. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/grpc_asyncio.py +0 -0
  41. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/types/__init__.py +0 -0
  42. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/types/cluster_service.py +0 -0
  43. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/SOURCES.txt +0 -0
  44. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/dependency_links.txt +0 -0
  45. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/not-zip-safe +0 -0
  46. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/requires.txt +0 -0
  47. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/top_level.txt +0 -0
  48. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/setup.cfg +0 -0
  49. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/setup.py +0 -0
  50. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/__init__.py +0 -0
  51. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/system/__init__.py +0 -0
  52. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/system/smoke_test.py +0 -0
  53. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/__init__.py +0 -0
  54. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/__init__.py +0 -0
  55. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1/__init__.py +0 -0
  56. {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1beta1/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-container
3
- Version: 2.61.0
3
+ Version: 2.62.0
4
4
  Summary: Google Cloud Container API client library
5
5
  Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-container
6
6
  Author: Google LLC
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "2.61.0" # {x-release-please-version}
16
+ __version__ = "2.62.0" # {x-release-please-version}
@@ -13,10 +13,20 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
+ import sys
17
+
18
+ import google.api_core as api_core
19
+
16
20
  from google.cloud.container_v1 import gapic_version as package_version
17
21
 
18
22
  __version__ = package_version.__version__
19
23
 
24
+ if sys.version_info >= (3, 8): # pragma: NO COVER
25
+ from importlib import metadata
26
+ else: # pragma: NO COVER
27
+ # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
28
+ # this code path once we drop support for Python 3.7
29
+ import importlib_metadata as metadata
20
30
 
21
31
  from .services.cluster_manager import ClusterManagerAsyncClient, ClusterManagerClient
22
32
  from .types.cluster_service import (
@@ -225,6 +235,100 @@ from .types.cluster_service import (
225
235
  WorkloadPolicyConfig,
226
236
  )
227
237
 
238
+ if hasattr(api_core, "check_python_version") and hasattr(
239
+ api_core, "check_dependency_versions"
240
+ ): # pragma: NO COVER
241
+ api_core.check_python_version("google.cloud.container_v1") # type: ignore
242
+ api_core.check_dependency_versions("google.cloud.container_v1") # type: ignore
243
+ else: # pragma: NO COVER
244
+ # An older version of api_core is installed which does not define the
245
+ # functions above. We do equivalent checks manually.
246
+ try:
247
+ import sys
248
+ import warnings
249
+
250
+ _py_version_str = sys.version.split()[0]
251
+ _package_label = "google.cloud.container_v1"
252
+ if sys.version_info < (3, 9):
253
+ warnings.warn(
254
+ "You are using a non-supported Python version "
255
+ + f"({_py_version_str}). Google will not post any further "
256
+ + f"updates to {_package_label} supporting this Python version. "
257
+ + "Please upgrade to the latest Python version, or at "
258
+ + f"least to Python 3.9, and then update {_package_label}.",
259
+ FutureWarning,
260
+ )
261
+ if sys.version_info[:2] == (3, 9):
262
+ warnings.warn(
263
+ f"You are using a Python version ({_py_version_str}) "
264
+ + f"which Google will stop supporting in {_package_label} in "
265
+ + "January 2026. Please "
266
+ + "upgrade to the latest Python version, or at "
267
+ + "least to Python 3.10, before then, and "
268
+ + f"then update {_package_label}.",
269
+ FutureWarning,
270
+ )
271
+
272
+ def parse_version_to_tuple(version_string: str):
273
+ """Safely converts a semantic version string to a comparable tuple of integers.
274
+ Example: "4.25.8" -> (4, 25, 8)
275
+ Ignores non-numeric parts and handles common version formats.
276
+ Args:
277
+ version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
278
+ Returns:
279
+ Tuple of integers for the parsed version string.
280
+ """
281
+ parts = []
282
+ for part in version_string.split("."):
283
+ try:
284
+ parts.append(int(part))
285
+ except ValueError:
286
+ # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
287
+ # This is a simplification compared to 'packaging.parse_version', but sufficient
288
+ # for comparing strictly numeric semantic versions.
289
+ break
290
+ return tuple(parts)
291
+
292
+ def _get_version(dependency_name):
293
+ try:
294
+ version_string: str = metadata.version(dependency_name)
295
+ parsed_version = parse_version_to_tuple(version_string)
296
+ return (parsed_version, version_string)
297
+ except Exception:
298
+ # Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
299
+ # or errors during parse_version_to_tuple
300
+ return (None, "--")
301
+
302
+ _dependency_package = "google.protobuf"
303
+ _next_supported_version = "4.25.8"
304
+ _next_supported_version_tuple = (4, 25, 8)
305
+ _recommendation = " (we recommend 6.x)"
306
+ (_version_used, _version_used_string) = _get_version(_dependency_package)
307
+ if _version_used and _version_used < _next_supported_version_tuple:
308
+ warnings.warn(
309
+ f"Package {_package_label} depends on "
310
+ + f"{_dependency_package}, currently installed at version "
311
+ + f"{_version_used_string}. Future updates to "
312
+ + f"{_package_label} will require {_dependency_package} at "
313
+ + f"version {_next_supported_version} or higher{_recommendation}."
314
+ + " Please ensure "
315
+ + "that either (a) your Python environment doesn't pin the "
316
+ + f"version of {_dependency_package}, so that updates to "
317
+ + f"{_package_label} can require the higher version, or "
318
+ + "(b) you manually update your Python environment to use at "
319
+ + f"least version {_next_supported_version} of "
320
+ + f"{_dependency_package}.",
321
+ FutureWarning,
322
+ )
323
+ except Exception:
324
+ warnings.warn(
325
+ "Could not determine the version of Python "
326
+ + "currently being used. To continue receiving "
327
+ + "updates for {_package_label}, ensure you are "
328
+ + "using a supported version of Python; see "
329
+ + "https://devguide.python.org/versions/"
330
+ )
331
+
228
332
  __all__ = (
229
333
  "ClusterManagerAsyncClient",
230
334
  "AcceleratorConfig",
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "2.61.0" # {x-release-please-version}
16
+ __version__ = "2.62.0" # {x-release-please-version}
@@ -151,6 +151,34 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
151
151
  _DEFAULT_ENDPOINT_TEMPLATE = "container.{UNIVERSE_DOMAIN}"
152
152
  _DEFAULT_UNIVERSE = "googleapis.com"
153
153
 
154
+ @staticmethod
155
+ def _use_client_cert_effective():
156
+ """Returns whether client certificate should be used for mTLS if the
157
+ google-auth version supports should_use_client_cert automatic mTLS enablement.
158
+
159
+ Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
160
+
161
+ Returns:
162
+ bool: whether client certificate should be used for mTLS
163
+ Raises:
164
+ ValueError: (If using a version of google-auth without should_use_client_cert and
165
+ GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
166
+ """
167
+ # check if google-auth version supports should_use_client_cert for automatic mTLS enablement
168
+ if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
169
+ return mtls.should_use_client_cert()
170
+ else: # pragma: NO COVER
171
+ # if unsupported, fallback to reading from env var
172
+ use_client_cert_str = os.getenv(
173
+ "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
174
+ ).lower()
175
+ if use_client_cert_str not in ("true", "false"):
176
+ raise ValueError(
177
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
178
+ " either `true` or `false`"
179
+ )
180
+ return use_client_cert_str == "true"
181
+
154
182
  @classmethod
155
183
  def from_service_account_info(cls, info: dict, *args, **kwargs):
156
184
  """Creates an instance of this client using the provided credentials
@@ -381,12 +409,8 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
381
409
  )
382
410
  if client_options is None:
383
411
  client_options = client_options_lib.ClientOptions()
384
- use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
412
+ use_client_cert = ClusterManagerClient._use_client_cert_effective()
385
413
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
386
- if use_client_cert not in ("true", "false"):
387
- raise ValueError(
388
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
389
- )
390
414
  if use_mtls_endpoint not in ("auto", "never", "always"):
391
415
  raise MutualTLSChannelError(
392
416
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
@@ -394,7 +418,7 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
394
418
 
395
419
  # Figure out the client cert source to use.
396
420
  client_cert_source = None
397
- if use_client_cert == "true":
421
+ if use_client_cert:
398
422
  if client_options.client_cert_source:
399
423
  client_cert_source = client_options.client_cert_source
400
424
  elif mtls.has_default_client_cert_source():
@@ -426,20 +450,14 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
426
450
  google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
427
451
  is not any of ["auto", "never", "always"].
428
452
  """
429
- use_client_cert = os.getenv(
430
- "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
431
- ).lower()
453
+ use_client_cert = ClusterManagerClient._use_client_cert_effective()
432
454
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
433
455
  universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
434
- if use_client_cert not in ("true", "false"):
435
- raise ValueError(
436
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
437
- )
438
456
  if use_mtls_endpoint not in ("auto", "never", "always"):
439
457
  raise MutualTLSChannelError(
440
458
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
441
459
  )
442
- return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
460
+ return use_client_cert, use_mtls_endpoint, universe_domain_env
443
461
 
444
462
  @staticmethod
445
463
  def _get_client_cert_source(provided_cert_source, use_cert_flag):
@@ -13,10 +13,20 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
+ import sys
17
+
18
+ import google.api_core as api_core
19
+
16
20
  from google.cloud.container_v1beta1 import gapic_version as package_version
17
21
 
18
22
  __version__ = package_version.__version__
19
23
 
24
+ if sys.version_info >= (3, 8): # pragma: NO COVER
25
+ from importlib import metadata
26
+ else: # pragma: NO COVER
27
+ # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
28
+ # this code path once we drop support for Python 3.7
29
+ import importlib_metadata as metadata
20
30
 
21
31
  from .services.cluster_manager import ClusterManagerAsyncClient, ClusterManagerClient
22
32
  from .types.cluster_service import (
@@ -242,6 +252,100 @@ from .types.cluster_service import (
242
252
  WorkloadPolicyConfig,
243
253
  )
244
254
 
255
+ if hasattr(api_core, "check_python_version") and hasattr(
256
+ api_core, "check_dependency_versions"
257
+ ): # pragma: NO COVER
258
+ api_core.check_python_version("google.cloud.container_v1beta1") # type: ignore
259
+ api_core.check_dependency_versions("google.cloud.container_v1beta1") # type: ignore
260
+ else: # pragma: NO COVER
261
+ # An older version of api_core is installed which does not define the
262
+ # functions above. We do equivalent checks manually.
263
+ try:
264
+ import sys
265
+ import warnings
266
+
267
+ _py_version_str = sys.version.split()[0]
268
+ _package_label = "google.cloud.container_v1beta1"
269
+ if sys.version_info < (3, 9):
270
+ warnings.warn(
271
+ "You are using a non-supported Python version "
272
+ + f"({_py_version_str}). Google will not post any further "
273
+ + f"updates to {_package_label} supporting this Python version. "
274
+ + "Please upgrade to the latest Python version, or at "
275
+ + f"least to Python 3.9, and then update {_package_label}.",
276
+ FutureWarning,
277
+ )
278
+ if sys.version_info[:2] == (3, 9):
279
+ warnings.warn(
280
+ f"You are using a Python version ({_py_version_str}) "
281
+ + f"which Google will stop supporting in {_package_label} in "
282
+ + "January 2026. Please "
283
+ + "upgrade to the latest Python version, or at "
284
+ + "least to Python 3.10, before then, and "
285
+ + f"then update {_package_label}.",
286
+ FutureWarning,
287
+ )
288
+
289
+ def parse_version_to_tuple(version_string: str):
290
+ """Safely converts a semantic version string to a comparable tuple of integers.
291
+ Example: "4.25.8" -> (4, 25, 8)
292
+ Ignores non-numeric parts and handles common version formats.
293
+ Args:
294
+ version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
295
+ Returns:
296
+ Tuple of integers for the parsed version string.
297
+ """
298
+ parts = []
299
+ for part in version_string.split("."):
300
+ try:
301
+ parts.append(int(part))
302
+ except ValueError:
303
+ # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
304
+ # This is a simplification compared to 'packaging.parse_version', but sufficient
305
+ # for comparing strictly numeric semantic versions.
306
+ break
307
+ return tuple(parts)
308
+
309
+ def _get_version(dependency_name):
310
+ try:
311
+ version_string: str = metadata.version(dependency_name)
312
+ parsed_version = parse_version_to_tuple(version_string)
313
+ return (parsed_version, version_string)
314
+ except Exception:
315
+ # Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
316
+ # or errors during parse_version_to_tuple
317
+ return (None, "--")
318
+
319
+ _dependency_package = "google.protobuf"
320
+ _next_supported_version = "4.25.8"
321
+ _next_supported_version_tuple = (4, 25, 8)
322
+ _recommendation = " (we recommend 6.x)"
323
+ (_version_used, _version_used_string) = _get_version(_dependency_package)
324
+ if _version_used and _version_used < _next_supported_version_tuple:
325
+ warnings.warn(
326
+ f"Package {_package_label} depends on "
327
+ + f"{_dependency_package}, currently installed at version "
328
+ + f"{_version_used_string}. Future updates to "
329
+ + f"{_package_label} will require {_dependency_package} at "
330
+ + f"version {_next_supported_version} or higher{_recommendation}."
331
+ + " Please ensure "
332
+ + "that either (a) your Python environment doesn't pin the "
333
+ + f"version of {_dependency_package}, so that updates to "
334
+ + f"{_package_label} can require the higher version, or "
335
+ + "(b) you manually update your Python environment to use at "
336
+ + f"least version {_next_supported_version} of "
337
+ + f"{_dependency_package}.",
338
+ FutureWarning,
339
+ )
340
+ except Exception:
341
+ warnings.warn(
342
+ "Could not determine the version of Python "
343
+ + "currently being used. To continue receiving "
344
+ + "updates for {_package_label}, ensure you are "
345
+ + "using a supported version of Python; see "
346
+ + "https://devguide.python.org/versions/"
347
+ )
348
+
245
349
  __all__ = (
246
350
  "ClusterManagerAsyncClient",
247
351
  "AcceleratorConfig",
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "2.61.0" # {x-release-please-version}
16
+ __version__ = "2.62.0" # {x-release-please-version}
@@ -149,6 +149,34 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
149
149
  _DEFAULT_ENDPOINT_TEMPLATE = "container.{UNIVERSE_DOMAIN}"
150
150
  _DEFAULT_UNIVERSE = "googleapis.com"
151
151
 
152
+ @staticmethod
153
+ def _use_client_cert_effective():
154
+ """Returns whether client certificate should be used for mTLS if the
155
+ google-auth version supports should_use_client_cert automatic mTLS enablement.
156
+
157
+ Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
158
+
159
+ Returns:
160
+ bool: whether client certificate should be used for mTLS
161
+ Raises:
162
+ ValueError: (If using a version of google-auth without should_use_client_cert and
163
+ GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
164
+ """
165
+ # check if google-auth version supports should_use_client_cert for automatic mTLS enablement
166
+ if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
167
+ return mtls.should_use_client_cert()
168
+ else: # pragma: NO COVER
169
+ # if unsupported, fallback to reading from env var
170
+ use_client_cert_str = os.getenv(
171
+ "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
172
+ ).lower()
173
+ if use_client_cert_str not in ("true", "false"):
174
+ raise ValueError(
175
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
176
+ " either `true` or `false`"
177
+ )
178
+ return use_client_cert_str == "true"
179
+
152
180
  @classmethod
153
181
  def from_service_account_info(cls, info: dict, *args, **kwargs):
154
182
  """Creates an instance of this client using the provided credentials
@@ -379,12 +407,8 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
379
407
  )
380
408
  if client_options is None:
381
409
  client_options = client_options_lib.ClientOptions()
382
- use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
410
+ use_client_cert = ClusterManagerClient._use_client_cert_effective()
383
411
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
384
- if use_client_cert not in ("true", "false"):
385
- raise ValueError(
386
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
387
- )
388
412
  if use_mtls_endpoint not in ("auto", "never", "always"):
389
413
  raise MutualTLSChannelError(
390
414
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
@@ -392,7 +416,7 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
392
416
 
393
417
  # Figure out the client cert source to use.
394
418
  client_cert_source = None
395
- if use_client_cert == "true":
419
+ if use_client_cert:
396
420
  if client_options.client_cert_source:
397
421
  client_cert_source = client_options.client_cert_source
398
422
  elif mtls.has_default_client_cert_source():
@@ -424,20 +448,14 @@ class ClusterManagerClient(metaclass=ClusterManagerClientMeta):
424
448
  google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
425
449
  is not any of ["auto", "never", "always"].
426
450
  """
427
- use_client_cert = os.getenv(
428
- "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
429
- ).lower()
451
+ use_client_cert = ClusterManagerClient._use_client_cert_effective()
430
452
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
431
453
  universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
432
- if use_client_cert not in ("true", "false"):
433
- raise ValueError(
434
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
435
- )
436
454
  if use_mtls_endpoint not in ("auto", "never", "always"):
437
455
  raise MutualTLSChannelError(
438
456
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
439
457
  )
440
- return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
458
+ return use_client_cert, use_mtls_endpoint, universe_domain_env
441
459
 
442
460
  @staticmethod
443
461
  def _get_client_cert_source(provided_cert_source, use_cert_flag):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-container
3
- Version: 2.61.0
3
+ Version: 2.62.0
4
4
  Summary: Google Cloud Container API client library
5
5
  Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-container
6
6
  Author: Google LLC
@@ -162,12 +162,19 @@ def test__read_environment_variables():
162
162
  with mock.patch.dict(
163
163
  os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
164
164
  ):
165
- with pytest.raises(ValueError) as excinfo:
166
- ClusterManagerClient._read_environment_variables()
167
- assert (
168
- str(excinfo.value)
169
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
170
- )
165
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
166
+ with pytest.raises(ValueError) as excinfo:
167
+ ClusterManagerClient._read_environment_variables()
168
+ assert (
169
+ str(excinfo.value)
170
+ == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
171
+ )
172
+ else:
173
+ assert ClusterManagerClient._read_environment_variables() == (
174
+ False,
175
+ "auto",
176
+ None,
177
+ )
171
178
 
172
179
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
173
180
  assert ClusterManagerClient._read_environment_variables() == (
@@ -206,6 +213,105 @@ def test__read_environment_variables():
206
213
  )
207
214
 
208
215
 
216
+ def test_use_client_cert_effective():
217
+ # Test case 1: Test when `should_use_client_cert` returns True.
218
+ # We mock the `should_use_client_cert` function to simulate a scenario where
219
+ # the google-auth library supports automatic mTLS and determines that a
220
+ # client certificate should be used.
221
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
222
+ with mock.patch(
223
+ "google.auth.transport.mtls.should_use_client_cert", return_value=True
224
+ ):
225
+ assert ClusterManagerClient._use_client_cert_effective() is True
226
+
227
+ # Test case 2: Test when `should_use_client_cert` returns False.
228
+ # We mock the `should_use_client_cert` function to simulate a scenario where
229
+ # the google-auth library supports automatic mTLS and determines that a
230
+ # client certificate should NOT be used.
231
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
232
+ with mock.patch(
233
+ "google.auth.transport.mtls.should_use_client_cert", return_value=False
234
+ ):
235
+ assert ClusterManagerClient._use_client_cert_effective() is False
236
+
237
+ # Test case 3: Test when `should_use_client_cert` is unavailable and the
238
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true".
239
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
240
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}):
241
+ assert ClusterManagerClient._use_client_cert_effective() is True
242
+
243
+ # Test case 4: Test when `should_use_client_cert` is unavailable and the
244
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false".
245
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
246
+ with mock.patch.dict(
247
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}
248
+ ):
249
+ assert ClusterManagerClient._use_client_cert_effective() is False
250
+
251
+ # Test case 5: Test when `should_use_client_cert` is unavailable and the
252
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True".
253
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
254
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "True"}):
255
+ assert ClusterManagerClient._use_client_cert_effective() is True
256
+
257
+ # Test case 6: Test when `should_use_client_cert` is unavailable and the
258
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False".
259
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
260
+ with mock.patch.dict(
261
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "False"}
262
+ ):
263
+ assert ClusterManagerClient._use_client_cert_effective() is False
264
+
265
+ # Test case 7: Test when `should_use_client_cert` is unavailable and the
266
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE".
267
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
268
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "TRUE"}):
269
+ assert ClusterManagerClient._use_client_cert_effective() is True
270
+
271
+ # Test case 8: Test when `should_use_client_cert` is unavailable and the
272
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE".
273
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
274
+ with mock.patch.dict(
275
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "FALSE"}
276
+ ):
277
+ assert ClusterManagerClient._use_client_cert_effective() is False
278
+
279
+ # Test case 9: Test when `should_use_client_cert` is unavailable and the
280
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set.
281
+ # In this case, the method should return False, which is the default value.
282
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
283
+ with mock.patch.dict(os.environ, clear=True):
284
+ assert ClusterManagerClient._use_client_cert_effective() is False
285
+
286
+ # Test case 10: Test when `should_use_client_cert` is unavailable and the
287
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
288
+ # The method should raise a ValueError as the environment variable must be either
289
+ # "true" or "false".
290
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
291
+ with mock.patch.dict(
292
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
293
+ ):
294
+ with pytest.raises(ValueError):
295
+ ClusterManagerClient._use_client_cert_effective()
296
+
297
+ # Test case 11: Test when `should_use_client_cert` is available and the
298
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
299
+ # The method should return False as the environment variable is set to an invalid value.
300
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
301
+ with mock.patch.dict(
302
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
303
+ ):
304
+ assert ClusterManagerClient._use_client_cert_effective() is False
305
+
306
+ # Test case 12: Test when `should_use_client_cert` is available and the
307
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also,
308
+ # the GOOGLE_API_CONFIG environment variable is unset.
309
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
310
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": ""}):
311
+ with mock.patch.dict(os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": ""}):
312
+ assert ClusterManagerClient._use_client_cert_effective() is False
313
+
314
+
209
315
  def test__get_client_cert_source():
210
316
  mock_provided_cert_source = mock.Mock()
211
317
  mock_default_cert_source = mock.Mock()
@@ -571,17 +677,6 @@ def test_cluster_manager_client_client_options(
571
677
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
572
678
  )
573
679
 
574
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
575
- with mock.patch.dict(
576
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
577
- ):
578
- with pytest.raises(ValueError) as excinfo:
579
- client = client_class(transport=transport_name)
580
- assert (
581
- str(excinfo.value)
582
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
583
- )
584
-
585
680
  # Check the case quota_project_id is provided
586
681
  options = client_options.ClientOptions(quota_project_id="octopus")
587
682
  with mock.patch.object(transport_class, "__init__") as patched:
@@ -797,6 +892,119 @@ def test_cluster_manager_client_get_mtls_endpoint_and_cert_source(client_class):
797
892
  assert api_endpoint == mock_api_endpoint
798
893
  assert cert_source is None
799
894
 
895
+ # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "Unsupported".
896
+ with mock.patch.dict(
897
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
898
+ ):
899
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
900
+ mock_client_cert_source = mock.Mock()
901
+ mock_api_endpoint = "foo"
902
+ options = client_options.ClientOptions(
903
+ client_cert_source=mock_client_cert_source,
904
+ api_endpoint=mock_api_endpoint,
905
+ )
906
+ api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source(
907
+ options
908
+ )
909
+ assert api_endpoint == mock_api_endpoint
910
+ assert cert_source is None
911
+
912
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset.
913
+ test_cases = [
914
+ (
915
+ # With workloads present in config, mTLS is enabled.
916
+ {
917
+ "version": 1,
918
+ "cert_configs": {
919
+ "workload": {
920
+ "cert_path": "path/to/cert/file",
921
+ "key_path": "path/to/key/file",
922
+ }
923
+ },
924
+ },
925
+ mock_client_cert_source,
926
+ ),
927
+ (
928
+ # With workloads not present in config, mTLS is disabled.
929
+ {
930
+ "version": 1,
931
+ "cert_configs": {},
932
+ },
933
+ None,
934
+ ),
935
+ ]
936
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
937
+ for config_data, expected_cert_source in test_cases:
938
+ env = os.environ.copy()
939
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", None)
940
+ with mock.patch.dict(os.environ, env, clear=True):
941
+ config_filename = "mock_certificate_config.json"
942
+ config_file_content = json.dumps(config_data)
943
+ m = mock.mock_open(read_data=config_file_content)
944
+ with mock.patch("builtins.open", m):
945
+ with mock.patch.dict(
946
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
947
+ ):
948
+ mock_api_endpoint = "foo"
949
+ options = client_options.ClientOptions(
950
+ client_cert_source=mock_client_cert_source,
951
+ api_endpoint=mock_api_endpoint,
952
+ )
953
+ (
954
+ api_endpoint,
955
+ cert_source,
956
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
957
+ assert api_endpoint == mock_api_endpoint
958
+ assert cert_source is expected_cert_source
959
+
960
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty).
961
+ test_cases = [
962
+ (
963
+ # With workloads present in config, mTLS is enabled.
964
+ {
965
+ "version": 1,
966
+ "cert_configs": {
967
+ "workload": {
968
+ "cert_path": "path/to/cert/file",
969
+ "key_path": "path/to/key/file",
970
+ }
971
+ },
972
+ },
973
+ mock_client_cert_source,
974
+ ),
975
+ (
976
+ # With workloads not present in config, mTLS is disabled.
977
+ {
978
+ "version": 1,
979
+ "cert_configs": {},
980
+ },
981
+ None,
982
+ ),
983
+ ]
984
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
985
+ for config_data, expected_cert_source in test_cases:
986
+ env = os.environ.copy()
987
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", "")
988
+ with mock.patch.dict(os.environ, env, clear=True):
989
+ config_filename = "mock_certificate_config.json"
990
+ config_file_content = json.dumps(config_data)
991
+ m = mock.mock_open(read_data=config_file_content)
992
+ with mock.patch("builtins.open", m):
993
+ with mock.patch.dict(
994
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
995
+ ):
996
+ mock_api_endpoint = "foo"
997
+ options = client_options.ClientOptions(
998
+ client_cert_source=mock_client_cert_source,
999
+ api_endpoint=mock_api_endpoint,
1000
+ )
1001
+ (
1002
+ api_endpoint,
1003
+ cert_source,
1004
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
1005
+ assert api_endpoint == mock_api_endpoint
1006
+ assert cert_source is expected_cert_source
1007
+
800
1008
  # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never".
801
1009
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
802
1010
  api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source()
@@ -847,18 +1055,6 @@ def test_cluster_manager_client_get_mtls_endpoint_and_cert_source(client_class):
847
1055
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
848
1056
  )
849
1057
 
850
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
851
- with mock.patch.dict(
852
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
853
- ):
854
- with pytest.raises(ValueError) as excinfo:
855
- client_class.get_mtls_endpoint_and_cert_source()
856
-
857
- assert (
858
- str(excinfo.value)
859
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
860
- )
861
-
862
1058
 
863
1059
  @pytest.mark.parametrize(
864
1060
  "client_class", [ClusterManagerClient, ClusterManagerAsyncClient]
@@ -28122,6 +28318,7 @@ def test_cluster_manager_grpc_asyncio_transport_channel():
28122
28318
 
28123
28319
  # Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
28124
28320
  # removed from grpc/grpc_asyncio transport constructor.
28321
+ @pytest.mark.filterwarnings("ignore::FutureWarning")
28125
28322
  @pytest.mark.parametrize(
28126
28323
  "transport_class",
28127
28324
  [
@@ -158,12 +158,19 @@ def test__read_environment_variables():
158
158
  with mock.patch.dict(
159
159
  os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
160
160
  ):
161
- with pytest.raises(ValueError) as excinfo:
162
- ClusterManagerClient._read_environment_variables()
163
- assert (
164
- str(excinfo.value)
165
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
166
- )
161
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
162
+ with pytest.raises(ValueError) as excinfo:
163
+ ClusterManagerClient._read_environment_variables()
164
+ assert (
165
+ str(excinfo.value)
166
+ == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
167
+ )
168
+ else:
169
+ assert ClusterManagerClient._read_environment_variables() == (
170
+ False,
171
+ "auto",
172
+ None,
173
+ )
167
174
 
168
175
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
169
176
  assert ClusterManagerClient._read_environment_variables() == (
@@ -202,6 +209,105 @@ def test__read_environment_variables():
202
209
  )
203
210
 
204
211
 
212
+ def test_use_client_cert_effective():
213
+ # Test case 1: Test when `should_use_client_cert` returns True.
214
+ # We mock the `should_use_client_cert` function to simulate a scenario where
215
+ # the google-auth library supports automatic mTLS and determines that a
216
+ # client certificate should be used.
217
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
218
+ with mock.patch(
219
+ "google.auth.transport.mtls.should_use_client_cert", return_value=True
220
+ ):
221
+ assert ClusterManagerClient._use_client_cert_effective() is True
222
+
223
+ # Test case 2: Test when `should_use_client_cert` returns False.
224
+ # We mock the `should_use_client_cert` function to simulate a scenario where
225
+ # the google-auth library supports automatic mTLS and determines that a
226
+ # client certificate should NOT be used.
227
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
228
+ with mock.patch(
229
+ "google.auth.transport.mtls.should_use_client_cert", return_value=False
230
+ ):
231
+ assert ClusterManagerClient._use_client_cert_effective() is False
232
+
233
+ # Test case 3: Test when `should_use_client_cert` is unavailable and the
234
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true".
235
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
236
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}):
237
+ assert ClusterManagerClient._use_client_cert_effective() is True
238
+
239
+ # Test case 4: Test when `should_use_client_cert` is unavailable and the
240
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false".
241
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
242
+ with mock.patch.dict(
243
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}
244
+ ):
245
+ assert ClusterManagerClient._use_client_cert_effective() is False
246
+
247
+ # Test case 5: Test when `should_use_client_cert` is unavailable and the
248
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True".
249
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
250
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "True"}):
251
+ assert ClusterManagerClient._use_client_cert_effective() is True
252
+
253
+ # Test case 6: Test when `should_use_client_cert` is unavailable and the
254
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False".
255
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
256
+ with mock.patch.dict(
257
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "False"}
258
+ ):
259
+ assert ClusterManagerClient._use_client_cert_effective() is False
260
+
261
+ # Test case 7: Test when `should_use_client_cert` is unavailable and the
262
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE".
263
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
264
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "TRUE"}):
265
+ assert ClusterManagerClient._use_client_cert_effective() is True
266
+
267
+ # Test case 8: Test when `should_use_client_cert` is unavailable and the
268
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE".
269
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
270
+ with mock.patch.dict(
271
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "FALSE"}
272
+ ):
273
+ assert ClusterManagerClient._use_client_cert_effective() is False
274
+
275
+ # Test case 9: Test when `should_use_client_cert` is unavailable and the
276
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set.
277
+ # In this case, the method should return False, which is the default value.
278
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
279
+ with mock.patch.dict(os.environ, clear=True):
280
+ assert ClusterManagerClient._use_client_cert_effective() is False
281
+
282
+ # Test case 10: Test when `should_use_client_cert` is unavailable and the
283
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
284
+ # The method should raise a ValueError as the environment variable must be either
285
+ # "true" or "false".
286
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
287
+ with mock.patch.dict(
288
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
289
+ ):
290
+ with pytest.raises(ValueError):
291
+ ClusterManagerClient._use_client_cert_effective()
292
+
293
+ # Test case 11: Test when `should_use_client_cert` is available and the
294
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
295
+ # The method should return False as the environment variable is set to an invalid value.
296
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
297
+ with mock.patch.dict(
298
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
299
+ ):
300
+ assert ClusterManagerClient._use_client_cert_effective() is False
301
+
302
+ # Test case 12: Test when `should_use_client_cert` is available and the
303
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also,
304
+ # the GOOGLE_API_CONFIG environment variable is unset.
305
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
306
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": ""}):
307
+ with mock.patch.dict(os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": ""}):
308
+ assert ClusterManagerClient._use_client_cert_effective() is False
309
+
310
+
205
311
  def test__get_client_cert_source():
206
312
  mock_provided_cert_source = mock.Mock()
207
313
  mock_default_cert_source = mock.Mock()
@@ -554,17 +660,6 @@ def test_cluster_manager_client_client_options(
554
660
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
555
661
  )
556
662
 
557
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
558
- with mock.patch.dict(
559
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
560
- ):
561
- with pytest.raises(ValueError) as excinfo:
562
- client = client_class(transport=transport_name)
563
- assert (
564
- str(excinfo.value)
565
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
566
- )
567
-
568
663
  # Check the case quota_project_id is provided
569
664
  options = client_options.ClientOptions(quota_project_id="octopus")
570
665
  with mock.patch.object(transport_class, "__init__") as patched:
@@ -778,6 +873,119 @@ def test_cluster_manager_client_get_mtls_endpoint_and_cert_source(client_class):
778
873
  assert api_endpoint == mock_api_endpoint
779
874
  assert cert_source is None
780
875
 
876
+ # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "Unsupported".
877
+ with mock.patch.dict(
878
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
879
+ ):
880
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
881
+ mock_client_cert_source = mock.Mock()
882
+ mock_api_endpoint = "foo"
883
+ options = client_options.ClientOptions(
884
+ client_cert_source=mock_client_cert_source,
885
+ api_endpoint=mock_api_endpoint,
886
+ )
887
+ api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source(
888
+ options
889
+ )
890
+ assert api_endpoint == mock_api_endpoint
891
+ assert cert_source is None
892
+
893
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset.
894
+ test_cases = [
895
+ (
896
+ # With workloads present in config, mTLS is enabled.
897
+ {
898
+ "version": 1,
899
+ "cert_configs": {
900
+ "workload": {
901
+ "cert_path": "path/to/cert/file",
902
+ "key_path": "path/to/key/file",
903
+ }
904
+ },
905
+ },
906
+ mock_client_cert_source,
907
+ ),
908
+ (
909
+ # With workloads not present in config, mTLS is disabled.
910
+ {
911
+ "version": 1,
912
+ "cert_configs": {},
913
+ },
914
+ None,
915
+ ),
916
+ ]
917
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
918
+ for config_data, expected_cert_source in test_cases:
919
+ env = os.environ.copy()
920
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", None)
921
+ with mock.patch.dict(os.environ, env, clear=True):
922
+ config_filename = "mock_certificate_config.json"
923
+ config_file_content = json.dumps(config_data)
924
+ m = mock.mock_open(read_data=config_file_content)
925
+ with mock.patch("builtins.open", m):
926
+ with mock.patch.dict(
927
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
928
+ ):
929
+ mock_api_endpoint = "foo"
930
+ options = client_options.ClientOptions(
931
+ client_cert_source=mock_client_cert_source,
932
+ api_endpoint=mock_api_endpoint,
933
+ )
934
+ (
935
+ api_endpoint,
936
+ cert_source,
937
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
938
+ assert api_endpoint == mock_api_endpoint
939
+ assert cert_source is expected_cert_source
940
+
941
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty).
942
+ test_cases = [
943
+ (
944
+ # With workloads present in config, mTLS is enabled.
945
+ {
946
+ "version": 1,
947
+ "cert_configs": {
948
+ "workload": {
949
+ "cert_path": "path/to/cert/file",
950
+ "key_path": "path/to/key/file",
951
+ }
952
+ },
953
+ },
954
+ mock_client_cert_source,
955
+ ),
956
+ (
957
+ # With workloads not present in config, mTLS is disabled.
958
+ {
959
+ "version": 1,
960
+ "cert_configs": {},
961
+ },
962
+ None,
963
+ ),
964
+ ]
965
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
966
+ for config_data, expected_cert_source in test_cases:
967
+ env = os.environ.copy()
968
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", "")
969
+ with mock.patch.dict(os.environ, env, clear=True):
970
+ config_filename = "mock_certificate_config.json"
971
+ config_file_content = json.dumps(config_data)
972
+ m = mock.mock_open(read_data=config_file_content)
973
+ with mock.patch("builtins.open", m):
974
+ with mock.patch.dict(
975
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
976
+ ):
977
+ mock_api_endpoint = "foo"
978
+ options = client_options.ClientOptions(
979
+ client_cert_source=mock_client_cert_source,
980
+ api_endpoint=mock_api_endpoint,
981
+ )
982
+ (
983
+ api_endpoint,
984
+ cert_source,
985
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
986
+ assert api_endpoint == mock_api_endpoint
987
+ assert cert_source is expected_cert_source
988
+
781
989
  # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never".
782
990
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
783
991
  api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source()
@@ -828,18 +1036,6 @@ def test_cluster_manager_client_get_mtls_endpoint_and_cert_source(client_class):
828
1036
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
829
1037
  )
830
1038
 
831
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
832
- with mock.patch.dict(
833
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
834
- ):
835
- with pytest.raises(ValueError) as excinfo:
836
- client_class.get_mtls_endpoint_and_cert_source()
837
-
838
- assert (
839
- str(excinfo.value)
840
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
841
- )
842
-
843
1039
 
844
1040
  @pytest.mark.parametrize(
845
1041
  "client_class", [ClusterManagerClient, ClusterManagerAsyncClient]
@@ -17680,6 +17876,7 @@ def test_cluster_manager_grpc_asyncio_transport_channel():
17680
17876
 
17681
17877
  # Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
17682
17878
  # removed from grpc/grpc_asyncio transport constructor.
17879
+ @pytest.mark.filterwarnings("ignore::FutureWarning")
17683
17880
  @pytest.mark.parametrize(
17684
17881
  "transport_class",
17685
17882
  [