2

I want to have all cron jobs of a server parsed by Ansible and write the existing entries into a JSON file on the Ansible management node.

Sadly I have no idea how to read the crontab and even more how to write all entries into a JSON.

Intention of this requirement:

This JSON shall be used by administrators to manage centrally all crons of all servers and to be able to push "Updates" down to the nodes.

How to solve this requirement?

U880D
  • 8,601
  • 6
  • 24
  • 40
cilap
  • 2,215
  • 1
  • 25
  • 51
  • I don't know if there is a straight way to achieve this. one thing you can try is to dump the output of crontab -l and use python library to convert text to string. – Eva Jul 06 '22 at 05:29
  • my issue is already on understanding the dump of the crontab, how to achieve this? – cilap Jul 06 '22 at 05:50
  • Unordered and non exhaustive documentation list: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/cron_module.html, https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables, https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html, https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fetch_module.html, https://docs.ansible.com/ansible/latest/collections/ansible/builtin/slurp_module.html. – Zeitounator Jul 06 '22 at 06:09
  • SInce your requirement seems to be to list **all** cron jobs for all users and independent where they are configured (`/etc/cron.d/`) such task or module isn't available in Ansible out-of-box yet. Technically it is possbible to achieve your goal with Ansible, but someone has to write the logic for. It could be done by several tasks in an Ansible playbook or a Custom Module for Ansible written in Bash or Python. – U880D Jul 06 '22 at 07:46
  • A good starting point is in example [How do I list all cron jobs for all users?](https://stackoverflow.com/questions/134906/). – U880D Jul 06 '22 at 07:48

2 Answers2

1

As the comments mention, you need to write the logic yourself, as there is no module that does that for you.

You can use this python-library to parse the files. But be aware that there can be a lot of locations where cron-jobs can be configured. Including, but not limited to

  • /etc/crontab
  • /etc/cron.d/*
  • /etc/cron.daily, weekly etc.
  • users contabs, that are modified using the crontab command

Then you can use the json-module in the standard-library to dump a JSON string.

In any case, you are approaching this in the wrong way. You should use the ansible.builtin.cron module to define all cron-tab entries in a playbook. You can then add, update or delete cron-jobs on the servers by updating the playbook and running it. You can even version your playbook using git, introduce a review-process etc.

toydarian
  • 4,246
  • 5
  • 23
  • 35
1

Use filter community.general.jc. It's a wrapper of the Python jc converter. For example, given the crontab

shell> ssh admin@test_11 cat /etc/crontab
# /etc/crontab - root's crontab for FreeBSD
#
# $FreeBSD$
#
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
#
#minute hour    mday    month   wday    who command
#
# Save some entropy so that /dev/random can re-seed on boot.
*/11    *   *   *   *   operator /usr/libexec/save-entropy
#
# Rotate log files every hour, if necessary.
0   *   *   *   *   root    newsyslog
#
# Perform daily/weekly/monthly maintenance.
1   3   *   *   *   root    periodic daily
15  4   *   *   6   root    periodic weekly
30  5   1   *   *   root    periodic monthly
#
# Adjust the time zone if the CMOS clock keeps local time, as opposed to
# UTC time.  See adjkerntz(8) for details.
1,31    0-5 *   *   *   root    adjkerntz -a

The playbook below

shell> cat pb.yml
- hosts: test_11,test_12
  tasks:
    - command:
        cmd: cat /etc/crontab
      register: result
    - set_fact:
        crontab: "{{ result.stdout|community.general.jc('crontab_u') }}"
    - copy:
        dest: /tmp/crontabs.json
        content: |
          {{ crontabs_dict|to_json }}
      vars:
        crontabs_list: "{{ ansible_play_hosts|map('extract', hostvars, 'crontab')|list }}"
        crontabs_dict: "{{ dict(ansible_play_hosts|zip(crontabs_list)) }}"
      delegate_to: localhost
      run_once: true

creates the file at the controller

shell> cat /tmp/crontabs.json 

{"test_11": {"variables": [{"name": "PATH", "value": "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"}, {"name": "SHELL", "value": "/bin/sh"}], "schedule": [{"minute": ["/11"], "hour": [""], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "operator", "command": "/usr/libexec/save-entropy"}, {"minute": ["0"], "hour": [""], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "newsyslog"}, {"minute": ["1"], "hour": ["3"], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "periodic daily"}, {"minute": ["15"], "hour": ["4"], "day_of_month": [""], "month": [""], "day_of_week": ["6"], "user": "root", "command": "periodic weekly"}, {"minute": ["30"], "hour": ["5"], "day_of_month": ["1"], "month": [""], "day_of_week": [""], "user": "root", "command": "periodic monthly"}, {"minute": ["1", "31"], "hour": ["0-5"], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "adjkerntz -a"}]}, "test_12": {"variables": [{"name": "PATH", "value": "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"}, {"name": "SHELL", "value": "/bin/sh"}], "schedule": [{"minute": ["/11"], "hour": [""], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "operator", "command": "/usr/libexec/save-entropy"}, {"minute": ["0"], "hour": [""], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "newsyslog"}, {"minute": ["1"], "hour": ["3"], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "periodic daily"}, {"minute": ["15"], "hour": ["4"], "day_of_month": [""], "month": [""], "day_of_week": ["6"], "user": "root", "command": "periodic weekly"}, {"minute": ["30"], "hour": ["5"], "day_of_month": ["1"], "month": [""], "day_of_week": [""], "user": "root", "command": "periodic monthly"}, {"minute": ["1", "31"], "hour": ["0-5"], "day_of_month": [""], "month": [""], "day_of_week": [""], "user": "root", "command": "adjkerntz -a"}]}}


The variable crontabs_dict in YAML

  crontabs_dict:
    test_11:
      schedule:
      - command: /usr/libexec/save-entropy
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['*']
        minute: ['*/11']
        month: ['*']
        user: operator
      - command: newsyslog
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['*']
        minute: ['0']
        month: ['*']
        user: root
      - command: periodic daily
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['3']
        minute: ['1']
        month: ['*']
        user: root
      - command: periodic weekly
        day_of_month: ['*']
        day_of_week: ['6']
        hour: ['4']
        minute: ['15']
        month: ['*']
        user: root
      - command: periodic monthly
        day_of_month: ['1']
        day_of_week: ['*']
        hour: ['5']
        minute: ['30']
        month: ['*']
        user: root
      - command: adjkerntz -a
        day_of_month: ['*']
        day_of_week: ['*']
        hour: [0-5]
        minute: ['1', '31']
        month: ['*']
        user: root
      variables:
      - {name: PATH, value: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'}
      - {name: SHELL, value: /bin/sh}
    test_12:
      schedule:
      - command: /usr/libexec/save-entropy
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['*']
        minute: ['*/11']
        month: ['*']
        user: operator
      - command: newsyslog
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['*']
        minute: ['0']
        month: ['*']
        user: root
      - command: periodic daily
        day_of_month: ['*']
        day_of_week: ['*']
        hour: ['3']
        minute: ['1']
        month: ['*']
        user: root
      - command: periodic weekly
        day_of_month: ['*']
        day_of_week: ['6']
        hour: ['4']
        minute: ['15']
        month: ['*']
        user: root
      - command: periodic monthly
        day_of_month: ['1']
        day_of_week: ['*']
        hour: ['5']
        minute: ['30']
        month: ['*']
        user: root
      - command: adjkerntz -a
        day_of_month: ['*']
        day_of_week: ['*']
        hour: [0-5]
        minute: ['1', '31']
        month: ['*']
        user: root
      variables:
      - {name: PATH, value: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'}
      - {name: SHELL, value: /bin/sh}
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63