Skip to content

Commit c1524a0

Browse files
committed
feat: support Storage Box Types
1 parent 86d3e0a commit c1524a0

File tree

7 files changed

+385
-0
lines changed

7 files changed

+385
-0
lines changed

hcloud/_client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from .server_types import ServerTypesClient
2626
from .servers import ServersClient
2727
from .ssh_keys import SSHKeysClient
28+
from .storage_box_types import StorageBoxTypesClient
2829
from .volumes import VolumesClient
2930

3031

@@ -250,6 +251,12 @@ def __init__(
250251
:type: :class:`PlacementGroupsClient <hcloud.placement_groups.client.PlacementGroupsClient>`
251252
"""
252253

254+
self.storage_box_types = StorageBoxTypesClient(self)
255+
"""StorageBoxTypesClient Instance
256+
257+
:type: :class:`StorageBoxTypesClient <hcloud.storage_box_types.client.StorageBoxTypesClient>`
258+
"""
259+
253260
def _get_user_agent(self) -> str:
254261
"""Get the user agent of the hcloud-python instance with the user application name (if specified)
255262
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from __future__ import annotations
2+
3+
from .client import (
4+
BoundStorageBoxType,
5+
StorageBoxTypesClient,
6+
StorageBoxTypesPageResult,
7+
)
8+
from .domain import StorageBoxType
9+
10+
__all__ = [
11+
"BoundStorageBoxType",
12+
"StorageBoxTypesClient",
13+
"StorageBoxTypesPageResult",
14+
"StorageBoxType",
15+
]

hcloud/storage_box_types/client.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING, Any, NamedTuple
4+
5+
from ..core import BoundModelBase, ClientEntityBase, Meta
6+
from .domain import StorageBoxType
7+
8+
if TYPE_CHECKING:
9+
from .._client import Client
10+
11+
12+
class BoundStorageBoxType(BoundModelBase, StorageBoxType):
13+
_client: StorageBoxTypesClient
14+
15+
model = StorageBoxType
16+
17+
18+
class StorageBoxTypesPageResult(NamedTuple):
19+
storage_box_types: list[BoundStorageBoxType]
20+
meta: Meta
21+
22+
23+
class StorageBoxTypesClient(ClientEntityBase):
24+
_client: Client
25+
26+
def get_by_id(self, id: int) -> BoundStorageBoxType:
27+
"""
28+
Returns a specific Storage Box Type.
29+
30+
See https://docs.hetzner.cloud/reference/hetzner#storage-box-types-get-a-storage-box-type
31+
32+
:param id: ID of the Storage Box Type.
33+
"""
34+
response = self._client._request_hetzner( # pylint: disable=protected-access
35+
method="GET",
36+
url=f"/storage_box_types/{id}",
37+
)
38+
return BoundStorageBoxType(self, response["storage_box_type"])
39+
40+
def get_by_name(self, name: str) -> BoundStorageBoxType | None:
41+
"""
42+
Returns a specific Storage Box Type.
43+
44+
See https://docs.hetzner.cloud/reference/hetzner#storage-box-types-list-storage-box-types
45+
46+
:param name: Name of the Storage Box Type.
47+
"""
48+
return self._get_first_by(name=name)
49+
50+
def get_list(
51+
self,
52+
name: str | None = None,
53+
page: int | None = None,
54+
per_page: int | None = None,
55+
) -> StorageBoxTypesPageResult:
56+
"""
57+
Returns a list of Storage Box Types for a specific page.
58+
59+
See https://docs.hetzner.cloud/reference/hetzner#storage-box-types-list-storage-box-types
60+
61+
:param name: Name of the Storage Box Type.
62+
:param page: Page number to return.
63+
:param per_page: Maximum number of entries returned per page.
64+
"""
65+
params: dict[str, Any] = {}
66+
if name is not None:
67+
params["name"] = name
68+
if page is not None:
69+
params["page"] = page
70+
if per_page is not None:
71+
params["per_page"] = per_page
72+
73+
response = self._client._request_hetzner( # pylint: disable=protected-access
74+
method="GET",
75+
url="/storage_box_types",
76+
params=params,
77+
)
78+
return StorageBoxTypesPageResult(
79+
storage_box_types=[
80+
BoundStorageBoxType(self, o) for o in response["storage_box_types"]
81+
],
82+
meta=Meta.parse_meta(response),
83+
)
84+
85+
def get_all(
86+
self,
87+
name: str | None = None,
88+
) -> list[BoundStorageBoxType]:
89+
"""
90+
Returns all Storage Box Types.
91+
92+
See https://docs.hetzner.cloud/reference/hetzner#storage-box-types-list-storage-box-types
93+
94+
:param name: Name of the Storage Box Type.
95+
"""
96+
return self._iter_pages(
97+
self.get_list,
98+
name=name,
99+
)

hcloud/storage_box_types/domain.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from __future__ import annotations
2+
3+
from ..core import BaseDomain, DomainIdentityMixin
4+
from ..deprecation import DeprecationInfo
5+
6+
7+
class StorageBoxType(BaseDomain, DomainIdentityMixin):
8+
"""
9+
Storage Box Type Domain.
10+
11+
See https://docs.hetzner.cloud/reference/hetzner#storage-box-types.
12+
"""
13+
14+
__api_properties__ = (
15+
"id",
16+
"name",
17+
"description",
18+
"snapshot_limit",
19+
"automatic_snapshot_limit",
20+
"subaccounts_limit",
21+
"size",
22+
"deprecation",
23+
"prices",
24+
)
25+
__slots__ = __api_properties__
26+
27+
def __init__(
28+
self,
29+
id: int | None = None,
30+
name: str | None = None,
31+
description: str | None = None,
32+
snapshot_limit: int | None = None,
33+
automatic_snapshot_limit: int | None = None,
34+
subaccounts_limit: int | None = None,
35+
size: int | None = None,
36+
prices: list[dict] | None = None,
37+
deprecation: dict | None = None,
38+
):
39+
self.id = id
40+
self.name = name
41+
self.description = description
42+
self.snapshot_limit = snapshot_limit
43+
self.automatic_snapshot_limit = automatic_snapshot_limit
44+
self.subaccounts_limit = subaccounts_limit
45+
self.size = size
46+
self.prices = prices
47+
self.deprecation = (
48+
DeprecationInfo.from_dict(deprecation) if deprecation is not None else None
49+
)

tests/unit/storage_box_types/__init__.py

Whitespace-only changes.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
6+
@pytest.fixture()
7+
def storage_box_type1():
8+
return {
9+
"id": 42,
10+
"name": "bx11",
11+
"description": "BX11",
12+
"snapshot_limit": 10,
13+
"automatic_snapshot_limit": 10,
14+
"subaccounts_limit": 100,
15+
"size": 1099511627776,
16+
"prices": [
17+
{
18+
"location": "fsn1",
19+
"price_hourly": {"gross": "0.0051", "net": "0.0051"},
20+
"price_monthly": {"gross": "3.2000", "net": "3.2000"},
21+
"setup_fee": {"gross": "0.0000", "net": "0.0000"},
22+
}
23+
],
24+
"deprecation": {
25+
"unavailable_after": "2023-09-01T00:00:00+00:00",
26+
"announced": "2023-06-01T00:00:00+00:00",
27+
},
28+
}
29+
30+
31+
@pytest.fixture()
32+
def storage_box_type2():
33+
return {
34+
"id": 43,
35+
"name": "bx21",
36+
"description": "BX21",
37+
"snapshot_limit": 20,
38+
"automatic_snapshot_limit": 20,
39+
"subaccounts_limit": 100,
40+
"size": 5497558138880,
41+
"prices": [
42+
{
43+
"location": "fsn1",
44+
"price_hourly": {"net": "1.0000", "gross": "1.1900"},
45+
"price_monthly": {"net": "1.0000", "gross": "1.1900"},
46+
"setup_fee": {"net": "1.0000", "gross": "1.1900"},
47+
}
48+
],
49+
"deprecation": None,
50+
}

0 commit comments

Comments
 (0)