Skip to content
Merged
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
162 changes: 162 additions & 0 deletions docs/administration/event-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,168 @@ The Event Rule authorizes the run, not the permissions of the user who triggered
the event. Restrict who can create or edit Event Rules, because those rules choose
which Scripts run. See [Permissions](permissions.md) for plugin action permissions.

## Practical examples

These examples report device changes in the Job log. Upload and activate each
Script as described in [Uploading](uploading.md#creating-a-project-from-one-script),
then create its rule under **Operations > Integrations > Event Rules**.
See [Event Rule execution permissions](permissions.md#event-rule-execution-permissions)
before granting access to manage these rules.

With **Conditions** empty, each rule queues a Job for every selected device
event, and the Script decides what to report. NetBox's
[snapshot conditions](https://docs.netbox.dev/en/stable/reference/conditions/#snapshot-conditions-event-rules)
can filter events before queuing a Job. For the status example, use
`{"attr": "status", "op": "changed"}` to skip unrelated updates. Keep the
Script's checks: `changed` can also match an update without a `prechange`
snapshot.

Snapshots describe the event, not the object's current state. They use model
values: `status` is a string such as `active`, and `tags` is a list of tag
**names**. A create event normally has no `prechange` snapshot, and a delete
event has no `postchange` snapshot. An update needs both snapshots to compare
values. An update has no `prechange` snapshot if the code that saved it did not
call `snapshot()` before saving. This can happen in Scripts or when NetBox saves
devices installed in a parent device's bays.

### Report device status changes

This Script reports creation and deletion, and skips updates where the status
did not change. It identifies deleted devices by their recorded ID without
looking them up in the database.

| Setting | Value |
|---|---|
| Name | Report device status changes |
| Object types | DCIM > Device |
| Enabled | Yes |
| Event types | Object created, Object updated, Object deleted |
| Conditions | Leave empty |
| Action type | Run Script |
| Script | Report device status changes |
| Action data | Leave empty |

```python
from netbox_scripts import Script


class ReportDeviceStatus(Script):
class Meta:
name = 'Report device status changes'
notifications_default = 'on_failure'

def run(self, data, commit):
event = self.event
if event is None:
self.log_info('No event context. Nothing to report.')
return
if event.get('object_type') != 'dcim.device':
return

device_id = event['object_id']
event_type = event.get('event_type')
if event_type == 'object_created':
self.log_info(f'Device {device_id} was created.')
return
if event_type == 'object_deleted':
self.log_info(f'Device {device_id} was deleted.')
return
if event_type != 'object_updated':
return

snapshots = event.get('snapshots') or {}
before = snapshots.get('prechange')
after = snapshots.get('postchange')
if before is None or after is None or 'status' not in before or 'status' not in after:
self.log_warning('Status snapshots are incomplete. Skipping this event.')
return
if before['status'] == after['status']:
return

self.log_info(f'Device {device_id}: status changed from {before["status"]} to {after["status"]}.')
```

### Report a tag being added or removed

This Script reports changes to membership of the `monitored` tag. Replace
`monitored` with the exact tag name you use. Changes to other tags are ignored.
A device created with the tag is not reported, because the rule reacts only to
updates.

| Setting | Value |
|---|---|
| Name | Report monitoring tag changes |
| Object types | DCIM > Device |
| Enabled | Yes |
| Event types | Object updated |
| Conditions | Leave empty |
| Action type | Run Script |
| Script | Report monitoring tag changes |
| Action data | Leave empty |

```python
from netbox_scripts import Script


class ReportMonitoringTag(Script):
class Meta:
name = 'Report monitoring tag changes'
notifications_default = 'on_failure'

def run(self, data, commit):
event = self.event
if event is None:
self.log_info('No event context. Nothing to report.')
return
if event.get('object_type') != 'dcim.device' or event.get('event_type') != 'object_updated':
return

snapshots = event.get('snapshots') or {}
before = snapshots.get('prechange')
after = snapshots.get('postchange')
if before is None or after is None or 'tags' not in before or 'tags' not in after:
self.log_warning('Tag snapshots are incomplete. Skipping this event.')
return

tag_name = 'monitored'
was_monitored = tag_name in before['tags']
is_monitored = tag_name in after['tags']
if was_monitored == is_monitored:
return

change = 'added' if is_monitored else 'removed'
self.log_info(f'Device {event["object_id"]}: tag {tag_name!r} was {change}.')
```

A missing snapshot or field does not mean an empty tag list. Skipping incomplete
snapshots avoids reporting a change that cannot be established. An empty list,
however, is valid and allows the first tag addition or last tag removal to be
detected.

### Adapting the examples

The examples only report events. Repeated delivery can repeat a log entry, but
does not modify devices or call an external service. Each matching rule queues
its own run, so multiple rules can report the same change more than once.

Before adding a write, fetch the live object and check its current state. It may
have changed again or been deleted while the Job was waiting. Use snapshots to
understand the original change. Do not reconstruct it from a current database
query.

Return without saving when the intended state is already present. Otherwise,
call the object's `snapshot()` method before changing any fields, so change
logging and subsequent events include the original values. Committed Scripts can
trigger further Event Rules, so ensure any update you make no longer matches the
same transition check. Comparing snapshots alone does not prevent duplicate
actions: the same event still contains the same change on a repeat run. For
external actions, use an idempotent operation or the service's supported
deduplication mechanism.

Log only the identifiers and selected values needed to explain the action.
Anyone who can view the Job can read its logs, so do not log complete snapshots,
request data or secrets.

## Scripts as event sources

The plugin's four object types can be Event Rule sources, like Devices or IP
Expand Down
Loading