2017-03-02 17:34:23 +03:00
#!/usr/bin/python
2017-05-11 19:26:36 +03:00
# coding: utf-8 -*-
2017-03-02 17:34:23 +03:00
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
Remove wildcard imports
Made the following changes:
* Removed wildcard imports
* Replaced long form of GPL header with short form
* Removed get_exception usage
* Added from __future__ boilerplate
* Adjust division operator to // where necessary
For the following files:
* web_infrastructure modules
* system modules
* linode, lxc, lxd, atomic, cloudscale, dimensiondata, ovh, packet,
profitbricks, pubnub, smartos, softlayer, univention modules
* compat dirs (disabled as its used intentionally)
2017-07-28 08:55:24 +03:00
# 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
2017-03-02 17:34:23 +03:00
2017-08-16 06:16:38 +03:00
ANSIBLE_METADATA = { ' metadata_version ' : ' 1.1 ' ,
2017-03-14 19:07:22 +03:00
' status ' : [ ' preview ' ] ,
' supported_by ' : ' community ' }
2017-03-02 17:34:23 +03:00
DOCUMENTATION = '''
- - -
module : tower_job_wait
version_added : " 2.3 "
2017-03-09 19:20:25 +03:00
author : " Wayne Witzel III (@wwitzel3) "
2017-03-02 17:34:23 +03:00
short_description : Wait for Ansible Tower job to finish .
description :
- Wait for Ansible Tower job to finish and report success or failure . See
U ( https : / / www . ansible . com / tower ) for an overview .
options :
job_id :
description :
- ID of the job to monitor .
required : True
2019-09-30 23:01:44 +03:00
type : int
2020-03-26 16:17:18 +03:00
interval :
description :
- The interval in sections , to request an update from Tower .
2020-03-26 17:57:32 +03:00
- For backwards compatability if unset this will be set to the average of min and max intervals
2020-03-26 16:17:18 +03:00
required : False
default : 1
type : float
2017-03-02 17:34:23 +03:00
min_interval :
description :
- Minimum interval in seconds , to request an update from Tower .
2020-03-26 23:25:01 +03:00
- deprecated , use interval instead
2019-09-30 23:01:44 +03:00
type : float
2017-03-02 17:34:23 +03:00
max_interval :
description :
- Maximum interval in seconds , to request an update from Tower .
2020-03-26 23:25:01 +03:00
- deprecated , use interval instead
2019-09-30 23:01:44 +03:00
type : float
2017-03-02 17:34:23 +03:00
timeout :
description :
- Maximum time in seconds to wait for a job to finish .
2019-09-30 23:01:44 +03:00
type : int
2020-03-25 21:06:32 +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
2017-03-02 17:34:23 +03:00
'''
EXAMPLES = '''
- name : Launch a job
tower_job_launch :
job_template : " My Job Template "
register : job
2018-08-09 02:10:26 +03:00
2017-03-02 17:34:23 +03:00
- name : Wait for job max 120 s
tower_job_wait :
2019-04-15 23:18:11 +03:00
job_id : " {{ job.id }} "
2017-03-02 17:34:23 +03:00
timeout : 120
'''
RETURN = '''
id :
description : job id that is being waited on
returned : success
type : int
sample : 99
elapsed :
description : total time in seconds the job took to run
returned : success
type : float
sample : 10.879
started :
description : timestamp of when the job started running
returned : success
2018-12-19 00:25:30 +03:00
type : str
2017-04-26 17:56:13 +03:00
sample : " 2017-03-01T17:03:53.200234Z "
2017-03-02 17:34:23 +03:00
finished :
description : timestamp of when the job finished running
returned : success
2018-12-19 00:25:30 +03:00
type : str
2017-04-26 17:56:13 +03:00
sample : " 2017-03-01T17:04:04.078782Z "
2017-03-02 17:34:23 +03:00
status :
description : current status of job
returned : success
2018-12-19 00:25:30 +03:00
type : str
2017-03-02 17:34:23 +03:00
sample : successful
'''
2020-03-25 21:06:32 +03:00
from . . module_utils . tower_api import TowerModule
import time
2017-03-02 17:34:23 +03:00
2020-03-25 21:06:32 +03:00
def check_job ( module , job_url ) :
response = module . get_endpoint ( job_url )
if response [ ' status_code ' ] != 200 :
module . fail_json ( msg = " Unable to read job from Tower {0} : {1} " . format ( response [ ' status_code ' ] , module . extract_errors_from_response ( response ) ) )
# Since we were successful, extract the fields we want to return
for k in ( ' id ' , ' status ' , ' elapsed ' , ' started ' , ' finished ' ) :
module . json_output [ k ] = response [ ' json ' ] . get ( k )
2017-03-02 17:34:23 +03:00
2020-03-25 21:06:32 +03:00
# And finally return the payload
return response [ ' json ' ]
2017-03-02 17:34:23 +03:00
def main ( ) :
2020-03-25 21:06:32 +03:00
# Any additional arguments that are not fields of the item can be added here
2018-08-02 18:17:39 +03:00
argument_spec = dict (
2017-05-11 19:26:36 +03:00
job_id = dict ( type = ' int ' , required = True ) ,
timeout = dict ( type = ' int ' ) ,
2020-03-26 16:17:18 +03:00
min_interval = dict ( type = ' float ' ) ,
max_interval = dict ( type = ' float ' ) ,
interval = dict ( type = ' float ' , default = 1 ) ,
2018-08-02 18:17:39 +03:00
)
2017-03-02 17:34:23 +03:00
2020-03-25 21:06:32 +03:00
# Create a module for ourselves
module = TowerModule ( argument_spec = argument_spec , supports_check_mode = True )
# Extract our parameters
job_id = module . params . get ( ' job_id ' )
timeout = module . params . get ( ' timeout ' )
min_interval = module . params . get ( ' min_interval ' )
max_interval = module . params . get ( ' max_interval ' )
2020-03-26 16:17:18 +03:00
interval = module . params . get ( ' interval ' )
if min_interval is not None or max_interval is not None :
2020-03-26 17:57:32 +03:00
# We can't tell if we got the default or if someone actually set this to 1.
# For now if we find 1 and had a min or max then we will do the average logic.
if interval == 1 :
2020-03-27 20:26:27 +03:00
if not min_interval :
min_interval = 1
if not max_interval :
max_interval = 30
interval = abs ( ( min_interval + max_interval ) / 2 )
2020-03-26 16:17:18 +03:00
module . deprecate (
2020-03-26 23:25:01 +03:00
msg = " Min and max interval have been deprecated, please use interval instead; interval will be set to {0} " . format ( interval ) ,
2020-03-26 16:17:18 +03:00
version = " 3.7 "
)
2020-03-25 21:06:32 +03:00
# Attempt to look up job based on the provided id
job = module . get_one ( ' jobs ' , * * {
' data ' : {
' id ' : job_id ,
}
} )
if job is None :
2020-03-26 17:57:32 +03:00
module . fail_json ( msg = ' Unable to wait on job {0} ; that ID does not exist in Tower. ' . format ( job_id ) )
2020-03-25 21:06:32 +03:00
job_url = job [ ' url ' ]
2020-03-26 16:17:18 +03:00
# Grab our start time to compare against for the timeout
2020-03-25 21:06:32 +03:00
start = time . time ( )
2020-03-26 16:17:18 +03:00
# Get the initial job status from Tower, this will exit if there are any issues with the HTTP call
2020-03-25 21:06:32 +03:00
result = check_job ( module , job_url )
2020-03-25 21:48:09 +03:00
# Loop while the job is not yet completed
2020-03-25 21:06:32 +03:00
while not result [ ' finished ' ] :
2020-03-26 16:17:18 +03:00
# If we are past our time out fail with a message
2020-03-27 22:44:23 +03:00
if timeout and timeout < time . time ( ) - start :
2020-03-25 21:06:32 +03:00
module . json_output [ ' msg ' ] = " Monitoring aborted due to timeout "
module . fail_json ( * * module . json_output )
2020-03-26 16:17:18 +03:00
# Put the process to sleep for our interval
time . sleep ( interval )
# Check the job again
result = check_job ( module , job_url )
2020-03-25 21:06:32 +03:00
# If the job has failed, we want to raise an Exception for that so we get a non-zero response.
if result [ ' failed ' ] :
module . json_output [ ' msg ' ] = ' Job with id {0} failed ' . format ( job_id )
module . fail_json ( * * module . json_output )
module . exit_json ( * * module . json_output )
2017-03-02 17:34:23 +03:00
if __name__ == ' __main__ ' :
main ( )