Skip to content
Open
2 changes: 2 additions & 0 deletions changelogs/fragments/102_module_at_add_chdir_option.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- at - add option ``chdir`` to permit to launch the ``at`` command from a specific directory (https://github.com/ansible-collections/ansible.posix/issues/13).
28 changes: 18 additions & 10 deletions plugins/modules/at.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
- All jobs are executed in the 'a' queue.
version_added: "1.0.0"
options:
chdir:
description:
- An optional location from where to run the command C(at).
- Useful for intance when running a playbook using ansible-pull with C(purge) option.
type: path
version_added: 1.3.0
command:
description:
- A command to be executed in the future.
Expand All @@ -38,7 +44,7 @@
description:
- The state dictates if the command or script file should be evaluated as present(added) or absent(deleted).
type: str
choices: [ absent, present ]
choices: [absent, present]
default: present
unique:
description:
Expand Down Expand Up @@ -78,32 +84,32 @@
from ansible.module_utils.basic import AnsibleModule


def add_job(module, result, at_cmd, count, units, command, script_file):
def add_job(module, result, at_cmd, count, units, command, script_file, chdir=None):
at_command = "%s -f %s now + %s %s" % (at_cmd, script_file, count, units)
rc, out, err = module.run_command(at_command, check_rc=True)
rc, out, err = module.run_command(at_command, cwd=chdir, check_rc=True)
if command:
os.unlink(script_file)
result['changed'] = True


def delete_job(module, result, at_cmd, command, script_file):
def delete_job(module, result, at_cmd, command, script_file, chdir=None):
for matching_job in get_matching_jobs(module, at_cmd, script_file):
at_command = "%s -r %s" % (at_cmd, matching_job)
rc, out, err = module.run_command(at_command, check_rc=True)
rc, out, err = module.run_command(at_command, cwd=chdir, check_rc=True)
result['changed'] = True
if command:
os.unlink(script_file)
module.exit_json(**result)


def get_matching_jobs(module, at_cmd, script_file):
def get_matching_jobs(module, at_cmd, script_file, chdir=None):
matching_jobs = []

atq_cmd = module.get_bin_path('atq', True)

# Get list of job numbers for the user.
atq_command = "%s" % atq_cmd
rc, out, err = module.run_command(atq_command, check_rc=True)
rc, out, err = module.run_command(atq_command, cwd=chdir, check_rc=True)
current_jobs = out.splitlines()
if len(current_jobs) == 0:
return matching_jobs
Expand All @@ -118,7 +124,7 @@ def get_matching_jobs(module, at_cmd, script_file):
split_current_job = current_job.split()
at_opt = '-c' if platform.system() != 'AIX' else '-lv'
at_command = "%s %s %s" % (at_cmd, at_opt, split_current_job[0])
rc, out, err = module.run_command(at_command, check_rc=True)
rc, out, err = module.run_command(at_command, cwd=chdir, check_rc=True)
if script_file_string in out:
matching_jobs.append(split_current_job[0])

Expand All @@ -139,6 +145,7 @@ def main():
module = AnsibleModule(
argument_spec=dict(
command=dict(type='str'),
chdir=dict(type='path'),
script_file=dict(type='str'),
count=dict(type='int'),
units=dict(type='str', choices=['minutes', 'hours', 'days', 'weeks']),
Expand All @@ -152,6 +159,7 @@ def main():

at_cmd = module.get_bin_path('at', True)

chdir = module.params['chdir']
command = module.params['command']
script_file = module.params['script_file']
count = module.params['count']
Expand All @@ -173,7 +181,7 @@ def main():

# if absent remove existing and return
if state == 'absent':
delete_job(module, result, at_cmd, command, script_file)
delete_job(module, result, at_cmd, command, script_file, chdir=chdir)

# if unique if existing return unchanged
if unique:
Expand All @@ -186,7 +194,7 @@ def main():
result['count'] = count
result['units'] = units

add_job(module, result, at_cmd, count, units, command, script_file)
add_job(module, result, at_cmd, count, units, command, script_file, chdir=chdir)

module.exit_json(**result)

Expand Down
1 change: 0 additions & 1 deletion tests/integration/targets/at/aliases
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
shippable/posix/group1
destructive
disabled # fixme package
123 changes: 96 additions & 27 deletions tests/integration/targets/at/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.


- set_fact: output_dir_test={{output_dir}}/at

- name: make sure our testing sub-directory does not exist
Expand All @@ -28,35 +29,103 @@
## at
##

- name: define distros to attempt installing at on
set_fact:
package_distros:
- RedHat
- CentOS
- ScientificLinux
- Fedora
- Ubuntu
- Debian
- openSUSE Leap

- name: ensure at is installed
package:
name: at
state: present
when: ansible_distribution in package_distros

- name: run the first example
at:
command: "ls -d / > /dev/null"
count: 20
units: minutes
register: at_test0
- debug: var=at_test0
- name: validate results
assert:
that:
- name: Run At tests
block:
- name: define distros to attempt installing at on
set_fact:
package_distros:
- RedHat
- CentOS
- ScientificLinux
- Fedora
- Ubuntu
- Debian
- openSUSE Leap

- name: ensure at is installed
package:
name: at
state: present
when: ansible_distribution in package_distros

- name: run the first example
at:
command: "ls -d / > /dev/null"
count: 20
units: minutes
register: at_test0

- debug: var=at_test0

- name: validate results
assert:
that:
- 'at_test0.changed is defined'
- 'at_test0.count is defined'
- 'at_test0.script_file is defined'
- 'at_test0.state is defined'
- 'at_test0.units is defined'

- name: Add a useless command using at
at:
command: /bin/logger 'AT task ran from Ansible'
count: 1
units: minutes
unique: yes
register: at_add

- debug: var=at_add

- name: Wait for at to run the previous command
pause:
minutes: 1

- name: Add a useless command
at:
command: /bin/logger 'AT task ran from Ansible'
count: 1
units: minutes
unique: true
state: absent
register: at_removal

- debug: var=at_removal

- name: Wait for at to run the previous command
pause:
minutes: 1

- name: Validate results
assert:
that:
- at_add is changed
- at_removal is changed

- name: Create an at command with chdir with valid value
at:
command: /bin/logger 'AT task ran from Ansible with chdir'
count: 1
units: minutes
chdir: /tmp
register: at_chdir_valid
- debug: var=at_chdir_valid

- name: Create an at command with chdir with invalid value
at:
command: /bin/logger 'AT task ran from Ansible with chdir'
count: 1
units: minutes
chdir: /invalid
register: at_chdir_invalid
ignore_errors: true

- debug: var=at_chdir_invalid

- name: Validate results
assert:
that:
- at_chdir_valid is changed
- at_chdir_invalid is changed
when:
- not (ansible_facts['distribution'] in ('Ubuntu','FreeBSD'))
- not (ansible_distribution == "CentOS" and ansible_distribution_version is version('6', '=='))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why CentOS 6 is disabled?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem here is that despite what the man page says, the version of at that ships with CentOS 6 does not seem to actually support the -r option. I'm not sure what OS X 10.11's problem is with ansible 2.10.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Akasurde @gravesm
I think that the -r option issue on CentOS6 will be fixed on #228