diff --git a/salt/modules/cron.py b/salt/modules/cron.py index 2fc718ff68..cc9631cb98 100644 --- a/salt/modules/cron.py +++ b/salt/modules/cron.py @@ -146,8 +146,24 @@ def _render_tab(lst): cron['cmd'] ) ) - for spec in lst['special']: - ret.append('{0} {1}\n'.format(spec['spec'], spec['cmd'])) + for cron in lst['special']: + if cron['comment'] is not None or cron['identifier'] is not None: + comment = '#' + if cron['comment']: + comment += ' {0}'.format( + cron['comment'].rstrip().replace('\n', '\n# ')) + if cron['identifier']: + comment += ' {0}:{1}'.format(SALT_CRON_IDENTIFIER, + cron['identifier']) + + comment += '\n' + ret.append(comment) + ret.append('{0}{1} {2}\n'.format( + cron['commented'] is True and '#DISABLED#' or '', + cron['spec'], + cron['cmd'] + ) + ) return ret @@ -322,7 +338,15 @@ def list_tab(user): continue dat['spec'] = comps[0] dat['cmd'] = ' '.join(comps[1:]) + dat['identifier'] = identifier + dat['comment'] = comment + dat['commented'] = False + if commented_cron_job: + dat['commented'] = True ret['special'].append(dat) + identifier = None + comment = None + commented_cron_job = False elif line.startswith('#'): # It's a comment! Catch it! comment_line = line.lstrip('# ') @@ -368,11 +392,17 @@ def list_tab(user): ret['pre'].append(line) return ret + # For consistency's sake ls = salt.utils.alias_function(list_tab, 'ls') -def set_special(user, special, cmd): +def set_special(user, + special, + cmd, + commented=False, + comment=None, + identifier=None): ''' Set up a special command in the crontab. @@ -384,11 +414,60 @@ def set_special(user, special, cmd): ''' lst = list_tab(user) for cron in lst['special']: - if special == cron['spec'] and cmd == cron['cmd']: + cid = _cron_id(cron) + if _cron_matched(cron, cmd, identifier): + test_setted_id = ( + cron['identifier'] is None + and SALT_CRON_NO_IDENTIFIER + or cron['identifier']) + tests = [(cron['comment'], comment), + (cron['commented'], commented), + (identifier, test_setted_id), + (cron['spec'], special)] + if cid or identifier: + tests.append((cron['cmd'], cmd)) + if any([_needs_change(x, y) for x, y in tests]): + rm_special(user, cmd, identifier=cid) + + # Use old values when setting the new job if there was no + # change needed for a given parameter + if not _needs_change(cron['spec'], special): + special = cron['spec'] + if not _needs_change(cron['commented'], commented): + commented = cron['commented'] + if not _needs_change(cron['comment'], comment): + comment = cron['comment'] + if not _needs_change(cron['cmd'], cmd): + cmd = cron['cmd'] + if ( + cid == SALT_CRON_NO_IDENTIFIER + ): + if identifier: + cid = identifier + if ( + cid == SALT_CRON_NO_IDENTIFIER + and cron['identifier'] is None + ): + cid = None + cron['identifier'] = cid + if not cid or ( + cid and not _needs_change(cid, identifier) + ): + identifier = cid + jret = set_special(user, special, cmd, commented=commented, + comment=comment, identifier=identifier) + if jret == 'new': + return 'updated' + else: + return jret return 'present' - spec = {'spec': special, - 'cmd': cmd} - lst['special'].append(spec) + cron = {'spec': special, + 'cmd': cmd, + 'identifier': identifier, + 'comment': comment, + 'commented': commented} + lst['special'].append(cron) + comdat = _write_cron_lines(user, _render_tab(lst)) if comdat['retcode']: # Failed to commit, return the error @@ -537,7 +616,7 @@ def set_job(user, return 'new' -def rm_special(user, special, cmd): +def rm_special(user, cmd, special=None, identifier=None): ''' Remove a special cron job for a specified user. @@ -545,22 +624,28 @@ def rm_special(user, special, cmd): .. code-block:: bash - salt '*' cron.rm_job root @hourly /usr/bin/foo + salt '*' cron.rm_special root /usr/bin/foo ''' lst = list_tab(user) ret = 'absent' rm_ = None for ind in range(len(lst['special'])): - if lst['special'][ind]['cmd'] == cmd and \ - lst['special'][ind]['spec'] == special: - lst['special'].pop(ind) - rm_ = ind + if rm_ is not None: + break + if _cron_matched(lst['special'][ind], cmd, identifier=identifier): + if special is None: + # No special param was specified + rm_ = ind + else: + if lst['special'][ind]['spec'] == special: + rm_ = ind if rm_ is not None: + lst['special'].pop(rm_) ret = 'removed' - comdat = _write_cron_lines(user, _render_tab(lst)) - if comdat['retcode']: - # Failed to commit - return comdat['stderr'] + comdat = _write_cron_lines(user, _render_tab(lst)) + if comdat['retcode']: + # Failed to commit, return the error + return comdat['stderr'] return ret @@ -611,6 +696,7 @@ def rm_job(user, return comdat['stderr'] return ret + rm = salt.utils.alias_function(rm_job, 'rm') diff --git a/salt/states/cron.py b/salt/states/cron.py index e285e97790..2cfe8f1835 100644 --- a/salt/states/cron.py +++ b/salt/states/cron.py @@ -201,7 +201,14 @@ def _check_cron(user, return 'present' else: for cron in lst['special']: - if special == cron['spec'] and cmd == cron['cmd']: + if _cron_matched(cron, cmd, identifier): + if any([_needs_change(x, y) for x, y in + ((cron['spec'], special), + (cron['identifier'], identifier), + (cron['cmd'], cmd), + (cron['comment'], comment), + (cron['commented'], commented))]): + return 'update' return 'present' return 'absent' @@ -348,7 +355,12 @@ def present(name, commented=commented, identifier=identifier) else: - data = __salt__['cron.set_special'](user, special, name) + data = __salt__['cron.set_special'](user=user, + special=special, + cmd=name, + comment=comment, + commented=commented, + identifier=identifier) if data == 'present': ret['comment'] = 'Cron {0} already present'.format(name) return ret @@ -417,7 +429,7 @@ def absent(name, if special is None: data = __salt__['cron.rm_job'](user, name, identifier=identifier) else: - data = __salt__['cron.rm_special'](user, special, name) + data = __salt__['cron.rm_special'](user, name, special=special, identifier=identifier) if data == 'absent': ret['comment'] = "Cron {0} already absent".format(name)