Fix Slack notification setup to support the new slack web hook format and convert all existing data to use the new format (so we only have one code path)
This commit is contained in:
parent
79b61e7709
commit
107847a4bb
5 changed files with 97 additions and 22 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
|
|
@ -363,11 +363,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 +375,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 +384,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 +419,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;
|
||||
};
|
||||
|
|
54
tools/migrateslackwebhook.py
Normal file
54
tools/migrateslackwebhook.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
import argparse
|
||||
import logging
|
||||
import json
|
||||
|
||||
from app import app
|
||||
from data import model
|
||||
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