Merge pull request #2 from coreos-inc/escort
Fix Slack notification setup to support the new slack web hook format
This commit is contained in:
commit
e5f41889cf
5 changed files with 96 additions and 27 deletions
|
@ -0,0 +1,24 @@
|
|||
"""Convert slack webhook data
|
||||
|
||||
Revision ID: 5b84373e5db
|
||||
Revises: 1c5b738283a5
|
||||
Create Date: 2014-12-16 12:02:55.167744
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5b84373e5db'
|
||||
down_revision = '1c5b738283a5'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from tools.migrateslackwebhook import run_slackwebhook_migration
|
||||
|
||||
|
||||
def upgrade(tables):
|
||||
run_slackwebhook_migration()
|
||||
|
||||
|
||||
def downgrade(tables):
|
||||
pass
|
|
@ -1,14 +1,10 @@
|
|||
import logging
|
||||
import io
|
||||
import os.path
|
||||
import tarfile
|
||||
import base64
|
||||
import json
|
||||
import requests
|
||||
import re
|
||||
|
||||
from flask.ext.mail import Message
|
||||
from app import mail, app, get_app_url
|
||||
from app import mail, app
|
||||
from data import model
|
||||
from workers.worker import JobException
|
||||
|
||||
|
@ -363,11 +359,8 @@ class SlackMethod(NotificationMethod):
|
|||
return 'slack'
|
||||
|
||||
def validate(self, repository, config_data):
|
||||
if not config_data.get('token', ''):
|
||||
raise CannotValidateNotificationMethodException('Missing Slack Token')
|
||||
|
||||
if not config_data.get('subdomain', '').isalnum():
|
||||
raise CannotValidateNotificationMethodException('Missing Slack Subdomain Name')
|
||||
if not config_data.get('url', ''):
|
||||
raise CannotValidateNotificationMethodException('Missing Slack Callback URL')
|
||||
|
||||
def format_for_slack(self, message):
|
||||
message = message.replace('\n', '')
|
||||
|
@ -378,10 +371,8 @@ class SlackMethod(NotificationMethod):
|
|||
def perform(self, notification, event_handler, notification_data):
|
||||
config_data = json.loads(notification.config_json)
|
||||
|
||||
token = config_data.get('token', '')
|
||||
subdomain = config_data.get('subdomain', '')
|
||||
|
||||
if not token or not subdomain:
|
||||
url = config_data.get('url', '')
|
||||
if not url:
|
||||
return
|
||||
|
||||
owner = model.get_user_or_org(notification.repository.namespace_user.username)
|
||||
|
@ -389,8 +380,6 @@ class SlackMethod(NotificationMethod):
|
|||
# Something went wrong.
|
||||
return
|
||||
|
||||
url = 'https://%s.slack.com/services/hooks/incoming-webhook?token=%s' % (subdomain, token)
|
||||
|
||||
level = event_handler.get_level(notification_data['event_data'], notification_data)
|
||||
color = {
|
||||
'info': '#ffffff',
|
||||
|
@ -426,5 +415,5 @@ class SlackMethod(NotificationMethod):
|
|||
raise NotificationMethodPerformException(error_message)
|
||||
|
||||
except requests.exceptions.RequestException as ex:
|
||||
logger.exception('Slack method was unable to be sent: %s' % ex.message)
|
||||
logger.exception('Slack method was unable to be sent: %s', ex.message)
|
||||
raise NotificationMethodPerformException(ex.message)
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
<tr ng-if="currentMethod.fields.length"><td colspan="2"><hr></td></tr>
|
||||
|
||||
<tr ng-repeat="field in currentMethod.fields">
|
||||
<td valign="top">{{ field.title }}:</td>
|
||||
<td valign="top" style="padding-top: 10px">{{ field.title }}:</td>
|
||||
<td>
|
||||
<div ng-switch on="field.type">
|
||||
<span ng-switch-when="email">
|
||||
|
@ -81,6 +81,9 @@
|
|||
</span>
|
||||
<input type="url" class="form-control" ng-model="currentConfig[field.name]" ng-switch-when="url" required>
|
||||
<input type="text" class="form-control" ng-model="currentConfig[field.name]" ng-switch-when="string" required>
|
||||
<input type="text" class="form-control" ng-model="currentConfig[field.name]" ng-switch-when="regex" required
|
||||
ng-pattern="getPattern(field)"
|
||||
placeholder="{{ field.placeholder }}">
|
||||
<div class="entity-search" namespace="repository.namespace"
|
||||
placeholder="''"
|
||||
current-entity="currentConfig[field.name]"
|
||||
|
|
|
@ -1484,15 +1484,12 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
'icon': 'slack-icon',
|
||||
'fields': [
|
||||
{
|
||||
'name': 'subdomain',
|
||||
'type': 'string',
|
||||
'title': 'Slack Subdomain'
|
||||
},
|
||||
{
|
||||
'name': 'token',
|
||||
'type': 'string',
|
||||
'title': 'Token',
|
||||
'help_url': 'https://{subdomain}.slack.com/services/new/incoming-webhook'
|
||||
'name': 'url',
|
||||
'type': 'regex',
|
||||
'title': 'Webhook URL',
|
||||
'regex': '^https://hooks\\.slack\\.com/services/[A-Z0-9]+/[A-Z0-9]+/[a-zA-Z0-9]+$',
|
||||
'help_url': 'https://slack.com/services/new/incoming-webhook',
|
||||
'placeholder': 'https://hooks.slack.com/service/{some}/{token}/{here}'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -5905,6 +5902,10 @@ quayApp.directive('createExternalNotificationDialog', function () {
|
|||
$scope.events = ExternalNotificationData.getSupportedEvents();
|
||||
$scope.methods = ExternalNotificationData.getSupportedMethods();
|
||||
|
||||
$scope.getPattern = function(field) {
|
||||
return new RegExp(field.regex);
|
||||
};
|
||||
|
||||
$scope.setEvent = function(event) {
|
||||
$scope.currentEvent = event;
|
||||
};
|
||||
|
|
52
tools/migrateslackwebhook.py
Normal file
52
tools/migrateslackwebhook.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import logging
|
||||
import json
|
||||
|
||||
from app import app
|
||||
from data.database import configure, RepositoryNotification, ExternalNotificationMethod
|
||||
|
||||
configure(app.config)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def run_slackwebhook_migration():
|
||||
slack_method = ExternalNotificationMethod.get(ExternalNotificationMethod.name == "slack")
|
||||
|
||||
encountered = set()
|
||||
while True:
|
||||
found = list(RepositoryNotification.select().where(
|
||||
RepositoryNotification.method == slack_method,
|
||||
RepositoryNotification.config_json ** "%subdomain%",
|
||||
~(RepositoryNotification.config_json ** "%url%")))
|
||||
|
||||
found = [f for f in found if not f.uuid in encountered]
|
||||
|
||||
if not found:
|
||||
logger.debug('No additional records found')
|
||||
return
|
||||
|
||||
logger.debug('Found %s records to be changed', len(found))
|
||||
for notification in found:
|
||||
encountered.add(notification.uuid)
|
||||
|
||||
try:
|
||||
config = json.loads(notification.config_json)
|
||||
except:
|
||||
logging.error("Cannot parse config for noticification %s", notification.uuid)
|
||||
continue
|
||||
|
||||
logger.debug("Checking notification %s", notification.uuid)
|
||||
if 'subdomain' in config and 'token' in config:
|
||||
subdomain = config['subdomain']
|
||||
token = config['token']
|
||||
new_url = 'https://%s.slack.com/services/hooks/incoming-webhook?token=%s' % (subdomain, token)
|
||||
config['url'] = new_url
|
||||
|
||||
logger.debug("Updating notification %s to URL: %s", notification.uuid, new_url)
|
||||
notification.config_json = json.dumps(config)
|
||||
notification.save()
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
|
||||
run_slackwebhook_migration()
|
Reference in a new issue