Skip to content

Commit d80fedd

Browse files
authored
Add Network Domains for IPv4 and IPv6 to Server (#11)
Closes #8 This PR allows users to directly get the network and the network mask on the server ipv6 address and it documents/fix the result we give the user instead of returning the API result directly.
1 parent cf9cfea commit d80fedd

5 files changed

Lines changed: 194 additions & 40 deletions

File tree

hcloud/floating_ips/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class BoundFloatingIP(BoundModelBase):
1111
model = FloatingIP
1212

13-
def __init__(self, client, data):
13+
def __init__(self, client, data, complete=True):
1414
from hcloud.servers.client import BoundServer
1515
server = data.get("server")
1616
if server is not None:
@@ -20,7 +20,7 @@ def __init__(self, client, data):
2020
if home_location is not None:
2121
data['home_location'] = BoundLocation(client._client.locations, home_location)
2222

23-
super(BoundFloatingIP, self).__init__(client, data)
23+
super(BoundFloatingIP, self).__init__(client, data, complete)
2424

2525
def get_actions_list(self, sort=None, page=None, per_page=None):
2626
# type: (Optional[List[str]], Optional[int], Optional[int]) -> PageResult[BoundAction, Meta]

hcloud/servers/client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33

44
from hcloud.actions.client import BoundAction
55
from hcloud.core.domain import add_meta_to_result
6+
from hcloud.floating_ips.client import BoundFloatingIP
67
from hcloud.isos.client import BoundIso
7-
from hcloud.servers.domain import Server, CreateServerResponse, ResetPasswordResponse, EnableRescueResponse, RequestConsoleResponse
8+
from hcloud.servers.domain import Server, CreateServerResponse, ResetPasswordResponse, EnableRescueResponse, RequestConsoleResponse, PublicNetwork, IPv4Address, IPv6Network
89
from hcloud.volumes.client import BoundVolume
910
from hcloud.images.domain import CreateImageResponse
1011
from hcloud.images.client import BoundImage
@@ -15,7 +16,7 @@
1516
class BoundServer(BoundModelBase):
1617
model = Server
1718

18-
def __init__(self, client, data, complete=False):
19+
def __init__(self, client, data, complete=True):
1920

2021
datacenter = data.get('datacenter')
2122
if datacenter is not None:
@@ -38,6 +39,13 @@ def __init__(self, client, data, complete=False):
3839
if server_type is not None:
3940
data['server_type'] = BoundServerType(client._client.server_types, server_type)
4041

42+
public_net = data.get("public_net")
43+
if public_net:
44+
ipv4_address = IPv4Address(**public_net['ipv4'])
45+
ipv6_network = IPv6Network(**public_net['ipv6'])
46+
floating_ips = [BoundFloatingIP(client._client.floating_ips, {"id": floating_ip}, complete=False) for floating_ip in public_net['floating_ips']]
47+
data['public_net'] = PublicNetwork(ipv4=ipv4_address, ipv6=ipv6_network, floating_ips=floating_ips)
48+
4149
super(BoundServer, self).__init__(client, data, complete)
4250

4351
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):

hcloud/servers/domain.py

Lines changed: 86 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,25 @@ class Server(BaseDomain):
2828
created = ISODateTime()
2929

3030
def __init__(
31-
self,
32-
id,
33-
name=None,
34-
status=None,
35-
created=None,
36-
public_net=None,
37-
server_type=None,
38-
datacenter=None,
39-
image=None,
40-
iso=None,
41-
rescue_enabled=None,
42-
locked=None,
43-
backup_window=None,
44-
outgoing_traffic=None,
45-
ingoing_traffic=None,
46-
included_traffic=None,
47-
protection=None,
48-
labels=None,
49-
volumes=None,
31+
self,
32+
id,
33+
name=None,
34+
status=None,
35+
created=None,
36+
public_net=None,
37+
server_type=None,
38+
datacenter=None,
39+
image=None,
40+
iso=None,
41+
rescue_enabled=None,
42+
locked=None,
43+
backup_window=None,
44+
outgoing_traffic=None,
45+
ingoing_traffic=None,
46+
included_traffic=None,
47+
protection=None,
48+
labels=None,
49+
volumes=None,
5050
):
5151
self.id = id
5252
self.name = name
@@ -78,10 +78,10 @@ class CreateServerResponse(BaseDomain):
7878

7979
def __init__(
8080
self,
81-
server, # type: BoundServer
82-
action, # type: BoundAction
83-
next_actions, # type: List[Action]
84-
root_password # type: str
81+
server, # type: BoundServer
82+
action, # type: BoundAction
83+
next_actions, # type: List[Action]
84+
root_password # type: str
8585
):
8686
self.server = server
8787
self.action = action
@@ -97,8 +97,8 @@ class ResetPasswordResponse(BaseDomain):
9797

9898
def __init__(
9999
self,
100-
action, # type: BoundAction
101-
root_password # type: str
100+
action, # type: BoundAction
101+
root_password # type: str
102102
):
103103
self.action = action
104104
self.root_password = root_password
@@ -112,8 +112,8 @@ class EnableRescueResponse(BaseDomain):
112112

113113
def __init__(
114114
self,
115-
action, # type: BoundAction
116-
root_password # type: str
115+
action, # type: BoundAction
116+
root_password # type: str
117117
):
118118
self.action = action
119119
self.root_password = root_password
@@ -128,10 +128,66 @@ class RequestConsoleResponse(BaseDomain):
128128

129129
def __init__(
130130
self,
131-
action, # type: BoundAction
132-
wss_url, # type: str
133-
password, # type: str
131+
action, # type: BoundAction
132+
wss_url, # type: str
133+
password, # type: str
134134
):
135135
self.action = action
136136
self.wss_url = wss_url
137137
self.password = password
138+
139+
140+
class PublicNetwork(BaseDomain):
141+
__slots__ = (
142+
"ipv4",
143+
"ipv6",
144+
"floating_ips"
145+
)
146+
147+
def __init__(self,
148+
ipv4, # type: IPv4Address
149+
ipv6, # type: IPv6Network
150+
floating_ips, # type: List[BoundFloatingIP]
151+
):
152+
self.ipv4 = ipv4
153+
self.ipv6 = ipv6
154+
self.floating_ips = floating_ips
155+
156+
157+
class IPv4Address(BaseDomain):
158+
__slots__ = (
159+
"ip",
160+
"blocked",
161+
"dns_ptr"
162+
)
163+
164+
def __init__(self,
165+
ip, # type: str
166+
blocked, # type: bool
167+
dns_ptr, # type: str
168+
):
169+
self.ip = ip
170+
self.blocked = blocked
171+
self.dns_ptr = dns_ptr
172+
173+
174+
class IPv6Network(BaseDomain):
175+
__slots__ = (
176+
"ip",
177+
"blocked",
178+
"dns_ptr",
179+
"network",
180+
"network_mask"
181+
)
182+
183+
def __init__(self,
184+
ip, # type: str
185+
blocked, # type: bool
186+
dns_ptr, # type: list
187+
):
188+
self.ip = ip
189+
self.blocked = blocked
190+
self.dns_ptr = dns_ptr
191+
ip_parts = self.ip.split("/") # 2001:db8::/64 to 2001:db8:: and 64
192+
self.network = ip_parts[0]
193+
self.network_mask = ip_parts[1]

tests/unit/servers/conftest.py

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,26 @@ def response_simple_server():
99
"name": "my-server",
1010
"status": "running",
1111
"created": "2016-01-30T23:50+00:00",
12-
"public_net": {},
12+
"public_net": {
13+
"ipv4": {
14+
"ip": "1.2.3.4",
15+
"blocked": False,
16+
"dns_ptr": "server01.example.com"
17+
},
18+
"ipv6": {
19+
"ip": "2001:db8::/64",
20+
"blocked": False,
21+
"dns_ptr": [
22+
{
23+
"ip": "2001:db8::1",
24+
"dns_ptr": "server.example.com"
25+
}
26+
]
27+
},
28+
"floating_ips": [
29+
478
30+
]
31+
},
1332
"server_type": {
1433
"id": 1,
1534
"name": "cx11",
@@ -110,7 +129,25 @@ def response_create_simple_server():
110129
"name": "my-server",
111130
"status": "running",
112131
"created": "2016-01-30T23:50+00:00",
113-
"public_net": {},
132+
"public_net": {
133+
"ipv4": {
134+
"ip": "1.2.3.4",
135+
"blocked": False,
136+
"dns_ptr": "server01.example.com"
137+
},
138+
"ipv6": {
139+
"ip": "2001:db8::/64",
140+
"blocked": False,
141+
"dns_ptr": [
142+
{
143+
"ip": "2001:db8::1",
144+
"dns_ptr": "server.example.com"
145+
}
146+
]
147+
},
148+
"floating_ips": [
149+
]
150+
},
114151
"server_type": {
115152
"id": 1,
116153
"name": "cx11",
@@ -380,7 +417,26 @@ def response_simple_servers():
380417
"name": "my-server",
381418
"status": "running",
382419
"created": "2016-01-30T23:50+00:00",
383-
"public_net": {},
420+
"public_net": {
421+
"ipv4": {
422+
"ip": "1.2.3.4",
423+
"blocked": False,
424+
"dns_ptr": "server01.example.com"
425+
},
426+
"ipv6": {
427+
"ip": "2001:db8::/64",
428+
"blocked": False,
429+
"dns_ptr": [
430+
{
431+
"ip": "2001:db8::1",
432+
"dns_ptr": "server.example.com"
433+
}
434+
]
435+
},
436+
"floating_ips": [
437+
478
438+
]
439+
},
384440
"server_type": {
385441
"id": 1,
386442
"name": "cx11",
@@ -474,7 +530,26 @@ def response_simple_servers():
474530
"name": "my-server2",
475531
"status": "running",
476532
"created": "2016-03-30T23:50+00:00",
477-
"public_net": {},
533+
"public_net": {
534+
"ipv4": {
535+
"ip": "1.2.3.4",
536+
"blocked": False,
537+
"dns_ptr": "server01.example.com"
538+
},
539+
"ipv6": {
540+
"ip": "2001:db8::/64",
541+
"blocked": False,
542+
"dns_ptr": [
543+
{
544+
"ip": "2001:db8::1",
545+
"dns_ptr": "server.example.com"
546+
}
547+
]
548+
},
549+
"floating_ips": [
550+
478
551+
]
552+
},
478553
"server_type": {
479554
"id": 1,
480555
"name": "cx11",

tests/unit/servers/test_client.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import mock
22
import pytest
33

4+
from hcloud.floating_ips.client import BoundFloatingIP
45
from hcloud.isos.client import BoundIso
56
from hcloud.servers.client import ServersClient, BoundServer
67

7-
from hcloud.servers.domain import Server
8+
from hcloud.servers.domain import Server, PublicNetwork, IPv4Address, IPv6Network
89
from hcloud.volumes.client import BoundVolume
910
from hcloud.volumes.domain import Volume
1011
from hcloud.images.domain import Image
@@ -32,7 +33,21 @@ def test_bound_server_init(self, response_full_server):
3233

3334
assert bound_server.id == 42
3435
assert bound_server.name == "my-server"
35-
assert bound_server.public_net["floating_ips"] == [478]
36+
assert isinstance(bound_server.public_net, PublicNetwork)
37+
assert isinstance(bound_server.public_net.ipv4, IPv4Address)
38+
assert bound_server.public_net.ipv4.ip == "1.2.3.4"
39+
assert bound_server.public_net.ipv4.blocked is False
40+
assert bound_server.public_net.ipv4.dns_ptr == "server01.example.com"
41+
42+
assert isinstance(bound_server.public_net.ipv6, IPv6Network)
43+
assert bound_server.public_net.ipv6.ip == "2001:db8::/64"
44+
assert bound_server.public_net.ipv6.blocked is False
45+
assert bound_server.public_net.ipv6.network == "2001:db8::"
46+
assert bound_server.public_net.ipv6.network_mask == "64"
47+
48+
assert isinstance(bound_server.public_net.floating_ips[0], BoundFloatingIP)
49+
assert bound_server.public_net.floating_ips[0].id == 478
50+
assert bound_server.public_net.floating_ips[0].complete is False
3651

3752
assert isinstance(bound_server.datacenter, BoundDatacenter)
3853
assert bound_server.datacenter._client == bound_server._client._client.datacenters

0 commit comments

Comments
 (0)