diff --git a/awx_collection/README.md b/awx_collection/README.md index df4508cf60..380f46549e 100644 --- a/awx_collection/README.md +++ b/awx_collection/README.md @@ -51,6 +51,7 @@ The following notes are changes that may require changes to playbooks: - Specified `tower_config` file used to handle `k=v` pairs on a single line; this is no longer supported. Please use a file formatted as `yaml`, `json` or `ini` only. - Some return values (e.g., `credential_type`) have been removed. Use of `id` is recommended. - `tower_job_template` no longer supports the deprecated `extra_vars_path` parameter, please use `extra_vars` with the lookup plugin to replace this functionality. + - The `notification_configuration` parameter of `tower_notification` has changed from a string to a dict. Please use the `lookup` plugin to read an existing file into a dict. ## Running Unit Tests diff --git a/awx_collection/plugins/modules/tower_notification.py b/awx_collection/plugins/modules/tower_notification.py index fb384fd878..1d31c01195 100644 --- a/awx_collection/plugins/modules/tower_notification.py +++ b/awx_collection/plugins/modules/tower_notification.py @@ -26,168 +26,182 @@ options: name: description: - The name of the notification. + type: str required: True + new_name: + description: + - Setting this option will change the existing name (looked up via the name field. type: str description: description: - The description of the notification. - required: False type: str organization: description: - The organization the notification belongs to. - required: False type: str notification_type: description: - The type of notification to be sent. - required: True - choices: ["email", "slack", "twilio", "pagerduty", "hipchat", "webhook", "irc"] + choices: + - 'email' + - 'grafana' + - 'hipchat' + - 'irc' + - 'mattermost' + - 'pagerduty' + - 'rocketchat' + - 'slack' + - 'twilio' + - 'webhook' type: str notification_configuration: description: - The notification configuration file. Note providing this field would disable all notification-configuration-related fields. - required: False - type: str + type: dict + messages: + description: + - Optional custom messages for notification template. + type: dict username: description: - - The mail server username. Required if I(notification_type=email). - required: False + - The mail server username. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str sender: description: - - The sender email address. Required if I(notification_type=email). - required: False + - The sender email address. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str recipients: description: - - The recipients email addresses. Required if I(notification_type=email). - required: False + - The recipients email addresses. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: list elements: str use_tls: description: - - The TLS trigger. Required if I(notification_type=email). - required: False + - The TLS trigger. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: bool host: description: - - The mail server host. Required if I(notification_type=email). - required: False + - The mail server host. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str use_ssl: description: - - The SSL trigger. Required if I(notification_type=email) or if I(notification_type=irc). - required: False + - The SSL trigger. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: bool password: description: - - The mail server password. Required if I(notification_type=email) or if I(notification_type=irc). - required: False + - The mail server password. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str port: description: - - The mail server port. Required if I(notification_type=email) or if I(notification_type=irc). - required: False + - The mail server port. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: int channels: description: - - The destination Slack channels. Required if I(notification_type=slack). - required: False + - The destination Slack channels. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: list elements: str token: description: - - The access token. Required if I(notification_type=slack), if I(notification_type=pagerduty) or if I(notification_type=hipchat). - required: False + - The access token. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str account_token: description: - - The Twillio account token. Required if I(notification_type=twillio). - required: False + - The Twillio account token. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str from_number: description: - - The source phone number. Required if I(notification_type=twillio). - required: False + - The source phone number. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str to_numbers: description: - - The destination phone numbers. Required if I(notification_type=twillio). - required: False + - The destination phone numbers. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: list elements: str account_sid: description: - - The Twillio account SID. Required if I(notification_type=twillio). - required: False + - The Twillio account SID. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str subdomain: description: - - The PagerDuty subdomain. Required if I(notification_type=pagerduty). - required: False + - The PagerDuty subdomain. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str service_key: description: - - The PagerDuty service/integration API key. Required if I(notification_type=pagerduty). - required: False + - The PagerDuty service/integration API key. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str client_name: description: - - The PagerDuty client identifier. Required if I(notification_type=pagerduty). - required: False + - The PagerDuty client identifier. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str message_from: description: - - The label to be shown with the notification. Required if I(notification_type=hipchat). - required: False + - The label to be shown with the notification. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str api_url: description: - - The HipChat API URL. Required if I(notification_type=hipchat). - required: False + - The HipChat API URL. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str color: description: - - The notification color. Required if I(notification_type=hipchat). - required: False + - The notification color. + - This parameter has been deprecated, please use 'notification_configuration' instead. choices: ["yellow", "green", "red", "purple", "gray", "random"] type: str rooms: description: - - HipChat rooms to send the notification to. Required if I(notification_type=hipchat). - required: False + - HipChat rooms to send the notification to. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: list elements: str notify: description: - - The notify channel trigger. Required if I(notification_type=hipchat). - required: False + - The notify channel trigger. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: bool url: description: - - The target URL. Required if I(notification_type=webhook). - required: False + - The target URL. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str headers: description: - - The HTTP headers as JSON string. Required if I(notification_type=webhook). - required: False + - The HTTP headers as JSON string. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: dict server: description: - - The IRC server address. Required if I(notification_type=irc). - required: False + - The IRC server address. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str nickname: description: - - The IRC nickname. Required if I(notification_type=irc). - required: False + - The IRC nickname. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: str targets: description: - - The destination channels or users. Required if I(notification_type=irc). - required: False + - The destination channels or users. + - This parameter has been deprecated, please use 'notification_configuration' instead. type: list elements: str state: @@ -196,22 +210,32 @@ options: default: "present" choices: ["present", "absent"] type: str - -requirements: -- ansible-tower-cli >= 3.0.2 - + tower_oauthtoken: + description: + - The Tower OAuth token to use. + version_added: "3.7" + type: str extends_documentation_fragment: awx.awx.auth ''' EXAMPLES = ''' -- name: Add Slack notification +- name: Add Slack notification with custom messages tower_notification: name: slack notification + organization: Default notification_type: slack - channels: - - general - token: cefda9e2be1f21d11cdd9452f5b7f97fda977f42 + notification_configuration: + channels: + - general + token: cefda9e2be1f21d11cdd9452f5b7f97fda977f42 + messages: + started: + message: "{{ '{{ job_friendly_name }}{{ job.id }} started' }}" + success: + message: "{{ '{{ job_friendly_name }} completed in {{ job.elapsed }} seconds' }}" + error: + message: "{{ '{{ job_friendly_name }} FAILED! Please look at {{ job.url }}' }}" state: present tower_config_file: "~/tower_cli.cfg" @@ -219,9 +243,10 @@ EXAMPLES = ''' tower_notification: name: webhook notification notification_type: webhook - url: http://www.example.com/hook - headers: - X-Custom-Header: value123 + notification_configuration: + url: http://www.example.com/hook + headers: + X-Custom-Header: value123 state: present tower_config_file: "~/tower_cli.cfg" @@ -229,15 +254,16 @@ EXAMPLES = ''' tower_notification: name: email notification notification_type: email - username: user - password: s3cr3t - sender: tower@example.com - recipients: - - user1@example.com - host: smtp.example.com - port: 25 - use_tls: no - use_ssl: no + notification_configuration: + username: user + password: s3cr3t + sender: tower@example.com + recipients: + - user1@example.com + host: smtp.example.com + port: 25 + use_tls: no + use_ssl: no state: present tower_config_file: "~/tower_cli.cfg" @@ -245,11 +271,12 @@ EXAMPLES = ''' tower_notification: name: twilio notification notification_type: twilio - account_token: a_token - account_sid: a_sid - from_number: '+15551112222' - to_numbers: - - '+15553334444' + notification_configuration: + account_token: a_token + account_sid: a_sid + from_number: '+15551112222' + to_numbers: + - '+15553334444' state: present tower_config_file: "~/tower_cli.cfg" @@ -257,10 +284,11 @@ EXAMPLES = ''' tower_notification: name: pagerduty notification notification_type: pagerduty - token: a_token - subdomain: sub - client_name: client - service_key: a_key + notification_configuration: + token: a_token + subdomain: sub + client_name: client + service_key: a_key state: present tower_config_file: "~/tower_cli.cfg" @@ -268,13 +296,14 @@ EXAMPLES = ''' tower_notification: name: hipchat notification notification_type: hipchat - token: a_token - message_from: user1 - api_url: https://hipchat.example.com - color: red - rooms: - - room-A - notify: yes + notification_configuration: + token: a_token + message_from: user1 + api_url: https://hipchat.example.com + color: red + rooms: + - room-A + notify: yes state: present tower_config_file: "~/tower_cli.cfg" @@ -282,20 +311,20 @@ EXAMPLES = ''' tower_notification: name: irc notification notification_type: irc - nickname: tower - password: s3cr3t - targets: - - user1 - port: 8080 - server: irc.example.com - use_ssl: no + notification_configuration: + nickname: tower + password: s3cr3t + targets: + - user1 + port: 8080 + server: irc.example.com + use_ssl: no state: present tower_config_file: "~/tower_cli.cfg" - name: Delete notification tower_notification: name: old notification - notification_type: email state: absent tower_config_file: "~/tower_cli.cfg" ''' @@ -304,125 +333,123 @@ EXAMPLES = ''' RETURN = ''' # ''' -from ..module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode +from ..module_utils.tower_api import TowerModule -try: - import tower_cli - import tower_cli.utils.exceptions as exc - - from tower_cli.conf import settings -except ImportError: - pass +OLD_INPUT_NAMES = ( + 'username', 'sender', 'recipients', 'use_tls', + 'host', 'use_ssl', 'password', 'port', + 'channels', 'token', 'account_token', 'from_number', + 'to_numbers', 'account_sid', 'subdomain', 'service_key', + 'client_name', 'message_from', 'api_url', 'color', + 'rooms', 'notify', 'url', 'headers', 'server', + 'nickname', 'targets', +) def main(): + # Any additional arguments that are not fields of the item can be added here argument_spec = dict( name=dict(required=True), - description=dict(required=False), - organization=dict(required=False), - notification_type=dict(required=True, choices=['email', 'slack', 'twilio', 'pagerduty', 'hipchat', 'webhook', 'irc']), - notification_configuration=dict(required=False), - username=dict(required=False), - sender=dict(required=False), - recipients=dict(required=False, type='list', elements='str'), - use_tls=dict(required=False, type='bool'), - host=dict(required=False), - use_ssl=dict(required=False, type='bool'), - password=dict(required=False, no_log=True), - port=dict(required=False, type='int'), - channels=dict(required=False, type='list', elements='str'), - token=dict(required=False, no_log=True), - account_token=dict(required=False, no_log=True), - from_number=dict(required=False), - to_numbers=dict(required=False, type='list', elements='str'), - account_sid=dict(required=False), - subdomain=dict(required=False), - service_key=dict(required=False, no_log=True), - client_name=dict(required=False), - message_from=dict(required=False), - api_url=dict(required=False), - color=dict(required=False, choices=['yellow', 'green', 'red', 'purple', 'gray', 'random']), - rooms=dict(required=False, type='list', elements='str'), - notify=dict(required=False, type='bool'), - url=dict(required=False), - headers=dict(required=False, type='dict', default={}), - server=dict(required=False), - nickname=dict(required=False), - targets=dict(required=False, type='list', elements='str'), + new_name=dict(), + description=dict(), + organization=dict(), + notification_type=dict(choices=[ + 'email', 'grafana', 'hipchat', 'irc', 'mattermost', + 'pagerduty', 'rocketchat', 'slack', 'twilio', 'webhook' + ]), + notification_configuration=dict(type='dict'), + messages=dict(type='dict'), + username=dict(), + sender=dict(), + recipients=dict(type='list', elements='str'), + use_tls=dict(type='bool'), + host=dict(), + use_ssl=dict(type='bool'), + password=dict(no_log=True), + port=dict(type='int'), + channels=dict(type='list', elements='str'), + token=dict(no_log=True), + account_token=dict(no_log=True), + from_number=dict(), + to_numbers=dict(type='list', elements='str'), + account_sid=dict(), + subdomain=dict(), + service_key=dict(no_log=True), + client_name=dict(), + message_from=dict(), + api_url=dict(), + color=dict(choices=['yellow', 'green', 'red', 'purple', 'gray', 'random']), + rooms=dict(type='list', elements='str'), + notify=dict(type='bool'), + url=dict(), + headers=dict(type='dict'), + server=dict(), + nickname=dict(), + targets=dict(type='list', elements='str'), state=dict(choices=['present', 'absent'], default='present'), ) + # Create a module for ourselves module = TowerModule(argument_spec=argument_spec, supports_check_mode=True) + # Extract our parameters name = module.params.get('name') + new_name = module.params.get("new_name") description = module.params.get('description') organization = module.params.get('organization') notification_type = module.params.get('notification_type') notification_configuration = module.params.get('notification_configuration') - username = module.params.get('username') - sender = module.params.get('sender') - recipients = module.params.get('recipients') - use_tls = module.params.get('use_tls') - host = module.params.get('host') - use_ssl = module.params.get('use_ssl') - password = module.params.get('password') - port = module.params.get('port') - channels = module.params.get('channels') - token = module.params.get('token') - account_token = module.params.get('account_token') - from_number = module.params.get('from_number') - to_numbers = module.params.get('to_numbers') - account_sid = module.params.get('account_sid') - subdomain = module.params.get('subdomain') - service_key = module.params.get('service_key') - client_name = module.params.get('client_name') - message_from = module.params.get('message_from') - api_url = module.params.get('api_url') - color = module.params.get('color') - rooms = module.params.get('rooms') - notify = module.params.get('notify') - url = module.params.get('url') - headers = module.params.get('headers') - server = module.params.get('server') - nickname = module.params.get('nickname') - targets = module.params.get('targets') + messages = module.params.get('messages') state = module.params.get('state') - json_output = {'notification': name, 'state': state} + # Attempt to look up the related items the user specified (these will fail the module if not found) + organization_id = None + if organization: + organization_id = module.resolve_name_to_id('organizations', organization) - tower_auth = tower_auth_config(module) - with settings.runtime_values(**tower_auth): - tower_check_mode(module) - notification_template = tower_cli.get_resource('notification_template') + # Attempt to look up an existing item based on the provided data + existing_item = module.get_one('notification_templates', **{ + 'data': { + 'name': name, + 'organization': organization_id, + } + }) - try: - org_res = tower_cli.get_resource('organization') - org = org_res.get(name=organization) + # Create notification_configuration from legacy inputs + final_notification_configuration = {} + for legacy_input in OLD_INPUT_NAMES: + if module.params.get(legacy_input) is not None: + module.deprecate(msg='{0} parameter has been deprecated, please use notification_configuration instead.'.format(legacy_input), version="3.6") + final_notification_configuration[legacy_input] = module.params.get(legacy_input) + # Give anything in notification_configuration prescedence over the individual inputs + if notification_configuration is not None: + final_notification_configuration.update(notification_configuration) - if state == 'present': - result = notification_template.modify(name=name, description=description, organization=org['id'], - notification_type=notification_type, - notification_configuration=notification_configuration, - username=username, sender=sender, recipients=recipients, - use_tls=use_tls, host=host, use_ssl=use_ssl, password=password, - port=port, channels=channels, token=token, - account_token=account_token, from_number=from_number, - to_numbers=to_numbers, account_sid=account_sid, - subdomain=subdomain, service_key=service_key, - client_name=client_name, message_from=message_from, - api_url=api_url, color=color, rooms=rooms, notify=notify, - url=url, headers=headers, server=server, nickname=nickname, - targets=targets, create_on_missing=True) - json_output['id'] = result['id'] - elif state == 'absent': - result = notification_template.delete(name=name) - except (exc.NotFound) as excinfo: - module.fail_json(msg='Failed to update notification template, organization not found: {0}'.format(excinfo), changed=False) - except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo: - module.fail_json(msg='Failed to update notification template: {0}'.format(excinfo), changed=False) + # Create the data that gets sent for create and update + new_fields = {} + if final_notification_configuration: + new_fields['notification_configuration'] = final_notification_configuration + new_fields['name'] = new_name if new_name else name + if description is not None: + new_fields['description'] = description + if organization is not None: + new_fields['organization'] = organization_id + if notification_type is not None: + new_fields['notification_type'] = notification_type + if messages is not None: + new_fields['messages'] = messages - json_output['changed'] = result['changed'] - module.exit_json(**json_output) + if state == 'absent': + # If the state was absent we can let the module delete it if needed, the module will handle exiting from this + module.delete_if_needed(existing_item) + elif state == 'present': + # If the state was present and we can let the module build or update the existing item, this will return on its own + module.create_or_update_if_needed( + existing_item, new_fields, + endpoint='notification_templates', item_type='notification_template', + associations={ + } + ) if __name__ == '__main__': diff --git a/awx_collection/test/awx/test_notification.py b/awx_collection/test/awx/test_notification.py new file mode 100644 index 0000000000..f06b83b79e --- /dev/null +++ b/awx_collection/test/awx/test_notification.py @@ -0,0 +1,112 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import pytest + +from awx.main.models import NotificationTemplate + + +def compare_with_encrypted(model_config, param_config): + '''Given a model_config from the database, assure that this is consistent + with the config given in the notification_configuration parameter + this requires handling of password fields + ''' + for key, model_val in model_config.items(): + param_val = param_config.get(key, 'missing') + if isinstance(model_val, str) and (model_val.startswith('$encrypted$') or param_val.startswith('$encrypted$')): + assert model_val.startswith('$encrypted$') # must be saved as encrypted + assert len(model_val) > len('$encrypted$') + else: + assert model_val == param_val, 'Config key {0} did not match, (model: {1}, input: {2})'.format( + key, model_val, param_val + ) + + +@pytest.mark.django_db +def test_create_modify_notification_template(run_module, admin_user, organization): + nt_config = { + 'username': 'user', + 'password': 'password', + 'sender': 'foo@invalid.com', + 'recipients': ['foo2@invalid.com'], + 'host': 'smtp.example.com', + 'port': 25, + 'use_tls': False, 'use_ssl': False, + 'timeout': 4 + } + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='email', + notification_configuration=nt_config, + ), admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert result.pop('changed', None), result + + nt = NotificationTemplate.objects.get(id=result['id']) + compare_with_encrypted(nt.notification_configuration, nt_config) + assert nt.organization == organization + + # Test no-op, this is impossible if the notification_configuration is given + # because we cannot determine if password fields changed + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='email', + ), admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert not result.pop('changed', None), result + + # Test a change in the configuration + nt_config['timeout'] = 12 + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='email', + notification_configuration=nt_config, + ), admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert result.pop('changed', None), result + + nt.refresh_from_db() + compare_with_encrypted(nt.notification_configuration, nt_config) + + +@pytest.mark.django_db +def test_invalid_notification_configuration(run_module, admin_user, organization): + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='email', + notification_configuration={}, + ), admin_user) + assert result.get('failed', False), result.get('msg', result) + assert 'Missing required fields for Notification Configuration' in result['msg'] + + +@pytest.mark.django_db +@pytest.mark.xfail(reason='Handling API validation changes w.r.t. changed status is an open item') +def test_deprecated_to_modern_no_op(run_module, admin_user, organization): + nt_config = { + 'url': 'http://www.example.com/hook', + 'headers': { + 'X-Custom-Header': 'value123' + } + } + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='webhook', + notification_configuration=nt_config, + ), admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert result.pop('changed', None), result + + result = run_module('tower_notification', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='webhook', + notification_configuration=nt_config, + ), admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert not result.pop('changed', None), result diff --git a/awx_collection/tests/integration/targets/tower_notification/tasks/main.yml b/awx_collection/tests/integration/targets/tower_notification/tasks/main.yml index 2c15f0b031..03025e4b6a 100644 --- a/awx_collection/tests/integration/targets/tower_notification/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_notification/tasks/main.yml @@ -9,7 +9,64 @@ hipchat_not: "AWX-Collection-tests-tower_notification-hipchat-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" irc_not: "AWX-Collection-tests-tower_notification-irc-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" -- name: Create Slack notification +- name: Test deprecation warnings + tower_notification: + name: "{{ slack_not }}" + organization: Default + notification_type: slack + username: maw + sender: maw + recipients: + - everyone + use_tls: true + host: all + use_ssl: false + password: password + port: 12 + channels: + - general + token: chunkecheese + account_token: asdf1234 + from_number: "1 (888) 733-4281" + to_numbers: + - 867-5309 + account_sid: vicious + subdomain: 'redhat.com' + service_key: skeleton + client_name: Bill + message_from: me + api_url: https://tower.example.com/api/v2 + color: green + rooms: + - The Study + - Kitchen + - Ballroom + - Conservatory + - Billiard Room + - Library + - Hall + - Lounge + - Dining Room + - Cellar + notify: true + url: ansible.com + headers: + X-Custom-Header: value123 + server: littimer.somewhere.com + nickname: chalk + targets: + - zombie + state: absent + register: result + ignore_errors: true + +- assert: + that: + - "'deprecations' in result" + # The 27 can be count from the size of the OLD_INPUT_NAMES list in the module + - result['deprecations'] | length() == 27 + +- name: Create Slack notification with custom messages tower_notification: name: "{{ slack_not }}" organization: Default @@ -17,6 +74,13 @@ token: a_token channels: - general + messages: + started: + message: "{{ '{{' }} job_friendly_name {{' }}' }} {{ '{{' }} job.id {{' }}' }} started" + success: + message: "{{ '{{' }} job_friendly_name {{ '}}' }} completed in {{ '{{' }} job.elapsed {{ '}}' }} seconds" + error: + message: "{{ '{{' }} job_friendly_name {{ '}}' }} FAILED! Please look at {{ '{{' }} job.url {{ '}}' }}" state: present register: result @@ -28,7 +92,6 @@ tower_notification: name: "{{ slack_not }}" organization: Default - notification_type: slack state: absent register: result @@ -55,7 +118,6 @@ tower_notification: name: "{{ webhook_not }}" organization: Default - notification_type: webhook state: absent register: result @@ -88,7 +150,6 @@ tower_notification: name: "{{ email_not }}" organization: Default - notification_type: email state: absent register: result @@ -117,7 +178,6 @@ tower_notification: name: "{{ twillo_not }}" organization: Default - notification_type: twilio state: absent register: result @@ -145,7 +205,6 @@ tower_notification: name: "{{ pd_not }}" organization: Default - notification_type: pagerduty state: absent register: result @@ -176,7 +235,6 @@ tower_notification: name: "{{ hipchat_not }}" organization: Default - notification_type: hipchat state: absent register: result @@ -207,7 +265,6 @@ tower_notification: name: "{{ irc_not }}" organization: Default - notification_type: irc state: absent register: result