Skip to content

Commit 7ef6fae

Browse files
committed
add process_event_queue
1 parent 98f051c commit 7ef6fae

File tree

4 files changed

+137
-3
lines changed

4 files changed

+137
-3
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,29 @@ spliter = IPSplitter(IPSet([
142142
143143
# subnets => [IPNetwork('192.168.1.0/28', '192.168.1.16/28', ...)]
144144
subnetes = spliter.split(28)
145-
```
145+
```
146+
147+
## process_event_queue
148+
149+
Inspired by https://github.com/netbox-community/netbox/issues/14896.
150+
151+
The `process_event_queue` helper allows you to pass a snapshot of object changes to a script call on an event.
152+
153+
### How to use
154+
155+
1. Override original events_pipeline in configuration.py:
156+
```
157+
EVENTS_PIPELINE = ('netbox_scripthelper.events.process_event_queue', )
158+
```
159+
160+
2. Create a new event rule with the Script action type.
161+
3. In the script handler, refer to the additional attributes:
162+
```
163+
def run(self, data, commit):
164+
postchange = data['snapshots']['postchange']
165+
prechange = data['snapshots']['prechange']
166+
event = data['event']
167+
username = data['username']
168+
169+
```
170+

netbox_scripthelper/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class ScriptHelperConfig(PluginConfig):
99
name = 'netbox_scripthelper'
1010
verbose_name = 'NetBox ScriptHelper'
1111
description = 'Collections of utilities for Netbox custom scripts.'
12-
version = '0.3.2'
12+
version = '0.4.0'
1313
author = 'Andrey Shalashov'
1414
author_email = 'avshalashov@yandex.ru'
1515
base_url = 'scripthelper'

netbox_scripthelper/events.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from django.contrib.auth import get_user_model
2+
from django.utils import timezone
3+
from django.utils.translation import gettext as _
4+
from django_rq import get_queue
5+
6+
from core.models import Job
7+
from netbox.config import get_config
8+
from netbox.constants import RQ_QUEUE_DEFAULT
9+
from utilities.rqworker import get_rq_retry
10+
from extras.choices import EventRuleActionChoices, ObjectChangeActionChoices
11+
from extras.models import EventRule
12+
13+
14+
def process_event_rules(event_rules, model_name, event, data, username=None, snapshots=None, request_id=None):
15+
if username:
16+
user = get_user_model().objects.get(username=username)
17+
else:
18+
user = None
19+
20+
for event_rule in event_rules:
21+
22+
# Evaluate event rule conditions (if any)
23+
if not event_rule.eval_conditions(data):
24+
continue
25+
26+
# Webhooks
27+
if event_rule.action_type == EventRuleActionChoices.WEBHOOK:
28+
29+
# Select the appropriate RQ queue
30+
queue_name = get_config().QUEUE_MAPPINGS.get('webhook', RQ_QUEUE_DEFAULT)
31+
rq_queue = get_queue(queue_name)
32+
33+
# Compile the task parameters
34+
params = {
35+
"event_rule": event_rule,
36+
"model_name": model_name,
37+
"event": event,
38+
"data": data,
39+
"snapshots": snapshots,
40+
"timestamp": timezone.now().isoformat(),
41+
"username": username,
42+
"retry": get_rq_retry()
43+
}
44+
if snapshots:
45+
params["snapshots"] = snapshots
46+
if request_id:
47+
params["request_id"] = request_id
48+
49+
# Enqueue the task
50+
rq_queue.enqueue(
51+
"extras.webhooks.send_webhook",
52+
**params
53+
)
54+
55+
# Scripts
56+
elif event_rule.action_type == EventRuleActionChoices.SCRIPT:
57+
# Resolve the script from action parameters
58+
script = event_rule.action_object.python_class()
59+
# a little trick for https://github.com/netbox-community/netbox/issues/14896
60+
data['snapshots'] = snapshots
61+
data['event'] = event
62+
data['username'] = username
63+
64+
# Enqueue a Job to record the script's execution
65+
Job.enqueue(
66+
"extras.scripts.run_script",
67+
instance=event_rule.action_object,
68+
name=script.name,
69+
user=user,
70+
data=data
71+
)
72+
73+
else:
74+
raise ValueError(_("Unknown action type for an event rule: {action_type}").format(
75+
action_type=event_rule.action_type
76+
))
77+
78+
79+
def process_event_queue(events):
80+
"""
81+
Flush a list of object representation to RQ for EventRule processing.
82+
"""
83+
events_cache = {
84+
'type_create': {},
85+
'type_update': {},
86+
'type_delete': {},
87+
}
88+
89+
for data in events:
90+
action_flag = {
91+
ObjectChangeActionChoices.ACTION_CREATE: 'type_create',
92+
ObjectChangeActionChoices.ACTION_UPDATE: 'type_update',
93+
ObjectChangeActionChoices.ACTION_DELETE: 'type_delete',
94+
}[data['event']]
95+
content_type = data['content_type']
96+
97+
# Cache applicable Event Rules
98+
if content_type not in events_cache[action_flag]:
99+
events_cache[action_flag][content_type] = EventRule.objects.filter(
100+
**{action_flag: True},
101+
object_types=content_type,
102+
enabled=True
103+
)
104+
event_rules = events_cache[action_flag][content_type]
105+
106+
process_event_rules(
107+
event_rules, content_type.model, data['event'], data['data'], data['username'],
108+
snapshots=data['snapshots'], request_id=data['request_id']
109+
)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='netbox_scripthelper',
5-
version='0.3.2',
5+
version='0.4.0',
66
description='Collections of utilities for Netbox custom scripts.',
77
url='https://github.com/k1nky/netbox-scripthelper-plugin',
88
long_description_content_type='text/markdown',

0 commit comments

Comments
 (0)