From a94e1e54775ced7c64a36833cf75b323e824dffe Mon Sep 17 00:00:00 2001 From: Richard C Isaacson Date: Wed, 15 Jan 2014 21:24:55 -0600 Subject: [PATCH 1/4] Refactored a few things to be more inline with the Ansible way. Passing testing. --- system/at | 162 ++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 85 deletions(-) diff --git a/system/at b/system/at index ffac9d1d535..274aa1dd77d 100644 --- a/system/at +++ b/system/at @@ -25,13 +25,8 @@ short_description: Schedule the execution of a command or scripts via the at com description: - Use this module to schedule a command or script to run once in the future. - All jobs are executed in the a queue. -version_added: "0.0" +version_added: "1.5" options: - user: - description: - - The user to execute the at command as. - required: false - default: null command: description: - A command to be executed in the future. @@ -42,22 +37,26 @@ options: - An existing script to be executed in the future. required: false default: null - unit_count: + count: description: - The count of units in the future to execute the command or script. required: true - unit_type: + units: description: - The type of units in the future to execute the command or script. required: true choices: ["minutes", "hours", "days", "weeks"] - action: + state: description: - - The action to take for the job defaulting to add. Unique will verify that there is only one entry in the queue. - - Delete will remove all existing queued jobs. - required: true - choices: ["add", "delete", "unique"] - default: add + - The state dictates if the command or script_file should be evaluated as present(added) or absent(deleted). + required: false + choices: ["present", "absent"] + default: "present" + unique: + description: + - If a matching job is present a new job will not be added. + required: false + default: false requirements: - at author: Richard Isaacson @@ -65,33 +64,41 @@ author: Richard Isaacson EXAMPLES = ''' # Schedule a command to execute in 20 minutes as root. -- at: command="ls -d / > /dev/null" unit_count=20 unit_type="minutes" - -# Schedule a script to execute in 1 hour as the neo user. -- at: script_file="/some/script.sh" user="neo" unit_count=1 unit_type="hours" +- at: command="ls -d / > /dev/null" count=20 units="minutes" # Match a command to an existing job and delete the job. -- at: command="ls -d / > /dev/null" action="delete" +- at: command="ls -d / > /dev/null" state="absent" # Schedule a command to execute in 20 minutes making sure it is unique in the queue. -- at: command="ls -d / > /dev/null" action="unique" unit_count=20 unit_type="minutes" +- at: command="ls -d / > /dev/null" unique=true count=20 units="minutes" ''' import os import tempfile +def add_job(module, result, at_cmd, count, units, command, script_file): + at_command = "%s now + %s %s -f %s" % (at_cmd, count, units, script_file) + rc, out, err = module.run_command(at_command, check_rc=True) + if command: + os.unlink(script_file) + result['changed'] = True -def matching_jobs(module, at_cmd, script_file, user=None): +def delete_job(module, result, at_cmd, command, script_file): + for matching_job in matching_jobs(module, at_cmd, script_file): + at_command = "%s -d %s" % (at_cmd, matching_job) + rc, out, err = module.run_command(at_command, check_rc=True) + result['changed'] = True + if command: + os.unlink(script_file) + module.exit_json(**result) + +def matching_jobs(module, at_cmd, script_file): matching_jobs = [] atq_cmd = module.get_bin_path('atq', True) # Get list of job numbers for the user. atq_command = "%s" % (atq_cmd) - if user: - atq_command = "su '%s' -c '%s'" % (user, atq_command) - rc, out, err = module.run_command(atq_command) - if rc != 0: - module.fail_json(msg=err) + rc, out, err = module.run_command(atq_command, check_rc=True) current_jobs = out.splitlines() if len(current_jobs) == 0: return matching_jobs @@ -104,100 +111,85 @@ def matching_jobs(module, at_cmd, script_file, user=None): for current_job in current_jobs: split_current_job = current_job.split() at_command = "%s -c %s" % (at_cmd, split_current_job[0]) - if user: - at_command = "su '%s' -c '%s'" % (user, at_command) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) + rc, out, err = module.run_command(at_command, check_rc=True) if script_file_string in out: matching_jobs.append(split_current_job[0]) # Return the list. return matching_jobs +def create_tempfile(command): + filed, script_file = tempfile.mkstemp(prefix='at') + fileh = os.fdopen(filed, 'w') + fileh.write(command) + fileh.close() + return script_file + #================================================ def main(): module = AnsibleModule( argument_spec = dict( - user=dict(required=False), - command=dict(required=False), - script_file=dict(required=False), - unit_count=dict(required=False, + command=dict(required=False, + type='str'), + script_file=dict(required=False, + type='str'), + count=dict(required=False, type='int'), - unit_type=dict(required=False, + units=dict(required=False, default=None, - choices=["minutes", "hours", "days", "weeks"], - type="str"), - action=dict(required=False, - default="add", - choices=["add", "delete", "unique"], - type="str") + choices=['minutes', 'hours', 'days', 'weeks'], + type='str'), + state=dict(required=False, + default='present', + choices=['present', 'absent'], + type='str'), + unique=dict(required=False, + default=False, + type='bool') ), - supports_check_mode = False, + mutually_exclusive = [['command', 'script_file']], + required_one_of = [['command', 'script_file']], + supports_check_mode = False ) at_cmd = module.get_bin_path('at', True) - user = module.params['user'] command = module.params['command'] script_file = module.params['script_file'] - unit_count = module.params['unit_count'] - unit_type = module.params['unit_type'] - action = module.params['action'] + count = module.params['count'] + units = module.params['units'] + state = module.params['state'] + unique = module.params['unique'] - if ((action == 'add') and (not unit_count or not unit_type)): - module.fail_json(msg="add action requires unit_count and unit_type") - - if (not command) and (not script_file): - module.fail_json(msg="command or script_file not specified") - - if command and script_file: - module.fail_json(msg="command and script_file are mutually exclusive") + if ((state == 'present') and (not count or not units)): + module.fail_json(msg="present state requires count and units") result = {} - result['action'] = action + result['state'] = state result['changed'] = False # If command transform it into a script_file if command: - filed, script_file = tempfile.mkstemp(prefix='at') - fileh = os.fdopen(filed, 'w') - fileh.write(command) - fileh.close() + script_file = create_tempfile(command) - # if delete then return - if action == 'delete': - for matching_job in matching_jobs(module, at_cmd, script_file, user): - at_command = "%s -d %s" % (at_cmd, matching_job) - if user: - at_command = "su '%s' -c '%s'" % (user, at_ccommand) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) - result['changed'] = True - module.exit_json(**result) + # if absent remove existing and return + if state == 'absent': + delete_job(module, result, at_cmd, command, script_file) # if unique if existing return unchanged - if action == 'unique': - if len(matching_jobs(module, at_cmd, script_file, user)) != 0: + if unique: + if len(matching_jobs(module, at_cmd, script_file)) != 0: + if command: + os.unlink(script_file) module.exit_json(**result) result['script_file'] = script_file - result['unit_count'] = unit_count - result['unit_type'] = unit_type + result['count'] = count + result['units'] = units - at_command = "%s now + %s %s -f %s" % (at_cmd, unit_count, unit_type, script_file) - if user: - # We expect that if this is an installed the permissions are already correct for the user to execute it. - at_command = "su '%s' -c '%s'" % (user, at_command) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) - if command: - os.unlink(script_file) - result['changed'] = True + add_job(module, result, at_cmd, count, units, command, script_file) module.exit_json(**result) From bdfb2de7fc83c2cabb88d75065f231e85cd46cfe Mon Sep 17 00:00:00 2001 From: Richard C Isaacson Date: Wed, 15 Jan 2014 21:28:13 -0600 Subject: [PATCH 2/4] Documentation cleanup. --- system/at | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/system/at b/system/at index 274aa1dd77d..917aa062f87 100644 --- a/system/at +++ b/system/at @@ -21,10 +21,10 @@ DOCUMENTATION = ''' --- module: at -short_description: Schedule the execution of a command or scripts via the at command. +short_description: Schedule the execution of a command or script file via the at command. description: - - Use this module to schedule a command or script to run once in the future. - - All jobs are executed in the a queue. + - Use this module to schedule a command or script file to run once in the future. + - All jobs are executed in the 'a' queue. version_added: "1.5" options: command: @@ -34,21 +34,21 @@ options: default: null script_file: description: - - An existing script to be executed in the future. + - An existing script file to be executed in the future. required: false default: null count: description: - - The count of units in the future to execute the command or script. + - The count of units in the future to execute the command or script file. required: true units: description: - - The type of units in the future to execute the command or script. + - The type of units in the future to execute the command or script file. required: true choices: ["minutes", "hours", "days", "weeks"] state: description: - - The state dictates if the command or script_file should be evaluated as present(added) or absent(deleted). + - The state dictates if the command or script file should be evaluated as present(added) or absent(deleted). required: false choices: ["present", "absent"] default: "present" From ce98edfc873ad75edafcfdfc8f911d582731ea17 Mon Sep 17 00:00:00 2001 From: Richard C Isaacson Date: Sun, 19 Jan 2014 20:51:39 -0600 Subject: [PATCH 3/4] Cleaning up pep8 alerts. --- system/at | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/system/at b/system/at index 917aa062f87..36131286388 100644 --- a/system/at +++ b/system/at @@ -132,19 +132,19 @@ def main(): module = AnsibleModule( argument_spec = dict( command=dict(required=False, - type='str'), + type='str'), script_file=dict(required=False, - type='str'), + type='str'), count=dict(required=False, - type='int'), + type='int'), units=dict(required=False, - default=None, - choices=['minutes', 'hours', 'days', 'weeks'], - type='str'), + default=None, + choices=['minutes', 'hours', 'days', 'weeks'], + type='str'), state=dict(required=False, - default='present', - choices=['present', 'absent'], - type='str'), + default='present', + choices=['present', 'absent'], + type='str'), unique=dict(required=False, default=False, type='bool') From 318842910514b441ed3f5d5d9f89a1d88615659f Mon Sep 17 00:00:00 2001 From: Richard C Isaacson Date: Mon, 10 Mar 2014 10:31:08 -0500 Subject: [PATCH 4/4] Some cleanup. --- system/at | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/system/at b/system/at index 36131286388..d1055abfc26 100644 --- a/system/at +++ b/system/at @@ -75,6 +75,8 @@ EXAMPLES = ''' import os import tempfile + + def add_job(module, result, at_cmd, count, units, command, script_file): at_command = "%s now + %s %s -f %s" % (at_cmd, count, units, script_file) rc, out, err = module.run_command(at_command, check_rc=True) @@ -82,8 +84,9 @@ def add_job(module, result, at_cmd, count, units, command, script_file): os.unlink(script_file) result['changed'] = True + def delete_job(module, result, at_cmd, command, script_file): - for matching_job in matching_jobs(module, at_cmd, script_file): + for matching_job in get_matching_jobs(module, at_cmd, script_file): at_command = "%s -d %s" % (at_cmd, matching_job) rc, out, err = module.run_command(at_command, check_rc=True) result['changed'] = True @@ -91,13 +94,14 @@ def delete_job(module, result, at_cmd, command, script_file): os.unlink(script_file) module.exit_json(**result) -def matching_jobs(module, at_cmd, script_file): + +def get_matching_jobs(module, at_cmd, script_file): matching_jobs = [] atq_cmd = module.get_bin_path('atq', True) # Get list of job numbers for the user. - atq_command = "%s" % (atq_cmd) + atq_command = "%s" % atq_cmd rc, out, err = module.run_command(atq_command, check_rc=True) current_jobs = out.splitlines() if len(current_jobs) == 0: @@ -118,6 +122,7 @@ def matching_jobs(module, at_cmd, script_file): # Return the list. return matching_jobs + def create_tempfile(command): filed, script_file = tempfile.mkstemp(prefix='at') fileh = os.fdopen(filed, 'w') @@ -125,7 +130,6 @@ def create_tempfile(command): fileh.close() return script_file -#================================================ def main(): @@ -149,9 +153,9 @@ def main(): default=False, type='bool') ), - mutually_exclusive = [['command', 'script_file']], - required_one_of = [['command', 'script_file']], - supports_check_mode = False + mutually_exclusive=[['command', 'script_file']], + required_one_of=[['command', 'script_file']], + supports_check_mode=False ) at_cmd = module.get_bin_path('at', True) @@ -163,12 +167,10 @@ def main(): state = module.params['state'] unique = module.params['unique'] - if ((state == 'present') and (not count or not units)): + if (state == 'present') and (not count or not units): module.fail_json(msg="present state requires count and units") - result = {} - result['state'] = state - result['changed'] = False + result = {'state': state, 'changed': False} # If command transform it into a script_file if command: @@ -180,7 +182,7 @@ def main(): # if unique if existing return unchanged if unique: - if len(matching_jobs(module, at_cmd, script_file)) != 0: + if len(get_matching_jobs(module, at_cmd, script_file)) != 0: if command: os.unlink(script_file) module.exit_json(**result)