Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Adds Software Version module #489

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions plugins/module_utils/dcim.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
NB_RACK_GROUPS = "rack_groups"
NB_REAR_PORTS = "rear_ports"
NB_REAR_PORT_TEMPLATES = "rear_port_templates"
NB_SOFTWARE_VERSIONS = "software_versions"
NB_VIRTUAL_CHASSIS = "virtual_chassis"


Expand Down Expand Up @@ -117,6 +118,8 @@ def run(self):
name = self.module.params["data"]["master"]
elif data.get("id"):
name = data["id"]
elif endpoint_name == "software_version":
name = data["version"]
elif endpoint_name == "cable":
if self.module.params["termination_a"].get("name"):
termination_a_name = self.module.params["termination_a"]["name"]
Expand Down
4 changes: 4 additions & 0 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"rack_groups",
"rear_ports",
"rear_port_templates",
"software_versions",
"virtual_chassis",
],
extras=[
Expand Down Expand Up @@ -167,6 +168,7 @@
rear_port_template="name",
rir="name",
route_targets="name",
software_version="version",
status="name",
tenant="name",
tenant_group="name",
Expand Down Expand Up @@ -343,6 +345,7 @@
"route_targets": "route_target",
"services": "services",
"static_group_associations": "static_group_association",
"software_versions": "software_version",
"statuses": "statuses",
"tags": "tags",
"teams": "team",
Expand Down Expand Up @@ -449,6 +452,7 @@
"role": set(["name"]),
"route_target": set(["name"]),
"services": set(["device", "virtual_machine", "name", "port", "protocol"]),
"software_version": set(["version", "platform"]),
"static_group_association": set(["dynamic_group", "associated_object_type", "associated_object_id"]),
"statuses": set(["name"]),
"tags": set(["name"]),
Expand Down
162 changes: 162 additions & 0 deletions plugins/modules/software_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2025, Network to Code (@networktocode) <[email protected]>
# 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: software_version
short_description: Creates, updates or removes software versions from Nautobot
description:
- Creates, updates or removes software versions from Nautobot
notes:
- This module requires Nautobot v2.2+
- This should be ran with connection C(local) and hosts C(localhost)
- Tags should be defined as a YAML list
author:
- Joe Wesch (@joewesch)
requirements:
- pynautobot
version_added: "5.7.0"
extends_documentation_fragment:
- networktocode.nautobot.fragments.base
- networktocode.nautobot.fragments.tags
- networktocode.nautobot.fragments.custom_fields
options:
version:
description:
- The version of the software
required: true
type: str
platform:
description:
- The platform the software will be applied to
- Required if I(state=present) and does not exist yet
required: false
type: raw
status:
description:
- The status of the software
- Required if I(state=present) and does not exist yet
required: false
type: str
alias:
description:
- Optional alternative label for this version
required: false
type: str
release_date:
description:
- The date the software was released
required: false
type: str
end_of_support_date:
description:
- The date the software will no longer be supported
required: false
type: str
documentation_url:
description:
- URL to the software documentation
required: false
type: str
long_term_support:
description:
- Whether the software is long term support
required: false
type: bool
pre_release:
description:
- Whether the software is pre-release
required: false
type: bool
"""

EXAMPLES = r"""
---
- name: Create a software version
networktocode.nautobot.software_version:
url: http://nautobot.local
token: thisIsMyToken
version: 1.0.0
platform: Cisco IOS
status: Active
alias: My Alias
release_date: 2024-01-01
end_of_support_date: 2024-12-31
documentation_url: https://example.com
long_term_support: true
pre_release: false
state: present

- name: Update a software version
networktocode.nautobot.software_version:
url: http://nautobot.local
token: thisIsMyToken
version: 1.0.0
state: present

- name: Delete a software version
networktocode.nautobot.software_version:
url: http://nautobot.local
token: thisIsMyToken
version: 1.0.0
state: absent
"""

RETURN = r"""
software_version:
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_SOFTWARE_VERSIONS,
)
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(
version=dict(required=True, type="str"),
platform=dict(required=False, type="raw"),
status=dict(required=False, type="str"),
alias=dict(required=False, type="str"),
release_date=dict(required=False, type="str"),
end_of_support_date=dict(required=False, type="str"),
documentation_url=dict(required=False, type="str"),
long_term_support=dict(required=False, type="bool"),
pre_release=dict(required=False, type="bool"),
)
)

module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
software_version = NautobotDcimModule(module, NB_SOFTWARE_VERSIONS)
software_version.run()


if __name__ == "__main__": # pragma: no cover
main()
3 changes: 3 additions & 0 deletions tests/integration/nautobot-populate.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ def make_nautobot_calls(endpoint, payload):
cisco_manu = nb.dcim.manufacturers.get(name="Cisco")
arista_manu = nb.dcim.manufacturers.get(name="Arista")

# Create Platforms
platforms = [{"name": "Cisco IOS", "manufacturer": cisco_manu.id, "network_driver": "cisco_ios", "napalm_driver": "ios"}]
created_platforms = make_nautobot_calls(nb.dcim.platforms, platforms)

# Create Device Types
device_types = [
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/targets/latest/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,14 @@
tags:
- vlan_location

- name: "PYNAUTOBOT_SOFTWARE_VERSION TESTS"
include_tasks:
file: "software_version.yml"
apply:
tags:
- software_version
tags:
- software_version

##########################
##
Expand Down
151 changes: 151 additions & 0 deletions tests/integration/targets/latest/tasks/software_version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
- set_fact:
cisco_ios_platform: "{{ lookup('networktocode.nautobot.lookup', 'platforms', api_endpoint=nautobot_url, token=nautobot_token, api_filter='name=\"Cisco IOS\"') }}"

- name: "SOFTWARE VERSION 1: Necessary info creation"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.0.0"
platform: "Cisco IOS"
status: "Active"
state: present
register: test_one

- name: "SOFTWARE VERSION 1: ASSERT - Necessary info creation"
assert:
that:
- test_one is changed
- test_one['diff']['before']['state'] == "absent"
- test_one['diff']['after']['state'] == "present"
- test_one['software_version']['version'] == "1.0.0"
- test_one['msg'] == "software_version 1.0.0 created"

- name: "SOFTWARE VERSION 2: Create duplicate"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.0.0"
platform: "Cisco IOS"
state: present
register: test_two_duplicate

- name: "SOFTWARE VERSION 2: ASSERT - Create duplicate"
assert:
that:
- not test_two_duplicate['changed']
- test_two_duplicate['software_version']['version'] == "1.0.0"
- test_two_duplicate['msg'] == "software_version 1.0.0 already exists"

- name: "SOFTWARE VERSION 3: Create with all info"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
platform: "Cisco IOS"
status: "Active"
release_date: "2024-01-01"
end_of_support_date: "2025-01-01"
documentation_url: "https://example.com"
long_term_support: true
pre_release: false
state: present
register: test_three

- name: "SOFTWARE VERSION 3: ASSERT - Create with all info"
assert:
that:
- test_three is changed
- test_three['diff']['before']['state'] == "absent"
- test_three['diff']['after']['state'] == "present"
- test_three['software_version']['version'] == "1.1.0"
- test_three['software_version']['platform'] == cisco_ios_platform['key']
- test_three['software_version']['status'] == active['key']
- test_three['software_version']['release_date'] == "2024-01-01"
- test_three['software_version']['end_of_support_date'] == "2025-01-01"
- test_three['software_version']['documentation_url'] == "https://example.com"
- test_three['software_version']['long_term_support'] == true
- test_three['software_version']['pre_release'] == false
- test_three['msg'] == "software_version 1.1.0 created"

- name: "SOFTWARE VERSION 4: Create with all info duplicate"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
platform: "Cisco IOS"
status: "Active"
release_date: "2024-01-01"
end_of_support_date: "2025-01-01"
documentation_url: "https://example.com"
long_term_support: true
pre_release: false
state: present
register: test_four

- name: "SOFTWARE VERSION 4: ASSERT - Create with all info duplicate"
assert:
that:
- not test_four['changed']
- test_four['software_version']['version'] == "1.1.0"
- test_four['msg'] == "software_version 1.1.0 already exists"

- name: "SOFTWARE VERSION 5: Update"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
end_of_support_date: "2026-01-01"
register: test_five

- name: "SOFTWARE VERSION 5: ASSERT - Update"
assert:
that:
- test_five is changed
- test_five['diff']['before']['end_of_support_date'] == "2025-01-01"
- test_five['diff']['after']['end_of_support_date'] == "2026-01-01"

- name: "SOFTWARE VERSION 6: Update duplicate"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
end_of_support_date: "2026-01-01"
register: test_six

- name: "SOFTWARE VERSION 6: ASSERT - Update duplicate"
assert:
that:
- not test_six['changed']
- test_six['software_version']['version'] == "1.1.0"
- test_six['msg'] == "software_version 1.1.0 already exists"

- name: "SOFTWARE VERSION 7: Delete"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
state: absent
register: test_seven

- name: "SOFTWARE VERSION 7: ASSERT - Delete"
assert:
that:
- test_seven is changed
- test_seven['diff']['before']['state'] == "present"
- test_seven['diff']['after']['state'] == "absent"
- test_seven['msg'] == "software_version 1.1.0 deleted"

- name: "SOFTWARE VERSION 8: Delete non-existent"
networktocode.nautobot.software_version:
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
version: "1.1.0"
state: absent
register: test_eight

- name: "SOFTWARE VERSION 8: ASSERT - Delete non-existent"
assert:
that:
- not test_eight['changed']
- test_eight['msg'] == "software_version 1.1.0 already absent"