Skip to content

Commit

Permalink
Merge pull request #456 from nautobot/u/tsm1th-add-job-button
Browse files Browse the repository at this point in the history
Added job button module and new 2.3 fields
  • Loading branch information
joewesch authored Dec 16, 2024
2 parents 0eccc50 + bc291d7 commit 1a8b48e
Show file tree
Hide file tree
Showing 11 changed files with 386 additions and 2 deletions.
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
17 changes: 16 additions & 1 deletion development/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,23 @@ services:
<<: *nautobot-base
worker:
entrypoint: "nautobot-server rqworker"
#### ENABLE CELERY ######
# This is what is required to add a celery worker. This broke CI so is disabled for now.
# - "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:
# 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
###########################
depends_on:
- "nautobot"
- "nautobot"
<<: *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)
2 changes: 2 additions & 0 deletions plugins/lookup/lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ 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},
"job-buttons": {"endpoint": nautobot.extras.job_buttons},
"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 @@ -19,6 +19,7 @@
NB_CUSTOM_FIELD_CHOICES = "custom_field_choices"
NB_CONTACT = "contacts"
NB_TEAM = "teams"
NB_JOB_BUTTONS = "job_buttons"
NB_OBJECT_METADATA = "object_metadata"
NB_METADATA_CHOICES = "metadata_choices"
NB_METADATA_TYPES = "metadata_types"
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 @@ -86,6 +86,8 @@
"metadata_types",
"object_metadata",
"dynamic_groups",
"jobs",
"job_buttons",
"relationship_associations",
"roles",
"static_group_associations",
Expand Down Expand Up @@ -214,6 +216,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 @@ -304,6 +307,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 @@ -399,6 +403,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) <info@networktocode.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = r"""
---
module: 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()
6 changes: 6 additions & 0 deletions tests/integration/nautobot-populate.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,11 @@ def make_nautobot_calls(endpoint, payload):
]
created_custom_fields = make_nautobot_calls(nb.extras.custom_fields, custom_fields)

# 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()

###############
# v2.2+ items #
###############
Expand Down Expand Up @@ -699,5 +704,6 @@ def make_nautobot_calls(endpoint, payload):
dynamic_groups = [{"name": "TestStaticAssociations", "content_type": "dcim.device", "group_type": "static"}]
created_dynamic_groups = make_nautobot_calls(nb.extras.dynamic_groups, dynamic_groups)


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

0 comments on commit 1a8b48e

Please sign in to comment.