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.
- {google_cloud_container-2.61.0/google_cloud_container.egg-info → google_cloud_container-2.62.0}/PKG-INFO +1 -1
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/gapic_version.py +1 -1
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/__init__.py +104 -0
- {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
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/client.py +32 -14
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/__init__.py +104 -0
- {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
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/client.py +32 -14
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0/google_cloud_container.egg-info}/PKG-INFO +1 -1
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1/test_cluster_manager.py +226 -29
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1beta1/test_cluster_manager.py +226 -29
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/LICENSE +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/MANIFEST.in +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/README.rst +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/py.typed +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/gapic_metadata.json +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/py.typed +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/async_client.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/pagers.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/base.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/grpc.py +0 -0
- {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
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/services/cluster_manager/transports/rest.py +0 -0
- {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
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/types/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/types/cluster_service.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/gapic_metadata.json +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/py.typed +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/async_client.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/pagers.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/base.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/services/cluster_manager/transports/grpc.py +0 -0
- {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
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/types/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1beta1/types/cluster_service.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/SOURCES.txt +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/dependency_links.txt +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/not-zip-safe +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/requires.txt +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google_cloud_container.egg-info/top_level.txt +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/setup.cfg +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/setup.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/system/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/system/smoke_test.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1/__init__.py +0 -0
- {google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/container_v1beta1/__init__.py +0 -0
|
@@ -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",
|
|
@@ -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 =
|
|
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
|
|
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 =
|
|
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
|
|
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",
|
|
@@ -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 =
|
|
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
|
|
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 =
|
|
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
|
|
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):
|
|
@@ -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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
[
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/__init__.py
RENAMED
|
File without changes
|
{google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
{google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/google/cloud/container_v1/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{google_cloud_container-2.61.0 → google_cloud_container-2.62.0}/tests/unit/gapic/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|