Skip to content

Commit 3b895fe

Browse files
author
Ilyas Gasanov
committed
[DOP-24139] Add method for creating namespaces
1 parent db5181f commit 3b895fe

File tree

5 files changed

+61
-19
lines changed

5 files changed

+61
-19
lines changed

conftest.py

Lines changed: 7 additions & 10 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,9 @@ def hwm_store():
164168

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

169-
store = HorizonHWMStore(
172+
HorizonHWMStore(
170173
api_url=HORIZON_URL,
171174
auth=LoginPassword(login=HORIZON_USER, password=HORIZON_PASSWORD),
172175
namespace=HORIZON_NAMESPACE,
173-
)
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
176+
).force_create_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, check

horizon_hwm_store/horizon_hwm_store.py

Lines changed: 34 additions & 6 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():
102105
with IncrementalStrategy():
103106
df = reader.run()
104107
writer.run(df)
@@ -213,6 +216,24 @@ def check(self) -> HorizonHWMStore:
213216
self._get_namespace_id()
214217
return self
215218

219+
def force_create_namespace(self) -> HorizonHWMStore:
220+
"""
221+
Create a namespace with name specified in HorizonHWMStore class.
222+
223+
Returns
224+
-------
225+
HorizonHWMStore
226+
Self
227+
"""
228+
namespace = self._get_namespace(self.namespace)
229+
if namespace is None:
230+
try:
231+
namespace = self.client.create_namespace(NamespaceCreateRequestV1(name=self.namespace))
232+
self._namespace_id = namespace.id # noqa: WPS601
233+
except EntityAlreadyExistsError:
234+
...
235+
return self
236+
216237
# LoginPassword, RetryConfig and TimeoutConfig can be inherited from Pydantic v2 BaseModel
217238
# which is detected by Pydantic v1 as arbitrary type. So we need to parse them manually.
218239
@validator("auth", pre=True)
@@ -233,6 +254,10 @@ def _check_timeout(cls, value: TimeoutConfig):
233254
return TimeoutConfig.parse_obj(value)
234255
return value
235256

257+
def _get_namespace(self, name: str) -> NamespaceResponseV1 | None:
258+
namespaces = self.client.paginate_namespaces(query=NamespacePaginateQueryV1(name=name)).items
259+
return namespaces[0] if namespaces else None
260+
236261
def _get_namespace_id(self) -> int:
237262
"""
238263
Fetch the ID of the namespace. Raises an exception if the namespace doesn't exist.
@@ -250,11 +275,14 @@ def _get_namespace_id(self) -> int:
250275
if self._namespace_id is not None:
251276
return self._namespace_id
252277

253-
namespaces = self.client.paginate_namespaces(NamespacePaginateQueryV1(name=self.namespace)).items
254-
if not namespaces:
255-
raise RuntimeError(f"Namespace {self.namespace!r} not found. Please create it before using.")
278+
namespace = self._get_namespace(self.namespace)
279+
if namespace is None:
280+
raise RuntimeError(
281+
f"Namespace {self.namespace!r} not found. "
282+
"Please create it before using by calling .force_create_namespace() method.",
283+
)
256284

257-
self._namespace_id = namespaces[0].id # noqa: WPS601
285+
self._namespace_id = namespace.id # noqa: WPS601
258286
return self._namespace_id
259287

260288
def _get_hwm_id(self, namespace_id: int, hwm_name: str) -> Optional[int]:

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()
83+
assert store.get_hwm("some_hwm_name") is None

0 commit comments

Comments
 (0)