From 3657cacfca7b9c46b0046a43ab2b35b5ceffa2a4 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Wed, 29 Aug 2018 10:49:32 +1000 Subject: [PATCH] Add logrotate role and rotate ansible log files Add a logrotate role that allows basic configuration of a logrotate configuration for a specific log-file. Use this role in the ansible-cron and install-ansible roles to ensure the log output they are generating is rotated. This role is not intended to manage the logrotate package (mostly to avoid the overhead of frequently checking package state when this is expected to be called for multiple configuration files on a server). We add it as a base package to our servers. Tests are added for testinfra. Change-Id: I90f59c3e42c1135d6be120de38e942ece608b761 --- playbooks/roles/ansible-cron/tasks/main.yaml | 6 +++ .../roles/base-server/defaults/main.yaml | 1 + .../roles/install-ansible/tasks/main.yaml | 7 +++ playbooks/roles/logrotate/README.rst | 43 +++++++++++++++++++ playbooks/roles/logrotate/defaults/main.yaml | 7 +++ playbooks/roles/logrotate/tasks/main.yaml | 18 ++++++++ .../logrotate/templates/logrotate.conf.j2 | 21 +++++++++ testinfra/test_base.py | 16 +++++++ 8 files changed, 119 insertions(+) create mode 100644 playbooks/roles/logrotate/README.rst create mode 100644 playbooks/roles/logrotate/defaults/main.yaml create mode 100644 playbooks/roles/logrotate/tasks/main.yaml create mode 100644 playbooks/roles/logrotate/templates/logrotate.conf.j2 diff --git a/playbooks/roles/ansible-cron/tasks/main.yaml b/playbooks/roles/ansible-cron/tasks/main.yaml index 0385ebdfff..c25dbea5f6 100644 --- a/playbooks/roles/ansible-cron/tasks/main.yaml +++ b/playbooks/roles/ansible-cron/tasks/main.yaml @@ -19,3 +19,9 @@ day: "{{ update_cron_interval.day }}" month: "{{ update_cron_interval.month }}" weekday: "{{ update_cron_interval.weekday }}" + +- name: Setup log rotation + include_role: + name: logrotate + vars: + logrotate_file_name: /var/log/ansible/run_all_cron.log \ No newline at end of file diff --git a/playbooks/roles/base-server/defaults/main.yaml b/playbooks/roles/base-server/defaults/main.yaml index dbc13b26c3..0da2e7296e 100644 --- a/playbooks/roles/base-server/defaults/main.yaml +++ b/playbooks/roles/base-server/defaults/main.yaml @@ -4,6 +4,7 @@ bastion_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSLlN41ftgxkNeUi/kATYP base_packages: - at - git + - logrotate - lvm2 - ntp - openssh-server diff --git a/playbooks/roles/install-ansible/tasks/main.yaml b/playbooks/roles/install-ansible/tasks/main.yaml index ff43453699..1806e3258b 100644 --- a/playbooks/roles/install-ansible/tasks/main.yaml +++ b/playbooks/roles/install-ansible/tasks/main.yaml @@ -44,3 +44,10 @@ copy: src: openstack.py dest: /etc/ansible/inventory_plugins/openstack.py + + +- name: Setup log rotation + include_role: + name: logrotate + vars: + logrotate_file_name: /var/log/ansible/ansible.log \ No newline at end of file diff --git a/playbooks/roles/logrotate/README.rst b/playbooks/roles/logrotate/README.rst new file mode 100644 index 0000000000..4250a90d70 --- /dev/null +++ b/playbooks/roles/logrotate/README.rst @@ -0,0 +1,43 @@ +Add log rotation file + +.. note:: This role does not manage the ``logrotate`` package or + configuration directory, and it is assumed to be installed + and available. + +This role installs a log rotation file in ``/etc/logrotate.d/`` for a +given file. + +For information on the directives see ``logrotate.conf(5)``. This is +not an exhaustive list of directives (contributions are welcome). + +** Role Variables ** + +.. zuul:rolevar:: logrotate_file_name + + The log file on disk to rotate + +.. zuul:rolevar:: logrotate_config_file_name + :default: Unique name based on :zuul:rolevar::`logrotate.logrotate_file_name` + + The name of the configuration file in ``/etc/logrotate.d`` + +.. zuul:rolevar:: logrotate_compress + :default: yes + +.. zuul:rolevar:: logrotate_copytruncate + :default: yes + +.. zuul:rolevar:: logrotate_delaycompress + :default: yes + +.. zuul:rolevar:: logrotate_missingok + :default: yes + +.. zuul:rolevar:: logrotate_rotate + :default: 7 + +.. zuul:rolevar:: logrotate_daily + :default: yes + +.. zuul:rolevar:: logrotate_notifempty + :default: yes diff --git a/playbooks/roles/logrotate/defaults/main.yaml b/playbooks/roles/logrotate/defaults/main.yaml new file mode 100644 index 0000000000..8f9b815c24 --- /dev/null +++ b/playbooks/roles/logrotate/defaults/main.yaml @@ -0,0 +1,7 @@ +logrotate_compress: yes +logrotate_copytruncate: yes +logrotate_delaycompress: yes +logrotate_missingok: yes +logrotate_rotate: 7 +logrotate_daily: yes +logrotate_notifempty: yes \ No newline at end of file diff --git a/playbooks/roles/logrotate/tasks/main.yaml b/playbooks/roles/logrotate/tasks/main.yaml new file mode 100644 index 0000000000..f2767d9f65 --- /dev/null +++ b/playbooks/roles/logrotate/tasks/main.yaml @@ -0,0 +1,18 @@ +- name: Check for filename + fail: + msg: Must set logrotate_file_name for logfile to rotate + when: logrotate_file_name is not defined + +# Hash the full path to avoid any conflicts but remain idempotent. +# "/var/log/ansible/ansible.log" becomes "ansible.log.37237.conf" for example +- name: Create a unique config name + set_fact: + logrotate_generated_config_file_name: "{{ logrotate_file_name | basename }}.{{ (logrotate_file_name|hash('sha1'))[0:5] }}.conf" + +- name: 'Install {{ logrotate_file_name }} rotatation config file' + template: + src: logrotate.conf.j2 + dest: '/etc/logrotate.d/{{ logrotate_config_file_name|default(logrotate_generated_config_file_name) }}' + owner: root + group: root + mode: 0644 \ No newline at end of file diff --git a/playbooks/roles/logrotate/templates/logrotate.conf.j2 b/playbooks/roles/logrotate/templates/logrotate.conf.j2 new file mode 100644 index 0000000000..0ed1039997 --- /dev/null +++ b/playbooks/roles/logrotate/templates/logrotate.conf.j2 @@ -0,0 +1,21 @@ +{{ logrotate_file_name }} { +{% if logrotate_compress %} + compress +{% endif %} +{% if logrotate_copytruncate %} + copytruncate +{% endif %} +{% if logrotate_delaycompress %} + delaycompress +{% endif %} +{% if logrotate_missingok %} + missingok +{% endif %} + rotate {{ logrotate_rotate }} +{% if logrotate_daily %} + daily +{% endif %} +{% if logrotate_notifempty %} + notifempty +{% endif %} +} diff --git a/testinfra/test_base.py b/testinfra/test_base.py index de39174d56..f0b7dc5783 100644 --- a/testinfra/test_base.py +++ b/testinfra/test_base.py @@ -151,6 +151,22 @@ def test_unattended_upgrades(host): assert cfg_file.contains('apply_updates = yes') +def test_logrotate(host): + '''Check for log rotation configuration files + + The magic number here is [0:5] of the sha1 hash of the full + path to the rotated logfile; the role adds this for uniqueness. + ''' + ansible_vars = host.ansible.get_variables() + if ansible_vars['inventory_hostname'] == 'bridge.openstack.org': + cfg_file = host.file("/etc/logrotate.d/ansible.log.37237.conf") + assert cfg_file.exists + assert cfg_file.contains('/var/log/ansible/ansible.log') + cfg_file = host.file("/etc/logrotate.d/run_all_cron.log.1a953.conf") + assert cfg_file.exists + assert cfg_file.contains('/var/log/ansible/run_all_cron.log') + + def test_openstacksdk_config(host): ansible_vars = host.ansible.get_variables() if ansible_vars['inventory_hostname'] == 'bridge.openstack.org':