From bf8b1c2364f1e1664d0948bbd8375c5f9b0152be Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:39:14 +0000 Subject: [PATCH 1/8] Added module type model and tests --- plugins/module_utils/dcim.py | 2 + plugins/module_utils/utils.py | 5 + plugins/modules/module_type.py | 114 +++++++++++++ .../targets/latest/tasks/module_type.yml | 157 ++++++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 plugins/modules/module_type.py create mode 100644 tests/integration/targets/latest/tasks/module_type.yml diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index 9dce4313..4d56e0f1 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -32,6 +32,7 @@ NB_LOCATIONS = "locations" NB_LOCATION_TYPES = "location_types" NB_MANUFACTURERS = "manufacturers" +NB_MODULE_TYPES = "module_types" NB_NAMESPACES = "namespaces" NB_PLATFORMS = "platforms" NB_POWER_FEEDS = "power_feeds" @@ -69,6 +70,7 @@ def run(self): - interface_templates - inventory_items - manufacturers + - module_types - platforms - power_feeds - power_outlets diff --git a/plugins/module_utils/utils.py b/plugins/module_utils/utils.py index 431ee83e..ea93a4ea 100644 --- a/plugins/module_utils/utils.py +++ b/plugins/module_utils/utils.py @@ -54,6 +54,7 @@ "location_types", "manufacturers", "modules", + "module_types", "platforms", "power_feeds", "power_outlets", @@ -118,6 +119,7 @@ location_type="name", manufacturer="name", master="name", + module_type="model", nat_inside="address", nat_outside="address", parent_location="name", @@ -184,6 +186,7 @@ "location_type": "location_types", "manufacturer": "manufacturers", "module": "modules", + "module_type": "module_types", "master": "devices", "nat_inside": "ip_addresses", "nat_outside": "ip_addresses", @@ -259,6 +262,7 @@ "location_types": "location_type", "manufacturers": "manufacturer", "modules": "module", + "module_types": "module_type", "namespaces": "namespace", "permissions": "permission", "platforms": "platform", @@ -341,6 +345,7 @@ "location_type": set(["name"]), "manufacturer": set(["name"]), "master": set(["name"]), + "module_type": set(["model"]), "namespace": set(["name"]), "nat_inside": set(["namespace", "address"]), "parent_rack_group": set(["name"]), diff --git a/plugins/modules/module_type.py b/plugins/modules/module_type.py new file mode 100644 index 00000000..d1bf8e68 --- /dev/null +++ b/plugins/modules/module_type.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Network to Code (@networktocode) +# 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_type +short_description: Create, update or delete module types within Nautobot +description: + - Creates, updates or removes module types 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: + manufacturer: + description: + - The manufacturer of the module type + - Required if I(state=present) and the module type does not exist yet + required: false + type: raw + model: + description: + - The model of the module type + required: true + type: raw + part_number: + description: + - The part number of the module type + required: false + type: str + comments: + description: + - Comments that may include additional information in regards to the module type + required: false + type: str +""" + +EXAMPLES = r""" +- name: Create a module type + networktocode.nautobot.module_type: + url: http://nautobot.local + token: thisIsMyToken + model: HooverMaxProModel60 + manufacturer: Best Quality Vacuum + state: present + +- name: Delete a module type + networktocode.nautobot.module_type: + url: http://nautobot.local + token: thisIsMyToken + model: HooverMaxProModel60 + state: absent +""" + +RETURN = r""" +module_type: + 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_MODULE_TYPES, +) +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( + manufacturer=dict(required=False, type="raw"), + model=dict(required=True, type="raw"), + part_number=dict(required=False, type="str"), + comments=dict(required=False, type="str"), + ) + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + module_type = NautobotDcimModule(module, NB_MODULE_TYPES) + module_type.run() + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/tests/integration/targets/latest/tasks/module_type.yml b/tests/integration/targets/latest/tasks/module_type.yml new file mode 100644 index 00000000..c618bed6 --- /dev/null +++ b/tests/integration/targets/latest/tasks/module_type.yml @@ -0,0 +1,157 @@ +--- +## +## +### PYNAUTOBOT_MODULE_TYPE +## +## +- set_fact: + manufacturer: "{{ lookup('networktocode.nautobot.lookup', 'manufacturers', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Manufacturer\"') }}" + +- name: "1 - Create module type with minimum information" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + state: present + register: test_one + +- name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_type']['model'] == "ws-test-3750" + - test_one['module_type']['manufacturer'] == manufacturer['key'] + - test_one['msg'] == "module_type ws-test-3750 created" + +- name: "2 - Create module type with minimum information idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: "ws-test-3750" + manufacturer: Test Manufacturer + state: present + register: test_two + +- name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_type']['model'] == "ws-test-3750" + - test_two['module_type']['manufacturer'] == manufacturer['key'] + - test_two['msg'] == "module_type ws-test-3750 already exists" + +- name: "3 - Update module type" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + part_number: ws-3750g-v2 + comments: With great power comes great responsibility! + state: present + register: test_three + +- name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['part_number'] == "ws-3750g-v2" + - test_three['module_type']['model'] == "ws-test-3750" + - test_three['module_type']['manufacturer'] == manufacturer['key'] + - test_three['module_type']['comments'] == "With great power comes great responsibility!" + - test_three['module_type']['part_number'] == "ws-3750g-v2" + - test_three['msg'] == "module_type ws-test-3750 updated" + +- name: "4 - Update idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + part_number: ws-3750g-v2 + comments: With great power comes great responsibility! + state: present + register: test_four + +- name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_type']['model'] == "ws-test-3750" + - test_four['msg'] == "module_type ws-test-3750 already exists" + +- name: "5 - Create module type with all params" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + manufacturer: Test Manufacturer + part_number: ws-3750g-v3 + comments: With great power comes great responsibility! + state: present + register: test_five + +- name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_type']['model'] == "ws-test-3750-2" + - test_five['module_type']['manufacturer'] == manufacturer['key'] + - test_five['module_type']['comments'] == "With great power comes great responsibility!" + - test_five['module_type']['part_number'] == "ws-3750g-v3" + - test_five['msg'] == "module_type ws-test-3750-2 created" + +- name: "6 - Create module type with all params idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + manufacturer: Test Manufacturer + part_number: ws-3750g-v3 + comments: With great power comes great responsibility! + state: present + register: test_six + +- name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module_type']['model'] == "ws-test-3750-2" + - test_six['module_type']['manufacturer'] == manufacturer['key'] + - test_six['module_type']['comments'] == "With great power comes great responsibility!" + - test_six['module_type']['part_number'] == "ws-3750g-v3" + - test_six['msg'] == "module_type ws-test-3750-2 already exists" + +- name: "7 - Delete" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + state: absent + register: test_seven + +- name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_type ws-test-3750-2 deleted" + +- name: "8 - Delete idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: "ws-test-3750-2" + state: absent + register: test_eight + +- name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_type'] == None + - test_eight['msg'] == "module_type ws-test-3750-2 already absent" From 60ea898005f6128713fab05f39b5a26cbe7e9c5c Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Sat, 9 Nov 2024 02:33:46 +0000 Subject: [PATCH 2/8] Added module bay template model and tests --- plugins/lookup/lookup.py | 1 + plugins/module_utils/dcim.py | 2 + plugins/module_utils/utils.py | 5 + plugins/modules/module_bay_template.py | 138 ++++++++++++++ .../latest/tasks/module_bay_template.yml | 169 ++++++++++++++++++ 5 files changed, 315 insertions(+) create mode 100644 plugins/modules/module_bay_template.py create mode 100644 tests/integration/targets/latest/tasks/module_bay_template.yml diff --git a/plugins/lookup/lookup.py b/plugins/lookup/lookup.py index 3210995f..06e18eea 100644 --- a/plugins/lookup/lookup.py +++ b/plugins/lookup/lookup.py @@ -203,6 +203,7 @@ def get_endpoint(nautobot, term): "locations": {"endpoint": nautobot.dcim.locations}, "location-types": {"endpoint": nautobot.dcim.location_types}, "manufacturers": {"endpoint": nautobot.dcim.manufacturers}, + "module-types": {"endpoint": nautobot.dcim.module_types}, "modules": {"endpoint": nautobot.dcim.modules}, "namespaces": {"endpoint": nautobot.ipam.namespaces}, "object-changes": {"endpoint": nautobot.extras.object_changes}, diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index 4d56e0f1..9948ada9 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -32,6 +32,7 @@ NB_LOCATIONS = "locations" NB_LOCATION_TYPES = "location_types" NB_MANUFACTURERS = "manufacturers" +NB_MODULE_BAY_TEMPLATES = "module_bay_templates" NB_MODULE_TYPES = "module_types" NB_NAMESPACES = "namespaces" NB_PLATFORMS = "platforms" @@ -70,6 +71,7 @@ def run(self): - interface_templates - inventory_items - manufacturers + - module_bay_templates - module_types - platforms - power_feeds diff --git a/plugins/module_utils/utils.py b/plugins/module_utils/utils.py index ea93a4ea..904eb8d3 100644 --- a/plugins/module_utils/utils.py +++ b/plugins/module_utils/utils.py @@ -54,6 +54,7 @@ "location_types", "manufacturers", "modules", + "module_bay_templates", "module_types", "platforms", "power_feeds", @@ -119,6 +120,7 @@ location_type="name", manufacturer="name", master="name", + module_bay_template="name", module_type="model", nat_inside="address", nat_outside="address", @@ -186,6 +188,7 @@ "location_type": "location_types", "manufacturer": "manufacturers", "module": "modules", + "module_bay_template": "module_bay_templates", "module_type": "module_types", "master": "devices", "nat_inside": "ip_addresses", @@ -262,6 +265,7 @@ "location_types": "location_type", "manufacturers": "manufacturer", "modules": "module", + "module_bay_templates": "module_bay_template", "module_types": "module_type", "namespaces": "namespace", "permissions": "permission", @@ -345,6 +349,7 @@ "location_type": set(["name"]), "manufacturer": set(["name"]), "master": set(["name"]), + "module_bay_template": set(["name"]), "module_type": set(["model"]), "namespace": set(["name"]), "nat_inside": set(["namespace", "address"]), diff --git a/plugins/modules/module_bay_template.py b/plugins/modules/module_bay_template.py new file mode 100644 index 00000000..52306885 --- /dev/null +++ b/plugins/modules/module_bay_template.py @@ -0,0 +1,138 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Network to Code (@networktocode) +# 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_bay_template +short_description: Create, update or delete module bay templates within Nautobot +description: + - Creates, updates or removes module bay templates 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: + device_type: + description: + - The device type of the module bay template + required: false + type: raw + module_type: + description: + - The module type of the module bay template + required: false + type: raw + name: + description: + - The name of the module bay template + required: true + type: str + label: + description: + - The label of the module bay template + required: false + type: str + position: + description: + - The position of the module bay within the device or module + required: false + type: str + description: + description: + - The description of the module bay template + required: false + type: str +""" + +EXAMPLES = r""" +- name: Create a module bay template + networktocode.nautobot.module_bay_template: + url: http://nautobot.local + token: thisIsMyToken + module_type: HooverMaxProModel60 + name: Edward Galbraith + label: Br Ba + position: "1" + description: Granite State + state: present + +- name: Delete a module bay template + networktocode.nautobot.module_bay_template: + url: http://nautobot.local + token: thisIsMyToken + name: Edward Galbraith + state: absent +""" + +RETURN = r""" +module_bay_template: + 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_MODULE_BAY_TEMPLATES, +) +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( + device_type=dict(required=False, type="raw"), + module_type=dict(required=False, type="raw"), + name=dict(required=True, type="str"), + label=dict(required=False, type="str"), + position=dict(required=False, type="str"), + description=dict(required=False, type="str"), + ) + ) + + required_one_of = [ + ("device_type", "module_type"), + ] + mutually_exclusive = [ + ("device_type", "module_type"), + ] + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + ) + module_bay_template = NautobotDcimModule(module, NB_MODULE_BAY_TEMPLATES) + module_bay_template.run() + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/tests/integration/targets/latest/tasks/module_bay_template.yml b/tests/integration/targets/latest/tasks/module_bay_template.yml new file mode 100644 index 00000000..d2816655 --- /dev/null +++ b/tests/integration/targets/latest/tasks/module_bay_template.yml @@ -0,0 +1,169 @@ +--- +## +## +### PYNAUTOBOT_MODULE_BAY_TEMPLATE +## +## +- set_fact: + test_module_type: "{{ lookup('networktocode.nautobot.lookup', 'module-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"HooverMaxProModel60\"') }}" + test_device_type: "{{ lookup('networktocode.nautobot.lookup', 'device-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"Cisco Test\"') }}" + +- name: "1 - Create module bay template with minimum information" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + state: present + register: test_one + +- name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_bay_template']['name'] == "Edward Galbraith" + - test_one['module_bay_template']['module_type'] == test_module_type['key'] + - test_one['msg'] == "module_bay_template Edward Galbraith created" + +- name: "2 - Create module bay template with minimum information idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + state: present + register: test_two + +- name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_bay_template']['name'] == "Edward Galbraith" + - test_one['module_bay_template']['module_type'] == test_module_type['key'] + - test_two['msg'] == "module_bay_template Edward Galbraith already exists" + +- name: "3 - Update module bay template" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + label: Br Ba + position: "1" + description: Granite State + state: present + register: test_three + +- name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['label'] == "Br Ba" + - test_three['diff']['after']['position'] == "1" + - test_three['diff']['after']['description'] == "Granite State" + - test_three['module_bay_template']['name'] == "Edward Galbraith" + - test_three['module_bay_template']['module_type'] == test_module_type['key'] + - test_three['module_bay_template']['label'] == "Br Ba" + - test_three['module_bay_template']['position'] == "1" + - test_three['module_bay_template']['description'] == "Granite State" + - test_three['msg'] == "module_bay_template Edward Galbraith updated" + +- name: "4 - Update idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + label: Br Ba + position: "1" + description: Granite State + state: present + register: test_four + +- name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_bay_template']['name'] == "Edward Galbraith" + - test_four['msg'] == "module_bay_template Edward Galbraith already exists" + +- name: "5 - Create module bay template with all params" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + label: test1234 + position: "42" + description: Cisco Test Module Bay + state: present + register: test_five + +- name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_bay_template']['name'] == "Test1234" + - test_five['module_bay_template']['label'] == "test1234" + - test_five['module_bay_template']['position'] == "42" + - test_five['module_bay_template']['description'] == "Cisco Test Module Bay" + - test_five['module_bay_template']['device_type'] == test_device_type['key'] + - test_five['msg'] == "module_bay_template Test1234 created" + +- name: "6 - Create module bay template with all params idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + label: test1234 + position: "42" + description: Cisco Test Module Bay + state: present + register: test_six + +- name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_five['module_bay_template']['name'] == "Test1234" + - test_five['module_bay_template']['label'] == "test1234" + - test_five['module_bay_template']['position'] == "42" + - test_five['module_bay_template']['description'] == "Cisco Test Module Bay" + - test_five['module_bay_template']['device_type'] == test_device_type['key'] + - test_six['msg'] == "module_bay_template Test1234 already exists" + +- name: "7 - Delete" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + state: absent + register: test_seven + +- name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_bay_template Test1234 deleted" + +- name: "8 - Delete idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + state: absent + register: test_eight + +- name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_bay_template'] == None + - test_eight['msg'] == "module_bay_template Test1234 already absent" From 56f3637d7a2458302b4e4b167555d6dac49a68d3 Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Sat, 9 Nov 2024 05:29:43 +0000 Subject: [PATCH 3/8] Added module bays model and tests --- plugins/lookup/lookup.py | 2 + plugins/module_utils/dcim.py | 2 + plugins/module_utils/utils.py | 8 + plugins/modules/module_bay.py | 152 +++++++++++++++ plugins/modules/module_bay_template.py | 1 + .../targets/latest/tasks/module_bay.yml | 178 ++++++++++++++++++ 6 files changed, 343 insertions(+) create mode 100644 plugins/modules/module_bay.py create mode 100644 tests/integration/targets/latest/tasks/module_bay.yml diff --git a/plugins/lookup/lookup.py b/plugins/lookup/lookup.py index 06e18eea..736b8a7e 100644 --- a/plugins/lookup/lookup.py +++ b/plugins/lookup/lookup.py @@ -203,6 +203,8 @@ 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}, diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index 9948ada9..d3caf3b0 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -33,6 +33,7 @@ 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_NAMESPACES = "namespaces" NB_PLATFORMS = "platforms" @@ -72,6 +73,7 @@ def run(self): - inventory_items - manufacturers - module_bay_templates + - module_bays - module_types - platforms - power_feeds diff --git a/plugins/module_utils/utils.py b/plugins/module_utils/utils.py index 904eb8d3..3cf1b08f 100644 --- a/plugins/module_utils/utils.py +++ b/plugins/module_utils/utils.py @@ -55,6 +55,7 @@ "manufacturers", "modules", "module_bay_templates", + "module_bays", "module_types", "platforms", "power_feeds", @@ -121,6 +122,7 @@ manufacturer="name", master="name", module_bay_template="name", + module_bay="name", module_type="model", nat_inside="address", nat_outside="address", @@ -189,12 +191,15 @@ "manufacturer": "manufacturers", "module": "modules", "module_bay_template": "module_bay_templates", + "module_bay": "module_bays", "module_type": "module_types", "master": "devices", "nat_inside": "ip_addresses", "nat_outside": "ip_addresses", "namespace": "namespaces", "platform": "platforms", + "parent_device": "devices", + "parent_module": "modules", "parent_rack_group": "rack_groups", "parent_location": "locations", "parent_location_type": "location_types", @@ -266,6 +271,7 @@ "manufacturers": "manufacturer", "modules": "module", "module_bay_templates": "module_bay_template", + "module_bays": "module_bay", "module_types": "module_type", "namespaces": "namespace", "permissions": "permission", @@ -350,9 +356,11 @@ "manufacturer": set(["name"]), "master": set(["name"]), "module_bay_template": set(["name"]), + "module_bay": set(["name", "parent_device", "parent_module"]), "module_type": set(["model"]), "namespace": set(["name"]), "nat_inside": set(["namespace", "address"]), + "parent_module": set(["module_type", "parent_module_bay"]), "parent_rack_group": set(["name"]), "parent_tenant_group": set(["name"]), "permission": set(["name"]), diff --git a/plugins/modules/module_bay.py b/plugins/modules/module_bay.py new file mode 100644 index 00000000..0da93f68 --- /dev/null +++ b/plugins/modules/module_bay.py @@ -0,0 +1,152 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Network to Code (@networktocode) +# 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_bay +short_description: Create, update or delete module bays within Nautobot +description: + - Creates, updates or removes module bays 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: + parent_device: + description: + - The parent device of the module bay + required: false + type: raw + parent_module: + description: + - The parent module of the module bay + required: false + type: raw + name: + description: + - The name of the module bay + required: true + type: str + label: + description: + - The label of the module bay + required: false + type: str + position: + description: + - The position of the module bay within the device or module + required: false + type: str + description: + description: + - The description of the module bay + required: false + type: str +""" + +EXAMPLES = r""" +- name: Create a module bay inside a device + networktocode.nautobot.module_bay: + url: http://nautobot.local + token: thisIsMyToken + parent_device: test100 + name: Watch Bay + label: watchbay + position: "42" + description: The bay of watches + state: present + +- name: Create a module bay inside a module + networktocode.nautobot.module_bay: + url: http://nautobot.local + token: thisIsMyToken + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ some_module_bay['key'] }}" + name: Fixing Good + label: FiXiNgGoOd + position: "321" + description: Good Fixing is better than Bad Breaking + state: present + +- name: Delete a module bay + networktocode.nautobot.module_bay: + url: http://nautobot.local + token: thisIsMyToken + parent_device: test100 + name: Watch Bay + state: absent +""" + +RETURN = r""" +module_bay: + 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_MODULE_BAYS, +) +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( + parent_device=dict(required=False, type="raw"), + parent_module=dict(required=False, type="raw"), + name=dict(required=True, type="str"), + label=dict(required=False, type="str"), + position=dict(required=False, type="str"), + description=dict(required=False, type="str"), + ) + ) + + required_one_of = [ + ("parent_device", "parent_module"), + ] + mutually_exclusive = [ + ("parent_device", "parent_module"), + ] + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + ) + module_bay = NautobotDcimModule(module, NB_MODULE_BAYS) + module_bay.run() + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/plugins/modules/module_bay_template.py b/plugins/modules/module_bay_template.py index 52306885..b4c86064 100644 --- a/plugins/modules/module_bay_template.py +++ b/plugins/modules/module_bay_template.py @@ -72,6 +72,7 @@ networktocode.nautobot.module_bay_template: url: http://nautobot.local token: thisIsMyToken + module_type: HooverMaxProModel60 name: Edward Galbraith state: absent """ diff --git a/tests/integration/targets/latest/tasks/module_bay.yml b/tests/integration/targets/latest/tasks/module_bay.yml new file mode 100644 index 00000000..e9b695a5 --- /dev/null +++ b/tests/integration/targets/latest/tasks/module_bay.yml @@ -0,0 +1,178 @@ +--- +## +## +### PYNAUTOBOT_MODULE_BAY +## +## +- set_fact: + test_module: '{{ lookup(''networktocode.nautobot.lookup'', ''modules'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''q="HooverMaxProModel60"'') }}' + test_device: "{{ lookup('networktocode.nautobot.lookup', 'devices', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"test100\"') }}" + test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStrip"'') }}' + +- name: "1 - Create module bay with minimum information" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + state: present + register: test_one + +- name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_bay']['name'] == "Watch Bay" + - test_one['module_bay']['parent_device'] == test_device['key'] + - test_one['msg'] == "module_bay Watch Bay created" + +- name: "2 - Create module bay with minimum information idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + state: present + register: test_two + +- name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_bay']['name'] == "Watch Bay" + - test_one['module_bay']['parent_device'] == test_device['key'] + - test_two['msg'] == "module_bay Watch Bay already exists" + +- name: "3 - Update module bay" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + label: watchbay + position: "42" + description: The bay of watches + state: present + register: test_three + +- name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['label'] == "watchbay" + - test_three['diff']['after']['position'] == "42" + - test_three['diff']['after']['description'] == "The bay of watches" + - test_three['module_bay']['name'] == "Watch Bay" + - test_three['module_bay']['parent_device'] == test_device['key'] + - test_three['module_bay']['label'] == "watchbay" + - test_three['module_bay']['position'] == "42" + - test_three['module_bay']['description'] == "The bay of watches" + - test_three['msg'] == "module_bay Watch Bay updated" + +- name: "4 - Update idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + label: watchbay + position: "42" + description: The bay of watches + state: present + register: test_four + +- name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_bay']['name'] == "Watch Bay" + - test_four['msg'] == "module_bay Watch Bay already exists" + +- name: "5 - Create module bay with all params" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + label: FiXiNgGoOd + position: "321" + description: Good Fixing is better than Bad Breaking + state: present + register: test_five + +- name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_bay']['name'] == "Fixing Good" + - test_five['module_bay']['label'] == "FiXiNgGoOd" + - test_five['module_bay']['position'] == "321" + - test_five['module_bay']['description'] == "Good Fixing is better than Bad Breaking" + - test_five['module_bay']['parent_module'] == test_module['key'] + - test_five['msg'] == "module_bay Fixing Good created" + +- name: "6 - Create module bay with all params idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + label: FiXiNgGoOd + position: "321" + description: Good Fixing is better than Bad Breaking + state: present + register: test_six + +- name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_five['module_bay']['name'] == "Fixing Good" + - test_five['module_bay']['label'] == "FiXiNgGoOd" + - test_five['module_bay']['position'] == "321" + - test_five['module_bay']['description'] == "Good Fixing is better than Bad Breaking" + - test_five['module_bay']['parent_module'] == test_module['key'] + - test_six['msg'] == "module_bay Fixing Good already exists" + +- name: "7 - Delete" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + state: absent + register: test_seven + +- name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_bay Fixing Good deleted" + +- name: "8 - Delete idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + state: absent + register: test_eight + +- name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_bay'] == None + - test_eight['msg'] == "module_bay Fixing Good already absent" From f04695717776376e223cd457f5e2cb762eaf8ae1 Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Sun, 10 Nov 2024 00:25:55 +0000 Subject: [PATCH 4/8] Added module model and tests, added all module tests to CI --- plugins/module_utils/dcim.py | 16 ++ plugins/module_utils/utils.py | 9 +- plugins/modules/module.py | 170 +++++++++++++++ tests/integration/nautobot-populate.py | 6 +- .../integration/targets/latest/tasks/main.yml | 36 ++++ .../targets/latest/tasks/module.yml | 199 ++++++++++++++++++ .../targets/latest/tasks/module_bay.yml | 10 +- .../latest/tasks/module_bay_template.yml | 10 +- 8 files changed, 442 insertions(+), 14 deletions(-) create mode 100644 plugins/modules/module.py create mode 100644 tests/integration/targets/latest/tasks/module.yml diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index d3caf3b0..e76be678 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -35,6 +35,7 @@ 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" @@ -75,6 +76,7 @@ def run(self): - module_bay_templates - module_bays - module_types + - modules - platforms - power_feeds - power_outlets @@ -139,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", "—") + + name = f"{parent_parent_name} > {parent_name} > {module_type_name}" + # Make color params lowercase if data.get("color"): data["color"] = data["color"].lower() diff --git a/plugins/module_utils/utils.py b/plugins/module_utils/utils.py index 3cf1b08f..896cf326 100644 --- a/plugins/module_utils/utils.py +++ b/plugins/module_utils/utils.py @@ -53,10 +53,10 @@ "locations", "location_types", "manufacturers", - "modules", "module_bay_templates", "module_bays", "module_types", + "modules", "platforms", "power_feeds", "power_outlets", @@ -189,16 +189,17 @@ "location": "locations", "location_type": "location_types", "manufacturer": "manufacturers", - "module": "modules", "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", @@ -269,10 +270,10 @@ "locations": "location", "location_types": "location_type", "manufacturers": "manufacturer", - "modules": "module", "module_bay_templates": "module_bay_template", "module_bays": "module_bay", "module_types": "module_type", + "modules": "module", "namespaces": "namespace", "permissions": "permission", "platforms": "platform", @@ -358,8 +359,10 @@ "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"]), diff --git a/plugins/modules/module.py b/plugins/modules/module.py new file mode 100644 index 00000000..67f2836b --- /dev/null +++ b/plugins/modules/module.py @@ -0,0 +1,170 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2024, Network to Code (@networktocode) +# 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 + 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() + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/tests/integration/nautobot-populate.py b/tests/integration/nautobot-populate.py index 260a1220..4630d491 100755 --- a/tests/integration/nautobot-populate.py +++ b/tests/integration/nautobot-populate.py @@ -119,6 +119,8 @@ def make_nautobot_calls(endpoint, payload): if nautobot_version >= version.parse("2.2"): location_content_types.append("dcim.controller") +if nautobot_version >= version.parse("2.3"): + location_content_types.append("dcim.module") location_types = [{"name": "My Parent Location Type", "content_types": location_content_types, "nestable": True}] created_location_types = make_nautobot_calls(nb.dcim.location_types, location_types) @@ -267,6 +269,8 @@ def make_nautobot_calls(endpoint, payload): if nautobot_version >= version.parse("2.2"): device_roles.append({"name": "Test Controller Role", "color": "e91e65", "vm_role": False, "content_types": ["dcim.controller"]}) +if nautobot_version >= version.parse("2.3"): + device_roles.append({"name": "Test Module Role", "color": "795548", "vm_role": False, "content_types": ["dcim.module"]}) created_device_roles = make_nautobot_calls(nb.extras.roles, device_roles) @@ -647,7 +651,7 @@ def make_nautobot_calls(endpoint, payload): created_power_outlet_module_types = make_nautobot_calls(nb.dcim.module_types, power_outlet_module_types) # Create a module bay - power_outlet_module_bays = [{"parent_device": test100.id, "name": "PowerStrip"}] + power_outlet_module_bays = [{"parent_device": test100.id, "name": "PowerStrip"}, {"parent_device": test100.id, "name": "PowerStripTwo"}] created_power_outlet_module_bays = make_nautobot_calls(nb.dcim.module_bays, power_outlet_module_bays) # Assign module type to module bay diff --git a/tests/integration/targets/latest/tasks/main.yml b/tests/integration/targets/latest/tasks/main.yml index 30291773..59443c19 100644 --- a/tests/integration/targets/latest/tasks/main.yml +++ b/tests/integration/targets/latest/tasks/main.yml @@ -590,3 +590,39 @@ - controller tags: - controller + +- name: "PYNAUTOBOT_MODULE_TYPE TESTS" + include_tasks: + file: "module_type.yml" + apply: + tags: + - module_type + tags: + - module_type + +- name: "PYNAUTOBOT_MODULE_BAY_TEMPLATE TESTS" + include_tasks: + file: "module_bay_template.yml" + apply: + tags: + - module_bay_template + tags: + - module_bay_template + +- name: "PYNAUTOBOT_MODULE_BAY TESTS" + include_tasks: + file: "module_bay.yml" + apply: + tags: + - module_bay + tags: + - module_bay + +- name: "PYNAUTOBOT_MODULE TESTS" + include_tasks: + file: "module.yml" + apply: + tags: + - module + tags: + - module diff --git a/tests/integration/targets/latest/tasks/module.yml b/tests/integration/targets/latest/tasks/module.yml new file mode 100644 index 00000000..d33934c4 --- /dev/null +++ b/tests/integration/targets/latest/tasks/module.yml @@ -0,0 +1,199 @@ +--- +## +## +### PYNAUTOBOT_MODULE +## +## +- set_fact: + test_module_type: '{{ lookup(''networktocode.nautobot.lookup'', ''module-types'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''model="HooverMaxProModel60"'') }}' + test_module_role: "{{ lookup('networktocode.nautobot.lookup', 'roles', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Module Role\"') }}" + test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStripTwo"'') }}' + test_module_status: "{{ lookup('networktocode.nautobot.lookup', 'statuses', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=Active') }}" + test_module_tenant: "{{ lookup('networktocode.nautobot.lookup', 'tenants', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Tenant\"') }}" + test_module_child_location: "{{ lookup('networktocode.nautobot.lookup', 'locations', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Child Test Location\" parent=\"Parent Test Location\"') }}" + +- name: "1 - Create module with minimum information" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + status: Active + state: present + register: test_one + +- name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module']['module_type'] == test_module_type['key'] + - test_one['module']['parent_module_bay'] == test_module_bay['key'] + - test_one['module']['status'] == test_module_status['key'] + - test_one['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 created" + +- name: "2 - Create module with minimum information idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + status: Active + state: present + register: test_two + +- name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module']['module_type'] == test_module_type['key'] + - test_two['module']['parent_module_bay'] == test_module_bay['key'] + - test_two['module']['status'] == test_module_status['key'] + - test_two['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" + +- name: "3 - Update module" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + serial: "123456" + asset_tag: "654321" + state: present + register: test_three + +- name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['serial'] == "123456" + - test_three['diff']['after']['asset_tag'] == "654321" + - test_three['module']['module_type'] == test_module_type['key'] + - test_three['module']['parent_module_bay'] == test_module_bay['key'] + - test_three['module']['status'] == test_module_status['key'] + - test_three['module']['serial'] == "123456" + - test_three['module']['asset_tag'] == "654321" + - test_three['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 updated" + +- name: "4 - Update idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + serial: "123456" + asset_tag: "654321" + state: present + register: test_four + +- name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module']['module_type'] == test_module_type['key'] + - test_four['module']['parent_module_bay'] == test_module_bay['key'] + - test_four['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" + +- name: "5 - Create module with all params" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + 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 + register: test_five + +- name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module']['module_type'] == test_module_type['key'] + - test_five['module']['location'] == test_module_child_location['key'] + - test_five['module']['serial'] == "654321" + - test_five['module']['asset_tag'] == "123456" + - test_five['module']['role'] == test_module_role['key'] + - test_five['module']['status'] == test_module_status['key'] + - test_five['module']['tenant'] == test_module_tenant['key'] + - test_five['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 created" + +- name: "6 - Create module with all params idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + 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 + register: test_six + +- name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module']['module_type'] == test_module_type['key'] + - test_six['module']['location'] == test_module_child_location['key'] + - test_six['module']['serial'] == "654321" + - test_six['module']['asset_tag'] == "123456" + - test_six['module']['role'] == test_module_role['key'] + - test_six['module']['status'] == test_module_status['key'] + - test_six['module']['tenant'] == test_module_tenant['key'] + - test_six['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already exists" + +- name: "7 - Delete" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + location: + name: "Child Test Location" + parent: "Parent Test Location" + state: absent + register: test_seven + +- name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 deleted" + +- name: "8 - Delete idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + location: + name: "Child Test Location" + parent: "Parent Test Location" + state: absent + register: test_eight + +- name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module'] == None + - test_eight['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already absent" diff --git a/tests/integration/targets/latest/tasks/module_bay.yml b/tests/integration/targets/latest/tasks/module_bay.yml index e9b695a5..5d0dc36c 100644 --- a/tests/integration/targets/latest/tasks/module_bay.yml +++ b/tests/integration/targets/latest/tasks/module_bay.yml @@ -133,11 +133,11 @@ assert: that: - not test_six['changed'] - - test_five['module_bay']['name'] == "Fixing Good" - - test_five['module_bay']['label'] == "FiXiNgGoOd" - - test_five['module_bay']['position'] == "321" - - test_five['module_bay']['description'] == "Good Fixing is better than Bad Breaking" - - test_five['module_bay']['parent_module'] == test_module['key'] + - test_six['module_bay']['name'] == "Fixing Good" + - test_six['module_bay']['label'] == "FiXiNgGoOd" + - test_six['module_bay']['position'] == "321" + - test_six['module_bay']['description'] == "Good Fixing is better than Bad Breaking" + - test_six['module_bay']['parent_module'] == test_module['key'] - test_six['msg'] == "module_bay Fixing Good already exists" - name: "7 - Delete" diff --git a/tests/integration/targets/latest/tasks/module_bay_template.yml b/tests/integration/targets/latest/tasks/module_bay_template.yml index d2816655..3a3ef1ff 100644 --- a/tests/integration/targets/latest/tasks/module_bay_template.yml +++ b/tests/integration/targets/latest/tasks/module_bay_template.yml @@ -128,11 +128,11 @@ assert: that: - not test_six['changed'] - - test_five['module_bay_template']['name'] == "Test1234" - - test_five['module_bay_template']['label'] == "test1234" - - test_five['module_bay_template']['position'] == "42" - - test_five['module_bay_template']['description'] == "Cisco Test Module Bay" - - test_five['module_bay_template']['device_type'] == test_device_type['key'] + - test_six['module_bay_template']['name'] == "Test1234" + - test_six['module_bay_template']['label'] == "test1234" + - test_six['module_bay_template']['position'] == "42" + - test_six['module_bay_template']['description'] == "Cisco Test Module Bay" + - test_six['module_bay_template']['device_type'] == test_device_type['key'] - test_six['msg'] == "module_bay_template Test1234 already exists" - name: "7 - Delete" From 4b47a5f62672e2eb27631f3a78e62e28890f03a7 Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:26:11 +0000 Subject: [PATCH 5/8] Fixed var issue in assertions --- tests/integration/targets/latest/tasks/module_bay.yml | 2 +- tests/integration/targets/latest/tasks/module_bay_template.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/targets/latest/tasks/module_bay.yml b/tests/integration/targets/latest/tasks/module_bay.yml index 5d0dc36c..a369d81e 100644 --- a/tests/integration/targets/latest/tasks/module_bay.yml +++ b/tests/integration/targets/latest/tasks/module_bay.yml @@ -42,7 +42,7 @@ that: - not test_two['changed'] - test_two['module_bay']['name'] == "Watch Bay" - - test_one['module_bay']['parent_device'] == test_device['key'] + - test_two['module_bay']['parent_device'] == test_device['key'] - test_two['msg'] == "module_bay Watch Bay already exists" - name: "3 - Update module bay" diff --git a/tests/integration/targets/latest/tasks/module_bay_template.yml b/tests/integration/targets/latest/tasks/module_bay_template.yml index 3a3ef1ff..663eec8b 100644 --- a/tests/integration/targets/latest/tasks/module_bay_template.yml +++ b/tests/integration/targets/latest/tasks/module_bay_template.yml @@ -41,7 +41,7 @@ that: - not test_two['changed'] - test_two['module_bay_template']['name'] == "Edward Galbraith" - - test_one['module_bay_template']['module_type'] == test_module_type['key'] + - test_two['module_bay_template']['module_type'] == test_module_type['key'] - test_two['msg'] == "module_bay_template Edward Galbraith already exists" - name: "3 - Update module bay template" From 387323919f6176947da9620daf1a4750aa93a64b Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Mon, 11 Nov 2024 20:39:36 +0000 Subject: [PATCH 6/8] Changed integration test for modules to only run on 2.3+ and fixed minor issues --- plugins/modules/module.py | 6 +- .../targets/latest/tasks/module.yml | 390 +++++++++--------- .../targets/latest/tasks/module_bay.yml | 348 ++++++++-------- .../latest/tasks/module_bay_template.yml | 330 +++++++-------- .../targets/latest/tasks/module_type.yml | 306 +++++++------- 5 files changed, 698 insertions(+), 682 deletions(-) diff --git a/plugins/modules/module.py b/plugins/modules/module.py index 67f2836b..97854f38 100644 --- a/plugins/modules/module.py +++ b/plugins/modules/module.py @@ -41,7 +41,7 @@ type: str role: description: - - The asset tag of the module + - The role of the module required: false type: raw status: @@ -162,8 +162,8 @@ def main(): mutually_exclusive=mutually_exclusive, ) - module = NautobotDcimModule(module, NB_MODULES) - module.run() + nb_module = NautobotDcimModule(module, NB_MODULES) + nb_module.run() if __name__ == "__main__": # pragma: no cover diff --git a/tests/integration/targets/latest/tasks/module.yml b/tests/integration/targets/latest/tasks/module.yml index d33934c4..6e0760e7 100644 --- a/tests/integration/targets/latest/tasks/module.yml +++ b/tests/integration/targets/latest/tasks/module.yml @@ -4,196 +4,200 @@ ### PYNAUTOBOT_MODULE ## ## -- set_fact: - test_module_type: '{{ lookup(''networktocode.nautobot.lookup'', ''module-types'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''model="HooverMaxProModel60"'') }}' - test_module_role: "{{ lookup('networktocode.nautobot.lookup', 'roles', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Module Role\"') }}" - test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStripTwo"'') }}' - test_module_status: "{{ lookup('networktocode.nautobot.lookup', 'statuses', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=Active') }}" - test_module_tenant: "{{ lookup('networktocode.nautobot.lookup', 'tenants', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Tenant\"') }}" - test_module_child_location: "{{ lookup('networktocode.nautobot.lookup', 'locations', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Child Test Location\" parent=\"Parent Test Location\"') }}" - -- name: "1 - Create module with minimum information" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - parent_module_bay: - name: PowerStripTwo - parent_device: test100 - status: Active - state: present - register: test_one - -- name: "1 - ASSERT" - assert: - that: - - test_one is changed - - test_one['diff']['before']['state'] == "absent" - - test_one['diff']['after']['state'] == "present" - - test_one['module']['module_type'] == test_module_type['key'] - - test_one['module']['parent_module_bay'] == test_module_bay['key'] - - test_one['module']['status'] == test_module_status['key'] - - test_one['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 created" - -- name: "2 - Create module with minimum information idempotent" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - parent_module_bay: - name: PowerStripTwo - parent_device: test100 - status: Active - state: present - register: test_two - -- name: "2 - ASSERT" - assert: - that: - - not test_two['changed'] - - test_two['module']['module_type'] == test_module_type['key'] - - test_two['module']['parent_module_bay'] == test_module_bay['key'] - - test_two['module']['status'] == test_module_status['key'] - - test_two['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" - -- name: "3 - Update module" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - parent_module_bay: - name: PowerStripTwo - parent_device: test100 - serial: "123456" - asset_tag: "654321" - state: present - register: test_three - -- name: "3 - ASSERT" - assert: - that: - - test_three is changed - - test_three['diff']['after']['serial'] == "123456" - - test_three['diff']['after']['asset_tag'] == "654321" - - test_three['module']['module_type'] == test_module_type['key'] - - test_three['module']['parent_module_bay'] == test_module_bay['key'] - - test_three['module']['status'] == test_module_status['key'] - - test_three['module']['serial'] == "123456" - - test_three['module']['asset_tag'] == "654321" - - test_three['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 updated" - -- name: "4 - Update idempotent" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - parent_module_bay: - name: PowerStripTwo - parent_device: test100 - serial: "123456" - asset_tag: "654321" - state: present - register: test_four - -- name: "4 - ASSERT" - assert: - that: - - not test_four['changed'] - - test_four['module']['module_type'] == test_module_type['key'] - - test_four['module']['parent_module_bay'] == test_module_bay['key'] - - test_four['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" - -- name: "5 - Create module with all params" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - 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 - register: test_five - -- name: "5 - ASSERT" - assert: - that: - - test_five is changed - - test_five['module']['module_type'] == test_module_type['key'] - - test_five['module']['location'] == test_module_child_location['key'] - - test_five['module']['serial'] == "654321" - - test_five['module']['asset_tag'] == "123456" - - test_five['module']['role'] == test_module_role['key'] - - test_five['module']['status'] == test_module_status['key'] - - test_five['module']['tenant'] == test_module_tenant['key'] - - test_five['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 created" - -- name: "6 - Create module with all params idempotent" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - 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 - register: test_six - -- name: "6 - ASSERT" - assert: - that: - - not test_six['changed'] - - test_six['module']['module_type'] == test_module_type['key'] - - test_six['module']['location'] == test_module_child_location['key'] - - test_six['module']['serial'] == "654321" - - test_six['module']['asset_tag'] == "123456" - - test_six['module']['role'] == test_module_role['key'] - - test_six['module']['status'] == test_module_status['key'] - - test_six['module']['tenant'] == test_module_tenant['key'] - - test_six['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already exists" - -- name: "7 - Delete" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - location: - name: "Child Test Location" - parent: "Parent Test Location" - state: absent - register: test_seven - -- name: "7 - ASSERT" - assert: - that: - - test_seven is changed - - test_seven['diff']['before']['state'] == "present" - - test_seven['diff']['after']['state'] == "absent" - - test_seven['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 deleted" - -- name: "8 - Delete idempotent" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - location: - name: "Child Test Location" - parent: "Parent Test Location" - state: absent - register: test_eight - -- name: "8 - ASSERT`" - assert: - that: - - not test_eight['changed'] - - test_eight['module'] == None - - test_eight['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already absent" +- name: "NAUTOBOT 2.3+ MODULE TESTS" + when: + - "nautobot_version is version('2.3', '>=')" + block: + - set_fact: + test_module_type: '{{ lookup(''networktocode.nautobot.lookup'', ''module-types'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''model="HooverMaxProModel60"'') }}' + test_module_role: "{{ lookup('networktocode.nautobot.lookup', 'roles', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Module Role\"') }}" + test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStripTwo"'') }}' + test_module_status: "{{ lookup('networktocode.nautobot.lookup', 'statuses', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=Active') }}" + test_module_tenant: "{{ lookup('networktocode.nautobot.lookup', 'tenants', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Tenant\"') }}" + test_module_child_location: "{{ lookup('networktocode.nautobot.lookup', 'locations', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Child Test Location\" parent=\"Parent Test Location\"') }}" + + - name: "1 - Create module with minimum information" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + status: Active + state: present + register: test_one + + - name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module']['module_type'] == test_module_type['key'] + - test_one['module']['parent_module_bay'] == test_module_bay['key'] + - test_one['module']['status'] == test_module_status['key'] + - test_one['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 created" + + - name: "2 - Create module with minimum information idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + status: Active + state: present + register: test_two + + - name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module']['module_type'] == test_module_type['key'] + - test_two['module']['parent_module_bay'] == test_module_bay['key'] + - test_two['module']['status'] == test_module_status['key'] + - test_two['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" + + - name: "3 - Update module" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + serial: "123456" + asset_tag: "654321" + state: present + register: test_three + + - name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['serial'] == "123456" + - test_three['diff']['after']['asset_tag'] == "654321" + - test_three['module']['module_type'] == test_module_type['key'] + - test_three['module']['parent_module_bay'] == test_module_bay['key'] + - test_three['module']['status'] == test_module_status['key'] + - test_three['module']['serial'] == "123456" + - test_three['module']['asset_tag'] == "654321" + - test_three['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 updated" + + - name: "4 - Update idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: + name: PowerStripTwo + parent_device: test100 + serial: "123456" + asset_tag: "654321" + state: present + register: test_four + + - name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module']['module_type'] == test_module_type['key'] + - test_four['module']['parent_module_bay'] == test_module_bay['key'] + - test_four['msg'] == "module test100 > PowerStripTwo > HooverMaxProModel60 already exists" + + - name: "5 - Create module with all params" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + 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 + register: test_five + + - name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module']['module_type'] == test_module_type['key'] + - test_five['module']['location'] == test_module_child_location['key'] + - test_five['module']['serial'] == "654321" + - test_five['module']['asset_tag'] == "123456" + - test_five['module']['role'] == test_module_role['key'] + - test_five['module']['status'] == test_module_status['key'] + - test_five['module']['tenant'] == test_module_tenant['key'] + - test_five['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 created" + + - name: "6 - Create module with all params idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + 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 + register: test_six + + - name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module']['module_type'] == test_module_type['key'] + - test_six['module']['location'] == test_module_child_location['key'] + - test_six['module']['serial'] == "654321" + - test_six['module']['asset_tag'] == "123456" + - test_six['module']['role'] == test_module_role['key'] + - test_six['module']['status'] == test_module_status['key'] + - test_six['module']['tenant'] == test_module_tenant['key'] + - test_six['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already exists" + + - name: "7 - Delete" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + location: + name: "Child Test Location" + parent: "Parent Test Location" + state: absent + register: test_seven + + - name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 deleted" + + - name: "8 - Delete idempotent" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + location: + name: "Child Test Location" + parent: "Parent Test Location" + state: absent + register: test_eight + + - name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module'] == None + - test_eight['msg'] == "module Parent Test Location > Child Test Location > HooverMaxProModel60 already absent" diff --git a/tests/integration/targets/latest/tasks/module_bay.yml b/tests/integration/targets/latest/tasks/module_bay.yml index a369d81e..9446b299 100644 --- a/tests/integration/targets/latest/tasks/module_bay.yml +++ b/tests/integration/targets/latest/tasks/module_bay.yml @@ -4,175 +4,179 @@ ### PYNAUTOBOT_MODULE_BAY ## ## -- set_fact: - test_module: '{{ lookup(''networktocode.nautobot.lookup'', ''modules'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''q="HooverMaxProModel60"'') }}' - test_device: "{{ lookup('networktocode.nautobot.lookup', 'devices', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"test100\"') }}" - test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStrip"'') }}' - -- name: "1 - Create module bay with minimum information" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_device: test100 - name: Watch Bay - state: present - register: test_one - -- name: "1 - ASSERT" - assert: - that: - - test_one is changed - - test_one['diff']['before']['state'] == "absent" - - test_one['diff']['after']['state'] == "present" - - test_one['module_bay']['name'] == "Watch Bay" - - test_one['module_bay']['parent_device'] == test_device['key'] - - test_one['msg'] == "module_bay Watch Bay created" - -- name: "2 - Create module bay with minimum information idempotent" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_device: test100 - name: Watch Bay - state: present - register: test_two - -- name: "2 - ASSERT" - assert: - that: - - not test_two['changed'] - - test_two['module_bay']['name'] == "Watch Bay" - - test_two['module_bay']['parent_device'] == test_device['key'] - - test_two['msg'] == "module_bay Watch Bay already exists" - -- name: "3 - Update module bay" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_device: test100 - name: Watch Bay - label: watchbay - position: "42" - description: The bay of watches - state: present - register: test_three - -- name: "3 - ASSERT" - assert: - that: - - test_three is changed - - test_three['diff']['after']['label'] == "watchbay" - - test_three['diff']['after']['position'] == "42" - - test_three['diff']['after']['description'] == "The bay of watches" - - test_three['module_bay']['name'] == "Watch Bay" - - test_three['module_bay']['parent_device'] == test_device['key'] - - test_three['module_bay']['label'] == "watchbay" - - test_three['module_bay']['position'] == "42" - - test_three['module_bay']['description'] == "The bay of watches" - - test_three['msg'] == "module_bay Watch Bay updated" - -- name: "4 - Update idempotent" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_device: test100 - name: Watch Bay - label: watchbay - position: "42" - description: The bay of watches - state: present - register: test_four - -- name: "4 - ASSERT" - assert: - that: - - not test_four['changed'] - - test_four['module_bay']['name'] == "Watch Bay" - - test_four['msg'] == "module_bay Watch Bay already exists" - -- name: "5 - Create module bay with all params" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_module: - module_type: HooverMaxProModel60 - parent_module_bay: "{{ test_module_bay['key'] }}" - name: Fixing Good - label: FiXiNgGoOd - position: "321" - description: Good Fixing is better than Bad Breaking - state: present - register: test_five - -- name: "5 - ASSERT" - assert: - that: - - test_five is changed - - test_five['module_bay']['name'] == "Fixing Good" - - test_five['module_bay']['label'] == "FiXiNgGoOd" - - test_five['module_bay']['position'] == "321" - - test_five['module_bay']['description'] == "Good Fixing is better than Bad Breaking" - - test_five['module_bay']['parent_module'] == test_module['key'] - - test_five['msg'] == "module_bay Fixing Good created" - -- name: "6 - Create module bay with all params idempotent" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_module: - module_type: HooverMaxProModel60 - parent_module_bay: "{{ test_module_bay['key'] }}" - name: Fixing Good - label: FiXiNgGoOd - position: "321" - description: Good Fixing is better than Bad Breaking - state: present - register: test_six - -- name: "6 - ASSERT" - assert: - that: - - not test_six['changed'] - - test_six['module_bay']['name'] == "Fixing Good" - - test_six['module_bay']['label'] == "FiXiNgGoOd" - - test_six['module_bay']['position'] == "321" - - test_six['module_bay']['description'] == "Good Fixing is better than Bad Breaking" - - test_six['module_bay']['parent_module'] == test_module['key'] - - test_six['msg'] == "module_bay Fixing Good already exists" - -- name: "7 - Delete" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_module: - module_type: HooverMaxProModel60 - parent_module_bay: "{{ test_module_bay['key'] }}" - name: Fixing Good - state: absent - register: test_seven - -- name: "7 - ASSERT" - assert: - that: - - test_seven is changed - - test_seven['diff']['before']['state'] == "present" - - test_seven['diff']['after']['state'] == "absent" - - test_seven['msg'] == "module_bay Fixing Good deleted" - -- name: "8 - Delete idempotent" - networktocode.nautobot.module_bay: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - parent_module: - module_type: HooverMaxProModel60 - parent_module_bay: "{{ test_module_bay['key'] }}" - name: Fixing Good - state: absent - register: test_eight - -- name: "8 - ASSERT`" - assert: - that: - - not test_eight['changed'] - - test_eight['module_bay'] == None - - test_eight['msg'] == "module_bay Fixing Good already absent" +- name: "NAUTOBOT 2.3+ MODULE BAY TESTS" + when: + - "nautobot_version is version('2.3', '>=')" + block: + - set_fact: + test_module: '{{ lookup(''networktocode.nautobot.lookup'', ''modules'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''q="HooverMaxProModel60"'') }}' + test_device: "{{ lookup('networktocode.nautobot.lookup', 'devices', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"test100\"') }}" + test_module_bay: '{{ lookup(''networktocode.nautobot.lookup'', ''module-bays'', api_endpoint=nautobot_url, token=nautobot_token, api_filter=''name="PowerStrip"'') }}' + + - name: "1 - Create module bay with minimum information" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + state: present + register: test_one + + - name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_bay']['name'] == "Watch Bay" + - test_one['module_bay']['parent_device'] == test_device['key'] + - test_one['msg'] == "module_bay Watch Bay created" + + - name: "2 - Create module bay with minimum information idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + state: present + register: test_two + + - name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_bay']['name'] == "Watch Bay" + - test_two['module_bay']['parent_device'] == test_device['key'] + - test_two['msg'] == "module_bay Watch Bay already exists" + + - name: "3 - Update module bay" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + label: watchbay + position: "42" + description: The bay of watches + state: present + register: test_three + + - name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['label'] == "watchbay" + - test_three['diff']['after']['position'] == "42" + - test_three['diff']['after']['description'] == "The bay of watches" + - test_three['module_bay']['name'] == "Watch Bay" + - test_three['module_bay']['parent_device'] == test_device['key'] + - test_three['module_bay']['label'] == "watchbay" + - test_three['module_bay']['position'] == "42" + - test_three['module_bay']['description'] == "The bay of watches" + - test_three['msg'] == "module_bay Watch Bay updated" + + - name: "4 - Update idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_device: test100 + name: Watch Bay + label: watchbay + position: "42" + description: The bay of watches + state: present + register: test_four + + - name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_bay']['name'] == "Watch Bay" + - test_four['msg'] == "module_bay Watch Bay already exists" + + - name: "5 - Create module bay with all params" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + label: FiXiNgGoOd + position: "321" + description: Good Fixing is better than Bad Breaking + state: present + register: test_five + + - name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_bay']['name'] == "Fixing Good" + - test_five['module_bay']['label'] == "FiXiNgGoOd" + - test_five['module_bay']['position'] == "321" + - test_five['module_bay']['description'] == "Good Fixing is better than Bad Breaking" + - test_five['module_bay']['parent_module'] == test_module['key'] + - test_five['msg'] == "module_bay Fixing Good created" + + - name: "6 - Create module bay with all params idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + label: FiXiNgGoOd + position: "321" + description: Good Fixing is better than Bad Breaking + state: present + register: test_six + + - name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module_bay']['name'] == "Fixing Good" + - test_six['module_bay']['label'] == "FiXiNgGoOd" + - test_six['module_bay']['position'] == "321" + - test_six['module_bay']['description'] == "Good Fixing is better than Bad Breaking" + - test_six['module_bay']['parent_module'] == test_module['key'] + - test_six['msg'] == "module_bay Fixing Good already exists" + + - name: "7 - Delete" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + state: absent + register: test_seven + + - name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_bay Fixing Good deleted" + + - name: "8 - Delete idempotent" + networktocode.nautobot.module_bay: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + parent_module: + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key'] }}" + name: Fixing Good + state: absent + register: test_eight + + - name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_bay'] == None + - test_eight['msg'] == "module_bay Fixing Good already absent" diff --git a/tests/integration/targets/latest/tasks/module_bay_template.yml b/tests/integration/targets/latest/tasks/module_bay_template.yml index 663eec8b..40a6cb7d 100644 --- a/tests/integration/targets/latest/tasks/module_bay_template.yml +++ b/tests/integration/targets/latest/tasks/module_bay_template.yml @@ -4,166 +4,170 @@ ### PYNAUTOBOT_MODULE_BAY_TEMPLATE ## ## -- set_fact: - test_module_type: "{{ lookup('networktocode.nautobot.lookup', 'module-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"HooverMaxProModel60\"') }}" - test_device_type: "{{ lookup('networktocode.nautobot.lookup', 'device-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"Cisco Test\"') }}" - -- name: "1 - Create module bay template with minimum information" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - name: Edward Galbraith - state: present - register: test_one - -- name: "1 - ASSERT" - assert: - that: - - test_one is changed - - test_one['diff']['before']['state'] == "absent" - - test_one['diff']['after']['state'] == "present" - - test_one['module_bay_template']['name'] == "Edward Galbraith" - - test_one['module_bay_template']['module_type'] == test_module_type['key'] - - test_one['msg'] == "module_bay_template Edward Galbraith created" - -- name: "2 - Create module bay template with minimum information idempotent" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - name: Edward Galbraith - state: present - register: test_two - -- name: "2 - ASSERT" - assert: - that: - - not test_two['changed'] - - test_two['module_bay_template']['name'] == "Edward Galbraith" - - test_two['module_bay_template']['module_type'] == test_module_type['key'] - - test_two['msg'] == "module_bay_template Edward Galbraith already exists" - -- name: "3 - Update module bay template" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - name: Edward Galbraith - label: Br Ba - position: "1" - description: Granite State - state: present - register: test_three - -- name: "3 - ASSERT" - assert: - that: - - test_three is changed - - test_three['diff']['after']['label'] == "Br Ba" - - test_three['diff']['after']['position'] == "1" - - test_three['diff']['after']['description'] == "Granite State" - - test_three['module_bay_template']['name'] == "Edward Galbraith" - - test_three['module_bay_template']['module_type'] == test_module_type['key'] - - test_three['module_bay_template']['label'] == "Br Ba" - - test_three['module_bay_template']['position'] == "1" - - test_three['module_bay_template']['description'] == "Granite State" - - test_three['msg'] == "module_bay_template Edward Galbraith updated" - -- name: "4 - Update idempotent" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - name: Edward Galbraith - label: Br Ba - position: "1" - description: Granite State - state: present - register: test_four - -- name: "4 - ASSERT" - assert: - that: - - not test_four['changed'] - - test_four['module_bay_template']['name'] == "Edward Galbraith" - - test_four['msg'] == "module_bay_template Edward Galbraith already exists" - -- name: "5 - Create module bay template with all params" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - device_type: Cisco Test - name: Test1234 - label: test1234 - position: "42" - description: Cisco Test Module Bay - state: present - register: test_five - -- name: "5 - ASSERT" - assert: - that: - - test_five is changed - - test_five['module_bay_template']['name'] == "Test1234" - - test_five['module_bay_template']['label'] == "test1234" - - test_five['module_bay_template']['position'] == "42" - - test_five['module_bay_template']['description'] == "Cisco Test Module Bay" - - test_five['module_bay_template']['device_type'] == test_device_type['key'] - - test_five['msg'] == "module_bay_template Test1234 created" - -- name: "6 - Create module bay template with all params idempotent" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - device_type: Cisco Test - name: Test1234 - label: test1234 - position: "42" - description: Cisco Test Module Bay - state: present - register: test_six - -- name: "6 - ASSERT" - assert: - that: - - not test_six['changed'] - - test_six['module_bay_template']['name'] == "Test1234" - - test_six['module_bay_template']['label'] == "test1234" - - test_six['module_bay_template']['position'] == "42" - - test_six['module_bay_template']['description'] == "Cisco Test Module Bay" - - test_six['module_bay_template']['device_type'] == test_device_type['key'] - - test_six['msg'] == "module_bay_template Test1234 already exists" - -- name: "7 - Delete" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - device_type: Cisco Test - name: Test1234 - state: absent - register: test_seven - -- name: "7 - ASSERT" - assert: - that: - - test_seven is changed - - test_seven['diff']['before']['state'] == "present" - - test_seven['diff']['after']['state'] == "absent" - - test_seven['msg'] == "module_bay_template Test1234 deleted" - -- name: "8 - Delete idempotent" - networktocode.nautobot.module_bay_template: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - device_type: Cisco Test - name: Test1234 - state: absent - register: test_eight - -- name: "8 - ASSERT`" - assert: - that: - - not test_eight['changed'] - - test_eight['module_bay_template'] == None - - test_eight['msg'] == "module_bay_template Test1234 already absent" +- name: "NAUTOBOT 2.3+ MODULE BAY TEMPLATE TESTS" + when: + - "nautobot_version is version('2.3', '>=')" + block: + - set_fact: + test_module_type: "{{ lookup('networktocode.nautobot.lookup', 'module-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"HooverMaxProModel60\"') }}" + test_device_type: "{{ lookup('networktocode.nautobot.lookup', 'device-types', api_endpoint=nautobot_url, token=nautobot_token, api_filter='model=\"Cisco Test\"') }}" + + - name: "1 - Create module bay template with minimum information" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + state: present + register: test_one + + - name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_bay_template']['name'] == "Edward Galbraith" + - test_one['module_bay_template']['module_type'] == test_module_type['key'] + - test_one['msg'] == "module_bay_template Edward Galbraith created" + + - name: "2 - Create module bay template with minimum information idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + state: present + register: test_two + + - name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_bay_template']['name'] == "Edward Galbraith" + - test_two['module_bay_template']['module_type'] == test_module_type['key'] + - test_two['msg'] == "module_bay_template Edward Galbraith already exists" + + - name: "3 - Update module bay template" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + label: Br Ba + position: "1" + description: Granite State + state: present + register: test_three + + - name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['label'] == "Br Ba" + - test_three['diff']['after']['position'] == "1" + - test_three['diff']['after']['description'] == "Granite State" + - test_three['module_bay_template']['name'] == "Edward Galbraith" + - test_three['module_bay_template']['module_type'] == test_module_type['key'] + - test_three['module_bay_template']['label'] == "Br Ba" + - test_three['module_bay_template']['position'] == "1" + - test_three['module_bay_template']['description'] == "Granite State" + - test_three['msg'] == "module_bay_template Edward Galbraith updated" + + - name: "4 - Update idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + name: Edward Galbraith + label: Br Ba + position: "1" + description: Granite State + state: present + register: test_four + + - name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_bay_template']['name'] == "Edward Galbraith" + - test_four['msg'] == "module_bay_template Edward Galbraith already exists" + + - name: "5 - Create module bay template with all params" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + label: test1234 + position: "42" + description: Cisco Test Module Bay + state: present + register: test_five + + - name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_bay_template']['name'] == "Test1234" + - test_five['module_bay_template']['label'] == "test1234" + - test_five['module_bay_template']['position'] == "42" + - test_five['module_bay_template']['description'] == "Cisco Test Module Bay" + - test_five['module_bay_template']['device_type'] == test_device_type['key'] + - test_five['msg'] == "module_bay_template Test1234 created" + + - name: "6 - Create module bay template with all params idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + label: test1234 + position: "42" + description: Cisco Test Module Bay + state: present + register: test_six + + - name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module_bay_template']['name'] == "Test1234" + - test_six['module_bay_template']['label'] == "test1234" + - test_six['module_bay_template']['position'] == "42" + - test_six['module_bay_template']['description'] == "Cisco Test Module Bay" + - test_six['module_bay_template']['device_type'] == test_device_type['key'] + - test_six['msg'] == "module_bay_template Test1234 already exists" + + - name: "7 - Delete" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + state: absent + register: test_seven + + - name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_bay_template Test1234 deleted" + + - name: "8 - Delete idempotent" + networktocode.nautobot.module_bay_template: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + device_type: Cisco Test + name: Test1234 + state: absent + register: test_eight + + - name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_bay_template'] == None + - test_eight['msg'] == "module_bay_template Test1234 already absent" diff --git a/tests/integration/targets/latest/tasks/module_type.yml b/tests/integration/targets/latest/tasks/module_type.yml index c618bed6..e3650ed3 100644 --- a/tests/integration/targets/latest/tasks/module_type.yml +++ b/tests/integration/targets/latest/tasks/module_type.yml @@ -4,154 +4,158 @@ ### PYNAUTOBOT_MODULE_TYPE ## ## -- set_fact: - manufacturer: "{{ lookup('networktocode.nautobot.lookup', 'manufacturers', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Manufacturer\"') }}" - -- name: "1 - Create module type with minimum information" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750 - manufacturer: Test Manufacturer - state: present - register: test_one - -- name: "1 - ASSERT" - assert: - that: - - test_one is changed - - test_one['diff']['before']['state'] == "absent" - - test_one['diff']['after']['state'] == "present" - - test_one['module_type']['model'] == "ws-test-3750" - - test_one['module_type']['manufacturer'] == manufacturer['key'] - - test_one['msg'] == "module_type ws-test-3750 created" - -- name: "2 - Create module type with minimum information idempotent" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: "ws-test-3750" - manufacturer: Test Manufacturer - state: present - register: test_two - -- name: "2 - ASSERT" - assert: - that: - - not test_two['changed'] - - test_two['module_type']['model'] == "ws-test-3750" - - test_two['module_type']['manufacturer'] == manufacturer['key'] - - test_two['msg'] == "module_type ws-test-3750 already exists" - -- name: "3 - Update module type" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750 - manufacturer: Test Manufacturer - part_number: ws-3750g-v2 - comments: With great power comes great responsibility! - state: present - register: test_three - -- name: "3 - ASSERT" - assert: - that: - - test_three is changed - - test_three['diff']['after']['part_number'] == "ws-3750g-v2" - - test_three['module_type']['model'] == "ws-test-3750" - - test_three['module_type']['manufacturer'] == manufacturer['key'] - - test_three['module_type']['comments'] == "With great power comes great responsibility!" - - test_three['module_type']['part_number'] == "ws-3750g-v2" - - test_three['msg'] == "module_type ws-test-3750 updated" - -- name: "4 - Update idempotent" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750 - manufacturer: Test Manufacturer - part_number: ws-3750g-v2 - comments: With great power comes great responsibility! - state: present - register: test_four - -- name: "4 - ASSERT" - assert: - that: - - not test_four['changed'] - - test_four['module_type']['model'] == "ws-test-3750" - - test_four['msg'] == "module_type ws-test-3750 already exists" - -- name: "5 - Create module type with all params" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750-2 - manufacturer: Test Manufacturer - part_number: ws-3750g-v3 - comments: With great power comes great responsibility! - state: present - register: test_five - -- name: "5 - ASSERT" - assert: - that: - - test_five is changed - - test_five['module_type']['model'] == "ws-test-3750-2" - - test_five['module_type']['manufacturer'] == manufacturer['key'] - - test_five['module_type']['comments'] == "With great power comes great responsibility!" - - test_five['module_type']['part_number'] == "ws-3750g-v3" - - test_five['msg'] == "module_type ws-test-3750-2 created" - -- name: "6 - Create module type with all params idempotent" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750-2 - manufacturer: Test Manufacturer - part_number: ws-3750g-v3 - comments: With great power comes great responsibility! - state: present - register: test_six - -- name: "6 - ASSERT" - assert: - that: - - not test_six['changed'] - - test_six['module_type']['model'] == "ws-test-3750-2" - - test_six['module_type']['manufacturer'] == manufacturer['key'] - - test_six['module_type']['comments'] == "With great power comes great responsibility!" - - test_six['module_type']['part_number'] == "ws-3750g-v3" - - test_six['msg'] == "module_type ws-test-3750-2 already exists" - -- name: "7 - Delete" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: ws-test-3750-2 - state: absent - register: test_seven - -- name: "7 - ASSERT" - assert: - that: - - test_seven is changed - - test_seven['diff']['before']['state'] == "present" - - test_seven['diff']['after']['state'] == "absent" - - test_seven['msg'] == "module_type ws-test-3750-2 deleted" - -- name: "8 - Delete idempotent" - networktocode.nautobot.module_type: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - model: "ws-test-3750-2" - state: absent - register: test_eight - -- name: "8 - ASSERT`" - assert: - that: - - not test_eight['changed'] - - test_eight['module_type'] == None - - test_eight['msg'] == "module_type ws-test-3750-2 already absent" +- name: "NAUTOBOT 2.3+ MODULE TYPE TESTS" + when: + - "nautobot_version is version('2.3', '>=')" + block: + - set_fact: + manufacturer: "{{ lookup('networktocode.nautobot.lookup', 'manufacturers', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Manufacturer\"') }}" + + - name: "1 - Create module type with minimum information" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + state: present + register: test_one + + - name: "1 - ASSERT" + assert: + that: + - test_one is changed + - test_one['diff']['before']['state'] == "absent" + - test_one['diff']['after']['state'] == "present" + - test_one['module_type']['model'] == "ws-test-3750" + - test_one['module_type']['manufacturer'] == manufacturer['key'] + - test_one['msg'] == "module_type ws-test-3750 created" + + - name: "2 - Create module type with minimum information idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: "ws-test-3750" + manufacturer: Test Manufacturer + state: present + register: test_two + + - name: "2 - ASSERT" + assert: + that: + - not test_two['changed'] + - test_two['module_type']['model'] == "ws-test-3750" + - test_two['module_type']['manufacturer'] == manufacturer['key'] + - test_two['msg'] == "module_type ws-test-3750 already exists" + + - name: "3 - Update module type" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + part_number: ws-3750g-v2 + comments: With great power comes great responsibility! + state: present + register: test_three + + - name: "3 - ASSERT" + assert: + that: + - test_three is changed + - test_three['diff']['after']['part_number'] == "ws-3750g-v2" + - test_three['module_type']['model'] == "ws-test-3750" + - test_three['module_type']['manufacturer'] == manufacturer['key'] + - test_three['module_type']['comments'] == "With great power comes great responsibility!" + - test_three['module_type']['part_number'] == "ws-3750g-v2" + - test_three['msg'] == "module_type ws-test-3750 updated" + + - name: "4 - Update idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750 + manufacturer: Test Manufacturer + part_number: ws-3750g-v2 + comments: With great power comes great responsibility! + state: present + register: test_four + + - name: "4 - ASSERT" + assert: + that: + - not test_four['changed'] + - test_four['module_type']['model'] == "ws-test-3750" + - test_four['msg'] == "module_type ws-test-3750 already exists" + + - name: "5 - Create module type with all params" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + manufacturer: Test Manufacturer + part_number: ws-3750g-v3 + comments: With great power comes great responsibility! + state: present + register: test_five + + - name: "5 - ASSERT" + assert: + that: + - test_five is changed + - test_five['module_type']['model'] == "ws-test-3750-2" + - test_five['module_type']['manufacturer'] == manufacturer['key'] + - test_five['module_type']['comments'] == "With great power comes great responsibility!" + - test_five['module_type']['part_number'] == "ws-3750g-v3" + - test_five['msg'] == "module_type ws-test-3750-2 created" + + - name: "6 - Create module type with all params idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + manufacturer: Test Manufacturer + part_number: ws-3750g-v3 + comments: With great power comes great responsibility! + state: present + register: test_six + + - name: "6 - ASSERT" + assert: + that: + - not test_six['changed'] + - test_six['module_type']['model'] == "ws-test-3750-2" + - test_six['module_type']['manufacturer'] == manufacturer['key'] + - test_six['module_type']['comments'] == "With great power comes great responsibility!" + - test_six['module_type']['part_number'] == "ws-3750g-v3" + - test_six['msg'] == "module_type ws-test-3750-2 already exists" + + - name: "7 - Delete" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: ws-test-3750-2 + state: absent + register: test_seven + + - name: "7 - ASSERT" + assert: + that: + - test_seven is changed + - test_seven['diff']['before']['state'] == "present" + - test_seven['diff']['after']['state'] == "absent" + - test_seven['msg'] == "module_type ws-test-3750-2 deleted" + + - name: "8 - Delete idempotent" + networktocode.nautobot.module_type: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + model: "ws-test-3750-2" + state: absent + register: test_eight + + - name: "8 - ASSERT`" + assert: + that: + - not test_eight['changed'] + - test_eight['module_type'] == None + - test_eight['msg'] == "module_type ws-test-3750-2 already absent" From 3c6057d5eb8c81a22470fabe7902d1397fa0798f Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:44:04 +0000 Subject: [PATCH 7/8] Added error handling for module name logic and test --- plugins/module_utils/dcim.py | 12 +++++++++--- .../integration/targets/latest/tasks/module.yml | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index e76be678..22e67045 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -143,17 +143,23 @@ def run(self): elif endpoint_name == "module": module_type_name = self.module.params["module_type"] - if self.module.params["parent_module_bay"]: + if isinstance(self.module.params["parent_module_bay"], dict): 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"]: + elif isinstance(self.module.params["location"], dict): parent_name = self.module.params["location"].get("name") parent_parent_name = self.module.params["location"].get("parent", "—") + else: + parent_name = None + parent_parent_name = None - name = f"{parent_parent_name} > {parent_name} > {module_type_name}" + if not (parent_name or parent_parent_name): + self._handle_errors(msg=f"Could not resolve parent of new module {module_type_name}") + else: + name = f"{parent_parent_name} > {parent_name} > {module_type_name}" # Make color params lowercase if data.get("color"): diff --git a/tests/integration/targets/latest/tasks/module.yml b/tests/integration/targets/latest/tasks/module.yml index 6e0760e7..63937731 100644 --- a/tests/integration/targets/latest/tasks/module.yml +++ b/tests/integration/targets/latest/tasks/module.yml @@ -16,6 +16,23 @@ test_module_tenant: "{{ lookup('networktocode.nautobot.lookup', 'tenants', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Tenant\"') }}" test_module_child_location: "{{ lookup('networktocode.nautobot.lookup', 'locations', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Child Test Location\" parent=\"Parent Test Location\"') }}" + - name: "0 - Verify error handling if parent_module_bay or location attributes are missing" + networktocode.nautobot.module: + url: "{{ nautobot_url }}" + token: "{{ nautobot_token }}" + module_type: HooverMaxProModel60 + parent_module_bay: "{{ test_module_bay['key']}}" + status: Active + state: present + ignore_errors: true + register: test_zero + + - name: "0 - ASSERT" + assert: + that: + - not test_zero['changed'] + - test_zero['msg'] == "Could not resolve parent of new module HooverMaxProModel60" + - name: "1 - Create module with minimum information" networktocode.nautobot.module: url: "{{ nautobot_url }}" From cfb55c86df8e9967e1a1940e9ae5dbc8c5736e8b Mon Sep 17 00:00:00 2001 From: Travis Smith <141754521+tsm1th@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:24:30 +0000 Subject: [PATCH 8/8] Simplified module name logic --- plugins/module_utils/dcim.py | 23 +++++++------------ .../targets/latest/tasks/module.yml | 17 -------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/plugins/module_utils/dcim.py b/plugins/module_utils/dcim.py index 22e67045..4a253e92 100644 --- a/plugins/module_utils/dcim.py +++ b/plugins/module_utils/dcim.py @@ -142,24 +142,17 @@ def run(self): ) elif endpoint_name == "module": - module_type_name = self.module.params["module_type"] - if isinstance(self.module.params["parent_module_bay"], dict): - parent_name = self.module.params["parent_module_bay"].get("name") + name = self.module.params["module_type"] + if isinstance(self.module.params["parent_module_bay"], str): + name = f"{self.module.params['parent_module_bay']} > {name}" + elif isinstance(self.module.params["parent_module_bay"], dict): + name = f"{self.module.params['parent_module_bay'].get('name')} > {name}" if self.module.params["parent_module_bay"].get("parent_device"): - parent_parent_name = self.module.params["parent_module_bay"].get("parent_device") + name = f"{self.module.params['parent_module_bay'].get('parent_device')} > {name}" elif self.module.params["parent_module_bay"].get("parent_module"): - parent_parent_name = self.module.params["parent_module_bay"].get("parent_module") + name = f"{self.module.params['parent_module_bay'].get('parent_module')} > {name}" elif isinstance(self.module.params["location"], dict): - parent_name = self.module.params["location"].get("name") - parent_parent_name = self.module.params["location"].get("parent", "—") - else: - parent_name = None - parent_parent_name = None - - if not (parent_name or parent_parent_name): - self._handle_errors(msg=f"Could not resolve parent of new module {module_type_name}") - else: - name = f"{parent_parent_name} > {parent_name} > {module_type_name}" + name = f"{self.module.params['location'].get('parent', '—')} > {self.module.params['location'].get('name')} > {name}" # Make color params lowercase if data.get("color"): diff --git a/tests/integration/targets/latest/tasks/module.yml b/tests/integration/targets/latest/tasks/module.yml index 63937731..6e0760e7 100644 --- a/tests/integration/targets/latest/tasks/module.yml +++ b/tests/integration/targets/latest/tasks/module.yml @@ -16,23 +16,6 @@ test_module_tenant: "{{ lookup('networktocode.nautobot.lookup', 'tenants', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Test Tenant\"') }}" test_module_child_location: "{{ lookup('networktocode.nautobot.lookup', 'locations', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Child Test Location\" parent=\"Parent Test Location\"') }}" - - name: "0 - Verify error handling if parent_module_bay or location attributes are missing" - networktocode.nautobot.module: - url: "{{ nautobot_url }}" - token: "{{ nautobot_token }}" - module_type: HooverMaxProModel60 - parent_module_bay: "{{ test_module_bay['key']}}" - status: Active - state: present - ignore_errors: true - register: test_zero - - - name: "0 - ASSERT" - assert: - that: - - not test_zero['changed'] - - test_zero['msg'] == "Could not resolve parent of new module HooverMaxProModel60" - - name: "1 - Create module with minimum information" networktocode.nautobot.module: url: "{{ nautobot_url }}"