[2.11] Do not remove non-empty cron tabs (#74698)

* Only remove crontabs if they are empty

(cherry picked from commit fefda12827)

* Add integration test to ensure system cron tab doesn't get removed. Increase cron integration tests separation.

(cherry picked from commit 1e37fa86b4)

* Also detect crontab which only contains whitespace as empty.

(cherry picked from commit 4b69c8f501)

* cron integration test: Adjust system crontab path to be distribution specific.

(cherry picked from commit 70be3730db)

* Add changelog fragment for #74497.

(cherry picked from commit c606b50a3d)

Co-authored-by: Fabian Klemp <fabian.klemp@elara-gmbh.de>
pull/74418/head
elara-leitstellentechnik 4 years ago committed by GitHub
parent 3d6c8ee3e0
commit 22adad0f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
bugfixes:
- ansible.builtin.cron - Keep non-empty crontabs, when removing cron jobs
(https://github.com/ansible/ansible/pull/74497).

@ -291,7 +291,10 @@ class CronTab(object):
if len(self.lines) == 0: if len(self.lines) == 0:
return True return True
else: else:
for line in self.lines:
if line.strip():
return False return False
return True
def write(self, backup_file=None): def write(self, backup_file=None):
""" """
@ -675,18 +678,6 @@ def main():
(backuph, backup_file) = tempfile.mkstemp(prefix='crontab') (backuph, backup_file) = tempfile.mkstemp(prefix='crontab')
crontab.write(backup_file) 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 env:
if ' ' in name: if ' ' in name:
module.fail_json(msg="Invalid name for environment variable") module.fail_json(msg="Invalid name for environment variable")
@ -729,6 +720,17 @@ def main():
if len(old_job) > 0: if len(old_job) > 0:
crontab.remove_job(name) crontab.remove_job(name)
changed = True 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 # no changes to env/job, but existing crontab needs a terminating newline
if not changed and crontab.n_existing != '': if not changed and crontab.n_existing != '':

@ -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) - name: add cron task (check mode enabled, cron task not already created)
cron: cron:
name: test cron task name: test cron task
@ -130,40 +149,115 @@
- name: Removing a cron file when the name is specified is allowed (#57471) - name: Removing a cron file when the name is specified is allowed (#57471)
when: ansible_distribution != 'Alpine' when: ansible_distribution != 'Alpine'
block: 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 - name: Cron file creation
cron: cron:
cron_file: cron_filename cron_file: cron_remove_name
name: "integration test cron" name: "integration test cron"
job: 'ls' job: 'ls'
user: root user: root
- name: Cron file deletion - name: Cron file deletion
cron: cron:
cron_file: cron_filename cron_file: cron_remove_name
name: "integration test cron" name: "integration test cron"
state: absent state: absent
- name: Check file succesfull deletion - name: Check file succesfull deletion
stat: 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 register: cron_file_stats
- assert: - assert:
that: not cron_file_stats.stat.exists 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) - name: Allow non-ascii chars in job (#69492)
when: ansible_distribution != 'Alpine' when: ansible_distribution != 'Alpine'
block: 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 - name: Cron file creation
cron: cron:
cron_file: cron_filename cron_file: cron_nonascii
name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)" name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)"
job: 'echo "うどんは好きだがお化け👻は苦手である。"' job: 'echo "うどんは好きだがお化け👻は苦手である。"'
user: root user: root
- name: "Ensure cron_file contains job string" - name: "Ensure cron_file contains job string"
replace: replace:
path: /etc/cron.d/cron_filename path: /etc/cron.d/cron_nonascii
regexp: "うどんは好きだがお化け👻は苦手である。" regexp: "うどんは好きだがお化け👻は苦手である。"
replace: "それは機密情報🔓です。" replace: "それは機密情報🔓です。"
register: find_chars register: find_chars
@ -171,13 +265,13 @@
- name: Cron file deletion - name: Cron file deletion
cron: cron:
cron_file: cron_filename cron_file: cron_nonascii
name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)" name: "cron job that contain non-ascii chars in job (これは日本語です; This is Japanese)"
state: absent state: absent
- name: Check file succesfull deletion - name: Check file succesfull deletion
stat: stat:
path: /etc/cron.d/cron_filename path: /etc/cron.d/cron_nonascii
register: cron_file_stats register: cron_file_stats
- assert: - assert:

@ -0,0 +1 @@
system_crontab: /etc/crontabs/root

@ -0,0 +1 @@
system_crontab: /etc/crontab
Loading…
Cancel
Save