From 911c217c798b69e00c7c25ed5ee0eae3f35884e2 Mon Sep 17 00:00:00 2001 From: Nidhi Nandwani Date: Mon, 28 Sep 2026 06:04:55 +0000 Subject: [PATCH 1/3] feat(storage): support DirectPath over Interconnect in gRPC client Add support for DirectPath over Cloud Interconnect in GCS gRPC client (GrpcClient and AsyncGrpcClient). - Add attempt_direct_path_xds_over_interconnect parameter and GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT env var override. - Rewrite default endpoint to storage-direct.googleapis.com when enabled. - Forward credentials, quota_project_id, and attempt_direct_path_xds_over_interconnect to GAPIC transport. - Unit tests for sync and async gRPC client. [Generated-by: AI] --- .../storage/asyncio/async_grpc_client.py | 53 +++++-- .../google/cloud/storage/grpc_client.py | 78 +++++++++- .../unit/asyncio/test_async_grpc_client.py | 84 +++++++++++ .../tests/unit/test_grpc_client.py | 134 ++++++++++++++++++ 4 files changed, 338 insertions(+), 11 deletions(-) diff --git a/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py b/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py index 18ee348401c7..e210fb5fc195 100644 --- a/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py +++ b/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py @@ -22,8 +22,11 @@ DEFAULT_CLIENT_INFO, ) from google.cloud.storage import __version__ - -_DEFAULT_HOST = "storage.googleapis.com" +from google.cloud.storage.grpc_client import ( + _DEFAULT_HOST, + _resolve_direct_path_interconnect, + _rewrite_host_for_interconnect, +) def _validate_metadata(metadata): @@ -63,6 +66,13 @@ class AsyncGrpcClient: :param attempt_direct_path: (Optional) Whether to attempt to use DirectPath for gRPC connections. Defaults to ``True``. + + :type attempt_direct_path_xds_over_interconnect: bool + :param attempt_direct_path_xds_over_interconnect: + (Optional) Whether to attempt DirectPath over Cloud Interconnect + using xDS and standard TLS. Can also be overridden via the + ``GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT`` environment + variable (``"true"`` or ``"false"``). Defaults to ``False``. """ def __init__( @@ -72,6 +82,7 @@ def __init__( client_options=None, *, attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=False, ): if isinstance(credentials, auth_credentials.AnonymousCredentials): if client_options is None or client_options.api_endpoint is None: @@ -92,11 +103,16 @@ def __init__( if agent_version not in client_info.user_agent: client_info.user_agent += f" {agent_version} " + use_dp_interconnect = _resolve_direct_path_interconnect( + attempt_direct_path_xds_over_interconnect + ) + self._grpc_client = self._create_async_grpc_client( credentials=credentials, client_info=client_info, client_options=client_options, attempt_direct_path=attempt_direct_path, + attempt_direct_path_xds_over_interconnect=use_dp_interconnect, ) def _create_anonymous_client(self, client_options, credentials): @@ -120,6 +136,7 @@ def _create_async_grpc_client( client_info=None, client_options=None, attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=False, ): transport_cls = storage_v2.StorageAsyncClient.get_transport_class( "grpc_asyncio" @@ -129,17 +146,33 @@ def _create_async_grpc_client( host = _DEFAULT_HOST quota_project_id = None - if client_options: + if isinstance(client_options, dict): + host = client_options.get("api_endpoint") or _DEFAULT_HOST + quota_project_id = client_options.get("quota_project_id") + elif client_options: host = getattr(client_options, "api_endpoint", None) or _DEFAULT_HOST quota_project_id = getattr(client_options, "quota_project_id", None) - channel = transport_cls.create_channel( - host=host, - quota_project_id=quota_project_id, - attempt_direct_path=attempt_direct_path, - credentials=credentials, - options=(("grpc.primary_user_agent", primary_user_agent),), - ) + if attempt_direct_path_xds_over_interconnect: + host = _rewrite_host_for_interconnect(host) + channel = transport_cls.create_channel( + host=host, + quota_project_id=quota_project_id, + attempt_direct_path=bool( + attempt_direct_path or attempt_direct_path_xds_over_interconnect + ), + attempt_direct_path_xds_over_interconnect=True, + credentials=credentials, + options=(("grpc.primary_user_agent", primary_user_agent),), + ) + else: + channel = transport_cls.create_channel( + host=host, + quota_project_id=quota_project_id, + attempt_direct_path=attempt_direct_path, + credentials=credentials, + options=(("grpc.primary_user_agent", primary_user_agent),), + ) transport = transport_cls(channel=channel) return storage_v2.StorageAsyncClient( diff --git a/packages/google-cloud-storage/google/cloud/storage/grpc_client.py b/packages/google-cloud-storage/google/cloud/storage/grpc_client.py index 4fdb23e702b6..01415c9640f4 100644 --- a/packages/google-cloud-storage/google/cloud/storage/grpc_client.py +++ b/packages/google-cloud-storage/google/cloud/storage/grpc_client.py @@ -14,11 +14,49 @@ """A client for interacting with Google Cloud Storage using the gRPC API.""" +import os + from google.cloud.client import ClientWithProject from google.cloud import _storage_v2 as storage_v2 _marker = object() +_DEFAULT_HOST = "storage.googleapis.com" +_DEFAULT_HOST_DIRECT_PATH = "storage-direct.googleapis.com" +_DIRECT_PATH_INTERCONNECT_ENV = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT" + + +def _resolve_direct_path_interconnect(option_value: bool) -> bool: + """Resolves DirectPath over Interconnect flag from env var or parameter.""" + env_val = os.environ.get(_DIRECT_PATH_INTERCONNECT_ENV) + if env_val is not None: + env_val_clean = env_val.strip().lower() + if env_val_clean == "true": + return True + elif env_val_clean == "false": + return False + else: + raise ValueError( + f"Invalid value for {_DIRECT_PATH_INTERCONNECT_ENV}: {env_val}" + ) + return bool(option_value) + + +def _rewrite_host_for_interconnect( + host: str, + old_host: str = _DEFAULT_HOST, + new_host: str = _DEFAULT_HOST_DIRECT_PATH, +) -> str: + """Rewrites the default GCS endpoint to the DirectPath over Interconnect host.""" + if not host: + return new_host + for prefix in ("", "https://", "http://", "dns:///"): + candidate = f"{prefix}{old_host}" + if host.startswith(candidate): + rest = host[len(candidate) :] + if not rest or rest[0] in (":", "/", "?", "#"): + return f"{prefix}{new_host}{rest}" + return host class GrpcClient(ClientWithProject): @@ -58,6 +96,13 @@ class GrpcClient(ClientWithProject): This provides a direct, unproxied connection to GCS for lower latency and higher throughput, and is highly recommended when running on Google Cloud infrastructure. Defaults to ``True``. + + :type attempt_direct_path_xds_over_interconnect: bool + :param attempt_direct_path_xds_over_interconnect: + (Optional) Whether to attempt DirectPath over Cloud Interconnect + using xDS and standard TLS. Can also be overridden via the + ``GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT`` environment + variable (``"true"`` or ``"false"``). Defaults to ``False``. """ def __init__( @@ -69,6 +114,7 @@ def __init__( *, api_key=None, attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=False, ): super(GrpcClient, self).__init__(project=project, credentials=credentials) @@ -80,11 +126,16 @@ def __init__( elif api_key: client_options.api_key = api_key + use_dp_interconnect = _resolve_direct_path_interconnect( + attempt_direct_path_xds_over_interconnect + ) + self._grpc_client = self._create_gapic_client( credentials=credentials, client_info=client_info, client_options=client_options, attempt_direct_path=attempt_direct_path, + attempt_direct_path_xds_over_interconnect=use_dp_interconnect, ) def _create_gapic_client( @@ -93,11 +144,36 @@ def _create_gapic_client( client_info=None, client_options=None, attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=False, ): """Creates and configures the low-level GAPIC `storage_v2` client.""" transport_cls = storage_v2.StorageClient.get_transport_class("grpc") - channel = transport_cls.create_channel(attempt_direct_path=attempt_direct_path) + if attempt_direct_path_xds_over_interconnect: + host = _DEFAULT_HOST + quota_project_id = None + if isinstance(client_options, dict): + host = client_options.get("api_endpoint") or _DEFAULT_HOST + quota_project_id = client_options.get("quota_project_id") + elif client_options is not None: + host = getattr(client_options, "api_endpoint", None) or _DEFAULT_HOST + quota_project_id = getattr(client_options, "quota_project_id", None) + host = _rewrite_host_for_interconnect(host) + channel_kwargs = { + "host": host, + "credentials": credentials, + "attempt_direct_path": bool( + attempt_direct_path or attempt_direct_path_xds_over_interconnect + ), + "attempt_direct_path_xds_over_interconnect": True, + } + if quota_project_id is not None: + channel_kwargs["quota_project_id"] = quota_project_id + channel = transport_cls.create_channel(**channel_kwargs) + else: + channel = transport_cls.create_channel( + attempt_direct_path=attempt_direct_path + ) transport = transport_cls(credentials=credentials, channel=channel) diff --git a/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py b/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py index 24168dc137d4..eefa33fc1ccd 100644 --- a/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py +++ b/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py @@ -431,3 +431,87 @@ async def test_get_object_invalid_metadata(self, invalid_metadata, expected_exc) client = async_grpc_client.AsyncGrpcClient(credentials=_make_credentials()) with pytest.raises(expected_exc): await client.get_object("bucket", "object", metadata=invalid_metadata) + + @mock.patch("google.cloud._storage_v2.StorageAsyncClient") + def test_async_grpc_client_attempt_direct_path_xds_over_interconnect( + self, mock_async_storage_client + ): + mock_transport_cls = mock.MagicMock() + mock_async_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + + async_grpc_client.AsyncGrpcClient( + credentials=mock_creds, + attempt_direct_path_xds_over_interconnect=True, + ) + + kwargs = mock_async_storage_client.call_args.kwargs + client_info = kwargs["client_info"] + primary_user_agent = client_info.to_user_agent() + expected_options = (("grpc.primary_user_agent", primary_user_agent),) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage-direct.googleapis.com", + quota_project_id=None, + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + credentials=mock_creds, + options=expected_options, + ) + + @mock.patch("google.cloud._storage_v2.StorageAsyncClient") + def test_async_grpc_client_interconnect_env_override( + self, mock_async_storage_client + ): + mock_transport_cls = mock.MagicMock() + mock_async_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": "true"}, + ): + async_grpc_client.AsyncGrpcClient( + credentials=mock_creds, + attempt_direct_path=False, + attempt_direct_path_xds_over_interconnect=False, + ) + + kwargs = mock_async_storage_client.call_args.kwargs + client_info = kwargs["client_info"] + primary_user_agent = client_info.to_user_agent() + expected_options = (("grpc.primary_user_agent", primary_user_agent),) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage-direct.googleapis.com", + quota_project_id=None, + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + credentials=mock_creds, + options=expected_options, + ) + + mock_transport_cls.create_channel.reset_mock() + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": " FALSE "}, + ): + async_grpc_client.AsyncGrpcClient( + credentials=mock_creds, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage.googleapis.com", + quota_project_id=None, + attempt_direct_path=True, + credentials=mock_creds, + options=expected_options, + ) + + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": "invalid"}, + ): + with pytest.raises(ValueError): + async_grpc_client.AsyncGrpcClient(credentials=mock_creds) diff --git a/packages/google-cloud-storage/tests/unit/test_grpc_client.py b/packages/google-cloud-storage/tests/unit/test_grpc_client.py index 9baa15c0ad5f..54b82a77d61b 100644 --- a/packages/google-cloud-storage/tests/unit/test_grpc_client.py +++ b/packages/google-cloud-storage/tests/unit/test_grpc_client.py @@ -197,3 +197,137 @@ def test_constructor_with_api_key_and_dict_options( client_info=None, client_options=expected_options, ) + + @mock.patch("google.cloud.storage.grpc_client.ClientWithProject") + @mock.patch("google.cloud._storage_v2.StorageClient") + def test_grpc_client_attempt_direct_path_xds_over_interconnect( + self, mock_storage_client, mock_base_client + ): + mock_transport_cls = mock.MagicMock() + mock_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + mock_base_client.return_value._credentials = mock_creds + + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage-direct.googleapis.com", + credentials=mock_creds, + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + ) + + @mock.patch("google.cloud.storage.grpc_client.ClientWithProject") + @mock.patch("google.cloud._storage_v2.StorageClient") + def test_grpc_client_attempt_direct_path_xds_over_interconnect_with_quota_project( + self, mock_storage_client, mock_base_client + ): + mock_transport_cls = mock.MagicMock() + mock_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + mock_base_client.return_value._credentials = mock_creds + + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + client_options={"quota_project_id": "my-quota-proj"}, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage-direct.googleapis.com", + credentials=mock_creds, + quota_project_id="my-quota-proj", + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + ) + + @mock.patch("google.cloud.storage.grpc_client.ClientWithProject") + @mock.patch("google.cloud._storage_v2.StorageClient") + def test_grpc_client_attempt_direct_path_xds_over_interconnect_env_override( + self, mock_storage_client, mock_base_client + ): + mock_transport_cls = mock.MagicMock() + mock_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + mock_base_client.return_value._credentials = mock_creds + + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": " TRUE "}, + ): + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + attempt_direct_path_xds_over_interconnect=False, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + host="storage-direct.googleapis.com", + credentials=mock_creds, + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.reset_mock() + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": " FALSE "}, + ): + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + attempt_direct_path=True + ) + + with mock.patch.dict( + "os.environ", + {"GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT": "invalid"}, + ): + with self.assertRaises(ValueError): + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + ) + + def test_rewrite_host_for_interconnect_delimiters(self): + cases = [ + ("storage.googleapis.com", "storage-direct.googleapis.com"), + ("storage.googleapis.com:443", "storage-direct.googleapis.com:443"), + ("storage.googleapis.com/path", "storage-direct.googleapis.com/path"), + ( + "storage.googleapis.com?query=val", + "storage-direct.googleapis.com?query=val", + ), + ("storage.googleapis.com#section", "storage-direct.googleapis.com#section"), + ("https://storage.googleapis.com", "https://storage-direct.googleapis.com"), + ( + "https://storage.googleapis.com:443?q=1", + "https://storage-direct.googleapis.com:443?q=1", + ), + ( + "dns:///storage.googleapis.com:443", + "dns:///storage-direct.googleapis.com:443", + ), + ( + "storage.googleapis.com.evil.com", + "storage.googleapis.com.evil.com", + ), + ( + "google-c2p:///storage-direct.googleapis.com", + "google-c2p:///storage-direct.googleapis.com", + ), + ] + for original_host, expected_host in cases: + self.assertEqual( + grpc_client._rewrite_host_for_interconnect(original_host), + expected_host, + ) From 316be00ba589cbe4d4a038e1b4cb9c055868f287 Mon Sep 17 00:00:00 2001 From: Nidhi Nandwani Date: Mon, 28 Sep 2026 06:55:12 +0000 Subject: [PATCH 2/3] fix(storage): simplify attempt_direct_path boolean expression in gRPC client [Generated-by: AI] --- .../google/cloud/storage/asyncio/async_grpc_client.py | 4 +--- .../google-cloud-storage/google/cloud/storage/grpc_client.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py b/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py index e210fb5fc195..3b1487c8c7bb 100644 --- a/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py +++ b/packages/google-cloud-storage/google/cloud/storage/asyncio/async_grpc_client.py @@ -158,9 +158,7 @@ def _create_async_grpc_client( channel = transport_cls.create_channel( host=host, quota_project_id=quota_project_id, - attempt_direct_path=bool( - attempt_direct_path or attempt_direct_path_xds_over_interconnect - ), + attempt_direct_path=True, attempt_direct_path_xds_over_interconnect=True, credentials=credentials, options=(("grpc.primary_user_agent", primary_user_agent),), diff --git a/packages/google-cloud-storage/google/cloud/storage/grpc_client.py b/packages/google-cloud-storage/google/cloud/storage/grpc_client.py index 01415c9640f4..b3d8b261e77f 100644 --- a/packages/google-cloud-storage/google/cloud/storage/grpc_client.py +++ b/packages/google-cloud-storage/google/cloud/storage/grpc_client.py @@ -162,9 +162,7 @@ def _create_gapic_client( channel_kwargs = { "host": host, "credentials": credentials, - "attempt_direct_path": bool( - attempt_direct_path or attempt_direct_path_xds_over_interconnect - ), + "attempt_direct_path": True, "attempt_direct_path_xds_over_interconnect": True, } if quota_project_id is not None: From 63d50c2883421cfc5815e1c351acd60bdceb10cb Mon Sep 17 00:00:00 2001 From: Nidhi Nandwani Date: Mon, 12 Oct 2026 11:18:36 +0000 Subject: [PATCH 3/3] test(storage): add unit test for client options with direct path over interconnect Verify custom api_endpoint in ClientOptions is preserved when attempt_direct_path_xds_over_interconnect=True. [Generated-by: AI] --- .../unit/asyncio/test_async_grpc_client.py | 32 +++++++++++++++++++ .../tests/unit/test_grpc_client.py | 29 +++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py b/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py index eefa33fc1ccd..9dffa6b36c86 100644 --- a/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py +++ b/packages/google-cloud-storage/tests/unit/asyncio/test_async_grpc_client.py @@ -459,6 +459,38 @@ def test_async_grpc_client_attempt_direct_path_xds_over_interconnect( options=expected_options, ) + @mock.patch("google.cloud._storage_v2.StorageAsyncClient") + def test_create_gapic_client_custom_client_options_with_interconnect( + self, mock_async_storage_client + ): + mock_transport_cls = mock.MagicMock() + mock_async_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + + client_options_obj = client_options.ClientOptions( + api_endpoint="custom.endpoint.com", + quota_project_id="my-quota-proj", + ) + async_grpc_client.AsyncGrpcClient( + credentials=mock_creds, + client_options=client_options_obj, + attempt_direct_path_xds_over_interconnect=True, + ) + + kwargs = mock_async_storage_client.call_args.kwargs + client_info = kwargs["client_info"] + primary_user_agent = client_info.to_user_agent() + expected_options = (("grpc.primary_user_agent", primary_user_agent),) + + mock_transport_cls.create_channel.assert_called_once_with( + host="custom.endpoint.com", + quota_project_id="my-quota-proj", + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + credentials=mock_creds, + options=expected_options, + ) + @mock.patch("google.cloud._storage_v2.StorageAsyncClient") def test_async_grpc_client_interconnect_env_override( self, mock_async_storage_client diff --git a/packages/google-cloud-storage/tests/unit/test_grpc_client.py b/packages/google-cloud-storage/tests/unit/test_grpc_client.py index 54b82a77d61b..73a8e5b273e4 100644 --- a/packages/google-cloud-storage/tests/unit/test_grpc_client.py +++ b/packages/google-cloud-storage/tests/unit/test_grpc_client.py @@ -246,6 +246,35 @@ def test_grpc_client_attempt_direct_path_xds_over_interconnect_with_quota_projec attempt_direct_path_xds_over_interconnect=True, ) + @mock.patch("google.cloud.storage.grpc_client.ClientWithProject") + @mock.patch("google.cloud._storage_v2.StorageClient") + def test_create_gapic_client_custom_client_options_with_interconnect( + self, mock_storage_client, mock_base_client + ): + mock_transport_cls = mock.MagicMock() + mock_storage_client.get_transport_class.return_value = mock_transport_cls + mock_creds = _make_credentials() + mock_base_client.return_value._credentials = mock_creds + + client_options_obj = client_options_lib.ClientOptions( + api_endpoint="custom.endpoint.com", + quota_project_id="my-quota-proj", + ) + grpc_client.GrpcClient( + project="test-project", + credentials=mock_creds, + client_options=client_options_obj, + attempt_direct_path_xds_over_interconnect=True, + ) + + mock_transport_cls.create_channel.assert_called_once_with( + host="custom.endpoint.com", + credentials=mock_creds, + quota_project_id="my-quota-proj", + attempt_direct_path=True, + attempt_direct_path_xds_over_interconnect=True, + ) + @mock.patch("google.cloud.storage.grpc_client.ClientWithProject") @mock.patch("google.cloud._storage_v2.StorageClient") def test_grpc_client_attempt_direct_path_xds_over_interconnect_env_override(