Skip to content

Commit

Permalink
make purge idempotent; get rid of reset
Browse files Browse the repository at this point in the history
The use of `logging_purge_confs` should be be idempotent.  This is done
by first getting a list of all unowned config files to see if there are
any.  If there are, then the role will remove all unowned config files
not being currently written by the role invocation.  That way, if you
run the role again with `logging_purge_confs: true` and the same
parameters, the role will detect that there should be no changes to the
existing files, and return `changed: false`.

Get rid of `logging_reset_confs` - use only purge.  The way purge
works now is that it will look if the rsyslog package needs to be
reinstalled, by checking if /etc/rsyslog.conf is modified, and the
user has not provided any rsyslog_inputs (because rsyslog_inputs
will trigger /etc/rsyslog.conf to be overwritten if __rsyslog_enabled).
  • Loading branch information
richm committed Jan 27, 2022
1 parent 118fd30 commit 7939bdb
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 110 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,13 @@ These variables are set in the same level of the `logging_inputs`, `logging_outp
- `logging_enabled`: When 'true', logging role will deploy specified configuration file set. Default to 'true'.
- `logging_mark`: Mark message periodically by immark, if set to `true`. Default to `false`.
- `logging_mark_interval`: Interval for `logging_mark` in seconds. Default to `3600`.
- `logging_purge_confs`: `true` or `false`. If `logging_purge_confs` is set to `true`, remove files in rsyslog.d which do not belong to any rpm packages. That includes config files generated by the previous logging role run.
- `logging_reset_confs`: `true` or `false`. If `logging_reset_confs` is set to `true`, reinstall rsyslog package, and restore the pre-existing config files, which restores the default `/etc/rsyslog.conf`.
- `logging_purge_confs`: `true` or `false`. If `logging_purge_confs` is set to
`true`, remove files in rsyslog.d which do not belong to any rpm packages.
That includes config files generated by the previous logging role run. NOTE:
If `/etc/rsyslog.conf` was modified, and you use `logging_purge_confs: true`,
and you are not providing any `logging_inputs`, then the `rsyslog` package
will be uninstalled and reinstalled in order to revert back to the original
system default configuration.
- `logging_system_log_dir`: Directory where the local log output files are placed. Default to `/var/log`.
### Update and Delete
Expand All @@ -430,7 +435,7 @@ logging_flows:
outputs: [output_name1]
```

If you want to remove all the configuration files previously configured, in addition to setting `state: absent` to each logging_inputs and logging_outputs item, add `logging_enabled: false` to the configuration variables as follows. It will eliminate the global and common configuration files, as well.
If you want to remove all the configuration files previously configured, in addition to setting `state: absent` to each logging_inputs and logging_outputs item, add `logging_enabled: false` to the configuration variables as follows. It will eliminate the global and common configuration files, as well. Or, use `logging_purge_confs: true` to wipe out all previous configuration and replace it with your given configuration.

```yaml
logging_enabled: false
Expand Down
9 changes: 3 additions & 6 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ logging_flows: []

# `logging_purge_confs` is set to `true`, remove files in rsyslog.d which do
# not belong to any rpm packages. That includes config files generated by the
# previous logging role run.
# previous logging role run. This will also remove and install the rsyslog
# package in order to revert to the system default /etc/rsyslog.conf if you
# do not provide any logging_inputs
logging_purge_confs: false

# If `logging_reset_confs` is set to `true`, reinstall rsyslog package, and
# restore the pre-existing config files, which restores the default
# `/etc/rsyslog.conf`.
logging_reset_confs: false

# Variable to specify the directory to put the local output files to store logs.
logging_system_log_dir: /var/log

Expand Down
6 changes: 6 additions & 0 deletions roles/rsyslog/tasks/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
- inner_item.options | d() or inner_item.sections | d()
- inner_item.state is undefined or inner_item.state != 'absent'
notify: restart rsyslogd
register: __rsyslog_deploy_templates

- name: add deployed templates to global list
set_fact:
__rsyslog_template_results: "{{
__rsyslog_template_results + [__rsyslog_deploy_templates] }}"

- name: Remove role config files from rsyslog.d
file:
Expand Down
6 changes: 6 additions & 0 deletions roles/rsyslog/tasks/deploy_nolog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
- inner_item.filename | d() or inner_item.name | d()
- inner_item.options | d() or inner_item.sections | d()
notify: restart rsyslogd
register: __rsyslog_deploy_nolog_templates

- name: add deployed templates to global list
set_fact:
__rsyslog_template_results: "{{
__rsyslog_template_results + [__rsyslog_deploy_nolog_templates] }}"

- name: Remove role config files from rsyslog.d with no_log
file:
Expand Down
227 changes: 132 additions & 95 deletions roles/rsyslog/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,50 @@
{{ ansible_facts['distribution_version'] }}.yml"
when: item is file

# if inputs are given and rsyslog_enabled is true, rsyslog.conf will be
# overwritten, so no need to reinstall package
- name: Reinstall package to restore rsyslog config if purging
when:
- logging_purge_confs | bool | d(false)
- not (rsyslog_inputs and __rsyslog_enabled | bool)
block:
# it is assumed that the only packages providing config files that might
# be modified are the base packages - if this is not so, then additional
# packages will need to be added to this check
- name: Get status of rsyslog packages
command: rpm -V {{ item }}
loop: "{{ __rsyslog_base_packages }}"
register: __rsyslog_package_status
failed_when: false
changed_when: false
args:
warn: false

- name: Reset original confs - logging package is absent
package:
name: "{{ __rsyslog_base_packages }}"
state: absent
register: __rsyslog_erased
when: __rsyslog_package_status.results |
rejectattr('stdout', 'match', '^package .* is not installed') |
selectattr('stdout', 'search', ' /etc/rsyslog[.]conf($|\n)') |
list | length > 0

- name: Install/Update required packages
package:
name: "{{ __rsyslog_base_packages }} + {{ __rsyslog_tls_packages
if (logging_pki_files | d([]) | length > 0) else [] }} +
{{ rsyslog_extra_packages | flatten }}"
state: present
when:
- __rsyslog_enabled | bool
- __rsyslog_enabled | bool or
(__rsyslog_erased is success and __rsyslog_erased is changed)

# make sure we do not pollute the global namespace for subsequent runs
# of this role
- name: Reset erased flag
set_fact:
__rsyslog_erased: false

- name: Gather package facts
package_facts:
Expand Down Expand Up @@ -66,46 +102,6 @@
path: '{{ __rsyslog_work_dir }}'
mode: '0700'

# If logging_purge_confs is set to true, remove files in rsyslog.d
# which do not belong to any rpm packages. That includes config
# files generated by the previous logging role run.
# If logging_reset_confs is set to true, reinstall rsyslog package,
# and restore the pre-existing config files, which restores the
# default /etc/rsyslog.conf.
- name: >-
Purge original conf - remove confs with no owner package and
confs generated by previous logging role.
shell: |-
set -euo pipefail
for conf in $( ls "{{ __rsyslog_config_dir }}" ); do
rstr=$( rpm -qf "{{ __rsyslog_config_dir }}/$conf" 2>&1 || : )
if [[ $rstr == *"not owned by any package"* ]]; then
# confs generated by the logging role do not belong to
# any rpm packages.
/usr/bin/rm -f "{{ __rsyslog_config_dir }}/$conf"
fi
done
when: logging_purge_confs | bool | d(false)
- block:
- name: Reset original confs - logging package is absent
package:
name: "{{ __rsyslog_base_packages }}"
state: absent

- name: Reset original confs - logging package is present
package:
name: "{{ __rsyslog_base_packages }}"
state: present
rescue:
- name: Reset original configuration files failed
fail:
msg: >
Error: Reset {{ __rsyslog_base_packages }} failed.
Please ensure the package(s) are available to install
from the repository.
when: logging_reset_confs | bool | d(false)

- name: "Create logging directory if it does not exist or
the ownership and/or modes are different."
file:
Expand Down Expand Up @@ -175,6 +171,11 @@
- inner_item.state is undefined or inner_item.state != 'absent'
- inner_item.options | d() or inner_item.sections | d()
notify: restart rsyslogd
register: __rsyslog_templates

- name: Initialize list of template results
set_fact:
__rsyslog_template_results: "{{ [__rsyslog_templates] }}"

- name: Remove common config files in rsyslog.d
file:
Expand All @@ -194,6 +195,96 @@
- inner_item.options | d() or inner_item.sections | d()
notify: stop rsyslogd

- name: Include input sub-vars
include_vars:
file: "{{ role_path }}/vars/{{ varfile }}"
vars:
varfile: "inputs/{{ input_item.type }}/main.yml"
loop: "{{ rsyslog_inputs }}"
loop_control:
loop_var: input_item
when:
- input_item | d([])

- name: Run input sub-tasks
include_tasks:
file: "{{ tasks }}"
vars:
tasks: "{{ role_path }}/tasks/inputs/{{ input_item.type }}/main.yml"
__rsyslog_input: "{{ input_item }}"
loop: '{{ rsyslog_inputs | sort(attribute="type") }}'
loop_control:
extended: yes
loop_var: input_item
when:
- input_item | d([])
- input_item.type | d()
- input_item.type != "basics" or
(input_item.type == "basics" and
(ansible_loop.previtem is not defined or
(ansible_loop.previtem is defined and
ansible_loop.previtem.type != 'basics')))

- name: Include output sub-vars
include_vars:
file: "{{ role_path }}/vars/{{ varfile }}"
vars:
varfile: "outputs/{{ output_item.type }}/main.yml"
loop: "{{ rsyslog_outputs }}"
loop_control:
loop_var: output_item
when:
- output_item | d([])
- output_item.type | d()

- name: Run output sub-tasks
include_tasks:
file: "{{ tasks }}"
vars:
tasks: "{{ role_path }}/tasks/outputs/{{ output_item.type }}/main.yml"
__rsyslog_output: "{{ output_item }}"
loop: "{{ rsyslog_outputs }}"
loop_control:
loop_var: output_item
when:
- output_item | d([])

- name: Get rsyslog config files not owned by any package
shell: |
set -euo pipefail
for conf in $( ls "{{ __rsyslog_config_dir }}" ); do
rstr=$( rpm -qf "{{ __rsyslog_config_dir }}/$conf" 2>&1 || : )
if [[ "$rstr" == *"not owned by any package"* ]]; then
echo "{{ __rsyslog_config_dir }}/$conf"
fi
done
register: __rsyslog_confs
failed_when: false
changed_when: false
when: logging_purge_confs | bool | d(false)

# If logging_purge_confs is set to true, remove files in rsyslog.d
# which do not belong to any rpm packages. That includes config
# files generated by the previous logging role run.
- name: Purge - remove files not generated by current state
file:
path: "{{ item }}"
state: absent
loop: "{{ __rsyslog_files_to_remove }}"
notify: "{{ 'restart rsyslogd' if logging_enabled else 'stop rsyslogd' }}"
when:
- logging_purge_confs | bool | d(false)
- __rsyslog_files_to_remove | length > 0
vars:
__rsyslog_current_files: "{{ __rsyslog_template_results |
selectattr('results', 'defined') | map(attribute='results') |
flatten | selectattr('dest', 'defined') | map(attribute='dest') |
list | to_nice_json
}}"
__rsyslog_files_to_remove: "{{
__rsyslog_confs.stdout_lines | difference(__rsyslog_current_files)
}}"

# How to set rsyslog_custom_config_files:
# rsyslog_custom_config_files:
# - /path/to/custom0.conf
Expand Down Expand Up @@ -292,60 +383,6 @@
when:
- __rsyslog_enabled | bool

- name: Include input sub-vars
include_vars:
file: "{{ role_path }}/vars/{{ varfile }}"
vars:
varfile: "inputs/{{ input_item.type }}/main.yml"
loop: "{{ rsyslog_inputs }}"
loop_control:
loop_var: input_item
when:
- input_item | d([])

- name: Run input sub-tasks
include_tasks:
file: "{{ tasks }}"
vars:
tasks: "{{ role_path }}/tasks/inputs/{{ input_item.type }}/main.yml"
__rsyslog_input: "{{ input_item }}"
loop: '{{ rsyslog_inputs | sort(attribute="type") }}'
loop_control:
extended: yes
loop_var: input_item
when:
- input_item | d([])
- input_item.type | d()
- input_item.type != "basics" or
(input_item.type == "basics" and
(ansible_loop.previtem is not defined or
(ansible_loop.previtem is defined and
ansible_loop.previtem.type != 'basics')))

- name: Include output sub-vars
include_vars:
file: "{{ role_path }}/vars/{{ varfile }}"
vars:
varfile: "outputs/{{ output_item.type }}/main.yml"
loop: "{{ rsyslog_outputs }}"
loop_control:
loop_var: output_item
when:
- output_item | d([])
- output_item.type | d()

- name: Run output sub-tasks
include_tasks:
file: "{{ tasks }}"
vars:
tasks: "{{ role_path }}/tasks/outputs/{{ output_item.type }}/main.yml"
__rsyslog_output: "{{ output_item }}"
loop: "{{ rsyslog_outputs }}"
loop_control:
loop_var: output_item
when:
- output_item | d([])

- name: Enable rsyslog service
service:
name: rsyslog
Expand Down
1 change: 0 additions & 1 deletion tests/tests_basics_files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,6 @@

- name: END TEST CASE 3; Clean up the deployed config
vars:
logging_reset_confs: true
logging_enabled: false
logging_outputs:
- name: files_output0
Expand Down
2 changes: 1 addition & 1 deletion tests/tests_basics_forwards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@

- name: END TEST CASE 2; Clean up the deployed config
vars:
logging_reset_confs: true
logging_enabled: false
logging_purge_confs: true
logging_pki_files:
- ca_cert_src: "{{ __test_ca_cert }}"
cert_src: "{{ __test_cert }}"
Expand Down
Loading

0 comments on commit 7939bdb

Please sign in to comment.