rycus86/domain-automation

View on GitHub
src/notifications/slack_message.py

Summary

Maintainability
A
35 mins
Test Coverage
import logging
import threading

from slack import WebClient

from config import read_configuration
from metrics import Counter
from notifications import NotificationManager
from ssl_manager import SSLManager


logger = logging.getLogger('slack-notification')

messages_sent = Counter(
    'domain_automation_slack_sent',
    'The number of messages sent to Slack'
)
messages_failed = Counter(
    'domain_automation_slack_failed',
    'The number of messages failed to send to Slack'
)


class SlackNotificationManager(NotificationManager):
    def __init__(self):
        super(SlackNotificationManager, self).__init__()

        token = read_configuration(
            'SLACK_TOKEN', '/var/secrets/notifications'
        )

        self.channel = read_configuration(
            'SLACK_CHANNEL', '/var/secrets/notifications', 'general'
        )
        self.bot_name = read_configuration(
            'SLACK_BOT_NAME', '/var/secrets/notifications', 'domain-automation-bot'
        )
        self.bot_icon = read_configuration(
            'SLACK_BOT_ICON', '/var/secrets/notifications'
        )

        self.client = WebClient(token)

    def send_update(self, update_type, subdomain, result):
        message = '`[%s update]` *%s* : %s' % (update_type, subdomain.full, result)
        
        self.send_message(message)

    def send_message(self, message, retry=1):
        if retry > 3:
            logger.error('Giving up on Slack message: %s' % message)
            return

        extras = {'icon_url': self.bot_icon} if self.bot_icon else {}

        response = self.client.chat_postMessage(
            channel=self.channel,
            text=message,
            as_user=False,
            username=self.bot_name,
            **extras
        )

        if response['ok'] is False:
            messages_failed.inc()

            if 'Retry-After' in response['headers']:
                delay = int(response['headers']['Retry-After'])

                logger.debug('Retrying Slack message after %d seconds' % delay)

                retry_timer = threading.Timer(
                    delay, self.send_message,
                    args=[message], kwargs={'retry': retry + 1}
                )
                retry_timer.setDaemon(True)
                retry_timer.start()

            else:
                logger.error('Failed to send message to Slack: %s' % message)

        else:
            logger.info('Slack message sent: %s' % message)

            messages_sent.inc()

    def dns_updated(self, subdomain, result):
        self.send_update('DNS', subdomain, result)

    def ssl_updated(self, subdomain, result):
        if result == SSLManager.RESULT_NOT_YET_DUE_FOR_RENEWAL:
            return

        self.send_update('SSL', subdomain, result)

    def message(self, text):
        self.send_message(text)