From 217182384660cee32136236899d0f9cf55e3f804 Mon Sep 17 00:00:00 2001 From: David Moreau Simard Date: Tue, 23 Oct 2018 22:21:33 -0400 Subject: [PATCH] Finish JT.credentials functionality, add test Original commit: commit 3ec6196477135230c4b90b175310bdc2eaff36ed Author: David Moreau Simard Date: Tue Oct 23 22:21:33 2018 -0400 Add support for "credentials" in the tower_job_template module Job templates might require more than one credential. There's credential, vault_credential, machine_credential, etc. "credentials" is a thing, let's support it. --- awx_collection/README.md | 1 + .../plugins/modules/tower_job_template.py | 35 +++++++++++++++++-- awx_collection/test/awx/test_job_template.py | 26 ++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/awx_collection/README.md b/awx_collection/README.md index 901ac06b49..e817ea5ecd 100644 --- a/awx_collection/README.md +++ b/awx_collection/README.md @@ -19,6 +19,7 @@ The following notes are changes that may require changes to playbooks. - Specifying `inputs` or `injectors` as strings in the `tower_credential_type` module is no longer supported. Provide as dictionaries instead. - When a project is created, it will wait for the update/sync to finish by default; this can be turned off with the `wait` parameter, if desired. + - Creating a "scan" type job template is no longer supported. ## Running diff --git a/awx_collection/plugins/modules/tower_job_template.py b/awx_collection/plugins/modules/tower_job_template.py index 1a3575eba8..3d8a7a0730 100644 --- a/awx_collection/plugins/modules/tower_job_template.py +++ b/awx_collection/plugins/modules/tower_job_template.py @@ -36,7 +36,7 @@ options: description: - The job type to use for the job template. required: True - choices: ["run", "check", "scan"] + choices: ["run", "check"] type: str inventory: description: @@ -55,11 +55,20 @@ options: credential: description: - Name of the credential to use for the job template. + - Deprecated, mutually exclusive with 'credentials'. version_added: 2.7 type: str + credentials: + description: + - List of credentials to use for the job template. + - Will not remove any existing credentials. This may change in the future. + version_added: 2.8 + type: list + default: [] vault_credential: description: - Name of the vault credential to use for the job template. + - Deprecated, mutually exclusive with 'credential'. version_added: 2.7 type: str forks: @@ -300,13 +309,14 @@ def main(): argument_spec = dict( name=dict(required=True), description=dict(default=''), - job_type=dict(choices=['run', 'check', 'scan'], required=True), + job_type=dict(choices=['run', 'check']), inventory=dict(default=''), project=dict(required=True), playbook=dict(required=True), credential=dict(default=''), vault_credential=dict(default=''), custom_virtualenv=dict(type='str', required=False), + credentials=dict(type='list', default=[]), forks=dict(type='int'), limit=dict(default=''), verbosity=dict(type='int', choices=[0, 1, 2, 3, 4], default=0), @@ -335,7 +345,14 @@ def main(): state=dict(choices=['present', 'absent'], default='present'), ) - module = TowerModule(argument_spec=argument_spec, supports_check_mode=True) + module = TowerModule( + argument_spec=argument_spec, + supports_check_mode=True, + mutually_exclusive=[ + ('credential', 'credentials'), + ('vault_credential', 'credentials') + ] + ) name = module.params.get('name') state = module.params.pop('state') @@ -359,6 +376,18 @@ def main(): except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo: module.fail_json(msg='Failed to update job template: {0}'.format(excinfo), changed=False) + cred_list = module.params.get('credentials') + if cred_list: + cred = tower_cli.get_resource('credential') + for cred_name in cred_list: + try: + cred_id = cred.get(name=cred_name)['id'] + r = jt.associate_credential(result['id'], cred_id) + except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo: + module.fail_json(msg='Failed to add credential to job template: {0}'.format(excinfo), changed=False) + if r.get('changed'): + result['changed'] = True + json_output['changed'] = result['changed'] module.exit_json(**json_output) diff --git a/awx_collection/test/awx/test_job_template.py b/awx_collection/test/awx/test_job_template.py index daa9eacac5..39a9800df7 100644 --- a/awx_collection/test/awx/test_job_template.py +++ b/awx_collection/test/awx/test_job_template.py @@ -80,3 +80,29 @@ def test_create_job_template_with_old_machine_cred(run_module, admin_user, proje } assert machine_credential.id in [cred.pk for cred in jt.credentials.all()] + + +@pytest.mark.django_db +def test_create_job_template_with_new_credentials(run_module, admin_user, project, inventory, machine_credential): + jt = JobTemplate.objects.create( + name='foo', + playbook='helloworld.yml', + inventory=inventory, + project=project + ) + result = run_module('tower_job_template', dict( + name='foo', + playbook='helloworld.yml', + project=project.name, + credentials=[machine_credential.name] + ), admin_user) + assert result.pop('changed', None), result + + result.pop('invocation') + assert result == { + "job_template": "foo", + "state": "present", + "id": jt.id + } + + assert [machine_credential.id] == [cred.pk for cred in jt.credentials.all()]