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
This commit is contained in:
Ian Wienand 2018-08-29 10:49:32 +10:00
parent 5cb8af4744
commit 3657cacfca
8 changed files with 119 additions and 0 deletions

View File

@ -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

View File

@ -4,6 +4,7 @@ bastion_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSLlN41ftgxkNeUi/kATYP
base_packages:
- at
- git
- logrotate
- lvm2
- ntp
- openssh-server

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 %}
}

View File

@ -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':