Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for all new module models in Nautobot 2.3+ #446

Merged
merged 9 commits into from
Nov 12, 2024
3 changes: 3 additions & 0 deletions plugins/lookup/lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ def get_endpoint(nautobot, term):
"locations": {"endpoint": nautobot.dcim.locations},
"location-types": {"endpoint": nautobot.dcim.location_types},
"manufacturers": {"endpoint": nautobot.dcim.manufacturers},
"module-bay-templates": {"endpoint": nautobot.dcim.module_bay_templates},
"module-bays": {"endpoint": nautobot.dcim.module_bays},
"module-types": {"endpoint": nautobot.dcim.module_types},
"modules": {"endpoint": nautobot.dcim.modules},
"namespaces": {"endpoint": nautobot.ipam.namespaces},
"object-changes": {"endpoint": nautobot.extras.object_changes},
Expand Down
22 changes: 22 additions & 0 deletions plugins/module_utils/dcim.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
NB_LOCATIONS = "locations"
NB_LOCATION_TYPES = "location_types"
NB_MANUFACTURERS = "manufacturers"
NB_MODULE_BAY_TEMPLATES = "module_bay_templates"
NB_MODULE_BAYS = "module_bays"
NB_MODULE_TYPES = "module_types"
NB_MODULES = "modules"
NB_NAMESPACES = "namespaces"
NB_PLATFORMS = "platforms"
NB_POWER_FEEDS = "power_feeds"
Expand Down Expand Up @@ -69,6 +73,10 @@ def run(self):
- interface_templates
- inventory_items
- manufacturers
- module_bay_templates
- module_bays
- module_types
- modules
- platforms
- power_feeds
- power_outlets
Expand Down Expand Up @@ -133,6 +141,20 @@ def run(self):
termination_b_name,
)

elif endpoint_name == "module":
module_type_name = self.module.params["module_type"]
if self.module.params["parent_module_bay"]:
parent_name = self.module.params["parent_module_bay"].get("name")
if self.module.params["parent_module_bay"].get("parent_device"):
parent_parent_name = self.module.params["parent_module_bay"].get("parent_device")
elif self.module.params["parent_module_bay"].get("parent_module"):
parent_parent_name = self.module.params["parent_module_bay"].get("parent_module")
elif self.module.params["location"]:
parent_name = self.module.params["location"].get("name")
parent_parent_name = self.module.params["location"].get("parent", "—")
joewesch marked this conversation as resolved.
Show resolved Hide resolved

name = f"{parent_parent_name} > {parent_name} > {module_type_name}"

# Make color params lowercase
if data.get("color"):
data["color"] = data["color"].lower()
Expand Down
21 changes: 21 additions & 0 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"locations",
"location_types",
"manufacturers",
"module_bay_templates",
"module_bays",
"module_types",
"modules",
"platforms",
"power_feeds",
Expand Down Expand Up @@ -118,6 +121,9 @@
location_type="name",
manufacturer="name",
master="name",
module_bay_template="name",
module_bay="name",
module_type="model",
nat_inside="address",
nat_outside="address",
parent_location="name",
Expand Down Expand Up @@ -183,12 +189,18 @@
"location": "locations",
"location_type": "location_types",
"manufacturer": "manufacturers",
"module_bay_template": "module_bay_templates",
"module_bay": "module_bays",
"module_type": "module_types",
"module": "modules",
"master": "devices",
"nat_inside": "ip_addresses",
"nat_outside": "ip_addresses",
"namespace": "namespaces",
"platform": "platforms",
"parent_device": "devices",
"parent_module_bay": "module_bays",
"parent_module": "modules",
"parent_rack_group": "rack_groups",
"parent_location": "locations",
"parent_location_type": "location_types",
Expand Down Expand Up @@ -258,6 +270,9 @@
"locations": "location",
"location_types": "location_type",
"manufacturers": "manufacturer",
"module_bay_templates": "module_bay_template",
"module_bays": "module_bay",
"module_types": "module_type",
"modules": "module",
"namespaces": "namespace",
"permissions": "permission",
Expand Down Expand Up @@ -341,8 +356,14 @@
"location_type": set(["name"]),
"manufacturer": set(["name"]),
"master": set(["name"]),
"module_bay_template": set(["name"]),
"module_bay": set(["name", "parent_device", "parent_module"]),
"module_type": set(["model"]),
"module": set(["module_type", "parent_module_bay", "location"]),
"namespace": set(["name"]),
"nat_inside": set(["namespace", "address"]),
"parent_module_bay": set(["name", "parent_device", "parent_module"]),
"parent_module": set(["module_type", "parent_module_bay"]),
"parent_rack_group": set(["name"]),
"parent_tenant_group": set(["name"]),
"permission": set(["name"]),
Expand Down
170 changes: 170 additions & 0 deletions plugins/modules/module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2024, Network to Code (@networktocode) <info@networktocode.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = r"""
---
module: module
short_description: Create, update or delete modules within Nautobot
description:
- Creates, updates or removes modules from Nautobot
notes:
- Tags should be defined as a YAML list
- This should be ran with connection C(local) and hosts C(localhost)
author:
- Travis Smith (@tsm1th)
version_added: "5.4.0"
extends_documentation_fragment:
- networktocode.nautobot.fragments.base
- networktocode.nautobot.fragments.tags
- networktocode.nautobot.fragments.custom_fields
options:
module_type:
description:
- The module type of the module
required: true
type: raw
serial:
description:
- The serial number of the module
required: false
type: str
asset_tag:
description:
- The asset tag of the module
required: false
type: str
role:
description:
- The asset tag of the module
tsm1th marked this conversation as resolved.
Show resolved Hide resolved
required: false
type: raw
status:
description:
- The status of the module
- Required if I(state=present) and the device does not exist yet
required: false
type: raw
tenant:
description:
- The tenant of the module
required: false
type: raw
location:
description:
- The location of the module
required: false
type: raw
parent_module_bay:
description:
- The parent module bay of the module
required: false
type: raw
"""

EXAMPLES = r"""
- name: Create a module in module bay
networktocode.nautobot.module:
url: http://nautobot.local
token: thisIsMyToken
module_type: HooverMaxProModel60
parent_module_bay:
name: PowerStripTwo
parent_device: test100
status: Active
state: present

- name: Create a module at location
networktocode.nautobot.module:
url: http://nautobot.local
token: thisIsMyToken
module_type: HooverMaxProModel60
location:
name: "Child Test Location"
parent: "Parent Test Location"
serial: "654321"
asset_tag: "123456"
role: Test Module Role
status: Active
tenant: Test Tenant
state: present

- name: Delete a module
networktocode.nautobot.module:
url: http://nautobot.local
token: thisIsMyToken
module_type: HooverMaxProModel60
parent_module_bay:
name: PowerStripTwo
parent_device: test100
state: absent
"""

RETURN = r"""
module:
description: Serialized object as created or already existent within Nautobot
returned: success (when I(state=present))
type: dict
msg:
description: Message indicating failure or info about what has been achieved
returned: always
type: str
"""

from ansible_collections.networktocode.nautobot.plugins.module_utils.utils import (
NAUTOBOT_ARG_SPEC,
TAGS_ARG_SPEC,
CUSTOM_FIELDS_ARG_SPEC,
)
from ansible_collections.networktocode.nautobot.plugins.module_utils.dcim import (
NautobotDcimModule,
NB_MODULES,
)
from ansible.module_utils.basic import AnsibleModule
from copy import deepcopy


def main():
"""
Main entry point for module execution
"""
argument_spec = deepcopy(NAUTOBOT_ARG_SPEC)
argument_spec.update(deepcopy(TAGS_ARG_SPEC))
argument_spec.update(deepcopy(CUSTOM_FIELDS_ARG_SPEC))
argument_spec.update(
dict(
module_type=dict(required=True, type="raw"),
serial=dict(required=False, type="str"),
asset_tag=dict(required=False, type="str"),
role=dict(required=False, type="raw"),
status=dict(required=False, type="raw"),
tenant=dict(required=False, type="raw"),
location=dict(required=False, type="raw"),
parent_module_bay=dict(required=False, type="raw"),
)
)

required_one_of = [
("location", "parent_module_bay"),
]
mutually_exclusive = [
("location", "parent_module_bay"),
]
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_one_of=required_one_of,
mutually_exclusive=mutually_exclusive,
)

module = NautobotDcimModule(module, NB_MODULES)
module.run()
tsm1th marked this conversation as resolved.
Show resolved Hide resolved


if __name__ == "__main__": # pragma: no cover
main()
Loading
Loading