2019-01-18 14:08:04 +03:00
#!/usr/bin/python
# coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import , division , print_function
__metaclass__ = type
ANSIBLE_METADATA = { ' metadata_version ' : ' 1.1 ' ,
' status ' : [ ' preview ' ] ,
' supported_by ' : ' community ' }
DOCUMENTATION = '''
- - -
module : tower_workflow_launch
author : " John Westcott IV (@john-westcott-iv) "
version_added : " 2.8 "
short_description : Run a workflow in Ansible Tower
description :
- Launch an Ansible Tower workflows . See
U ( https : / / www . ansible . com / tower ) for an overview .
options :
2020-04-01 20:15:04 +03:00
name :
2019-01-18 14:08:04 +03:00
description :
- The name of the workflow template to run .
required : True
2019-09-30 23:01:44 +03:00
type : str
2020-04-01 20:15:04 +03:00
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 :
2020-04-09 19:40:13 +03:00
- Inventory to use for the job ran with this workflow , only used if prompt for inventory is set .
2020-04-01 20:15:04 +03:00
type : str
limit :
description :
- Limit to use for the I ( job_template ) .
type : str
scm_branch :
description :
2020-04-09 19:40:13 +03:00
- A specific branch of the SCM project to run the template on .
2020-04-01 20:15:04 +03:00
- This is only applicable if your project allows for branch override .
type : str
version_added : " 3.7 "
2019-01-18 14:08:04 +03:00
extra_vars :
description :
- Any extra vars required to launch the job .
2020-04-09 19:40:13 +03:00
type : dict
2019-01-18 14:08:04 +03:00
wait :
description :
- Wait for the workflow to complete .
default : True
type : bool
2020-04-01 20:15:04 +03:00
interval :
description :
- The interval to request an update from Tower .
required : False
default : 1
type : float
2019-01-18 14:08:04 +03:00
timeout :
description :
- If waiting for the workflow to complete this will abort after this
2019-09-12 17:53:05 +03:00
amount of seconds
2019-09-30 23:01:44 +03:00
type : int
2020-04-08 00:22:50 +03:00
tower_oauthtoken :
description :
- The Tower OAuth token to use .
required : False
type : str
version_added : " 3.7 "
2019-09-18 15:43:36 +03:00
extends_documentation_fragment : awx . awx . auth
2019-01-18 14:08:04 +03:00
'''
RETURN = '''
job_info :
2019-03-06 14:18:43 +03:00
description : dictionary containing information about the workflow executed
2019-01-18 14:08:04 +03:00
returned : If workflow launched
type : dict
'''
EXAMPLES = '''
2020-04-09 19:40:13 +03:00
- name : Launch a workflow with a timeout of 10 seconds
2019-01-18 14:08:04 +03:00
tower_workflow_launch :
2020-04-09 19:40:13 +03:00
workflow_template : " Test Workflow "
timeout : 10
2019-01-18 14:08:04 +03:00
2020-04-09 19:40:13 +03:00
- name : Launch a Workflow with extra_vars without waiting
2019-01-18 14:08:04 +03:00
tower_workflow_launch :
2020-04-09 19:40:13 +03:00
workflow_template : " Test workflow "
extra_vars :
var1 : My First Variable
var2 : My Second Variable
2019-01-18 14:08:04 +03:00
wait : False
'''
2020-04-01 20:15:04 +03:00
from . . module_utils . tower_api import TowerModule
2020-04-09 19:40:13 +03:00
import json
2020-04-01 20:15:04 +03:00
import time
2019-01-18 14:08:04 +03:00
def main ( ) :
2020-04-01 20:15:04 +03:00
# Any additional arguments that are not fields of the item can be added here
2019-01-18 14:08:04 +03:00
argument_spec = dict (
2020-04-01 20:15:04 +03:00
name = dict ( required = True , aliases = [ ' workflow_template ' ] ) ,
organization = dict ( ) ,
inventory = dict ( ) ,
limit = dict ( ) ,
2020-04-08 00:22:50 +03:00
scm_branch = dict ( ) ,
2020-04-09 19:40:13 +03:00
extra_vars = dict ( type = ' dict ' ) ,
2020-04-01 20:15:04 +03:00
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 ' ) ,
2019-01-18 14:08:04 +03:00
)
2020-04-01 20:15:04 +03:00
# Create a module for ourselves
2020-04-15 16:37:54 +03:00
module = TowerModule ( argument_spec = argument_spec )
2019-01-18 14:08:04 +03:00
2020-04-01 20:15:04 +03:00
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 ' )
2019-01-18 14:08:04 +03:00
wait = module . params . get ( ' wait ' )
2020-04-01 20:15:04 +03:00
interval = module . params . get ( ' interval ' )
2019-01-18 14:08:04 +03:00
timeout = module . params . get ( ' timeout ' )
2020-04-09 19:40:13 +03:00
# 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 )
2020-04-01 20:15:04 +03:00
# 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 ]
# 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 )
# Attempt to look up job_template based on the provided name
2020-04-08 00:22:50 +03:00
lookup_data = { ' name ' : name }
2020-04-01 20:15:04 +03:00
if organization :
lookup_data [ ' organization ' ] = module . resolve_name_to_id ( ' organizations ' , organization )
2020-04-09 19:40:13 +03:00
workflow_job_template = module . get_one ( ' workflow_job_templates ' , data = lookup_data )
2020-04-01 20:15:04 +03:00
if workflow_job_template is None :
module . fail_json ( msg = " Unable to find workflow job template " )
# 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 ' ,
}
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 :
2020-04-09 19:40:13 +03:00
module . fail_json ( msg = " Parameters specified which can not be passed into wotkflow job template, see errors for details " , errors = param_errors )
2020-04-01 20:15:04 +03:00
# Launch the job
2020-04-09 19:40:13 +03:00
result = module . post_endpoint ( workflow_job_template [ ' related ' ] [ ' launch ' ] , data = post_data )
2020-04-01 20:15:04 +03:00
if result [ ' status_code ' ] != 201 :
2020-04-09 19:40:13 +03:00
module . fail_json ( msg = " Failed to launch workflow, see response for details " , response = result )
2020-04-01 20:15:04 +03:00
module . json_output [ ' changed ' ] = True
module . json_output [ ' id ' ] = result [ ' json ' ] [ ' id ' ]
module . json_output [ ' status ' ] = result [ ' json ' ] [ ' status ' ]
# This is for backwards compatability
2020-04-08 00:22:50 +03:00
module . json_output [ ' job_info ' ] = { ' id ' : result [ ' json ' ] [ ' id ' ] }
2020-04-01 20:15:04 +03:00
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 ' ]
2020-04-09 19:40:13 +03:00
# If the job has failed, we want to raise a task failure for that so we get a non-zero response.
2020-04-01 20:15:04 +03:00
if result [ ' json ' ] [ ' failed ' ] :
2020-04-08 00:22:50 +03:00
module . json_output [ ' msg ' ] = ' The workflow " {0} " failed ' . format ( name )
2020-04-01 20:15:04 +03:00
module . fail_json ( * * module . json_output )
module . exit_json ( * * module . json_output )
2019-01-18 14:08:04 +03:00
if __name__ == ' __main__ ' :
main ( )