from contextlib import suppress from awxkit.api.mixins import HasCreate, HasCopy, DSAdapter from awxkit.api.pages import Organization from awxkit.api.resources import resources from awxkit.config import config import awxkit.exceptions as exc from awxkit.utils import not_provided, random_title, PseudoNamespace from . import base from . import page job_results = ('any', 'error', 'success') notification_types = ('email', 'irc', 'pagerduty', 'slack', 'twilio', 'webhook', 'mattermost', 'grafana', 'rocketchat') class NotificationTemplate(HasCopy, HasCreate, base.Base): dependencies = [Organization] NATURAL_KEY = ('organization', 'name') def test(self): """Create test notification""" assert 'test' in self.related, "No such related attribute 'test'" # trigger test notification notification_id = self.related.test.post().notification # return notification page notifications_pg = self.get_related('notifications', id=notification_id).wait_until_count(1) assert notifications_pg.count == 1, "test notification triggered (id:%s) but notification not found in response at %s/notifications/" % ( notification_id, self.url, ) return notifications_pg.results[0] def silent_delete(self): """Delete the Notification Template, ignoring the exception that is raised if there are notifications pending. """ try: super(NotificationTemplate, self).silent_delete() except (exc.MethodNotAllowed): pass def payload(self, organization, notification_type='slack', messages=not_provided, **kwargs): payload = PseudoNamespace( name=kwargs.get('name') or 'NotificationTemplate ({0}) - {1}'.format(notification_type, random_title()), description=kwargs.get('description') or random_title(10), organization=organization.id, notification_type=notification_type, ) if messages != not_provided: payload['messages'] = messages notification_configuration = kwargs.get('notification_configuration', {}) payload.notification_configuration = notification_configuration if payload.notification_configuration == {}: services = config.credentials.notification_services if notification_type == 'email': fields = ('host', 'username', 'password', 'port', 'use_ssl', 'use_tls', 'sender', 'recipients') cred = services.email elif notification_type == 'irc': fields = ('server', 'port', 'use_ssl', 'password', 'nickname', 'targets') cred = services.irc elif notification_type == 'pagerduty': fields = ('client_name', 'service_key', 'subdomain', 'token') cred = services.pagerduty elif notification_type == 'slack': fields = ('channels', 'token') cred = services.slack elif notification_type == 'twilio': fields = ('account_sid', 'account_token', 'from_number', 'to_numbers') cred = services.twilio elif notification_type == 'webhook': fields = ('url', 'headers') cred = services.webhook elif notification_type == 'mattermost': fields = ('mattermost_url', 'mattermost_username', 'mattermost_channel', 'mattermost_icon_url', 'mattermost_no_verify_ssl') cred = services.mattermost elif notification_type == 'grafana': fields = ('grafana_url', 'grafana_key') cred = services.grafana elif notification_type == 'rocketchat': fields = ('rocketchat_url', 'rocketchat_no_verify_ssl') cred = services.rocketchat else: raise ValueError('Unknown notification_type {0}'.format(notification_type)) for field in fields: if field == 'bot_token': payload_field = 'token' else: payload_field = field value = kwargs.get(field, cred.get(field, not_provided)) if value != not_provided: payload.notification_configuration[payload_field] = value return payload def create_payload(self, name='', description='', notification_type='slack', organization=Organization, messages=not_provided, **kwargs): if notification_type not in notification_types: raise ValueError('Unsupported notification type "{0}". Please use one of {1}.'.format(notification_type, notification_types)) self.create_and_update_dependencies(organization) payload = self.payload( organization=self.ds.organization, notification_type=notification_type, name=name, description=description, messages=messages, **kwargs ) payload.ds = DSAdapter(self.__class__.__name__, self._dependency_store) return payload def create(self, name='', description='', notification_type='slack', organization=Organization, messages=not_provided, **kwargs): payload = self.create_payload( name=name, description=description, notification_type=notification_type, organization=organization, messages=messages, **kwargs ) return self.update_identity(NotificationTemplates(self.connection).post(payload)) def associate(self, resource, job_result='any'): """Associates a NotificationTemplate with the provided resource""" return self._associate(resource, job_result) def disassociate(self, resource, job_result='any'): """Disassociates a NotificationTemplate with the provided resource""" return self._associate(resource, job_result, disassociate=True) def _associate(self, resource, job_result='any', disassociate=False): if job_result not in job_results: raise ValueError('Unsupported job_result type "{0}". Please use one of {1}.'.format(job_result, job_results)) result_attr = 'notification_templates_{0}'.format(job_result) if result_attr not in resource.related: raise ValueError('Unsupported resource "{0}". Does not have a related {1} field.'.format(resource, result_attr)) payload = dict(id=self.id) if disassociate: payload['disassociate'] = True with suppress(exc.NoContent): getattr(resource.related, result_attr).post(payload) page.register_page( [ resources.notification_template, (resources.notification_templates, 'post'), (resources.notification_template_copy, 'post'), resources.notification_template_any, resources.notification_template_started, resources.notification_template_error, resources.notification_template_success, resources.notification_template_approval, ], NotificationTemplate, ) class NotificationTemplates(page.PageList, NotificationTemplate): pass page.register_page( [ resources.notification_templates, resources.related_notification_templates, resources.notification_templates_any, resources.notification_templates_started, resources.notification_templates_error, resources.notification_templates_success, resources.notification_templates_approvals, ], NotificationTemplates, ) class NotificationTemplateCopy(base.Base): pass page.register_page(resources.notification_template_copy, NotificationTemplateCopy) class NotificationTemplateTest(base.Base): pass page.register_page(resources.notification_template_test, NotificationTemplateTest)