Skip to content

Commit 2d23cef

Browse files
Add support for Nodebalancers UDP (#494)
* Implemented changes for NodeBalancers UDP * Added unit tests * Fix lint * Fixed issue with cipher_suite in save * Lint * Addressed PR comments * Removed overriden _serialize method
1 parent f1fa70e commit 2d23cef

File tree

5 files changed

+203
-3
lines changed

5 files changed

+203
-3
lines changed

linode_api4/objects/nodebalancer.py

+36
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class NodeBalancerConfig(DerivedBase):
9797
"check_path": Property(mutable=True),
9898
"check_body": Property(mutable=True),
9999
"check_passive": Property(mutable=True),
100+
"udp_check_port": Property(mutable=True),
101+
"udp_session_timeout": Property(),
100102
"ssl_cert": Property(mutable=True),
101103
"ssl_key": Property(mutable=True),
102104
"ssl_commonname": Property(),
@@ -106,6 +108,39 @@ class NodeBalancerConfig(DerivedBase):
106108
"proxy_protocol": Property(mutable=True),
107109
}
108110

111+
def save(self, force=True) -> bool:
112+
"""
113+
Send this NodeBalancerConfig's mutable values to the server in a PUT request.
114+
:param force: If true, this method will always send a PUT request regardless of
115+
whether the field has been explicitly updated. For optimization
116+
purposes, this field should be set to false for typical update
117+
operations. (Defaults to True)
118+
:type force: bool
119+
"""
120+
121+
if not force and not self._changed:
122+
return False
123+
124+
data = self._serialize()
125+
126+
print(data)
127+
128+
if data.get("protocol") == "udp" and "cipher_suite" in data:
129+
data.pop("cipher_suite")
130+
131+
print(data)
132+
133+
result = self._client.put(
134+
NodeBalancerConfig.api_endpoint, model=self, data=data
135+
)
136+
137+
if "error" in result:
138+
return False
139+
140+
self._populate(result)
141+
142+
return True
143+
109144
@property
110145
def nodes(self):
111146
"""
@@ -233,6 +268,7 @@ class NodeBalancer(Base):
233268
"configs": Property(derived_class=NodeBalancerConfig),
234269
"transfer": Property(),
235270
"tags": Property(mutable=True, unordered=True),
271+
"client_udp_sess_throttle": Property(mutable=True),
236272
}
237273

238274
# create derived objects

test/fixtures/nodebalancers_123456_configs.json

+27-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,35 @@
2424
"protocol": "http",
2525
"ssl_fingerprint": "",
2626
"proxy_protocol": "none"
27+
},
28+
{
29+
"check": "connection",
30+
"check_attempts": 2,
31+
"stickiness": "table",
32+
"check_interval": 5,
33+
"check_body": "",
34+
"id": 65431,
35+
"check_passive": true,
36+
"algorithm": "roundrobin",
37+
"check_timeout": 3,
38+
"check_path": "/",
39+
"ssl_cert": null,
40+
"ssl_commonname": "",
41+
"port": 80,
42+
"nodebalancer_id": 123456,
43+
"cipher_suite": "none",
44+
"ssl_key": null,
45+
"nodes_status": {
46+
"up": 0,
47+
"down": 0
48+
},
49+
"protocol": "udp",
50+
"ssl_fingerprint": "",
51+
"proxy_protocol": "none",
52+
"udp_check_port": 12345
2753
}
2854
],
29-
"results": 1,
55+
"results": 2,
3056
"page": 1,
3157
"pages": 1
3258
}

test/fixtures/nodebalancers_123456_configs_65432_nodes.json

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,19 @@
99
"mode": "accept",
1010
"config_id": 54321,
1111
"nodebalancer_id": 123456
12+
},
13+
{
14+
"id": 12345,
15+
"address": "192.168.210.120",
16+
"label": "node12345",
17+
"status": "UP",
18+
"weight": 50,
19+
"mode": "none",
20+
"config_id": 123456,
21+
"nodebalancer_id": 123456
1222
}
1323
],
1424
"pages": 1,
1525
"page": 1,
16-
"results": 1
26+
"results": 2
1727
}

test/integration/models/nodebalancer/test_nodebalancer.py

+109-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import pytest
1111

12-
from linode_api4 import ApiError, LinodeClient
12+
from linode_api4 import ApiError, LinodeClient, NodeBalancer
1313
from linode_api4.objects import (
1414
NodeBalancerConfig,
1515
NodeBalancerNode,
@@ -64,6 +64,55 @@ def create_nb_config(test_linode_client, e2e_test_firewall):
6464
nb.delete()
6565

6666

67+
@pytest.fixture(scope="session")
68+
def create_nb_config_with_udp(test_linode_client, e2e_test_firewall):
69+
client = test_linode_client
70+
label = get_test_label(8)
71+
72+
nb = client.nodebalancer_create(
73+
region=TEST_REGION, label=label, firewall=e2e_test_firewall.id
74+
)
75+
76+
config = nb.config_create(protocol="udp", udp_check_port=1234)
77+
78+
yield config
79+
80+
config.delete()
81+
nb.delete()
82+
83+
84+
@pytest.fixture(scope="session")
85+
def create_nb(test_linode_client, e2e_test_firewall):
86+
client = test_linode_client
87+
label = get_test_label(8)
88+
89+
nb = client.nodebalancer_create(
90+
region=TEST_REGION, label=label, firewall=e2e_test_firewall.id
91+
)
92+
93+
yield nb
94+
95+
nb.delete()
96+
97+
98+
def test_create_nb(test_linode_client, e2e_test_firewall):
99+
client = test_linode_client
100+
label = get_test_label(8)
101+
102+
nb = client.nodebalancer_create(
103+
region=TEST_REGION,
104+
label=label,
105+
firewall=e2e_test_firewall.id,
106+
client_udp_sess_throttle=5,
107+
)
108+
109+
assert TEST_REGION, nb.region
110+
assert label == nb.label
111+
assert 5 == nb.client_udp_sess_throttle
112+
113+
nb.delete()
114+
115+
67116
def test_get_nodebalancer_config(test_linode_client, create_nb_config):
68117
config = test_linode_client.load(
69118
NodeBalancerConfig,
@@ -72,6 +121,65 @@ def test_get_nodebalancer_config(test_linode_client, create_nb_config):
72121
)
73122

74123

124+
def test_get_nb_config_with_udp(test_linode_client, create_nb_config_with_udp):
125+
config = test_linode_client.load(
126+
NodeBalancerConfig,
127+
create_nb_config_with_udp.id,
128+
create_nb_config_with_udp.nodebalancer_id,
129+
)
130+
131+
assert "udp" == config.protocol
132+
assert 1234 == config.udp_check_port
133+
assert 16 == config.udp_session_timeout
134+
135+
136+
def test_update_nb_config(test_linode_client, create_nb_config_with_udp):
137+
config = test_linode_client.load(
138+
NodeBalancerConfig,
139+
create_nb_config_with_udp.id,
140+
create_nb_config_with_udp.nodebalancer_id,
141+
)
142+
143+
config.udp_check_port = 4321
144+
config.save()
145+
146+
config_updated = test_linode_client.load(
147+
NodeBalancerConfig,
148+
create_nb_config_with_udp.id,
149+
create_nb_config_with_udp.nodebalancer_id,
150+
)
151+
152+
assert 4321 == config_updated.udp_check_port
153+
154+
155+
def test_get_nb(test_linode_client, create_nb):
156+
nb = test_linode_client.load(
157+
NodeBalancer,
158+
create_nb.id,
159+
)
160+
161+
assert nb.id == create_nb.id
162+
163+
164+
def test_update_nb(test_linode_client, create_nb):
165+
nb = test_linode_client.load(
166+
NodeBalancer,
167+
create_nb.id,
168+
)
169+
170+
nb.label = "ThisNewLabel"
171+
nb.client_udp_sess_throttle = 5
172+
nb.save()
173+
174+
nb_updated = test_linode_client.load(
175+
NodeBalancer,
176+
create_nb.id,
177+
)
178+
179+
assert "ThisNewLabel" == nb_updated.label
180+
assert 5 == nb_updated.client_udp_sess_throttle
181+
182+
75183
@pytest.mark.smoke
76184
def test_create_nb_node(
77185
test_linode_client, create_nb_config, linode_with_private_ip

test/unit/objects/nodebalancers_test.py

+20
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ def test_get_config(self):
4242
self.assertEqual(config.ssl_fingerprint, "")
4343
self.assertEqual(config.proxy_protocol, "none")
4444

45+
config_udp = NodeBalancerConfig(self.client, 65431, 123456)
46+
self.assertEqual(config_udp.protocol, "udp")
47+
self.assertEqual(config_udp.udp_check_port, 12345)
48+
49+
def test_update_config_udp(self):
50+
"""
51+
Tests that a config with a protocol of udp can be updated and that cipher suite is properly excluded in save()
52+
"""
53+
with self.mock_put("nodebalancers/123456/configs/65431") as m:
54+
config = self.client.load(NodeBalancerConfig, 65431, 123456)
55+
config.udp_check_port = 54321
56+
config.save()
57+
58+
self.assertEqual(m.call_url, "/nodebalancers/123456/configs/65431")
59+
self.assertEqual(m.call_data["udp_check_port"], 54321)
60+
self.assertNotIn("cipher_suite", m.call_data)
61+
4562

4663
class NodeBalancerNodeTest(ClientBaseCase):
4764
"""
@@ -66,6 +83,9 @@ def test_get_node(self):
6683
self.assertEqual(node.config_id, 65432)
6784
self.assertEqual(node.nodebalancer_id, 123456)
6885

86+
node_udp = NodeBalancerNode(self.client, 12345, (65432, 123456))
87+
self.assertEqual(node_udp.mode, "none")
88+
6989
def test_create_node(self):
7090
"""
7191
Tests that a node can be created

0 commit comments

Comments
 (0)