diff options
-rw-r--r-- | changelogs/fragments/74497-keep-non-empty-crontabs.yml | 3 | ||||
-rw-r--r-- | lib/ansible/modules/cron.py | 28 | ||||
-rw-r--r-- | test/integration/targets/cron/tasks/main.yml | 108 | ||||
-rw-r--r-- | test/integration/targets/cron/vars/alpine.yml | 1 | ||||
-rw-r--r-- | test/integration/targets/cron/vars/default.yml | 1 |
5 files changed, 121 insertions, 20 deletions
diff --git a/changelogs/fragments/74497-keep-non-empty-crontabs.yml b/changelogs/fragments/74497-keep-non-empty-crontabs.yml new file mode 100644 index 0000000000..2e88e6b54c --- /dev/null +++ b/changelogs/fragments/74497-keep-non-empty-crontabs.yml @@ -0,0 +1,3 @@ +bugfixes: + - ansible.builtin.cron - Keep non-empty crontabs, when removing cron jobs + (https://github.com/ansible/ansible/pull/74497). diff --git a/lib/ansible/modules/cron.py b/lib/ansible/modules/cron.py index 2424f5c065..621896366f 100644 --- a/lib/ansible/modules/cron.py +++ b/lib/ansible/modules/cron.py @@ -291,7 +291,10 @@ class CronTab(object): if len(self.lines) == 0: return True else: - return False + for line in self.lines: + if line.strip(): + return False + return True def write(self, backup_file=None): """ @@ -675,18 +678,6 @@ def main(): (backuph, backup_file) = tempfile.mkstemp(prefix='crontab') crontab.write(backup_file) - if crontab.cron_file 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") @@ -729,6 +720,17 @@ def main(): if len(old_job) > 0: crontab.remove_job(name) changed = True + if crontab.cron_file and crontab.is_empty(): + 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) # no changes to env/job, but existing crontab needs a terminating newline if not changed and crontab.n_existing != '': diff --git a/test/integration/targets/cron/tasks/main.yml b/test/integration/targets/cron/tasks/main.yml index 5484072a21..899ec54926 100644 --- a/test/integration/targets/cron/tasks/main.yml +++ b/test/integration/targets/cron/tasks/main.yml @@ -1,3 +1,22 @@ +- name: Include distribution specific variables + include_vars: "{{ lookup('first_found', search) }}" + vars: + search: + files: + - '{{ ansible_distribution | lower }}.yml' + - '{{ ansible_os_family | lower }}.yml' + - '{{ ansible_system | lower }}.yml' + - default.yml + paths: + - vars + +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=726661 +- name: Work around vixie-cron/PAM issue on old distros + command: sed -i '/pam_loginuid/ s/^/#/' /etc/pam.d/crond + when: + - ansible_distribution in ('RedHat', 'CentOS') + - ansible_distribution_major_version is version('6', '==') + - name: add cron task (check mode enabled, cron task not already created) cron: name: test cron task @@ -130,40 +149,115 @@ - name: Removing a cron file when the name is specified is allowed (#57471) when: ansible_distribution != 'Alpine' block: + - name: Check file does not exist + stat: + path: /etc/cron.d/cron_remove_name + register: cron_file_stats + + - assert: + that: not cron_file_stats.stat.exists + - name: Cron file creation cron: - cron_file: cron_filename + cron_file: cron_remove_name name: "integration test cron" job: 'ls' user: root - name: Cron file deletion cron: - cron_file: cron_filename + cron_file: cron_remove_name name: "integration test cron" state: absent - name: Check file succesfull deletion stat: - path: /etc/cron.d/cron_filename + path: /etc/cron.d/cron_remove_name + register: cron_file_stats + + - assert: + that: not cron_file_stats.stat.exists + +# BusyBox does not have /etc/cron.d +- name: Removing a cron file, which contains only whitespace + when: ansible_distribution != 'Alpine' + block: + - name: Check file does not exist + stat: + path: /etc/cron.d/cron_remove_whitespace + register: cron_file_stats + + - assert: + that: not cron_file_stats.stat.exists + + - name: Cron file creation + cron: + cron_file: cron_remove_whitespace + name: "integration test cron" + job: 'ls' + user: root + + - name: Add whitespace to cron file + shell: 'printf "\n \n\t\n" >> /etc/cron.d/cron_remove_whitespace' + + - name: Cron file deletion + cron: + cron_file: cron_remove_whitespace + name: "integration test cron" + state: absent + + - name: Check file succesfull deletion + stat: + path: /etc/cron.d/cron_remove_whitespace register: cron_file_stats - assert: that: not cron_file_stats.stat.exists +- name: System cron tab does not get removed + block: + - name: Add cron job + cron: + cron_file: "{{ system_crontab }}" + user: root + name: "integration test cron" + job: 'ls' + + - name: Remove cron job + cron: + cron_file: "{{ system_crontab }}" + name: "integration test cron" + state: absent + + - name: Check system crontab still exists + stat: + path: "{{ system_crontab }}" + register: cron_file_stats + + - assert: + that: cron_file_stats.stat.exists + - name: Allow non-ascii chars in job (#69492) when: ansible_distribution != 'Alpine' block: + - name: Check file does not exist + stat: + path: /etc/cron.d/cron_nonascii + register: cron_file_stats + + - assert: + that: not cron_file_stats.stat.exists + - name: Cron file creation cron: - cron_file: cron_filename + cron_file: cron_nonascii name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)" job: 'echo "うどんは好きだがお化け👻は苦手である。"' user: root - name: "Ensure cron_file contains job string" replace: - path: /etc/cron.d/cron_filename + path: /etc/cron.d/cron_nonascii regexp: "うどんは好きだがお化け👻は苦手である。" replace: "それは機密情報🔓です。" register: find_chars @@ -171,13 +265,13 @@ - name: Cron file deletion cron: - cron_file: cron_filename + cron_file: cron_nonascii name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)" state: absent - name: Check file succesfull deletion stat: - path: /etc/cron.d/cron_filename + path: /etc/cron.d/cron_nonascii register: cron_file_stats - assert: diff --git a/test/integration/targets/cron/vars/alpine.yml b/test/integration/targets/cron/vars/alpine.yml new file mode 100644 index 0000000000..29ca3b9474 --- /dev/null +++ b/test/integration/targets/cron/vars/alpine.yml @@ -0,0 +1 @@ +system_crontab: /etc/crontabs/root diff --git a/test/integration/targets/cron/vars/default.yml b/test/integration/targets/cron/vars/default.yml new file mode 100644 index 0000000000..69c5de469f --- /dev/null +++ b/test/integration/targets/cron/vars/default.yml @@ -0,0 +1 @@ +system_crontab: /etc/crontab |