Skip to content

Commit 9ce77ef

Browse files
Enhanced Interfaces: Implement endpoints & fields related to VPCs and non-interface networking (#526)
* Implement endpoints & fields related to VPCs and non-interface networking * Add LA notices
1 parent f42c79f commit 9ce77ef

17 files changed

+376
-36
lines changed

linode_api4/groups/networking.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
from typing import Any, Dict, Optional, Union
2+
13
from linode_api4.errors import UnexpectedResponseError
24
from linode_api4.groups import Group
35
from linode_api4.objects import (
46
VLAN,
57
Base,
68
Firewall,
9+
FirewallCreateDevicesOptions,
10+
FirewallSettings,
711
FirewallTemplate,
812
Instance,
913
IPAddress,
@@ -12,6 +16,8 @@
1216
NetworkTransferPrice,
1317
Region,
1418
)
19+
from linode_api4.objects.base import _flatten_request_body_recursive
20+
from linode_api4.util import drop_null_keys
1521

1622

1723
class NetworkingGroup(Group):
@@ -34,7 +40,15 @@ def firewalls(self, *filters):
3440
"""
3541
return self.client._get_and_filter(Firewall, *filters)
3642

37-
def firewall_create(self, label, rules, **kwargs):
43+
def firewall_create(
44+
self,
45+
label: str,
46+
rules: Dict[str, Any],
47+
devices: Optional[
48+
Union[FirewallCreateDevicesOptions, Dict[str, Any]]
49+
] = None,
50+
**kwargs,
51+
):
3852
"""
3953
Creates a new Firewall, either in the given Region or
4054
attached to the given Instance.
@@ -45,6 +59,8 @@ def firewall_create(self, label, rules, **kwargs):
4559
:type label: str
4660
:param rules: The rules to apply to the new Firewall. For more information on Firewall rules, see our `Firewalls Documentation`_.
4761
:type rules: dict
62+
:param devices: Represents devices to create created alongside a Linode Firewall.
63+
:type devices: Optional[Union[FirewallCreateDevicesOptions, Dict[str, Any]]]
4864
4965
:returns: The new Firewall.
5066
:rtype: Firewall
@@ -82,10 +98,14 @@ def firewall_create(self, label, rules, **kwargs):
8298
params = {
8399
"label": label,
84100
"rules": rules,
101+
"devices": devices,
85102
}
86103
params.update(kwargs)
87104

88-
result = self.client.post("/networking/firewalls", data=params)
105+
result = self.client.post(
106+
"/networking/firewalls",
107+
data=drop_null_keys(_flatten_request_body_recursive(params)),
108+
)
89109

90110
if not "id" in result:
91111
raise UnexpectedResponseError(
@@ -112,6 +132,24 @@ def firewall_templates(self, *filters):
112132
"""
113133
return self.client._get_and_filter(FirewallTemplate, *filters)
114134

135+
def firewall_settings(self) -> FirewallSettings:
136+
"""
137+
Returns an object representing the Linode Firewall settings for the current user.
138+
API Documentation: Not yet available.
139+
NOTE: This feature may not currently be available to all users.
140+
:returns: An object representing the Linode Firewall settings for the current user.
141+
:rtype: FirewallSettings
142+
"""
143+
result = self.client.get("/networking/firewalls/settings")
144+
145+
if "default_firewall_ids" not in result:
146+
raise UnexpectedResponseError(
147+
"Unexpected response when getting firewall settings!",
148+
json=result,
149+
)
150+
151+
return FirewallSettings(self.client, None, result)
152+
115153
def ips(self, *filters):
116154
"""
117155
Returns a list of IP addresses on this account, excluding private addresses.

linode_api4/objects/networking.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from dataclasses import dataclass
2-
from typing import Optional
1+
from dataclasses import dataclass, field
2+
from typing import List, Optional
33

44
from linode_api4.common import Price, RegionPrice
55
from linode_api4.errors import UnexpectedResponseError
@@ -87,6 +87,7 @@ class IPAddress(Base):
8787
"public": Property(),
8888
"rdns": Property(mutable=True),
8989
"linode_id": Property(),
90+
"interface_id": Property(),
9091
"region": Property(slug_relationship=Region),
9192
"vpc_nat_1_1": Property(json_object=InstanceIPNAT1To1),
9293
}
@@ -99,6 +100,8 @@ def linode(self):
99100
self._set("_linode", Instance(self._client, self.linode_id))
100101
return self._linode
101102

103+
# TODO (Enhanced Interfaces): Add `interface` property method
104+
102105
def to(self, linode):
103106
"""
104107
This is a helper method for ip-assign, and should not be used outside
@@ -176,6 +179,51 @@ class VLAN(Base):
176179
}
177180

178181

182+
@dataclass
183+
class FirewallCreateDevicesOptions(JSONObject):
184+
"""
185+
Represents devices to create created alongside a Linode Firewall.
186+
"""
187+
188+
linodes: List[int] = field(default_factory=list)
189+
nodebalancers: List[int] = field(default_factory=list)
190+
interfaces: List[int] = field(default_factory=list)
191+
192+
193+
@dataclass
194+
class FirewallSettingsDefaultFirewallIDs(JSONObject):
195+
"""
196+
Contains the IDs of Linode Firewalls that should be used by default
197+
when creating various interface types.
198+
199+
NOTE: This feature may not currently be available to all users.
200+
"""
201+
202+
vpc_interface: Optional[int] = None
203+
public_interface: Optional[int] = None
204+
linode: Optional[int] = None
205+
nodebalancer: Optional[int] = None
206+
207+
208+
class FirewallSettings(Base):
209+
"""
210+
Represents the Firewall settings for the current user.
211+
212+
API Documentation: Not yet available.
213+
214+
NOTE: This feature may not currently be available to all users.
215+
"""
216+
217+
api_endpoint = "/networking/firewalls/settings"
218+
219+
properties = {
220+
"default_firewall_ids": Property(
221+
json_object=FirewallSettingsDefaultFirewallIDs,
222+
mutable=True,
223+
),
224+
}
225+
226+
179227
class FirewallDevice(DerivedBase):
180228
"""
181229
An object representing the assignment between a Linode Firewall and another Linode resource.

linode_api4/objects/vpc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@dataclass
1212
class VPCSubnetLinodeInterface(JSONObject):
1313
id: int = 0
14+
config_id: Optional[int] = None
1415
active: bool = False
1516

1617

test/fixtures/networking_firewalls_123_devices.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,20 @@
1010
},
1111
"id": 123,
1212
"updated": "2018-01-02T00:01:01"
13+
},
14+
{
15+
"created": "2018-01-01T00:01:01",
16+
"entity": {
17+
"id": 123,
18+
"label": null,
19+
"type": "interface",
20+
"url": "/v4/linode/instances/123/interfaces/123"
21+
},
22+
"id": 456,
23+
"updated": "2018-01-02T00:01:01"
1324
}
1425
],
1526
"page": 1,
1627
"pages": 1,
17-
"results": 1
28+
"results": 2
1829
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"created": "2018-01-01T00:01:01",
3+
"entity": {
4+
"id": 123,
5+
"label": null,
6+
"type": "interface",
7+
"url": "/v4/linode/instances/123/interfaces/123"
8+
},
9+
"id": 456,
10+
"updated": "2018-01-02T00:01:01"
11+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"default_firewall_ids": {
3+
"vpc_interface": 123,
4+
"public_interface": 456,
5+
"linode": 789,
6+
"nodebalancer": 321
7+
}
8+
}

test/fixtures/networking_ips_127.0.0.1.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"address": "127.0.0.1",
33
"gateway": "127.0.0.1",
44
"linode_id": 123,
5+
"interface_id": 456,
56
"prefix": 24,
67
"public": true,
78
"rdns": "test.example.org",

test/fixtures/regions.json

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"capabilities": [
77
"Linodes",
88
"NodeBalancers",
9-
"Block Storage"
9+
"Block Storage",
10+
"Linode Interfaces"
1011
],
1112
"status": "ok",
1213
"resolvers": {
@@ -26,7 +27,8 @@
2627
"capabilities": [
2728
"Linodes",
2829
"NodeBalancers",
29-
"Block Storage"
30+
"Block Storage",
31+
"Linode Interfaces"
3032
],
3133
"status": "ok",
3234
"resolvers": {
@@ -46,7 +48,8 @@
4648
"capabilities": [
4749
"Linodes",
4850
"NodeBalancers",
49-
"Block Storage"
51+
"Block Storage",
52+
"Linode Interfaces"
5053
],
5154
"status": "ok",
5255
"resolvers": {
@@ -62,7 +65,8 @@
6265
"capabilities": [
6366
"Linodes",
6467
"NodeBalancers",
65-
"Block Storage"
68+
"Block Storage",
69+
"Linode Interfaces"
6670
],
6771
"status": "ok",
6872
"resolvers": {
@@ -82,7 +86,8 @@
8286
"capabilities": [
8387
"Linodes",
8488
"NodeBalancers",
85-
"Block Storage"
89+
"Block Storage",
90+
"Linode Interfaces"
8691
],
8792
"status": "ok",
8893
"resolvers": {
@@ -102,7 +107,8 @@
102107
"capabilities": [
103108
"Linodes",
104109
"NodeBalancers",
105-
"Block Storage"
110+
"Block Storage",
111+
"Linode Interfaces"
106112
],
107113
"status": "ok",
108114
"resolvers": {
@@ -123,7 +129,8 @@
123129
"Linodes",
124130
"NodeBalancers",
125131
"Block Storage",
126-
"Object Storage"
132+
"Object Storage",
133+
"Linode Interfaces"
127134
],
128135
"status": "ok",
129136
"resolvers": {
@@ -143,7 +150,8 @@
143150
"capabilities": [
144151
"Linodes",
145152
"NodeBalancers",
146-
"Block Storage"
153+
"Block Storage",
154+
"Linode Interfaces"
147155
],
148156
"status": "ok",
149157
"resolvers": {
@@ -164,7 +172,8 @@
164172
"Linodes",
165173
"NodeBalancers",
166174
"Block Storage",
167-
"Object Storage"
175+
"Object Storage",
176+
"Linode Interfaces"
168177
],
169178
"status": "ok",
170179
"resolvers": {
@@ -185,7 +194,8 @@
185194
"Linodes",
186195
"NodeBalancers",
187196
"Block Storage",
188-
"Object Storage"
197+
"Object Storage",
198+
"Linode Interfaces"
189199
],
190200
"status": "ok",
191201
"resolvers": {
@@ -205,7 +215,8 @@
205215
"capabilities": [
206216
"Linodes",
207217
"NodeBalancers",
208-
"Block Storage"
218+
"Block Storage",
219+
"Linode Interfaces"
209220
],
210221
"status": "ok",
211222
"resolvers": {

test/fixtures/vpcs_123456_subnets.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
"interfaces": [
1111
{
1212
"id": 678,
13-
"active": true
13+
"active": true,
14+
"config_id": null
1415
},
1516
{
1617
"id": 543,
17-
"active": false
18+
"active": false,
19+
"config_id": null
1820
}
1921
]
2022
}

test/fixtures/vpcs_123456_subnets_789.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
"interfaces": [
99
{
1010
"id": 678,
11-
"active": true
11+
"active": true,
12+
"config_id": null
1213
},
1314
{
1415
"id": 543,
15-
"active": false
16+
"active": false,
17+
"config_id": null
1618
}
1719
]
1820
}

test/integration/linode_client/test_linode_client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
import pytest
77

88
from linode_api4 import ApiError
9-
from linode_api4.objects import ConfigInterface, ObjectStorageKeys, Region
9+
from linode_api4.objects import (
10+
ConfigInterface,
11+
ObjectStorageKeys,
12+
Region,
13+
)
1014

1115

1216
@pytest.fixture(scope="session")

0 commit comments

Comments
 (0)