From a2d1c32da3e6fcdcf5b4544d666ea9607efe0efa Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Wed, 1 Apr 2020 13:15:04 -0400 Subject: [PATCH 1/8] Initial commit of tests for tower_workflow_launch --- .../plugins/modules/tower_workflow_launch.py | 196 +++++++++++------- .../tower_workflow_launch/tasks/main.yml | 75 +++++++ 2 files changed, 193 insertions(+), 78 deletions(-) create mode 100644 awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml diff --git a/awx_collection/plugins/modules/tower_workflow_launch.py b/awx_collection/plugins/modules/tower_workflow_launch.py index b403205253..7d0a962ee5 100644 --- a/awx_collection/plugins/modules/tower_workflow_launch.py +++ b/awx_collection/plugins/modules/tower_workflow_launch.py @@ -20,11 +20,34 @@ description: - Launch an Ansible Tower workflows. See U(https://www.ansible.com/tower) for an overview. options: - workflow_template: + name: description: - The name of the workflow template to run. required: True type: str + aliases: + - workflow_template + organization: + description: + - Organization the workflow job template exists in. + - Used to help lookup the object, cannot be modified using this module. + - If not provided, will lookup by name only, which does not work with duplicates. + required: False + type: str + inventory: + description: + - Inventory to use for the job, only used if prompt for inventory is set. + type: str + limit: + description: + - Limit to use for the I(job_template). + type: str + scm_branch: + description: + - A specific of the SCM project to run the template on. + - This is only applicable if your project allows for branch override. + type: str + version_added: "3.7" extra_vars: description: - Any extra vars required to launch the job. @@ -34,25 +57,21 @@ options: - Wait for the workflow to complete. default: True type: bool + interval: + description: + - The interval to request an update from Tower. + required: False + default: 1 + type: float timeout: description: - If waiting for the workflow to complete this will abort after this amount of seconds type: int - -requirements: - - "python >= 2.6" - - ansible-tower-cli >= 3.0.2 - extends_documentation_fragment: awx.awx.auth ''' RETURN = ''' -tower_version: - description: The version of Tower we connected to - returned: If connection to Tower works - type: str - sample: '3.4.0' job_info: description: dictionary containing information about the workflow executed returned: If workflow launched @@ -70,7 +89,7 @@ EXAMPLES = ''' - name: Launch a Workflow with parameters without waiting tower_workflow_launch: - workflow_template: "Test workflow" + name: "Test workflow" extra_vars: "---\nmy: var" wait: False delegate_to: localhost @@ -78,89 +97,110 @@ EXAMPLES = ''' register: workflow_task_info ''' -from ..module_utils.ansible_tower import TowerModule, tower_auth_config - -try: - import tower_cli - from tower_cli.api import client - from tower_cli.conf import settings - from tower_cli.exceptions import ServerError, ConnectionError, BadRequest, TowerCLIError -except ImportError: - pass +from ..module_utils.tower_api import TowerModule +import time def main(): + # Any additional arguments that are not fields of the item can be added here argument_spec = dict( - workflow_template=dict(required=True), + name=dict(required=True, aliases=['workflow_template']), + organization=dict(), + inventory=dict(), + limit=dict(), extra_vars=dict(), - wait=dict(default=True, type='bool'), - timeout=dict(default=None, type='int'), + wait=dict(required=False, default=True, type='bool'), + interval=dict(required=False, default=1.0, type='float'), + timeout=dict(required=False, default=None, type='int'), ) - module = TowerModule( - argument_spec=argument_spec, - supports_check_mode=True - ) + # Create a module for ourselves + module = TowerModule(argument_spec=argument_spec, supports_check_mode=True) - workflow_template = module.params.get('workflow_template') - extra_vars = module.params.get('extra_vars') + optional_args = {} + # Extract our parameters + name = module.params.get('name') + organization = module.params.get('organization') + inventory = module.params.get('inventory') + optional_args['limit'] = module.params.get('limit') + optional_args['extra_vars'] = module.params.get('extra_vars') wait = module.params.get('wait') + interval = module.params.get('interval') timeout = module.params.get('timeout') - # If we are going to use this result to return we can consider ourselfs changed - result = dict( - changed=False, - msg='initial message' - ) + # Create a datastructure to pass into our job launch + post_data = {} + for key in optional_args.keys(): + if optional_args[key]: + post_data[key] = optional_args[key] - tower_auth = tower_auth_config(module) - with settings.runtime_values(**tower_auth): - # First we will test the connection. This will be a test for both check and run mode - # Note, we are not using the tower_check_mode method here because we want to do more than just a ping test - # If we are in check mode we also want to validate that we can find the workflow - try: - ping_result = client.get('/ping').json() - # Stuff the version into the results as an FYI - result['tower_version'] = ping_result['version'] - except(ServerError, ConnectionError, BadRequest) as excinfo: - result['msg'] = "Failed to reach Tower: {0}".format(excinfo) - module.fail_json(**result) + # Attempt to look up the related items the user specified (these will fail the module if not found) + if inventory: + post_data['inventory'] = module.resolve_name_to_id('inventories', inventory) - # Now that we know we can connect, lets verify that we can resolve the workflow_template - try: - workflow = tower_cli.get_resource("workflow").get(**{'name': workflow_template}) - except TowerCLIError as e: - result['msg'] = "Failed to find workflow: {0}".format(e) - module.fail_json(**result) - # Since we were able to find the workflow, if we are in check mode we can return now - if module.check_mode: - result['msg'] = "Check mode passed" - module.exit_json(**result) + # Attempt to look up job_template based on the provided name + lookup_data = { 'name': name } + if organization: + lookup_data['organization'] = module.resolve_name_to_id('organizations', organization) + workflow_job_template = module.get_one('workflow_job_templates', **{ 'data': lookup_data }) - # We are no ready to run the workflow - try: - result['job_info'] = tower_cli.get_resource('workflow_job').launch( - workflow_job_template=workflow['id'], - monitor=False, - wait=wait, - timeout=timeout, - extra_vars=extra_vars - ) - if wait: - # If we were waiting for a result we will fail if the workflow failed - if result['job_info']['failed']: - result['msg'] = "Workflow execution failed" - module.fail_json(**result) - else: - module.exit_json(**result) + if workflow_job_template is None: + module.fail_json(msg="Unable to find workflow job template") - # We were not waiting and there should be no way we can make it here without the workflow fired off so we can return a success - module.exit_json(**result) + # The API will allow you to submit values to a jb launch that are not prompt on launch. + # Therefore, we will test to see if anything is set which is not prompt on launch and fail. + check_vars_to_prompts = { + 'inventory': 'ask_inventory_on_launch', + 'limit': 'ask_limit_on_launch', + 'scm_branch': 'ask_scm_branch_on_launch', + 'extra_vars': 'ask_variables_on_launch', + } - except TowerCLIError as e: - result['msg'] = "Failed to execute workflow: {0}".format(e) - module.fail_json(**result) + param_errors = [] + for variable_name in check_vars_to_prompts: + if variable_name in post_data and not workflow_job_template[check_vars_to_prompts[variable_name]]: + param_errors.append("The field {0} was specified but the workflow job template does not allow for it to be overridden".format(variable_name)) + if len(param_errors) > 0: + module.fail_json(msg="Parameters specified which can not be passed into wotkflow job template, see errors for details", **{'errors': param_errors}) + + # Launch the job + result = module.post_endpoint(workflow_job_template['related']['launch'], **{'data': post_data}) + + if result['status_code'] != 201: + module.fail_json(msg="Failed to launch workflow, see response for details", **{'response': result}) + + module.json_output['changed'] = True + module.json_output['id'] = result['json']['id'] + module.json_output['status'] = result['json']['status'] + # This is for backwards compatability + module.json_output['job_info'] = { 'id': result['json']['id'] } + + if not wait: + module.exit_json(**module.json_output) + + # Grab our start time to compare against for the timeout + start = time.time() + + job_url = result['json']['url'] + while not result['json']['finished']: + # If we are past our time out fail with a message + if timeout and timeout < time.time() - start: + module.json_output['msg'] = "Monitoring aborted due to timeout" + module.fail_json(**module.json_output) + + # Put the process to sleep for our interval + time.sleep(interval) + + result = module.get_endpoint(job_url) + module.json_output['status'] = result['json']['status'] + + # If the job has failed, we want to raise an Exception for that so we get a non-zero response. + if result['json']['failed']: + module.json_output['msg'] = 'Job with id {0} failed'.format(job_id) + module.fail_json(**module.json_output) + + module.exit_json(**module.json_output) if __name__ == '__main__': diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml new file mode 100644 index 0000000000..9debcf7537 --- /dev/null +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -0,0 +1,75 @@ +- name: Generate a random string for test + set_fact: + test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + when: test_id is not defined + +- name: Generate names + set_fact: + wfjt_name1: "Testing Workflow Job Launch" #"AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" + +- name: Create our workflow + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: present + +- name: Add a node + tower_workflow_job_template_node: + workflow_job_template: "{{ wfjt_name1 }}" + unified_job_template: "Demo Job Template" + identifier: leaf + register: new_node + +- name: Connect to Tower server but request an invalid workflow + tower_workflow_launch: + validate_certs: False + workflow_template: "Does Not Exist" + ignore_errors: true + register: result + +- assert: + that: + - result is failed + - "'Unable to find workflow job template' in result.msg" + +- name: Run the workflow without waiting (this should just give us back a job ID) + tower_workflow_launch: + validate_certs: False + workflow_template: "{{ wfjt_name1 }}" + wait: False + ignore_errors: True + register: result + +- assert: + that: + - result is not failed + - "'id' in result['job_info']" + +- name: Kick off a workflow and wait for it + tower_workflow_launch: + validate_certs: False + workflow_template: "{{ wfjt_name1 }}" + ignore_errors: True + register: result + +- assert: + that: + - result is not failed + - "'id' in result['job_info']" + +- name: Kick off a workflow and wait for it, but only for a second + tower_workflow_launch: + validate_certs: False + workflow_template: "{{ wfjt_name1 }}" + timeout: 1 + ignore_errors: True + register: result + +- assert: + that: + - result is failed + - "'Monitoring aborted due to timeout' in result.msg" + +- name: Cleanup workflow + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: absent From 9ddd020348d425739c91ba18d5138ef1bd8b4d7c Mon Sep 17 00:00:00 2001 From: beeankha Date: Tue, 7 Apr 2020 17:22:50 -0400 Subject: [PATCH 2/8] Fix sanity tests and edit test playbook --- .../plugins/modules/tower_workflow_launch.py | 16 +++++++++++----- .../targets/tower_workflow_launch/tasks/main.yml | 11 ++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/awx_collection/plugins/modules/tower_workflow_launch.py b/awx_collection/plugins/modules/tower_workflow_launch.py index 7d0a962ee5..31535fd52c 100644 --- a/awx_collection/plugins/modules/tower_workflow_launch.py +++ b/awx_collection/plugins/modules/tower_workflow_launch.py @@ -68,6 +68,12 @@ options: - If waiting for the workflow to complete this will abort after this amount of seconds type: int + tower_oauthtoken: + description: + - The Tower OAuth token to use. + required: False + type: str + version_added: "3.7" extends_documentation_fragment: awx.awx.auth ''' @@ -108,6 +114,7 @@ def main(): organization=dict(), inventory=dict(), limit=dict(), + scm_branch=dict(), extra_vars=dict(), wait=dict(required=False, default=True, type='bool'), interval=dict(required=False, default=1.0, type='float'), @@ -138,12 +145,11 @@ def main(): if inventory: post_data['inventory'] = module.resolve_name_to_id('inventories', inventory) - # Attempt to look up job_template based on the provided name - lookup_data = { 'name': name } + lookup_data = {'name': name} if organization: lookup_data['organization'] = module.resolve_name_to_id('organizations', organization) - workflow_job_template = module.get_one('workflow_job_templates', **{ 'data': lookup_data }) + workflow_job_template = module.get_one('workflow_job_templates', **{'data': lookup_data}) if workflow_job_template is None: module.fail_json(msg="Unable to find workflow job template") @@ -174,7 +180,7 @@ def main(): module.json_output['id'] = result['json']['id'] module.json_output['status'] = result['json']['status'] # This is for backwards compatability - module.json_output['job_info'] = { 'id': result['json']['id'] } + module.json_output['job_info'] = {'id': result['json']['id']} if not wait: module.exit_json(**module.json_output) @@ -197,7 +203,7 @@ def main(): # If the job has failed, we want to raise an Exception for that so we get a non-zero response. if result['json']['failed']: - module.json_output['msg'] = 'Job with id {0} failed'.format(job_id) + module.json_output['msg'] = 'The workflow "{0}" failed'.format(name) module.fail_json(**module.json_output) module.exit_json(**module.json_output) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index 9debcf7537..e32c406fe5 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -1,3 +1,4 @@ +--- - name: Generate a random string for test set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" @@ -7,6 +8,11 @@ set_fact: wfjt_name1: "Testing Workflow Job Launch" #"AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" +- name: Clean up test workflow from any previous runs + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: absent + - name: Create our workflow tower_workflow_job_template: name: "{{ wfjt_name1 }}" @@ -68,8 +74,3 @@ that: - result is failed - "'Monitoring aborted due to timeout' in result.msg" - -- name: Cleanup workflow - tower_workflow_job_template: - name: "{{ wfjt_name1 }}" - state: absent From 8b26ff1fe630e394700eb8c5d8958e30150399dc Mon Sep 17 00:00:00 2001 From: beeankha Date: Tue, 7 Apr 2020 20:23:51 -0400 Subject: [PATCH 3/8] Fix linter errors --- .../targets/tower_workflow_launch/tasks/main.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index e32c406fe5..929f000c75 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -27,7 +27,7 @@ - name: Connect to Tower server but request an invalid workflow tower_workflow_launch: - validate_certs: False + validate_certs: false workflow_template: "Does Not Exist" ignore_errors: true register: result @@ -39,10 +39,10 @@ - name: Run the workflow without waiting (this should just give us back a job ID) tower_workflow_launch: - validate_certs: False + validate_certs: false workflow_template: "{{ wfjt_name1 }}" - wait: False - ignore_errors: True + wait: false + ignore_errors: true register: result - assert: @@ -52,9 +52,9 @@ - name: Kick off a workflow and wait for it tower_workflow_launch: - validate_certs: False + validate_certs: false workflow_template: "{{ wfjt_name1 }}" - ignore_errors: True + ignore_errors: true register: result - assert: @@ -64,10 +64,10 @@ - name: Kick off a workflow and wait for it, but only for a second tower_workflow_launch: - validate_certs: False + validate_certs: false workflow_template: "{{ wfjt_name1 }}" timeout: 1 - ignore_errors: True + ignore_errors: true register: result - assert: From 6403895eae1c378d4eff774bb903254afbe99ee4 Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Wed, 8 Apr 2020 09:29:23 -0400 Subject: [PATCH 4/8] Puting tasks back to natural order --- .../tower_workflow_launch/tasks/main.yml | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index 929f000c75..459ac813cb 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -6,12 +6,7 @@ - name: Generate names set_fact: - wfjt_name1: "Testing Workflow Job Launch" #"AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" - -- name: Clean up test workflow from any previous runs - tower_workflow_job_template: - name: "{{ wfjt_name1 }}" - state: absent + wfjt_name1: "AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" - name: Create our workflow tower_workflow_job_template: @@ -50,18 +45,6 @@ - result is not failed - "'id' in result['job_info']" -- name: Kick off a workflow and wait for it - tower_workflow_launch: - validate_certs: false - workflow_template: "{{ wfjt_name1 }}" - ignore_errors: true - register: result - -- assert: - that: - - result is not failed - - "'id' in result['job_info']" - - name: Kick off a workflow and wait for it, but only for a second tower_workflow_launch: validate_certs: false @@ -74,3 +57,21 @@ that: - result is failed - "'Monitoring aborted due to timeout' in result.msg" + +- name: Kick off a workflow and wait for it + tower_workflow_launch: + validate_certs: false + workflow_template: "{{ wfjt_name1 }}" + ignore_errors: true + register: result + +- assert: + that: + - result is not failed + - "'id' in result['job_info']" + +- name: Clean up test workflow + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: absent + From 97d26728e431afb992da0e684a29c3a09322e94b Mon Sep 17 00:00:00 2001 From: beeankha Date: Wed, 8 Apr 2020 09:46:11 -0400 Subject: [PATCH 5/8] Fix one more linter issue --- .../targets/tower_workflow_launch/tasks/main.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index 459ac813cb..e32ea4586c 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -6,7 +6,12 @@ - name: Generate names set_fact: - wfjt_name1: "AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" + wfjt_name1: "Testing Workflow Job Launch" # "AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" + +- name: Clean up test workflow from any previous runs + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: absent - name: Create our workflow tower_workflow_job_template: @@ -69,9 +74,3 @@ that: - result is not failed - "'id' in result['job_info']" - -- name: Clean up test workflow - tower_workflow_job_template: - name: "{{ wfjt_name1 }}" - state: absent - From d7adcfb119426b65e017bd97f1a13eeebbb2fba0 Mon Sep 17 00:00:00 2001 From: beeankha Date: Wed, 8 Apr 2020 09:59:38 -0400 Subject: [PATCH 6/8] Revert unnecessary changes made to test playbook during rebase --- .../targets/tower_workflow_launch/tasks/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index e32ea4586c..3d3c41feb2 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -6,12 +6,7 @@ - name: Generate names set_fact: - wfjt_name1: "Testing Workflow Job Launch" # "AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" - -- name: Clean up test workflow from any previous runs - tower_workflow_job_template: - name: "{{ wfjt_name1 }}" - state: absent + wfjt_name1: "AWX-Collection-tests-tower_workflow_launch--wfjt1-{{ test_id }}" - name: Create our workflow tower_workflow_job_template: @@ -74,3 +69,8 @@ that: - result is not failed - "'id' in result['job_info']" + +- name: Clean up test workflow + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: absent From cf607691ac516f1e1449c7f01da9b201dfce8926 Mon Sep 17 00:00:00 2001 From: beeankha Date: Thu, 9 Apr 2020 12:40:13 -0400 Subject: [PATCH 7/8] Pass data and errors more clearly, change extra_vars to be a dict, update test playbook to have a task utilizing extra_vars --- .../plugins/modules/tower_workflow_launch.py | 43 ++++++++++--------- .../tower_workflow_launch/tasks/main.yml | 20 +++++++++ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/awx_collection/plugins/modules/tower_workflow_launch.py b/awx_collection/plugins/modules/tower_workflow_launch.py index 31535fd52c..0e7d8da75f 100644 --- a/awx_collection/plugins/modules/tower_workflow_launch.py +++ b/awx_collection/plugins/modules/tower_workflow_launch.py @@ -36,7 +36,7 @@ options: type: str inventory: description: - - Inventory to use for the job, only used if prompt for inventory is set. + - Inventory to use for the job ran with this workflow, only used if prompt for inventory is set. type: str limit: description: @@ -44,14 +44,14 @@ options: type: str scm_branch: description: - - A specific of the SCM project to run the template on. + - A specific branch of the SCM project to run the template on. - This is only applicable if your project allows for branch override. type: str version_added: "3.7" extra_vars: description: - Any extra vars required to launch the job. - type: str + type: dict wait: description: - Wait for the workflow to complete. @@ -86,24 +86,22 @@ job_info: EXAMPLES = ''' -- name: Launch a workflow +- name: Launch a workflow with a timeout of 10 seconds tower_workflow_launch: - name: "Test Workflow" - delegate_to: localhost - run_once: true - register: workflow_results + workflow_template: "Test Workflow" + timeout: 10 -- name: Launch a Workflow with parameters without waiting +- name: Launch a Workflow with extra_vars without waiting tower_workflow_launch: - name: "Test workflow" - extra_vars: "---\nmy: var" + workflow_template: "Test workflow" + extra_vars: + var1: My First Variable + var2: My Second Variable wait: False - delegate_to: localhost - run_once: true - register: workflow_task_info ''' from ..module_utils.tower_api import TowerModule +import json import time @@ -115,7 +113,7 @@ def main(): inventory=dict(), limit=dict(), scm_branch=dict(), - extra_vars=dict(), + extra_vars=dict(type='dict'), wait=dict(required=False, default=True, type='bool'), interval=dict(required=False, default=1.0, type='float'), timeout=dict(required=False, default=None, type='int'), @@ -135,6 +133,11 @@ def main(): interval = module.params.get('interval') timeout = module.params.get('timeout') + # Special treatment of extra_vars parameter + extra_vars = module.params.get('extra_vars') + if extra_vars is not None: + optional_args['extra_vars'] = json.dumps(extra_vars) + # Create a datastructure to pass into our job launch post_data = {} for key in optional_args.keys(): @@ -149,7 +152,7 @@ def main(): lookup_data = {'name': name} if organization: lookup_data['organization'] = module.resolve_name_to_id('organizations', organization) - workflow_job_template = module.get_one('workflow_job_templates', **{'data': lookup_data}) + workflow_job_template = module.get_one('workflow_job_templates', data=lookup_data) if workflow_job_template is None: module.fail_json(msg="Unable to find workflow job template") @@ -168,13 +171,13 @@ def main(): if variable_name in post_data and not workflow_job_template[check_vars_to_prompts[variable_name]]: param_errors.append("The field {0} was specified but the workflow job template does not allow for it to be overridden".format(variable_name)) if len(param_errors) > 0: - module.fail_json(msg="Parameters specified which can not be passed into wotkflow job template, see errors for details", **{'errors': param_errors}) + module.fail_json(msg="Parameters specified which can not be passed into wotkflow job template, see errors for details", errors=param_errors) # Launch the job - result = module.post_endpoint(workflow_job_template['related']['launch'], **{'data': post_data}) + result = module.post_endpoint(workflow_job_template['related']['launch'], data=post_data) if result['status_code'] != 201: - module.fail_json(msg="Failed to launch workflow, see response for details", **{'response': result}) + module.fail_json(msg="Failed to launch workflow, see response for details", response=result) module.json_output['changed'] = True module.json_output['id'] = result['json']['id'] @@ -201,7 +204,7 @@ def main(): result = module.get_endpoint(job_url) module.json_output['status'] = result['json']['status'] - # If the job has failed, we want to raise an Exception for that so we get a non-zero response. + # If the job has failed, we want to raise a task failure for that so we get a non-zero response. if result['json']['failed']: module.json_output['msg'] = 'The workflow "{0}" failed'.format(name) module.fail_json(**module.json_output) diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index 3d3c41feb2..9f9c76e2a8 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -70,6 +70,26 @@ - result is not failed - "'id' in result['job_info']" +- name: Prompt the workflow's extra_vars on launch + tower_workflow_job_template: + name: "{{ wfjt_name1 }}" + state: present + ask_variables_on_launch: true + +- name: Kick off a workflow with extra_vars + tower_workflow_launch: + validate_certs: false + workflow_template: "{{ wfjt_name1 }}" + extra_vars: + var1: My First Variable + var2: My Second Variable + ignore_errors: true + register: result + +- assert: + that: + - result is not failed + - name: Clean up test workflow tower_workflow_job_template: name: "{{ wfjt_name1 }}" From 4acdf8584bfb33fcb47281547deb5a33f755556f Mon Sep 17 00:00:00 2001 From: beeankha Date: Thu, 9 Apr 2020 15:12:49 -0400 Subject: [PATCH 8/8] Update workflow_launch module and test playbook --- awx_collection/plugins/modules/tower_workflow_launch.py | 1 - .../integration/targets/tower_workflow_launch/tasks/main.yml | 5 ----- 2 files changed, 6 deletions(-) diff --git a/awx_collection/plugins/modules/tower_workflow_launch.py b/awx_collection/plugins/modules/tower_workflow_launch.py index 0e7d8da75f..6b78e877e2 100644 --- a/awx_collection/plugins/modules/tower_workflow_launch.py +++ b/awx_collection/plugins/modules/tower_workflow_launch.py @@ -128,7 +128,6 @@ def main(): organization = module.params.get('organization') inventory = module.params.get('inventory') optional_args['limit'] = module.params.get('limit') - optional_args['extra_vars'] = module.params.get('extra_vars') wait = module.params.get('wait') interval = module.params.get('interval') timeout = module.params.get('timeout') diff --git a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml index 9f9c76e2a8..bf88aecf7d 100644 --- a/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_workflow_launch/tasks/main.yml @@ -22,7 +22,6 @@ - name: Connect to Tower server but request an invalid workflow tower_workflow_launch: - validate_certs: false workflow_template: "Does Not Exist" ignore_errors: true register: result @@ -34,7 +33,6 @@ - name: Run the workflow without waiting (this should just give us back a job ID) tower_workflow_launch: - validate_certs: false workflow_template: "{{ wfjt_name1 }}" wait: false ignore_errors: true @@ -47,7 +45,6 @@ - name: Kick off a workflow and wait for it, but only for a second tower_workflow_launch: - validate_certs: false workflow_template: "{{ wfjt_name1 }}" timeout: 1 ignore_errors: true @@ -60,7 +57,6 @@ - name: Kick off a workflow and wait for it tower_workflow_launch: - validate_certs: false workflow_template: "{{ wfjt_name1 }}" ignore_errors: true register: result @@ -78,7 +74,6 @@ - name: Kick off a workflow with extra_vars tower_workflow_launch: - validate_certs: false workflow_template: "{{ wfjt_name1 }}" extra_vars: var1: My First Variable