In our quest to get all things into Matrix, we've also sent Salt events into a Matrix room. This is extremely useful to monitor the results of automatic highstate runs, individual commands, etc.

Salt logging in Matrix

For this effort, we looked at implementing a Matrix returner, which is probably the best solution. But not being that strong of a Python programmer, and having some desire to control/filter what gets posted, instead we went down the path of a custom Reactor, based on this post.

This involves 2 configuration changes, a Python script, and the matrix_client Python library. First of all, install the library:


pip install matrix_client


... with that available, here's the script we created, starting with the one in the blog post linked above, but modifying heavily for our needs. We put it in our main Salt state directory, under a _runners subdirectory - /srv/salt/_runners/process_minion_data.py:


import subprocess
from matrix_client.api import MatrixHttpApi

def post_changes(matrix_hs, room_id, token, message, data_str):
data = eval(data_str)
error = False
changes = False

funtype = data['fun'].split('.')[0]
# Skip saltutil calls... can add others here as needed.
if funtype == 'saltutil':
return True

if type(data['return']) is dict:
for state, result in data['return'].iteritems():
if type(result) is not dict:
error = True
message = message + ' Res: ' + str(result)
break;
if not result['result']:
error = True
break
if result['changes']:
changes = True
break
else:
if not data['success']:
error = True

matrix = MatrixHttpApi(matrix_hs, token=token)
if error or changes:
state = subprocess.check_output(["salt-run", "jobs.lookup_jid", data['jid'], "--out=highs
tate"])
response = matrix.send_message(room_id, message + "\n" + state)
else:
response = matrix.send_message(room_id, message)
return True


Next, the Reactor Yaml file, /srv/reactor/notify-changes.sls:


notify-changes:
runner.process_minion_data.post_changes:
- kwarg:
matrix_hs: [Your homeserver URL]
room_id: "[Room ID to post -- if there's a !, it needs to be quoted]"
token: "[Token for Matrix account to post as]"
message: "Salt master: minion run: {{ data['fun'] }} id: {{ data['id'] }} jid: {{ data[
'jid'] }}"
data_str: {{ data|yaml_dquote }}


... we did have to alter the Yaml structure compared to the blog post we based this on, due to changes in how Salt calls its runners.

Finally, you need to register the reactor and the runner path in the Master configuration file. We did this by adding a file, /etc/salt/master.d/reactor.conf:

```
reactor:
- 'salt/job/*/ret/*':
- /srv/reactor/notify-changes.sls

runner_dirs:
- /srv/salt/_runners

Also set the highstate output to short for unchanged states:

state_output: changes
```

And voila! We now have Salt logging its activity into a Matrix room.

Share this article with your friends!

Comments (0)

Add new comment

This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.