├── .travis.yml ├── icingaexchange.yml ├── LICENSE ├── mattermost.py └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: python 3 | python: 4 | - "2.7" 5 | - "3.4" 6 | - "3.5" 7 | - "3.6" 8 | - "3.7" 9 | - "nightly" 10 | script: 11 | - "python mattermost.py --url https://example.com --notificationtype CUSTOM --hostalias myexample.com" 12 | -------------------------------------------------------------------------------- /icingaexchange.yml: -------------------------------------------------------------------------------- 1 | name: icinga2-mattermost 2 | description: "file:///README.md" 3 | url: "https://github.com/Reamer/icinga2-mattermost" 4 | tags: Alarm 5 | vendor: Linux 6 | target: Process 7 | type: Plugin, Notification, Notification Command 8 | license: None 9 | releases: 10 | - 11 | name: 1.0 12 | description: "1.0 Release" 13 | files: 14 | - 15 | name: mattermost.py 16 | url: "file:///mattermost.py" 17 | description: "First release" 18 | checksum: 49d14acb29eecddba9fb6bfd193e8fd8 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Philipp Dallig 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mattermost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright (c) 2015 NDrive SA 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | import argparse 24 | import json 25 | try: 26 | import urllib.request as urllib_request 27 | except ImportError: 28 | import urllib2 as urllib_request 29 | try: 30 | import urllib.parse as urllib_parse 31 | except ImportError: 32 | import urllib as urllib_parse 33 | 34 | VERSION = "1.2.0" 35 | 36 | TEMPLATE_HOST = "__{notificationtype}__ {hostalias} is {hoststate} - {hostoutput}" # noqa 37 | TEMPLATE_SERVICE = "__{notificationtype}__ {hostalias}/{servicedesc} is {servicestate} - {serviceoutput}" # noqa 38 | 39 | def parse(): 40 | parser = argparse.ArgumentParser(description='Sends alerts to Mattermost') 41 | parser.add_argument('--url', help='Incoming Webhook URL', required=True) 42 | parser.add_argument('--channel', help='Channel to notify') 43 | parser.add_argument('--username', help='Username to notify as', 44 | default='Icinga') 45 | parser.add_argument('--iconurl', help='URL of icon to use for username', 46 | default='https://s3.amazonaws.com/cloud.ohloh.net/attachments/50631/icinga_logo_med.png') # noqa 47 | parser.add_argument('--notificationtype', help='Notification Type', 48 | required=True) 49 | parser.add_argument('--hostalias', help='Host Alias', required=True) 50 | parser.add_argument('--hoststate', help='Host State') 51 | parser.add_argument('--hostoutput', help='Host Output') 52 | parser.add_argument('--servicedesc', help='Service Description') 53 | parser.add_argument('--servicestate', help='Service State') 54 | parser.add_argument('--serviceoutput', help='Service Output') 55 | parser.add_argument('--author', help='Author') 56 | parser.add_argument('--comment', help='Comment') 57 | parser.add_argument('--oneline', action='store_true', help='Print only one line') 58 | parser.add_argument('--version', action='version', 59 | version='%(prog)s {version}'.format(version=VERSION)) 60 | args = parser.parse_args() 61 | return args 62 | 63 | def emoji(notificationtype): 64 | return { 65 | "RECOVERY": ":white_check_mark:", 66 | "PROBLEM": ":fire:", 67 | "DOWNTIMESTART": ":clock10:", 68 | "DOWNTIMEEND": ":sunny:", 69 | "DOWNTIMEREMOVED": "", 70 | "CUSTOM": ":sound:", 71 | "FLAPPINGSTART": ":cloud:", 72 | "FLAPPINGEND": ":sunny:", 73 | "ACKNOWLEDGEMENT": ":exclamation:", 74 | }.get(notificationtype, "") 75 | 76 | def make_data(args): 77 | template = TEMPLATE_SERVICE if args.servicestate else TEMPLATE_HOST 78 | 79 | # Emojis 80 | 81 | text = emoji(args.notificationtype) + " " + template.format(**vars(args)) 82 | 83 | if args.oneline: 84 | text = text.splitlines()[0] 85 | if args.author: 86 | text += " authored by " + args.author 87 | if args.comment: 88 | text += " commented with " + args.comment 89 | 90 | payload = { 91 | "username": args.username, 92 | "icon_url": args.iconurl, 93 | "text": text 94 | } 95 | 96 | if args.channel: 97 | payload["channel"] = args.channel 98 | 99 | data = {'payload' : json.dumps(payload)} 100 | return data 101 | 102 | 103 | def request(url, data): 104 | rawdata = urllib_parse.urlencode(data).encode("utf-8") 105 | req = urllib_request.Request(url, rawdata) 106 | response = urllib_request.urlopen(req) 107 | return response.read() 108 | 109 | if __name__ == "__main__": 110 | args = parse() 111 | data = make_data(args) 112 | response = request(args.url, data) 113 | print(response.decode('utf-8')) 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Icinga2 Mattermost Plugin 2 | 3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2c896aaa0476426f86e7802198fba6d7)](https://app.codacy.com/app/philipp.dallig/icinga2-mattermost?utm_source=github.com&utm_medium=referral&utm_content=Reamer/icinga2-mattermost&utm_campaign=Badge_Grade_Dashboard) 4 | [![Build Status](https://travis-ci.com/Reamer/icinga2-mattermost.svg?branch=master)](https://travis-ci.com/Reamer/icinga2-mattermost) 5 | 6 | A plugin for Icinga2 to enable notifications to Mattermost Open Source Chat. 7 | 8 | ## Usage 9 | Assuming you are using Icinga2, the steps are: 10 | 11 | ### 1. Install 12 | Copy _mattermost.py_ to any Location. A good Location would be _PluginContribDir_/icinga2-mattermost/. 13 | ### 2. Create the notification command 14 | 15 | ``` 16 | object NotificationCommand "mattermost_service" { 17 | import "plugin-notification-command" 18 | 19 | command = [ PluginContribDir + "/icinga2-mattermost/mattermost.py" ] 20 | 21 | arguments = { 22 | "--channel" = { 23 | "description" = "mattermost channel" 24 | "required" = true 25 | "value" = "$mattermost_channel$" 26 | } 27 | "--hostalias" = { 28 | "required" = true 29 | "value" = "$mattermost_hostalias$" 30 | } 31 | "--notificationtype" = { 32 | "required" = true 33 | "value" = "$mattermost_notificationtype$" 34 | } 35 | "--author" = { 36 | "value" = "$mattermost_author$" 37 | } 38 | "--comment" = { 39 | "value" = "$mattermost_comment$" 40 | } 41 | "--oneline" = { 42 | "set_if" = "$mattermost_oneline$" 43 | } 44 | "--servicedesc" = { 45 | "required" = true 46 | "value" = "$mattermost_servicedesc$" 47 | } 48 | "--serviceoutput" = { 49 | "required" = true 50 | "value" = "$mattermost_serviceoutput$" 51 | } 52 | "--servicestate" = { 53 | "required" = true 54 | "value" = "$mattermost_servicestate$" 55 | } 56 | "--url" = { 57 | "description" = "mattermost incomming webhook url" 58 | "required" = true 59 | "value" = "$mattermost_url$" 60 | } 61 | } 62 | 63 | vars += { 64 | "mattermost_channel" = "$user.vars.channel$" 65 | "mattermost_hostalias" = "$host.display_name$" 66 | "mattermost_notificationtype" = "$notification.type$" 67 | "mattermost_author" = "$notification.author$" 68 | "mattermost_comment" = "$notification.comment$" 69 | "mattermost_oneline" = "$user.vars.oneline$" 70 | "mattermost_servicedesc" = "$service.display_name$" 71 | "mattermost_serviceoutput" = "$service.output$" 72 | "mattermost_servicestate" = "$service.state$" 73 | "mattermost_url" = "$user.vars.url$" 74 | } 75 | } 76 | 77 | object NotificationCommand "mattermost_host" { 78 | import "plugin-notification-command" 79 | 80 | command = [ PluginContribDir + "/icinga2-mattermost/mattermost.py" ] 81 | 82 | arguments = { 83 | "--channel" = { 84 | "description" = "mattermost channel" 85 | "required" = true 86 | "value" = "$mattermost_channel$" 87 | } 88 | "--hostalias" = { 89 | "required" = true 90 | "value" = "$mattermost_hostalias$" 91 | } 92 | "--hostoutput" = { 93 | "required" = true 94 | "value" = "$mattermost_hostoutput$" 95 | } 96 | "--hoststate" = { 97 | "required" = true 98 | "value" = "$mattermost_hoststate$" 99 | } 100 | "--notificationtype" = { 101 | "required" = true 102 | "value" = "$mattermost_notificationtype$" 103 | } 104 | "--author" = { 105 | "value" = "$mattermost_author$" 106 | } 107 | "--comment" = { 108 | "value" = "$mattermost_comment$" 109 | } 110 | "--oneline" = { 111 | "set_if" = "$mattermost_oneline$" 112 | } 113 | "--url" = { 114 | "description" = "mattermost incomming webhook url" 115 | "required" = true 116 | "value" = "$mattermost_url$" 117 | } 118 | } 119 | 120 | vars += { 121 | "mattermost_channel" = "$user.vars.channel$" 122 | "mattermost_hostalias" = "$host.display_name$" 123 | "mattermost_hostoutput" = "$host.output$" 124 | "mattermost_hoststate" = "$host.state$" 125 | "mattermost_notificationtype" = "$notification.type$" 126 | "mattermost_author" = "$notification.author$" 127 | "mattermost_comment" = "$notification.comment$" 128 | "mattermost_oneline" = "$user.vars.oneline$" 129 | "mattermost_url" = "$user.vars.url$" 130 | } 131 | } 132 | ``` 133 | ### 3. Create the mattermost User 134 | ``` 135 | object User "mattermost" { 136 | import "generic-user" 137 | display_name = "Mattermost User" 138 | enable_notifications = true 139 | 140 | vars.channel = icinga /* Use here the url channel name, ie. without special characters and spaces */ 141 | vars.url = https://mattermost.example.com /* Copy incoming Webhook URL defined in mattermost */ 142 | vars.oneline = false /* Use true if you prefer having all output squashed on one line */ 143 | } 144 | ``` 145 | ### 4. Apply notifications to mattermost User 146 | ``` 147 | apply Notification "mattermost_service" to Service { 148 | assign where true 149 | command = "mattermost_service" 150 | users = [ "mattermost" ] 151 | period = "24x7" 152 | types = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ] 153 | states = [ OK, Warning, Critical, Unknown ] 154 | } 155 | ``` 156 | 157 | ``` 158 | apply Notification "mattermost_host" to Host { 159 | assign where true 160 | command = "mattermost_host" 161 | users = [ "mattermost" ] 162 | period = "24x7" 163 | types = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ] 164 | states = [ Up, Down ] 165 | } 166 | ``` 167 | 168 | ## Testing 169 | 170 | In order to test the webhook you can use the following command. 171 | 172 | ```bash 173 | ./mattermost.py --url https://my.mattermost-domain.com/hooks/XXXXXXYYYYYYY --notificationtype CUSTOM --hostalias myexample.com 174 | ``` 175 | --------------------------------------------------------------------------------