Skip to content

Commit 353aaa0

Browse files
committed
Resolve "Implement client for Datacenter endpoint"
1 parent decbc3a commit 353aaa0

25 files changed

Lines changed: 712 additions & 80 deletions

File tree

hcloud/datacenters/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

hcloud/datacenters/client.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# -*- coding: utf-8 -*-
2+
from hcloud.core.client import ClientEntityBase, BoundModelBase
3+
4+
from hcloud.datacenters.domain import Datacenter, DatacenterServerTypes
5+
from hcloud.locations.client import BoundLocation
6+
from hcloud.server_types.client import BoundServerType
7+
8+
9+
class BoundDatacenter(BoundModelBase):
10+
model = Datacenter
11+
12+
def __init__(self, client, data):
13+
location = data.get("location")
14+
if location is not None:
15+
data['location'] = BoundLocation(client._client.locations, location)
16+
17+
server_types = data.get("server_types")
18+
if server_types is not None:
19+
DatacenterServerTypes
20+
available = [BoundServerType(client._client.server_types, {"id": server_type}, complete=False) for server_type in server_types['available']]
21+
supported = [BoundServerType(client._client.server_types, {"id": server_type}, complete=False) for server_type in server_types['supported']]
22+
available_for_migration = [BoundServerType(client._client.server_types, {"id": server_type}, complete=False) for server_type in server_types['available_for_migration']]
23+
data['server_types'] = DatacenterServerTypes(available=available, supported=supported, available_for_migration=available_for_migration)
24+
25+
super(BoundDatacenter, self).__init__(client, data)
26+
27+
28+
class DatacentersClient(ClientEntityBase):
29+
30+
def get_by_id(self, id):
31+
# type: (int) -> datacenters.client.BoundDatacenter
32+
response = self._client.request(url="/datacenters/{datacenter_id}".format(datacenter_id=id), method="GET")
33+
return BoundDatacenter(self, response['datacenter'])
34+
35+
def get_all(self, name=None):
36+
# type: (Optional[str]) -> List[BoundAction]
37+
params = {}
38+
if name is not None:
39+
params.update({"name": name})
40+
41+
response = self._client.request(url="/datacenters", method="GET", params=params)
42+
return [BoundDatacenter(self, datacenter_data) for datacenter_data in response['datacenters']]

hcloud/datacenters/domain.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# -*- coding: utf-8 -*-
2+
from hcloud.core.domain import BaseDomain
3+
4+
5+
class Datacenter(BaseDomain):
6+
7+
__slots__ = (
8+
"id",
9+
"name",
10+
"description",
11+
"location",
12+
"server_types",
13+
)
14+
15+
def __init__(
16+
self,
17+
id=None,
18+
name=None,
19+
description=None,
20+
location=None,
21+
server_types=None
22+
):
23+
self.id = id
24+
self.name = name
25+
self.description = description
26+
self.location = location
27+
self.server_types = server_types
28+
29+
30+
class DatacenterServerTypes:
31+
__slots__ = (
32+
"available",
33+
"supported",
34+
"available_for_migration"
35+
)
36+
37+
def __init__(self, available, supported, available_for_migration):
38+
self.available = available
39+
self.supported = supported
40+
self.available_for_migration = available_for_migration

hcloud/hcloud.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from hcloud.servers.client import ServersClient
88
from hcloud.server_types.client import ServerTypesClient
99
from hcloud.volumes.client import VolumesClient
10+
from hcloud.locations.client import LocationsClient
11+
from hcloud.datacenters.client import DatacentersClient
1012

1113

1214
from .version import VERSION
@@ -26,6 +28,8 @@ def __init__(self, token):
2628
self.token = token
2729
self.api_endpoint = "https://api.hetzner.cloud/v1"
2830

31+
self.datacenters = DatacentersClient(self)
32+
self.locations = LocationsClient(self)
2933
self.servers = ServersClient(self)
3034
self.server_types = ServerTypesClient(self)
3135
self.volumes = VolumesClient(self)

hcloud/locations/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

hcloud/locations/client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
from hcloud.core.client import ClientEntityBase, BoundModelBase
3+
4+
from hcloud.locations.domain import Location
5+
6+
7+
class BoundLocation(BoundModelBase):
8+
model = Location
9+
10+
11+
class LocationsClient(ClientEntityBase):
12+
13+
def get_by_id(self, id):
14+
# type: (int) -> locations.client.BoundLocation
15+
response = self._client.request(url="/locations/{location_id}".format(location_id=id), method="GET")
16+
return BoundLocation(self, response['location'])
17+
18+
def get_all(self, name=None):
19+
# type: # type: (Optional[str]) -> List[BoundAction]
20+
params = {}
21+
if name is not None:
22+
params.update({"name": name})
23+
24+
response = self._client.request(url="/locations", method="GET", params=params)
25+
return [BoundLocation(self, location_data) for location_data in response['locations']]

hcloud/locations/domain.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# -*- coding: utf-8 -*-
2+
from hcloud.core.domain import BaseDomain
3+
4+
5+
class Location(BaseDomain):
6+
7+
__slots__ = (
8+
"id",
9+
"name",
10+
"description",
11+
"country",
12+
"city",
13+
"latitude",
14+
"longitude"
15+
)
16+
17+
def __init__(
18+
self,
19+
id=None,
20+
name=None,
21+
description=None,
22+
country=None,
23+
city=None,
24+
latitude=None,
25+
longitude=None
26+
):
27+
self.id = id
28+
self.name = name
29+
self.description = description
30+
self.country = country
31+
self.city = city
32+
self.latitude = latitude
33+
self.longitude = longitude

hcloud/servers/client.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
from hcloud.images.domain import Image, CreateImageResponse
88
from hcloud.iso.domain import Iso
99
from hcloud.server_types.client import BoundServerType
10+
from hcloud.datacenters.client import BoundDatacenter
1011

1112

1213
class BoundServer(BoundModelBase):
1314
model = Server
1415

1516
def __init__(self, client, data):
17+
18+
datacenter = data.get('datacenter')
19+
if datacenter is not None:
20+
data['datacenter'] = BoundDatacenter(client._client.datacenters, datacenter)
21+
1622
volumes = data.get('volumes', [])
1723
if volumes:
1824
volumes = [BoundVolume(client._client.volumes, {"id": volume}, complete=False) for volume in volumes]
@@ -22,7 +28,6 @@ def __init__(self, client, data):
2228
if image is not None:
2329
# data['image'] = BoundImage(client._client.images, image, complete=True) # When Image Client is implemented
2430
data['image'] = Image(**image)
25-
print(data['image'].id)
2631

2732
iso = data.get("iso", None)
2833
if iso is not None:
@@ -139,20 +144,19 @@ def get_all(self, name=None, label_selector=None):
139144
return [BoundServer(self, server_data) for server_data in response['servers']]
140145

141146
def create(self,
142-
name, # type: str
143-
server_type, # type: str
144-
image, # type: Image
145-
ssh_keys=None, # type: Optional[List[str]]
146-
volumes=None, # type: Optional[List[Volume]]
147-
user_data=None, # type: Optional[str]
148-
labels=None, # type: Optional[Dict[str, str]]
149-
location=None, # type: Optional[str]
150-
datacenter=None, # type: Optional[str]
151-
start_after_create=True # type: Optional[bool]
147+
name, # type: str
148+
server_type, # type: str
149+
image, # type: Image
150+
ssh_keys=None, # type: Optional[List[str]]
151+
volumes=None, # type: Optional[List[Volume]]
152+
user_data=None, # type: Optional[str]
153+
labels=None, # type: Optional[Dict[str, str]]
154+
location=None, # type: Optional[Location]
155+
datacenter=None, # type: Optional[Datacenter]
156+
start_after_create=True, # type: Optional[bool]
157+
automount=None # type: Optional[bool]
152158
):
153159
# type: (...) -> CreateServerResponse
154-
# TODO: convert location str type to locations.domain.Location type, when implementation is ready
155-
# TODO: convert datacenter str type to datacenters.domain.Datacenter type, when implementation is ready
156160
"""
157161
Should be visible in docs
158162
:param name:
@@ -170,12 +174,15 @@ def create(self,
170174
data = {
171175
'name': name,
172176
'server_type': server_type,
173-
"start_after_create": start_after_create
177+
"start_after_create": start_after_create,
178+
"image": image.id_or_name
174179
}
175-
if image.id is not None:
176-
data['image'] = image.id
177-
else:
178-
data['image'] = image.name
180+
181+
if location is not None:
182+
data['location'] = location.id_or_name
183+
184+
if datacenter is not None:
185+
data['datacenter'] = datacenter.id_or_name
179186

180187
if ssh_keys is not None:
181188
data['ssh_keys'] = ssh_keys
@@ -185,10 +192,8 @@ def create(self,
185192
data['user_data'] = user_data
186193
if labels is not None:
187194
data['labels'] = labels
188-
if location is not None:
189-
data['location'] = location
190-
if datacenter is not None:
191-
data["datacenter"] = datacenter
195+
if automount is not None:
196+
data["automount"] = automount
192197

193198
response = self._client.request(url="/servers", method="POST", json=data)
194199

hcloud/volumes/client.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33

44
from hcloud.actions.client import BoundAction
55
from hcloud.volumes.domain import Volume, CreateVolumeResponse
6+
from hcloud.locations.client import BoundLocation
67

78

89
class BoundVolume(BoundModelBase):
910
model = Volume
1011

12+
def __init__(self, client, data, complete=True):
13+
location = data.get("location")
14+
if location is not None:
15+
data['location'] = BoundLocation(client._client.locations, location)
16+
super(BoundVolume, self).__init__(client, data, complete)
17+
1118
def attach(self, server):
1219
# type: (Union[Server, BoundServer]) -> Action
1320
return self._client.attach(server, self)
@@ -34,14 +41,15 @@ def get_all(self, label_selector=None):
3441
return [BoundVolume(self, volume_data) for volume_data in response['volumes']]
3542

3643
def create(self,
37-
size, # type: int
38-
name, # type: str
39-
labels=None, # type: Optional[str]
40-
location=None, # type: Optional[str]
41-
server=None # type: Optional[Server]
44+
size, # type: int
45+
name, # type: str
46+
labels=None, # type: Optional[str]
47+
location=None, # type: Optional[Location]
48+
server=None, # type: Optional[Server],
49+
automount=None, # type: Optional[bool],
50+
format=None, # type: Optional[str],
4251
):
4352
# type: (...) -> CreateVolumeResponse
44-
# TODO: convert location str type to locations.domain.Location type, when implementation is ready
4553

4654
if size <= 0:
4755
raise ValueError("size must be greater than 0")
@@ -56,9 +64,14 @@ def create(self,
5664
if labels is not None:
5765
data['labels'] = labels
5866
if location is not None:
59-
data['location'] = location
67+
data['location'] = location.id_or_name
68+
6069
if server is not None:
6170
data['server'] = server.id
71+
if automount is not None:
72+
data['automount'] = automount
73+
if format is not None:
74+
data['format'] = format
6275

6376
response = self._client.request(url="/volumes", json=data, method="POST")
6477

tests/integration/datacenters/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)