Skip to content

Commit 439d7fe

Browse files
Add netbox_tenant & netbox_tenant_group
1 parent 832b9cf commit 439d7fe

File tree

11 files changed

+591
-27
lines changed

11 files changed

+591
-27
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ env:
99
global:
1010
- COLLECTION_NAMESPACE: fragmentedpacket
1111
- COLLECTION_NAME: netbox_modules
12-
- COLLECTION_VERSION: 0.0.8
12+
- COLLECTION_VERSION: 0.0.9
1313

1414
matrix:
1515
include:

README.md

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
**THIS IS A WIP DUE TO COLLECTIONS BEING IN TECH REVIEW CURRENTLY (Ansible 2.8) BUT WILL BE UPDATED AS NECESSARY AS COLLECTIONS MATURES**
55

66
## Todo
7+
78
- ~~initial build and changes to properly import module_utils~~
89
- Add testing to Travis CI
910
- ~~Initial unit tests~~
@@ -12,9 +13,10 @@
1213
- Local testing using Tox
1314
- Test currently supported versions of Ansible
1415
- ~~Add documentation on how to use to README~~
15-
- Add documentation on how to contribute to collection
16+
- ~~Add documentation on how to contribute to collection~~
1617

1718
## Requirements
19+
1820
- Netbox 2.5+
1921
- pynetbox 4.0.6+
2022
- Python 3.6+
@@ -23,19 +25,23 @@
2325

2426
## Existing Modules
2527

26-
- netbox_device
27-
- netbox_device_interface
28-
- netbox_ip_address
29-
- netbox_prefix
30-
- netbox_site
28+
- netbox_device
29+
- netbox_device_interface
30+
- netbox_ip_address
31+
- netbox_prefix
32+
- netbox_site
33+
- netbox_tenant
34+
- netbox_tenant_group
3135

3236
## How to Use
37+
3338
- Install via Mazer
3439
- `mazer install fragmentedpacket.netbox_modules`
3540
- Follow Ansible instructions to use the collection
3641
- [https://docs.ansible.com/ansible/devel/dev_guide/collections_tech_preview.html#using-collections](https://docs.ansible.com/ansible/devel/dev_guide/collections_tech_preview.html#using-collections)
3742

38-
#### Example playbook
43+
### Example playbook
44+
3945
```yaml
4046
- name: "Test Netbox modules"
4147
connection: local
@@ -59,12 +65,18 @@
5965
```
6066
6167
## How to Contribute
62-
**Will be updated with diagram and more information needed to contribute**
6368
64-
If looking to contribute before this is updated, please review the code and hopefully it is enough to get started on adding new modules and how the new modules should be structured.
69+
The structure of the Netbox modules attempts to follow the layout of the Netbox API by having a module_util for each application (`dcim, ipam, tenancy, etc`) that inherits from a base module (`NetboxModule - netbox_utils.py`) and then implements the specific endpoints within the correct application module.
70+
71+
ex. Add logic for adding devices under netbox_dcim.py or ip addresses under netbox_ipam.py
72+
73+
In turn when creating the actual modules, we're just calling a single function and passing in the Ansible Module and the endpoint. This means all the logic is within the specific application's module_util module and a lot of the logic should be the same for most endpoints since it is a basic operation of using the desired state of the endpoint and then either making sure it exists, updating it if it does exist, or removing it. There may be some special logic for other endpoints, but it should be minimal.
74+
75+
(Ansible Module) netbox_{{ endpoint }} -> (Module Util) netbox_{{ application }} -> (Module Util) netbox_utils
6576

66-
#### Testing
77+
### Testing
6778

6879
1. Please update `tests/unit/module_utils/test_netbox_base_class.py` if editing anything within the base class that needs to be tested.
69-
2. Run `black .` within the base directory for black formatting as it's required for tests to pass
70-
3. Check necessary dependencies defined within `.travis.yml` for now if you're wanting to test locally
80+
2. Please add or update an existing play to test the new Netbox module for integration testing within `tests/integration/integration-tests.yml`
81+
3. Run `black .` within the base directory for black formatting as it's required for tests to pass
82+
4. Check necessary dependencies defined within `.travis.yml` for now if you're wanting to test locally

galaxy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace: fragmentedpacket
99
name: netbox_modules
1010

1111
# The version of the collection. Must be compatible with semantic versioning
12-
version: 0.0.8
12+
version: 0.0.9
1313

1414
# The path to the Markdown (.md) readme file. This path is relative to the root of the collection
1515
readme: README.md
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright: (c) 2018, Mikhail Yohman (@fragmentedpacket) <mikhail.yohman@gmail.com>
3+
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4+
from __future__ import absolute_import, division, print_function
5+
6+
__metaclass__ = type
7+
8+
# This should just be temporary once 2.9 is relased and tested we can remove this
9+
try:
10+
from ansible_collections.fragmentedpacket.netbox_modules.plugins.module_utils.netbox_utils import (
11+
NetboxModule,
12+
ENDPOINT_NAME_MAPPING,
13+
)
14+
except ImportError:
15+
import sys
16+
17+
sys.path.append(".")
18+
from netbox_utils import NetboxModule, ENDPOINT_NAME_MAPPING
19+
20+
21+
NB_TENANTS = "tenants"
22+
NB_TENANT_GROUPS = "tenant_groups"
23+
24+
25+
class NetboxTenancyModule(NetboxModule):
26+
def __init__(self, module, endpoint):
27+
super().__init__(module, endpoint)
28+
29+
def run(self):
30+
"""
31+
This function should have all necessary code for endpoints within the application
32+
to create/update/delete the endpoint objects
33+
Supported endpoints:
34+
tenants
35+
tenant groups
36+
"""
37+
# Used to dynamically set key when returning results
38+
endpoint_name = ENDPOINT_NAME_MAPPING[self.endpoint]
39+
40+
self.result = {"changed": False}
41+
42+
application = self._find_app(self.endpoint)
43+
nb_app = getattr(self.nb, application)
44+
nb_endpoint = getattr(nb_app, self.endpoint)
45+
46+
data = self.data
47+
48+
# Used for msg output
49+
name = data.get("name")
50+
51+
data["slug"] = self._to_slug(name)
52+
53+
object_query_params = self._build_query_params(endpoint_name, data)
54+
try:
55+
self.nb_object = nb_endpoint.get(**object_query_params)
56+
except ValueError:
57+
self._handle_errors(msg="More than one result returned for %s" % (name))
58+
59+
if self.state == "present":
60+
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)
61+
elif self.state == "absent":
62+
self._ensure_object_absent(endpoint_name, name)
63+
64+
try:
65+
serialized_object = self.nb_object.serialize()
66+
except AttributeError:
67+
serialized_object = self.nb_object
68+
69+
self.result.update({endpoint_name: serialized_object})
70+
71+
self.module.exit_json(**self.result)

plugins/module_utils/netbox_utils.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
device="name",
4545
device_role="slug",
4646
device_type="slug",
47+
group="slug",
4748
manufacturer="slug",
4849
nat_inside="address",
4950
nat_outside="address",
@@ -68,6 +69,7 @@
6869
device="devices",
6970
device_role="device_roles",
7071
device_type="device_types",
72+
group="tenant_groups",
7173
interface="interfaces",
7274
lag="interfaces",
7375
nat_inside="ip_addresses",
@@ -94,6 +96,7 @@
9496
NO_DEFAULT_ID = set(
9597
[
9698
"device",
99+
"group",
97100
"lag",
98101
"primary_ip",
99102
"primary_ip4",
@@ -108,6 +111,7 @@
108111
"untagged_vlan",
109112
"tagged_vlans",
110113
"tenant",
114+
"tenant_group",
111115
]
112116
)
113117

@@ -118,6 +122,7 @@
118122
"prefixes": "prefix",
119123
"sites": "site",
120124
"tenants": "tenant",
125+
"tenant_groups": "tenant_group",
121126
}
122127

123128
DEVICE_STATUS = dict(offline=0, active=1, planned=2, staged=3, failed=4, inventory=5)
@@ -209,8 +214,10 @@
209214
"prefix": set(["prefix", "vrf"]),
210215
"site": set(["name"]),
211216
"vlan": set(["name", "site", "vlan_group", "tenant"]),
212-
"untagged_vlan": set(["name", "site", "vlan_group", "tenant"]),
213217
"tagged_vlans": set(["name", "site", "vlan_group", "tenant"]),
218+
"tenant": set(["name"]),
219+
"tenant_group": set(["name"]),
220+
"untagged_vlan": set(["name", "site", "vlan_group", "tenant"]),
214221
}
215222

216223
QUERY_PARAMS_IDS = set(["device", "vrf", "site", "vlan_group", "tenant"])
@@ -343,11 +350,13 @@ def _change_choices_id(self, endpoint, data):
343350
:params endpoint (str): The endpoint that will be used for mapping to required _choices
344351
:params data (dict): User defined data passed into the module
345352
"""
346-
required_choices = REQUIRED_ID_FIND[endpoint]
347-
for choice in required_choices:
348-
for key, value in choice.items():
349-
if data.get(key):
350-
data[key] = value[data[key].lower()]
353+
if REQUIRED_ID_FIND.get(endpoint):
354+
required_choices = REQUIRED_ID_FIND[endpoint]
355+
for choice in required_choices:
356+
for key, value in choice.items():
357+
if data.get(key):
358+
data[key] = value[data[key].lower()]
359+
351360
return data
352361

353362
def _find_app(self, endpoint):

plugins/modules/netbox_device.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ def main():
192192
validate_certs=dict(type="bool", default=True),
193193
)
194194

195-
global module
196195
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
197196

198197
# Fail if device name is not given

0 commit comments

Comments
 (0)