Skip to content

Commit a7a33da

Browse files
Fix merge conflict
2 parents c62f160 + 82a2772 commit a7a33da

File tree

8 files changed

+303
-2
lines changed

8 files changed

+303
-2
lines changed

linode_api4/groups/networking.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
Firewall,
99
FirewallCreateDevicesOptions,
1010
FirewallSettings,
11+
FirewallTemplate,
1112
Instance,
1213
IPAddress,
1314
IPv6Pool,
@@ -114,14 +115,28 @@ def firewall_create(
114115
f = Firewall(self.client, result["id"], result)
115116
return f
116117

117-
def firewall_settings(self) -> FirewallSettings:
118+
def firewall_templates(self, *filters):
118119
"""
119-
Returns an object representing the Linode Firewall settings for the current user.
120+
Returns a list of Firewall Templates available to the current user.
120121
121122
API Documentation: Not yet available.
122123
123124
NOTE: This feature may not currently be available to all users.
124125
126+
:param filters: Any number of filters to apply to this query.
127+
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
128+
for more details on filtering.
129+
130+
:returns: A list of Firewall Templates available to the current user.
131+
:rtype: PaginatedList of FirewallTemplate
132+
"""
133+
return self.client._get_and_filter(FirewallTemplate, *filters)
134+
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.
125140
:returns: An object representing the Linode Firewall settings for the current user.
126141
:rtype: FirewallSettings
127142
"""

linode_api4/objects/networking.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,22 @@ def device_create(self, id, type="linode", **kwargs):
355355
return c
356356

357357

358+
class FirewallTemplate(Base):
359+
"""
360+
Represents a single Linode Firewall template.
361+
362+
API documentation: Not yet available.
363+
364+
NOTE: This feature may not currently be available to all users.
365+
"""
366+
367+
api_endpoint = "/networking/firewalls/templates/{slug}"
368+
369+
id_attribute = "slug"
370+
371+
properties = {"slug": Property(identifier=True), "rules": Property()}
372+
373+
358374
class NetworkTransferPrice(Base):
359375
"""
360376
An NetworkTransferPrice represents the structure of a valid network transfer price.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"data": [
3+
{
4+
"slug": "public",
5+
"rules": {
6+
"outbound": [
7+
{
8+
"action": "ACCEPT",
9+
"addresses": {
10+
"ipv4": [
11+
"192.0.2.0/24",
12+
"198.51.100.2/32"
13+
],
14+
"ipv6": [
15+
"2001:DB8::/128"
16+
]
17+
},
18+
"description": "test",
19+
"label": "test-rule",
20+
"ports": "22-24, 80, 443",
21+
"protocol": "TCP"
22+
}
23+
],
24+
"outbound_policy": "DROP",
25+
"inbound": [
26+
{
27+
"action": "ACCEPT",
28+
"addresses": {
29+
"ipv4": [
30+
"192.0.2.0/24",
31+
"198.51.100.2/32"
32+
],
33+
"ipv6": [
34+
"2001:DB8::/128"
35+
]
36+
},
37+
"description": "test",
38+
"label": "test-rule",
39+
"ports": "22-24, 80, 443",
40+
"protocol": "TCP"
41+
}
42+
],
43+
"inbound_policy": "DROP"
44+
}
45+
},
46+
{
47+
"slug": "vpc",
48+
"rules": {
49+
"outbound": [
50+
{
51+
"action": "ACCEPT",
52+
"addresses": {
53+
"ipv4": [
54+
"192.0.2.0/24",
55+
"198.51.100.2/32"
56+
],
57+
"ipv6": [
58+
"2001:DB8::/128"
59+
]
60+
},
61+
"description": "test",
62+
"label": "test-rule",
63+
"ports": "22-24, 80, 443",
64+
"protocol": "TCP"
65+
}
66+
],
67+
"outbound_policy": "DROP",
68+
"inbound": [
69+
{
70+
"action": "ACCEPT",
71+
"addresses": {
72+
"ipv4": [
73+
"192.0.2.0/24",
74+
"198.51.100.2/32"
75+
],
76+
"ipv6": [
77+
"2001:DB8::/128"
78+
]
79+
},
80+
"description": "test",
81+
"label": "test-rule",
82+
"ports": "22-24, 80, 443",
83+
"protocol": "TCP"
84+
}
85+
],
86+
"inbound_policy": "DROP"
87+
}
88+
}
89+
],
90+
"page": 1,
91+
"pages": 1,
92+
"results": 2
93+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"slug": "public",
3+
"rules": {
4+
"outbound": [
5+
{
6+
"action": "ACCEPT",
7+
"addresses": {
8+
"ipv4": [
9+
"192.0.2.0/24",
10+
"198.51.100.2/32"
11+
],
12+
"ipv6": [
13+
"2001:DB8::/128"
14+
]
15+
},
16+
"description": "test",
17+
"label": "test-rule",
18+
"ports": "22-24, 80, 443",
19+
"protocol": "TCP"
20+
}
21+
],
22+
"outbound_policy": "DROP",
23+
"inbound": [
24+
{
25+
"action": "ACCEPT",
26+
"addresses": {
27+
"ipv4": [
28+
"192.0.2.0/24",
29+
"198.51.100.2/32"
30+
],
31+
"ipv6": [
32+
"2001:DB8::/128"
33+
]
34+
},
35+
"description": "test",
36+
"label": "test-rule",
37+
"ports": "22-24, 80, 443",
38+
"protocol": "TCP"
39+
}
40+
],
41+
"inbound_policy": "DROP"
42+
}
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"slug": "vpc",
3+
"rules": {
4+
"outbound": [
5+
{
6+
"action": "ACCEPT",
7+
"addresses": {
8+
"ipv4": [
9+
"192.0.2.0/24",
10+
"198.51.100.2/32"
11+
],
12+
"ipv6": [
13+
"2001:DB8::/128"
14+
]
15+
},
16+
"description": "test",
17+
"label": "test-rule",
18+
"ports": "22-24, 80, 443",
19+
"protocol": "TCP"
20+
}
21+
],
22+
"outbound_policy": "DROP",
23+
"inbound": [
24+
{
25+
"action": "ACCEPT",
26+
"addresses": {
27+
"ipv4": [
28+
"192.0.2.0/24",
29+
"198.51.100.2/32"
30+
],
31+
"ipv6": [
32+
"2001:DB8::/128"
33+
]
34+
},
35+
"description": "test",
36+
"label": "test-rule",
37+
"ports": "22-24, 80, 443",
38+
"protocol": "TCP"
39+
}
40+
],
41+
"inbound_policy": "DROP"
42+
}
43+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from linode_api4 import FirewallTemplate, MappedObject
2+
3+
4+
def __assert_firewall_template_rules(rules: MappedObject):
5+
# We can't confidently say that these rules will not be changed
6+
# in the future, so we can just do basic assertions here.
7+
assert isinstance(rules.inbound_policy, str)
8+
assert len(rules.inbound_policy) > 0
9+
10+
assert isinstance(rules.outbound_policy, str)
11+
assert len(rules.outbound_policy) > 0
12+
13+
assert isinstance(rules.outbound, list)
14+
assert isinstance(rules.inbound, list)
15+
16+
17+
def test_list_firewall_templates(test_linode_client):
18+
templates = test_linode_client.networking.firewall_templates()
19+
assert len(templates) > 0
20+
21+
for template in templates:
22+
assert isinstance(template.slug, str)
23+
assert len(template.slug) > 0
24+
25+
__assert_firewall_template_rules(template.rules)
26+
27+
28+
def test_get_firewall_template(test_linode_client):
29+
template = test_linode_client.load(FirewallTemplate, "vpc")
30+
31+
assert template.slug == "vpc"
32+
33+
__assert_firewall_template_rules(template.rules)

test/unit/groups/networking_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from test.unit.base import ClientBaseCase
2+
from test.unit.objects.firewall_test import FirewallTemplatesTest
3+
4+
5+
class NetworkingGroupTest(ClientBaseCase):
6+
"""
7+
Tests methods under the NetworkingGroup class.
8+
"""
9+
10+
def test_get_templates(self):
11+
templates = self.client.networking.firewall_templates()
12+
13+
assert templates[0].slug == "public"
14+
FirewallTemplatesTest.assert_rules(templates[0].rules)
15+
16+
assert templates[1].slug == "vpc"
17+
FirewallTemplatesTest.assert_rules(templates[1].rules)

test/unit/objects/firewall_test.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from test.unit.base import ClientBaseCase
22

3+
from linode_api4 import FirewallTemplate, MappedObject
34
from linode_api4.objects import Firewall, FirewallDevice
45

56

@@ -117,3 +118,43 @@ def test_get_device(self):
117118
self.assertEqual(device.entity.url, "/v4/linode/instances/123")
118119

119120
self.assertEqual(device._populated, True)
121+
122+
123+
class FirewallTemplatesTest(ClientBaseCase):
124+
@staticmethod
125+
def assert_rules(rules: MappedObject):
126+
assert rules.outbound_policy == "DROP"
127+
assert len(rules.outbound) == 1
128+
129+
assert rules.inbound_policy == "DROP"
130+
assert len(rules.inbound) == 1
131+
132+
outbound_rule = rules.outbound[0]
133+
assert outbound_rule.action == "ACCEPT"
134+
assert outbound_rule.addresses.ipv4[0] == "192.0.2.0/24"
135+
assert outbound_rule.addresses.ipv4[1] == "198.51.100.2/32"
136+
assert outbound_rule.addresses.ipv6[0] == "2001:DB8::/128"
137+
assert outbound_rule.description == "test"
138+
assert outbound_rule.label == "test-rule"
139+
assert outbound_rule.ports == "22-24, 80, 443"
140+
assert outbound_rule.protocol == "TCP"
141+
142+
inbound_rule = rules.outbound[0]
143+
assert inbound_rule.action == "ACCEPT"
144+
assert inbound_rule.addresses.ipv4[0] == "192.0.2.0/24"
145+
assert inbound_rule.addresses.ipv4[1] == "198.51.100.2/32"
146+
assert inbound_rule.addresses.ipv6[0] == "2001:DB8::/128"
147+
assert inbound_rule.description == "test"
148+
assert inbound_rule.label == "test-rule"
149+
assert inbound_rule.ports == "22-24, 80, 443"
150+
assert inbound_rule.protocol == "TCP"
151+
152+
def test_get_public(self):
153+
template = self.client.load(FirewallTemplate, "public")
154+
assert template.slug == "public"
155+
self.assert_rules(template.rules)
156+
157+
def test_get_vpc(self):
158+
template = self.client.load(FirewallTemplate, "vpc")
159+
assert template.slug == "vpc"
160+
self.assert_rules(template.rules)

0 commit comments

Comments
 (0)