Merge ~bjornt/maas:api-better-tests into maas:master

Proposed by Björn Tillenius
Status: Merged
Approved by: Björn Tillenius
Approved revision: 6cea490cb6d91dedbdf2e984fa668589495d307f
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~bjornt/maas:api-better-tests
Merge into: maas:master
Diff against target: 854 lines (+486/-162)
4 files modified
src/maasserver/api/tests/test_interfaces.py (+210/-57)
src/maasserver/api/tests/test_subnets.py (+146/-30)
src/maasserver/api/tests/test_vlans.py (+128/-75)
src/maasserver/testing/factory.py (+2/-0)
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
MAAS Lander Needs Fixing
Review via email: mp+419448@code.launchpad.net

Commit message

Add some more tests for the API handlers.

This is in preparation for changing the way we generate the JSON
representation.

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b api-better-tests lp:~bjornt/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12366/console
COMMIT: e91fd87abc9b6a05657fd1db21c32373ea32b9d7

review: Needs Fixing
Revision history for this message
Adam Collard (adam-collard) :
review: Approve
~bjornt/maas:api-better-tests updated
6cea490... by Björn Tillenius

Fix test failures.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/tests/test_interfaces.py b/src/maasserver/api/tests/test_interfaces.py
2index 89c6171..5b17370 100644
3--- a/src/maasserver/api/tests/test_interfaces.py
4+++ b/src/maasserver/api/tests/test_interfaces.py
5@@ -26,6 +26,7 @@ from maasserver.enum import (
6 NODE_TYPE,
7 )
8 from maasserver.models import Interface
9+from maasserver.models.vlan import DEFAULT_MTU
10 from maasserver.testing.api import APITestCase, APITransactionTestCase
11 from maasserver.testing.factory import factory
12 from maasserver.utils.converters import json_load_bytes
13@@ -60,6 +61,44 @@ def get_interface_uri(interface, node=None):
14 return reverse("interface_handler", args=[node.system_id, interface])
15
16
17+def serialize_vlan(vlan):
18+ return {
19+ "id": vlan.id,
20+ "dhcp_on": vlan.dhcp_on,
21+ "external_dhcp": vlan.external_dhcp,
22+ "fabric": vlan.fabric.get_name(),
23+ "fabric_id": vlan.fabric_id,
24+ "mtu": vlan.mtu,
25+ "primary_rack": None,
26+ "secondary_rack": None,
27+ "space": "undefined" if not vlan.space else vlan.space.get_name(),
28+ "vid": vlan.vid,
29+ "name": vlan.get_name(),
30+ "relay_vlan": None,
31+ "resource_uri": f"/MAAS/api/2.0/vlans/{vlan.id}/",
32+ }
33+
34+
35+def serialize_subnet(subnet):
36+ return {
37+ "name": subnet.name,
38+ "id": subnet.id,
39+ "vlan": serialize_vlan(subnet.vlan),
40+ "description": "",
41+ "cidr": subnet.cidr,
42+ "rdns_mode": subnet.rdns_mode,
43+ "gateway_ip": subnet.gateway_ip,
44+ "dns_servers": subnet.dns_servers,
45+ "allow_dns": subnet.allow_dns,
46+ "allow_proxy": subnet.allow_proxy,
47+ "active_discovery": subnet.active_discovery,
48+ "managed": subnet.managed,
49+ "disabled_boot_architectures": subnet.disabled_boot_architectures,
50+ "space": "undefined" if not subnet.space else subnet.space.get_name(),
51+ "resource_uri": f"/MAAS/api/2.0/subnets/{subnet.id}/",
52+ }
53+
54+
55 def make_complex_interface(node, name=None):
56 """Makes interface with parents and children."""
57 fabric = factory.make_Fabric()
58@@ -887,14 +926,113 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser):
59 get_interface_uri(interface, node=node),
60 )
61
62+ def test_read_basic(self):
63+ node = factory.make_Node()
64+ interface = factory.make_Interface(
65+ node=node,
66+ name="eno1",
67+ iftype=INTERFACE_TYPE.PHYSICAL,
68+ mac_address="11:11:11:11:11:11",
69+ enabled=False,
70+ vendor="my-vendor",
71+ product="my-product",
72+ firmware_version="1.2.3",
73+ link_connected=False,
74+ vlan=None,
75+ interface_speed=100,
76+ sriov_max_vf=0,
77+ tags=[],
78+ )
79+
80+ uri = get_interface_uri(interface)
81+ response = self.client.get(uri)
82+ self.assertEqual(
83+ http.client.OK, response.status_code, response.content
84+ )
85+ parsed_interface = json_load_bytes(response.content)
86+ self.maxDiff = None
87+ self.assertEqual(
88+ {
89+ "system_id": node.system_id,
90+ "id": interface.id,
91+ "name": "eno1",
92+ "type": INTERFACE_TYPE.PHYSICAL,
93+ "vlan": None,
94+ "mac_address": "11:11:11:11:11:11",
95+ "parents": [],
96+ "children": [],
97+ "tags": [],
98+ "enabled": False,
99+ "links": [],
100+ "params": "",
101+ "discovered": None,
102+ "effective_mtu": DEFAULT_MTU,
103+ "vendor": "my-vendor",
104+ "product": "my-product",
105+ "firmware_version": "1.2.3",
106+ "link_connected": False,
107+ "interface_speed": 100,
108+ "link_speed": 0,
109+ "numa_node": 0,
110+ "sriov_max_vf": 0,
111+ "resource_uri": (
112+ f"/MAAS/api/2.0/nodes/{node.system_id}/interfaces/{interface.id}/"
113+ ),
114+ },
115+ parsed_interface,
116+ )
117+
118+ def test_read_connected(self):
119+ vlan = factory.make_VLAN(name="my-vlan", mtu=1234)
120+ interface = factory.make_Interface(
121+ enabled=True,
122+ link_connected=True,
123+ vlan=vlan,
124+ interface_speed=100,
125+ link_speed=10,
126+ tags=["foo", "bar"],
127+ )
128+
129+ uri = get_interface_uri(interface)
130+ response = self.client.get(uri)
131+ self.assertEqual(
132+ http.client.OK, response.status_code, response.content
133+ )
134+ parsed_interface = json_load_bytes(response.content)
135+ expected_parts = {
136+ "id": interface.id,
137+ "tags": ["foo", "bar"],
138+ "enabled": True,
139+ "discovered": None,
140+ "effective_mtu": 1234,
141+ "link_connected": True,
142+ "interface_speed": 100,
143+ "link_speed": 10,
144+ "vlan": {
145+ "id": vlan.id,
146+ "dhcp_on": vlan.dhcp_on,
147+ "external_dhcp": vlan.external_dhcp,
148+ "fabric": vlan.fabric.get_name(),
149+ "fabric_id": vlan.fabric_id,
150+ "mtu": vlan.mtu,
151+ "primary_rack": None,
152+ "secondary_rack": None,
153+ "space": "undefined",
154+ "vid": vlan.vid,
155+ "name": vlan.get_name(),
156+ "relay_vlan": None,
157+ "resource_uri": f"/MAAS/api/2.0/vlans/{vlan.id}/",
158+ },
159+ }
160+ for key, value in expected_parts.items():
161+ self.assertEqual(parsed_interface[key], value)
162+
163 def test_read(self):
164 node = factory.make_Node()
165 bond, parents, children = make_complex_interface(node)
166- # Add some known links to the bond interface.
167
168- # First link is a DHCP link.
169- links = []
170- dhcp_subnet = factory.make_Subnet()
171+ # Add some known links to the bond interface.
172+ dhcp_subnet = factory.make_Subnet(vlan=bond.vlan)
173 dhcp_ip = factory.make_StaticIPAddress(
174 alloc_type=IPADDRESS_TYPE.DHCP,
175 ip="",
176@@ -908,19 +1046,9 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser):
177 subnet=dhcp_subnet,
178 interface=bond,
179 )
180- links.append(
181- MatchesDict(
182- {
183- "id": Equals(dhcp_ip.id),
184- "mode": Equals(INTERFACE_LINK_TYPE.DHCP),
185- "subnet": ContainsDict({"id": Equals(dhcp_subnet.id)}),
186- "ip_address": Equals(discovered_ip),
187- }
188- )
189- )
190
191 # Second link is a STATIC ip link.
192- static_subnet = factory.make_Subnet()
193+ static_subnet = factory.make_Subnet(vlan=bond.vlan)
194 static_ip = factory.pick_ip_in_network(static_subnet.get_ipnetwork())
195 sip = factory.make_StaticIPAddress(
196 alloc_type=IPADDRESS_TYPE.STICKY,
197@@ -928,40 +1056,21 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser):
198 subnet=static_subnet,
199 interface=bond,
200 )
201- links.append(
202- MatchesDict(
203- {
204- "id": Equals(sip.id),
205- "mode": Equals(INTERFACE_LINK_TYPE.STATIC),
206- "ip_address": Equals(static_ip),
207- "subnet": ContainsDict({"id": Equals(static_subnet.id)}),
208- }
209- )
210- )
211
212 # Third link is just a LINK_UP. In reality this cannot exist while the
213 # other two links exist but for testing we allow it. If validation of
214 # the StaticIPAddress model ever included this check, which it
215 # probably should then this will fail and cause this test to break.
216- link_subnet = factory.make_Subnet()
217+ link_subnet = factory.make_Subnet(vlan=bond.vlan)
218 link_ip = factory.make_StaticIPAddress(
219 alloc_type=IPADDRESS_TYPE.STICKY,
220 ip="",
221 subnet=link_subnet,
222 interface=bond,
223 )
224- links.append(
225- MatchesDict(
226- {
227- "id": Equals(link_ip.id),
228- "mode": Equals(INTERFACE_LINK_TYPE.LINK_UP),
229- "subnet": ContainsDict({"id": Equals(link_subnet.id)}),
230- }
231- )
232- )
233
234 # Add MTU parameter.
235- bond.params = {"mtu": random.randint(800, 2000)}
236+ bond.params = {"mtu": 1234}
237 bond.save()
238
239 uri = get_interface_uri(bond)
240@@ -970,33 +1079,77 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser):
241 http.client.OK, response.status_code, response.content
242 )
243 parsed_interface = json_load_bytes(response.content)
244- self.assertThat(
245- parsed_interface,
246- ContainsDict(
247- {
248- "id": Equals(bond.id),
249- "name": Equals(bond.name),
250- "type": Equals(bond.type),
251- "vlan": ContainsDict({"id": Equals(bond.vlan.id)}),
252- "mac_address": Equals("%s" % bond.mac_address),
253- "tags": Equals(bond.tags),
254- "resource_uri": Equals(get_interface_uri(bond)),
255- "params": Equals(bond.params),
256- "effective_mtu": Equals(bond.get_effective_mtu()),
257- "system_id": Equals(node.system_id),
258- }
259- ),
260- )
261+
262+ expected_parts = {
263+ "id": bond.id,
264+ "name": bond.name,
265+ "type": bond.type,
266+ "mac_address": str(bond.mac_address),
267+ "vlan": serialize_vlan(bond.vlan),
268+ "tags": bond.tags,
269+ "resource_uri": get_interface_uri(bond),
270+ "params": {"mtu": 1234},
271+ "effective_mtu": 1500,
272+ "system_id": node.system_id,
273+ }
274+ for key, value in expected_parts.items():
275+ self.assertEqual(parsed_interface[key], value)
276 self.assertEqual(
277 sorted(nic.name for nic in parents), parsed_interface["parents"]
278 )
279 self.assertEqual(
280 sorted(nic.name for nic in children), parsed_interface["children"]
281 )
282- self.assertThat(parsed_interface["links"], MatchesSetwise(*links))
283- json_discovered = parsed_interface["discovered"][0]
284- self.assertEqual(dhcp_subnet.id, json_discovered["subnet"]["id"])
285- self.assertEqual(discovered_ip, json_discovered["ip_address"])
286+
287+ self.assertEqual(
288+ [
289+ {
290+ "id": dhcp_ip.id,
291+ "mode": "dhcp",
292+ "ip_address": discovered_ip,
293+ "subnet": serialize_subnet(dhcp_subnet),
294+ },
295+ {
296+ "id": sip.id,
297+ "mode": "static",
298+ "ip_address": static_ip,
299+ "subnet": serialize_subnet(static_subnet),
300+ },
301+ {
302+ "id": link_ip.id,
303+ "mode": "link_up",
304+ "subnet": serialize_subnet(link_subnet),
305+ },
306+ ],
307+ parsed_interface["links"],
308+ )
309+ self.assertEqual(
310+ [
311+ {
312+ "ip_address": discovered_ip,
313+ "subnet": serialize_subnet(dhcp_subnet),
314+ },
315+ ],
316+ parsed_interface["discovered"],
317+ )
318+
319+ def test_read_effective_mtu(self):
320+ node = factory.make_Node()
321+ bond, parents, children = make_complex_interface(node)
322+ bond.params = {"mtu": 1000}
323+ bond.save()
324+ children[0].params = {"mtu": 2000}
325+ children[0].save()
326+
327+ uri = get_interface_uri(bond)
328+ response = self.client.get(uri)
329+ self.assertEqual(
330+ http.client.OK, response.status_code, response.content
331+ )
332+ parsed_interface = json_load_bytes(response.content)
333+
334+ self.assertEqual(bond.id, parsed_interface["id"])
335+ self.assertEqual(2000, parsed_interface["effective_mtu"])
336
337 def test_read_by_specifier(self):
338 node = factory.make_Node(hostname="tasty-biscuits")
339diff --git a/src/maasserver/api/tests/test_subnets.py b/src/maasserver/api/tests/test_subnets.py
340index c85dede..2fc8cad 100644
341--- a/src/maasserver/api/tests/test_subnets.py
342+++ b/src/maasserver/api/tests/test_subnets.py
343@@ -8,12 +8,18 @@ import random
344
345 from django.conf import settings
346 from django.urls import reverse
347-from testtools.matchers import Contains, ContainsDict, Equals
348-
349-from maasserver.enum import IPADDRESS_TYPE, NODE_STATUS, RDNS_MODE_CHOICES
350+from testtools.matchers import Contains, Equals
351+
352+from maasserver.enum import (
353+ IPADDRESS_TYPE,
354+ NODE_STATUS,
355+ RDNS_MODE,
356+ RDNS_MODE_CHOICES,
357+)
358 from maasserver.testing.api import APITestCase, explain_unexpected_response
359-from maasserver.testing.factory import factory, RANDOM
360+from maasserver.testing.factory import factory
361 from maasserver.utils.orm import reload_object
362+from maastesting.djangotestcase import CountQueries
363 from provisioningserver.boot import BootMethodRegistry
364 from provisioningserver.utils.network import inet_ntop, IPRangeStatistics
365
366@@ -36,21 +42,58 @@ class TestSubnetsAPI(APITestCase.ForUser):
367 self.assertEqual("/MAAS/api/2.0/subnets/", get_subnets_uri())
368
369 def test_read(self):
370- subnets = [factory.make_Subnet() for _ in range(3)]
371+ def make_subnet():
372+ space = factory.make_Space()
373+ subnet = factory.make_Subnet(space=space)
374+ primary_rack = factory.make_RackController(subnet=subnet)
375+ secondary_rack = factory.make_RackController(subnet=subnet)
376+ relay_vlan = factory.make_VLAN()
377+ vlan = subnet.vlan
378+ vlan.dhcp_on = True
379+ vlan.primary_rack = primary_rack
380+ vlan.secondary_rack = secondary_rack
381+ vlan.relay_vlan = relay_vlan
382+ vlan.save()
383+ return subnet
384+
385+ subnets = [make_subnet()]
386 uri = get_subnets_uri()
387- response = self.client.get(uri)
388+ with CountQueries() as counter:
389+ response = self.client.get(uri)
390+ base_count = counter.count
391
392 self.assertEqual(
393 http.client.OK, response.status_code, response.content
394 )
395- expected_ids = [subnet.id for subnet in subnets]
396+
397 result_ids = [
398 subnet["id"]
399 for subnet in json.loads(
400 response.content.decode(settings.DEFAULT_CHARSET)
401 )
402 ]
403- self.assertCountEqual(expected_ids, result_ids)
404+ self.assertCountEqual(
405+ [subnet.id for subnet in subnets],
406+ result_ids,
407+ json.loads(response.content.decode(settings.DEFAULT_CHARSET)),
408+ )
409+
410+ subnets.append(make_subnet())
411+ with CountQueries() as counter:
412+ response = self.client.get(uri)
413+ # XXX: These should be the same.
414+ self.assertEqual(base_count + 7, counter.count)
415+
416+ self.assertEqual(
417+ http.client.OK, response.status_code, response.content
418+ )
419+ result_ids = [
420+ subnet["id"]
421+ for subnet in json.loads(
422+ response.content.decode(settings.DEFAULT_CHARSET)
423+ )
424+ ]
425+ self.assertCountEqual([subnet.id for subnet in subnets], result_ids)
426
427 def test_create(self):
428 self.become_admin()
429@@ -269,8 +312,15 @@ class TestSubnetAPI(APITestCase.ForUser):
430 "/MAAS/api/2.0/subnets/%s/" % subnet.id, get_subnet_uri(subnet)
431 )
432
433- def test_read(self):
434- subnet = factory.make_Subnet(space=RANDOM)
435+ def test_read_basic(self):
436+ subnet = factory.make_Subnet(
437+ name="my-subnet",
438+ cidr="10.10.10.0/24",
439+ gateway_ip=None,
440+ space=None,
441+ dns_servers=[],
442+ disabled_boot_architectures=[],
443+ )
444 uri = get_subnet_uri(subnet)
445 response = self.client.get(uri)
446
447@@ -280,34 +330,100 @@ class TestSubnetAPI(APITestCase.ForUser):
448 parsed_subnet = json.loads(
449 response.content.decode(settings.DEFAULT_CHARSET)
450 )
451- self.assertThat(
452+ self.assertEqual(
453 parsed_subnet,
454- ContainsDict(
455- {
456- "id": Equals(subnet.id),
457- "name": Equals(subnet.name),
458- "vlan": ContainsDict({"vid": Equals(subnet.vlan.vid)}),
459- "space": Equals(subnet.space.get_name()),
460- "cidr": Equals(subnet.cidr),
461- "gateway_ip": Equals(subnet.gateway_ip),
462- "dns_servers": Equals(subnet.dns_servers),
463- "managed": Equals(subnet.managed),
464- "disabled_boot_architectures": Equals(
465- subnet.disabled_boot_architectures
466- ),
467- }
468- ),
469+ {
470+ "id": subnet.id,
471+ "name": "my-subnet",
472+ "active_discovery": False,
473+ "allow_dns": True,
474+ "allow_proxy": True,
475+ "description": "",
476+ "space": "undefined",
477+ "cidr": "10.10.10.0/24",
478+ "gateway_ip": None,
479+ "dns_servers": [],
480+ "managed": True,
481+ "disabled_boot_architectures": [],
482+ "rdns_mode": RDNS_MODE.DEFAULT,
483+ "resource_uri": f"/MAAS/api/2.0/subnets/{subnet.id}/",
484+ "vlan": {
485+ "id": subnet.vlan_id,
486+ "dhcp_on": subnet.vlan.dhcp_on,
487+ "external_dhcp": subnet.vlan.external_dhcp,
488+ "fabric": subnet.vlan.fabric.get_name(),
489+ "fabric_id": subnet.vlan.fabric_id,
490+ "mtu": subnet.vlan.mtu,
491+ "primary_rack": None,
492+ "secondary_rack": None,
493+ "space": "undefined",
494+ "vid": subnet.vlan.vid,
495+ "name": subnet.vlan.get_name(),
496+ "relay_vlan": None,
497+ "resource_uri": f"/MAAS/api/2.0/vlans/{subnet.vlan_id}/",
498+ },
499+ },
500 )
501
502- def test_read_includes_description(self):
503- description = factory.make_string()
504- subnet = factory.make_Subnet(space=RANDOM, description=description)
505+ def test_read_full(self):
506+ space = factory.make_Space(name="my-space")
507+ subnet = factory.make_Subnet(
508+ name="my-subnet",
509+ cidr="10.20.20.0/24",
510+ gateway_ip="10.20.20.1",
511+ space=space,
512+ dns_servers=["10.20.20.20"],
513+ disabled_boot_architectures=["pxe"],
514+ active_discovery=True,
515+ allow_proxy=False,
516+ allow_dns=False,
517+ description="My subnet",
518+ managed=False,
519+ rdns_mode=RDNS_MODE.DISABLED,
520+ )
521 uri = get_subnet_uri(subnet)
522 response = self.client.get(uri)
523+
524+ self.assertEqual(
525+ http.client.OK, response.status_code, response.content
526+ )
527 parsed_subnet = json.loads(
528 response.content.decode(settings.DEFAULT_CHARSET)
529 )
530- self.assertEqual(description, parsed_subnet["description"])
531+ self.assertEqual(
532+ parsed_subnet,
533+ {
534+ "id": subnet.id,
535+ "name": "my-subnet",
536+ "active_discovery": True,
537+ "allow_dns": False,
538+ "allow_proxy": False,
539+ "description": "My subnet",
540+ "space": "my-space",
541+ "cidr": "10.20.20.0/24",
542+ "gateway_ip": "10.20.20.1",
543+ "dns_servers": ["10.20.20.20"],
544+ "managed": False,
545+ "disabled_boot_architectures": ["pxe"],
546+ "rdns_mode": RDNS_MODE.DISABLED,
547+ "resource_uri": f"/MAAS/api/2.0/subnets/{subnet.id}/",
548+ "vlan": {
549+ "id": subnet.vlan_id,
550+ "dhcp_on": subnet.vlan.dhcp_on,
551+ "external_dhcp": subnet.vlan.external_dhcp,
552+ "fabric": subnet.vlan.fabric.get_name(),
553+ "fabric_id": subnet.vlan.fabric_id,
554+ "mtu": subnet.vlan.mtu,
555+ "primary_rack": None,
556+ "secondary_rack": None,
557+ "space": "my-space",
558+ "vid": subnet.vlan.vid,
559+ "name": subnet.vlan.get_name(),
560+ "relay_vlan": None,
561+ "resource_uri": f"/MAAS/api/2.0/vlans/{subnet.vlan_id}/",
562+ },
563+ },
564+ )
565
566 def test_read_404_when_bad_id(self):
567 uri = reverse("subnet_handler", args=[random.randint(100, 1000)])
568diff --git a/src/maasserver/api/tests/test_vlans.py b/src/maasserver/api/tests/test_vlans.py
569index 2296787..38665d2 100644
570--- a/src/maasserver/api/tests/test_vlans.py
571+++ b/src/maasserver/api/tests/test_vlans.py
572@@ -10,12 +10,13 @@ import random
573
574 from django.conf import settings
575 from django.urls import reverse
576-from testtools.matchers import ContainsDict, Equals, Is, Not
577+from testtools.matchers import Equals, Is, Not
578
579-from maasserver.models import Space
580+from maasserver.models import Space, VLAN
581 from maasserver.testing.api import APITestCase
582 from maasserver.testing.factory import factory, RANDOM
583 from maasserver.utils.orm import reload_object
584+from maastesting.djangotestcase import CountQueries
585
586
587 def get_vlans_uri(fabric):
588@@ -41,23 +42,71 @@ class TestVlansAPI(APITestCase.ForUser):
589 )
590
591 def test_read(self):
592+ def make_vlan():
593+ space = factory.make_Space()
594+ subnet = factory.make_Subnet(fabric=fabric, space=space)
595+ primary_rack = factory.make_RackController()
596+ factory.make_Interface(node=primary_rack, subnet=subnet)
597+ secondary_rack = factory.make_RackController()
598+ factory.make_Interface(node=secondary_rack, subnet=subnet)
599+ relay_vlan = factory.make_VLAN()
600+ vlan = subnet.vlan
601+ vlan.dhcp_on = True
602+ vlan.primary_rack = primary_rack
603+ vlan.secondary_rack = secondary_rack
604+ vlan.relay_vlan = relay_vlan
605+ vlan.save()
606+
607+ def serialize_vlan(vlan):
608+ return {
609+ "id": vlan.id,
610+ "name": vlan.get_name(),
611+ "vid": vlan.vid,
612+ "fabric": vlan.fabric.name,
613+ "fabric_id": vlan.fabric_id,
614+ "mtu": vlan.mtu,
615+ "primary_rack": (
616+ vlan.primary_rack.system_id if vlan.primary_rack else None
617+ ),
618+ "secondary_rack": (
619+ vlan.secondary_rack.system_id
620+ if vlan.secondary_rack
621+ else None
622+ ),
623+ "dhcp_on": vlan.dhcp_on,
624+ "external_dhcp": None,
625+ "relay_vlan": serialize_vlan(vlan.relay_vlan)
626+ if vlan.relay_vlan
627+ else None,
628+ "space": vlan.space.name if vlan.space else "undefined",
629+ "resource_uri": f"/MAAS/api/2.0/vlans/{vlan.id}/",
630+ }
631+
632 fabric = factory.make_Fabric()
633- for vid in range(1, 4):
634- factory.make_VLAN(vid=vid, fabric=fabric)
635+ make_vlan()
636+
637 uri = get_vlans_uri(fabric)
638- response = self.client.get(uri)
639+ with CountQueries() as counter:
640+ response = self.client.get(uri)
641+ base_count = counter.count
642
643 self.assertEqual(
644 http.client.OK, response.status_code, response.content
645 )
646- expected_ids = [vlan.vid for vlan in fabric.vlan_set.all()]
647- result_ids = [
648- vlan["vid"]
649- for vlan in json.loads(
650- response.content.decode(settings.DEFAULT_CHARSET)
651- )
652- ]
653- self.assertCountEqual(expected_ids, result_ids)
654+ result = json.loads(response.content.decode(settings.DEFAULT_CHARSET))
655+ # It's three VLANs, since when creating a fabric, a default VLAN
656+ # is always created.
657+ vlans = {vlan.id: vlan for vlan in VLAN.objects.filter(fabric=fabric)}
658+ self.assertEqual(2, len(result))
659+ for serialized_vlan in result:
660+ vlan = vlans[serialized_vlan["id"]]
661+ self.assertEqual(serialize_vlan(vlan), serialized_vlan)
662+
663+ make_vlan()
664+ with CountQueries() as counter:
665+ response = self.client.get(uri)
666+ # XXX: These really should be equal.
667+ self.assertEqual(base_count + 5, counter.count)
668
669 def test_create(self):
670 self.become_admin()
671@@ -187,9 +236,11 @@ class TestVlanAPI(APITestCase.ForUser):
672 "/MAAS/api/2.0/vlans/%s/" % vlan.id, get_vlan_uri(vlan)
673 )
674
675- def test_read(self):
676- fabric = factory.make_Fabric()
677- vlan = factory.make_VLAN(fabric=fabric)
678+ def test_read_basic(self):
679+ fabric = factory.make_Fabric(name="my-fabric")
680+ vlan = factory.make_VLAN(
681+ fabric=fabric, name="my-vlan", vid=123, mtu=1234
682+ )
683 uri = get_vlan_uri(vlan)
684 response = self.client.get(uri)
685
686@@ -199,24 +250,29 @@ class TestVlanAPI(APITestCase.ForUser):
687 parsed_vlan = json.loads(
688 response.content.decode(settings.DEFAULT_CHARSET)
689 )
690- self.assertThat(
691+ self.assertEqual(
692 parsed_vlan,
693- ContainsDict(
694- {
695- "id": Equals(vlan.id),
696- "name": Equals(vlan.get_name()),
697- "vid": Equals(vlan.vid),
698- "fabric": Equals(fabric.get_name()),
699- "fabric_id": Equals(fabric.id),
700- "resource_uri": Equals(get_vlan_uri(vlan)),
701- }
702- ),
703- )
704-
705- def test_read_with_fabric(self):
706- fabric = factory.make_Fabric()
707- vlan = factory.make_VLAN(fabric=fabric)
708- uri = get_vlan_uri(vlan, fabric)
709+ {
710+ "id": vlan.id,
711+ "name": "my-vlan",
712+ "vid": 123,
713+ "fabric": "my-fabric",
714+ "fabric_id": fabric.id,
715+ "mtu": 1234,
716+ "primary_rack": None,
717+ "secondary_rack": None,
718+ "dhcp_on": False,
719+ "external_dhcp": None,
720+ "relay_vlan": None,
721+ "space": "undefined",
722+ "resource_uri": f"/MAAS/api/2.0/vlans/{vlan.id}/",
723+ },
724+ )
725+
726+ def test_read_with_space(self):
727+ space = factory.make_Space(name="my-space")
728+ vlan = factory.make_VLAN(space=space)
729+ uri = get_vlan_uri(vlan, vlan.fabric)
730 response = self.client.get(uri)
731
732 self.assertEqual(
733@@ -225,22 +281,19 @@ class TestVlanAPI(APITestCase.ForUser):
734 parsed_vlan = json.loads(
735 response.content.decode(settings.DEFAULT_CHARSET)
736 )
737- self.assertThat(
738- parsed_vlan,
739- ContainsDict(
740- {
741- "id": Equals(vlan.id),
742- "name": Equals(vlan.get_name()),
743- "vid": Equals(vlan.vid),
744- "fabric": Equals(fabric.get_name()),
745- "resource_uri": Equals(get_vlan_uri(vlan)),
746- }
747- ),
748- )
749-
750- def test_read_with_space(self):
751- space = factory.make_Space()
752- vlan = factory.make_VLAN(space=space)
753+ self.assertEqual(parsed_vlan["space"], "my-space")
754+
755+ def test_read_with_dhcp(self):
756+ subnet = factory.make_Subnet()
757+ primary_rack = factory.make_RackController()
758+ factory.make_Interface(node=primary_rack, subnet=subnet)
759+ secondary_rack = factory.make_RackController()
760+ factory.make_Interface(node=secondary_rack, subnet=subnet)
761+ vlan = subnet.vlan
762+ vlan.dhcp_on = True
763+ vlan.primary_rack = primary_rack
764+ vlan.secondary_rack = secondary_rack
765+ vlan.save()
766 uri = get_vlan_uri(vlan, vlan.fabric)
767 response = self.client.get(uri)
768
769@@ -250,21 +303,15 @@ class TestVlanAPI(APITestCase.ForUser):
770 parsed_vlan = json.loads(
771 response.content.decode(settings.DEFAULT_CHARSET)
772 )
773- self.assertThat(
774- parsed_vlan,
775- ContainsDict(
776- {
777- "id": Equals(vlan.id),
778- "name": Equals(vlan.get_name()),
779- "vid": Equals(vlan.vid),
780- "space": Equals(space.get_name()),
781- "resource_uri": Equals(get_vlan_uri(vlan)),
782- }
783- ),
784- )
785-
786- def test_read_without_space_returns_undefined_space(self):
787- vlan = factory.make_VLAN(space=None)
788+ self.assertTrue(parsed_vlan["dhcp_on"])
789+ self.assertEqual(primary_rack.system_id, parsed_vlan["primary_rack"])
790+ self.assertEqual(
791+ secondary_rack.system_id, parsed_vlan["secondary_rack"]
792+ )
793+
794+ def test_read_with_relay_vlan(self):
795+ relay_vlan = factory.make_VLAN(name="my-relay")
796+ vlan = factory.make_VLAN(relay_vlan=relay_vlan)
797 uri = get_vlan_uri(vlan, vlan.fabric)
798 response = self.client.get(uri)
799
800@@ -274,17 +321,23 @@ class TestVlanAPI(APITestCase.ForUser):
801 parsed_vlan = json.loads(
802 response.content.decode(settings.DEFAULT_CHARSET)
803 )
804- self.assertThat(
805- parsed_vlan,
806- ContainsDict(
807- {
808- "id": Equals(vlan.id),
809- "name": Equals(vlan.get_name()),
810- "vid": Equals(vlan.vid),
811- "space": Equals(Space.UNDEFINED),
812- "resource_uri": Equals(get_vlan_uri(vlan)),
813- }
814- ),
815+ self.assertEqual(
816+ {
817+ "id": relay_vlan.id,
818+ "name": "my-relay",
819+ "vid": relay_vlan.vid,
820+ "fabric": relay_vlan.fabric.name,
821+ "fabric_id": relay_vlan.fabric_id,
822+ "mtu": relay_vlan.mtu,
823+ "primary_rack": None,
824+ "secondary_rack": None,
825+ "dhcp_on": False,
826+ "external_dhcp": None,
827+ "relay_vlan": None,
828+ "space": "undefined",
829+ "resource_uri": f"/MAAS/api/2.0/vlans/{relay_vlan.id}/",
830+ },
831+ parsed_vlan["relay_vlan"],
832 )
833
834 def test_read_404_when_bad_id(self):
835diff --git a/src/maasserver/testing/factory.py b/src/maasserver/testing/factory.py
836index afaabfe..99e5258 100644
837--- a/src/maasserver/testing/factory.py
838+++ b/src/maasserver/testing/factory.py
839@@ -1617,6 +1617,7 @@ class Factory(maastesting.factory.Factory):
840 primary_rack=None,
841 secondary_rack=None,
842 relay_vlan=None,
843+ mtu=1500,
844 ):
845 assert vid != 0, "VID=0 VLANs are auto-created"
846 if name is RANDOM:
847@@ -1636,6 +1637,7 @@ class Factory(maastesting.factory.Factory):
848 primary_rack=primary_rack,
849 secondary_rack=secondary_rack,
850 relay_vlan=relay_vlan,
851+ mtu=mtu,
852 )
853 vlan.save()
854 for rack in [primary_rack, secondary_rack]:

Subscribers

People subscribed via source and target branches