Skip to content

Commit

Permalink
Add slack notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
sukrit007 committed Jul 13, 2016
1 parent 6792d98 commit f2369e2
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 1 deletion.
6 changes: 6 additions & 0 deletions conf/appconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
.strip().lower() in BOOLEAN_TRUE_VALUES,
'token': '',
'level': LEVEL_PENDING
},
'slack': {
'enabled': os.getenv('HIPCHAT_ENABLED', 'false').strip()
.lower() in BOOLEAN_TRUE_VALUES,
'level': LEVEL_FAILED,
'url': ''
}
}
}
Expand Down
18 changes: 17 additions & 1 deletion orchestrator/tasks/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ def notify_hipchat(obj, ctx, level, config, security_profile):
headers=headers).raise_for_status()


@app.task
def notify_slack(obj, ctx, level, config, security_profile):
config = decrypt_config(config, profile=security_profile)
ctx.setdefault('github', True)
url = config.get('url')
msg = templatefactory.render_template(
'slack.json.jinja', notification=util.as_dict(obj), ctx=ctx,
level=level)
headers = {
'content-type': 'application/json',
}
if url:
requests.post(url, data=msg, headers=headers)\
.raise_for_status()


@app.task
def notify_github(obj, ctx, level, config, security_profile):
config = decrypt_config(config, profile=security_profile)
Expand Down Expand Up @@ -96,5 +112,5 @@ def notify_github(obj, ctx, level, config, security_profile):
requests.post(status_url, data=json.dumps(data),
headers=headers).raise_for_status()
else:
# Github notification not sent
# Github notification is not sent
pass
31 changes: 31 additions & 0 deletions orchestrator/templates/slack.json.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"username": "Orchestrator ({{ctx.env}}-{{ctx.operation}})",
"channel": "{{ notification.channel or '#totem' }}",
"text":
{% if ctx.github %}
"<https://github.com/{{ctx.owner}}|{{ctx.owner or 'NA'}}> / <https://github.com/{{ctx.owner}}/{{ctx.repo}}|{{ctx.repo or 'NA'}}> / <https://github.com/{{ctx.owner}}/{{ctx.repo}}/{{ctx.ref}}|{{ctx.ref or 'NA'}} / <https://github.com/{{ctx.owner}}/{{ctx.repo}}/commits/{{ctx.commit or ctx.ref}}|{{ctx.commit or ctx.ref or 'NA'}}>"
{% else %}
"{{ctx.owner or 'NA'}} / {{ctx.repo or 'NA'}} / {{ctx.ref or 'NA'}} / {{ctx.commit or 'NA'}}"
{% endif %},

"attachments": [
{
"text": "{{ notification.message | truncate(1000) }} {%if notification.code == 'CONFIG_VALIDATION_ERROR' -%}
<https://github.com/totem/cluster-orchestrator/blob/master/schemas/job-config-v1.json | Click here to view the job-config-v1 schema.>
{%- endif %} {% if ctx['job-id'] -%}
(job-id: {{ ctx['job-id'] }})
{%- endif -%}",
"color":
{% if level == 1 %}
"danger"
{% elif level == 2 %}
"warning"
{% elif level == 3 %}
"good"
{% else %}
"#439FE0"
{% endif %}
}
]

}
37 changes: 37 additions & 0 deletions tests/integration/orchestrator/templates/test_slack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import json

from nose.tools import eq_, ok_

from orchestrator import templatefactory

"""
Tests for Slack Jinja templates
"""


def test_slack_template():
"""
should render json output for slack API.
"""

output = templatefactory.render_template(
'slack.json.jinja',
ctx={
"env": "local",
"operation": "test",
"owner": "test-owner",
"repo": "test-repo",
"ref": "test-ref",
"github": True,
"job-id": "test-job"
},
notification={
"message": "test message",
"code": "CONFIG_VALIDATION_ERROR"
}, level=1)
slack_dict = json.loads(output)

eq_(slack_dict.get("username"), "Orchestrator (local-test)")
eq_(slack_dict.get("channel"), "#totem")
ok_(slack_dict.get("text"))
ok_(slack_dict.get("attachments"))
54 changes: 54 additions & 0 deletions tests/unit/orchestrator/tasks/test_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,60 @@ def test_notify_hipchat_for_level_success(m_json, m_templatefactory,
})


@patch('orchestrator.tasks.notification.requests')
@patch('orchestrator.tasks.notification.templatefactory')
@patch('orchestrator.tasks.notification.json')
def test_notify_slack(m_json, m_templatefactory, m_requests):
"""
Should send slack notification
:return:
"""
# Given: Template factory that renders html template for notification
m_templatefactory.render_template.return_value = '{}'

# And: Mock implementation for jsonify (for validating data)
m_json.dumps.side_effect = lambda data: data

# When: I send message using slack
notification.notify_slack(
{'message': 'mock'}, {}, LEVEL_FAILED,
{'url': 'http://mockslackurl'},
'default')

# Then: Notification gets send successfully
m_requests.post.assert_called_once_with(
'http://mockslackurl',
headers={
'content-type': 'application/json'
},
data='{}')


@patch('orchestrator.tasks.notification.requests')
@patch('orchestrator.tasks.notification.templatefactory')
@patch('orchestrator.tasks.notification.json')
def test_notify_slack_when_url_is_not_set(m_json, m_templatefactory,
m_requests):
"""
Should not send slack notification
:return:
"""
# Given: Template factory that renders html template for notification
m_templatefactory.render_template.return_value = '{}'

# And: Mock implementation for jsonify (for validating data)
m_json.dumps.side_effect = lambda data: data

# When: I send message using slack
notification.notify_slack(
{'message': 'mock'}, {}, LEVEL_FAILED,
{},
'default')

# Then: Notification is not sent
m_requests.post.assert_not_called()


@patch('orchestrator.tasks.notification.requests')
@patch('orchestrator.tasks.notification.json')
def test_github(m_json, m_requests):
Expand Down

0 comments on commit f2369e2

Please sign in to comment.