Skip to content

Commit b24e7df

Browse files
Add range allocate
1 parent 972fbcc commit b24e7df

File tree

2 files changed

+139
-4
lines changed

2 files changed

+139
-4
lines changed

linode_api4/groups/networking.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,64 @@ def ipv6_ranges(self, *filters):
180180
"""
181181
return self.client._get_and_filter(IPv6Range, *filters)
182182

183+
def ipv6_range_allocate(
184+
self,
185+
prefix_length: int,
186+
route_target: Optional[str] = None,
187+
linode: Optional[Union[Instance, int]] = None,
188+
**kwargs,
189+
) -> IPv6Range:
190+
"""
191+
Creates an IPv6 Range and assigns it based on the provided Linode or route target IPv6 SLAAC address.
192+
193+
API Documentation: https://techdocs.akamai.com/linode-api/reference/post-ipv6-range
194+
195+
Create an IPv6 range assigned to a Linode by ID::
196+
197+
range = client.networking.ipv6_range_allocate(64, linode_id=123)
198+
199+
200+
Create an IPv6 range assigned to a Linode by SLAAC::
201+
202+
range = client.networking.ipv6_range_allocate(
203+
64,
204+
route_target=instance.ipv6.split("/")[0]
205+
)
206+
207+
:param prefix_length: The prefix length of the IPv6 range.
208+
:type prefix_length: int
209+
:param route_target: The IPv6 SLAAC address to assign this range to. Required if linode is not specified.
210+
:type route_target: str
211+
:param linode: The ID of the Linode to assign this range to.
212+
The SLAAC address for the provided Linode is used as the range's route_target.
213+
Required if linode is not specified.
214+
:type linode: Instance or int
215+
216+
:returns: The new IPAddress.
217+
:rtype: IPAddress
218+
"""
219+
220+
params = {
221+
"prefix_length": prefix_length,
222+
"route_target": route_target,
223+
"linode_id": linode,
224+
}
225+
226+
params.update(**kwargs)
227+
228+
result = self.client.post(
229+
"/networking/ipv6/ranges",
230+
data=drop_null_keys(_flatten_request_body_recursive(params)),
231+
)
232+
233+
if not "range" in result:
234+
raise UnexpectedResponseError(
235+
"Unexpected response when allocating IPv6 range!", json=result
236+
)
237+
238+
result = IPv6Range(self.client, result["address"], result)
239+
return result
240+
183241
def ipv6_pools(self, *filters):
184242
"""
185243
Returns a list of IPv6 pools on this account.

test/integration/models/linode/interfaces/test_interfaces.py

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ipaddress
2+
from test.integration.conftest import get_region
23
from test.integration.helpers import get_test_label
34

45
import pytest
@@ -9,20 +10,44 @@
910
LinodeInterface,
1011
LinodeInterfaceDefaultRouteOptions,
1112
LinodeInterfaceOptions,
13+
LinodeInterfacePublicIPv4AddressOptions,
14+
LinodeInterfacePublicIPv4Options,
15+
LinodeInterfacePublicIPv6Options,
16+
LinodeInterfacePublicIPv6RangeOptions,
1217
LinodeInterfacePublicOptions,
1318
LinodeInterfaceVLANOptions,
1419
LinodeInterfaceVPCOptions,
1520
)
1621

1722

23+
@pytest.fixture(scope="function")
24+
def instance_with_interface_generation_linode(
25+
test_linode_client, e2e_test_firewall
26+
):
27+
client = test_linode_client
28+
29+
label = get_test_label()
30+
31+
instance, _ = client.linode.instance_create(
32+
"g6-nanode-1",
33+
get_region(test_linode_client, {"Linode Interfaces"}, site_type="core"),
34+
label=label,
35+
interface_generation=InterfaceGeneration.LINODE,
36+
)
37+
38+
yield instance
39+
40+
instance.delete()
41+
42+
1843
@pytest.fixture(scope="session")
19-
def linode_create_with_interfaces(
44+
def instance_with_interfaces(
2045
test_linode_client, e2e_test_firewall, create_vpc_with_subnet
2146
):
2247
client = test_linode_client
2348
vpc, subnet = create_vpc_with_subnet
2449

25-
# Are there regions where VPCs are supported but Linode Interfaces aren't
50+
# Are there regions where VPCs are supported but Linode Interfaces aren't?
2651
region = vpc.region
2752
label = get_test_label()
2853

@@ -61,9 +86,9 @@ def linode_create_with_interfaces(
6186

6287
def test_linode_create_with_linode_interfaces(
6388
create_vpc_with_subnet,
64-
linode_create_with_interfaces,
89+
instance_with_interfaces,
6590
):
66-
instance: Instance = linode_create_with_interfaces
91+
instance: Instance = instance_with_interfaces
6792
vpc, subnet = create_vpc_with_subnet
6893

6994
def __assert_base(iface: LinodeInterface):
@@ -126,3 +151,55 @@ def __assert_vlan(iface: LinodeInterface):
126151
__assert_public(instance.interfaces[0])
127152
__assert_vpc(instance.interfaces[1])
128153
__assert_vlan(instance.interfaces[2])
154+
155+
156+
def test_linode_interface_create_public(
157+
e2e_test_firewall,
158+
instance_with_interface_generation_linode,
159+
):
160+
instance: Instance = instance_with_interface_generation_linode
161+
162+
ip = instance.ip_allocate()
163+
instance
164+
165+
iface = instance.interface_create(
166+
firewall_id=e2e_test_firewall.id,
167+
default_route=LinodeInterfaceDefaultRouteOptions(
168+
ipv4=True,
169+
ipv6=True,
170+
),
171+
public=LinodeInterfacePublicOptions(
172+
ipv4=LinodeInterfacePublicIPv4Options(
173+
addresses=[
174+
LinodeInterfacePublicIPv4AddressOptions(
175+
address=ip.address,
176+
primary=True,
177+
)
178+
]
179+
),
180+
ipv6=LinodeInterfacePublicIPv6Options(
181+
ranges=[LinodeInterfacePublicIPv6RangeOptions()]
182+
),
183+
),
184+
)
185+
186+
assert iface.id is not None
187+
assert iface.linode_id == instance.id
188+
189+
assert iface.created is not None
190+
assert iface.updated is not None
191+
192+
assert isinstance(iface.mac_address, str)
193+
assert iface.version
194+
195+
assert iface.default_route.ipv4
196+
assert iface.default_route.ipv6
197+
198+
assert iface.public.ipv4.addresses[0].address == ip.address
199+
assert iface.public.ipv4.addresses[0].primary
200+
assert len(iface.public.ipv4.shared) == 0
201+
202+
assert iface.public.ipv6.slaac[0].address == instance.ipv6.split("/")[0]
203+
assert iface.public.ipv6.slaac[0].prefix == 64
204+
assert len(iface.public.ipv6.shared) == 0
205+
assert len(iface.public.ipv6.ranges) == 0

0 commit comments

Comments
 (0)