Merge branch 'fix-awx_collection-docs' of github.com:sean-m-sullivan/awx into fix-awx_collection-docs

This commit is contained in:
sean-m-sullivan
2021-02-10 15:45:38 -06:00
176 changed files with 6352 additions and 3269 deletions

View File

@@ -37,6 +37,12 @@ options:
description:
- Inventory to use for the job, only used if prompt for inventory is set.
type: str
organization:
description:
- Organization the 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.
type: str
credentials:
description:
- Credential to use for job, only used if prompt for credential is set.
@@ -149,6 +155,7 @@ def main():
name=dict(required=True, aliases=['job_template']),
job_type=dict(choices=['run', 'check']),
inventory=dict(default=None),
organization=dict(),
# Credentials will be a str instead of a list for backwards compatability
credentials=dict(type='list', default=None, aliases=['credential'], elements='str'),
limit=dict(),
@@ -172,6 +179,7 @@ def main():
name = module.params.get('name')
optional_args['job_type'] = module.params.get('job_type')
inventory = module.params.get('inventory')
organization = module.params.get('organization')
credentials = module.params.get('credentials')
optional_args['limit'] = module.params.get('limit')
optional_args['tags'] = module.params.get('tags')
@@ -201,7 +209,10 @@ def main():
post_data['credentials'].append(module.resolve_name_to_id('credentials', credential))
# Attempt to look up job_template based on the provided name
job_template = module.get_one('job_templates', name_or_id=name)
lookup_data = {}
if organization:
lookup_data['organization'] = module.resolve_name_to_id('organizations', organization)
job_template = module.get_one('job_templates', name_or_id=name, data=lookup_data)
if job_template is None:
module.fail_json(msg="Unable to find job template by name {0}".format(name))
@@ -211,7 +222,6 @@ def main():
check_vars_to_prompts = {
'scm_branch': 'ask_scm_branch_on_launch',
'diff_mode': 'ask_diff_mode_on_launch',
'extra_vars': 'ask_variables_on_launch',
'limit': 'ask_limit_on_launch',
'tags': 'ask_tags_on_launch',
'skip_tags': 'ask_skip_tags_on_launch',
@@ -225,6 +235,9 @@ def main():
for variable_name in check_vars_to_prompts:
if module.params.get(variable_name) and not job_template[check_vars_to_prompts[variable_name]]:
param_errors.append("The field {0} was specified but the job template does not allow for it to be overridden".format(variable_name))
# Check if Either ask_variables_on_launch, or survey_enabled is enabled for use of extra vars.
if module.params.get('extra_vars') and not (job_template['ask_variables_on_launch'] or job_template['survey_enabled']):
param_errors.append("The field extra_vars was specified but the job template does not allow for it to be overridden")
if len(param_errors) > 0:
module.fail_json(msg="Parameters specified which can not be passed into job template, see errors for details", **{'errors': param_errors})

View File

@@ -91,6 +91,8 @@ options:
timeout:
description:
- The amount of time (in seconds) to run before the SCM Update is canceled. A value of 0 means no timeout.
- If waiting for the project to update this will abort after this
amount of seconds
default: 0
type: int
aliases:
@@ -133,6 +135,19 @@ options:
- list of notifications to send on error
type: list
elements: str
update_project:
description:
- Force project to update after changes.
- Used in conjunction with wait, interval, and timeout.
default: False
type: bool
interval:
description:
- The interval to request an update from Tower.
- Requires wait.
required: False
default: 1
type: float
extends_documentation_fragment: awx.awx.auth
'''
@@ -164,7 +179,13 @@ from ..module_utils.tower_api import TowerAPIModule
def wait_for_project_update(module, last_request):
# The current running job for the udpate is in last_request['summary_fields']['current_update']['id']
# The current running job for the update is in last_request['summary_fields']['current_update']['id']
# Get parameters that were not passed in
update_project = module.params.get('update_project')
wait = module.params.get('wait')
timeout = module.params.get('timeout')
interval = module.params.get('interval')
if 'current_update' in last_request['summary_fields']:
running = True
@@ -177,6 +198,25 @@ def wait_for_project_update(module, last_request):
if result['status'] != 'successful':
module.fail_json(msg="Project update failed")
elif update_project:
result = module.post_endpoint(last_request['related']['update'])
if result['status_code'] != 202:
module.fail_json(msg="Failed to update project, see response for details", response=result)
if not wait:
module.exit_json(**module.json_output)
# Grab our start time to compare against for the timeout
start = time.time()
# Invoke wait function
module.wait_on_url(
url=result['json']['url'],
object_name=module.get_item_name(last_request),
object_type='Project Update',
timeout=timeout, interval=interval
)
module.exit_json(**module.json_output)
@@ -205,6 +245,8 @@ def main():
notification_templates_error=dict(type="list", elements='str'),
state=dict(choices=['present', 'absent'], default='present'),
wait=dict(type='bool', default=True),
update_project=dict(default=False, type='bool'),
interval=dict(default=1.0, type='float'),
)
# Create a module for ourselves
@@ -231,6 +273,8 @@ def main():
organization = module.params.get('organization')
state = module.params.get('state')
wait = module.params.get('wait')
update_project = module.params.get('update_project')
interval = module.params.get('interval')
# Attempt to look up the related items the user specified (these will fail the module if not found)
lookup_data = {}
@@ -300,7 +344,7 @@ def main():
# If we are doing a not manual project, register our on_change method
# An on_change function, if registered, will fire after an post_endpoint or update_if_needed completes successfully
on_change = None
if wait and scm_type != '':
if wait and scm_type != '' or update_project and scm_type != '':
on_change = wait_for_project_update
# If the state was present and we can let the module build or update the existing project, this will return on its own

View File

@@ -126,9 +126,6 @@ def main():
# Grab our start time to compare against for the timeout
start = time.time()
if not wait:
module.exit_json(**module.json_output)
# Invoke wait function
module.wait_on_url(
url=result['json']['url'],

View File

@@ -152,15 +152,17 @@ def main():
'inventory': 'ask_inventory_on_launch',
'limit': 'ask_limit_on_launch',
'scm_branch': 'ask_scm_branch_on_launch',
'extra_vars': 'ask_variables_on_launch',
}
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))
# Check if Either ask_variables_on_launch, or survey_enabled is enabled for use of extra vars.
if module.params.get('extra_vars') and not (workflow_job_template['ask_variables_on_launch'] or workflow_job_template['survey_enabled']):
param_errors.append("The field extra_vars was specified but the workflow job template does not allow for it to be overridden")
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 workflow job template, see errors for details", errors=param_errors)
# Launch the job
result = module.post_endpoint(workflow_job_template['related']['launch'], data=post_data)

View File

@@ -37,7 +37,7 @@ ignore_parameters = [
# Add the module name as the key with the value being the list of params to ignore
no_api_parameter_ok = {
# The wait is for whether or not to wait for a project update on change
'tower_project': ['wait'],
'tower_project': ['wait', 'interval', 'update_project'],
# Existing_token and id are for working with an existing tokens
'tower_token': ['existing_token', 'existing_token_id'],
# /survey spec is now how we handle associations

View File

@@ -81,10 +81,11 @@ def test_resets_job_template_values(run_module, admin_user, project, inventory):
@pytest.mark.django_db
def test_job_launch_with_prompting(run_module, admin_user, project, inventory, machine_credential):
def test_job_launch_with_prompting(run_module, admin_user, project, organization, inventory, machine_credential):
JobTemplate.objects.create(
name='foo',
project=project,
organization=organization,
playbook='helloworld.yml',
ask_variables_on_launch=True,
ask_inventory_on_launch=True,

View File

@@ -136,5 +136,5 @@ def test_build_notification_message_undefined(run_module, admin_user, organizati
), admin_user)
nt = NotificationTemplate.objects.get(id=result['id'])
_, body = job.build_notification_message(nt, 'running')
assert '{"started_by": "My Placeholder"}' in body
body = job.build_notification_message(nt, 'running')
assert '{"started_by": "My Placeholder"}' in body[1]

View File

@@ -70,12 +70,84 @@
scm_type: git
scm_url: https://github.com/ansible/test-playbooks
- name: Create the job template with survey
tower_job_template:
name: "{{ jt_name2 }}"
project: "{{ proj_name }}"
playbook: debug.yml
job_type: run
state: present
inventory: "Demo Inventory"
survey_enabled: true
ask_variables_on_launch: false
survey_spec:
name: ''
description: ''
spec:
- question_name: Basic Name
question_description: Name
required: true
type: text
variable: basic_name
min: 0
max: 1024
default: ''
choices: ''
new_question: true
- question_name: Choose yes or no?
question_description: Choosing yes or no.
required: false
type: multiplechoice
variable: option_true_false
min:
max:
default: 'yes'
choices: |-
yes
no
new_question: true
- name: Kick off a job template with survey
tower_job_launch:
job_template: "{{ jt_name2 }}"
extra_vars:
basic_name: My First Variable
option_true_false: 'no'
ignore_errors: true
register: result
- assert:
that:
- result is not failed
- name: Prompt the job templates extra_vars on launch
tower_job_template:
name: "{{ jt_name2 }}"
state: present
ask_variables_on_launch: true
- name: Kick off a job template with extra_vars
tower_job_launch:
job_template: "{{ jt_name2 }}"
extra_vars:
basic_name: My First Variable
var1: My First Variable
var2: My Second Variable
ignore_errors: true
register: result
- assert:
that:
- result is not failed
- name: Create a Job Template for testing extra_vars
tower_job_template:
name: "{{ jt_name2 }}"
project: "{{ proj_name }}"
playbook: debug.yml
job_type: run
survey_enabled: false
state: present
inventory: "Demo Inventory"
extra_vars:
@@ -85,6 +157,7 @@
- name: Launch job template with inventory and credential for prompt on launch
tower_job_launch:
job_template: "{{ jt_name2 }}"
organization: Default
register: result
- assert:

View File

@@ -138,6 +138,29 @@
that:
- result is changed
- name: Update a git project, update the project and wait.
tower_project:
name: "{{ project_name3 }}"
organization: Default
scm_type: git
scm_branch: empty_branch
scm_url: https://github.com/ansible/test-playbooks
allow_override: true
wait: true
update_project: true
register: result
- name: Update a git project, update the project without waiting.
tower_project:
name: "{{ project_name3 }}"
organization: Default
scm_type: git
scm_branch: empty_branch
scm_url: https://github.com/ansible/test-playbooks
wait: false
update_project: true
register: result
- name: Create a job template that overrides the project scm_branch
tower_job_template:
name: "{{ jt1 }}"

View File

@@ -66,6 +66,66 @@
- result is not failed
- "'id' in result['job_info']"
- name: Kick off a workflow with extra_vars but not enabled
tower_workflow_launch:
workflow_template: "{{ wfjt_name1 }}"
extra_vars:
var1: My First Variable
var2: My Second Variable
ignore_errors: true
register: result
- assert:
that:
- result is failed
- "'The field extra_vars was specified but the workflow job template does not allow for it to be overridden' in result.errors"
- name: Prompt the workflow's with survey
tower_workflow_job_template:
name: "{{ wfjt_name1 }}"
state: present
survey_enabled: true
ask_variables_on_launch: false
survey:
name: ''
description: ''
spec:
- question_name: Basic Name
question_description: Name
required: true
type: text
variable: basic_name
min: 0
max: 1024
default: ''
choices: ''
new_question: true
- question_name: Choose yes or no?
question_description: Choosing yes or no.
required: false
type: multiplechoice
variable: option_true_false
min:
max:
default: 'yes'
choices: |-
yes
no
new_question: true
- name: Kick off a workflow with survey
tower_workflow_launch:
workflow_template: "{{ wfjt_name1 }}"
extra_vars:
basic_name: My First Variable
option_true_false: 'no'
ignore_errors: true
register: result
- assert:
that:
- result is not failed
- name: Prompt the workflow's extra_vars on launch
tower_workflow_job_template:
name: "{{ wfjt_name1 }}"
@@ -76,6 +136,7 @@
tower_workflow_launch:
workflow_template: "{{ wfjt_name1 }}"
extra_vars:
basic_name: My First Variable
var1: My First Variable
var2: My Second Variable
ignore_errors: true