etc-git: use "ansible-commit" to efficiently commit all available repositories (including /etc inside LXC) from Ansible

This commit is contained in:
Jérémy Lecour 2022-04-27 14:22:59 +02:00 committed by Jérémy Lecour
parent 381a71aca1
commit 805a8ecb3a
7 changed files with 326 additions and 177 deletions

View file

@ -12,7 +12,7 @@ The **patch** part changes is incremented if multiple releases happen the same m
### Added ### Added
* etc-git: Commit /etc in lxc containers when they are git repositories * etc-git: use "ansible-commit" to efficiently commit all available repositories (including /etc inside LXC) from Ansible
* minifirewall: configure proxy/backup/sysctl values * minifirewall: configure proxy/backup/sysctl values
* nagios-nrpe: Add a check dhcp_pool * nagios-nrpe: Add a check dhcp_pool
* redis : Activate overcommit sysctl * redis : Activate overcommit sysctl

View file

@ -4,3 +4,4 @@ etc_git_default_commit_message: Ansible run
etc_git_monitor_status: True etc_git_monitor_status: True
etc_git_purge_index_lock_enabled: True etc_git_purge_index_lock_enabled: True
etc_git_purge_index_lock_age: 86400 etc_git_purge_index_lock_age: 86400
etc_git_config_repositories: True

View file

@ -0,0 +1,183 @@
#!/bin/sh
set -u
VERSION="22.04"
show_version() {
cat <<END
ansible-commit version ${VERSION}
Copyright 2022 Evolix <info@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
and others.
ansible-commit comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public Licence for details.
END
}
show_help() {
cat <<END
ansible-commit is a wrapper for evocommit, to be used with Ansible
END
show_usage
}
show_usage() {
cat <<END
Usage: ansible-commit --message "add new host"
Options
--message MESSAGE set the commit message
-V, --version print version number
-v, --verbose increase verbosity
-n, --dry-run actions are not executed
--help print this message and exit
--version print version and exit
END
}
is_dry_run() {
test "${DRY_RUN}" = "1"
}
is_verbose() {
test "${VERBOSE}" = "1"
}
main() {
rc=0
common_args="--ansible"
if is_verbose; then
common_args="${common_args} --verbose"
fi
if is_dry_run; then
common_args="${common_args} --dry-run"
fi
if [ -d "/etc/.git" ]; then
# shellcheck disable=SC2086,SC2090
${evocommit_bin} ${common_args} --repository /etc --message "${MESSAGE}"
last_rc=$?
if [ ${last_rc} -ne 0 ]; then
rc=${last_rc}
fi
fi
if [ -d "/etc/bind/.git" ]; then
# shellcheck disable=SC2086,SC2090
${evocommit_bin} ${common_args} --repository /etc/bind --message "${MESSAGE}"
last_rc=$?
if [ ${last_rc} -ne 0 ]; then
rc=${last_rc}
fi
fi
if [ -d "/usr/share/scripts/.git" ]; then
# shellcheck disable=SC2086,SC2090
${evocommit_bin} ${common_args} --repository /usr/share/scripts --message "${MESSAGE}"
last_rc=$?
if [ ${last_rc} -ne 0 ]; then
rc=${last_rc}
fi
fi
if [ -n "${lxc_ls_bin}" ]; then
for container in $(${lxc_ls_bin} -1); do
if [ -n "${lxc_config_bin}" ]; then
# discovered path
etc_path="$(${lxc_config_bin} lxc.lxcpath)/${container}/rootfs/etc"
else
# fallback to default path
etc_path="/var/lib/lxc/${container}/rootfs/etc"
fi
if [ -d "${etc_path}/.git" ]; then
# shellcheck disable=SC2086,SC2090
${evocommit_bin} ${common_args} --repository "${etc_path}" --message "${MESSAGE}"
last_rc=$?
if [ ${last_rc} -ne 0 ]; then
rc=${last_rc}
fi
fi
done
fi
exit ${rc}
}
# Parse options
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
while :; do
case ${1:-''} in
-h|-\?|--help)
show_help
exit 0
;;
-V|--version)
show_version
exit 0
;;
--message)
# message options, with value speparated by space
if [ -n "$2" ]; then
MESSAGE=$2
shift
else
printf 'FAILED: "--message" requires a non-empty option argument.\n' >&2
exit 1
fi
;;
--message=?*)
# message options, with value speparated by =
MESSAGE=${1#*=}
;;
--message=)
# message options, without value
printf 'FAILED: "--message" requires a non-empty option argument.\n' >&2
exit 1
;;
-n|--dry-run)
# disable actual commands
DRY_RUN=1
;;
-v|--verbose)
# print verbose information
VERBOSE=1
;;
--)
# End of all options.
shift
break
;;
-?*|[[:alnum:]]*)
# ignore unknown options
printf 'FAILED: Unknown option (ignored): %s\n' "$1" >&2
;;
*)
# Default case: If no more options then break out of the loop.
break
;;
esac
shift
done
if [ -z "${MESSAGE}" ]; then
echo "FAILED: missing message parameter" >&2
show_usage
exit 1
fi
DRY_RUN=${DRY_RUN:-0}
VERBOSE=${VERBOSE:-0}
evocommit_bin=$(command -v evocommit)
if [ -z "${evocommit_bin}" ]; then
echo "FAILED: evocommit not found" >&2
exit 1
fi
lxc_ls_bin=$(command -v lxc-ls)
lxc_config_bin=$(command -v lxc-config)
main

View file

@ -1,79 +1,9 @@
--- ---
# /etc - name: "Execute ansible-commit"
- name: Is /etc a git repository command: "/usr/local/bin/ansible-commit --verbose --message \"{{ commit_message | mandatory }}\""
stat:
path: /etc/.git
register: _etc_git
- name: "evocommit /etc"
command: "/usr/local/bin/evocommit --ansible --repository /etc --message \"{{ commit_message | mandatory }}\""
changed_when: changed_when:
- _etc_git_commit.stdout - _ansible_commit.stdout
- "'CHANGED:' in _etc_git_commit.stdout" - "'CHANGED:' in _ansible_commit.stdout"
ignore_errors: yes ignore_errors: True
register: _etc_git_commit register: _ansible_commit
when:
- _etc_git.stat.exists
- _etc_git.stat.isdir
# /etc/bind
- name: Is /etc/bind a git repository
stat:
path: /etc/bind/.git
register: _etc_bind_git
- name: "evocommit /etc/bind"
command: "/usr/local/bin/evocommit --ansible --repository /etc/bind --message \"{{ commit_message | mandatory }}\""
changed_when:
- _etc_bind_git_commit.stdout
- "'CHANGED:' in _etc_bind_git_commit.stdout"
ignore_errors: yes
register: _etc_bind_git_commit
when:
- _etc_bind_git.stat.exists
- _etc_bind_git.stat.isdir
# /usr/share/scripts
- name: Is /usr/share/scripts a git repository
stat:
path: /usr/share/scripts/.git
register: _usr_share_scripts_git
- name: "evocommit /usr/share/scripts"
command: "/usr/local/bin/evocommit --ansible --repository /usr/share/scripts --message \"{{ commit_message | mandatory }}\""
changed_when:
- _usr_share_scripts_git_commit.stdout
- "'CHANGED:' in _usr_share_scripts_git_commit.stdout"
ignore_errors: yes
register: _usr_share_scripts_git_commit
when:
- _usr_share_scripts_git.stat.exists
- _usr_share_scripts_git.stat.isdir
- name: Check if there are lxc containers
stat:
path: /var/lib/lxc
get_attributes: no
get_checksum: no
get_mime: no
register: _var_lib_lxc
- name: Get lxc containers and commit their /etc when needed
block:
- name: Get all lxc containers
find:
paths: /var/lib/lxc
recurse: no
file_type: directory
register: _lxc_containers
- name: "Commit /etc in all containers"
include_tasks:
file: lxc_commit.yml
loop: "{{ _lxc_containers.files | map(attribute='path') | map('basename') }}"
loop_control:
loop_var: container
when:
- _var_lib_lxc.stat.exists
- _var_lib_lxc.stat.isdir or _var_lib_lxc.stat.islnk

View file

@ -9,108 +9,13 @@
when: when:
- ansible_distribution == "Debian" - ansible_distribution == "Debian"
- include_role: - name: Install and configure utilities
name: evolix/remount-usr include: utils.yml
- name: "evocommit script is installed"
copy:
src: evocommit
dest: /usr/local/bin/evocommit
mode: "0755"
force: yes
tags: tags:
- etc-git - etc-git
- include: repository.yml - name: Configure repositories
vars: include: repositories.yml
repository_path: "/etc"
gitignore_items:
- "aliases.db"
- "*.swp"
- "postfix/sa-blacklist.access"
- "postfix/*.db"
- "postfix/spamd.cidr"
- "evobackup/.keep-*"
- "letsencrypt/.certbot.lock"
- name: verify /usr/share/scripts presence
stat:
path: /usr/share/scripts
register: _usr_share_scripts
- include: repository.yml
vars:
repository_path: "/usr/share/scripts"
gitignore_items: []
when:
- _usr_share_scripts.stat.isdir
- ansible_distribution_major_version is version('10', '>=')
- name: "etc-git-optimize script is installed"
copy:
src: etc-git-optimize
dest: /usr/share/scripts/etc-git-optimize
mode: "0755"
force: yes
tags: tags:
- etc-git - etc-git
when: etc_git_config_repositories | bool
- name: "etc-git-status script is installed"
copy:
src: etc-git-status
dest: /usr/share/scripts/etc-git-status
mode: "0755"
force: yes
tags:
- etc-git
- name: Check if cron is installed
shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'"
args:
executable: /bin/bash
failed_when: False
changed_when: False
check_mode: no
register: is_cron_installed
- block:
- name: Legacy cron jobs for /etc/.git status are absent
file:
dest: "{{ item }}"
state: absent
loop:
- /etc/cron.monthly/optimize-etc-git
- /etc/cron.d/etc-git-status
- name: Cron job for monthly git optimization
cron:
name: "Monthly optimization"
cron_file: etc-git
special_time: "monthly"
user: root
job: "/usr/share/scripts/etc-git-optimize"
- name: Cron job for hourly git status
cron:
name: "Hourly warning for unclean Git repository if nobody is connected"
cron_file: etc-git
special_time: "hourly"
user: root
job: "who > /dev/null || /usr/share/scripts/etc-git-status"
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
- name: Cron job for daily git status
cron:
name: "Daily warning for unclean Git repository"
cron_file: etc-git
user: root
job: "/usr/share/scripts/etc-git-status"
minute: "21"
hour: "21"
weekday: "*"
day: "*"
month: "*"
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
when: is_cron_installed.rc == 0
tags:
- etc-git

View file

@ -0,0 +1,37 @@
---
- include: repository.yml
vars:
repository_path: "/etc"
gitignore_items:
- "aliases.db"
- "*.swp"
- "postfix/sa-blacklist.access"
- "postfix/*.db"
- "postfix/spamd.cidr"
- "evobackup/.keep-*"
- "letsencrypt/.certbot.lock"
tags:
- etc-git
- name: verify /usr/share/scripts presence
stat:
path: /usr/share/scripts
register: _usr_share_scripts
tags:
- etc-git
- include_role:
name: evolix/remount-usr
when:
- _usr_share_scripts.stat.isdir
- include: repository.yml
vars:
repository_path: "/usr/share/scripts"
gitignore_items: []
when:
- _usr_share_scripts.stat.isdir
- ansible_distribution_major_version is version('10', '>=')
tags:
- etc-git

93
etc-git/tasks/utils.yml Normal file
View file

@ -0,0 +1,93 @@
---
- include_role:
name: evolix/remount-usr
tags:
- etc-git
- name: "evocommit script is installed"
copy:
src: evocommit
dest: /usr/local/bin/evocommit
mode: "0755"
force: yes
tags:
- etc-git
- name: "ansible-commit script is installed"
copy:
src: ansible-commit
dest: /usr/local/bin/ansible-commit
mode: "0755"
force: yes
tags:
- etc-git
- name: "etc-git-optimize script is installed"
copy:
src: etc-git-optimize
dest: /usr/share/scripts/etc-git-optimize
mode: "0755"
force: yes
tags:
- etc-git
- name: "etc-git-status script is installed"
copy:
src: etc-git-status
dest: /usr/share/scripts/etc-git-status
mode: "0755"
force: yes
tags:
- etc-git
- name: Check if cron is installed
shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'"
args:
executable: /bin/bash
failed_when: False
changed_when: False
check_mode: no
register: is_cron_installed
- block:
- name: Legacy cron jobs for /etc/.git status are absent
file:
dest: "{{ item }}"
state: absent
loop:
- /etc/cron.monthly/optimize-etc-git
- /etc/cron.d/etc-git-status
- name: Cron job for monthly git optimization
cron:
name: "Monthly optimization"
cron_file: etc-git
special_time: "monthly"
user: root
job: "/usr/share/scripts/etc-git-optimize"
- name: Cron job for hourly git status
cron:
name: "Hourly warning for unclean Git repository if nobody is connected"
cron_file: etc-git
special_time: "hourly"
user: root
job: "who > /dev/null || /usr/share/scripts/etc-git-status"
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
- name: Cron job for daily git status
cron:
name: "Daily warning for unclean Git repository"
cron_file: etc-git
user: root
job: "/usr/share/scripts/etc-git-status"
minute: "21"
hour: "21"
weekday: "*"
day: "*"
month: "*"
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
when: is_cron_installed.rc == 0
tags:
- etc-git