Skip to content

Commit 95d0b20

Browse files
new: Add vpc field to Instance(...).ips property method result (#379)
* Support ipv4.vpc field in Instance.ips property method * Update integration test * Add null check
1 parent 49dd2c6 commit 95d0b20

5 files changed

Lines changed: 160 additions & 87 deletions

File tree

linode_api4/objects/linode.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
)
2222
from linode_api4.objects.base import MappedObject
2323
from linode_api4.objects.filtering import FilterableAttribute
24-
from linode_api4.objects.networking import IPAddress, IPv6Range
24+
from linode_api4.objects.networking import IPAddress, IPv6Range, VPCIPAddress
2525
from linode_api4.objects.vpc import VPC, VPCSubnet
2626
from linode_api4.paginated_list import PaginatedList
2727

@@ -693,6 +693,10 @@ def ips(self):
693693
i = IPAddress(self._client, c["address"], c)
694694
reserved.append(i)
695695

696+
vpc = [
697+
VPCIPAddress.from_json(v) for v in result["ipv4"].get("vpc", [])
698+
]
699+
696700
slaac = IPAddress(
697701
self._client,
698702
result["ipv6"]["slaac"]["address"],
@@ -716,6 +720,7 @@ def ips(self):
716720
"private": v4pri,
717721
"shared": shared_ips,
718722
"reserved": reserved,
723+
"vpc": vpc,
719724
},
720725
"ipv6": {
721726
"slaac": slaac,

linode_api4/objects/networking.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from dataclasses import dataclass
2+
from typing import Optional
23

34
from linode_api4.errors import UnexpectedResponseError
45
from linode_api4.objects import Base, DerivedBase, JSONObject, Property, Region
@@ -106,6 +107,32 @@ def to(self, linode):
106107
return {"address": self.address, "linode_id": linode.id}
107108

108109

110+
@dataclass
111+
class VPCIPAddress(JSONObject):
112+
"""
113+
VPCIPAddress represents the IP address of a VPC.
114+
115+
NOTE: This is not implemented as a typical API object (Base) because VPC IPs
116+
cannot be refreshed through the /networking/ips/{address} endpoint.
117+
"""
118+
119+
address: str = ""
120+
gateway: str = ""
121+
region: str = ""
122+
subnet_mask: str = ""
123+
vpc_id: int = 0
124+
subnet_id: int = 0
125+
linode_id: int = 0
126+
config_id: int = 0
127+
interface_id: int = 0
128+
prefix: int = 0
129+
130+
active: bool = False
131+
132+
address_range: Optional[str] = None
133+
nat_1_1: Optional[str] = None
134+
135+
109136
class VLAN(Base):
110137
"""
111138
.. note:: At this time, the Linode API only supports listing VLANs.
Lines changed: 94 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,106 @@
11
{
2-
"ipv4": {
3-
"private": [
4-
{
5-
"address": "192.168.133.234",
6-
"gateway": null,
7-
"linode_id": 123,
8-
"prefix": 17,
9-
"public": false,
10-
"rdns": null,
11-
"region": "us-east",
12-
"subnet_mask": "255.255.128.0",
13-
"type": "ipv4"
14-
}
15-
],
16-
"public": [
17-
{
18-
"address": "97.107.143.141",
19-
"gateway": "97.107.143.1",
20-
"linode_id": 123,
21-
"prefix": 24,
22-
"public": true,
23-
"rdns": "test.example.org",
24-
"region": "us-east",
25-
"subnet_mask": "255.255.255.0",
26-
"type": "ipv4"
27-
}
28-
],
29-
"reserved": [
30-
{
31-
"address": "97.107.143.141",
32-
"gateway": "97.107.143.1",
33-
"linode_id": 123,
34-
"prefix": 24,
35-
"public": true,
36-
"rdns": "test.example.org",
37-
"region": "us-east",
38-
"subnet_mask": "255.255.255.0",
39-
"type": "ipv4"
40-
}
41-
],
42-
"shared": [
43-
{
44-
"address": "97.107.143.141",
45-
"gateway": "97.107.143.1",
46-
"linode_id": 123,
47-
"prefix": 24,
48-
"public": true,
49-
"rdns": "test.example.org",
50-
"region": "us-east",
51-
"subnet_mask": "255.255.255.0",
52-
"type": "ipv4"
53-
}
54-
]
55-
},
56-
"ipv6": {
57-
"global": [
58-
{
59-
"prefix": 124,
60-
"range": "2600:3c01::2:5000:0",
61-
"region": "us-east",
62-
"route_target": "2600:3c01::2:5000:f"
63-
}
64-
],
65-
"link_local": {
66-
"address": "fe80::f03c:91ff:fe24:3a2f",
67-
"gateway": "fe80::1",
2+
"ipv4": {
3+
"private": [
4+
{
5+
"address": "192.168.133.234",
6+
"gateway": null,
687
"linode_id": 123,
69-
"prefix": 64,
8+
"prefix": 17,
709
"public": false,
7110
"rdns": null,
7211
"region": "us-east",
73-
"subnet_mask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
74-
"type": "ipv6"
75-
},
76-
"slaac": {
77-
"address": "2600:3c03::f03c:91ff:fe24:3a2f",
78-
"gateway": "fe80::1",
12+
"subnet_mask": "255.255.128.0",
13+
"type": "ipv4"
14+
}
15+
],
16+
"public": [
17+
{
18+
"address": "97.107.143.141",
19+
"gateway": "97.107.143.1",
7920
"linode_id": 123,
80-
"prefix": 64,
21+
"prefix": 24,
8122
"public": true,
82-
"rdns": null,
23+
"rdns": "test.example.org",
24+
"region": "us-east",
25+
"subnet_mask": "255.255.255.0",
26+
"type": "ipv4"
27+
}
28+
],
29+
"reserved": [
30+
{
31+
"address": "97.107.143.141",
32+
"gateway": "97.107.143.1",
33+
"linode_id": 123,
34+
"prefix": 24,
35+
"public": true,
36+
"rdns": "test.example.org",
8337
"region": "us-east",
84-
"subnet_mask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
85-
"type": "ipv6"
38+
"subnet_mask": "255.255.255.0",
39+
"type": "ipv4"
40+
}
41+
],
42+
"vpc": [
43+
{
44+
"address": "10.0.0.2",
45+
"address_range": null,
46+
"vpc_id": 39246,
47+
"subnet_id": 39388,
48+
"region": "us-mia",
49+
"linode_id": 55904908,
50+
"config_id": 59036295,
51+
"interface_id": 1186165,
52+
"active": true,
53+
"nat_1_1": "172.233.179.133",
54+
"gateway": "10.0.0.1",
55+
"prefix": 24,
56+
"subnet_mask": "255.255.255.0"
8657
}
58+
],
59+
"shared": [
60+
{
61+
"address": "97.107.143.141",
62+
"gateway": "97.107.143.1",
63+
"linode_id": 123,
64+
"prefix": 24,
65+
"public": true,
66+
"rdns": "test.example.org",
67+
"region": "us-east",
68+
"subnet_mask": "255.255.255.0",
69+
"type": "ipv4"
70+
}
71+
]
72+
},
73+
"ipv6": {
74+
"global": [
75+
{
76+
"prefix": 124,
77+
"range": "2600:3c01::2:5000:0",
78+
"region": "us-east",
79+
"route_target": "2600:3c01::2:5000:f"
80+
}
81+
],
82+
"link_local": {
83+
"address": "fe80::f03c:91ff:fe24:3a2f",
84+
"gateway": "fe80::1",
85+
"linode_id": 123,
86+
"prefix": 64,
87+
"public": false,
88+
"rdns": null,
89+
"region": "us-east",
90+
"subnet_mask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
91+
"type": "ipv6"
92+
},
93+
"slaac": {
94+
"address": "2600:3c03::f03c:91ff:fe24:3a2f",
95+
"gateway": "fe80::1",
96+
"linode_id": 123,
97+
"prefix": 64,
98+
"public": true,
99+
"rdns": null,
100+
"region": "us-east",
101+
"subnet_mask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
102+
"type": "ipv6"
87103
}
88104
}
105+
}
89106

test/integration/models/test_linode.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,20 @@ def test_create_vpc(
621621
assert interface.ipv4.nat_1_1 == linode.ipv4[0]
622622
assert interface.ip_ranges == ["10.0.0.5/32"]
623623

624+
vpc_ip = linode.ips.ipv4.vpc[0]
625+
vpc_range_ip = linode.ips.ipv4.vpc[1]
626+
627+
assert vpc_ip.nat_1_1 == linode.ips.ipv4.public[0].address
628+
assert vpc_ip.address_range is None
629+
assert vpc_ip.vpc_id == vpc.id
630+
assert vpc_ip.subnet_id == subnet.id
631+
assert vpc_ip.config_id == config.id
632+
assert vpc_ip.interface_id == interface.id
633+
assert not vpc_ip.active
634+
635+
assert vpc_range_ip.address_range == "10.0.0.5/32"
636+
assert not vpc_range_ip.active
637+
624638
def test_update_vpc(
625639
self,
626640
linode_for_network_interface_tests,

test/unit/objects/linode_test.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -348,15 +348,25 @@ def test_ips(self):
348348

349349
ips = linode.ips
350350

351-
self.assertIsNotNone(ips.ipv4)
352-
self.assertIsNotNone(ips.ipv6)
353-
self.assertIsNotNone(ips.ipv4.public)
354-
self.assertIsNotNone(ips.ipv4.private)
355-
self.assertIsNotNone(ips.ipv4.shared)
356-
self.assertIsNotNone(ips.ipv4.reserved)
357-
self.assertIsNotNone(ips.ipv6.slaac)
358-
self.assertIsNotNone(ips.ipv6.link_local)
359-
self.assertIsNotNone(ips.ipv6.ranges)
351+
assert ips.ipv4 is not None
352+
assert ips.ipv6 is not None
353+
assert ips.ipv4.public is not None
354+
assert ips.ipv4.private is not None
355+
assert ips.ipv4.shared is not None
356+
assert ips.ipv4.reserved is not None
357+
assert ips.ipv4.vpc is not None
358+
assert ips.ipv6.slaac is not None
359+
assert ips.ipv6.link_local is not None
360+
assert ips.ipv6.ranges is not None
361+
362+
vpc_ip = ips.ipv4.vpc[0]
363+
assert vpc_ip.nat_1_1 == "172.233.179.133"
364+
assert vpc_ip.address_range == None
365+
assert vpc_ip.vpc_id == 39246
366+
assert vpc_ip.subnet_id == 39388
367+
assert vpc_ip.config_id == 59036295
368+
assert vpc_ip.interface_id == 1186165
369+
assert vpc_ip.active
360370

361371
def test_initiate_migration(self):
362372
"""

0 commit comments

Comments
 (0)