Skip to content

Commit 3672869

Browse files
authored
Bring nodebalancer-related functionality to API parity (#267)
## 📝 Description Add missing fields and methods of node balancer to bring it to API parity. https://jira.linode.com/browse/TPT-1891 ## ✔️ How to Test `tox`
1 parent 1610f83 commit 3672869

4 files changed

Lines changed: 172 additions & 2 deletions

File tree

linode_api4/objects/nodebalancer.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import os
22

33
from linode_api4.errors import UnexpectedResponseError
4-
from linode_api4.objects import Base, DerivedBase, Property, Region
4+
from linode_api4.objects import (
5+
Base,
6+
DerivedBase,
7+
MappedObject,
8+
Property,
9+
Region,
10+
)
511
from linode_api4.objects.networking import IPAddress
612

713

@@ -209,6 +215,8 @@ class NodeBalancer(Base):
209215
"ipv6": Property(),
210216
"region": Property(slug_relationship=Region),
211217
"configs": Property(derived_class=NodeBalancerConfig),
218+
"transfer": Property(),
219+
"tags": Property(),
212220
}
213221

214222
# create derived objects
@@ -239,3 +247,58 @@ def config_create(self, **kwargs):
239247

240248
c = NodeBalancerConfig(self._client, result["id"], self.id, result)
241249
return c
250+
251+
def config_rebuild(self, config_id, nodes, **kwargs):
252+
"""
253+
Rebuilds a NodeBalancer Config and its Nodes that you have permission to modify.
254+
Use this command to update a NodeBalancer’s Config and Nodes with a single request.
255+
256+
API documentation: https://www.linode.com/docs/api/nodebalancers/#config-rebuild
257+
258+
:param config_id: The ID of the Config to access.
259+
:type config_id: int
260+
261+
:param nodes: The NodeBalancer Node(s) that serve this Config.
262+
:type nodes: [{ address: str, id: int, label: str, mode: str, weight: int }]
263+
264+
:returns: A nodebalancer config that rebuilt successfully.
265+
:rtype: NodeBalancerConfig
266+
"""
267+
params = {
268+
"nodes": nodes,
269+
}
270+
params.update(kwargs)
271+
272+
result = self._client.post(
273+
"{}/configs/{}/rebuild".format(
274+
NodeBalancer.api_endpoint, config_id
275+
),
276+
model=self,
277+
data=params,
278+
)
279+
280+
if not "id" in result:
281+
raise UnexpectedResponseError(
282+
"Unexpected response rebuilding config!", json=result
283+
)
284+
285+
return NodeBalancerConfig(self._client, result["id"], self.id, result)
286+
287+
def statistics(self):
288+
"""
289+
Returns detailed statistics about the requested NodeBalancer.
290+
291+
API documentation: https://www.linode.com/docs/api/nodebalancers/#nodebalancer-statistics-view
292+
293+
:returns: The requested stats.
294+
:rtype: MappedObject
295+
"""
296+
result = self._client.get(
297+
"{}/stats".format(NodeBalancer.api_endpoint), model=self
298+
)
299+
300+
if not "title" in result:
301+
raise UnexpectedResponseError(
302+
"Unexpected response generating stats!", json=result
303+
)
304+
return MappedObject(**result)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"algorithm": "roundrobin",
3+
"check": "http_body",
4+
"check_attempts": 3,
5+
"check_body": "it works",
6+
"check_interval": 90,
7+
"check_passive": true,
8+
"check_path": "/test",
9+
"check_timeout": 10,
10+
"cipher_suite": "recommended",
11+
"id": 4567,
12+
"nodebalancer_id": 12345,
13+
"nodes_status": {
14+
"down": 0,
15+
"up": 4
16+
},
17+
"port": 80,
18+
"protocol": "http",
19+
"proxy_protocol": "none",
20+
"ssl_cert": "<REDACTED>",
21+
"ssl_commonname": "www.example.com",
22+
"ssl_fingerprint": "00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F:10:11:12:13",
23+
"ssl_key": "<REDACTED>",
24+
"stickiness": "http_cookie"
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"data": {
3+
"connections": [
4+
null
5+
],
6+
"traffic": {
7+
"in": [
8+
null
9+
],
10+
"out": [
11+
null
12+
]
13+
}
14+
},
15+
"title": "linode.com - balancer12345 (12345) - day (5 min avg)"
16+
}

test/objects/nodebalancers_test.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from test.base import ClientBaseCase
22

3-
from linode_api4.objects import NodeBalancerConfig, NodeBalancerNode
3+
from linode_api4.objects import (
4+
NodeBalancer,
5+
NodeBalancerConfig,
6+
NodeBalancerNode,
7+
)
48
from linode_api4.objects.base import MappedObject
59

610

@@ -128,3 +132,65 @@ def test_delete_node(self):
128132
self.assertEqual(
129133
m.call_url, "/nodebalancers/123456/configs/65432/nodes/54321"
130134
)
135+
136+
def test_config_rebuild(self):
137+
"""
138+
Test that you can rebuild the cofig of a node balancer.
139+
"""
140+
config_rebuild_url = "/nodebalancers/12345/configs/4567/rebuild"
141+
with self.mock_post(config_rebuild_url) as m:
142+
nb = NodeBalancer(self.client, 12345)
143+
nodes = [
144+
{
145+
"id": 54321,
146+
"address": "192.168.210.120:80",
147+
"label": "node1",
148+
"weight": 50,
149+
"mode": "accept",
150+
}
151+
]
152+
153+
result = nb.config_rebuild(
154+
4567,
155+
nodes,
156+
port=1234,
157+
protocol="https",
158+
algorithm="roundrobin",
159+
)
160+
self.assertIsNotNone(result)
161+
self.assertEqual(result.id, 4567)
162+
self.assertEqual(result.nodebalancer_id, 12345)
163+
self.assertEqual(m.call_url, config_rebuild_url)
164+
self.assertEqual(
165+
m.call_data,
166+
{
167+
"port": 1234,
168+
"protocol": "https",
169+
"algorithm": "roundrobin",
170+
"nodes": [
171+
{
172+
"id": 54321,
173+
"address": "192.168.210.120:80",
174+
"label": "node1",
175+
"weight": 50,
176+
"mode": "accept",
177+
},
178+
],
179+
},
180+
)
181+
182+
def test_statistics(self):
183+
"""
184+
Test that you can get the statistics about the requested NodeBalancer.
185+
"""
186+
statistics_url = "/nodebalancers/12345/stats"
187+
with self.mock_get(statistics_url) as m:
188+
nb = NodeBalancer(self.client, 12345)
189+
result = nb.statistics()
190+
191+
self.assertIsNotNone(result)
192+
self.assertEqual(
193+
result.title,
194+
"linode.com - balancer12345 (12345) - day (5 min avg)",
195+
)
196+
self.assertEqual(m.call_url, statistics_url)

0 commit comments

Comments
 (0)