From 8f1fccefebeeb085c234d3527b461e677c3699ec Mon Sep 17 00:00:00 2001 From: beeankha Date: Thu, 7 May 2020 11:44:43 -0400 Subject: [PATCH] Add notification association functionality to tower_workflow_job_template module, along with updated integration/unit tests --- .../modules/tower_workflow_job_template.py | 39 +++++++ .../test/awx/test_workflow_job_template.py | 49 ++++++++- .../tasks/main.yml | 104 +++++++++++++++++- 3 files changed, 185 insertions(+), 7 deletions(-) diff --git a/awx_collection/plugins/modules/tower_workflow_job_template.py b/awx_collection/plugins/modules/tower_workflow_job_template.py index a58b6d40bc..e130d02cf1 100644 --- a/awx_collection/plugins/modules/tower_workflow_job_template.py +++ b/awx_collection/plugins/modules/tower_workflow_job_template.py @@ -113,6 +113,21 @@ options: - If value not set, will try environment variable C(TOWER_OAUTH_TOKEN) and then config files type: str version_added: "3.7" + notification_templates_started: + description: + - list of notifications to send on start + type: list + elements: str + notification_templates_success: + description: + - list of notifications to send on success + type: list + elements: str + notification_templates_error: + description: + - list of notifications to send on error + type: list + elements: str extends_documentation_fragment: awx.awx.auth ''' @@ -155,6 +170,9 @@ def main(): ask_limit_on_launch=dict(type='bool'), webhook_service=dict(choices=['github', 'gitlab']), webhook_credential=dict(), + notification_templates_started=dict(type="list", elements='str'), + notification_templates_success=dict(type="list", elements='str'), + notification_templates_error=dict(type="list", elements='str'), state=dict(choices=['present', 'absent'], default='present'), ) @@ -204,6 +222,26 @@ def main(): if 'extra_vars' in new_fields: new_fields['extra_vars'] = json.dumps(new_fields['extra_vars']) + association_fields = {} + + notifications_start = module.params.get('notification_templates_started') + if notifications_start is not None: + association_fields['notification_templates_started'] = [] + for item in notifications_start: + association_fields['notification_templates_started'].append(module.resolve_name_to_id('notification_templates', item)) + + notifications_success = module.params.get('notification_templates_success') + if notifications_success is not None: + association_fields['notification_templates_success'] = [] + for item in notifications_success: + association_fields['notification_templates_success'].append(module.resolve_name_to_id('notification_templates', item)) + + notifications_error = module.params.get('notification_templates_error') + if notifications_error is not None: + association_fields['notification_templates_error'] = [] + for item in notifications_error: + association_fields['notification_templates_error'].append(module.resolve_name_to_id('notification_templates', item)) + on_change = None new_spec = module.params.get('survey') if new_spec: @@ -221,6 +259,7 @@ def main(): module.create_or_update_if_needed( existing_item, new_fields, endpoint='workflow_job_templates', item_type='workflow_job_template', + associations=association_fields, on_create=on_change, on_update=on_change ) diff --git a/awx_collection/test/awx/test_workflow_job_template.py b/awx_collection/test/awx/test_workflow_job_template.py index 903b399dbd..bc2a44b11e 100644 --- a/awx_collection/test/awx/test_workflow_job_template.py +++ b/awx_collection/test/awx/test_workflow_job_template.py @@ -3,7 +3,7 @@ __metaclass__ = type import pytest -from awx.main.models import WorkflowJobTemplate +from awx.main.models import WorkflowJobTemplate, NotificationTemplate @pytest.mark.django_db @@ -81,6 +81,53 @@ def test_survey_spec_only_changed(run_module, admin_user, organization, survey_s assert wfjt.survey_spec == survey_spec +@pytest.mark.django_db +def test_associate_only_on_success(run_module, admin_user, organization, project): + wfjt = WorkflowJobTemplate.objects.create( + organization=organization, name='foo-workflow', + # survey_enabled=True, survey_spec=survey_spec + ) + create_kwargs = dict( + notification_configuration={ + 'url': 'http://www.example.com/hook', + 'headers': { + 'X-Custom-Header': 'value123' + }, + 'password': 'bar' + }, + notification_type='webhook', + organization=organization + ) + nt1 = NotificationTemplate.objects.create(name='nt1', **create_kwargs) + nt2 = NotificationTemplate.objects.create(name='nt2', **create_kwargs) + + wfjt.notification_templates_error.add(nt1) + + # test preservation of error NTs when success NTs are added + result = run_module('tower_workflow_job_template', { + 'name': 'foo-workflow', + 'organization': organization.name, + 'notification_templates_success': ['nt2'] + }, admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert result.get('changed', True), result + + assert list(wfjt.notification_templates_success.values_list('id', flat=True)) == [nt2.id] + assert list(wfjt.notification_templates_error.values_list('id', flat=True)) == [nt1.id] + + # test removal to empty list + result = run_module('tower_workflow_job_template', { + 'name': 'foo-workflow', + 'organization': organization.name, + 'notification_templates_success': [] + }, admin_user) + assert not result.get('failed', False), result.get('msg', result) + assert result.get('changed', True), result + + assert list(wfjt.notification_templates_success.values_list('id', flat=True)) == [] + assert list(wfjt.notification_templates_error.values_list('id', flat=True)) == [nt1.id] + + @pytest.mark.django_db def test_delete_with_spec(run_module, admin_user, organization, survey_spec): WorkflowJobTemplate.objects.create( diff --git a/awx_collection/tests/integration/targets/tower_workflow_job_template/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_job_template/tasks/main.yml index 6840dd515a..8a7a977164 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_job_template/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_job_template/tasks/main.yml @@ -1,11 +1,17 @@ --- -- name: Generate names +- name: Generate a random string for names set_fact: - scm_cred_name: "AWX-Collection-tests-tower_workflow_job_template-scm-cred-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - demo_project_name: "AWX-Collection-tests-tower_workflow_job_template-proj-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - jt1_name: "AWX-Collection-tests-tower_workflow_job_template-jt1-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - jt2_name: "AWX-Collection-tests-tower_workflow_job_template-jt2-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - wfjt_name: "AWX-Collection-tests-tower_workflow_job_template-wfjt-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + +- name: Generate random names for test objects + set_fact: + scm_cred_name: "AWX-Collection-tests-tower_workflow_job_template-scm-cred-{{ test_id }}" + demo_project_name: "AWX-Collection-tests-tower_workflow_job_template-proj-{{ test_id }}" + jt1_name: "AWX-Collection-tests-tower_workflow_job_template-jt1-{{ test_id }}" + jt2_name: "AWX-Collection-tests-tower_workflow_job_template-jt2-{{ test_id }}" + wfjt_name: "AWX-Collection-tests-tower_workflow_job_template-wfjt-{{ test_id }}" + email_not: "AWX-Collection-tests-tower_job_template-email-not-{{ test_id }}" + webhook_not: "AWX-Collection-tests-tower_notification-wehbook-not-{{ test_id }}" - name: Create an SCM Credential tower_credential: @@ -18,6 +24,33 @@ that: - "result is changed" +- name: Add email notification + tower_notification: + name: "{{ email_not }}" + organization: Default + notification_type: email + username: user + password: s3cr3t + sender: tower@example.com + recipients: + - user1@example.com + host: smtp.example.com + port: 25 + use_tls: false + use_ssl: false + state: present + +- name: Add webhook notification + tower_notification: + name: "{{ webhook_not }}" + organization: Default + notification_type: webhook + url: http://www.example.com/hook + headers: + X-Custom-Header: value123 + state: present + register: result + - name: Create a Demo Project tower_project: name: "{{ demo_project_name }}" @@ -104,6 +137,53 @@ unified_job_template: "{{ jt1_name }}" workflow: "{{ wfjt_name }}" +- name: Add started notifications to workflow job template + tower_workflow_job_template: + name: "{{ wfjt_name }}" + notification_templates_started: + - "{{ email_not }}" + - "{{ webhook_not }}" + register: result + +- assert: + that: + - "result is changed" + +- name: Re Add started notifications to workflow job template + tower_workflow_job_template: + name: "{{ wfjt_name }}" + notification_templates_started: + - "{{ email_not }}" + - "{{ webhook_not }}" + register: result + +- assert: + that: + - "result is not changed" + +- name: Add success notifications to workflow job template + tower_workflow_job_template: + name: "{{ wfjt_name }}" + notification_templates_success: + - "{{ email_not }}" + - "{{ webhook_not }}" + register: result + +- assert: + that: + - "result is changed" + +- name: Remove "on start" webhook notification from workflow job template + tower_workflow_job_template: + name: "{{ wfjt_name }}" + notification_templates_started: + - "{{ email_not }}" + register: result + +- assert: + that: + - "result is changed" + - name: Delete a workflow job template with an invalid inventory and webook_credential tower_workflow_job_template: name: "{{ wfjt_name }}" @@ -182,3 +262,15 @@ - assert: that: - "result is changed" + +- name: Delete email notification + tower_notification: + name: "{{ email_not }}" + organization: Default + state: absent + +- name: Delete webhook notification + tower_notification: + name: "{{ webhook_not }}" + organization: Default + state: absent