mirror of
https://github.com/ansible/awx.git
synced 2026-05-09 10:27:37 -02:30
Adding EE/IG/labels/forks/timeout/job_slice_count to schedules
Modifying schedules to work with related fields Updating awx.awx.workflow_job_template_node
This commit is contained in:
committed by
Alan Rominger
parent
2e217ed466
commit
809df74050
@@ -42,17 +42,37 @@ options:
|
||||
- Optional description of this schedule.
|
||||
required: False
|
||||
type: str
|
||||
execution_environment:
|
||||
description:
|
||||
- Execution Environment applied as a prompt, assuming jot template prompts for execution environment
|
||||
type: str
|
||||
extra_data:
|
||||
description:
|
||||
- Specify C(extra_vars) for the template.
|
||||
required: False
|
||||
type: dict
|
||||
default: {}
|
||||
forks:
|
||||
description:
|
||||
- Forks applied as a prompt, assuming job template prompts for forks
|
||||
type: int
|
||||
instance_groups:
|
||||
description:
|
||||
- List of Instance Groups applied as a prompt, assuming job template prompts for instance groups
|
||||
type: list
|
||||
elements: str
|
||||
inventory:
|
||||
description:
|
||||
- Inventory applied as a prompt, assuming job template prompts for inventory
|
||||
required: False
|
||||
type: str
|
||||
job_slice_count:
|
||||
description:
|
||||
- Job Slice Count applied as a prompt, assuming job template prompts for job slice count
|
||||
type: int
|
||||
labels:
|
||||
description:
|
||||
- List of labels applied as a prompt, assuming job template prompts for labels
|
||||
credentials:
|
||||
description:
|
||||
- List of credentials applied as a prompt, assuming job template prompts for credentials
|
||||
@@ -63,6 +83,10 @@ options:
|
||||
- Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true.
|
||||
required: False
|
||||
type: str
|
||||
timeout:
|
||||
description:
|
||||
- Timeout applied as a prompt, assuming job template prompts for timeout
|
||||
type: int
|
||||
job_type:
|
||||
description:
|
||||
- The job type to use for the job template.
|
||||
@@ -176,8 +200,14 @@ def main():
|
||||
name=dict(required=True),
|
||||
new_name=dict(),
|
||||
description=dict(),
|
||||
execution_environment=dict(type='str'),
|
||||
extra_data=dict(type='dict'),
|
||||
forks=dict(type='int'),
|
||||
instance_groups=dict(type='list', elements='str'),
|
||||
inventory=dict(),
|
||||
job_slice_count=dict(type='int'),
|
||||
labels=dict(type='list', elements='str'),
|
||||
timeout=dict(type='int'),
|
||||
credentials=dict(type='list', elements='str'),
|
||||
scm_branch=dict(),
|
||||
job_type=dict(choices=['run', 'check']),
|
||||
@@ -200,8 +230,14 @@ def main():
|
||||
name = module.params.get('name')
|
||||
new_name = module.params.get("new_name")
|
||||
description = module.params.get('description')
|
||||
execution_environment = module.params.get('execution_environment')
|
||||
extra_data = module.params.get('extra_data')
|
||||
forks = module.params.get('forks')
|
||||
instance_groups = module.params.get('instance_groups')
|
||||
inventory = module.params.get('inventory')
|
||||
job_slice_count = module.params.get('job_slice_count')
|
||||
labels = module.params.get('labels')
|
||||
timeout = module.params.get('timeout')
|
||||
credentials = module.params.get('credentials')
|
||||
scm_branch = module.params.get('scm_branch')
|
||||
job_type = module.params.get('job_type')
|
||||
@@ -238,6 +274,28 @@ def main():
|
||||
for item in credentials:
|
||||
association_fields['credentials'].append(module.resolve_name_to_id('credentials', item))
|
||||
|
||||
# We need to clear out the name from the search fields so we can use name_or_id in the following searches
|
||||
if 'name' in search_fields:
|
||||
del search_fields['name']
|
||||
|
||||
if labels is not None:
|
||||
association_fields['labels'] = []
|
||||
for item in labels:
|
||||
label_id = module.get_one('labels', name_or_id=item, **{'data': search_fields})
|
||||
if label_id is None:
|
||||
module.fail_json(msg='Could not find label entry with name {0}'.format(item))
|
||||
else:
|
||||
association_fields['labels'].append(label_id['id'])
|
||||
|
||||
if instance_groups is not None:
|
||||
association_fields['instance_groups'] = []
|
||||
for item in instance_groups:
|
||||
instance_group_id = module.get_one('instance_groups', name_or_id=item, **{'data': search_fields})
|
||||
if instance_group_id is None:
|
||||
module.fail_json(msg='Could not find instance_group entry with name {0}'.format(item))
|
||||
else:
|
||||
association_fields['instance_groups'].append(instance_group_id['id'])
|
||||
|
||||
# Create the data that gets sent for create and update
|
||||
new_fields = {}
|
||||
if rrule is not None:
|
||||
@@ -267,6 +325,22 @@ def main():
|
||||
new_fields['unified_job_template'] = unified_job_template_id
|
||||
if enabled is not None:
|
||||
new_fields['enabled'] = enabled
|
||||
if forks is not None:
|
||||
new_fields['forks'] = forks
|
||||
if job_slice_count is not None:
|
||||
new_fields['job_slice_count'] = job_slice_count
|
||||
if timeout is not None:
|
||||
new_fields['timeout'] = timeout
|
||||
|
||||
if execution_environment is not None:
|
||||
if execution_environment == '':
|
||||
new_fields['execution_environment'] = ''
|
||||
else:
|
||||
ee = module.get_one('execution_environments', name_or_id=execution_environment, **{'data': search_fields})
|
||||
if ee is None:
|
||||
module.fail_json(msg='could not find execution_environment entry with name {0}'.format(execution_environment))
|
||||
else:
|
||||
new_fields['execution_environment'] = ee['id']
|
||||
|
||||
if state == 'absent':
|
||||
# If the state was absent we can let the module delete it if needed, the module will handle exiting from this
|
||||
|
||||
@@ -152,6 +152,30 @@ options:
|
||||
- Uniqueness is not handled rigorously.
|
||||
type: list
|
||||
elements: str
|
||||
execution_environment:
|
||||
description:
|
||||
- Execution Environment applied as a prompt, assuming jot template prompts for execution environment
|
||||
type: str
|
||||
forks:
|
||||
description:
|
||||
- Forks applied as a prompt, assuming job template prompts for forks
|
||||
type: int
|
||||
instance_groups:
|
||||
description:
|
||||
- List of Instance Groups applied as a prompt, assuming job template prompts for instance groups
|
||||
type: list
|
||||
elements: str
|
||||
job_slice_count:
|
||||
description:
|
||||
- Job Slice Count applied as a prompt, assuming job template prompts for job slice count
|
||||
type: int
|
||||
labels:
|
||||
description:
|
||||
- List of labels applied as a prompt, assuming job template prompts for labels
|
||||
timeout:
|
||||
description:
|
||||
- Timeout applied as a prompt, assuming job template prompts for timeout
|
||||
type: int
|
||||
state:
|
||||
description:
|
||||
- Desired state of the resource.
|
||||
@@ -255,6 +279,12 @@ def main():
|
||||
always_nodes=dict(type='list', elements='str'),
|
||||
failure_nodes=dict(type='list', elements='str'),
|
||||
credentials=dict(type='list', elements='str'),
|
||||
execution_environment=dict(type='str'),
|
||||
forks=dict(type='int'),
|
||||
instance_groups=dict(type='list', elements='str'),
|
||||
job_slice_count=dict(type='int'),
|
||||
labels=dict(type='list', elements='str'),
|
||||
timeout=dict(type='int'),
|
||||
state=dict(choices=['present', 'absent'], default='present'),
|
||||
)
|
||||
mutually_exclusive = [("unified_job_template", "approval_node")]
|
||||
@@ -327,32 +357,44 @@ def main():
|
||||
'diff_mode',
|
||||
'verbosity',
|
||||
'all_parents_must_converge',
|
||||
'forks',
|
||||
'job_slice_count',
|
||||
'timeout',
|
||||
):
|
||||
field_val = module.params.get(field_name)
|
||||
if field_val:
|
||||
new_fields[field_name] = field_val
|
||||
|
||||
association_fields = {}
|
||||
for association in ('always_nodes', 'success_nodes', 'failure_nodes', 'credentials'):
|
||||
for association in ('always_nodes', 'success_nodes', 'failure_nodes', 'credentials', 'instance_groups', 'labels'):
|
||||
name_list = module.params.get(association)
|
||||
if name_list is None:
|
||||
continue
|
||||
id_list = []
|
||||
for sub_name in name_list:
|
||||
if association == 'credentials':
|
||||
endpoint = 'credentials'
|
||||
lookup_data = {'name': sub_name}
|
||||
if association in ['credentials', 'instance_groups', 'labels']:
|
||||
sub_obj = module.get_one(association, name_or_id=sub_name)
|
||||
else:
|
||||
endpoint = 'workflow_job_template_nodes'
|
||||
lookup_data = {'identifier': sub_name}
|
||||
if workflow_job_template_id:
|
||||
lookup_data['workflow_job_template'] = workflow_job_template_id
|
||||
sub_obj = module.get_one(endpoint, **{'data': lookup_data})
|
||||
sub_obj = module.get_one(endpoint, **{'data': lookup_data})
|
||||
if sub_obj is None:
|
||||
module.fail_json(msg='Could not find {0} entry with name {1}'.format(association, sub_name))
|
||||
id_list.append(sub_obj['id'])
|
||||
if id_list:
|
||||
association_fields[association] = id_list
|
||||
association_fields[association] = id_list
|
||||
|
||||
execution_environment = module.params.get('execution_environment')
|
||||
if execution_environment is not None:
|
||||
if execution_environment == '':
|
||||
new_fields['execution_environment'] = ''
|
||||
else:
|
||||
ee = module.get_one('execution_environments', name_or_id=execution_environment)
|
||||
if ee is None:
|
||||
module.fail_json(msg='could not find execution_environment entry with name {0}'.format(execution_environment))
|
||||
else:
|
||||
new_fields['execution_environment'] = ee['id']
|
||||
|
||||
# In the case of a new object, the utils need to know it is a node
|
||||
new_fields['type'] = 'workflow_job_template_node'
|
||||
|
||||
@@ -7,11 +7,17 @@
|
||||
set_fact:
|
||||
org_name: "AWX-Collection-tests-organization-org-{{ test_id }}"
|
||||
sched1: "AWX-Collection-tests-schedule-sched1-{{ test_id }}"
|
||||
sched2: "AWX-Collection-tests-schedule-sched2-{{ test_id }}"
|
||||
cred1: "AWX-Collection-tests-schedule-cred1-{{ 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 }}"
|
||||
ee1: "AWX-Collection-tests-schedule-ee1-{{ test_id }}"
|
||||
label1: "AWX-Collection-tests-schedule-l1-{{ test_id }}"
|
||||
label2: "AWX-Collection-tests-schedule-l2-{{ test_id }}"
|
||||
ig1: "AWX-Collection-tests-schedule-ig1-{{ test_id }}"
|
||||
ig2: "AWX-Collection-tests-schedule-ig2-{{ test_id }}"
|
||||
|
||||
- block:
|
||||
- name: Try to create without an rrule
|
||||
@@ -124,6 +130,12 @@
|
||||
ask_limit_on_launch: true
|
||||
ask_diff_mode_on_launch: true
|
||||
ask_verbosity_on_launch: true
|
||||
ask_execution_environment_on_launch: true
|
||||
ask_forks_on_launch: true
|
||||
ask_instance_groups_on_launch: true
|
||||
ask_job_slice_count_on_launch: true
|
||||
ask_labels_on_launch: true
|
||||
ask_timeout_on_launch: true
|
||||
job_type: run
|
||||
state: present
|
||||
register: result
|
||||
@@ -132,14 +144,33 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Create labels
|
||||
label:
|
||||
name: "{{ item }}"
|
||||
organization: "{{ org_name }}"
|
||||
loop:
|
||||
- "{{ label1 }}"
|
||||
- "{{ label2 }}"
|
||||
|
||||
- name: Create an execution environment
|
||||
execution_environment:
|
||||
name: "{{ ee1 }}"
|
||||
image: "junk"
|
||||
|
||||
- name: Create instance groups
|
||||
instance_group:
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
|
||||
- name: Create with options that the JT does support
|
||||
schedule:
|
||||
name: "{{ sched1 }}"
|
||||
name: "{{ sched2 }}"
|
||||
state: present
|
||||
unified_job_template: "{{ jt1 }}"
|
||||
rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1"
|
||||
description: "This hopefully will not work"
|
||||
description: "This hopefully will work"
|
||||
extra_data:
|
||||
some: var
|
||||
inventory: Demo Inventory
|
||||
@@ -153,6 +184,33 @@
|
||||
diff_mode: true
|
||||
verbosity: 4
|
||||
enabled: true
|
||||
execution_environment: "{{ ee1 }}"
|
||||
forks: 10
|
||||
instance_groups:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
job_slice_count: 10
|
||||
labels:
|
||||
- "{{ label1 }}"
|
||||
- "{{ label2 }}"
|
||||
timeout: 10
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Reset some options
|
||||
schedule:
|
||||
name: "{{ sched2 }}"
|
||||
state: present
|
||||
execution_environment: ""
|
||||
forks: 1
|
||||
instance_groups: []
|
||||
job_slice_count: 1
|
||||
labels: []
|
||||
timeout: 60
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
@@ -163,7 +221,7 @@
|
||||
- name: Disable a schedule
|
||||
schedule:
|
||||
name: "{{ sched1 }}"
|
||||
unified_job_template: "{{ jt1 }}"
|
||||
unified_job_template: "Demo Job Template"
|
||||
state: present
|
||||
enabled: "false"
|
||||
register: result
|
||||
@@ -213,42 +271,48 @@
|
||||
- result is changed
|
||||
|
||||
always:
|
||||
- name: Delete the schedule
|
||||
- name: Delete the schedules
|
||||
schedule:
|
||||
name: "{{ sched1 }}"
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "{{ sched1 }}"
|
||||
- "{{ sched2 }}"
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete the jt
|
||||
- name: Delete the jt1
|
||||
job_template:
|
||||
name: "{{ jt1 }}"
|
||||
project: "{{ proj1 }}"
|
||||
playbook: hello_world.yml
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete the jt
|
||||
- name: Delete the jt2
|
||||
job_template:
|
||||
name: "{{ jt2 }}"
|
||||
project: "{{ proj2 }}"
|
||||
playbook: hello_world.yml
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete the Project
|
||||
- name: Delete the Project2
|
||||
project:
|
||||
name: "{{ proj2 }}"
|
||||
organization: "{{ org_name }}"
|
||||
state: absent
|
||||
scm_type: git
|
||||
scm_url: https://github.com/ansible/ansible-tower-samples.git
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete the Project
|
||||
- name: Delete the Project1
|
||||
project:
|
||||
name: "{{ proj1 }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
scm_type: git
|
||||
scm_url: https://github.com/ansible/ansible-tower-samples.git
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete Credential1
|
||||
credential:
|
||||
@@ -256,9 +320,28 @@
|
||||
organization: Default
|
||||
credential_type: Red Hat Ansible Automation Platform
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
# Labels can not be deleted
|
||||
|
||||
- name: Delete an execution environment
|
||||
execution_environment:
|
||||
name: "{{ ee1 }}"
|
||||
image: "junk"
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete instance groups
|
||||
instance_group:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
ignore_errors: True
|
||||
|
||||
- name: "Remove the organization"
|
||||
organization:
|
||||
name: "{{ org_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
project_inv: "AWX-Collection-tests-inventory_source-inv-project-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
project_inv_source: "AWX-Collection-tests-inventory_source-inv-source-project-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
github_webhook_credential_name: "AWX-Collection-tests-credential-webhook-{{ test_id }}_github"
|
||||
ee1: "AWX-Collection-tests-workflow_job_template-ee1-{{ test_id }}"
|
||||
label1: "AWX-Collection-tests-workflow_job_template-l1-{{ test_id }}"
|
||||
label2: "AWX-Collection-tests-workflow_job_template-l2-{{ test_id }}"
|
||||
ig1: "AWX-Collection-tests-workflow_job_template-ig1-{{ test_id }}"
|
||||
ig2: "AWX-Collection-tests-workflow_job_template-ig2-{{ test_id }}"
|
||||
|
||||
- block:
|
||||
- name: "Create a new organization"
|
||||
@@ -181,6 +186,12 @@
|
||||
playbook: hello_world.yml
|
||||
job_type: run
|
||||
state: present
|
||||
ask_execution_environment_on_launch: true
|
||||
ask_forks_on_launch: true
|
||||
ask_instance_groups_on_launch: true
|
||||
ask_timeout_on_launch: true
|
||||
ask_job_slice_count_on_launch: true
|
||||
ask_labels_on_launch: true
|
||||
register: jt2_name_result
|
||||
|
||||
- assert:
|
||||
@@ -198,6 +209,12 @@
|
||||
state: present
|
||||
survey_enabled: true
|
||||
survey_spec: '{"spec": [{"index": 0, "question_name": "my question?", "default": "mydef", "variable": "myvar", "type": "text", "required": false}], "description": "test", "name": "test"}'
|
||||
ask_execution_environment_on_launch: true
|
||||
ask_forks_on_launch: true
|
||||
ask_instance_groups_on_launch: true
|
||||
ask_timeout_on_launch: true
|
||||
ask_job_slice_count_on_launch: true
|
||||
ask_labels_on_launch: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
@@ -255,6 +272,26 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Create labels
|
||||
label:
|
||||
name: "{{ item }}"
|
||||
organization: "{{ org_name }}"
|
||||
loop:
|
||||
- "{{ label1 }}"
|
||||
- "{{ label2 }}"
|
||||
|
||||
- name: Create an execution environment
|
||||
execution_environment:
|
||||
name: "{{ ee1 }}"
|
||||
image: "junk"
|
||||
|
||||
- name: Create instance groups
|
||||
instance_group:
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
|
||||
# Node actions do what the schema command used to do
|
||||
- name: Create leaf node
|
||||
workflow_job_template_node:
|
||||
@@ -262,6 +299,39 @@
|
||||
unified_job_template: "{{ jt2_name }}"
|
||||
lookup_organization: "{{ org_name }}"
|
||||
workflow: "{{ wfjt_name }}"
|
||||
execution_environment: "{{ ee1 }}"
|
||||
forks: 12
|
||||
instance_groups:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
job_slice_count: 2
|
||||
labels:
|
||||
- "{{ label1 }}"
|
||||
- "{{ label2 }}"
|
||||
timeout: 23
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "results is changed"
|
||||
|
||||
- name: Update prompts on leaf node
|
||||
workflow_job_template_node:
|
||||
identifier: leaf
|
||||
unified_job_template: "{{ jt2_name }}"
|
||||
lookup_organization: "{{ org_name }}"
|
||||
workflow: "{{ wfjt_name }}"
|
||||
execution_environment: ""
|
||||
forks: 1
|
||||
instance_groups: []
|
||||
job_slice_count: 1
|
||||
labels: []
|
||||
timeout: 10
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "results is changed"
|
||||
|
||||
- name: Create root node
|
||||
workflow_job_template_node:
|
||||
@@ -815,6 +885,24 @@
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
# Labels can not be deleted
|
||||
|
||||
- name: Delete an execution environment
|
||||
execution_environment:
|
||||
name: "{{ ee1 }}"
|
||||
image: "junk"
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
|
||||
- name: Delete instance groups
|
||||
instance_group:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "{{ ig1 }}"
|
||||
- "{{ ig2 }}"
|
||||
ignore_errors: True
|
||||
|
||||
- name: "Remove the organization"
|
||||
organization:
|
||||
name: "{{ org_name }}"
|
||||
|
||||
Reference in New Issue
Block a user