Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 45d60a7

Browse files
committed
feat: expose universe_domain for tpc
1 parent 7a91bbf commit 45d60a7

4 files changed

Lines changed: 250 additions & 0 deletions

File tree

google/cloud/bigtable/data/_async/client.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,20 @@ def __init__(
211211
*args, **kwargs, channel=custom_channel
212212
),
213213
)
214+
if (
215+
credentials
216+
and credentials._universe_domain != self.universe_domain
217+
and self._emulator_host is None
218+
):
219+
# validate that the universe domain of the credentials matches the
220+
# universe domain configured in client_options
221+
raise ValueError(
222+
f"The configured universe domain ({self.universe_domain}) does "
223+
"not match the universe domain found in the credentials "
224+
f"({self._credentials.universe_domain}). If you haven't "
225+
"configured the universe domain explicitly, `googleapis.com` "
226+
"is the default."
227+
)
214228
self._is_closed = CrossSync.Event()
215229
self.transport = cast(TransportType, self._gapic_client.transport)
216230
# keep track of active instances to for warmup on channel refresh
@@ -235,6 +249,24 @@ def __init__(
235249
stacklevel=2,
236250
)
237251

252+
@property
253+
def universe_domain(self) -> str:
254+
"""Return the universe domain used by the client instance.
255+
256+
Returns:
257+
str: The universe domain used by the client instance.
258+
"""
259+
return self._gapic_client.universe_domain
260+
261+
@property
262+
def api_endpoint(self) -> str:
263+
"""Return the API endpoint used by the client instance.
264+
265+
Returns:
266+
str: The API endpoint used by the client instance.
267+
"""
268+
return self._gapic_client.api_endpoint
269+
238270
@staticmethod
239271
def _client_version() -> str:
240272
"""

google/cloud/bigtable/data/_sync_autogen/client.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ def __init__(
158158
*args, **kwargs, channel=custom_channel
159159
),
160160
)
161+
if (
162+
credentials
163+
and credentials._universe_domain != self.universe_domain
164+
and (self._emulator_host is None)
165+
):
166+
raise ValueError(
167+
f"The configured universe domain ({self.universe_domain}) does not match the universe domain found in the credentials ({self._credentials.universe_domain}). If you haven't configured the universe domain explicitly, `googleapis.com` is the default."
168+
)
161169
self._is_closed = CrossSync._Sync_Impl.Event()
162170
self.transport = cast(TransportType, self._gapic_client.transport)
163171
self._active_instances: Set[_WarmedInstanceKey] = set()
@@ -179,6 +187,22 @@ def __init__(
179187
stacklevel=2,
180188
)
181189

190+
@property
191+
def universe_domain(self) -> str:
192+
"""Return the universe domain used by the client instance.
193+
194+
Returns:
195+
str: The universe domain used by the client instance."""
196+
return self._gapic_client.universe_domain
197+
198+
@property
199+
def api_endpoint(self) -> str:
200+
"""Return the API endpoint used by the client instance.
201+
202+
Returns:
203+
str: The API endpoint used by the client instance."""
204+
return self._gapic_client.api_endpoint
205+
182206
@staticmethod
183207
def _client_version() -> str:
184208
"""Helper function to return the client version string for this client"""

tests/unit/data/_async/test_client.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from google.cloud.bigtable_v2.types import ReadRowsResponse
2727
from google.cloud.bigtable.data.read_rows_query import ReadRowsQuery
2828
from google.api_core import exceptions as core_exceptions
29+
from google.api_core import client_options
2930
from google.cloud.bigtable.data.exceptions import InvalidChunk
3031
from google.cloud.bigtable.data.exceptions import _MutateRowsIncomplete
3132
from google.cloud.bigtable.data.mutations import DeleteAllFromRow
@@ -1038,6 +1039,111 @@ def test_client_ctor_sync(self):
10381039
assert client.project == "project-id"
10391040
assert client._channel_refresh_task is None
10401041

1042+
@CrossSync.pytest
1043+
async def test_default_universe_domain(self):
1044+
"""
1045+
When not passed, universe_domain should default to googleapis.com
1046+
"""
1047+
async with self._make_client(project="project-id", credentials=None) as client:
1048+
assert client.universe_domain == "googleapis.com"
1049+
assert client.api_endpoint == "bigtable.googleapis.com"
1050+
1051+
@CrossSync.pytest
1052+
async def test_custom_universe_domain(self):
1053+
"""test with a customized universe domain value"""
1054+
universe_domain = "test-universe.test"
1055+
options = client_options.ClientOptions(universe_domain=universe_domain)
1056+
async with self._make_client(
1057+
project="project_id",
1058+
client_options=options,
1059+
use_emulator=False,
1060+
credentials=None,
1061+
) as client:
1062+
assert client.universe_domain == universe_domain
1063+
assert client.api_endpoint == f"bigtable.{universe_domain}"
1064+
1065+
@CrossSync.pytest
1066+
async def test_custom_universe_domain_w_emulator(self):
1067+
"""test with a customized universe domain value and emulator enabled"""
1068+
universe_domain = "test-universe.test"
1069+
options = client_options.ClientOptions(universe_domain=universe_domain)
1070+
async with self._make_client(
1071+
project="project_id",
1072+
client_options=options,
1073+
use_emulator=True,
1074+
credentials=None,
1075+
) as client:
1076+
assert client.universe_domain == universe_domain
1077+
assert client.api_endpoint == f"bigtable.{universe_domain}"
1078+
1079+
@CrossSync.pytest
1080+
async def test_configured_universe_domain_matches_GDU(self):
1081+
"""that configured universe domain succeeds with matched GDU credentials."""
1082+
universe_domain = "googleapis.com"
1083+
options = client_options.ClientOptions(universe_domain=universe_domain)
1084+
async with self._make_client(
1085+
project="project_id", client_options=options, credentials=None
1086+
) as client:
1087+
assert client.universe_domain == "googleapis.com"
1088+
assert client.api_endpoint == "bigtable.googleapis.com"
1089+
1090+
@CrossSync.pytest
1091+
async def test_credential_universe_domain_matches_GDU(self):
1092+
"""Test with credentials"""
1093+
creds = AnonymousCredentials()
1094+
creds._universe_domain = "googleapis.com"
1095+
async with self._make_client(project="project_id", credentials=creds) as client:
1096+
assert client.universe_domain == "googleapis.com"
1097+
assert client.api_endpoint == "bigtable.googleapis.com"
1098+
1099+
@CrossSync.pytest
1100+
async def test_anomynous_credential_universe_domain(self):
1101+
"""Anomynopus credentials should use default universe domain"""
1102+
creds = AnonymousCredentials()
1103+
async with self._make_client(project="project_id", credentials=creds) as client:
1104+
assert client.universe_domain == "googleapis.com"
1105+
assert client.api_endpoint == "bigtable.googleapis.com"
1106+
1107+
@CrossSync.pytest
1108+
async def test_configured_universe_domain_mismatched_credentials(self):
1109+
"""Test that configured universe domain errors with mismatched universe
1110+
domain credentials.
1111+
"""
1112+
universe_domain = "test-universe.test"
1113+
options = client_options.ClientOptions(universe_domain=universe_domain)
1114+
creds = AnonymousCredentials()
1115+
creds._universe_domain = "different-universe"
1116+
with pytest.raises(ValueError) as exc:
1117+
self._make_client(
1118+
project="project_id",
1119+
client_options=options,
1120+
use_emulator=False,
1121+
credentials=creds,
1122+
)
1123+
err_msg = (
1124+
f"The configured universe domain ({universe_domain}) does "
1125+
"not match the universe domain found in the credentials "
1126+
f"({creds.universe_domain}). If you haven't "
1127+
"configured the universe domain explicitly, `googleapis.com` "
1128+
"is the default."
1129+
)
1130+
assert exc.value.args[0] == err_msg
1131+
1132+
@CrossSync.pytest
1133+
async def test_configured_universe_domain_matches_credentials(self):
1134+
"""Test that configured universe domain succeeds with matching universe
1135+
domain credentials.
1136+
"""
1137+
universe_domain = "test-universe.test"
1138+
options = client_options.ClientOptions(universe_domain=universe_domain)
1139+
creds = AnonymousCredentials()
1140+
creds._universe_domain = universe_domain
1141+
async with self._make_client(
1142+
project="project_id", credentials=creds, client_options=options
1143+
) as client:
1144+
assert client.universe_domain == universe_domain
1145+
assert client.api_endpoint == f"bigtable.{universe_domain}"
1146+
10411147

10421148
@CrossSync.convert_class("TestTable", add_mapping_for_name="TestTable")
10431149
class TestTableAsync:

tests/unit/data/_sync_autogen/test_client.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from google.cloud.bigtable_v2.types import ReadRowsResponse
2626
from google.cloud.bigtable.data.read_rows_query import ReadRowsQuery
2727
from google.api_core import exceptions as core_exceptions
28+
from google.api_core import client_options
2829
from google.cloud.bigtable.data.exceptions import InvalidChunk
2930
from google.cloud.bigtable.data.exceptions import _MutateRowsIncomplete
3031
from google.cloud.bigtable.data.mutations import DeleteAllFromRow
@@ -836,6 +837,93 @@ def test_context_manager(self):
836837
close_mock.assert_called_once()
837838
true_close()
838839

840+
def test_default_universe_domain(self):
841+
"""When not passed, universe_domain should default to googleapis.com"""
842+
with self._make_client(project="project-id", credentials=None) as client:
843+
assert client.universe_domain == "googleapis.com"
844+
assert client.api_endpoint == "bigtable.googleapis.com"
845+
846+
def test_custom_universe_domain(self):
847+
"""test with a customized universe domain value"""
848+
universe_domain = "test-universe.test"
849+
options = client_options.ClientOptions(universe_domain=universe_domain)
850+
with self._make_client(
851+
project="project_id",
852+
client_options=options,
853+
use_emulator=False,
854+
credentials=None,
855+
) as client:
856+
assert client.universe_domain == universe_domain
857+
assert client.api_endpoint == f"bigtable.{universe_domain}"
858+
859+
def test_custom_universe_domain_w_emulator(self):
860+
"""test with a customized universe domain value and emulator enabled"""
861+
universe_domain = "test-universe.test"
862+
options = client_options.ClientOptions(universe_domain=universe_domain)
863+
with self._make_client(
864+
project="project_id",
865+
client_options=options,
866+
use_emulator=True,
867+
credentials=None,
868+
) as client:
869+
assert client.universe_domain == universe_domain
870+
assert client.api_endpoint == f"bigtable.{universe_domain}"
871+
872+
def test_configured_universe_domain_matches_GDU(self):
873+
"""that configured universe domain succeeds with matched GDU credentials."""
874+
universe_domain = "googleapis.com"
875+
options = client_options.ClientOptions(universe_domain=universe_domain)
876+
with self._make_client(
877+
project="project_id", client_options=options, credentials=None
878+
) as client:
879+
assert client.universe_domain == "googleapis.com"
880+
assert client.api_endpoint == "bigtable.googleapis.com"
881+
882+
def test_credential_universe_domain_matches_GDU(self):
883+
"""Test with credentials"""
884+
creds = AnonymousCredentials()
885+
creds._universe_domain = "googleapis.com"
886+
with self._make_client(project="project_id", credentials=creds) as client:
887+
assert client.universe_domain == "googleapis.com"
888+
assert client.api_endpoint == "bigtable.googleapis.com"
889+
890+
def test_anomynous_credential_universe_domain(self):
891+
"""Anomynopus credentials should use default universe domain"""
892+
creds = AnonymousCredentials()
893+
with self._make_client(project="project_id", credentials=creds) as client:
894+
assert client.universe_domain == "googleapis.com"
895+
assert client.api_endpoint == "bigtable.googleapis.com"
896+
897+
def test_configured_universe_domain_mismatched_credentials(self):
898+
"""Test that configured universe domain errors with mismatched universe
899+
domain credentials."""
900+
universe_domain = "test-universe.test"
901+
options = client_options.ClientOptions(universe_domain=universe_domain)
902+
creds = AnonymousCredentials()
903+
creds._universe_domain = "different-universe"
904+
with pytest.raises(ValueError) as exc:
905+
self._make_client(
906+
project="project_id",
907+
client_options=options,
908+
use_emulator=False,
909+
credentials=creds,
910+
)
911+
err_msg = f"The configured universe domain ({universe_domain}) does not match the universe domain found in the credentials ({creds.universe_domain}). If you haven't configured the universe domain explicitly, `googleapis.com` is the default."
912+
assert exc.value.args[0] == err_msg
913+
914+
def test_configured_universe_domain_matches_credentials(self):
915+
"""Test that configured universe domain succeeds with matching universe
916+
domain credentials."""
917+
universe_domain = "test-universe.test"
918+
options = client_options.ClientOptions(universe_domain=universe_domain)
919+
creds = AnonymousCredentials()
920+
creds._universe_domain = universe_domain
921+
with self._make_client(
922+
project="project_id", credentials=creds, client_options=options
923+
) as client:
924+
assert client.universe_domain == universe_domain
925+
assert client.api_endpoint == f"bigtable.{universe_domain}"
926+
839927

840928
@CrossSync._Sync_Impl.add_mapping_decorator("TestTable")
841929
class TestTable:

0 commit comments

Comments
 (0)