Skip to content

Commit 9a9fa85

Browse files
author
Ilyas Gasanov
committed
[DOP-24139] Add namespace create/delete methods
1 parent db5181f commit 9a9fa85

File tree

5 files changed

+59
-13
lines changed

5 files changed

+59
-13
lines changed

conftest.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
KeyValueIntHWM,
1616
)
1717
from horizon.client.auth import LoginPassword
18-
from horizon.commons.schemas.v1 import NamespaceCreateRequestV1
1918
from packaging.version import Version
2019

2120
from horizon_hwm_store import HorizonHWMStore
@@ -149,6 +148,11 @@ def file_with_mtime(mtime: datetime) -> Path:
149148

150149

151150
@pytest.fixture(params=HWMS_WITH_VALUE)
151+
def hwm_new_values(request):
152+
return request.param
153+
154+
155+
@pytest.fixture(params=[HWMS_WITH_VALUE[0]])
152156
def hwm_new_value(request):
153157
return request.param
154158

@@ -164,16 +168,10 @@ def hwm_store():
164168

165169
@pytest.fixture(scope="module")
166170
def ensure_namespace():
167-
from requests.exceptions import HTTPError
168171

169172
store = HorizonHWMStore(
170173
api_url=HORIZON_URL,
171174
auth=LoginPassword(login=HORIZON_USER, password=HORIZON_PASSWORD),
172175
namespace=HORIZON_NAMESPACE,
173176
)
174-
175-
try:
176-
store.client.create_namespace(NamespaceCreateRequestV1(name=HORIZON_NAMESPACE)) # noqa: WPS437
177-
except HTTPError:
178-
# exception: 409 Client Error: Conflict for url: http://horizon/v1/namespaces/ - namespace already exists
179-
pass
177+
store.force_create_namespace(HORIZON_NAMESPACE)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``force_create_namespace`` method

docs/horizon-hwm-store.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ Horizon HWM Store
66
.. currentmodule:: horizon_hwm_store.horizon_hwm_store
77

88
.. autoclass:: HorizonHWMStore
9-
:members: get_hwm, set_hwm
9+
:members: get_hwm, set_hwm, force_create_namespace

horizon_hwm_store/horizon_hwm_store.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
from etl_entities.hwm_store import BaseHWMStore, register_hwm_store_class
99
from horizon.client.auth import LoginPassword
1010
from horizon.client.sync import HorizonClientSync, RetryConfig, TimeoutConfig
11+
from horizon.commons.exceptions import EntityAlreadyExistsError
1112
from horizon.commons.schemas.v1 import (
1213
HWMCreateRequestV1,
1314
HWMPaginateQueryV1,
1415
HWMUpdateRequestV1,
16+
NamespaceCreateRequestV1,
1517
NamespacePaginateQueryV1,
18+
NamespaceResponseV1,
1619
)
1720

1821
try:
@@ -33,7 +36,7 @@ class HorizonHWMStore(BaseHWMStore):
3336
3437
.. warning::
3538
36-
It is required to create namespace in Horizon BEFORE using this class.
39+
It is required to create a namespace BEFORE working with HWMs.
3740
3841
Parameters
3942
----------
@@ -98,7 +101,7 @@ class HorizonHWMStore(BaseHWMStore):
98101
namespace="namespace",
99102
retry=RetryConfig(total=5),
100103
timeout=TimeoutConfig(request_timeout=10),
101-
):
104+
).force_create_namespace("namespace"):
102105
with IncrementalStrategy():
103106
df = reader.run()
104107
writer.run(df)
@@ -213,6 +216,30 @@ def check(self) -> HorizonHWMStore:
213216
self._get_namespace_id()
214217
return self
215218

219+
def force_create_namespace(self, name: str) -> HorizonHWMStore:
220+
"""
221+
Create a namespace.
222+
223+
Parameters
224+
----------
225+
name : str
226+
The name of the namespace to create.
227+
228+
Examples
229+
--------
230+
.. code:: python
231+
232+
hwm_store.force_create_namespace(namespace_unique_name)
233+
"""
234+
namespace = self._get_namespace(name)
235+
if namespace is None:
236+
try:
237+
namespace = self.client.create_namespace(NamespaceCreateRequestV1(name=name))
238+
self._namespace_id = namespace.id # noqa: WPS601
239+
except EntityAlreadyExistsError:
240+
...
241+
return self
242+
216243
# LoginPassword, RetryConfig and TimeoutConfig can be inherited from Pydantic v2 BaseModel
217244
# which is detected by Pydantic v1 as arbitrary type. So we need to parse them manually.
218245
@validator("auth", pre=True)
@@ -233,6 +260,10 @@ def _check_timeout(cls, value: TimeoutConfig):
233260
return TimeoutConfig.parse_obj(value)
234261
return value
235262

263+
def _get_namespace(self, name: str) -> NamespaceResponseV1 | None:
264+
namespaces = self.client.paginate_namespaces(query=NamespacePaginateQueryV1(name=name)).items
265+
return namespaces[0] if namespaces else None
266+
236267
def _get_namespace_id(self) -> int:
237268
"""
238269
Fetch the ID of the namespace. Raises an exception if the namespace doesn't exist.

tests/tests_integration/test_horizon_hwm_store_integration.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
HORIZON_NAMESPACE = os.environ.get("HORIZON_NAMESPACE")
1515

1616

17-
def test_hwm_store_integration(hwm_store, hwm_new_value, ensure_namespace):
18-
hwm, new_value = hwm_new_value
17+
def test_hwm_store_integration(hwm_store, hwm_new_values, ensure_namespace):
18+
hwm, new_value = hwm_new_values
1919
assert hwm_store.get_hwm(hwm.name) is None
2020

2121
hwm_store.set_hwm(hwm)
@@ -65,3 +65,19 @@ def test_hwm_store_unexisting_namespace(hwm_new_value):
6565

6666
with pytest.raises(RuntimeError, match=error_msg):
6767
store.set_hwm(hwm)
68+
69+
70+
def test_hwm_store_creates_namespace():
71+
namespace_name = "new_namespace"
72+
store = HorizonHWMStore(
73+
api_url=HORIZON_URL,
74+
auth=LoginPassword(login=HORIZON_USER, password=HORIZON_PASSWORD),
75+
namespace=namespace_name,
76+
)
77+
error_msg = "Namespace 'new_namespace' not found. Please create it before using."
78+
79+
with pytest.raises(RuntimeError, match=error_msg):
80+
store.get_hwm("some_hwm_name")
81+
82+
store.force_create_namespace(namespace_name)
83+
assert store.get_hwm("some_hwm_name") is None

0 commit comments

Comments
 (0)