From da2db775e09117d70af56135d0f36f6c8dd5e52a Mon Sep 17 00:00:00 2001 From: squirrel289 Date: Mon, 30 Jun 2025 16:35:55 -0400 Subject: [PATCH 1/2] Add support for managing NetBox event rules --- changelogs/fragments/netbox_event_rule.yml | 3 + docs/plugins/index.rst | 4 +- docs/plugins/netbox_event_rule_module.rst | 1348 ++++++++++++++++++++ plugins/lookup/nb_lookup.py | 1 + plugins/module_utils/netbox_extras.py | 2 + plugins/module_utils/netbox_utils.py | 10 + plugins/modules/netbox_event_rule.py | 338 +++++ 7 files changed, 1705 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/netbox_event_rule.yml create mode 100644 docs/plugins/netbox_event_rule_module.rst create mode 100644 plugins/modules/netbox_event_rule.py diff --git a/changelogs/fragments/netbox_event_rule.yml b/changelogs/fragments/netbox_event_rule.yml new file mode 100644 index 000000000..61f4724a9 --- /dev/null +++ b/changelogs/fragments/netbox_event_rule.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - Minor changes required to support new event_rule module \ No newline at end of file diff --git a/docs/plugins/index.rst b/docs/plugins/index.rst index c019dcaae..1cbd1cf45 100644 --- a/docs/plugins/index.rst +++ b/docs/plugins/index.rst @@ -1,5 +1,5 @@ .. meta:: - :antsibull-docs: 2.13.1 + :antsibull-docs: 2.16.2 .. _plugins_in_netbox.netbox: @@ -79,6 +79,7 @@ Modules * :ansplugin:`netbox_device_interface_template module ` -- Creates or removes interfaces on devices from NetBox * :ansplugin:`netbox_device_role module ` -- Create, update or delete devices roles within NetBox * :ansplugin:`netbox_device_type module ` -- Create, update or delete device types within NetBox +* :ansplugin:`netbox_event_rule module ` -- Creates, updates or deletes event rule configuration within NetBox * :ansplugin:`netbox_export_template module ` -- Creates, updates or deletes export templates within NetBox * :ansplugin:`netbox_fhrp_group module ` -- Create, update or delete FHRP groups within NetBox * :ansplugin:`netbox_fhrp_group_assignment module ` -- Create, update or delete FHRP group assignments within NetBox @@ -172,6 +173,7 @@ Modules netbox_device_interface_template_module netbox_device_role_module netbox_device_type_module + netbox_event_rule_module netbox_export_template_module netbox_fhrp_group_module netbox_fhrp_group_assignment_module diff --git a/docs/plugins/netbox_event_rule_module.rst b/docs/plugins/netbox_event_rule_module.rst new file mode 100644 index 000000000..8aca99e5b --- /dev/null +++ b/docs/plugins/netbox_event_rule_module.rst @@ -0,0 +1,1348 @@ +.. Document meta + +:orphan: + +.. |antsibull-internal-nbsp| unicode:: 0xA0 + :trim: + +.. meta:: + :antsibull-docs: 2.16.2 + +.. Anchors + +.. _ansible_collections.netbox.netbox.netbox_event_rule_module: + +.. Anchors: short name for ansible.builtin + +.. Title + +netbox.netbox.netbox_event_rule module -- Creates, updates or deletes event rule configuration within NetBox +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. Collection note + +.. note:: + This module is part of the `netbox.netbox collection `_ (version 3.21.0). + + It is not included in ``ansible-core``. + To check whether it is installed, run :code:`ansible-galaxy collection list`. + + To install it, use: :code:`ansible-galaxy collection install netbox.netbox`. + You need further requirements to be able to use this module, + see :ref:`Requirements ` for details. + + To use it in a playbook, specify: :code:`netbox.netbox.netbox_event_rule`. + +.. version_added + +.. rst-class:: ansible-version-added + +New in netbox.netbox 3.22.0 + +.. contents:: + :local: + :depth: 1 + +.. Deprecated + + +Synopsis +-------- + +.. Description + +- Creates, updates or removes event rule configuration within NetBox + + +.. Aliases + + +.. Requirements + +.. _ansible_collections.netbox.netbox.netbox_event_rule_module_requirements: + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- pynetbox + + + + + + +.. Options + +Parameters +---------- + +.. tabularcolumns:: \X{1}{3}\X{2}{3} + +.. list-table:: + :width: 100% + :widths: auto + :header-rows: 1 + :class: longtable ansible-option-table + + * - Parameter + - Comments + + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-cert: + + .. rst-class:: ansible-option-title + + **cert** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`any` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + Certificate path + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data: + + .. rst-class:: ansible-option-title + + **data** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`dictionary` / :ansible-option-required:`required` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + Defines the event rule parameters. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/action_object_id: + + .. rst-class:: ansible-option-title + + **action_object_id** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`integer` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The ID of the action object (e.g., the webhook ID). + + Required when :emphasis:`state=present` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/action_object_type: + + .. rst-class:: ansible-option-title + + **action_object_type** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The content type of the action object (e.g., 'extras.webhook'). + + Required when :emphasis:`state=present` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/action_type: + + .. rst-class:: ansible-option-title + + **action_type** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The type of action to take when the event rule is triggered. + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry:`"webhook"` + - :ansible-option-choices-entry:`"script"` + - :ansible-option-choices-entry:`"notification"` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions: + + .. rst-class:: ansible-option-title + + **conditions** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`dictionary` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + Dictionary defining conditions for the event rule to trigger. + + The parameters \`or\`, \`and\`, and \`attr\` are mutually exclusive. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/and: + + .. rst-class:: ansible-option-title + + **and** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=dictionary` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + A list of conditions or nested operators that must all evaluate to true to trigger the event rule. + + Must not be provided if 'or', 'attr' or 'value' is provided. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/attr: + + .. rst-class:: ansible-option-title + + **attr** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The name of the attribute to evaluate. + + Must not be provided if 'and' or 'or' is provided. + + Required if 'value', 'op' or 'negate' is provided. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/negate: + + .. rst-class:: ansible-option-title + + **negate** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`boolean` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + If true, the condition will be negated. + + Must not be provided if 'and' or 'or' is provided. + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry:`false` + - :ansible-option-choices-entry:`true` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/op: + + .. rst-class:: ansible-option-title + + **op** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The operator to use when comparing the value of attr to the expected value. + + Must not be provided if 'and' or 'or' is provided. + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry:`"="` + - :ansible-option-choices-entry:`"\>"` + - :ansible-option-choices-entry:`"\<"` + - :ansible-option-choices-entry:`"\>="` + - :ansible-option-choices-entry:`"\<="` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/or: + + .. rst-class:: ansible-option-title + + **or** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=dictionary` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + A list of conditions or nested operators with at least one option evaluating to true to trigger the event rule. + + Must not be provided if 'and', 'attr' or 'value' is provided. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.04\textwidth}\begin{minipage}[t]{0.28\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/conditions/value: + + .. rst-class:: ansible-option-title + + **value** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The expected value to compare against the attribute identified by attr + + Must not be provided if 'and' or 'or' is provided. + + Required if 'attr', 'op' or 'negate' is provided. + + + .. raw:: html + +
+ + + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/custom_fields: + + .. rst-class:: ansible-option-title + + **custom_fields** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`dictionary` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + Dictionary of custom fields for the event rule. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/description: + + .. rst-class:: ansible-option-title + + **description** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + A description for the event rule. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/enabled: + + .. rst-class:: ansible-option-title + + **enabled** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`boolean` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + Whether the event rule is enabled. + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry:`false` + - :ansible-option-choices-entry:`true` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/event_types: + + .. rst-class:: ansible-option-title + + **event_types** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=string` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + List of event types that trigger the rule. + + Required when :emphasis:`state=present` + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry:`"object\_created"` + - :ansible-option-choices-entry:`"object\_updated"` + - :ansible-option-choices-entry:`"object\_deleted"` + - :ansible-option-choices-entry:`"job\_started"` + - :ansible-option-choices-entry:`"job\_completed"` + - :ansible-option-choices-entry:`"job\_failed"` + - :ansible-option-choices-entry:`"job\_errored"` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/name: + + .. rst-class:: ansible-option-title + + **name** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` / :ansible-option-required:`required` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + The name of the event rule. + + Required when :emphasis:`state=absent` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/object_types: + + .. rst-class:: ansible-option-title + + **object_types** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=any` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + List of content types (e.g., 'dcim.device') the event rule applies to. + + Required when :emphasis:`state=present` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. raw:: latex + + \hspace{0.02\textwidth}\begin{minipage}[t]{0.3\textwidth} + + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-data/tags: + + .. rst-class:: ansible-option-title + + **tags** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=any` + + .. raw:: html + +
+ + .. raw:: latex + + \end{minipage} + + - .. raw:: html + +
+ + List of tags to apply to the event rule. + + + .. raw:: html + +
+ + + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-netbox_token: + + .. rst-class:: ansible-option-title + + **netbox_token** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` / :ansible-option-required:`required` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + The NetBox API token. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-netbox_url: + + .. rst-class:: ansible-option-title + + **netbox_url** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` / :ansible-option-required:`required` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + The URL of the NetBox instance. + + Must be accessible by the Ansible control host. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-query_params: + + .. rst-class:: ansible-option-title + + **query_params** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`list` / :ansible-option-elements:`elements=string` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + This can be used to override the specified values in ALLOWED\_QUERY\_PARAMS that are defined + + in plugins/module\_utils/netbox\_utils.py and provides control to users on what may make + + an object unique in their environment. + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-state: + + .. rst-class:: ansible-option-title + + **state** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + The state of the object. + + + .. rst-class:: ansible-option-line + + :ansible-option-choices:`Choices:` + + - :ansible-option-choices-entry-default:`"present"` :ansible-option-choices-default-mark:`← (default)` + - :ansible-option-choices-entry:`"absent"` + + + .. raw:: html + +
+ + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__parameter-validate_certs: + + .. rst-class:: ansible-option-title + + **validate_certs** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`any` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + If :literal:`no`\ , SSL certificates will not be validated. + + This should only be used on personally controlled sites using a self-signed certificates. + + + .. rst-class:: ansible-option-line + + :ansible-option-default-bold:`Default:` :ansible-option-default:`true` + + .. raw:: html + +
+ + +.. Attributes + + +.. Notes + +Notes +----- + +.. note:: + - This should be ran with connection :literal:`local` and hosts :literal:`localhost` + +.. Seealso + + +.. Examples + +Examples +-------- + +.. code-block:: yaml+jinja + + # Example 1: Create an event rule using attr and value conditions (based on sample JSON) + - name: Create Netbox Event Rule for Virtual Disk Creation with specific name + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: present + data: + name: "test-webhook-event" + action_type: "webhook" + action_object_type: "extras.webhook" + action_object_id: -1 # Replace with your webhook ID + enabled: true + object_types: + - virtualization.virtualdisk + event_types: + - object_created + conditions: + attr: "name" + value: "scsi0" + negate: true # This condition triggers if the name is NOT "scsi0" + + # Example 2: Create an event rule using 'and' conditions + - name: Update Netbox Event Rule for Virtual Disk Creation or Update in specific names + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: present + data: + name: "test-webhook-event" + event_types: + - object_created + conditions: + "and": + - "attr": "name" + "value": "scsi0" + "negate": true + - "attr": "name" + "value": "rootfs" + "negate": true + + description: "Triggered when a virtual disk is created that is NOT named 'scsi0' or 'rootfs'." + tags: + - automation + - netbox-event-rule + + # Example 3: Ensure an event rule is absent + - name: Ensure test-webhook-event rule is absent + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: absent + data: + name: "test-webhook-event" + + + +.. Facts + + +.. Return values + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. tabularcolumns:: \X{1}{3}\X{2}{3} + +.. list-table:: + :width: 100% + :widths: auto + :header-rows: 1 + :class: longtable ansible-option-table + + * - Key + - Description + + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__return-msg: + + .. rst-class:: ansible-option-title + + **msg** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`string` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + Message indicating failure or info about what has been achieved + + + .. rst-class:: ansible-option-line + + :ansible-option-returned-bold:`Returned:` always + + + .. raw:: html + +
+ + + * - .. raw:: html + +
+
+ + .. _ansible_collections.netbox.netbox.netbox_event_rule_module__return-webhook: + + .. rst-class:: ansible-option-title + + **webhook** + + .. raw:: html + + + + .. ansible-option-type-line:: + + :ansible-option-type:`dictionary` + + .. raw:: html + +
+ + - .. raw:: html + +
+ + Serialized object as created/existent/updated/deleted within NetBox + + + .. rst-class:: ansible-option-line + + :ansible-option-returned-bold:`Returned:` always + + + .. raw:: html + +
+ + + +.. Status (Presently only deprecated) + + +.. Authors + +Authors +~~~~~~~ + +- Chris Caldwell (@squirrel289) + + + +.. Extra links + +Collection links +~~~~~~~~~~~~~~~~ + +.. ansible-links:: + + - title: "Issue Tracker" + url: "https://github.com/netbox-community/ansible_modules/issues" + external: true + - title: "Repository (Sources)" + url: "https://github.com/netbox-community/ansible_modules" + external: true + + +.. Parsing errors diff --git a/plugins/lookup/nb_lookup.py b/plugins/lookup/nb_lookup.py index f3ca1cbcf..6514a0808 100644 --- a/plugins/lookup/nb_lookup.py +++ b/plugins/lookup/nb_lookup.py @@ -207,6 +207,7 @@ def get_endpoint(netbox, term): "device-roles": {"endpoint": netbox.dcim.device_roles}, "device-types": {"endpoint": netbox.dcim.device_types}, "devices": {"endpoint": netbox.dcim.devices}, + "event-rules": {"endpoint": netbox.extras.event_rules}, "export-templates": {"endpoint": netbox.dcim.export_templates}, "fhrp-group-assignments": {"endpoint": netbox.ipam.fhrp_group_assignments}, "fhrp-groups": {"endpoint": netbox.ipam.fhrp_groups}, diff --git a/plugins/module_utils/netbox_extras.py b/plugins/module_utils/netbox_extras.py index 64eb9c8b9..5e17769d9 100644 --- a/plugins/module_utils/netbox_extras.py +++ b/plugins/module_utils/netbox_extras.py @@ -16,6 +16,7 @@ NB_CUSTOM_FIELDS = "custom_fields" NB_CUSTOM_FIELD_CHOICE_SETS = "custom_field_choice_sets" NB_CUSTOM_LINKS = "custom_links" +NB_EVENT_RULES = "event_rules" NB_EXPORT_TEMPLATES = "export_templates" NB_JOURNAL_ENTRIES = "journal_entries" NB_WEBHOOKS = "webhooks" @@ -40,6 +41,7 @@ def run(self): Supported endpoints: - config_contexts - config_templates + - event_rules - tags - journal entries """ diff --git a/plugins/module_utils/netbox_utils.py b/plugins/module_utils/netbox_utils.py index 08a756234..e1126f850 100644 --- a/plugins/module_utils/netbox_utils.py +++ b/plugins/module_utils/netbox_utils.py @@ -87,6 +87,7 @@ "custom_fields": {}, "custom_field_choice_sets": {}, "custom_links": {}, + "event_rules": {}, "export_templates": {}, "journal_entries": {}, "webhooks": {}, @@ -376,6 +377,7 @@ "devices": "device", "device_roles": "device_role", "device_types": "device_type", + "event_rules": "event_rule", "export_templates": "export_template", "fhrp_groups": "fhrp_group", "fhrp_group_assignments": "fhrp_group_assignment", @@ -495,6 +497,7 @@ "device": set(["name"]), "device_role": set(["slug"]), "device_type": set(["slug"]), + "event_rule": set(["name"]), "export_template": set(["name"]), "fhrp_group": set( ["id", "group_id", "interface_type", "device", "virtual_machine"] @@ -1462,6 +1465,13 @@ def _update_netbox_object(self, data): NetBox object and the Ansible diff. """ serialized_nb_obj = self.nb_object.serialize() + + # `conditionsc don't serialize properly and couldn't find a clean fix within serialize + # Since this is the only place we're serializing, just fixing it here as a workaround + dict_self = dict(self.nb_object) + if dict_self.get("conditions"): + serialized_nb_obj["conditions"] = dict_self["conditions"] + if "custom_fields" in serialized_nb_obj: custom_fields = serialized_nb_obj.get("custom_fields", {}) shared_keys = custom_fields.keys() & data.get("custom_fields", {}).keys() diff --git a/plugins/modules/netbox_event_rule.py b/plugins/modules/netbox_event_rule.py new file mode 100644 index 000000000..fd6f0d7a9 --- /dev/null +++ b/plugins/modules/netbox_event_rule.py @@ -0,0 +1,338 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2025, Chris Caldwell (@squirrel289) +# 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_event_rule +short_description: Creates, updates or deletes event rule configuration within NetBox +description: + - Creates, updates or removes event rule configuration within NetBox +notes: + - This should be ran with connection C(local) and hosts C(localhost) +author: + - Chris Caldwell (@squirrel289) +requirements: + - pynetbox +version_added: "3.22.0" +extends_documentation_fragment: + - netbox.netbox.common +options: + data: + type: dict + description: + - Defines the event rule parameters. + required: true + suboptions: + object_types: + description: + - List of content types (e.g., 'dcim.device') the event rule applies to. + - Required when I(state=present) + type: list + elements: raw + required: false # Required if state is 'present' + name: + description: + - The name of the event rule. + - Required when I(state=absent) + type: str + required: true + enabled: + description: + - Whether the event rule is enabled. + type: bool + required: false + event_types: + description: + - List of event types that trigger the rule. + - Required when I(state=present) + type: list + elements: str + required: false # Required if state is 'present' + choices: + - object_created + - object_updated + - object_deleted + - job_started + - job_completed + - job_failed + - job_errored + conditions: + description: + - Dictionary defining conditions for the event rule to trigger. + - The parameters `or`, `and`, and `attr` are mutually exclusive. + required: false + type: dict + suboptions: + and: + description: + - A list of conditions or nested operators that must all evaluate to true + to trigger the event rule. + - Must not be provided if 'or', 'attr' or 'value' is provided. + type: list + elements: dict + required: false + or: + description: + - A list of conditions or nested operators with at least one option evaluating to true + to trigger the event rule. + - Must not be provided if 'and', 'attr' or 'value' is provided. + type: list + elements: dict + required: false + attr: + description: + - The name of the attribute to evaluate. + - Must not be provided if 'and' or 'or' is provided. + - Required if 'value', 'op' or 'negate' is provided. + type: str + required: false + value: + description: + - The expected value to compare against the attribute identified by attr + - Must not be provided if 'and' or 'or' is provided. + - Required if 'attr', 'op' or 'negate' is provided. + type: str + required: false + op: + description: + - The operator to use when comparing the value of attr to the expected value. + - Must not be provided if 'and' or 'or' is provided. + type: str + choices: + - '=' + - '>' + - '<' + - '>=' + - '<=' + required: false + negate: + description: + - If true, the condition will be negated. + - Must not be provided if 'and' or 'or' is provided. + type: bool + required: false + action_type: + description: + - The type of action to take when the event rule is triggered. + type: str + choices: + - webhook + - script + - notification + required: false + action_object_type: + description: + - The content type of the action object (e.g., 'extras.webhook'). + - Required when I(state=present) + type: str + required: false # Required if state is 'present' + action_object_id: + description: + - The ID of the action object (e.g., the webhook ID). + - Required when I(state=present) + type: int + required: false # Required if state is 'present' + description: + description: + - A description for the event rule. + type: str + required: false + tags: + description: + - List of tags to apply to the event rule. + type: list + elements: raw + required: false + custom_fields: + description: + - Dictionary of custom fields for the event rule. + type: dict + required: false + +""" +EXAMPLES = r""" +# Example 1: Create an event rule using attr and value conditions (based on sample JSON) +- name: Create Netbox Event Rule for Virtual Disk Creation with specific name + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: present + data: + name: "test-webhook-event" + action_type: "webhook" + action_object_type: "extras.webhook" + action_object_id: -1 # Replace with your webhook ID + enabled: true + object_types: + - virtualization.virtualdisk + event_types: + - object_created + conditions: + attr: "name" + value: "scsi0" + negate: true # This condition triggers if the name is NOT "scsi0" + +# Example 2: Create an event rule using 'and' conditions +- name: Update Netbox Event Rule for Virtual Disk Creation or Update in specific names + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: present + data: + name: "test-webhook-event" + event_types: + - object_created + conditions: + "and": + - "attr": "name" + "value": "scsi0" + "negate": true + - "attr": "name" + "value": "rootfs" + "negate": true + + description: "Triggered when a virtual disk is created that is NOT named 'scsi0' or 'rootfs'." + tags: + - automation + - netbox-event-rule + +# Example 3: Ensure an event rule is absent +- name: Ensure test-webhook-event rule is absent + netbox.netbox.netbox_event_rule: + netbox_url: "http://localhost:32768" # Replace with your Netbox URL + netbox_token: "0123456789abcdef0123456789abcdef01234567" # Replace with your Netbox token + state: absent + data: + name: "test-webhook-event" +""" + +RETURN = r""" +webhook: + 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_EVENT_RULES, +) +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( + object_types=dict(required=False, type="list", elements="raw"), + name=dict(required=True, type="str"), + enabled=dict(required=False, type="bool"), + event_types=dict( + required=False, + choices=[ + "object_created", + "object_updated", + "object_deleted", + "job_started", + "job_completed", + "job_failed", + "job_errored", + ], + elements="str", + type="list", + ), + conditions=dict( + type="dict", + required=False, + options={ + "attr": dict( + required=False, + type="str", + ), + "value": dict( + required=False, + type="str", + ), + "negate": dict( + required=False, + type="bool", + ), + "op": dict( + required=False, + choices=["=", ">", "<", ">=", "<="], + type="str", + ), + "or": dict(type="list", required=False, elements="dict"), + "and": dict(type="list", required=False, elements="dict"), + }, + required_together=[ + ["value", "attr"], + ], + required_by=dict( + negate=["value", "attr"], + op=["value", "attr"], + ), + mutually_exclusive=[ + ["or", "and", "attr"], + ], + ), + action_type=dict( + required=False, + choices=[ + "webhook", + "script", + "notification", + ], + type="str", + ), + action_object_type=dict(required=False, type="str"), + action_object_id=dict(required=False, type="int"), + description=dict(required=False, type="str"), + tags=dict(required=False, type="list", elements="raw"), + custom_fields=dict(required=False, type="dict"), + ), + ) + ) + ) + required_if = [ + ( + "state", + "present", + ["object_types", "event_types", "action_object_type", "action_object_id"], + ), + ("state", "absent", ["name"]), + ] + + module = NetboxAnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=required_if, + ) + + netbox_event_rule = NetboxExtrasModule(module, NB_EVENT_RULES) + netbox_event_rule.run() + + +if __name__ == "__main__": # pragma: no cover + main() From 1b87285b4f56103d99165d3f380887138d492943 Mon Sep 17 00:00:00 2001 From: squirrel289 Date: Mon, 30 Jun 2025 19:31:43 -0400 Subject: [PATCH 2/2] Added empty line at end of changelog fragment --- changelogs/fragments/netbox_event_rule.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/netbox_event_rule.yml b/changelogs/fragments/netbox_event_rule.yml index 61f4724a9..f655d4902 100644 --- a/changelogs/fragments/netbox_event_rule.yml +++ b/changelogs/fragments/netbox_event_rule.yml @@ -1,3 +1,3 @@ --- minor_changes: - - Minor changes required to support new event_rule module \ No newline at end of file + - Minor changes required to support new event_rule module