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

Added job button module and new 2.3 fields #456

Merged
merged 12 commits into from
Dec 16, 2024
3 changes: 3 additions & 0 deletions development/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ COPY ./development/requirements.txt /opt/nautobot/requirements.txt
# Install the requirements
RUN pip install -r /opt/nautobot/requirements.txt

# Copy in the jobs
COPY ./development/jobs /opt/nautobot/jobs

# Copy in the development configuration file
COPY ./development/nautobot_config.py /opt/nautobot/nautobot_config.py
4 changes: 4 additions & 0 deletions development/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ NAUTOBOT_REDIS_PORT=6379
# NAUTOBOT_REDIS_SSL=True
NAUTOBOT_SECRET_KEY=0123456789abcdef0123456789abcdef01234567

NAUTOBOT_DEBUG=True
NAUTOBOT_LOG_DEPRECATION_WARNINGS=True
NAUTOBOT_LOG_LEVEL=DEBUG

# Needed for Postgres should match the values for Nautobot above
PGPASSWORD=decinablesprewad
POSTGRES_DB=nautobot
Expand Down
14 changes: 12 additions & 2 deletions development/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,19 @@ services:
- "redis"
<<: *nautobot-base
worker:
entrypoint: "nautobot-server rqworker"
entrypoint:
- "sh"
- "-c" # this is to evaluate the $NAUTOBOT_LOG_LEVEL from the env
- "nautobot-server celery worker -l $$NAUTOBOT_LOG_LEVEL --events" ## $$ because of docker-compose
depends_on:
- "nautobot"
nautobot:
condition: "service_healthy"
healthcheck:
interval: "30s"
timeout: "10s"
start_period: "30s"
retries: 3
test: ["CMD", "bash", "-c", "nautobot-server celery inspect ping --destination celery@$$HOSTNAME"] ## $$ because of docker-compose
<<: *nautobot-base
postgres:
image: "postgres:13"
Expand Down
13 changes: 13 additions & 0 deletions development/jobs/example_job_button_receiver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from nautobot.apps.jobs import JobButtonReceiver, register_jobs


class ExampleSimpleJobButtonReceiver(JobButtonReceiver):
class Meta:
name = "Example Simple Job Button Receiver"

def receive_job_button(self, obj):
self.logger.info("Running Job Button Receiver.", extra={"object": obj})
# Add job logic here


register_jobs(ExampleSimpleJobButtonReceiver)
1 change: 1 addition & 0 deletions plugins/lookup/lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ def get_endpoint(nautobot, term):
"inventory-items": {"endpoint": nautobot.dcim.inventory_items},
"ip-addresses": {"endpoint": nautobot.ipam.ip_addresses},
"ip-address-to-interface": {"endpoint": nautobot.ipam.ip_address_to_interface},
"jobs": {"endpoint": nautobot.extras.jobs},
"locations": {"endpoint": nautobot.dcim.locations},
"location-types": {"endpoint": nautobot.dcim.location_types},
"manufacturers": {"endpoint": nautobot.dcim.manufacturers},
Expand Down
1 change: 1 addition & 0 deletions plugins/module_utils/extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
NB_CUSTOM_FIELD_CHOICES = "custom_field_choices"
NB_CONTACT = "contacts"
NB_TEAM = "teams"
NB_JOB_BUTTONS = "job_buttons"


class NautobotExtrasModule(NautobotModule):
Expand Down
5 changes: 5 additions & 0 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
"contacts",
"custom_fields",
"custom_field_choices",
"jobs",
"job_buttons",
"relationship_associations",
"roles",
"statuses",
Expand Down Expand Up @@ -207,6 +209,7 @@
"interface_template": "interface_templates",
"ip_addresses": "ip_addresses",
"ipaddresses": "ip_addresses",
"job": "jobs",
"lag": "interfaces",
"location": "locations",
"location_type": "location_types",
Expand Down Expand Up @@ -295,6 +298,7 @@
"inventory_items": "inventory_item",
"ip_addresses": "ip_address",
"ip_address_to_interface": "ip_address_to_interface",
"job_buttons": "job_button",
"locations": "location",
"location_types": "location_type",
"manufacturers": "manufacturer",
Expand Down Expand Up @@ -385,6 +389,7 @@
"ip_addresses": set(["address", "namespace", "device", "interfaces", "vm_interfaces"]),
"ipaddresses": set(["address", "namespace", "device", "interfaces", "vm_interfaces"]),
"ip_address_to_interface": set(["ip_address", "interface", "vm_interface"]),
"job_button": set(["name"]),
"lag": set(["name"]),
"location": set(["name", "id", "parent"]),
"location_type": set(["name"]),
Expand Down
149 changes: 149 additions & 0 deletions plugins/modules/job_button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2023, 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: job_button
short_description: Creates or removes job buttons from Nautobot
description:
- Creates or removes job buttons from Nautobot
notes:
- This should be ran with connection C(local) and hosts C(localhost)
author:
- Travis Smith (@tsm1th)
requirements:
- pynautobot
version_added: "5.5.0"
extends_documentation_fragment:
- networktocode.nautobot.fragments.base
options:
name:
description:
- The name of the job button
required: true
type: str
content_types:
description:
- The content types to associate the job button with
- Required if I(state=present) and the job button does not exist yet
required: false
type: list
elements: str
job:
description:
- The job receiver to associate job with
- Required if I(state=present) and the job button does not exist yet
required: false
type: raw
enabled:
description:
- Whether or not the button is enabled
required: false
type: bool
text:
description:
- The text to display on the button
- Required if I(state=present) and the job button does not exist yet
required: false
type: str
weight:
description:
- Position this field should be displayed in
required: false
type: int
group_name:
description:
- Buttons in the same group will appear in a dropdown menu
required: false
type: str
button_class:
description:
- Button class of this button
- Required if I(state=present) and the job button does not exist yet
required: false
choices:
- default
- primary
- success
- info
- warning
- danger
- link
type: str
confirmation:
description:
- Whether or not a confirmation pop-up box will appear
required: false
type: bool
"""

EXAMPLES = r"""
- name: Create job button within Nautobot with only required information
networktocode.nautobot.job_button:
url: http://nautobot.local
token: thisIsMyToken
name: MyJobButton
content_types:
- dcim.device
job: MyJob
text: SubmitMe
state: present

- name: Delete job button within Nautobot
networktocode.nautobot.job_button:
url: http://nautobot.local
token: thisIsMyToken
name: MyJobButton
state: absent
"""

RETURN = r"""
job_button:
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
from ansible_collections.networktocode.nautobot.plugins.module_utils.extras import (
NautobotExtrasModule,
NB_JOB_BUTTONS,
)
from ansible.module_utils.basic import AnsibleModule
from copy import deepcopy


def main():
"""Execute job button module."""
argument_spec = deepcopy(NAUTOBOT_ARG_SPEC)
argument_spec.update(
dict(
name=dict(required=True, type="str"),
content_types=dict(required=False, type="list", elements="str"),
job=dict(required=False, type="raw"),
enabled=dict(required=False, type="bool"),
text=dict(required=False, type="str"),
weight=dict(required=False, type="int"),
group_name=dict(required=False, type="str"),
button_class=dict(required=False, choices=["default", "primary", "success", "info", "warning", "danger", "link"], type="str"),
confirmation=dict(required=False, type="bool"),
)
)

module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
job_button = NautobotExtrasModule(module, NB_JOB_BUTTONS)
job_button.run()


if __name__ == "__main__": # pragma: no cover
main()
4 changes: 4 additions & 0 deletions tests/integration/nautobot-populate.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,10 @@ def make_nautobot_calls(endpoint, payload):
]
created_device_interface_roles = make_nautobot_calls(nb.extras.roles, device_interface_roles)

# Enable example job for job tests
example_job_receiver = nb.extras.jobs.get(name="Example Simple Job Button Receiver")
example_job_receiver.enabled = True
example_job_receiver.save()

if ERRORS:
sys.exit("Errors have occurred when creating objects, and should have been printed out. Check previous output.")
Loading