Skip to content

Commit bc9fbcb

Browse files
authored
Add module netbox_l2vpn (#846)
1 parent 678bc02 commit bc9fbcb

File tree

7 files changed

+310
-1
lines changed

7 files changed

+310
-1
lines changed

meta/runtime.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ action_groups:
4141
- netbox_inventory_item
4242
- netbox_ip_address
4343
- netbox_ipam_role
44+
- netbox_l2vpn
4445
- netbox_location
4546
- netbox_manufacturer
4647
- netbox_platform

plugins/module_utils/netbox_ipam.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
NB_VLAN_GROUPS = "vlan_groups"
2929
NB_VRFS = "vrfs"
3030
NB_SERVICES = "services"
31+
NB_L2VPNS = "l2vpns"
32+
NB_L2VPN_TERMINATIONS = "l2vpn_terminations"
3133

3234

3335
class NetboxIpamModule(NetboxModule):
@@ -147,6 +149,8 @@ def run(self):
147149
- aggregates
148150
- ipam_roles
149151
- ip_addresses
152+
- l2vpns
153+
- l2vpn_terminations
150154
- prefixes
151155
- rirs
152156
- route_targets

plugins/module_utils/netbox_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
ipam=[
8686
"aggregates",
8787
"ip_addresses",
88+
"l2vpns",
89+
"l2vpn_terminations",
8890
"prefixes",
8991
"rirs",
9092
"roles",
@@ -126,6 +128,7 @@
126128
group="slug",
127129
installed_device="name",
128130
import_targets="name",
131+
l2vpn="name",
129132
location="slug",
130133
manufacturer="slug",
131134
nat_inside="address",
@@ -306,6 +309,7 @@
306309
"interface_templates": "interface_template",
307310
"inventory_items": "inventory_item",
308311
"ip_addresses": "ip_address",
312+
"l2vpns": "l2vpn",
309313
"locations": "location",
310314
"manufacturers": "manufacturer",
311315
"platforms": "platform",
@@ -408,6 +412,7 @@
408412
"ipaddresses": set(
409413
["address", "vrf", "device", "interface", "assigned_object", "virtual_machine"]
410414
),
415+
"l2vpn": set(["name"]),
411416
"lag": set(["name"]),
412417
"location": set(["slug"]),
413418
"manufacturer": set(["slug"]),
@@ -556,6 +561,7 @@
556561
"device_roles",
557562
"device_types",
558563
"ipam_roles",
564+
"l2vpns",
559565
"locations",
560566
"rack_groups",
561567
"rack_roles",

plugins/modules/netbox_l2vpn.py

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
# Copyright: (c) 2022, Martin Rødvand (@rodvand) <martin@rodvand.net>
4+
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5+
6+
from __future__ import absolute_import, division, print_function
7+
8+
__metaclass__ = type
9+
10+
DOCUMENTATION = r"""
11+
---
12+
module: netbox_l2vpn
13+
short_description: Create, update or delete L2VPNs within NetBox
14+
description:
15+
- Creates, updates or removes L2VPNs from NetBox
16+
notes:
17+
- Tags should be defined as a YAML list
18+
- This should be ran with connection C(local) and hosts C(localhost)
19+
author:
20+
- Martin Rødvand (@rodvand)
21+
requirements:
22+
- pynetbox
23+
version_added: '3.9.0'
24+
extends_documentation_fragment:
25+
- netbox.netbox.common
26+
options:
27+
data:
28+
type: dict
29+
description:
30+
- Defines the L2VPN configuration
31+
suboptions:
32+
name:
33+
description:
34+
- The name of the L2VPN
35+
required: true
36+
type: str
37+
type:
38+
description:
39+
- The type of L2VPN
40+
required: true
41+
type: raw
42+
identifier:
43+
description:
44+
- The identifier of the L2VPN
45+
required: false
46+
type: int
47+
import_targets:
48+
description:
49+
- Route targets to import
50+
required: false
51+
type: list
52+
elements: raw
53+
export_targets:
54+
description:
55+
- Route targets to export
56+
required: false
57+
type: list
58+
elements: raw
59+
description:
60+
description:
61+
- The description of the L2VPN
62+
required: false
63+
type: str
64+
tenant:
65+
description:
66+
- The tenant that the L2VPN will be assigned to
67+
required: false
68+
type: raw
69+
tags:
70+
description:
71+
- Any tags that the L2VPN may need to be associated with
72+
required: false
73+
type: list
74+
elements: raw
75+
custom_fields:
76+
description:
77+
- Must exist in NetBox
78+
required: false
79+
type: dict
80+
required: true
81+
"""
82+
83+
EXAMPLES = r"""
84+
- name: "Test NetBox modules"
85+
connection: local
86+
hosts: localhost
87+
gather_facts: False
88+
89+
tasks:
90+
- name: Create L2VPN within NetBox with only required information
91+
netbox_l2vpn:
92+
netbox_url: http://netbox.local
93+
netbox_token: thisIsMyToken
94+
data:
95+
name: Test L2VPN
96+
type: vxlan
97+
state: present
98+
99+
- name: Delete L2VPN within netbox
100+
netbox_vlan:
101+
netbox_url: http://netbox.local
102+
netbox_token: thisIsMyToken
103+
data:
104+
name: Test L2VPN
105+
type: vxlan
106+
state: absent
107+
108+
- name: Create L2VPN with all required information
109+
netbox_vlan:
110+
netbox_url: http://netbox.local
111+
netbox_token: thisIsMyToken
112+
data:
113+
name: Test L2VPN
114+
type: vpls
115+
identifier: 43256
116+
import_targets:
117+
- "65000:1"
118+
export_targets:
119+
- "65000:2"
120+
tenant: Test Tenant
121+
description: Just a test
122+
tags:
123+
- Schnozzberry
124+
state: present
125+
"""
126+
127+
RETURN = r"""
128+
l2vpn:
129+
description: Serialized object as created or already existent within NetBox
130+
returned: success (when I(state=present))
131+
type: dict
132+
msg:
133+
description: Message indicating failure or info about what has been achieved
134+
returned: always
135+
type: str
136+
"""
137+
138+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_utils import (
139+
NetboxAnsibleModule,
140+
NETBOX_ARG_SPEC,
141+
)
142+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_ipam import (
143+
NetboxIpamModule,
144+
NB_L2VPNS,
145+
)
146+
from copy import deepcopy
147+
148+
149+
def main():
150+
"""
151+
Main entry point for module execution
152+
"""
153+
argument_spec = deepcopy(NETBOX_ARG_SPEC)
154+
argument_spec.update(
155+
dict(
156+
data=dict(
157+
type="dict",
158+
required=True,
159+
options=dict(
160+
name=dict(required=True, type="str"),
161+
type=dict(required=True, type="raw"),
162+
identifier=dict(required=False, type="int"),
163+
import_targets=dict(required=False, type="list", elements="raw"),
164+
export_targets=dict(required=False, type="list", elements="raw"),
165+
description=dict(required=False, type="str"),
166+
tenant=dict(required=False, type="raw"),
167+
tags=dict(required=False, type="list", elements="raw"),
168+
custom_fields=dict(required=False, type="dict"),
169+
),
170+
),
171+
)
172+
)
173+
required_if = [
174+
("state", "present", ["name", "type"]),
175+
("state", "absent", ["name", "type"]),
176+
]
177+
178+
module = NetboxAnsibleModule(
179+
argument_spec=argument_spec, supports_check_mode=True, required_if=required_if
180+
)
181+
182+
netbox_l2vpn = NetboxIpamModule(module, NB_L2VPNS)
183+
netbox_l2vpn.run()
184+
185+
186+
if __name__ == "__main__":
187+
main()

tests/integration/inventory

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[testgroup]
2+
testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/Users/rodvand/collections/ansible_collections/netbox/netbox/venv/bin/python3.9"

tests/integration/targets/v3.3/tasks/main.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
23
- name: "NETBOX_DEVICE TESTS"
34
include_tasks: "netbox_device.yml"
45

@@ -235,4 +236,13 @@
235236
tags:
236237
- netbox_webhook
237238
tags:
238-
- netbox_webhook
239+
- netbox_webhook
240+
241+
- name: "NETBOX_L2VPN TESTS"
242+
include_tasks:
243+
file: "netbox_l2vpn.yml"
244+
apply:
245+
tags:
246+
- netbox_l2vpn
247+
tags:
248+
- netbox_l2vpn
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
##
3+
##
4+
### NETBOX_L2VPN
5+
##
6+
##
7+
- name: "L2VPN 1: Necessary info creation"
8+
netbox.netbox.netbox_l2vpn:
9+
netbox_url: http://localhost:32768
10+
netbox_token: 0123456789abcdef0123456789abcdef01234567
11+
data:
12+
name: Test L2VPN
13+
type: vxlan
14+
state: present
15+
register: test_one
16+
17+
- name: "L2VPN 1: ASSERT - Necessary info creation"
18+
assert:
19+
that:
20+
- test_one is changed
21+
- test_one['diff']['before']['state'] == "absent"
22+
- test_one['diff']['after']['state'] == "present"
23+
- test_one['l2vpn']['name'] == "Test L2VPN"
24+
- test_one['l2vpn']['type'] == "vxlan"
25+
- test_one['msg'] == "l2vpn Test L2VPN created"
26+
27+
- name: "L2VPN 2: Create duplicate"
28+
netbox.netbox.netbox_l2vpn:
29+
netbox_url: http://localhost:32768
30+
netbox_token: 0123456789abcdef0123456789abcdef01234567
31+
data:
32+
name: Test L2VPN
33+
type: vxlan
34+
state: present
35+
register: test_two
36+
37+
- name: "L2VPN 2: ASSERT - Create duplicate"
38+
assert:
39+
that:
40+
- not test_two['changed']
41+
- test_two['l2vpn']['name'] == "Test L2VPN"
42+
- test_two['l2vpn']['type'] == "vxlan"
43+
- test_two['msg'] == "l2vpn Test L2VPN already exists"
44+
45+
- name: "L2VPN 4: ASSERT - Update"
46+
netbox.netbox.netbox_l2vpn:
47+
netbox_url: http://localhost:32768
48+
netbox_token: 0123456789abcdef0123456789abcdef01234567
49+
data:
50+
name: "Test L2VPN"
51+
type: vxlan
52+
tenant: "Test Tenant"
53+
description: Updated description
54+
import_targets:
55+
- "4000:4000"
56+
- "5000:5000"
57+
export_targets:
58+
- "6000:6000"
59+
tags:
60+
- "Schnozzberry"
61+
state: present
62+
register: test_four
63+
64+
- name: "L2VPN: ASSERT - Updated"
65+
assert:
66+
that:
67+
- test_four is changed
68+
- test_four['diff']['after']['description'] == "Updated description"
69+
- test_four['diff']['after']['import_targets'] == [1, 2]
70+
- test_four['diff']['after']['export_targets'] == [3]
71+
- test_four['diff']['after']['tags'][0] == 4
72+
- test_four['l2vpn']['name'] == "Test L2VPN"
73+
- test_four['l2vpn']['tenant'] == 1
74+
- test_four['l2vpn']['import_targets'] == [1, 2]
75+
- test_four['l2vpn']['export_targets'] == [3]
76+
- test_four['l2vpn']['description'] == "Updated description"
77+
- test_four['l2vpn']['tags'][0] == 4
78+
- test_four['msg'] == "l2vpn Test L2VPN updated"
79+
80+
- name: "L2VPN: ASSERT - Delete"
81+
netbox.netbox.netbox_l2vpn:
82+
netbox_url: http://localhost:32768
83+
netbox_token: 0123456789abcdef0123456789abcdef01234567
84+
data:
85+
name: "Test L2VPN"
86+
type: vxlan
87+
state: absent
88+
register: test_six
89+
90+
- name: "L2VPN 6: ASSERT - Delete"
91+
assert:
92+
that:
93+
- test_six is changed
94+
- test_six['l2vpn']['name'] == "Test L2VPN"
95+
- test_six['l2vpn']['tenant'] == 1
96+
- test_six['l2vpn']['type'] == "vxlan"
97+
- test_six['l2vpn']['description'] == "Updated description"
98+
- test_six['l2vpn']['tags'][0] == 4
99+
- test_six['msg'] == "l2vpn Test L2VPN deleted"

0 commit comments

Comments
 (0)