Skip to content

Commit 2ab764d

Browse files
authored
add regions endpoints (#71)
1 parent 93a0018 commit 2ab764d

File tree

2 files changed

+198
-0
lines changed

2 files changed

+198
-0
lines changed

singlestoredb/management/region.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Optional
55

66
from .manager import Manager
7+
from .utils import NamedList
78
from .utils import vars_to_str
89

910

@@ -65,3 +66,94 @@ def from_dict(cls, obj: Dict[str, str], manager: Manager) -> 'Region':
6566
)
6667
out._manager = manager
6768
return out
69+
70+
71+
class RegionManager(Manager):
72+
"""
73+
SingleStoreDB region manager.
74+
75+
This class should be instantiated using :func:`singlestoredb.manage_regions`.
76+
77+
Parameters
78+
----------
79+
access_token : str, optional
80+
The API key or other access token for the workspace management API
81+
version : str, optional
82+
Version of the API to use
83+
base_url : str, optional
84+
Base URL of the workspace management API
85+
86+
See Also
87+
--------
88+
:func:`singlestoredb.manage_regions`
89+
"""
90+
91+
#: Object type
92+
obj_type = 'region'
93+
94+
def list_regions(self) -> NamedList[Region]:
95+
"""
96+
List all available regions.
97+
98+
Returns
99+
-------
100+
NamedList[Region]
101+
List of available regions
102+
103+
Raises
104+
------
105+
ManagementError
106+
If there is an error getting the regions
107+
"""
108+
res = self._get('regions')
109+
return NamedList(
110+
[Region.from_dict(item, self) for item in res.json()],
111+
)
112+
113+
def list_shared_tier_regions(self) -> NamedList[Region]:
114+
"""
115+
List regions that support shared tier workspaces.
116+
117+
Returns
118+
-------
119+
NamedList[Region]
120+
List of regions that support shared tier workspaces
121+
122+
Raises
123+
------
124+
ManagementError
125+
If there is an error getting the regions
126+
"""
127+
res = self._get('regions/sharedtier')
128+
return NamedList(
129+
[Region.from_dict(item, self) for item in res.json()],
130+
)
131+
132+
133+
def manage_regions(
134+
access_token: Optional[str] = None,
135+
version: Optional[str] = None,
136+
base_url: Optional[str] = None,
137+
) -> RegionManager:
138+
"""
139+
Retrieve a SingleStoreDB region manager.
140+
141+
Parameters
142+
----------
143+
access_token : str, optional
144+
The API key or other access token for the workspace management API
145+
version : str, optional
146+
Version of the API to use
147+
base_url : str, optional
148+
Base URL of the workspace management API
149+
150+
Returns
151+
-------
152+
:class:`RegionManager`
153+
154+
"""
155+
return RegionManager(
156+
access_token=access_token,
157+
version=version,
158+
base_url=base_url,
159+
)

singlestoredb/tests/test_management.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import singlestoredb as s2
1414
from singlestoredb.management.job import Status
1515
from singlestoredb.management.job import TargetType
16+
from singlestoredb.management.region import Region
17+
from singlestoredb.management.utils import NamedList
1618

1719

1820
TEST_DIR = pathlib.Path(os.path.dirname(__file__))
@@ -1372,3 +1374,107 @@ def test_file_object(self):
13721374

13731375
# Cleanup
13741376
space.remove('obj_test_2.ipynb')
1377+
1378+
1379+
@pytest.mark.management
1380+
class TestRegions(unittest.TestCase):
1381+
"""Test cases for region management."""
1382+
1383+
manager = None
1384+
1385+
@classmethod
1386+
def setUpClass(cls):
1387+
"""Set up the test environment."""
1388+
cls.manager = s2.manage_regions()
1389+
1390+
@classmethod
1391+
def tearDownClass(cls):
1392+
"""Clean up the test environment."""
1393+
cls.manager = None
1394+
1395+
def test_list_regions(self):
1396+
"""Test listing all regions."""
1397+
regions = self.manager.list_regions()
1398+
1399+
# Verify we get a NamedList
1400+
assert isinstance(regions, NamedList)
1401+
1402+
# Verify we have at least one region
1403+
assert len(regions) > 0
1404+
1405+
# Verify region properties
1406+
region = regions[0]
1407+
assert isinstance(region, Region)
1408+
assert hasattr(region, 'id')
1409+
assert hasattr(region, 'name')
1410+
assert hasattr(region, 'provider')
1411+
1412+
# Verify provider values
1413+
providers = {x.provider for x in regions}
1414+
assert 'Azure' in providers or 'GCP' in providers or 'AWS' in providers
1415+
1416+
# Verify region can be accessed by name or ID
1417+
region_by_name = regions[region.name]
1418+
region_by_id = regions[region.id]
1419+
assert region_by_name == region_by_id
1420+
assert region_by_name.id == region.id
1421+
assert region_by_name.name == region.name
1422+
assert region_by_name.provider == region.provider
1423+
1424+
def test_list_shared_tier_regions(self):
1425+
"""Test listing shared tier regions."""
1426+
regions = self.manager.list_shared_tier_regions()
1427+
1428+
# Verify we get a NamedList
1429+
assert isinstance(regions, NamedList)
1430+
1431+
# Verify region properties if we have any shared tier regions
1432+
if regions:
1433+
region = regions[0]
1434+
assert isinstance(region, Region)
1435+
assert hasattr(region, 'id')
1436+
assert hasattr(region, 'name')
1437+
assert hasattr(region, 'provider')
1438+
1439+
# Verify provider values
1440+
providers = {x.provider for x in regions}
1441+
assert any(p in providers for p in ['Azure', 'GCP', 'AWS'])
1442+
1443+
# Verify region can be accessed by name or ID
1444+
region_by_name = regions[region.name]
1445+
region_by_id = regions[region.id]
1446+
assert region_by_name == region_by_id
1447+
assert region_by_name.id == region.id
1448+
assert region_by_name.name == region.name
1449+
assert region_by_name.provider == region.provider
1450+
1451+
def test_str_repr(self):
1452+
"""Test string representation of regions."""
1453+
regions = self.manager.list_regions()
1454+
if not regions:
1455+
self.skipTest('No regions available for testing')
1456+
1457+
region = regions[0]
1458+
1459+
# Test __str__
1460+
s = str(region)
1461+
assert region.id in s
1462+
assert region.name in s
1463+
assert region.provider in s
1464+
1465+
# Test __repr__
1466+
assert repr(region) == str(region)
1467+
1468+
def test_no_manager(self):
1469+
"""Test behavior when manager is not available."""
1470+
regions = self.manager.list_regions()
1471+
if not regions:
1472+
self.skipTest('No regions available for testing')
1473+
1474+
region = regions[0]
1475+
region._manager = None
1476+
1477+
# Verify from_dict class method
1478+
with self.assertRaises(s2.ManagementError) as cm:
1479+
Region.get_shared_tier_regions(None)
1480+
assert 'No workspace manager' in str(cm.exception)

0 commit comments

Comments
 (0)