I’ve been working towards making things simpler when managing distributed resources at work. And since we spend most of our day in the chat room (was Slack, now Mattermost) I thought it’s best to get started with ChatOps
It’s just a fancy word for doing stuff right from the chat window. And there’s so much one can do, especially with simple Slash Commands.
Here’s a lambda function I setup yesterday for invalidating CloudFront distributions.
from time import time
import boto3
import json
import os
import re
EXPECTED_TOKEN = os.environ['mmToken']
ALLOWED_USERS = re.split('[, ]', os.environ['allowedUsers'])
DISTRIBUTIONS = {
'site-name': 'DISTRIBUTIONID',
'another.site': 'DISTRIBUTIONID05'
}
def parse_command_text(command_text):
pattern = r"({})\s+(.*)".format('|'.join(DISTRIBUTIONS.keys()))
m = re.match(pattern, command_text)
if m:
return { 'site': m.group(1), 'path': path}
else:
return False
def lambda_handler(event, context):
# Parse the request
try:
request_data = event["queryStringParameters"]
except:
return {
"statusCode": 400,
"headers": {"Content-Type": "application/json"},
"body": '{ "message": "Use GET for setting up mattermost slash command" }'
}
# Check the token matches.
if request_data.get("token", "") != EXPECTED_TOKEN:
print('Wrong Token!')
return {
"statusCode": 401,
"headers": {"Content-Type": "application/json"},
"body": '{ "message": "Mattermost token does not match" }'
}
# Check the user is allowed to run the command
if request_data.get("user_name", "") not in ALLOWED_USERS:
print('Wrong User! {} not in {}'.format(request_data['user_name'], ALLOWED_USERS))
return {
"statusCode": 401,
"headers": {"Content-Type": "application/json"},
"body": '{ "message": "User not allowed to perform action" }'
}
# parse the command
command_text = request_data.get("text", "")
if not command_text:
print('Nothing to do, bailing out')
return {
"statusCode": 404,
"headers": {"Content-Type": "application/json"},
"body": '{ "message": "No command text sent" }'
}
parts = parse_command_text(command_text)
if not parts:
print('Bad formatting - command: {}'.format(command_text))
return {
"statusCode": 402,
"headers": {"Content-Type": "application/json"},
"body": '{ "message": "Wrong pattern" }'
}
# Do the actual work
cf_client = boto3.client('cloudfront')
# Invalidate
boto_response = cf_client.create_invalidation(
DistributionId=DISTRIBUTIONS[parts['site']],
InvalidationBatch={
'Paths': {
'Quantity': len(parts['path']),
'Items': parts['path']
},
'CallerReference': str(time()).replace(".", "")
}
)['Invalidation']
# Build the response message text.
text = """##### Executing invalidation
| Key | Info |
| --- | ---- |
| Site | {} |
| Path | {} |
| ID | {} |
| Status | {} |""".format(
parts['site'],
parts['path'],
boto_response['Id'],
boto_response['Status']
)
# Build the response object.
response = {
"response_type": "in_channel",
"text": text,
}
# Return the response as JSON
return {
"body": json.dumps(response),
"headers": {"Content-Type": "application/json"},
"statusCode": 200,
}
Note that you need to hook that up with an API Gateway in AWS. Once that’s done, you will have a URL endpoint ready for deployment.
Next, I created the slash command in mattermost with the following:
That’s pretty much it. Rinse and repeat for a different command, different usage.
On my list next is to have more interaction with the user in mattermost per https://docs.mattermost.com/developer/interactive-messages.html
Weekend Project, Yay!
Top comments (0)