Skip to content

Commit

Permalink
Merge pull request #41 from idealista/develop
Browse files Browse the repository at this point in the history
v1.3.0
  • Loading branch information
José Noguera authored Jan 8, 2018
2 parents 4c24c92 + 3ccad27 commit d53f214
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 26 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a ch

## [Unreleased](https://github.com/idealista/prom2teams/tree/develop)

## [1.3.0](https://github.com/idealista/prom2teams/tree/1.3.0)
[Full Changelog](https://github.com/idealista/prom2teams/compare/1.2.0...1.3.0)
### Added
- *[#32](https://github.com/idealista/prom2teams/issues/32) Support alerts with missing mandatory attributes* @lindhor
- *[#38](https://github.com/idealista/prom2teams/issues/38) Dockerfile* @jnogol

## [1.2.0](https://github.com/idealista/prom2teams/tree/1.2.0)
[Full Changelog](https://github.com/idealista/prom2teams/compare/1.1.3...1.2.0)
### Added
- *[#32](https://github.com/idealista/prom2teams/issues/32) Sets default value for "instance" in alerts* @maglo
- *[#32](https://github.com/idealista/prom2teams/issues/32) Set default value for "instance" in alerts* @maglo

### Fixed
- *[#26](https://github.com/idealista/prom2teams/issues/26) Able to handle multiple received alarms* @jnogol
Expand Down
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.5-slim-jessie

LABEL maintainer="[email protected]"

EXPOSE 8089

RUN pip install prom2teams
COPY config.ini /opt/prom2teams/config.ini

ENTRYPOINT ["prom2teams", "--configpath", "/opt/prom2teams/config.ini"]
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ $ pip3 install prom2teams

```bash
# To start the server (a config file path must be provided, log file path, log level and Jinja2 template path are optional arguments):
$ prom2teams start --configpath <config file path> [--logfilepath <log file path>] [--loglevel (DEBUG|INFO|WARNING|ERROR|CRITICAL)] [--templatepath <Jinja2 template file path>]
$ prom2teams --configpath <config file path> [--logfilepath <log file path>] [--loglevel (DEBUG|INFO|WARNING|ERROR|CRITICAL)] [--templatepath <Jinja2 template file path>]

# To show the help message:
$ prom2teams --help
Expand Down Expand Up @@ -80,12 +80,17 @@ url: 0.0.0.0:8089

prom2teams provides a [default template](app/teams/template.j2) built with [Jinja2](http://jinja.pocoo.org/docs/2.9/) to render messages in Microsoft Teams. This template could be overrided using the 'templatepath' argument ('--templatepath <Jinja2 template file path>') during the application start.

Some fields are considered mandatory when received from Alert Manager.
If such a field is not included a default value of 'unknown' is assigned as described below:

Other optional fields are skipped and not included in the Teams message.

## Testing

To run the test suite you should type the following:

```bash
# After cloning prom2 teams :)
# After cloning prom2teams :)
$ python3 -m unittest discover tests
```

Expand Down
18 changes: 7 additions & 11 deletions prom2teams/message/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
logger = logging.getLogger()

def check_fields(json_alerts_attr, json_alerts_labels_attr, json_alerts_annotations_attr):
mandatory_fields = ['alertname', 'status', 'summary']
optional_fields = ['severity', 'description', 'instance']
mandatory_fields = ['alertname', 'status', 'instance', 'summary']
optional_fields = ['severity', 'description']
fields = mandatory_fields + optional_fields

alert_fields = {}

# Set the instance to 'none' by default.
alert_fields['alert_instance'] = 'none'

for field in fields:
alert_field_key = 'alert_' + field
if field in json_alerts_attr:
Expand All @@ -22,13 +19,12 @@ def check_fields(json_alerts_attr, json_alerts_labels_attr, json_alerts_annotati
alert_fields[alert_field_key] = json_alerts_labels_attr[field]
elif field in json_alerts_annotations_attr:
alert_fields[alert_field_key] = json_alerts_annotations_attr[field]
# If the field isn't in the JSON but it's a mandatory field, then we send an error message
# If the field isn't in the JSON but it's a mandatory field, then we use default values
elif field in mandatory_fields:
alert_fields['alert_severity'] = 'severe'
alert_fields['alert_status'] = 'incorrect'
alert_fields['alert_summary'] = 'Incorrect JSON received. At least one mandatory field ('+field+') is absent.'
return alert_fields

if field in json_alerts_attr:
alert_fields[alert_field_key] = json_alerts_attr[field]
else:
alert_fields[alert_field_key] = 'unknown'
return alert_fields

def parse(json_str):
Expand Down
5 changes: 3 additions & 2 deletions prom2teams/teams/template.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
'resolved' : '2DC72D',
'critical' : '8C1A1A',
'severe' : '8C1A1A',
'warning' : 'FF9A0B'
'warning' : 'FF9A0B',
'unknown' : 'CCCCCC'
}
-%}

Expand All @@ -12,7 +13,7 @@
"@context": "http://schema.org/extensions",
"themeColor": "{% if alert_status=='resolved' %} {{ theme_colors.resolved }} {% else %} {{ theme_colors[msg_text.alert_severity] }} {% endif %}",
"summary": "{{ msg_text.alert_summary }}",
"title": "Prometheus alarm {% if alert_status=='resolved' %} (Resolved) {% elif alert_status=='incorrect' %} (Incorrect) {% endif %}",
"title": "Prometheus alarm {% if alert_status=='resolved' %} (Resolved) {% elif alert_status=='unknown' %} (status unknown) {% endif %}",
"sections": [{
"activityTitle": "{{ msg_text.alert_summary }}",
"facts": [{% if msg_text.alert_alertname %}{
Expand Down
8 changes: 2 additions & 6 deletions tests/data/jsons/without_mandatory_field.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
"alerts": [
{
"labels": {
"alertname": "DiskSpace",
"device": "rootfs",
"fstype": "rootfs",
"instance": "cs30.evilcorp",
"job": "fsociety",
"mountpoint": "/",
"severity": "severe"
"mountpoint": "/"
},
"annotations": {
"description": "disk usage 73% on rootfs device",
"summary": "Disk usage alert on CS30.evilcorp"
"description": "disk usage 73% on rootfs device"
},
"startsAt": "2017-05-09T07:01:37.803Z",
"endsAt": "2017-05-09T07:08:37.818278068Z",
Expand Down
8 changes: 4 additions & 4 deletions tests/test_json_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ def test_json_with_all_fields(self):
with open(self.TEST_CONFIG_FILES_PATH + 'all_ok.json') as json_data:
json_received = json.load(json_data)
alert_fields = parse(json.dumps(json_received))
self.assertNotIn('Incorrect',str(alert_fields))
self.assertNotIn('unknown',str(alert_fields))

def test_json_without_mandatory_field(self):
with open(self.TEST_CONFIG_FILES_PATH + 'without_mandatory_field.json') as json_data:
json_received = json.load(json_data)
alert_fields = parse(json.dumps(json_received))
self.assertIn('Incorrect',str(alert_fields))
self.assertIn('unknown',str(alert_fields))

def test_json_without_optional_field(self):
with open(self.TEST_CONFIG_FILES_PATH + 'without_optional_field.json') as json_data:
json_received = json.load(json_data)
alert_fields = parse(json.dumps(json_received))
self.assertNotIn('Incorrect',str(alert_fields))
self.assertNotIn('unknown',str(alert_fields))

def test_json_without_instance_field(self):
with open(self.TEST_CONFIG_FILES_PATH + 'without_instance_field.json') as json_data:
json_received = json.load(json_data)
alert_fields = parse(json.dumps(json_received))
self.assertEqual('none',str(alert_fields['alarm_0']['alert_instance']))
self.assertEqual('unknown',str(alert_fields['alarm_0']['alert_instance']))

if __name__ == '__main__':
unittest.main()

0 comments on commit d53f214

Please sign in to comment.