From c026790f559a2e962098a191516cab1f06c40295 Mon Sep 17 00:00:00 2001 From: sean-m-ssullivan Date: Thu, 23 Sep 2021 13:25:01 -0400 Subject: [PATCH] add ability to lookup unified job template by org --- awx_collection/plugins/modules/schedule.py | 14 ++++- .../modules/workflow_job_template_node.py | 15 ++++- awx_collection/test/awx/test_completeness.py | 7 ++- .../targets/schedule/tasks/main.yml | 58 ++++++++++++++++++- .../workflow_job_template/tasks/main.yml | 56 ++++++++++++++++++ 5 files changed, 144 insertions(+), 6 deletions(-) diff --git a/awx_collection/plugins/modules/schedule.py b/awx_collection/plugins/modules/schedule.py index 7ca661ec6f..e29051209c 100644 --- a/awx_collection/plugins/modules/schedule.py +++ b/awx_collection/plugins/modules/schedule.py @@ -108,6 +108,11 @@ options: - Name of unified job template to schedule. required: False type: str + organization: + description: + - The organization the unified job template exists in. + - Used for looking up the unified job template, not a direct model field. + type: str enabled: description: - Enables processing of this schedule. @@ -161,6 +166,7 @@ def main(): diff_mode=dict(type='bool'), verbosity=dict(type='int', choices=[0, 1, 2, 3, 4, 5]), unified_job_template=dict(), + organization=dict(), enabled=dict(type='bool'), state=dict(choices=['present', 'absent'], default='present'), ) @@ -184,6 +190,7 @@ def main(): diff_mode = module.params.get('diff_mode') verbosity = module.params.get('verbosity') unified_job_template = module.params.get('unified_job_template') + organization = module.params.get('organization') enabled = module.params.get('enabled') state = module.params.get('state') @@ -191,10 +198,13 @@ def main(): inventory_id = None if inventory: inventory_id = module.resolve_name_to_id('inventories', inventory) + search_fields = {} + if organization: + search_fields['organization'] = module.resolve_name_to_id('organizations', organization) unified_job_template_id = None if unified_job_template: - unified_job_template_id = module.resolve_name_to_id('unified_job_templates', unified_job_template) - + search_fields['name'] = unified_job_template + unified_job_template_id = module.get_one('unified_job_templates', **{'data': search_fields})['id'] # Attempt to look up an existing item based on the provided data existing_item = module.get_one('schedules', name_or_id=name) diff --git a/awx_collection/plugins/modules/workflow_job_template_node.py b/awx_collection/plugins/modules/workflow_job_template_node.py index 82dddb07e4..bad358669e 100644 --- a/awx_collection/plugins/modules/workflow_job_template_node.py +++ b/awx_collection/plugins/modules/workflow_job_template_node.py @@ -93,6 +93,11 @@ options: - Omit if creating an approval node. - This parameter is mutually exclusive with C(approval_node). type: str + lookup_organization: + description: + - Organization the inventories, job template, project, inventory source the unified_job_template exists in. + - If not provided, will lookup by name only, which does not work with duplicates. + type: str approval_node: description: - A dictionary of Name, description, and timeout values for the approval node. @@ -243,6 +248,7 @@ def main(): diff_mode=dict(type='bool'), verbosity=dict(choices=['0', '1', '2', '3', '4', '5']), unified_job_template=dict(), + lookup_organization=dict(), approval_node=dict(type='dict'), all_parents_must_converge=dict(type='bool'), success_nodes=dict(type='list', elements='str'), @@ -270,6 +276,7 @@ def main(): state = module.params.get('state') approval_node = module.params.get('approval_node') new_fields = {} + lookup_organization = module.params.get('lookup_organization') search_fields = {'identifier': identifier} # Attempt to look up the related items the user specified (these will fail the module if not found) @@ -296,9 +303,15 @@ def main(): # 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) + # Set lookup data to use + search_fields = {} + if lookup_organization: + search_fields['organization'] = module.resolve_name_to_id('organizations', lookup_organization) + unified_job_template = module.params.get('unified_job_template') if unified_job_template: - new_fields['unified_job_template'] = module.resolve_name_to_id('unified_job_templates', unified_job_template) + search_fields['name'] = unified_job_template + new_fields['unified_job_template'] = module.get_one('unified_job_templates', **{'data': search_fields})['id'] inventory = module.params.get('inventory') if inventory: diff --git a/awx_collection/test/awx/test_completeness.py b/awx_collection/test/awx/test_completeness.py index 27fbd1afca..19e4f699dc 100644 --- a/awx_collection/test/awx/test_completeness.py +++ b/awx_collection/test/awx/test_completeness.py @@ -56,10 +56,13 @@ no_api_parameter_ok = { # We take an organization here to help with the lookups only 'job_template': ['survey_spec', 'organization'], 'inventory_source': ['organization'], - # Organization is how we are looking up job templates, Approval node is for workflow_approval_templates - 'workflow_job_template_node': ['organization', 'approval_node'], + # Organization is how we are looking up job templates, Approval node is for workflow_approval_templates, + # lookup_organization is for specifiying the organization for the unified job template lookup + 'workflow_job_template_node': ['organization', 'approval_node', 'lookup_organization'], # Survey is how we handle associations 'workflow_job_template': ['survey_spec', 'destroy_current_schema'], + # organization is how we lookup unified job templates + 'schedule': ['organization'], # ad hoc commands support interval and timeout since its more like job_launch 'ad_hoc_command': ['interval', 'timeout', 'wait'], # group parameters to perserve hosts and children. diff --git a/awx_collection/tests/integration/targets/schedule/tasks/main.yml b/awx_collection/tests/integration/targets/schedule/tasks/main.yml index ef4181e9d8..e8c5e469a6 100644 --- a/awx_collection/tests/integration/targets/schedule/tasks/main.yml +++ b/awx_collection/tests/integration/targets/schedule/tasks/main.yml @@ -5,10 +5,13 @@ - name: generate random string for schedule set_fact: + org_name: "AWX-Collection-tests-organization-org-{{ test_id }}" sched1: "AWX-Collection-tests-schedule-sched1-{{ test_id }}" cred1: "AWX-Collection-tests-schedule-cred1-{{ test_id }}" - proj1: "AWX-Collection-tests-schedule-proj-{{ test_id }}" + proj1: "AWX-Collection-tests-schedule-proj1-{{ test_id }}" + proj2: "AWX-Collection-tests-schedule-proj2-{{ test_id }}" jt1: "AWX-Collection-tests-schedule-jt1-{{ test_id }}" + jt2: "AWX-Collection-tests-schedule-jt1-{{ test_id }}" - block: - name: Try to create without an rrule @@ -84,6 +87,19 @@ scm_type: git scm_url: https://github.com/ansible/ansible-tower-samples.git + - name: "Create a new organization" + organization: + name: "{{ org_name }}" + + - name: Create a Demo Project in another org + project: + name: "{{ proj2 }}" + organization: "{{ org_name }}" + allow_override: true + state: present + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + - name: Create Credential1 credential: name: "{{ cred1 }}" @@ -154,6 +170,24 @@ - assert: that: - result is changed + + - name: Create a second Job Template in new org + job_template: + name: "{{ jt2 }}" + project: "{{ proj2 }}" + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: present + + - name: Build a schedule with a job template's name in two orgs + schedule: + name: "{{ sched1 }}" + state: present + unified_job_template: "{{ jt2 }}" + rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" + register: result + always: - name: Delete the schedule schedule: @@ -167,6 +201,22 @@ playbook: hello_world.yml state: absent + - name: Delete the jt + job_template: + name: "{{ jt2 }}" + project: "{{ proj2 }}" + playbook: hello_world.yml + state: absent + + - name: Delete the Project + project: + name: "{{ proj2 }}" + organization: "{{ org_name }}" + state: absent + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + register: result + - name: Delete the Project project: name: "{{ proj1 }}" @@ -182,3 +232,9 @@ organization: Default credential_type: Red Hat Ansible Automation Platform state: absent + + - name: "Remove the organization" + organization: + name: "{{ org_name }}" + state: absent + register: result diff --git a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml index ea7887077a..bfd64ce89b 100644 --- a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml +++ b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml @@ -8,6 +8,7 @@ org_name: "AWX-Collection-tests-organization-org-{{ test_id }}" scm_cred_name: "AWX-Collection-tests-workflow_job_template-scm-cred-{{ test_id }}" demo_project_name: "AWX-Collection-tests-workflow_job_template-proj-{{ test_id }}" + demo_project_name_2: "AWX-Collection-tests-workflow_job_template-proj-{{ test_id }}_2" jt1_name: "AWX-Collection-tests-workflow_job_template-jt1-{{ test_id }}" jt2_name: "AWX-Collection-tests-workflow_job_template-jt2-{{ test_id }}" approval_node_name: "AWX-Collection-tests-workflow_approval_node-{{ test_id }}" @@ -87,6 +88,20 @@ that: - "result is changed" +- name: Create a 2nd Demo Project in another org + project: + name: "{{ demo_project_name_2 }}" + organization: "{{ org_name }}" + state: present + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + scm_credential: "{{ scm_cred_name }}" + register: result + +- assert: + that: + - "result is changed" + - name: Add an inventory inventory: description: Test inventory @@ -136,6 +151,20 @@ that: - "result is changed" +- name: Create a second Job Template in new org + job_template: + name: "{{ jt2_name }}" + project: "{{ demo_project_name_2 }}" + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: present + register: result + +- assert: + that: + - "result is changed" + - name: Add a Survey to second Job Template job_template: name: "{{ jt2_name }}" @@ -191,6 +220,7 @@ workflow_job_template_node: identifier: leaf unified_job_template: "{{ jt2_name }}" + lookup_organization: "{{ org_name }}" workflow: "{{ wfjt_name }}" - name: Create root node @@ -616,6 +646,22 @@ job_template: name: "{{ jt2_name }}" project: "{{ demo_project_name }}" + organization: Default + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: absent + register: result + +- assert: + that: + - "result is changed" + +- name: Delete the second Job Template + job_template: + name: "{{ jt2_name }}" + project: "{{ demo_project_name_2 }}" + organization: "{{ org_name }}" inventory: Demo Inventory playbook: hello_world.yml job_type: run @@ -658,6 +704,16 @@ state: absent register: result +- name: Delete the 2nd Demo Project + project: + name: "{{ demo_project_name_2 }}" + organization: "{{ org_name }}" + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + scm_credential: "{{ scm_cred_name }}" + state: absent + register: result + - assert: that: - "result is changed"