diff --git a/changelogs/fragments/cron_removals.yml b/changelogs/fragments/cron_removals.yml new file mode 100644 index 00000000000..6d6275cbb82 --- /dev/null +++ b/changelogs/fragments/cron_removals.yml @@ -0,0 +1,2 @@ +minor_changes: + - cron, removed previously deprecated 'reboot' and now requires either 'name' as unique identifier. diff --git a/lib/ansible/modules/cron.py b/lib/ansible/modules/cron.py index a84a4bada7f..51d6b4eec7d 100644 --- a/lib/ansible/modules/cron.py +++ b/lib/ansible/modules/cron.py @@ -57,12 +57,14 @@ options: cron_file: description: - If specified, uses this file instead of an individual user's crontab. + The assumption is that this file is exclusively managed by the module, + do not use if the file contains multiple entries, NEVER use for /etc/crontab. - If this is a relative path, it is interpreted with respect to I(/etc/cron.d). - - If it is absolute, it will typically be C(/etc/crontab). - Many linux distros expect (and some require) the filename portion to consist solely of upper- and lower-case letters, digits, underscores, and hyphens. - - To use the I(cron_file) parameter you must specify the I(user) as well. - type: str + - Using this parameter requires you to specify the I(user) as well, unless I(state) is not I(present). + - Either this parameter or I(name) is required + type: path backup: description: - If set, create a backup of the crontab before it is modified. @@ -232,6 +234,7 @@ class CronTab(object): self.cron_cmd = self.module.get_bin_path('crontab', required=True) if cron_file: + if os.path.isabs(cron_file): self.cron_file = cron_file self.b_cron_file = to_bytes(cron_file, errors='surrogate_or_strict') @@ -557,7 +560,7 @@ def main(): name=dict(type='str', required=True), user=dict(type='str'), job=dict(type='str', aliases=['value']), - cron_file=dict(type='str'), + cron_file=dict(type='path'), state=dict(type='str', default='present', choices=['present', 'absent']), backup=dict(type='bool', default=False), minute=dict(type='str', default='*'), @@ -600,6 +603,10 @@ def main(): warnings = list() if cron_file: + + if cron_file == '/etc/crontab': + module.fail_json(msg="Will not manage /etc/crontab via cron_file, see documentation.") + cron_file_basename = os.path.basename(cron_file) if not re.search(r'^[A-Z0-9_-]+$', cron_file_basename, re.I): warnings.append('Filename portion of cron_file ("%s") should consist' % cron_file_basename + @@ -632,15 +639,15 @@ def main(): if special_time and platform.system() == 'SunOS': module.fail_json(msg="Solaris does not support special_time=... or @reboot") - if cron_file and do_install: - if not user: + if do_install: + if cron_file and 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 job is None: + 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 (insertafter or insertbefore) and not env: + module.fail_json(msg="Insertafter and insertbefore parameters are valid only with env=yes") # if requested make a backup before making a change if backup and not module.check_mode: