Skip to content

Commit 7282d6a

Browse files
author
Pedro Rodrigues
committed
add regions endpoints
1 parent e157e27 commit 7282d6a

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.utils import NamedList
1618

1719

1820
TEST_DIR = pathlib.Path(os.path.dirname(__file__))
@@ -1487,3 +1489,107 @@ def test_file_object(self):
14871489

14881490
# Cleanup
14891491
space.remove('obj_test_2.ipynb')
1492+
1493+
1494+
@pytest.mark.management
1495+
class TestRegions(unittest.TestCase):
1496+
"""Test cases for region management."""
1497+
1498+
manager = None
1499+
1500+
@classmethod
1501+
def setUpClass(cls):
1502+
"""Set up the test environment."""
1503+
cls.manager = s2.manage_regions()
1504+
1505+
@classmethod
1506+
def tearDownClass(cls):
1507+
"""Clean up the test environment."""
1508+
cls.manager = None
1509+
1510+
def test_list_regions(self):
1511+
"""Test listing all regions."""
1512+
regions = self.manager.list_regions()
1513+
1514+
# Verify we get a NamedList
1515+
assert isinstance(regions, NamedList)
1516+
1517+
# Verify we have at least one region
1518+
assert len(regions) > 0
1519+
1520+
# Verify region properties
1521+
region = regions[0]
1522+
assert isinstance(region, Region)
1523+
assert hasattr(region, 'id')
1524+
assert hasattr(region, 'name')
1525+
assert hasattr(region, 'provider')
1526+
1527+
# Verify provider values
1528+
providers = {x.provider for x in regions}
1529+
assert 'Azure' in providers or 'GCP' in providers or 'AWS' in providers
1530+
1531+
# Verify region can be accessed by name or ID
1532+
region_by_name = regions[region.name]
1533+
region_by_id = regions[region.id]
1534+
assert region_by_name == region_by_id
1535+
assert region_by_name.id == region.id
1536+
assert region_by_name.name == region.name
1537+
assert region_by_name.provider == region.provider
1538+
1539+
def test_list_shared_tier_regions(self):
1540+
"""Test listing shared tier regions."""
1541+
regions = self.manager.list_shared_tier_regions()
1542+
1543+
# Verify we get a NamedList
1544+
assert isinstance(regions, NamedList)
1545+
1546+
# Verify region properties if we have any shared tier regions
1547+
if regions:
1548+
region = regions[0]
1549+
assert isinstance(region, Region)
1550+
assert hasattr(region, 'id')
1551+
assert hasattr(region, 'name')
1552+
assert hasattr(region, 'provider')
1553+
1554+
# Verify provider values
1555+
providers = {x.provider for x in regions}
1556+
assert any(p in providers for p in ['Azure', 'GCP', 'AWS'])
1557+
1558+
# Verify region can be accessed by name or ID
1559+
region_by_name = regions[region.name]
1560+
region_by_id = regions[region.id]
1561+
assert region_by_name == region_by_id
1562+
assert region_by_name.id == region.id
1563+
assert region_by_name.name == region.name
1564+
assert region_by_name.provider == region.provider
1565+
1566+
def test_str_repr(self):
1567+
"""Test string representation of regions."""
1568+
regions = self.manager.list_regions()
1569+
if not regions:
1570+
self.skipTest('No regions available for testing')
1571+
1572+
region = regions[0]
1573+
1574+
# Test __str__
1575+
s = str(region)
1576+
assert region.id in s
1577+
assert region.name in s
1578+
assert region.provider in s
1579+
1580+
# Test __repr__
1581+
assert repr(region) == str(region)
1582+
1583+
def test_no_manager(self):
1584+
"""Test behavior when manager is not available."""
1585+
regions = self.manager.list_regions()
1586+
if not regions:
1587+
self.skipTest('No regions available for testing')
1588+
1589+
region = regions[0]
1590+
region._manager = None
1591+
1592+
# Verify from_dict class method
1593+
with self.assertRaises(s2.ManagementError) as cm:
1594+
Region.get_shared_tier_regions(None)
1595+
assert 'No workspace manager' in str(cm.exception)

0 commit comments

Comments
 (0)