Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add custom link module #722

Merged
merged 5 commits into from
Feb 3, 2022
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
1 change: 1 addition & 0 deletions plugins/module_utils/netbox_extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
NB_CONFIG_CONTEXTS = "config_contexts"
NB_TAGS = "tags"
NB_CUSTOM_FIELDS = "custom_fields"
NB_CUSTOM_LINKS = "custom_links"


class NetboxExtrasModule(NetboxModule):
Expand Down
5 changes: 4 additions & 1 deletion plugins/module_utils/netbox_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"site_groups",
"virtual_chassis",
],
extras=["config_contexts", "tags", "custom_fields"],
extras=["config_contexts", "tags", "custom_fields", "custom_links"],
ipam=[
"aggregates",
"ip_addresses",
Expand Down Expand Up @@ -110,6 +110,7 @@
contact_group="name",
contact_role="name",
custom_field="name",
custom_link="name",
device="name",
device_role="slug",
device_type="slug",
Expand Down Expand Up @@ -281,6 +282,7 @@
"contact_groups": "contact_group",
"contact_roles": "contact_role",
"custom_fields": "custom_field",
"custom_links": "custom_link",
"device_bays": "device_bay",
"device_bay_templates": "device_bay_template",
"devices": "device",
Expand Down Expand Up @@ -363,6 +365,7 @@
"contact_group": set(["name"]),
"contact_role": set(["name"]),
"custom_field": set(["name"]),
"custom_link": set(["name"]),
"dcim.consoleport": set(["name", "device"]),
"dcim.consoleserverport": set(["name", "device"]),
"dcim.frontport": set(["name", "device", "rear_port"]),
Expand Down
162 changes: 162 additions & 0 deletions plugins/modules/netbox_custom_link.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Martin Rødvand (@rodvand) <[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: netbox_custom_link
short_description: Creates, updates or deletes custom links within NetBox
description:
- Creates, updates or removes custom links from NetBox
notes:
- This should be ran with connection C(local) and hosts C(localhost)
- Use the C(!unsafe) data type if you want jinja2 code in link_text or link_url
author:
- Martin Rødvand (@rodvand)
requirements:
- pynetbox
version_added: "3.6.0"
extends_documentation_fragment:
- netbox.netbox.common
options:
data:
type: dict
description:
- Defines the custom field
suboptions:
content_type:
description:
- The content type to apply this custom link to
required: false
type: raw
name:
description:
- The name of the custom link
required: true
type: str
link_text:
description:
- Link text of the custom link
required: true
type: raw
link_url:
description:
- Link URL of the custom link
required: true
type: raw
weight:
description:
- Fields with higher weights appear lower in a form
required: false
type: int
group_name:
description:
- The group to associate the custom link with
required: false
type: str
button_class:
description:
- Button class for the custom link
required: false
type: raw
new_window:
description:
- Open link in new window
required: false
type: bool
required: true
"""

EXAMPLES = r"""
- name: "Test NetBox custom_link module"
connection: local
hosts: localhost
tasks:
- name: Create a custom link on device
netbox_custom_link:
netbox_url: http://netbox.local
netbox_token: thisIsMyToken
data:
content_type: "dcim.device"
name: Custom Link
link_text: "Open Web Management"
link_url: !unsafe https://{{ obj.name }}.domain.local

- name: Delete the custom link
netbox_custom_field:
netbox_url: http://netbox.local
netbox_token: thisIsMyToken
data:
content_type: "dcim.device"
name: Custom Link
link_text: "Open Web Management"
link_url: !unsafe https://{{ obj.name }}.domain.local
state: absent
"""

RETURN = r"""
custom_link:
description: Serialized object as created/existent/updated/deleted within NetBox
returned: always
type: dict
msg:
description: Message indicating failure or info about what has been achieved
returned: always
type: str
"""

from ansible_collections.netbox.netbox.plugins.module_utils.netbox_utils import (
NetboxAnsibleModule,
NETBOX_ARG_SPEC,
)
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_extras import (
NetboxExtrasModule,
NB_CUSTOM_LINKS,
)
from copy import deepcopy


def main():
"""
Main entry point for module execution
"""
argument_spec = deepcopy(NETBOX_ARG_SPEC)
argument_spec.update(
dict(
data=dict(
type="dict",
required=True,
options=dict(
content_type=dict(required=False, type="raw"),
name=dict(required=True, type="str"),
link_text=dict(required=True, type="raw"),
link_url=dict(required=True, type="raw"),
weight=dict(required=False, type="int"),
group_name=dict(required=False, type="str"),
button_class=dict(required=False, type="raw"),
new_window=dict(required=False, type="bool"),
),
)
)
)

required_if = [
("state", "present", ["content_type", "name", "link_text", "link_url"]),
("state", "absent", ["name"]),
]

module = NetboxAnsibleModule(
argument_spec=argument_spec, supports_check_mode=True, required_if=required_if
)

netbox_custom_link = NetboxExtrasModule(module, NB_CUSTOM_LINKS)
netbox_custom_link.run()


if __name__ == "__main__":
main()
11 changes: 10 additions & 1 deletion tests/integration/targets/v3.1/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,13 @@
tags:
- netbox_custom_field
tags:
- netbox_custom_field
- netbox_custom_field

- name: "NETBOX_CUSTOM_LINK TESTS"
include_tasks:
file: "netbox_custom_link.yml"
apply:
tags:
- netbox_custom_link
tags:
- netbox_custom_link
108 changes: 108 additions & 0 deletions tests/integration/targets/v3.1/tasks/netbox_custom_link.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
##
##
### NETBOX_CUSTOM_LINK
##
##
- name: "CUSTOM_LINK 1: Necessary info creation"
netbox.netbox.netbox_custom_link:
netbox_url: http://localhost:32768
netbox_token: 0123456789abcdef0123456789abcdef01234567
data:
content_type: "dcim.device"
name: Custom Link
link_text: Open Web management
link_url: !unsafe https://{{ obj.name }}.domain.local/
state: present
register: test_one

- name: "CUSTOM_LINK 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['custom_link']['name'] == "Custom Link"
- test_one['custom_link']['content_type'] == "dcim.device"
- test_one['custom_link']['link_text'] == "Open Web management"
- test_one['msg'] == "custom_link Custom Link created"

- name: "CUSTOM_LINK 2: Create duplicate"
netbox.netbox.netbox_custom_link:
netbox_url: http://localhost:32768
netbox_token: 0123456789abcdef0123456789abcdef01234567
data:
content_type: "dcim.device"
name: Custom Link
link_text: Open Web management
link_url: !unsafe https://{{ obj.name }}.domain.local/
state: present
register: test_two

- name: "CUSTOM_LINK 2: ASSERT - Create duplicate"
assert:
that:
- not test_two['changed']
- test_two['custom_link']['name'] == "Custom Link"
- test_two['msg'] == "custom_link Custom Link already exists"

- name: "CUSTOM_FIELD 3: Update data and add weight"
netbox.netbox.netbox_custom_link:
netbox_url: http://localhost:32768
netbox_token: 0123456789abcdef0123456789abcdef01234567
data:
content_type: "dcim.device"
name: Custom Link
link_text: Open Web management
link_url: !unsafe https://{{ obj.name }}.domain.local/
weight: 50
state: present
register: test_three

- name: "CUSTOM_FIELD 3: ASSERT - Updated"
assert:
that:
- test_three is changed
- test_three['diff']['after']['weight'] == 50
- test_three['custom_link']['name'] == "Custom Link"
- test_three['msg'] == "custom_link Custom Link updated"

- name: "CUSTOM_LINK 4: Change content type"
netbox.netbox.netbox_custom_link:
netbox_url: http://localhost:32768
netbox_token: 0123456789abcdef0123456789abcdef01234567
data:
content_type: "virtualization.virtualmachine"
name: Custom Link
link_text: Open Web management
link_url: !unsafe https://{{ obj.name }}.domain.local/
state: present
register: test_four

- name: "CUSTOM_LINK 4: ASSERT - Change content type"
assert:
that:
- test_four is changed
- test_four['diff']['after']['content_type'] == "virtualization.virtualmachine"
- test_four['custom_link']['name'] == "Custom Link"
- test_four['msg'] == "custom_link Custom Link updated"

- name: "CUSTOM_LINK 5: Delete"
netbox.netbox.netbox_custom_link:
netbox_url: http://localhost:32768
netbox_token: 0123456789abcdef0123456789abcdef01234567
data:
content_type: "virtualization.virtualmachine"
name: Custom Link
link_text: Open Web management
link_url: !unsafe https://{{ obj.name }}.domain.local/
state: absent
register: test_five

- name: "CUSTOM_LINK 5: ASSERT - Deleted"
assert:
that:
- test_five is changed
- test_five['diff']['after']['state'] == "absent"
- test_five['custom_link']['name'] == "Custom Link"
- test_five['msg'] == "custom_link Custom Link deleted"