mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-24 19:31:26 -07:00
Currently, when writing user's crontab, ansible calls crontab <file> -u <user> This is incorrect according to crontab(1) on both FreeBSD and Linux, which suggest that file argument should be the last. At least on FreeBSD, this leads to incorrect cron module bahavior which writes to root's crontab instead of users's
698 lines
23 KiB
Python
698 lines
23 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# (c) 2012, Dane Summers <dsummers@pinedesk.biz>
|
|
# (c) 2013, Mike Grozak <mike.grozak@gmail.com>
|
|
# (c) 2013, Patrick Callahan <pmc@patrickcallahan.com>
|
|
# (c) 2015, Evan Kaufman <evan@digitalflophouse.com>
|
|
# (c) 2015, Luca Berruti <nadirio@gmail.com>
|
|
#
|
|
# This file is part of Ansible
|
|
#
|
|
# Ansible is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Ansible is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# Cron Plugin: The goal of this plugin is to provide an indempotent method for
|
|
# setting up cron jobs on a host. The script will play well with other manually
|
|
# entered crons. Each cron job entered will be preceded with a comment
|
|
# describing the job so that it can be found later, which is required to be
|
|
# present in order for this plugin to find/modify the job.
|
|
#
|
|
# This module is based on python-crontab by Martin Owens.
|
|
#
|
|
|
|
DOCUMENTATION = """
|
|
---
|
|
module: cron
|
|
short_description: Manage cron.d and crontab entries.
|
|
description:
|
|
- Use this module to manage crontab and environment variables entries. This module allows
|
|
you to create environment variables and named crontab entries, update, or delete them.
|
|
- 'When crontab jobs are managed: the module includes one line with the description of the
|
|
crontab entry C("#Ansible: <name>") corresponding to the "name" passed to the module,
|
|
which is used by future ansible/module calls to find/check the state. The "name"
|
|
parameter should be unique, and changing the "name" value will result in a new cron
|
|
task being created (or a different one being removed).'
|
|
- 'When environment variables are managed: no comment line is added, but, when the module
|
|
needs to find/check the state, it uses the "name" parameter to find the environment
|
|
variable definition line.'
|
|
version_added: "0.9"
|
|
options:
|
|
name:
|
|
description:
|
|
- Description of a crontab entry or, if env is set, the name of environment variable.
|
|
Required if state=absent
|
|
default: null
|
|
required: false
|
|
user:
|
|
description:
|
|
- The specific user whose crontab should be modified.
|
|
required: false
|
|
default: root
|
|
job:
|
|
description:
|
|
- The command to execute or, if env is set, the value of environment variable.
|
|
Required if state=present.
|
|
required: false
|
|
aliases: ['value']
|
|
default: null
|
|
state:
|
|
description:
|
|
- Whether to ensure the job or environment variable is present or absent.
|
|
required: false
|
|
default: present
|
|
choices: [ "present", "absent" ]
|
|
cron_file:
|
|
description:
|
|
- If specified, uses this file instead of an individual user's crontab.
|
|
If this is a relative path, it is interpreted with respect to
|
|
/etc/cron.d. (If it is absolute, it will typically be /etc/crontab).
|
|
To use the C(cron_file) parameter you must specify the C(user) as well.
|
|
required: false
|
|
default: null
|
|
backup:
|
|
description:
|
|
- If set, create a backup of the crontab before it is modified.
|
|
The location of the backup is returned in the C(backup_file) variable by this module.
|
|
required: false
|
|
choices: [ "yes", "no" ]
|
|
default: no
|
|
minute:
|
|
description:
|
|
- Minute when the job should run ( 0-59, *, */2, etc )
|
|
required: false
|
|
default: "*"
|
|
hour:
|
|
description:
|
|
- Hour when the job should run ( 0-23, *, */2, etc )
|
|
required: false
|
|
default: "*"
|
|
day:
|
|
description:
|
|
- Day of the month the job should run ( 1-31, *, */2, etc )
|
|
required: false
|
|
default: "*"
|
|
aliases: [ "dom" ]
|
|
month:
|
|
description:
|
|
- Month of the year the job should run ( 1-12, *, */2, etc )
|
|
required: false
|
|
default: "*"
|
|
weekday:
|
|
description:
|
|
- Day of the week that the job should run ( 0-6 for Sunday-Saturday, *, etc )
|
|
required: false
|
|
default: "*"
|
|
aliases: [ "dow" ]
|
|
reboot:
|
|
description:
|
|
- If the job should be run at reboot. This option is deprecated. Users should use special_time.
|
|
version_added: "1.0"
|
|
required: false
|
|
default: "no"
|
|
choices: [ "yes", "no" ]
|
|
special_time:
|
|
description:
|
|
- Special time specification nickname.
|
|
version_added: "1.3"
|
|
required: false
|
|
default: null
|
|
choices: [ "reboot", "yearly", "annually", "monthly", "weekly", "daily", "hourly" ]
|
|
disabled:
|
|
description:
|
|
- If the job should be disabled (commented out) in the crontab. Only has effect if state=present
|
|
version_added: "1.9"
|
|
required: false
|
|
default: false
|
|
env:
|
|
description:
|
|
- If set, manages a crontab's environment variable. New variables are added on top of crontab.
|
|
"name" and "value" paramenters are the name and the value of environment variable.
|
|
version_added: "2"
|
|
required: false
|
|
default: "no"
|
|
choices: [ "yes", "no" ]
|
|
insertafter:
|
|
description:
|
|
- Used with C(state=present) and C(env). If specified, the environment variable will be
|
|
inserted after the declaration of specified environment variable.
|
|
version_added: "2"
|
|
required: false
|
|
default: null
|
|
insertbefore:
|
|
description:
|
|
- Used with C(state=present) and C(env). If specified, the environment variable will be
|
|
inserted before the declaration of specified environment variable.
|
|
version_added: "2"
|
|
required: false
|
|
default: null
|
|
requirements:
|
|
- cron
|
|
author:
|
|
- "Dane Summers (@dsummersl)"
|
|
- 'Mike Grozak'
|
|
- 'Patrick Callahan'
|
|
- 'Evan Kaufman (@EvanK)'
|
|
- 'Luca Berruti (@lberruti)'
|
|
"""
|
|
|
|
EXAMPLES = '''
|
|
# Ensure a job that runs at 2 and 5 exists.
|
|
# Creates an entry like "0 5,2 * * ls -alh > /dev/null"
|
|
- cron: name="check dirs" minute="0" hour="5,2" job="ls -alh > /dev/null"
|
|
|
|
# Ensure an old job is no longer present. Removes any job that is prefixed
|
|
# by "#Ansible: an old job" from the crontab
|
|
- cron: name="an old job" state=absent
|
|
|
|
# Creates an entry like "@reboot /some/job.sh"
|
|
- cron: name="a job for reboot" special_time=reboot job="/some/job.sh"
|
|
|
|
# Creates an entry like "PATH=/opt/bin" on top of crontab
|
|
- cron: name=PATH env=yes value=/opt/bin
|
|
|
|
# Creates an entry like "APP_HOME=/srv/app" and insert it after PATH
|
|
# declaration
|
|
- cron: name=APP_HOME env=yes value=/srv/app insertafter=PATH
|
|
|
|
# Creates a cron file under /etc/cron.d
|
|
- cron: name="yum autoupdate" weekday="2" minute=0 hour=12
|
|
user="root" job="YUMINTERACTIVE=0 /usr/sbin/yum-autoupdate"
|
|
cron_file=ansible_yum-autoupdate
|
|
|
|
# Removes a cron file from under /etc/cron.d
|
|
- cron: name="yum autoupdate" cron_file=ansible_yum-autoupdate state=absent
|
|
|
|
# Removes "APP_HOME" environment variable from crontab
|
|
- cron: name=APP_HOME env=yes state=absent
|
|
'''
|
|
|
|
import os
|
|
import re
|
|
import tempfile
|
|
import platform
|
|
import pipes
|
|
|
|
CRONCMD = "/usr/bin/crontab"
|
|
|
|
class CronTabError(Exception):
|
|
pass
|
|
|
|
class CronTab(object):
|
|
"""
|
|
CronTab object to write time based crontab file
|
|
|
|
user - the user of the crontab (defaults to root)
|
|
cron_file - a cron file under /etc/cron.d, or an absolute path
|
|
"""
|
|
def __init__(self, module, user=None, cron_file=None):
|
|
self.module = module
|
|
self.user = user
|
|
self.root = (os.getuid() == 0)
|
|
self.lines = None
|
|
self.ansible = "#Ansible: "
|
|
|
|
if cron_file:
|
|
if os.path.isabs(cron_file):
|
|
self.cron_file = cron_file
|
|
else:
|
|
self.cron_file = os.path.join('/etc/cron.d', cron_file)
|
|
else:
|
|
self.cron_file = None
|
|
|
|
self.read()
|
|
|
|
def read(self):
|
|
# Read in the crontab from the system
|
|
self.lines = []
|
|
if self.cron_file:
|
|
# read the cronfile
|
|
try:
|
|
f = open(self.cron_file, 'r')
|
|
self.lines = f.read().splitlines()
|
|
f.close()
|
|
except IOError:
|
|
# cron file does not exist
|
|
return
|
|
except:
|
|
raise CronTabError("Unexpected error:", sys.exc_info()[0])
|
|
else:
|
|
# using safely quoted shell for now, but this really should be two non-shell calls instead. FIXME
|
|
(rc, out, err) = self.module.run_command(self._read_user_execute(), use_unsafe_shell=True)
|
|
|
|
if rc != 0 and rc != 1: # 1 can mean that there are no jobs.
|
|
raise CronTabError("Unable to read crontab")
|
|
|
|
lines = out.splitlines()
|
|
count = 0
|
|
for l in lines:
|
|
if count > 2 or (not re.match( r'# DO NOT EDIT THIS FILE - edit the master and reinstall.', l) and
|
|
not re.match( r'# \(/tmp/.*installed on.*\)', l) and
|
|
not re.match( r'# \(.*version.*\)', l)):
|
|
self.lines.append(l)
|
|
count += 1
|
|
|
|
def is_empty(self):
|
|
if len(self.lines) == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def write(self, backup_file=None):
|
|
"""
|
|
Write the crontab to the system. Saves all information.
|
|
"""
|
|
if backup_file:
|
|
fileh = open(backup_file, 'w')
|
|
elif self.cron_file:
|
|
fileh = open(self.cron_file, 'w')
|
|
else:
|
|
filed, path = tempfile.mkstemp(prefix='crontab')
|
|
os.chmod(path, int('0644', 8))
|
|
fileh = os.fdopen(filed, 'w')
|
|
|
|
fileh.write(self.render())
|
|
fileh.close()
|
|
|
|
# return if making a backup
|
|
if backup_file:
|
|
return
|
|
|
|
# Add the entire crontab back to the user crontab
|
|
if not self.cron_file:
|
|
# quoting shell args for now but really this should be two non-shell calls. FIXME
|
|
(rc, out, err) = self.module.run_command(self._write_execute(path), use_unsafe_shell=True)
|
|
os.unlink(path)
|
|
|
|
if rc != 0:
|
|
self.module.fail_json(msg=err)
|
|
|
|
def add_job(self, name, job):
|
|
# Add the comment
|
|
self.lines.append("%s%s" % (self.ansible, name))
|
|
|
|
# Add the job
|
|
self.lines.append("%s" % (job))
|
|
|
|
def update_job(self, name, job):
|
|
return self._update_job(name, job, self.do_add_job)
|
|
|
|
def do_add_job(self, lines, comment, job):
|
|
lines.append(comment)
|
|
|
|
lines.append("%s" % (job))
|
|
|
|
def remove_job(self, name):
|
|
return self._update_job(name, "", self.do_remove_job)
|
|
|
|
def do_remove_job(self, lines, comment, job):
|
|
return None
|
|
|
|
def add_env(self, decl, insertafter=None, insertbefore=None):
|
|
if not (insertafter or insertbefore):
|
|
self.lines.insert(0, decl)
|
|
return
|
|
|
|
if insertafter:
|
|
other_name = insertafter
|
|
elif insertbefore:
|
|
other_name = insertbefore
|
|
other_decl = self.find_env(other_name)
|
|
if len(other_decl) > 0:
|
|
if insertafter:
|
|
index = other_decl[0]+1
|
|
elif insertbefore:
|
|
index = other_decl[0]
|
|
self.lines.insert(index, decl)
|
|
return
|
|
|
|
self.module.fail_json(msg="Variable named '%s' not found." % other_name)
|
|
|
|
def update_env(self, name, decl):
|
|
return self._update_env(name, decl, self.do_add_env)
|
|
|
|
def do_add_env(self, lines, decl):
|
|
lines.append(decl)
|
|
|
|
def remove_env(self, name):
|
|
return self._update_env(name, '', self.do_remove_env)
|
|
|
|
def do_remove_env(self, lines, decl):
|
|
return None
|
|
|
|
def remove_job_file(self):
|
|
try:
|
|
os.unlink(self.cron_file)
|
|
return True
|
|
except OSError:
|
|
# cron file does not exist
|
|
return False
|
|
except:
|
|
raise CronTabError("Unexpected error:", sys.exc_info()[0])
|
|
|
|
def find_job(self, name):
|
|
comment = None
|
|
for l in self.lines:
|
|
if comment is not None:
|
|
if comment == name:
|
|
return [comment, l]
|
|
else:
|
|
comment = None
|
|
elif re.match( r'%s' % self.ansible, l):
|
|
comment = re.sub( r'%s' % self.ansible, '', l)
|
|
|
|
return []
|
|
|
|
def find_env(self, name):
|
|
for index, l in enumerate(self.lines):
|
|
if re.match( r'^%s=' % name, l):
|
|
return [index, l]
|
|
|
|
return []
|
|
|
|
def get_cron_job(self,minute,hour,day,month,weekday,job,special,disabled):
|
|
if disabled:
|
|
disable_prefix = '#'
|
|
else:
|
|
disable_prefix = ''
|
|
|
|
if special:
|
|
if self.cron_file:
|
|
return "%s@%s %s %s" % (disable_prefix, special, self.user, job)
|
|
else:
|
|
return "%s@%s %s" % (disable_prefix, special, job)
|
|
else:
|
|
if self.cron_file:
|
|
return "%s%s %s %s %s %s %s %s" % (disable_prefix,minute,hour,day,month,weekday,self.user,job)
|
|
else:
|
|
return "%s%s %s %s %s %s %s" % (disable_prefix,minute,hour,day,month,weekday,job)
|
|
|
|
return None
|
|
|
|
def get_jobnames(self):
|
|
jobnames = []
|
|
|
|
for l in self.lines:
|
|
if re.match( r'%s' % self.ansible, l):
|
|
jobnames.append(re.sub( r'%s' % self.ansible, '', l))
|
|
|
|
return jobnames
|
|
|
|
def get_envnames(self):
|
|
envnames = []
|
|
|
|
for l in self.lines:
|
|
if re.match( r'^\S+=' , l):
|
|
envnames.append(l.split('=')[0])
|
|
|
|
return envnames
|
|
|
|
def _update_job(self, name, job, addlinesfunction):
|
|
ansiblename = "%s%s" % (self.ansible, name)
|
|
newlines = []
|
|
comment = None
|
|
|
|
for l in self.lines:
|
|
if comment is not None:
|
|
addlinesfunction(newlines, comment, job)
|
|
comment = None
|
|
elif l == ansiblename:
|
|
comment = l
|
|
else:
|
|
newlines.append(l)
|
|
|
|
self.lines = newlines
|
|
|
|
if len(newlines) == 0:
|
|
return True
|
|
else:
|
|
return False # TODO add some more error testing
|
|
|
|
def _update_env(self, name, decl, addenvfunction):
|
|
newlines = []
|
|
|
|
for l in self.lines:
|
|
if re.match( r'^%s=' % name, l):
|
|
addenvfunction(newlines, decl)
|
|
else:
|
|
newlines.append(l)
|
|
|
|
self.lines = newlines
|
|
|
|
def render(self):
|
|
"""
|
|
Render this crontab as it would be in the crontab.
|
|
"""
|
|
crons = []
|
|
for cron in self.lines:
|
|
crons.append(cron)
|
|
|
|
result = '\n'.join(crons)
|
|
if result and result[-1] not in ['\n', '\r']:
|
|
result += '\n'
|
|
return result
|
|
|
|
def _read_user_execute(self):
|
|
"""
|
|
Returns the command line for reading a crontab
|
|
"""
|
|
user = ''
|
|
if self.user:
|
|
if platform.system() == 'SunOS':
|
|
return "su %s -c '%s -l'" % (pipes.quote(self.user), pipes.quote(CRONCMD))
|
|
elif platform.system() == 'AIX':
|
|
return "%s -l %s" % (pipes.quote(CRONCMD), pipes.quote(self.user))
|
|
elif platform.system() == 'HP-UX':
|
|
return "%s %s %s" % (CRONCMD , '-l', pipes.quote(self.user))
|
|
else:
|
|
user = '-u %s' % pipes.quote(self.user)
|
|
return "%s %s %s" % (CRONCMD , user, '-l')
|
|
|
|
def _write_execute(self, path):
|
|
"""
|
|
Return the command line for writing a crontab
|
|
"""
|
|
user = ''
|
|
if self.user:
|
|
if platform.system() in ['SunOS', 'HP-UX', 'AIX']:
|
|
return "chown %s %s ; su '%s' -c '%s %s'" % (pipes.quote(self.user), pipes.quote(path), pipes.quote(self.user), CRONCMD, pipes.quote(path))
|
|
else:
|
|
user = '-u %s' % pipes.quote(self.user)
|
|
return "%s %s %s" % (CRONCMD , user, pipes.quote(path))
|
|
|
|
|
|
|
|
#==================================================
|
|
|
|
def main():
|
|
# The following example playbooks:
|
|
#
|
|
# - cron: name="check dirs" hour="5,2" job="ls -alh > /dev/null"
|
|
#
|
|
# - name: do the job
|
|
# cron: name="do the job" hour="5,2" job="/some/dir/job.sh"
|
|
#
|
|
# - name: no job
|
|
# cron: name="an old job" state=absent
|
|
#
|
|
# - name: sets env
|
|
# cron: name="PATH" env=yes value="/bin:/usr/bin"
|
|
#
|
|
# Would produce:
|
|
# PATH=/bin:/usr/bin
|
|
# # Ansible: check dirs
|
|
# * * 5,2 * * ls -alh > /dev/null
|
|
# # Ansible: do the job
|
|
# * * 5,2 * * /some/dir/job.sh
|
|
|
|
module = AnsibleModule(
|
|
argument_spec = dict(
|
|
name=dict(required=False),
|
|
user=dict(required=False),
|
|
job=dict(required=False, aliases=['value']),
|
|
cron_file=dict(required=False),
|
|
state=dict(default='present', choices=['present', 'absent']),
|
|
backup=dict(default=False, type='bool'),
|
|
minute=dict(default='*'),
|
|
hour=dict(default='*'),
|
|
day=dict(aliases=['dom'], default='*'),
|
|
month=dict(default='*'),
|
|
weekday=dict(aliases=['dow'], default='*'),
|
|
reboot=dict(required=False, default=False, type='bool'),
|
|
special_time=dict(required=False,
|
|
default=None,
|
|
choices=["reboot", "yearly", "annually", "monthly", "weekly", "daily", "hourly"],
|
|
type='str'),
|
|
disabled=dict(default=False, type='bool'),
|
|
env=dict(required=False, type='bool'),
|
|
insertafter=dict(required=False),
|
|
insertbefore=dict(required=False),
|
|
),
|
|
supports_check_mode = True,
|
|
mutually_exclusive=[
|
|
['reboot', 'special_time'],
|
|
['insertafter', 'insertbefore'],
|
|
]
|
|
)
|
|
|
|
name = module.params['name']
|
|
user = module.params['user']
|
|
job = module.params['job']
|
|
cron_file = module.params['cron_file']
|
|
state = module.params['state']
|
|
backup = module.params['backup']
|
|
minute = module.params['minute']
|
|
hour = module.params['hour']
|
|
day = module.params['day']
|
|
month = module.params['month']
|
|
weekday = module.params['weekday']
|
|
reboot = module.params['reboot']
|
|
special_time = module.params['special_time']
|
|
disabled = module.params['disabled']
|
|
env = module.params['env']
|
|
insertafter = module.params['insertafter']
|
|
insertbefore = module.params['insertbefore']
|
|
do_install = state == 'present'
|
|
|
|
changed = False
|
|
res_args = dict()
|
|
|
|
# Ensure all files generated are only writable by the owning user. Primarily relevant for the cron_file option.
|
|
os.umask(int('022', 8))
|
|
crontab = CronTab(module, user, cron_file)
|
|
|
|
module.debug('cron instantiated - name: "%s"' % name)
|
|
|
|
if module._diff:
|
|
diff = dict()
|
|
diff['before'] = crontab.render()
|
|
if crontab.cron_file:
|
|
diff['before_header'] = crontab.cron_file
|
|
else:
|
|
if crontab.user:
|
|
diff['before_header'] = 'crontab for user "%s"' % crontab.user
|
|
else:
|
|
diff['before_header'] = 'crontab'
|
|
|
|
# --- user input validation ---
|
|
|
|
if (special_time or reboot) and \
|
|
(True in [(x != '*') for x in [minute, hour, day, month, weekday]]):
|
|
module.fail_json(msg="You must specify time and date fields or special time.")
|
|
|
|
if cron_file and do_install:
|
|
if not user:
|
|
module.fail_json(msg="To use cron_file=... parameter you must specify user=... as well")
|
|
|
|
if job is None and do_install:
|
|
module.fail_json(msg="You must specify 'job' to install a new cron job or variable")
|
|
|
|
if (insertafter or insertbefore) and not env and do_install:
|
|
module.fail_json(msg="Insertafter and insertbefore parameters are valid only with env=yes")
|
|
|
|
if reboot:
|
|
special_time = "reboot"
|
|
|
|
# if requested make a backup before making a change
|
|
if backup and not module.check_mode:
|
|
(backuph, backup_file) = tempfile.mkstemp(prefix='crontab')
|
|
crontab.write(backup_file)
|
|
|
|
|
|
if crontab.cron_file and not name and not do_install:
|
|
if module._diff:
|
|
diff['after'] = ''
|
|
diff['after_header'] = '/dev/null'
|
|
else:
|
|
diff = dict()
|
|
if module.check_mode:
|
|
changed = os.path.isfile(crontab.cron_file)
|
|
else:
|
|
changed = crontab.remove_job_file()
|
|
module.exit_json(changed=changed,cron_file=cron_file,state=state,diff=diff)
|
|
|
|
if env:
|
|
if ' ' in name:
|
|
module.fail_json(msg="Invalid name for environment variable")
|
|
decl = '%s="%s"' % (name, job)
|
|
old_decl = crontab.find_env(name)
|
|
|
|
if do_install:
|
|
if len(old_decl) == 0:
|
|
crontab.add_env(decl, insertafter, insertbefore)
|
|
changed = True
|
|
if len(old_decl) > 0 and old_decl[1] != decl:
|
|
crontab.update_env(name, decl)
|
|
changed = True
|
|
else:
|
|
if len(old_decl) > 0:
|
|
crontab.remove_env(name)
|
|
changed = True
|
|
else:
|
|
job = crontab.get_cron_job(minute, hour, day, month, weekday, job, special_time, disabled)
|
|
old_job = crontab.find_job(name)
|
|
|
|
if do_install:
|
|
if len(old_job) == 0:
|
|
crontab.add_job(name, job)
|
|
changed = True
|
|
if len(old_job) > 0 and old_job[1] != job:
|
|
crontab.update_job(name, job)
|
|
changed = True
|
|
else:
|
|
if len(old_job) > 0:
|
|
crontab.remove_job(name)
|
|
changed = True
|
|
|
|
res_args = dict(
|
|
jobs = crontab.get_jobnames(),
|
|
envs = crontab.get_envnames(),
|
|
changed = changed
|
|
)
|
|
|
|
if changed:
|
|
if not module.check_mode:
|
|
crontab.write()
|
|
if module._diff:
|
|
diff['after'] = crontab.render()
|
|
if crontab.cron_file:
|
|
diff['after_header'] = crontab.cron_file
|
|
else:
|
|
if crontab.user:
|
|
diff['after_header'] = 'crontab for user "%s"' % crontab.user
|
|
else:
|
|
diff['after_header'] = 'crontab'
|
|
|
|
res_args['diff'] = diff
|
|
|
|
# retain the backup only if crontab or cron file have changed
|
|
if backup:
|
|
if changed:
|
|
res_args['backup_file'] = backup_file
|
|
else:
|
|
if not module.check_mode:
|
|
os.unlink(backup_file)
|
|
|
|
if cron_file:
|
|
res_args['cron_file'] = cron_file
|
|
|
|
module.exit_json(**res_args)
|
|
|
|
# --- should never get here
|
|
module.exit_json(msg="Unable to execute cron task.")
|
|
|
|
# import module snippets
|
|
from ansible.module_utils.basic import *
|
|
|
|
main()
|
|
|