diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b4a350..1e398916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,48 @@ The **patch** part changes incrementally at each release. ### Security +## [10.6.0] 2021-06-28 + +### Added + +* Add Elastic GPG key to kibana, filebeat, logstash, metricbeat roles +* apache: new variable for mpm mode (+ updated default config accordingly) +* evolinux-base: add default motd template +* kvm-host: add migrate-vm script +* mysql: variable to disable myadd script overwrite (default: True) +* nodejs: update apt cache before installing the package +* squid: add Yarn apt repository in default whitelist + +### Changed + +* Update Galaxy metadata (company, platforms and galaxy_tags) +* Use 'loop' syntax instead of 'with_first_found/with_items/with_dict/with_nested/with_list' +* Use Ansible syntax used in Ansible 2.8+ +* apt: store keys in /etc/apt/trusted.gpg.d in ascii format +* certbot: sync_remote.sh is configurable +* evolinux-base: copy GPG key instead of using apt-key +* evomaintenance: upstream release 0.6.4 +* kvm-host: replace the "kvm-tools" package with scripts deployed by Ansible +* listupgrade: upstream release 21.06.2 +* nodejs: change GPG key name +* ntpd: Add leapfile configuration setting to ntpd on debian 10+ +* packweb-apache: install phpMyAdmin from buster-backports +* spamassassin: change dependency on evomaintenance +* squid: remove obsolete variable on Squid 4 + +### Fixed + +* add default (useless) value for file lookup (first_found) +* fix pipefail option for shell invocations +* elasticsearch: inline YAML formatting of seed_hosts and initial_master_nodes +* evolinux-base: fix motd lookup path +* ldap: fix edge cases where passwords were not set/get properly +* listupgrade: fix wget error + shellcheck cleanup + +### Removed + +* elasticsearch: recent versiond don't depend on external JRE + ## [10.5.1] 2021-04-13 ### Added @@ -37,7 +79,7 @@ The **patch** part changes incrementally at each release. * apache: new variables for logrotate + server-status * filebeat: package can be upgraded to latest (default: False) * haproxy: possible admin access with login/pass -* lxc-php: Add PHP 7.4 support +* lxc-php: Add PHP 7.4 support * metricbeat: package can be upgraded to latest (default: False) * metricbeat: new variables to configure SSL mode * nagios-nrpe: new script check_phpfpm_multi @@ -110,7 +152,7 @@ The **patch** part changes incrementally at each release. * tomcat-instance: fail if uid already exists * varnish: change template name for better readability * varnish: no threadpool delay by default -* varnish: no custom reload script for Debian 10 and later +* varnish: no custom reload script for Debian 10 and later ### Fixed diff --git a/amazon-ec2/tasks/create-instance.yml b/amazon-ec2/tasks/create-instance.yml index 470cac72..a3f84b1a 100644 --- a/amazon-ec2/tasks/create-instance.yml +++ b/amazon-ec2/tasks/create-instance.yml @@ -21,11 +21,11 @@ groupname: launched-instances ansible_user: admin ansible_ssh_common_args: "-o StrictHostKeyChecking=no" - with_items: "{{ec2.instances}}" + loop: "{{ec2.instances}}" - debug: msg: "Your newly created instance is reachable at: {{item.public_dns_name}}" - with_items: "{{ec2.instances}}" + loop: "{{ec2.instances}}" - name: Wait for SSH to come up on all instances (give up after 2m) wait_for: @@ -33,4 +33,4 @@ host: "{{item.public_dns_name}}" port: 22 timeout: 120 - with_items: "{{ec2.instances}}" + loop: "{{ec2.instances}}" diff --git a/apache/defaults/main.yml b/apache/defaults/main.yml index e49dbc20..7b58ea3f 100644 --- a/apache/defaults/main.yml +++ b/apache/defaults/main.yml @@ -23,3 +23,5 @@ log2mail_alert_email: Null apache_logrotate_frequency: daily apache_logrotate_rotate: 365 + +apache_mpm: "itk" \ No newline at end of file diff --git a/apache/files/evolinux-custom.conf b/apache/files/evolinux-custom.conf index 64d8f97a..b5ed3a77 100644 --- a/apache/files/evolinux-custom.conf +++ b/apache/files/evolinux-custom.conf @@ -24,3 +24,6 @@ SetEnvIf User-Agent "ApacheBench" GoAway=1 # # Header set Access-Control-Allow-Origin "*" # + +# you need disable EnableCapabilities to use data on NFS mounts +#EnableCapabilities off diff --git a/apache/files/evolinux-defaults.conf b/apache/files/evolinux-defaults.conf index e5eadda8..06e28d9e 100644 --- a/apache/files/evolinux-defaults.conf +++ b/apache/files/evolinux-defaults.conf @@ -3,12 +3,43 @@ Timeout 10 KeepAliveTimeout 2 MaxKeepAliveRequests 10 #MaxClients 250 -MaxRequestWorkers 250 -ServerLimit 250 -StartServers 50 -MinSpareServers 20 -MaxSpareServers 30 -MaxRequestsPerChild 0 + + + MaxRequestWorkers 250 + ServerLimit 250 + StartServers 50 + MinSpareServers 20 + MaxSpareServers 30 + MaxRequestsPerChild 0 + + + + StartServers 3 + MinSpareThreads 25 + MaxSpareThreads 75 + ThreadLimit 64 + ThreadsPerChild 25 + MaxRequestWorkers 150 + MaxConnectionsPerChild 0 + + + + LimitUIDRange 0 6000 + LimitGIDRange 0 6000 + + + + SSLProtocol all -SSLv2 -SSLv3 + SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!RC4 + + + + ExtendedStatus On + + ProxyStatus On + + + AllowOverride None @@ -17,26 +48,11 @@ MaxRequestsPerChild 0 Deny from env=GoAway - - SSLProtocol all -SSLv2 -SSLv3 - SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!RC4 - Require all denied - - ExtendedStatus On - - ProxyStatus On - - - - - LimitUIDRange 0 6000 - LimitGIDRange 0 6000 - Require all denied diff --git a/apache/files/save_apache_status.sh b/apache/files/save_apache_status.sh index 8ca29f15..12f8faed 100644 --- a/apache/files/save_apache_status.sh +++ b/apache/files/save_apache_status.sh @@ -4,7 +4,7 @@ set -e DIR="/var/log/apache-status" URL="http://127.0.0.1/server-status" -TS=`date +%Y%m%d%H%M%S` +TS=$(date +%Y%m%d%H%M%S) FILE="${DIR}/${TS}.html" if [ ! -d "${DIR}" ]; then diff --git a/apache/meta/main.yml b/apache/meta/main.yml index 3f717653..c4daabd5 100644 --- a/apache/meta/main.yml +++ b/apache/meta/main.yml @@ -1,18 +1,24 @@ +--- galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Apache issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # Be sure to remove the '[]' above if you add dependencies + # to this list. dependencies: [] # List your role dependencies here, one per line. diff --git a/apache/tasks/auth.yml b/apache/tasks/auth.yml index b785c704..fd01517c 100644 --- a/apache/tasks/auth.yml +++ b/apache/tasks/auth.yml @@ -10,7 +10,7 @@ force: no tags: - apache - + - name: Load IP whitelist task include: ip_whitelist.yml @@ -40,7 +40,7 @@ dest: /etc/apache2/private_htpasswd line: "{{ item }}" state: present - with_items: "{{ apache_private_htpasswd_present }}" + loop: "{{ apache_private_htpasswd_present }}" notify: reload apache tags: - apache @@ -50,7 +50,7 @@ dest: /etc/apache2/private_htpasswd line: "{{ item }}" state: absent - with_items: "{{ apache_private_htpasswd_absent }}" + loop: "{{ apache_private_htpasswd_absent }}" notify: reload apache tags: - apache diff --git a/apache/tasks/ip_whitelist.yml b/apache/tasks/ip_whitelist.yml index ac2b6f87..18f4a681 100644 --- a/apache/tasks/ip_whitelist.yml +++ b/apache/tasks/ip_whitelist.yml @@ -5,7 +5,7 @@ dest: /etc/apache2/ipaddr_whitelist.conf line: "Require ip {{ item }}" state: present - with_items: "{{ apache_ipaddr_whitelist_present }}" + loop: "{{ apache_ipaddr_whitelist_present }}" notify: reload apache tags: - apache @@ -16,7 +16,7 @@ dest: /etc/apache2/ipaddr_whitelist.conf line: "Require ip {{ item }}" state: absent - with_items: "{{ apache_ipaddr_whitelist_absent }}" + loop: "{{ apache_ipaddr_whitelist_absent }}" notify: reload apache tags: - apache diff --git a/apache/tasks/main.yml b/apache/tasks/main.yml index 3854c539..1a028205 100644 --- a/apache/tasks/main.yml +++ b/apache/tasks/main.yml @@ -4,7 +4,6 @@ apt: name: - apache2 - - libapache2-mpm-itk - libapache2-mod-evasive - apachetop - libwww-perl @@ -14,6 +13,18 @@ - packages when: ansible_distribution_major_version is version('9', '>=') +- name: itk package is installed if required (Debian 9 or later) + apt: + name: + - libapache2-mpm-itk + state: present + tags: + - apache + - packages + when: + - ansible_distribution_major_version is version('9', '>=') + - apache_mpm == "itk" + - name: packages are installed (jessie) apt: name: @@ -31,11 +42,10 @@ apache2_module: name: '{{ item }}' state: present - with_items: + loop: - rewrite - expires - headers - - cgi - ssl - include - negotiation @@ -44,6 +54,18 @@ tags: - apache +- name: basic modules are enabled + apache2_module: + name: '{{ item }}' + state: present + loop: + - cgi + notify: reload apache + when: apache_mpm == "prefork" or apache_mpm == "itk" + tags: + - apache + + - name: Copy Apache defaults config file copy: src: evolinux-defaults.conf @@ -80,7 +102,7 @@ command: "a2enconf {{ item }}" register: command_result changed_when: "'Enabling' in command_result.stderr" - with_items: + loop: - z-evolinux-defaults.conf - zzz-evolinux-custom.conf notify: reload apache @@ -108,7 +130,7 @@ state: link force: yes notify: reload apache - when: apache_evolinux_default_enabled + when: apache_evolinux_default_enabled | bool tags: - apache @@ -183,6 +205,6 @@ - apache - include: munin.yml - when: apache_munin_include + when: apache_munin_include | bool tags: - apache diff --git a/apache/tasks/munin.yml b/apache/tasks/munin.yml index 144ae0f8..fe07a5cf 100644 --- a/apache/tasks/munin.yml +++ b/apache/tasks/munin.yml @@ -15,7 +15,7 @@ src: "/usr/share/munin/plugins/{{ item }}" dest: "/etc/munin/plugins/{{ item }}" state: link - with_items: + loop: - apache_accesses - apache_processes - apache_volume diff --git a/apache/tasks/server_status.yml b/apache/tasks/server_status.yml index 1d6cd8df..2ca77951 100644 --- a/apache/tasks/server_status.yml +++ b/apache/tasks/server_status.yml @@ -14,7 +14,7 @@ # The last character "\u000A" is a line feed (LF), it's better to keep it content: "{{ apache_serverstatus_suffix }}\u000A" force: yes - when: apache_serverstatus_suffix != "" + when: apache_serverstatus_suffix | length > 0 - name: generate random string for server-status suffix shell: "apg -a 1 -M N -n 1 > {{ apache_serverstatus_suffix_file }}" diff --git a/apt/files/reg.asc b/apt/files/reg.asc new file mode 100644 index 00000000..3fadeb07 --- /dev/null +++ b/apt/files/reg.asc @@ -0,0 +1,920 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.6 +Comment: Hostname: keyserver.ubuntu.com + +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 +BWcdiQ== +=iUyJ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/apt/files/reg.gpg b/apt/files/reg.gpg index 3fadeb07..48782d84 100644 Binary files a/apt/files/reg.gpg and b/apt/files/reg.gpg differ diff --git a/apt/meta/main.yml b/apt/meta/main.yml index b9fd3b76..c1872414 100644 --- a/apt/meta/main.yml +++ b/apt/meta/main.yml @@ -1,17 +1,23 @@ galaxy_info: - author: Evolix + company: Evolix description: Add repositories to APT sources list. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # Be sure to remove the '[]' above if you add dependencies + # to this list. dependencies: [] # List your role dependencies here, one per line. diff --git a/apt/tasks/basics.yml b/apt/tasks/basics.yml index 3b9aadd6..fee1430a 100644 --- a/apt/tasks/basics.yml +++ b/apt/tasks/basics.yml @@ -14,13 +14,13 @@ file: path: '{{ item }}' state: absent - with_items: + loop: - /etc/apt/sources.list.d/debian-security.list - /etc/apt/sources.list.d/debian-jessie.list - /etc/apt/sources.list.d/debian-stretch.list - /etc/apt/sources.list.d/debian-buster.list - /etc/apt/sources.list.d/debian-update.list - when: apt_clean_gandi_sourceslist + when: apt_clean_gandi_sourceslist | bool tags: - apt diff --git a/apt/tasks/config.yml b/apt/tasks/config.yml index 48892b9e..4d7372fc 100644 --- a/apt/tasks/config.yml +++ b/apt/tasks/config.yml @@ -8,11 +8,11 @@ create: yes state: present mode: "0640" - with_items: + loop: - { line: "APT::Install-Recommends \"false\";", regexp: 'APT::Install-Recommends' } - { line: "APT::Install-Suggests \"false\";", regexp: 'APT::Install-Suggests' } - { line: "APT::Periodic::Enable \"0\";", regexp: 'APT::Periodic::Enable' } - when: apt_evolinux_config + when: apt_evolinux_config | bool tags: - apt @@ -23,12 +23,12 @@ create: yes state: present mode: "0640" - with_items: + loop: - "DPkg::Pre-Invoke { \"df /tmp | grep -q /tmp && mount -oremount,exec /tmp || true\"; };" - "DPkg::Pre-Invoke { \"df /usr | grep -q /usr && mount -oremount,rw /usr || true\"; };" - "DPkg::Post-Invoke { \"df /tmp | grep -q /tmp && mount -oremount /tmp || true\"; };" - "DPkg::Post-Invoke { \"df /usr | grep -q /usr && mount -oremount /usr || true\"; };" - when: apt_hooks + when: apt_hooks | bool tags: - apt @@ -36,7 +36,7 @@ apt: name: aptitude state: absent - when: apt_remove_aptitude + when: apt_remove_aptitude | bool tags: - apt @@ -50,6 +50,6 @@ - name: Upgrading system apt: upgrade: dist - when: apt_upgrade + when: apt_upgrade | bool tags: - apt diff --git a/apt/tasks/evolix_public.yml b/apt/tasks/evolix_public.yml index 0edb2ec8..00067f46 100644 --- a/apt/tasks/evolix_public.yml +++ b/apt/tasks/evolix_public.yml @@ -1,17 +1,21 @@ --- -# - name: Fail if distribution is not supported -# fail: -# msg: "Error: Evolix public repository is not compatble with 'Debian Stretch' yet." -# when: ansible_distribution_release == "stretch" -# tags: -# - apt - +- name: Evolix embedded GPG key is absent + apt_key: + id: "B8612B5D" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - apt - name: Add Evolix GPG key - apt_key: - #url: http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x44975278B8612B5D - data: "{{ lookup('file', 'reg.gpg') }}" + copy: + src: reg.asc + dest: /etc/apt/trusted.gpg.d/reg.asc + force: yes + mode: "0644" + owner: root + group: root tags: - apt diff --git a/apt/tasks/hold_packages.yml b/apt/tasks/hold_packages.yml index f93c34a7..691f3763 100644 --- a/apt/tasks/hold_packages.yml +++ b/apt/tasks/hold_packages.yml @@ -1,10 +1,15 @@ --- - name: "hold packages (apt)" - shell: "(dpkg -l {{ item }} 2>/dev/null | grep -q -E '^(i|h)i') && ((apt-mark showhold | grep --quiet {{ item }}) || apt-mark hold {{ item }})" + shell: "set -o pipefail && (dpkg -l {{ item }} 2>/dev/null | grep -q -E '^(i|h)i') && ((apt-mark showhold | grep --quiet {{ item }}) || apt-mark hold {{ item }})" + args: + executable: /bin/bash + check_mode: no register: apt_mark changed_when: "item + ' set on hold.' in apt_mark.stdout" - failed_when: apt_mark.rc != 0 and not apt_mark.stdout == '' + failed_when: + - apt_mark.rc != 0 + - apt_mark.stdout | length > 0 loop: "{{ apt_hold_packages }}" tags: - apt @@ -28,7 +33,10 @@ - apt - name: "unhold packages (apt)" - shell: "(dpkg -l {{ item }} 2>/dev/null | grep -q -E '^(i|h)i') && ((apt-mark showhold | grep --quiet {{ item }}) && apt-mark unhold {{ item }})" + shell: "set -o pipefail && (dpkg -l {{ item }} 2>/dev/null | grep -q -E '^(i|h)i') && ((apt-mark showhold | grep --quiet {{ item }}) && apt-mark unhold {{ item }})" + args: + executable: /bin/bash + check_mode: no register: apt_mark changed_when: "'Canceled hold on' + item in apt_mark.stdout" failed_when: apt_mark.rc != 0 and not apt_mark.stdout = '' diff --git a/apt/tasks/main.yml b/apt/tasks/main.yml index 92f06856..118f8ef9 100644 --- a/apt/tasks/main.yml +++ b/apt/tasks/main.yml @@ -10,30 +10,30 @@ - name: Custom configuration include: config.yml - when: apt_config + when: apt_config | bool tags: - apt - name: Install basics repositories include: basics.yml - when: apt_install_basics + when: apt_install_basics | bool tags: - apt - name: Install APT Backports repository include: backports.yml - when: apt_install_backports + when: apt_install_backports | bool tags: - apt - name: Install Evolix Public APT repository include: evolix_public.yml - when: apt_install_evolix_public + when: apt_install_evolix_public | bool tags: - apt - name: Install check for packages marked hold include: hold_packages.yml - when: apt_install_hold_packages + when: apt_install_hold_packages | bool tags: - apt diff --git a/bind/meta/main.yml b/bind/meta/main.yml index 5f082615..6cf180b1 100644 --- a/bind/meta/main.yml +++ b/bind/meta/main.yml @@ -1,17 +1,23 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of bind9. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # Be sure to remove the '[]' above if you add dependencies + # to this list. dependencies: [] # List your role dependencies here, one per line. diff --git a/bind/tasks/main.yml b/bind/tasks/main.yml index c5b9110c..d1348cd2 100644 --- a/bind/tasks/main.yml +++ b/bind/tasks/main.yml @@ -6,7 +6,7 @@ bind_cache_dir: /var/cache/bind bind_statistics_file: /var/run/named.stats bind_chroot_path: /var/chroot-bind - when: bind_chroot_set + when: bind_chroot_set | bool - name: configure apparmor template: @@ -34,7 +34,7 @@ mode: "0644" force: yes notify: restart bind - when: bind_recursive_server + when: bind_recursive_server | bool - name: enable zones.rfc1918 for recursive server lineinfile: @@ -42,7 +42,7 @@ line: 'include "/etc/bind/zones.rfc1918";' regexp: "zones.rfc1918" notify: restart bind - when: bind_recursive_server + when: bind_recursive_server | bool - name: Set bind configuration for authoritative server template: @@ -53,7 +53,7 @@ mode: "0644" force: yes notify: restart bind - when: bind_authoritative_server + when: bind_authoritative_server | bool - name: Create systemd service template: @@ -75,7 +75,7 @@ group: adm mode: "0640" state: touch - when: not bind_chroot_set + when: not (bind_chroot_set | bool) - name: "touch {{ bind_query_file }} if non chroot" file: @@ -84,7 +84,7 @@ group: adm mode: "0640" state: touch - when: not bind_chroot_set + when: not (bind_chroot_set | bool) - name: send chroot-bind.sh in /root copy: @@ -94,17 +94,19 @@ owner: root force: yes backup: yes - when: bind_chroot_set + when: bind_chroot_set | bool - name: exec chroot-bind.sh command: "/root/chroot-bind.sh" register: chrootbind_run changed_when: False - when: bind_chroot_set + when: bind_chroot_set | bool - debug: var: chrootbind_run.stdout_lines - when: bind_chroot_set and chrootbind_run.stdout != "" + when: + - bind_chroot_set | bool + - chrootbind_run.stdout | length > 0 - name: Modify OPTIONS in /etc/default/bind9 for chroot replace: @@ -112,7 +114,7 @@ regexp: '^OPTIONS=.*' replace: 'OPTIONS="-u bind -t {{ bind_chroot_path }}"' notify: restart bind - when: bind_chroot_set + when: bind_chroot_set | bool - name: logrotate for bind template: diff --git a/bind/tasks/munin.yml b/bind/tasks/munin.yml index 5f9da280..f97ddf85 100644 --- a/bind/tasks/munin.yml +++ b/bind/tasks/munin.yml @@ -14,7 +14,7 @@ src: "/usr/share/munin/plugins/{{ item }}" dest: "/etc/munin/plugins/{{ item }}" state: link - with_items: + loop: - bind9 - bind9_rndc notify: restart munin-node @@ -30,7 +30,7 @@ src: "/usr/share/munin/plugins/{{ item }}" dest: "/etc/munin/plugins/{{ item }}" state: link - with_items: + loop: - bind9 - bind9_rndc notify: restart munin-node diff --git a/certbot/defaults/main.yml b/certbot/defaults/main.yml index 99f02e15..2d198b43 100644 --- a/certbot/defaults/main.yml +++ b/certbot/defaults/main.yml @@ -2,3 +2,5 @@ certbot_work_dir: /var/lib/letsencrypt certbot_custom_crontab: True + +certbot_hooks_sync_remote_servers: [] \ No newline at end of file diff --git a/certbot/files/hooks/apache.sh b/certbot/files/hooks/deploy/apache.sh similarity index 100% rename from certbot/files/hooks/apache.sh rename to certbot/files/hooks/deploy/apache.sh diff --git a/certbot/files/hooks/dovecot.sh b/certbot/files/hooks/deploy/dovecot.sh similarity index 100% rename from certbot/files/hooks/dovecot.sh rename to certbot/files/hooks/deploy/dovecot.sh diff --git a/certbot/files/hooks/haproxy.sh b/certbot/files/hooks/deploy/haproxy.sh similarity index 100% rename from certbot/files/hooks/haproxy.sh rename to certbot/files/hooks/deploy/haproxy.sh diff --git a/certbot/files/hooks/nginx.sh b/certbot/files/hooks/deploy/nginx.sh similarity index 100% rename from certbot/files/hooks/nginx.sh rename to certbot/files/hooks/deploy/nginx.sh diff --git a/certbot/files/hooks/postfix.sh b/certbot/files/hooks/deploy/postfix.sh similarity index 100% rename from certbot/files/hooks/postfix.sh rename to certbot/files/hooks/deploy/postfix.sh diff --git a/certbot/files/hooks/sync_remote.sh b/certbot/files/hooks/deploy/sync_remote.sh similarity index 54% rename from certbot/files/hooks/sync_remote.sh rename to certbot/files/hooks/deploy/sync_remote.sh index d041f895..08006b38 100644 --- a/certbot/files/hooks/sync_remote.sh +++ b/certbot/files/hooks/deploy/sync_remote.sh @@ -29,20 +29,22 @@ main() { if found_renewed_lineage; then RENEWED_DOMAINS=${RENEWED_DOMAINS:-$(domain_from_cert)} - remore_lineage=${remote_dir}/renewed_lineage/$(basename ${RENEWED_LINEAGE}) + remote_lineage=${remote_dir}/renewed_lineage/$(basename "${RENEWED_LINEAGE}") for server in ${servers}; do remote_host="root@${server}" - ssh ${remote_host} "mkdir -p ${remote_dir}" \ + # shellcheck disable=SC2029 + ssh "${remote_host}" "mkdir -p ${remote_lineage}" \ || error "Couldn't create ${remote_dir} directory ${server}" - rsync --archive --copy-links --delete ${RENEWED_LINEAGE}/ ${remote_host}:${remore_lineage}/ \ + rsync --archive --copy-links --delete "${RENEWED_LINEAGE}/" "${remote_host}:${remote_lineage}/" \ || error "Couldn't sync certificate on ${server}" - rsync --archive --copy-links --delete --exclude $0 --delete-excluded ${hooks_dir}/ ${remote_host}:${remote_dir}/hooks/ \ + rsync --archive --copy-links --delete --exclude $0 --delete-excluded "${hooks_dir}/" "${remote_host}:${remote_dir}/hooks/" \ || error "Couldn't sync hooks on ${server}" - ssh ${remote_host} "export RENEWED_LINEAGE=\"${remore_lineage}/\" RENEWED_DOMAINS=${RENEWED_DOMAINS}; find ${remote_dir}/hooks/ -mindepth 1 -maxdepth 1 -type f -executable -exec {} \;" \ + # shellcheck disable=SC2029 + ssh "${remote_host}" "export RENEWED_LINEAGE=\"${remote_lineage}/\" RENEWED_DOMAINS=${RENEWED_DOMAINS}; find ${remote_dir}/hooks/ -mindepth 1 -maxdepth 1 -type f -executable -exec {} \;" \ || error "Something went wrong on ${server} for deploy hooks" done else @@ -50,13 +52,23 @@ main() { fi } -readonly PROGNAME=$(basename "$0") -readonly VERBOSE=${VERBOSE:-"0"} -readonly QUIET=${QUIET:-"0"} +PROGNAME=$(basename "$0") +VERBOSE=${VERBOSE:-"0"} +QUIET=${QUIET:-"0"} -readonly hooks_dir="/etc/letsencrypt/renewal-hooks/deploy" -readonly remote_dir="/root/cert_sync" +hooks_dir="/etc/letsencrypt/renewal-hooks/deploy" +# The config file lust have the same name as the script, with a different extension (.cf instead of .sh) +config_file="${0%.*}.cf" +remote_dir="/root/cert_sync" -readonly servers="" +if [ -f "${config_file}" ]; then + . "${config_file}" +fi +servers=${servers:-""} + +if [ -z "${servers}" ]; then + echo "${PROGNAME}: No server provided. Skip." >&2 + exit 0 +fi main diff --git a/certbot/files/hooks/z-commit-etc.sh b/certbot/files/hooks/deploy/z-commit-etc.sh similarity index 100% rename from certbot/files/hooks/z-commit-etc.sh rename to certbot/files/hooks/deploy/z-commit-etc.sh diff --git a/certbot/files/letsencrypt-auto b/certbot/files/letsencrypt-auto index 2a0cda9b..0e26e29a 100644 --- a/certbot/files/letsencrypt-auto +++ b/certbot/files/letsencrypt-auto @@ -497,7 +497,7 @@ Python36SclIsAvailable() { # Try to enable rh-python36 from SCL if it is necessary and possible. EnablePython36SCL() { - if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then + if "$EXISTS" python3.6 > /dev/null 2>/dev/null; then return 0 fi if [ ! -f /opt/rh/rh-python36/enable ]; then @@ -815,7 +815,7 @@ elif [ -f /etc/redhat-release ]; then unset LE_PYTHON DeterminePythonVersion "NOCRASH" - RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` + RPM_DIST_NAME=`(. /etc/os-release 2>/dev/null && echo $ID) || echo "unknown"` if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. @@ -825,7 +825,7 @@ elif [ -f /etc/redhat-release ]; then # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". - RPM_DIST_VERSION=$( (. /etc/os-release 2> /dev/null && echo "$VERSION_ID") | cut -d '.' -f1 || echo "unknown") + RPM_DIST_VERSION=$( (. /etc/os-release 2>/dev/null && echo "$VERSION_ID") | cut -d '.' -f1 || echo "unknown") # If RPM_DIST_VERSION is an empty string or it contains any nonnumeric # characters, the value is unexpected so we set RPM_DIST_VERSION to 0. diff --git a/certbot/tasks/install-legacy.yml b/certbot/tasks/install-legacy.yml index fe0cb8e2..e186c80d 100644 --- a/certbot/tasks/install-legacy.yml +++ b/certbot/tasks/install-legacy.yml @@ -48,7 +48,7 @@ src: cron_jessie dest: /etc/cron.d/certbot force: yes - when: certbot_custom_crontab + when: certbot_custom_crontab | bool - name: disable self-upgrade ini_file: diff --git a/certbot/tasks/main.yml b/certbot/tasks/main.yml index 54c1f803..e280875c 100644 --- a/certbot/tasks/main.yml +++ b/certbot/tasks/main.yml @@ -23,17 +23,26 @@ - name: Deploy hooks are present copy: - src: hooks/ + src: hooks/deploy/ dest: /etc/letsencrypt/renewal-hooks/deploy/ mode: "0700" owner: root group: root -- name: Move commit-etc.sh to z-commit-etc.sh if present +- name: "sync_remote is configured with servers" + lineinfile: + dest: /etc/letsencrypt/renewal-hooks/deploy/sync_remote.cf + regexp: "^servers=" + line: "servers=\"{{ certbot_hooks_sync_remote_servers | join(' ') }}\"" + create: yes + +# begining of backward compatibility tasks +- name: Move deploy/commit-etc.sh to deploy/z-commit-etc.sh if present command: "mv /etc/letsencrypt/renewal-hooks/deploy/commit-etc.sh /etc/letsencrypt/renewal-hooks/deploy/z-commit-etc.sh" args: removes: /etc/letsencrypt/renewal-hooks/deploy/commit-etc.sh creates: /etc/letsencrypt/renewal-hooks/deploy/z-commit-etc.sh +# end of backward compatibility tasks - name: "certbot lock is ignored by Git" lineinfile: diff --git a/clamav/tasks/main.yml b/clamav/tasks/main.yml index 27d30cbc..be9e5b00 100644 --- a/clamav/tasks/main.yml +++ b/clamav/tasks/main.yml @@ -5,7 +5,7 @@ question: "{{ item.key }}" value: "{{ item.value }}" vtype: "{{ item.type }}" - with_items: + loop: - { key: 'clamav-daemon/debconf', type: 'boolean', value: 'true' } - { key: 'clamav-daemon/MaxHTMLNormalize', type: 'string', value: '10M' } - { key: 'clamav-daemon/StatsPEDisabled', type: 'boolean', value: 'true' } @@ -57,7 +57,7 @@ question: "{{ item.key }}" value: "{{ item.value }}" vtype: "{{ item.type }}" - with_items: + loop: - { key: 'clamav-freshclam/autoupdate_freshclam', type: 'select', value: 'daemon' } - { key: 'clamav-freshclam/proxy_user', type: 'string', value: '' } - { key: 'clamav-freshclam/NotifyClamd', type: 'boolean', value: 'true' } diff --git a/dhcpd/meta/main.yml b/dhcpd/meta/main.yml index 74b43142..44edbee0 100644 --- a/dhcpd/meta/main.yml +++ b/dhcpd/meta/main.yml @@ -1,17 +1,23 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of isc-dhcp-server. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # Be sure to remove the '[]' above if you add dependencies + # to this list. dependencies: [] # List your role dependencies here, one per line. diff --git a/docker-host/files/docker-debian.gpg b/docker-host/files/docker-debian.asc similarity index 100% rename from docker-host/files/docker-debian.gpg rename to docker-host/files/docker-debian.asc diff --git a/docker-host/tasks/main.yml b/docker-host/tasks/main.yml index 9a66bb92..d3a41a28 100644 --- a/docker-host/tasks/main.yml +++ b/docker-host/tasks/main.yml @@ -28,9 +28,13 @@ when: ansible_distribution_release == 'jessie' - name: Add Docker's official GPG key - apt_key: - #url: https://download.docker.com/linux/debian/gpg - data: "{{ lookup('file', 'docker-debian.gpg') }}" + copy: + src: docker-debian.asc + dest: /etc/apt/trusted.gpg.d/docker-debian.asc + force: yes + mode: "0644" + owner: root + group: root - name: Install docker and python-docker apt: @@ -71,17 +75,17 @@ state: directory mode: "0644" owner: root - when: docker_tls_enabled + when: docker_tls_enabled | bool - name: Copy shellpki utility to Docker TLS directory template: src: "{{ item }}.j2" dest: "{{ docker_tls_path }}/{{ item }}" mode: "0744" - with_items: + loop: - shellpki.sh - openssl.cnf - when: docker_tls_enabled + when: docker_tls_enabled | bool - name: Check if certs are already created stat: @@ -90,4 +94,6 @@ - name: Creating a CA, server key command: "{{ docker_tls_path }}/shellpki.sh init" - when: docker_tls_enabled and not tls_certs_stat.stat.isdir is defined + when: + - docker_tls_enabled | bool + - not tls_certs_stat.stat.isdir diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml index 1a7e4280..aa817086 100644 --- a/dovecot/tasks/main.yml +++ b/dovecot/tasks/main.yml @@ -24,7 +24,7 @@ line: "{{ item.key }} = {{ item.value }}" regexp: "^#*{{ item.key }}" state: present - with_items: + loop: - { key: 'hosts', value: '127.0.0.1' } - { key: 'auth_bind', value: 'yes' } - { key: 'ldap_version', value: 3 } diff --git a/drbd/meta/main.yml b/drbd/meta/main.yml index f07ce45d..511001b0 100644 --- a/drbd/meta/main.yml +++ b/drbd/meta/main.yml @@ -1,17 +1,23 @@ galaxy_info: - author: Evolix + company: Evolix description: Install tools to setup DRBD replication accross servers. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # Be sure to remove the '[]' above if you add dependencies + # to this list. dependencies: [] # List your role dependencies here, one per line. diff --git a/elasticsearch/files/elasticsearch.key b/elasticsearch/files/elastic.asc similarity index 100% rename from elasticsearch/files/elasticsearch.key rename to elasticsearch/files/elastic.asc diff --git a/elasticsearch/meta/main.yml b/elasticsearch/meta/main.yml index 736c0a42..fa608e85 100644 --- a/elasticsearch/meta/main.yml +++ b/elasticsearch/meta/main.yml @@ -1,20 +1,20 @@ --- galaxy_info: - author: Evolix + company: Evolix description: Install Elasticsearch issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is @@ -24,6 +24,3 @@ galaxy_info: # # NOTE: A tag is limited to a single word comprised of # alphanumeric characters. Maximum 20 tags per role. - -dependencies: - - { role: evolix/java, alternative: 'openjdk' } diff --git a/elasticsearch/tasks/configuration.yml b/elasticsearch/tasks/configuration.yml index e8362fa3..5afa94b0 100644 --- a/elasticsearch/tasks/configuration.yml +++ b/elasticsearch/tasks/configuration.yml @@ -6,7 +6,7 @@ line: "cluster.name: {{ elasticsearch_cluster_name }}" regexp: "^cluster.name:" insertafter: "^# *cluster.name:" - when: elasticsearch_cluster_name|default("", True) + when: elasticsearch_cluster_name | default("", True) | length > 0 tags: - config @@ -25,7 +25,7 @@ line: "network.host: {{ elasticsearch_network_host }}" regexp: "^network.host:" insertafter: "^# *network.host:" - when: elasticsearch_network_host|default("", True) + when: elasticsearch_network_host | default("", True) | length > 0 tags: - config @@ -35,7 +35,7 @@ line: "network.publish_host: {{ elasticsearch_network_publish_host }}" regexp: "^network.publish_host:" insertafter: "^network.host:" - when: elasticsearch_network_publish_host|default("", True) + when: elasticsearch_network_publish_host | default("", True) | length > 0 tags: - config @@ -45,25 +45,43 @@ line: "http.publish_host: {{ elasticsearch_http_publish_host }}" regexp: "^http.publish_host:" insertafter: "^http.port:" - when: elasticsearch_http_publish_host|default("", True) + when: elasticsearch_http_publish_host | default("", True) | length > 0 tags: - config - name: Configure discovery seed hosts lineinfile: dest: /etc/elasticsearch/elasticsearch.yml - line: "discovery.seed_hosts: {{ elasticsearch_discovery_seed_hosts | to_yaml }}" + line: "discovery.seed_hosts: {{ elasticsearch_discovery_seed_hosts | to_yaml(default_flow_style=True) }}" regexp: "^discovery.seed_hosts:" - when: elasticsearch_discovery_seed_hosts + when: elasticsearch_discovery_seed_hosts | default([], True) | length > 0 + tags: + - config + +- name: Configure empty discovery seed hosts + lineinfile: + dest: /etc/elasticsearch/elasticsearch.yml + regexp: "^discovery.seed_hosts:" + state: absent + when: elasticsearch_discovery_seed_hosts | default([], True) | length <= 0 tags: - config - name: Configure initial master nodes lineinfile: dest: /etc/elasticsearch/elasticsearch.yml - line: "cluster.initial_master_nodes: {{ elasticsearch_cluster_initial_master_nodes | to_yaml }}" + line: "cluster.initial_master_nodes: {{ elasticsearch_cluster_initial_master_nodes | to_yaml(default_flow_style=True) }}" regexp: "^cluster.initial_master_nodes:" - when: elasticsearch_cluster_initial_master_nodes + when: elasticsearch_cluster_initial_master_nodes | default([], True) | length > 0 + tags: + - config + +- name: Configure empty initial master nodes + lineinfile: + dest: /etc/elasticsearch/elasticsearch.yml + regexp: "^cluster.initial_master_nodes:" + state: absent + when: elasticsearch_cluster_initial_master_nodes | default([], True) | length <= 0 tags: - config @@ -98,7 +116,7 @@ line: "discovery.zen.ping.unicast.hosts: {{ elasticsearch_cluster_members }}" regexp: "^discovery.zen.ping.unicast.hosts:" insertafter: "^#discovery.zen.ping.unicast.hosts" - when: elasticsearch_cluster_members|default("", True) + when: elasticsearch_cluster_members | default("", True) | length > 0 tags: - config @@ -108,6 +126,6 @@ line: "discovery.zen.minimum_master_nodes: {{ elasticsearch_minimum_master_nodes }}" regexp: "^discovery.zen.minimum_master_nodes:" insertafter: "^#discovery.zen.minimum_master_nodes" - when: elasticsearch_minimum_master_nodes|default("", True) + when: elasticsearch_minimum_master_nodes | default("", True) | length > 0 tags: - config diff --git a/elasticsearch/tasks/datadir.yml b/elasticsearch/tasks/datadir.yml index 66ec48a1..c0c20f05 100644 --- a/elasticsearch/tasks/datadir.yml +++ b/elasticsearch/tasks/datadir.yml @@ -16,8 +16,8 @@ tags: - elasticsearch when: - - elasticsearch_custom_datadir != '' - - elasticsearch_custom_datadir != None + - elasticsearch_custom_datadir is not none + - elasticsearch_custom_datadir | length > 0 - name: Datadir is moved to custom path block: @@ -44,7 +44,7 @@ tags: - elasticsearch when: - - elasticsearch_custom_datadir != '' - - elasticsearch_custom_datadir != None + - elasticsearch_custom_datadir is not none + - elasticsearch_custom_datadir | length > 0 - elasticsearch_custom_datadir != elasticsearch_current_real_datadir_test.stdout - not elasticsearch_custom_datadir_test.stat.exists diff --git a/elasticsearch/tasks/logs.yml b/elasticsearch/tasks/logs.yml index 16bbe5d6..01829dc9 100644 --- a/elasticsearch/tasks/logs.yml +++ b/elasticsearch/tasks/logs.yml @@ -1,7 +1,10 @@ --- - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False register: is_cron_installed diff --git a/elasticsearch/tasks/main.yml b/elasticsearch/tasks/main.yml index 126170a1..6f5ccc8c 100644 --- a/elasticsearch/tasks/main.yml +++ b/elasticsearch/tasks/main.yml @@ -15,7 +15,7 @@ - include: additional_scripts.yml - include: plugin_head.yml - when: elasticsearch_plugin_head + when: elasticsearch_plugin_head | bool - include: curator.yml - when: elasticsearch_curator + when: elasticsearch_curator | bool diff --git a/elasticsearch/tasks/packages.yml b/elasticsearch/tasks/packages.yml index 1a0ad8dc..da154593 100644 --- a/elasticsearch/tasks/packages.yml +++ b/elasticsearch/tasks/packages.yml @@ -5,17 +5,29 @@ name: apt-transport-https state: present tags: - - elasticsearch - - packages + - elasticsearch + - packages + +- name: Elastic embedded GPG key is absent + apt_key: + id: "D88E42B4" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - elasticsearch + - packages - name: Elastic GPG key is installed - apt_key: - # url: https://artifacts.elastic.co/GPG-KEY-elasticsearch - data: "{{ lookup('file', 'elasticsearch.key') }}" - state: present + copy: + src: elastic.asc + dest: /etc/apt/trusted.gpg.d/elastic.asc + force: yes + mode: "0644" + owner: root + group: root tags: - - elasticsearch - - packages + - elasticsearch + - packages - name: Elastic sources list is available apt_repository: @@ -24,16 +36,16 @@ state: present update_cache: yes tags: - - elasticsearch - - packages + - elasticsearch + - packages - name: Elasticsearch is installed apt: name: elasticsearch state: present tags: - - elasticsearch - - packages + - elasticsearch + - packages - name: Elasticsearch service is enabled service: diff --git a/elasticsearch/tasks/tmpdir.yml b/elasticsearch/tasks/tmpdir.yml index 086870fe..920300d7 100644 --- a/elasticsearch/tasks/tmpdir.yml +++ b/elasticsearch/tasks/tmpdir.yml @@ -9,9 +9,14 @@ - name: Tmpdir is moved to custom path block: - - name: "Create {{ elasticsearch_custom_tmpdir or elasticsearch_default_tmpdir | mandatory }}" + - set_fact: + _elasticsearch_custom_tmpdir: "{{ elasticsearch_custom_tmpdir | default(elasticsearch_default_tmpdir, True) | mandatory }}" + tags: + - elasticsearch + + - name: "Create {{ _elasticsearch_custom_tmpdir }}" file: - path: "{{ elasticsearch_custom_tmpdir or elasticsearch_default_tmpdir | mandatory }}" + path: "{{ _elasticsearch_custom_tmpdir }}" owner: elasticsearch group: elasticsearch mode: "0755" @@ -22,7 +27,7 @@ - name: change JVM tmpdir (< 6.x) lineinfile: dest: /etc/elasticsearch/jvm.options - line: "-Djava.io.tmpdir={{ elasticsearch_custom_tmpdir or elasticsearch_default_tmpdir | mandatory }}" + line: "-Djava.io.tmpdir={{ _elasticsearch_custom_tmpdir }}" regexp: "^-Djava.io.tmpdir=" insertafter: "## JVM configuration" notify: @@ -34,7 +39,7 @@ - name: check if ES_TMPDIR is available (>= 6.x) lineinfile: dest: /etc/default/elasticsearch - line: "ES_TMPDIR={{ elasticsearch_custom_tmpdir or elasticsearch_default_tmpdir | mandatory }}" + line: "ES_TMPDIR={{ _elasticsearch_custom_tmpdir }}" regexp: "^ES_TMPDIR=" insertafter: "JAVA_HOME" notify: @@ -54,4 +59,4 @@ tags: - elasticsearch when: elastic_stack_version is version('6', '>=') - when: (elasticsearch_custom_tmpdir != '' and elasticsearch_custom_tmpdir != None) or fstab_tmp_noexec.rc == 0 + when: (elasticsearch_custom_tmpdir is not none and elasticsearch_custom_tmpdir | length > 0) or fstab_tmp_noexec.rc == 0 diff --git a/etc-git/meta/main.yml b/etc-git/meta/main.yml index ef9d621e..cb666d15 100644 --- a/etc-git/meta/main.yml +++ b/etc-git/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Put /etc under Git version control. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/etc-git/tasks/commit.yml b/etc-git/tasks/commit.yml index 9833601e..4bcf8e5c 100644 --- a/etc-git/tasks/commit.yml +++ b/etc-git/tasks/commit.yml @@ -8,11 +8,9 @@ - include: do_commit.yml vars: git_folder: "/etc" - when: - - _etc_git.stat.exists - - _etc_git.stat.isdir - - + when: + - _etc_git.stat.exists + - _etc_git.stat.isdir - name: Is /usr/share/scripts a git repository stat: @@ -23,5 +21,5 @@ vars: git_folder: "/usr/share/scripts" when: - - _usr_share_scripts_git.stat.exists - - _usr_share_scripts_git.stat.isdir + - _usr_share_scripts_git.stat.exists + - _usr_share_scripts_git.stat.isdir diff --git a/etc-git/tasks/do_commit.yml b/etc-git/tasks/do_commit.yml index f13c7e50..6b09eaaf 100644 --- a/etc-git/tasks/do_commit.yml +++ b/etc-git/tasks/do_commit.yml @@ -5,7 +5,6 @@ name: remount-usr when: git_folder is match('/usr/.*') - - name: "is {{ git_folder }} clean?" command: git status --porcelain args: @@ -50,7 +49,7 @@ register: commit_end_run when: - not ansible_check_mode - - git_status.stdout + - git_status.stdout | length > 0 ignore_errors: yes tags: - etc-git diff --git a/etc-git/tasks/main.yml b/etc-git/tasks/main.yml index 8d16b79f..37d1c692 100644 --- a/etc-git/tasks/main.yml +++ b/etc-git/tasks/main.yml @@ -33,7 +33,9 @@ - ansible_distribution_major_version is version('10', '>=') - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + 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 diff --git a/etc-git/tasks/repository.yml b/etc-git/tasks/repository.yml index 1430c5bd..e8599c1e 100644 --- a/etc-git/tasks/repository.yml +++ b/etc-git/tasks/repository.yml @@ -46,7 +46,7 @@ lineinfile: dest: "{{ repository_path }}/.gitignore" line: "{{ item }}" - with_items: "{{ gitignore_items | default([]) }}" + loop: "{{ gitignore_items | default([]) }}" tags: - etc-git @@ -68,6 +68,6 @@ chdir: "{{ repository_path }}" warn: no register: git_commit - when: git_log.rc != 0 or (git_init is defined and git_init.changed) + when: git_log.rc != 0 or (git_init is defined and git_init is changed) tags: - etc-git diff --git a/evoacme/files/make-csr.sh b/evoacme/files/make-csr.sh index edec8787..0641c1d5 100755 --- a/evoacme/files/make-csr.sh +++ b/evoacme/files/make-csr.sh @@ -112,9 +112,9 @@ openssl_selfsigned() { [ -r "${key}" ] || error "File ${key} is not readable" [ -w "${crt_dir}" ] || error "Directory ${crt_dir} is not writable" if grep -q SAN "${cfg}"; then - "${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -extensions SAN -extfile "${cfg}" -signkey "${key}" -out "${crt}" 2> /dev/null + "${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -extensions SAN -extfile "${cfg}" -signkey "${key}" -out "${crt}" 2>/dev/null else - "${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -signkey "${key}" -out "${crt}" 2> /dev/null + "${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -signkey "${key}" -out "${crt}" 2>/dev/null fi [ -r "${crt}" ] || error "Something went wrong, ${crt} has not been generated" @@ -126,7 +126,7 @@ openssl_key(){ [ -w "${key_dir}" ] || error "Directory ${key_dir} is not writable" - "${OPENSSL_BIN}" genrsa -out "${key}" "${size}" 2> /dev/null + "${OPENSSL_BIN}" genrsa -out "${key}" "${size}" 2>/dev/null [ -r "${key}" ] || error "Something went wrong, ${key} has not been generated" } diff --git a/evoacme/meta/main.yml b/evoacme/meta/main.yml index ea0c5551..c238d701 100644 --- a/evoacme/meta/main.yml +++ b/evoacme/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Install evoacme ; a wrapper for Certbot (Let's Encrypt) issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/evoacme/tasks/conf.yml b/evoacme/tasks/conf.yml index 4d9f6704..402fbdcf 100644 --- a/evoacme/tasks/conf.yml +++ b/evoacme/tasks/conf.yml @@ -4,7 +4,7 @@ section: 'req' option: "{{ item.name }}" value: "{{ item.var }}" - with_items: + loop: - { name: 'default_bits', var: "{{ evoacme_ssl_key_size }}" } - { name: 'encrypt_key', var: 'yes' } - { name: 'distinguished_name', var: 'req_dn' } @@ -16,7 +16,7 @@ section: 'req_dn' option: "{{ item.name }}" value: "{{ item.var }}" - with_items: + loop: - { name: 'C', var: "{{ evoacme_ssl_ct }}" } - { name: 'ST', var: "{{ evoacme_ssl_state }}" } - { name: 'L', var: "{{ evoacme_ssl_loc }}" } diff --git a/evoacme/tasks/evoacme_hook.yml b/evoacme/tasks/evoacme_hook.yml index 51dbb21c..2951fa00 100644 --- a/evoacme/tasks/evoacme_hook.yml +++ b/evoacme/tasks/evoacme_hook.yml @@ -16,4 +16,4 @@ src: "hooks/{{ hook_name }}" dest: "{{ evoacme_hooks_dir }}/{{ hook_name }}" mode: "0750" - when: _find_hook.stdout == "" + when: _find_hook.stdout | length == 0 diff --git a/evoacme/tasks/main.yml b/evoacme/tasks/main.yml index 4c71d90e..1cc84c5d 100644 --- a/evoacme/tasks/main.yml +++ b/evoacme/tasks/main.yml @@ -6,7 +6,7 @@ - ansible_distribution == "Debian" - ansible_distribution_major_version is version('9', '>=') msg: only compatible with Debian >= 9 - when: not evoacme_disable_debian_check + when: not (evoacme_disable_debian_check | bool) - include: certbot.yml diff --git a/evoacme/tasks/scripts.yml b/evoacme/tasks/scripts.yml index 50d95890..89aacff8 100644 --- a/evoacme/tasks/scripts.yml +++ b/evoacme/tasks/scripts.yml @@ -39,6 +39,6 @@ file: path: "/usr/local/bin/{{ item }}" state: absent - with_items: + loop: - 'make-csr' - 'evoacme' diff --git a/evobackup-client/handlers/main.yml b/evobackup-client/handlers/main.yml index 17df304a..fc1b7739 100644 --- a/evobackup-client/handlers/main.yml +++ b/evobackup-client/handlers/main.yml @@ -13,4 +13,4 @@ command: "bkctld restart {{ evolinux_hostname }}" # - "bkctld sync {{ evolinux_hostname }}" delegate_to: "{{ evobackup_client__hosts[0].ip }}" - when: evobackup_client__hosts|length > 1 + when: evobackup_client__hosts | length > 1 diff --git a/evobackup-client/tasks/open_ssh_ports.yml b/evobackup-client/tasks/open_ssh_ports.yml index be96c161..3d1701ef 100644 --- a/evobackup-client/tasks/open_ssh_ports.yml +++ b/evobackup-client/tasks/open_ssh_ports.yml @@ -14,7 +14,7 @@ marker: "# {mark} {{ item.name }}" block: | /sbin/iptables -A INPUT -p tcp --sport {{ item.port }} --dport 1024:65535 -s {{ item.ip }} -m state --state ESTABLISHED,RELATED -j ACCEPT - with_items: "{{ evobackup_client__hosts }}" + loop: "{{ evobackup_client__hosts }}" notify: restart minifirewall when: evobackup_client__minifirewall.stat.exists tags: diff --git a/evobackup-client/tasks/upload_scripts.yml b/evobackup-client/tasks/upload_scripts.yml index 8d698519..79e5d7db 100644 --- a/evobackup-client/tasks/upload_scripts.yml +++ b/evobackup-client/tasks/upload_scripts.yml @@ -6,11 +6,13 @@ dest: "{{ evobackup_client__cron_path }}" force: true mode: 0755 - with_first_found: - - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.{{ inventory_hostname }}.sh.j2" - - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.{{ host_group }}.sh.j2" - - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.sh.j2" - - "zzz_evobackup.default.sh.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.{{ inventory_hostname }}.sh.j2" + - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.{{ host_group | default('all') }}.sh.j2" + - "templates/evobackup-client/{{ evobackup_client__cron_template_name }}.sh.j2" + - "templates/zzz_evobackup.default.sh.j2" tags: - evobackup_client - evobackup_client_backup_scripts diff --git a/evobackup-client/tasks/verify_ssh.yml b/evobackup-client/tasks/verify_ssh.yml index 4e968197..d48fb455 100644 --- a/evobackup-client/tasks/verify_ssh.yml +++ b/evobackup-client/tasks/verify_ssh.yml @@ -5,7 +5,7 @@ path: /root/.ssh/known_hosts name: "[{{ item.name }}]:{{ item.port }}" key: "[{{ item.name }}]:{{ item.port }} {{ item.fingerprint }}" - with_list: "{{ evobackup_client__hosts }}" + loop: "{{ evobackup_client__hosts }}" tags: - evobackup_client - evobackup_client_backup_hosts diff --git a/evobackup-client/templates/zzz_evobackup.default.sh.j2 b/evobackup-client/templates/zzz_evobackup.default.sh.j2 index 49de9744..fd2be5b4 100644 --- a/evobackup-client/templates/zzz_evobackup.default.sh.j2 +++ b/evobackup-client/templates/zzz_evobackup.default.sh.j2 @@ -124,7 +124,7 @@ pick_server() { if [ -e "${PIDFILE}" ]; then pid=$(cat "${PIDFILE}") # Does process still exist ? - if kill -0 "${pid}" 2> /dev/null; then + if kill -0 "${pid}" 2>/dev/null; then # Killing the childs of evobackup. for ppid in $(pgrep -P "${pid}"); do kill -9 "${ppid}"; diff --git a/evocheck/files/evocheck.sh b/evocheck/files/evocheck.sh index 287982e2..7adf5757 100644 --- a/evocheck/files/evocheck.sh +++ b/evocheck/files/evocheck.sh @@ -109,7 +109,7 @@ is_pack_samba(){ } is_installed(){ for pkg in "$@"; do - dpkg -l "$pkg" 2> /dev/null | grep -q -E '^(i|h)i' || return 1 + dpkg -l "$pkg" 2>/dev/null | grep -q -E '^(i|h)i' || return 1 done } minifirewall_file() { diff --git a/evocheck/meta/main.yml b/evocheck/meta/main.yml index 35c76d72..9f435be4 100644 --- a/evocheck/meta/main.yml +++ b/evocheck/meta/main.yml @@ -7,13 +7,14 @@ galaxy_info: license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - squeeze + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/evocheck/tasks/cron.yml b/evocheck/tasks/cron.yml index 4ef10b05..ecf1e1d0 100644 --- a/evocheck/tasks/cron.yml +++ b/evocheck/tasks/cron.yml @@ -1,7 +1,9 @@ --- - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + 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 diff --git a/evocheck/tasks/exec.yml b/evocheck/tasks/exec.yml index 244d0347..306cf019 100644 --- a/evocheck/tasks/exec.yml +++ b/evocheck/tasks/exec.yml @@ -10,6 +10,6 @@ - debug: var: evocheck_run.stdout_lines - when: evocheck_run.stdout != "" + when: evocheck_run.stdout | length > 0 tags: - evocheck-exec diff --git a/evocheck/tasks/main.yml b/evocheck/tasks/main.yml index 0e374b92..87e2d636 100644 --- a/evocheck/tasks/main.yml +++ b/evocheck/tasks/main.yml @@ -7,4 +7,4 @@ when: evocheck_force_install == "package" - include: cron.yml - when: evocheck_update_crontab + when: evocheck_update_crontab | bool diff --git a/evolinux-base/defaults/main.yml b/evolinux-base/defaults/main.yml index 98ff43ef..26f6e4c8 100644 --- a/evolinux-base/defaults/main.yml +++ b/evolinux-base/defaults/main.yml @@ -51,7 +51,7 @@ evolinux_kernel_include: True evolinux_kernel_reboot_after_panic: True evolinux_kernel_disable_tcp_timestamps: True evolinux_kernel_customize_swappiness: True -evolinux_kernel_swappiness: 20 +evolinux_kernel_swappiness: "20" evolinux_kernel_cve20165696: True # fstab diff --git a/evolinux-base/files/hpePublicKey2048_key1.pub b/evolinux-base/files/hpePublicKey2048_key1.asc similarity index 100% rename from evolinux-base/files/hpePublicKey2048_key1.pub rename to evolinux-base/files/hpePublicKey2048_key1.asc diff --git a/evolinux-base/files/hwraid.le-vert.net.gpg.key b/evolinux-base/files/hwraid.le-vert.net.asc similarity index 100% rename from evolinux-base/files/hwraid.le-vert.net.gpg.key rename to evolinux-base/files/hwraid.le-vert.net.asc diff --git a/evolinux-base/meta/main.yml b/evolinux-base/meta/main.yml index 58265332..84c001c1 100644 --- a/evolinux-base/meta/main.yml +++ b/evolinux-base/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Evolix usual customizations for a Debian installation. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/evolinux-base/tasks/default_www.yml b/evolinux-base/tasks/default_www.yml index 8956d824..84580b54 100644 --- a/evolinux-base/tasks/default_www.yml +++ b/evolinux-base/tasks/default_www.yml @@ -4,7 +4,7 @@ path: /var/www state: directory mode: "0755" - when: evolinux_default_www_files + when: evolinux_default_www_files | bool - name: images are copied copy: @@ -13,7 +13,7 @@ mode: "0644" directory_mode: "0755" follow: yes - when: evolinux_default_www_files + when: evolinux_default_www_files | bool - name: index is copied template: @@ -21,7 +21,7 @@ dest: /var/www/index.html mode: "0644" force: no - when: evolinux_default_www_files + when: evolinux_default_www_files | bool # SSL cert @@ -43,6 +43,6 @@ command: openssl x509 -req -days 3650 -sha256 -in /etc/ssl/{{ ansible_fqdn }}.csr -signkey /etc/ssl/private/{{ ansible_fqdn }}.key -out /etc/ssl/certs/{{ ansible_fqdn }}.crt args: creates: "/etc/ssl/certs/{{ ansible_fqdn }}.crt" - when: evolinux_default_www_ssl_cert + when: evolinux_default_www_ssl_cert | bool - meta: flush_handlers diff --git a/evolinux-base/tasks/fstab.yml b/evolinux-base/tasks/fstab.yml index bb70fde8..e10f483e 100644 --- a/evolinux-base/tasks/fstab.yml +++ b/evolinux-base/tasks/fstab.yml @@ -17,7 +17,7 @@ notify: remount /home when: - fstab_content.stdout | regex_search('\s/home\s') - - evolinux_fstab_home + - evolinux_fstab_home | bool - name: /tmp partition is customized replace: @@ -26,7 +26,7 @@ replace: '\1{{ evolinux_fstab_tmp_options | mandatory }}\3' when: - fstab_content.stdout | regex_search('\s/tmp\s') - - evolinux_fstab_tmp + - evolinux_fstab_tmp | bool - name: /usr partition is customized replace: @@ -35,7 +35,7 @@ replace: '\1{{ evolinux_fstab_usr_options | mandatory }}\3' when: - fstab_content.stdout | regex_search('\s/usr\s') - - evolinux_fstab_usr + - evolinux_fstab_usr | bool - name: /var partition is customized replace: @@ -45,7 +45,7 @@ notify: remount /var when: - fstab_content.stdout | regex_search('\s/var\s') - - evolinux_fstab_var + - evolinux_fstab_var | bool - name: /var/tmp is created mount: @@ -55,7 +55,7 @@ opts: "{{ evolinux_fstab_var_tmp_options | mandatory }}" state: mounted when: - - evolinux_fstab_var_tmp + - evolinux_fstab_var_tmp | bool - name: /dev/shm is created (Debian 10 and later) mount: @@ -65,7 +65,7 @@ opts: "{{ evolinux_fstab_dev_shm_options | mandatory }}" state: mounted when: - - evolinux_fstab_dev_shm + - evolinux_fstab_dev_shm | bool - ansible_distribution_major_version is version('10', '>=') - meta: flush_handlers diff --git a/evolinux-base/tasks/hardware.yml b/evolinux-base/tasks/hardware.yml index c44c1248..7f4ebf36 100644 --- a/evolinux-base/tasks/hardware.yml +++ b/evolinux-base/tasks/hardware.yml @@ -29,7 +29,7 @@ # HP gen <10: Hewlett-Packard Company Smart Array # HP gen >=10: Adaptec Smart Storage PQI - name: Detect if RAID is installed - shell: lspci -q | grep -e "RAID bus controller" -e "Serial Attached SCSI controller" + shell: "set -o pipefail && lspci -q | grep -e 'RAID bus controller' -e 'Serial Attached SCSI controller'" check_mode: no register: raidmodel changed_when: "'FAILED' in raidmodel.stdout" @@ -37,10 +37,20 @@ - name: HPE Smart Storage Administrator (ssacli) is present block: - - name: Add HPE GPG key + - name: HPE GPG embedded key is absent apt_key: - #url: https://downloads.linux.hpe.com/SDR/hpePublicKey2048_key1.pub - data: "{{ lookup('file', 'hpePublicKey2048_key1.pub') }}" + id: "26C2B797" + keyring: /etc/apt/trusted.gpg + state: absent + + - name: HPE GPG key is installed + copy: + src: hpePublicKey2048_key1.asc + dest: /etc/apt/trusted.gpg.d/hpePublicKey2048_key1.asc + force: yes + mode: "0644" + owner: root + group: root - name: Add HPE repository apt_repository: @@ -93,10 +103,21 @@ - name: MegaRAID SAS package is present block: - - name: Add HW tool GPG key + - name: HWRaid embedded GPG key is absent apt_key: - # url: https://hwraid.le-vert.net/debian/hwraid.le-vert.net.gpg.key - data: "{{ lookup('file', 'hwraid.le-vert.net.gpg.key') }}" + id: "23B3D3B4" + keyring: /etc/apt/trusted.gpg + state: absent + when: ansible_distribution_major_version is version('9', '>=') + + - name: HWRaid GPG key is installed + copy: + src: hwraid.le-vert.net.asc + dest: /etc/apt/trusted.gpg.d/hwraid.le-vert.net.asc + force: yes + mode: "0644" + owner: root + group: root when: ansible_distribution_major_version is version('9', '>=') - name: Add HW tool repository diff --git a/evolinux-base/tasks/hostname.yml b/evolinux-base/tasks/hostname.yml index b73c11c7..2b9cfa93 100644 --- a/evolinux-base/tasks/hostname.yml +++ b/evolinux-base/tasks/hostname.yml @@ -7,14 +7,14 @@ - name: Set hostname "{{ evolinux_hostname }}" hostname: name: "{{ evolinux_hostname }}" - when: evolinux_hostname_hosts + when: evolinux_hostname_hosts | bool - name: Set right localhost line in /etc/hosts replace: dest: /etc/hosts regexp: '^127.0.0.1(\s+)localhost.*$' replace: '127.0.0.1\1localhost.localdomain localhost' - when: evolinux_hostname_hosts + when: evolinux_hostname_hosts | bool - name: Set ip+fqdn+hostname in /etc/hosts lineinfile: @@ -22,21 +22,21 @@ regexp: '^{{ ansible_default_ipv4.address }}\s+' line: "{{ ansible_default_ipv4.address }} {{ [evolinux_fqdn, evolinux_internal_fqdn] | unique | join(' ') }} {{ [evolinux_hostname, evolinux_internal_hostname] | unique | join(' ') }}" insertafter: '127.0.0.1\s+localhost.localdomain' - when: evolinux_hostname_hosts + when: evolinux_hostname_hosts | bool - name: 127.0.1.1 is removed lineinfile: dest: /etc/hosts regexp: '^127.0.1.1\s+' state: absent - when: evolinux_hostname_hosts + when: evolinux_hostname_hosts | bool - name: /etc/mailname is up-to-date copy: dest: /etc/mailname content: "{{ evolinux_fqdn }}\n" force: yes - when: evolinux_hostname_mailname + when: evolinux_hostname_mailname | bool # Override facts diff --git a/evolinux-base/tasks/kernel.yml b/evolinux-base/tasks/kernel.yml index 95912855..76965f47 100644 --- a/evolinux-base/tasks/kernel.yml +++ b/evolinux-base/tasks/kernel.yml @@ -7,10 +7,10 @@ sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes - with_items: + loop: - { name: kernel.panic_on_oops, value: 1 } - { name: kernel.panic, value: 60 } - when: evolinux_kernel_reboot_after_panic + when: evolinux_kernel_reboot_after_panic | bool - name: Don't reboot after panic sysctl: @@ -18,10 +18,10 @@ sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: absent reload: yes - with_items: + loop: - kernel.panic_on_oops - kernel.panic - when: not evolinux_kernel_reboot_after_panic + when: not evolinux_kernel_reboot_after_panic | bool - name: Disable net.ipv4.tcp_timestamps sysctl: @@ -30,7 +30,7 @@ sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes - when: evolinux_kernel_disable_tcp_timestamps + when: evolinux_kernel_disable_tcp_timestamps | bool - name: Customize the swappiness sysctl: @@ -39,16 +39,16 @@ sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes - when: evolinux_kernel_customize_swappiness + when: evolinux_kernel_customize_swappiness | bool - name: Patch for TCP stack vulnerability CVE-2016-5696 sysctl: name: net.ipv4.tcp_challenge_ack_limit - value: 1073741823 + value: "1073741823" sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes - when: evolinux_kernel_cve20165696 + when: evolinux_kernel_cve20165696 | bool - name: Patch for TCP stack vulnerability CVE-2018-5391 (FragmentSmack) sysctl: @@ -57,10 +57,10 @@ sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes - with_items: - - { name: "net.ipv4.ipfrag_low_thresh", value: 196608 } - - { name: "net.ipv6.ip6frag_low_thresh", value: 196608 } - - { name: "net.ipv4.ipfrag_high_thresh", value: 262144 } - - { name: "net.ipv6.ip6frag_high_thresh", value: 262144 } + loop: + - { name: "net.ipv4.ipfrag_low_thresh", value: "196608" } + - { name: "net.ipv6.ip6frag_low_thresh", value: "196608" } + - { name: "net.ipv4.ipfrag_high_thresh", value: "262144" } + - { name: "net.ipv6.ip6frag_high_thresh", value: "262144" } - meta: flush_handlers diff --git a/evolinux-base/tasks/logs.yml b/evolinux-base/tasks/logs.yml index 9c1f45e4..2bf28b98 100644 --- a/evolinux-base/tasks/logs.yml +++ b/evolinux-base/tasks/logs.yml @@ -8,7 +8,7 @@ dest: /etc/rsyslog.conf mode: "0644" notify: restart rsyslog - when: evolinux_logs_rsyslog_conf + when: evolinux_logs_rsyslog_conf | bool - name: Disable logrotate default conf command: mv /etc/logrotate.d/rsyslog /etc/logrotate.d/rsyslog.disabled @@ -16,25 +16,25 @@ removes: /etc/logrotate.d/rsyslog creates: /etc/logrotate.d/rsyslog.disabled notify: restart rsyslog - when: evolinux_logs_disable_logrotate_rsyslog + when: evolinux_logs_disable_logrotate_rsyslog | bool - name: Copy many logrotate files copy: src: logs/logrotate.d/ dest: /etc/logrotate.d/ - when: evolinux_logs_logrotate_confs + when: evolinux_logs_logrotate_confs | bool - name: Copy rsyslog logrotate file template: src: logs/zsyslog.j2 dest: /etc/logrotate.d/zsyslog - when: evolinux_logs_logrotate_confs + when: evolinux_logs_logrotate_confs | bool - name: Configure logrotate.conf replace: dest: /etc/logrotate.conf regexp: "rotate [0-9]+" replace: "rotate 12" - when: evolinux_logs_default_rotate + when: evolinux_logs_default_rotate | bool - meta: flush_handlers diff --git a/evolinux-base/tasks/main.yml b/evolinux-base/tasks/main.yml index 0b2fdf89..2da87162 100644 --- a/evolinux-base/tasks/main.yml +++ b/evolinux-base/tasks/main.yml @@ -13,50 +13,50 @@ vars: apt_install_basics: "{{ evolinux_apt_replace_default_sources }}" apt_install_evolix_public: "{{ evolinux_apt_public_sources }}" - when: evolinux_apt_include + when: evolinux_apt_include | bool - name: /etc versioning with Git include_role: name: evolix/etc-git - when: evolinux_etcgit_include + when: evolinux_etcgit_include | bool - name: /etc/evolinux base include: etc-evolinux.yml - when: evolinux_etcevolinux_include + when: evolinux_etcevolinux_include | bool - name: Hostname include: hostname.yml - when: evolinux_hostname_include + when: evolinux_hostname_include | bool - name: Kernel tuning include: kernel.yml - when: evolinux_kernel_include + when: evolinux_kernel_include | bool - name: Fstab configuration include: fstab.yml - when: evolinux_fstab_include + when: evolinux_fstab_include | bool - name: Packages include: packages.yml - when: evolinux_packages_include + when: evolinux_packages_include | bool - name: System settings include: system.yml - when: evolinux_system_include + when: evolinux_system_include | bool - name: Minifirewall include_role: name: evolix/minifirewall - when: evolinux_minifirewall_include + when: evolinux_minifirewall_include | bool - name: Evomaintenance include_role: name: evolix/evomaintenance - when: evolinux_evomaintenance_include + when: evolinux_evomaintenance_include | bool - name: SSH configuration include: ssh.yml - when: evolinux_ssh_include + when: evolinux_ssh_include | bool ### disabled because of a memory leak # - name: Create evolinux users @@ -66,66 +66,66 @@ - name: Root user configuration include: root.yml - when: evolinux_root_include + when: evolinux_root_include | bool - name: Postfix include: postfix.yml - when: evolinux_postfix_include + when: evolinux_postfix_include | bool - name: Logs management include: logs.yml - when: evolinux_logs_include + when: evolinux_logs_include | bool - name: Default index page include: default_www.yml - when: evolinux_default_www_include + when: evolinux_default_www_include | bool - name: Hardware drivers and tools include: hardware.yml - when: evolinux_hardware_include + when: evolinux_hardware_include | bool - name: Customize for Online.net include: provider_online.yml - when: evolinux_provider_online_include + when: evolinux_provider_online_include | bool - name: Customize for Orange FCE include: provider_orange_fce.yml - when: evolinux_provider_orange_fce_include + when: evolinux_provider_orange_fce_include | bool - name: Override Log2mail service include: log2mail.yml - when: evolinux_log2mail_include + when: evolinux_log2mail_include | bool - include: motd.yml - name: Munin include_role: name: evolix/munin - when: evolinux_munin_include + when: evolinux_munin_include | bool - name: Nagios/NRPE include_role: name: evolix/nagios-nrpe - when: evolinux_nagios_nrpe_include + when: evolinux_nagios_nrpe_include | bool - name: fail2ban include_role: name: evolix/fail2ban - when: evolinux_fail2ban_include + when: evolinux_fail2ban_include | bool - name: Evocheck include_role: name: evolix/evocheck vars: evocheck_force_install: "{{ evolinux_evocheck_force_install }}" - when: evolinux_evocheck_include + when: evolinux_evocheck_include | bool - name: Listupgrade include_role: name: evolix/listupgrade - when: evolinux_listupgrade_include + when: evolinux_listupgrade_include | bool - name: Generate ldif script include_role: name: evolix/generate-ldif - when: evolinux_generateldif_include + when: evolinux_generateldif_include | bool diff --git a/evolinux-base/tasks/motd.yml b/evolinux-base/tasks/motd.yml index d1171eb4..70079463 100644 --- a/evolinux-base/tasks/motd.yml +++ b/evolinux-base/tasks/motd.yml @@ -7,11 +7,12 @@ owner: root group: root mode: "0644" - with_first_found: - - files: - - "motd/motd.{{ inventory_hostname }}.j2" - - "motd/motd.{{ host_group }}.j2" - - "motd/motd.default.j2" - skip: True + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/motd/motd.{{ inventory_hostname }}.j2" + - "templates/motd/motd.{{ host_group | default('all') }}.j2" + - "templates/motd/motd.default.j2" + - "templates/motd.default.j2" tags: - motd diff --git a/evolinux-base/tasks/packages.yml b/evolinux-base/tasks/packages.yml index ed2b1cd2..8df64abd 100644 --- a/evolinux-base/tasks/packages.yml +++ b/evolinux-base/tasks/packages.yml @@ -16,7 +16,7 @@ - ssl-cert - ca-certificates - rename - when: evolinux_packages_system + when: evolinux_packages_system | bool - name: Install/Update diagnostic tools apt: @@ -34,7 +34,7 @@ - telnet - traceroute - man - when: evolinux_packages_diagnostic + when: evolinux_packages_diagnostic | bool - name: Install/Update hardware tools apt: @@ -42,7 +42,7 @@ - hdparm - smartmontools - lm-sensors - when: evolinux_packages_hardware + when: evolinux_packages_hardware | bool - name: Install/Update common tools apt: @@ -58,21 +58,21 @@ - bc - pinentry-curses - ncurses-term - when: evolinux_packages_common + when: evolinux_packages_common | bool - name: Be sure that openntpd package is absent/purged apt: name: openntpd state: absent purge: True - when: evolinux_packages_purge_openntpd + when: evolinux_packages_purge_openntpd | bool - name: the chrony package is absent apt: name: chrony purge: True state: absent - when: evolinux_packages_purge_chrony + when: evolinux_packages_purge_chrony | bool - name: Be sure locate/mlocate is absent/purged apt: @@ -81,19 +81,19 @@ - mlocate state: absent purge: yes - when: evolinux_packages_purge_locate + when: evolinux_packages_purge_locate | bool - name: Install/Update serveur-base meta-package apt: name: serveur-base allow_unauthenticated: yes - when: evolinux_packages_serveur_base + when: evolinux_packages_serveur_base | bool - name: Install/Update packages for Stretch and later apt: name: net-tools when: - - evolinux_packages_stretch + - evolinux_packages_stretch | bool - ansible_distribution_major_version is version('9', '>=') - name: Install/Update packages for Buster and later @@ -102,7 +102,7 @@ - spectre-meltdown-checker - binutils when: - - evolinux_packages_buster + - evolinux_packages_buster | bool - ansible_distribution_major_version is version('10', '>=') - name: Customize logcheck recipient @@ -110,7 +110,7 @@ dest: /etc/logcheck/logcheck.conf regexp: '^SENDMAILTO=".*"$' line: 'SENDMAILTO="{{ logcheck_alert_email or general_alert_email | mandatory }}"' - when: evolinux_packages_logcheck_recipient + when: evolinux_packages_logcheck_recipient | bool - name: Deleting rpcbind and nfs-common apt: @@ -118,7 +118,7 @@ - rpcbind - nfs-common state: absent - when: evolinux_packages_delete_nfs + when: evolinux_packages_delete_nfs | bool # TODO: use ini_file when Ansible > 2.1 (no_extra_spaces: yes) @@ -128,11 +128,11 @@ dest: /etc/apt/listchanges.conf regexp: '^{{ item.option }}\s*=' line: "{{ item.option }}={{ item.value }}" - with_items: + loop: - { option: "confirm", value: "1" } - { option: "which", value: "both" } when: - - evolinux_packages_listchanges + - evolinux_packages_listchanges | bool - ansible_distribution == "Debian" - ansible_distribution_release == "jessie" diff --git a/evolinux-base/tasks/postfix.yml b/evolinux-base/tasks/postfix.yml index aa60e737..6a46548b 100644 --- a/evolinux-base/tasks/postfix.yml +++ b/evolinux-base/tasks/postfix.yml @@ -6,7 +6,7 @@ - postfix - mailgraph state: present - when: evolinux_postfix_packages + when: evolinux_postfix_packages | bool tags: - packages - postfix @@ -32,9 +32,10 @@ - postfix - name: fetch users list - shell: getent passwd | cut -d":" -f 1 | grep -v root + shell: "set -o pipefail && getent passwd | cut -d':' -f 1 | grep -v root" + args: + executable: /bin/bash check_mode: no - register: non_root_users_list changed_when: False tags: @@ -45,9 +46,9 @@ dest: /etc/aliases regexp: "^{{ item }}:.*" line: "{{ item }}: root" - with_items: "{{ non_root_users_list.stdout_lines }}" + loop: "{{ non_root_users_list.stdout_lines }}" notify: newaliases - when: evolinux_postfix_users_alias_root + when: evolinux_postfix_users_alias_root | bool tags: - postfix @@ -56,7 +57,7 @@ dest: /etc/aliases regexp: "^{{ item }}:.*" line: "{{ item }}: root" - with_items: + loop: - postmaster - abuse - mailer-daemon @@ -64,7 +65,7 @@ - error - bounce notify: newaliases - when: evolinux_postfix_mailer_alias_root + when: evolinux_postfix_mailer_alias_root | bool tags: - postfix @@ -74,7 +75,7 @@ regexp: "^root:" line: "root: {{ postfix_alias_email or general_alert_email | mandatory }}" notify: newaliases - when: evolinux_postfix_root_alias + when: evolinux_postfix_root_alias | bool tags: - postfix @@ -89,7 +90,7 @@ - exim4-daemon-light purge: yes state: absent - when: evolinux_postfix_purge_exim + when: evolinux_postfix_purge_exim | bool tags: - packages - postfix diff --git a/evolinux-base/tasks/provider_orange_fce.yml b/evolinux-base/tasks/provider_orange_fce.yml index 6cef30fb..4b9a26c7 100644 --- a/evolinux-base/tasks/provider_orange_fce.yml +++ b/evolinux-base/tasks/provider_orange_fce.yml @@ -5,7 +5,7 @@ sysctl_file: /etc/sysctl.d/evolinux_fce.conf state: present reload: yes - with_items: + loop: - { name: net.ipv4.tcp_keepalive_time, value: 250 } - { name: net.ipv4.tcp_keepalive_intvl, value: 60 } - { name: net.ipv6.conf.all.disable_ipv6, value: 1 } diff --git a/evolinux-base/tasks/root.yml b/evolinux-base/tasks/root.yml index 23f3cd9c..df50d977 100644 --- a/evolinux-base/tasks/root.yml +++ b/evolinux-base/tasks/root.yml @@ -5,7 +5,7 @@ path: /root state: directory mode: "0700" - when: evolinux_root_chmod + when: evolinux_root_chmod | bool - name: "Customize root's bashrc..." lineinfile: @@ -13,13 +13,13 @@ line: "{{ item }}" create: yes state: present - with_items: + loop: - "export HISTCONTROL=$HISTCONTROL${HISTCONTROL+,}ignoreboth,erasedups" - "export HISTSIZE=65535" - "export HISTTIMEFORMAT=\"%c : \"" - "shopt -s histappend" - "PROMPT_COMMAND=\"history -a;${PROMPT_COMMAND}\"" - when: evolinux_root_bashrc + when: evolinux_root_bashrc | bool ## .bash_history should be append-only @@ -28,14 +28,14 @@ content: "" dest: "/root/.bash_history" force: no - when: evolinux_root_bash_history + when: evolinux_root_bash_history | bool - name: Set umask in /root/.profile lineinfile: dest: "/root/.profile" line: "umask 0077" regexp: "umask [0-9]+" - when: evolinux_root_umask + when: evolinux_root_umask | bool - name: "/usr/share/scripts is present in root's PATH" lineinfile: @@ -48,7 +48,7 @@ src: root/gitconfig dest: "/root/.gitconfig" force: no - when: evolinux_root_gitconfig + when: evolinux_root_gitconfig | bool - name: Is .bash_history append-only shell: lsattr /root/.bash_history | grep -E "^.*a.* " @@ -61,7 +61,7 @@ - name: Set .bash_history append-only command: chattr +a /root/.bash_history when: - - evolinux_root_bash_history_appendonly + - evolinux_root_bash_history_appendonly | bool - bash_history_append_only.rc != 0 - "'Inappropriate ioctl' not in bash_history_append_only.stderr" @@ -71,7 +71,7 @@ regexp: '^SELECTED_EDITOR=' line: "SELECTED_EDITOR=\"/usr/bin/vim.basic\"" create: yes - when: evolinux_root_vim_default + when: evolinux_root_vim_default | bool - name: Setting vim root configuration lineinfile: @@ -79,14 +79,14 @@ line: "{{ item }}" create: yes state: present - with_items: + loop: - "syntax on" - "set background=dark" - "set expandtab" - "set tabstop=4" - "set softtabstop=4" - "set shiftwidth=4" - when: evolinux_root_vim_conf + when: evolinux_root_vim_conf | bool - name: disable SSH access for root replace: @@ -95,7 +95,7 @@ replace: "PermitRootLogin no" validate: '/usr/sbin/sshd -t -f %s' notify: reload sshd - when: evolinux_root_disable_ssh + when: evolinux_root_disable_ssh | bool ### Disabled : it seems useless and too dangerous for now # - name: remove root from AllowUsers directive diff --git a/evolinux-base/tasks/ssh.yml b/evolinux-base/tasks/ssh.yml index 2816af7f..e063d164 100644 --- a/evolinux-base/tasks/ssh.yml +++ b/evolinux-base/tasks/ssh.yml @@ -51,7 +51,7 @@ regexp: '^AcceptEnv' replace: "#AcceptEnv" notify: reload sshd - when: evolinux_ssh_disable_acceptenv + when: evolinux_ssh_disable_acceptenv | bool - name: Set log level to verbose (for Debian >= 9) replace: @@ -66,7 +66,7 @@ changed_when: False register: logname check_mode: no - when: evolinux_ssh_allow_current_user + when: evolinux_ssh_allow_current_user | bool # we must double-escape caracters, because python - name: verify AllowUsers directive @@ -75,7 +75,7 @@ changed_when: False register: grep_allowusers_ssh check_mode: no - when: evolinux_ssh_allow_current_user + when: evolinux_ssh_allow_current_user | bool - name: "Add AllowUsers sshd directive for current user" lineinfile: diff --git a/evolinux-base/tasks/system.yml b/evolinux-base/tasks/system.yml index 55820890..53fa243c 100644 --- a/evolinux-base/tasks/system.yml +++ b/evolinux-base/tasks/system.yml @@ -5,7 +5,7 @@ path: /tmp state: directory mode: "u=rwx,g=rwx,o=rwxt" - when: evolinux_system_chmod_tmp + when: evolinux_system_chmod_tmp | bool - name: Setting default locales lineinfile: @@ -13,12 +13,12 @@ line: "{{ item }}" create: yes state: present - with_items: + loop: - "en_US.UTF-8 UTF-8" - "fr_FR ISO-8859-1" - "fr_FR.UTF-8 UTF-8" register: default_locales - when: evolinux_system_locales + when: evolinux_system_locales | bool - name: Reconfigure locales command: /usr/sbin/locale-gen @@ -28,7 +28,7 @@ timezone: name: "{{ evolinux_system_timezone | mandatory }}" notify: restart cron - when: evolinux_system_set_timezone + when: evolinux_system_set_timezone | bool # TODO : find a way to force the console-data configuration # non-interactively (like tzdata ↑) @@ -41,13 +41,13 @@ dest: /etc/vim/vimrc regexp: 'let g:skip_defaults_vim =' line: 'let g:skip_defaults_vim = 1' - when: evolinux_system_vim_skip_defaults + when: evolinux_system_vim_skip_defaults | bool - name: Setting vim as default editor alternatives: name: editor path: /usr/bin/vim.basic - when: evolinux_system_vim_default_editor + when: evolinux_system_vim_default_editor | bool - name: Add "umask 027" to /etc/profile.d/evolinux.sh lineinfile: @@ -55,14 +55,14 @@ line: "umask 027" create: yes state: present - when: evolinux_system_profile + when: evolinux_system_profile | bool - name: Set /etc/adduser.conf DIR_MODE to 0700 replace: dest: /etc/adduser.conf regexp: "^DIR_MODE=0755$" replace: "DIR_MODE=0700" - when: evolinux_system_dirmode_adduser + when: evolinux_system_dirmode_adduser | bool # TODO: trouver comment ne pas faire ça sur Xen Dom-U @@ -72,7 +72,7 @@ line: "tty2" create: yes state: present - when: evolinux_system_restrict_securetty + when: evolinux_system_restrict_securetty | bool - name: Setting TMOUT to disconnect inactive users lineinfile: @@ -80,15 +80,17 @@ line: "export TMOUT=36000" create: yes state: present - when: evolinux_system_set_timeout + when: evolinux_system_set_timeout | bool #- name: Customizing /etc/fstab - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False - check_mode: no register: is_cron_installed - name: Set verbose logging for cron deamon @@ -97,7 +99,9 @@ line: "EXTRA_OPTS='-L 15'" create: yes state: present - when: is_cron_installed.rc == 0 and evolinux_system_cron_verboselog + when: + - is_cron_installed.rc == 0 + - evolinux_system_cron_verboselog | bool - name: Modify default umask for cron deamon lineinfile: @@ -105,19 +109,23 @@ line: "umask 022" create: yes state: present - when: is_cron_installed.rc == 0 and evolinux_system_cron_umask + when: + - is_cron_installed.rc == 0 + - evolinux_system_cron_umask | bool - name: Randomize periodic crontabs replace: dest: /etc/crontab regexp: "{{ item.regexp }}" replace: "{{ item.replace }}" - with_items: + loop: - { regexp: '^17((\s*\*){4})', replace: '{{ 59|random(start=1) }}\1' } - { regexp: '^25\s*6((\s*\*){3})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } - { regexp: '^47\s*6((\s*\*){2}\s*7)', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } - { regexp: '^52\s*6(\s*1(\s*\*){2})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } - when: is_cron_installed.rc == 0 and evolinux_system_cron_random + when: + - is_cron_installed.rc == 0 + - evolinux_system_cron_random | bool - include_role: name: evolix/ntpd @@ -131,7 +139,7 @@ force: no mode: "0755" when: - - evolinux_system_alert5_init + - evolinux_system_alert5_init | bool - ansible_distribution_release == "jessie" or ansible_distribution_release == "stretch" - name: Enable alert5 init script (jessie/stretch) @@ -139,8 +147,8 @@ name: alert5 enabled: yes when: - - evolinux_system_alert5_init - - evolinux_system_alert5_enable + - evolinux_system_alert5_init | bool + - evolinux_system_alert5_enable | bool - ansible_distribution_release == "jessie" or ansible_distribution_release == "stretch" @@ -152,7 +160,7 @@ force: no mode: "0755" when: - - evolinux_system_alert5_init + - evolinux_system_alert5_init | bool - ansible_distribution_major_version is version('10', '>=') - name: Install alert5 service (buster) @@ -162,7 +170,7 @@ force: yes mode: "0644" when: - - evolinux_system_alert5_init + - evolinux_system_alert5_init | bool - ansible_distribution_major_version is version('10', '>=') - name: Enable alert5 init script (buster) @@ -171,8 +179,8 @@ daemon_reload: yes enabled: yes when: - - evolinux_system_alert5_init - - evolinux_system_alert5_enable + - evolinux_system_alert5_init | bool + - evolinux_system_alert5_enable | bool - ansible_distribution_major_version is version('10', '>=') ## network interfaces @@ -189,7 +197,9 @@ dest: /etc/network/interfaces regexp: "allow-hotplug" replace: "auto" - when: evolinux_system_eni_auto and grep_hotplug_eni.rc == 0 + when: + - evolinux_system_eni_auto | bool + - grep_hotplug_eni.rc == 0 ## /sbin/deny diff --git a/evolinux-base/templates/motd/motd.default.j2 b/evolinux-base/templates/motd/motd.default.j2 new file mode 100644 index 00000000..9f03958a --- /dev/null +++ b/evolinux-base/templates/motd/motd.default.j2 @@ -0,0 +1,4 @@ +This server has been installed with Evolix Ansible roles. +https://gitea.evolix.org/evolix/ansible-roles + +--- diff --git a/evolinux-todo/meta/main.yml b/evolinux-todo/meta/main.yml index b1936540..bf350519 100644 --- a/evolinux-todo/meta/main.yml +++ b/evolinux-todo/meta/main.yml @@ -7,13 +7,14 @@ galaxy_info: license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/evolinux-todo/tasks/cat.yml b/evolinux-todo/tasks/cat.yml index 9cebeca5..58e3ba4c 100644 --- a/evolinux-todo/tasks/cat.yml +++ b/evolinux-todo/tasks/cat.yml @@ -10,4 +10,4 @@ - name: "Content of /etc/evolinux/todo.txt" debug: var: evolinux_todo.stdout_lines - when: evolinux_todo.stdout != "" + when: evolinux_todo.stdout | length > 0 diff --git a/evolinux-users/meta/main.yml b/evolinux-users/meta/main.yml index 8e019209..bac538ed 100644 --- a/evolinux-users/meta/main.yml +++ b/evolinux-users/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Creates evolinux users accounts. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/evolinux-users/tasks/main.yml b/evolinux-users/tasks/main.yml index b3be0c8d..8f12ba1b 100644 --- a/evolinux-users/tasks/main.yml +++ b/evolinux-users/tasks/main.yml @@ -9,22 +9,22 @@ - debug: msg: "Warning: empty 'evolinux_users' variable, tasks will be skipped!" - when: evolinux_users == {} + when: evolinux_users | length == 0 - name: Create user accounts include: user.yml vars: user: "{{ item.value }}" - with_dict: "{{ evolinux_users }}" - when: evolinux_users != {} + loop: "{{ evolinux_users | dict2items }}" + when: evolinux_users | length > 0 - name: Configure sudo include: sudo.yml vars: user: "{{ item.value }}" - with_dict: "{{ evolinux_users }}" - when: evolinux_users != {} + loop: "{{ evolinux_users | dict2items }}" + when: evolinux_users | length > 0 - name: Configure SSH include: ssh.yml - when: evolinux_users != {} + when: evolinux_users | length > 0 diff --git a/evolinux-users/tasks/ssh.yml b/evolinux-users/tasks/ssh.yml index e21f0978..ac2fdf12 100644 --- a/evolinux-users/tasks/ssh.yml +++ b/evolinux-users/tasks/ssh.yml @@ -48,7 +48,7 @@ - include: ssh_allowusers.yml vars: user: "{{ item.value }}" - with_dict: "{{ evolinux_users }}" + loop: "{{ evolinux_users | dict2items }}" when: - ssh_allowusers - not ssh_allowgroups @@ -59,6 +59,6 @@ regexp: '^PermitRootLogin (yes|without-password|prohibit-password)' replace: "PermitRootLogin no" notify: reload sshd - when: evolinux_root_disable_ssh + when: evolinux_root_disable_ssh | bool - meta: flush_handlers diff --git a/evolinux-users/tasks/sudo.yml b/evolinux-users/tasks/sudo.yml index 6f127da8..c27f5a29 100644 --- a/evolinux-users/tasks/sudo.yml +++ b/evolinux-users/tasks/sudo.yml @@ -4,6 +4,8 @@ when: ansible_distribution_release == "jessie" - include: sudo_stretch.yml - when: ansible_distribution_major_version is defined and ansible_distribution_major_version is version('9', '>=') + when: + - ansible_distribution_major_version is defined + - ansible_distribution_major_version is version('9', '>=') - meta: flush_handlers diff --git a/evolinux-users/tasks/sudo_jessie.yml b/evolinux-users/tasks/sudo_jessie.yml index f675954e..d3f70198 100644 --- a/evolinux-users/tasks/sudo_jessie.yml +++ b/evolinux-users/tasks/sudo_jessie.yml @@ -15,4 +15,4 @@ regexp: '^(User_Alias\s+ADMINS\s+=((?!{{ user.name }}).)*)$' replace: '\1,{{ user.name }}' validate: '/usr/sbin/visudo -cf %s' - when: not copy_sudoers_evolinux.changed + when: copy_sudoers_evolinux is not changed diff --git a/evolinux-users/tasks/user.yml b/evolinux-users/tasks/user.yml index b8dda1d2..0f8bd480 100644 --- a/evolinux-users/tasks/user.yml +++ b/evolinux-users/tasks/user.yml @@ -4,11 +4,11 @@ - fail: msg: "You must provide a value for the 'user.name ' variable." - when: user.name is not defined or user.name == '' + when: (user.name is not defined) or (user.name | length == 0) - fail: msg: "You must provide a value for the 'user.uid ' variable." - when: user.uid is not defined or user.uid == '' + when: (user.uid is not defined) or (user.uid | string | length == 0) - name: "Test if '{{ user.name }}' exists" command: 'id -u "{{ user.name }}"' @@ -102,7 +102,7 @@ state: present when: - evolinux_internal_group is defined - - evolinux_internal_group != "" + - evolinux_internal_group | length > 0 - ansible_distribution_major_version is version('9', '>=') - name: "Unix user '{{ user.name }}' belongs to group '{{ evolinux_internal_group }}' (Debian 9 or later)" @@ -112,7 +112,7 @@ append: yes when: - evolinux_internal_group is defined - - evolinux_internal_group != "" + - evolinux_internal_group | length > 0 - ansible_distribution_major_version is version('9', '>=') ## Optional secondary groups, defined per user @@ -120,12 +120,12 @@ - name: "Secondary Unix groups are present" group: name: "{{ group }}" - with_items: "{{ user.groups }}" + loop: "{{ user.groups }}" loop_control: loop_var: group when: - user.groups is defined - - user.groups != [] + - user.groups | length > 0 - name: "Unix user '{{ user.name }}' belongs to secondary groups" user: @@ -134,7 +134,7 @@ append: yes when: - user.groups is defined - - user.groups != [] + - user.groups | length > 0 # Permissions on home directory @@ -177,16 +177,20 @@ user: "{{ user.name }}" key: "{{ user.ssh_key }}" state: present - when: user.ssh_key is defined + when: + - user.ssh_key is defined + - user.ssh_key | length > 0 - name: "SSH public keys for '{{ user.name }}' are present" authorized_key: user: "{{ user.name }}" key: "{{ ssk_key }}" state: present - with_items: "{{ user.ssh_keys }}" + loop: "{{ user.ssh_keys }}" loop_control: loop_var: ssk_key - when: user.ssh_keys is defined + when: + - user.ssh_keys is defined + - user.ssh_keys | length > 0 - meta: flush_handlers diff --git a/evomaintenance/files/evomaintenance.sh b/evomaintenance/files/evomaintenance.sh index 1cd4ce7f..1961ebf2 100644 --- a/evomaintenance/files/evomaintenance.sh +++ b/evomaintenance/files/evomaintenance.sh @@ -4,16 +4,16 @@ # Dependencies (all OS): git postgresql-client # Dependencies (Debian): sudo -# Copyright 2007-2019 Evolix , Gregory Colpart , +# Copyright 2007-2021 Evolix , Gregory Colpart , # Jérémy Lecour and others. -VERSION="0.6.3" +VERSION="0.6.4" show_version() { cat <, +Copyright 2007-2021 Evolix , Gregory Colpart , Jérémy Lecour and others. @@ -178,9 +178,11 @@ is_repository_readonly() { if [ "$(get_system)" = "OpenBSD" ]; then partition=$(stat -f '%Sd' $1) mount | grep ${partition} | grep -q "read-only" - else + elif command -v findmnt >/dev/null; then mountpoint=$(stat -c '%m' $1) findmnt ${mountpoint} --noheadings --output OPTIONS -O ro + else + grep /usr /proc/mounts | grep -E '\bro\b' fi } remount_repository_readwrite() { diff --git a/evomaintenance/meta/main.yml b/evomaintenance/meta/main.yml index cb592aea..0e672054 100644 --- a/evomaintenance/meta/main.yml +++ b/evomaintenance/meta/main.yml @@ -7,14 +7,14 @@ galaxy_info: license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - stretch - - jessie - - squeeze + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/evomaintenance/tasks/install_vendor_debian.yml b/evomaintenance/tasks/install_vendor_debian.yml index a3d29b95..2faaac79 100644 --- a/evomaintenance/tasks/install_vendor_debian.yml +++ b/evomaintenance/tasks/install_vendor_debian.yml @@ -14,7 +14,7 @@ name: - postgresql-client state: present - when: evomaintenance_hook_db + when: evomaintenance_hook_db | bool tags: - evomaintenance @@ -42,7 +42,7 @@ mode: "{{ item.mode }}" force: yes backup: yes - with_items: + loop: - { src: 'evomaintenance.sh', dest: '/usr/share/scripts/', mode: '0700' } - { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/', mode: '0600' } tags: diff --git a/evomaintenance/tasks/install_vendor_openbsd.yml b/evomaintenance/tasks/install_vendor_openbsd.yml deleted file mode 100644 index 37307cfb..00000000 --- a/evomaintenance/tasks/install_vendor_openbsd.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- - -- name: Dependencies are installed - openbsd_pkg: - name: - - postgresql-client - - curl - state: present - tags: - - evomaintenance - -- name: /usr/share/scripts exists - file: - dest: /usr/share/scripts - mode: "0700" - owner: root - group: wheel - state: directory - tags: - - evomaintenance - -- name: Evomaintenance script and template are installed - copy: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: root - group: wheel - mode: "{{ item.mode }}" - force: yes - backup: yes - with_items: - - { src: 'evomaintenance.sh', dest: '/usr/share/scripts/', mode: '0700' } - - { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/', mode: '0600' } - tags: - - evomaintenance - -- name: Configuration is installed - template: - src: evomaintenance.j2 - dest: /etc/evomaintenance.cf - owner: root - group: wheel - mode: "0600" - force: "{{ evomaintenance_force_config | bool }}" - tags: - - evomaintenance - -- name: Copy mailevomaintenance - template: - src: mailevomaintenance.sh.j2 - dest: /usr/share/scripts/mailevomaintenance.sh - owner: root - group: wheel - mode: "0700" - tags: - - evomaintenance - -- name: Add mailevomaintenance cron - cron: - name: "mailevomaintenance" - job: "/usr/share/scripts/mailevomaintenance.sh" - minute: "50" - hour: "22" - disabled: yes - tags: - - mailevomaintenance diff --git a/evomaintenance/tasks/main.yml b/evomaintenance/tasks/main.yml index d56a124a..9826089b 100644 --- a/evomaintenance/tasks/main.yml +++ b/evomaintenance/tasks/main.yml @@ -1,7 +1,7 @@ --- - set_fact: - minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" + minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" - assert: that: @@ -11,19 +11,15 @@ - include: install_package_debian.yml when: - - not evomaintenance_install_vendor + - not (evomaintenance_install_vendor | bool) - ansible_distribution == "Debian" - include: install_vendor_debian.yml when: - - evomaintenance_install_vendor + - evomaintenance_install_vendor | bool - ansible_distribution == "Debian" -- include: install_vendor_openbsd.yml - when: - - ansible_distribution == "OpenBSD" - - include: minifirewall.yml when: - - evomaintenance_hook_db + - evomaintenance_hook_db | bool - ansible_distribution == "Debian" diff --git a/evomaintenance/tasks/minifirewall.yml b/evomaintenance/tasks/minifirewall.yml index fc6ed0a5..ad48e856 100644 --- a/evomaintenance/tasks/minifirewall.yml +++ b/evomaintenance/tasks/minifirewall.yml @@ -12,7 +12,7 @@ dest: /etc/default/minifirewall line: "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s {{ item }} -m state --state ESTABLISHED,RELATED -j ACCEPT" insertafter: "^# EvoMaintenance" - with_items: "{{ evomaintenance_hosts }}" + loop: "{{ evomaintenance_hosts }}" notify: "{{ minifirewall_restart_handler_name }}" when: minifirewall_default_file.stat.exists tags: @@ -31,6 +31,6 @@ - name: Force restart minifirewall command: /bin/true notify: restart minifirewall - when: minifirewall_restart_force + when: minifirewall_restart_force | bool tags: - evomaintenance diff --git a/fail2ban/meta/main.yml b/fail2ban/meta/main.yml index 5b80af79..54bdf4e8 100644 --- a/fail2ban/meta/main.yml +++ b/fail2ban/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Install Fail2ban and a few filters. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/fail2ban/tasks/main.yml b/fail2ban/tasks/main.yml index e496c07e..30c795c9 100644 --- a/fail2ban/tasks/main.yml +++ b/fail2ban/tasks/main.yml @@ -9,7 +9,7 @@ owner: root group: root mode: "0755" - with_items: + loop: - "/etc/fail2ban" - "/etc/fail2ban/filter.d" tags: @@ -32,7 +32,7 @@ - name: Include ignoredips update task include: ip_whitelist.yml - when: fail2ban_force_update_ignore_ips + when: fail2ban_force_update_ignore_ips | bool tags: - fail2ban @@ -43,7 +43,7 @@ option: enabled value: false notify: restart fail2ban - when: fail2ban_disable_ssh + when: fail2ban_disable_ssh | bool tags: - fail2ban @@ -52,7 +52,7 @@ src: "{{ item }}" dest: /etc/fail2ban/filter.d/ mode: "0644" - with_items: + loop: - dovecot-evolix.conf - sasl-evolix.conf - wordpress-soft.conf diff --git a/filebeat/files/elastic.asc b/filebeat/files/elastic.asc new file mode 100644 index 00000000..1b50dcca --- /dev/null +++ b/filebeat/files/elastic.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/filebeat/meta/main.yml b/filebeat/meta/main.yml index 97898e88..ce487942 100644 --- a/filebeat/meta/main.yml +++ b/filebeat/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Filebeat. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/filebeat/tasks/main.yml b/filebeat/tasks/main.yml index a19848e8..034808d3 100644 --- a/filebeat/tasks/main.yml +++ b/filebeat/tasks/main.yml @@ -5,17 +5,29 @@ name: apt-transport-https state: present tags: - - filebeat - - packages + - filebeat + - packages + +- name: Elastic embedded GPG key is absent + apt_key: + id: "D88E42B4" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - filebeat + - packages - name: Elastic GPG key is installed - apt_key: - # url: https://artifacts.elastic.co/GPG-KEY-elasticsearch - data: "{{ lookup('file', 'elasticsearch.key') }}" - state: present + copy: + src: elastic.asc + dest: /etc/apt/trusted.gpg.d/elastic.asc + force: yes + mode: "0644" + owner: root + group: root tags: - - filebeat - - packages + - filebeat + - packages - name: Elastic sources list is available apt_repository: @@ -24,8 +36,8 @@ state: present update_cache: yes tags: - - filebeat - - packages + - filebeat + - packages - name: Filebeat is installed apt: @@ -54,7 +66,9 @@ register: logstash_plugin_installed failed_when: false changed_when: false - when: filebeat_logstash_plugin and logstash_plugin.stat.exists + when: + - filebeat_logstash_plugin | bool + - logstash_plugin.stat.exists - name: Logstash plugin is installed block: @@ -64,9 +78,9 @@ - name: logstash-plugin install logstash-input-beats command: /usr/share/logstash/bin/logstash-plugin install logstash-input-beats when: - - filebeat_logstash_plugin + - filebeat_logstash_plugin | bool - logstash_plugin.stat.exists - - not logstash_plugin_installed | success + - not (logstash_plugin_installed | success) # When we don't use a config template (default) - block: @@ -76,7 +90,7 @@ regexp: '^(\s+)(- add_cloud_metadata:)' replace: '\1# \2' notify: restart filebeat - when: not filebeat_processors_cloud_metadata + when: not (filebeat_processors_cloud_metadata | bool) - name: cloud_metadata processor is disabled lineinfile: @@ -84,7 +98,7 @@ line: " - add_cloud_metadata: ~" insert_after: '^processors:' notify: restart filebeat - when: filebeat_processors_cloud_metadata + when: filebeat_processors_cloud_metadata | bool - name: Filebeat knows where to find Elasticsearch lineinfile: @@ -93,8 +107,7 @@ line: " hosts: [\"{{ filebeat_elasticsearch_hosts | join('\", \"') }}\"]" insertafter: "output.elasticsearch:" notify: restart filebeat - when: - - filebeat_elasticsearch_hosts + when: filebeat_elasticsearch_hosts | length > 0 - name: Filebeat protocol for Elasticsearch lineinfile: @@ -111,14 +124,14 @@ regexp: '{{ item.regexp }}' line: '{{ item.line }}' insertafter: "output.elasticsearch:" - with_items: + loop: - { regexp: '^ #?username: .*', line: ' username: "{{ filebeat_elasticsearch_auth_username }}"' } - { regexp: '^ #?password: .*', line: ' password: "{{ filebeat_elasticsearch_auth_password }}"' } notify: restart filebeat when: - - filebeat_elasticsearch_auth_username - - filebeat_elasticsearch_auth_password - when: not filebeat_use_config_template + - filebeat_elasticsearch_auth_username | length > 0 + - filebeat_elasticsearch_auth_password | length > 0 + when: not (filebeat_use_config_template | bool) - name: Filebeat api_key for Elasticsearch are configured lineinfile: @@ -127,7 +140,7 @@ line: ' api_key: "{{ filebeat_elasticsearch_auth_api_key }}"' insertafter: "output.elasticsearch:" notify: restart filebeat - when: filebeat_elasticsearch_auth_api_key + when: filebeat_elasticsearch_auth_api_key | length > 0 # When we use a config template - block: @@ -136,11 +149,13 @@ src: "{{ item }}" dest: /etc/filebeat/filebeat.yml force: "{{ filebeat_force_config }}" - with_first_found: - - "templates/filebeat/filebeat.{{ inventory_hostname }}.yml.j2" - - "templates/filebeat/filebeat.{{ host_group }}.yml.j2" - - "templates/filebeat/filebeat.default.yml.j2" - - "filebeat.default.yml.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/filebeat/filebeat.{{ inventory_hostname }}.yml.j2" + - "templates/filebeat/filebeat.{{ host_group | default('all') }}.yml.j2" + - "templates/filebeat/filebeat.default.yml.j2" + - "templates/filebeat.default.yml.j2" notify: restart filebeat - when: filebeat_update_config - when: filebeat_use_config_template + when: filebeat_update_config | bool + when: filebeat_use_config_template | bool diff --git a/fluentd/defaults/main.yml b/fluentd/defaults/main.yml index c17cb312..86475f51 100644 --- a/fluentd/defaults/main.yml +++ b/fluentd/defaults/main.yml @@ -3,10 +3,10 @@ fluentd_daemon: td-agent fluentd_conf_path: /etc/td-agent/td-agent.conf fluentd_port: 24230 -fluentd_bind_interface: +fluentd_bind_interface: -fluentd_host: -fluentd_host_port: +fluentd_host: +fluentd_host_port: -fluentd_flush_interval: +fluentd_flush_interval: fluentd_heartbeat_type: diff --git a/fluentd/files/fluentd.gpg b/fluentd/files/fluentd.asc similarity index 100% rename from fluentd/files/fluentd.gpg rename to fluentd/files/fluentd.asc diff --git a/fluentd/meta/main.yml b/fluentd/meta/main.yml index 3bbff0c4..ff74528b 100644 --- a/fluentd/meta/main.yml +++ b/fluentd/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Fluentd. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/fluentd/tasks/main.yml b/fluentd/tasks/main.yml index 41c532d1..159748e6 100644 --- a/fluentd/tasks/main.yml +++ b/fluentd/tasks/main.yml @@ -1,9 +1,22 @@ --- -- name: Fluentd GPG key is installed +- name: Fluentd embedded GPG key is absent apt_key: - # url: https://packages.treasuredata.com/GPG-KEY-td-agent - data: "{{ lookup('file', 'fluentd.gpg') }}" + id: "AB97ACBE" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - packages + - fluentd + +- name: Add Fluentd GPG key + copy: + src: fluentd.asc + dest: /etc/apt/trusted.gpg.d/fluentd.asc + force: yes + mode: "0644" + owner: root + group: root tags: - packages - fluentd diff --git a/haproxy/defaults/main.yml b/haproxy/defaults/main.yml index 3e3ec047..b94d2872 100644 --- a/haproxy/defaults/main.yml +++ b/haproxy/defaults/main.yml @@ -19,7 +19,7 @@ haproxy_stats_external_url: "{% if haproxy_stats_ssl %}https:{% else %}http:{% e haproxy_stats_access_ips: [] haproxy_stats_admin_ips: [] haproxy_stats_users: [] -## use crypt(8) password encryption +## use crypt(8) password encryption # haproxy_stats_users: # - { login: "", password: "" } diff --git a/haproxy/meta/main.yml b/haproxy/meta/main.yml index 32b06065..be1f56a8 100644 --- a/haproxy/meta/main.yml +++ b/haproxy/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of HAProxy issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/haproxy/tasks/main.yml b/haproxy/tasks/main.yml index 972429c4..d29e3cbc 100644 --- a/haproxy/tasks/main.yml +++ b/haproxy/tasks/main.yml @@ -84,7 +84,7 @@ - update-config - include: packages_backports.yml - when: haproxy_backports + when: haproxy_backports | bool - name: Install HAProxy package apt: @@ -100,13 +100,15 @@ dest: /etc/haproxy/haproxy.cfg force: "{{ haproxy_force_config }}" validate: "haproxy -c -f %s" - with_first_found: - - "templates/haproxy/haproxy.{{ inventory_hostname }}.cfg.j2" - - "templates/haproxy/haproxy.{{ host_group }}.cfg.j2" - - "templates/haproxy/haproxy.default.cfg.j2" - - "haproxy.default.cfg.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/haproxy/haproxy.{{ inventory_hostname }}.cfg.j2" + - "templates/haproxy/haproxy.{{ host_group | default('all') }}.cfg.j2" + - "templates/haproxy/haproxy.default.cfg.j2" + - "templates/haproxy.default.cfg.j2" notify: reload haproxy - when: haproxy_update_config + when: haproxy_update_config | bool tags: - haproxy - config diff --git a/java/meta/main.yml b/java/meta/main.yml index 9f4d9ab5..719b9ee0 100644 --- a/java/meta/main.yml +++ b/java/meta/main.yml @@ -1,16 +1,26 @@ --- galaxy_info: - author: Evolix + company: Evolix description: Installation of Java issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. diff --git a/java/tasks/main.yml b/java/tasks/main.yml index f6de0b43..f899bf1c 100644 --- a/java/tasks/main.yml +++ b/java/tasks/main.yml @@ -4,7 +4,7 @@ # when: java_version != 8 - include: openjdk.yml - when: "{{ java_alternative == 'openjdk' }}" + when: java_alternative == 'openjdk' - include: oracle.yml - when: "{{ java_alternative == 'oracle' }}" + when: java_alternative == 'oracle' diff --git a/java/tasks/openjdk.yml b/java/tasks/openjdk.yml index 8e187d1b..b41db0a7 100644 --- a/java/tasks/openjdk.yml +++ b/java/tasks/openjdk.yml @@ -26,6 +26,6 @@ alternatives: name: java path: "{{ java_bin_path[java_version] }}" - when: java_default_alternative + when: java_default_alternative | bool tags: - java diff --git a/java/tasks/oracle.yml b/java/tasks/oracle.yml index a2268b7b..c2ab5ebf 100644 --- a/java/tasks/oracle.yml +++ b/java/tasks/oracle.yml @@ -13,7 +13,7 @@ path: "{{ item }}" state: directory mode: "0777" - with_items: + loop: - /srv/java-package - /srv/java-package/src - /srv/java-package/tmp @@ -52,6 +52,6 @@ alternatives: name: java path: "/usr/lib/jvm/oracle-java{{ java_version }}-server-jre-amd64/bin/java" - when: java_default_alternative + when: java_default_alternative | bool tags: - java diff --git a/jenkins/files/jenkins.key b/jenkins/files/jenkins.asc similarity index 100% rename from jenkins/files/jenkins.key rename to jenkins/files/jenkins.asc diff --git a/jenkins/meta/main.yml b/jenkins/meta/main.yml index 7120e512..253b4372 100644 --- a/jenkins/meta/main.yml +++ b/jenkins/meta/main.yml @@ -1,18 +1,20 @@ --- galaxy_info: - author: Evolix + company: Evolix description: Install Jenkins issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/jenkins/tasks/main.yml b/jenkins/tasks/main.yml index a2e7c0aa..da23e5f5 100644 --- a/jenkins/tasks/main.yml +++ b/jenkins/tasks/main.yml @@ -5,10 +5,20 @@ # http://mirrors.jenkins.io/.* # http://jenkins.mirror.isppower.de/.* -- name: Add jenkins GPG key +- name: Jenkins embedded GPG key is absent apt_key: - # url: https://jenkins-ci.org/debian/jenkins-ci.org.key - data: "{{ lookup('file', 'jenkins.key') }}" + id: "D50582E6" + keyring: /etc/apt/trusted.gpg + state: absent + +- name: Add Jenkins GPG key + copy: + src: jenkins.asc + dest: /etc/apt/trusted.gpg.d/jenkins.asc + force: yes + mode: "0644" + owner: root + group: root - name: Add jenkins APT repository apt_repository: diff --git a/keepalived/tasks/main.yml b/keepalived/tasks/main.yml index dee97bca..807713a8 100644 --- a/keepalived/tasks/main.yml +++ b/keepalived/tasks/main.yml @@ -1,3 +1,5 @@ +--- + - name: install Keepalived service apt: pkg: keepalived diff --git a/kibana/files/elastic.asc b/kibana/files/elastic.asc new file mode 100644 index 00000000..1b50dcca --- /dev/null +++ b/kibana/files/elastic.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/kibana/meta/main.yml b/kibana/meta/main.yml index 4b8408f6..25034e03 100644 --- a/kibana/meta/main.yml +++ b/kibana/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Kibana. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/kibana/tasks/main.yml b/kibana/tasks/main.yml index 46fbe980..1ed342e0 100644 --- a/kibana/tasks/main.yml +++ b/kibana/tasks/main.yml @@ -5,17 +5,29 @@ name: apt-transport-https state: present tags: - - kibana - - packages + - kibana + - packages + +- name: Elastic embedded GPG key is absent + apt_key: + id: "D88E42B4" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - kibana + - packages - name: Elastic GPG key is installed - apt_key: - # url: https://artifacts.elastic.co/GPG-KEY-elasticsearch - data: "{{ lookup('file', 'elasticsearch.key') }}" - state: present + copy: + src: elastic.asc + dest: /etc/apt/trusted.gpg.d/elastic.asc + force: yes + mode: "0644" + owner: root + group: root tags: - - kibana - - packages + - kibana + - packages - name: Elastic sources list is available apt_repository: @@ -24,14 +36,15 @@ state: present update_cache: yes tags: - - kibana - - packages + - kibana + - packages - name: Kibana is installed apt: name: kibana state: present tags: + - kibana - packages - name: kibana server host configuration @@ -41,6 +54,8 @@ regexp: '^server.host:' insertafter: '^#server.host:' notify: restart kibana + tags: + - kibana - name: kibana server basepath configuration lineinfile: @@ -49,6 +64,8 @@ regexp: '^server.basePath:' insertafter: '^#server.basePath:' notify: restart kibana + tags: + - kibana - name: kibana log destination is present file: @@ -57,6 +74,8 @@ group: kibana mode: "0750" state: directory + tags: + - kibana - name: kibana log messages go to custom file lineinfile: @@ -65,12 +84,16 @@ regexp: '^logging.dest:' insertafter: '^#logging.dest:' notify: restart kibana + tags: + - kibana - name: Kibana service is enabled and started systemd: name: kibana enabled: yes state: started + tags: + - kibana - name: Logrotate configuration is enabled copy: @@ -79,6 +102,8 @@ mode: "0644" owner: root group: root + tags: + - kibana # - name: Get mount options for /usr partition # shell: "mount | grep 'on /usr type'" @@ -98,9 +123,9 @@ # args: # creates: "/var/lib/kibana/{{ item }}" # notify: restart kibana -# with_items: +# loop: # - optimize # - data - include: proxy_nginx.yml - when: kibana_proxy_nginx + when: kibana_proxy_nginx | bool diff --git a/kvm-host/defaults/main.yml b/kvm-host/defaults/main.yml index bb97c0f9..bec20a12 100644 --- a/kvm-host/defaults/main.yml +++ b/kvm-host/defaults/main.yml @@ -1,3 +1,4 @@ --- kvm_custom_libvirt_images_path: '' kvm_install_drbd: True +kvm_scripts_dir: /usr/local/sbin \ No newline at end of file diff --git a/kvm-host/files/add-vm.sh b/kvm-host/files/add-vm.sh new file mode 100755 index 00000000..ec50763d --- /dev/null +++ b/kvm-host/files/add-vm.sh @@ -0,0 +1,271 @@ +#!/bin/bash +# Add-VM script to add a VM on evoKVM. +# _ ____ ____ __ ____ __ +# / \ | _ \| _ \ \ \ / / \/ | +# / _ \ | | | | | | |____\ \ / /| |\/| | +# / ___ \| |_| | |_| |_____\ V / | | | | +# /_/ \_\____/|____/ \_/ |_| |_| +# +# Need packages: dialog +# Bash strict mode +set -euo pipefail + +isDryRun() { + test "${doDryRun}" = "true" +} + +dryRun() { + + if isDryRun; then + echo -e "\e[34mDoing:" "$*" "\e[39m" + else + echo -e "\e[34mDoing:" "$*" "\e[39m" + $* + fi +} + +critical() { + echo -ne "\e[31m${1}\e[39m\n" && exit 1 +} + +warn() { + + echo -ne "\e[33m${1}\e[39m\n" +} + +# shellcheck disable=SC1091 +[ -f "/etc/evolinux/add-vm.cnf" ] && . /etc/evolinux/add-vm.cnf +masterKVMIP="${masterKVMIP:-127.0.0.1}" +slaveKVMIP="${slaveKVMIP:-}" +disks="${disks:-}" +[ -n "${disks}" ] || disks=("ssd" "hdd") +bridgeName="${bridgeName:-br0}" +doDryRun=${doDryRun:-false} +isoImagePath="${isoImagePath:-}" +debianVersion="${debianAuto:-stable}" +preseedURL="${preseedURL:-}" +defaultVCPU="${defaultVCPU:-"2"}" +defaultRAM="${defaultRAM:-"4G"}" +defaultRootSize="${defaultRootSize:-"20G"}" +defaultHomeSize="${defaultHomeSize:-"40G"}" + +DIALOGOUT=$(mktemp --tmpdir=/tmp addvm.XXX) +export DIALOGOUT +# TODO: How to replace _ with a space?? +DIALOG="$(command -v dialog) --backtitle Add-VM_Press_F1_for_help" +export DIALOG +DIALOGRC=.dialogrc +export DIALOGRC +HELPFILE=$(mktemp --tmpdir=/tmp addvm.XXX) +export HELPFILE +tmpResFile=$(mktemp --tmpdir=/tmp addvm.XXX) +masterKVM="$(hostname -s)" +slaveKVM="$(ssh "${slaveKVMIP}" hostname -s)" + +# Exit & Cleanup function. +clean() { + echo -e "\nBye! Cleaning..." + rm -f "${DIALOGOUT}" + rm -f "${HELPFILE}" + exit +} +trap clean EXIT SIGINT + +${DIALOG} \ + --hfile "${HELPFILE}" \ + --title "KVM Config" \ + --form "Set the right config. If you do not want a type of disk, type none." 0 0 0 \ + "vCPU" 1 1 "${defaultVCPU}" 1 10 20 0 \ + "memory" 2 1 "${defaultRAM}" 2 10 20 0 \ + "volRoot" 3 1 "${disks[0]}-${defaultRootSize}" 3 10 20 0 \ + "volHome" 4 1 "${disks[1]}-${defaultHomeSize}" 4 10 20 0 \ + "vmName" 5 1 "" 5 10 20 0 \ + 2> "${DIALOGOUT}" + +vCPU=$(sed 1'q;d' "${DIALOGOUT}") +memory=$(sed 2'q;d' "${DIALOGOUT}" | tr -d 'G') +memory=$((memory * 1024 )) +volRoot=$(sed 3'q;d' "${DIALOGOUT}") +volHome=$(sed 4'q;d' "${DIALOGOUT}") +vmName=$(sed 5'q;d' "${DIALOGOUT}") + +if [ -z "${vmName}" ]; then + critical "You need a VM Name!!" +fi + +${DIALOG} \ + --title "Continue?" \ + --clear "$@" \ + --yesno "Will create a VM named ${vmName} on ${masterKVM} with ${vCPU} vCPU, ${memory} memory, ${volRoot} for / (and /usr, ...) and ${volHome} for /home." 10 80 +dialog_rc=$? + +if [[ ${dialog_rc} -ne 0 ]]; then + exit 1 +fi + +if ! [[ "${volRoot}" =~ ([^-]+)-([0-9]+G) ]]; then + critical "No volume for root device (/dev/vda)?!!" +else + volRootDisk="${BASH_REMATCH[1]}" + volRootSize="${BASH_REMATCH[2]}" + if [[ " ${disks[*]} " != *"${volRootDisk}"* ]]; then + critical "Unknow disk ${volRootDisk} !" + fi + dryRun lvcreate -L"${volRootSize}" -n"${vmName}_root" "${volRootDisk}" + dryRun ssh "${slaveKVMIP}" "lvcreate -L$volRootSize -n${vmName}_root ${volRootDisk}" +fi + +if ! [[ "${volHome}" =~ ([^-]+)-([0-9]+G) ]]; then + warn "No volume for home device (/dev/vdb)... Okay, not doing it!" + volHomeDisk="none" +else + volHomeDisk="${BASH_REMATCH[1]}" + volHomeSize="${BASH_REMATCH[2]}" + if [[ " ${disks[*]} " != *"${volHomeDisk}"* ]]; then + critical "Unknow disk ${volHomeDisk} !" + fi + dryRun lvcreate -L"${volHomeSize}" -n"${vmName}_home" "${volHomeDisk}" + dryRun ssh "${slaveKVMIP}" "lvcreate -L$volHomeSize -n${vmName}_home ${volHomeDisk}" +fi + +if [ -f "/etc/drbd.d/${vmName}.res" ]; then + warn "The DRBD resource file ${vmName}.res is already present! Continue? [y/N]" + read -r + if ! [[ "${REPLY}" =~ (Y|y) ]]; then + exit 1 + fi +fi + +# Generates drbd resource file. + +# shellcheck disable=SC2012 +if [ "$(ls /etc/drbd.d/ | wc -l)" -gt 1 ]; then + lastdrbdPort=$(grep -hEo ':[0-9]{4}' /etc/drbd.d/*.res | sort | uniq | tail -1 | sed 's/://') + drbdPort=$((lastdrbdPort+1)) + lastMinor=$(grep -hEo 'minor [0-9]{1,}' /etc/drbd.d/*.res | sed 's/minor //' | sort -n | tail -1) + minorvol0=$((lastMinor+1)) + minorvol1=$((lastMinor+2)) +else + drbdPort=7900 + minorvol0=0 + minorvol1=1 +fi + +cat << EOT > "${tmpResFile}" +resource "${vmName}" { + net { + cram-hmac-alg "sha1"; + shared-secret "$(apg -n 1 -m 16 -M lcN)"; + # Si pas de lien dedié 10G, passer en protocol A + # Et desactiver allow-two-primaries; + protocol C; + allow-two-primaries; + # Tuning perf. + max-buffers 8000; + max-epoch-size 8000; + sndbuf-size 0; + } + # A utiliser si RAID HW avec cache + batterie + disk { + disk-barrier no; + disk-flushes no; + } + volume 0 { + device minor ${minorvol0}; + disk /dev/${volRootDisk}/${vmName}_root; + meta-disk internal; + } +EOT +if [[ "${volHomeDisk}" != "none" ]]; then + cat << EOT >> "${tmpResFile}" + volume 1 { + device minor ${minorvol1}; + disk /dev/${volHomeDisk}/${vmName}_home; + meta-disk internal; + } +EOT +fi +cat << EOT >> "${tmpResFile}" + on ${masterKVM} { + address ${masterKVMIP}:${drbdPort}; + } + on ${slaveKVM} { + address ${slaveKVMIP}:${drbdPort}; + } +} +EOT + +# Create/Activate the new drbd resources. +drbdadm="$(command -v drbdadm)" +if isDryRun; then + drbdadm="${drbdadm} --dry-run" +fi + +if isDryRun; then + # shellcheck disable=SC2064 + trap "rm /etc/drbd.d/${vmName}.res && ssh ${slaveKVMIP} rm /etc/drbd.d/${vmName}.res" 0 +fi +install -m 600 "${tmpResFile}" "/etc/drbd.d/${vmName}.res" +scp "/etc/drbd.d/${vmName}.res" "${slaveKVMIP}:/etc/drbd.d/" +${drbdadm} create-md "${vmName}" +# shellcheck disable=SC2029 +ssh "${slaveKVMIP}" "${drbdadm} create-md ${vmName}" +${drbdadm} adjust "${vmName}" +# shellcheck disable=SC2029 +ssh "${slaveKVMIP}" "${drbdadm} adjust ${vmName}" +${drbdadm} -- --overwrite-data-of-peer primary "${vmName}" + +if ! isDryRun; then + sleep 5 + drbd-overview | tail -4 + + drbdDiskPath="/dev/drbd/by-res/${vmName}/0" + if ! [ -b "${drbdDiskPath}" ]; then + warn "${drbdDiskPath} not found! Continue? [y/N]" + read -r + if ! [[ "${REPLY}" =~ (Y|y) ]]; then + exit 1 + fi + fi +fi + +virtRootDisk="--disk path=/dev/drbd/by-disk/${volRootDisk}/${vmName}_root,bus=virtio,io=threads,cache=none,format=raw" +virtHomeDisk="" +if [ "${volHomeDisk}" != "none" ]; then + virtHomeDisk="--disk path=/dev/drbd/by-disk/${volHomeDisk}/${vmName}_home,bus=virtio,io=threads,cache=none,format=raw" +fi +if [ -n "${preseedURL}" ]; then + bootMode="--location https://deb.debian.org/debian/dists/${debianVersion}/main/installer-amd64/ --extra-args auto=true priority=critical url=${preseedURL} hostname=${vmName}" +fi +if [ -f "${isoImagePath}" ]; then + bootMode="--cdrom=${isoImagePath}" +fi +bootMode=${bootMode:-"--pxe"} + +dryRun virt-install \ + --connect=qemu:///system \ + --name="${vmName}" \ + --cpu "mode=host-passthrough" \ + --vcpus="${vCPU}" \ + --memory="${memory}" \ + "${virtRootDisk}" \ + "${virtHomeDisk}" \ + "${bootMode}" \ + --network="bridge:${bridgeName},model=virtio" \ + --noautoconsole \ + --graphics "vnc,listen=127.0.0.1,keymap=fr" \ + --rng /dev/random \ + --os-variant=none +virt_install_rc=$? + +if [ "${virt_install_rc}" = "0" ]; then + echo -e "\e[32mDone! Now you can install your VM with virt-manager.\e[39m" +else + echo -e "\e[31mError! VM couldn't be created.\e[39m" +fi + +if ! isDryRun && [ -x /usr/share/scripts/evomaintenance.sh ]; then + echo "Install VM ${vmName} (add-vm.sh)" | /usr/share/scripts/evomaintenance.sh +fi + + diff --git a/kvm-host/files/kvmstats.sh b/kvm-host/files/kvmstats.sh new file mode 100755 index 00000000..5fa20ccb --- /dev/null +++ b/kvm-host/files/kvmstats.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +error () { + echo "$0": "$@" >&2 + exit 1 +} + +usage () { + echo 'usage:' "$0" '[-a] [-u k|m|g] [-o human|html|csv]' >&2 + exit 1 +} + +for DEP in bc virsh +do + command -v "$DEP" > /dev/null || error "$DEP" 'command not found' +done + +POW="$(echo '1024 ^ 3' | bc)" +FMT='human' +while [ "$#" -ne 0 ] +do + case "$1" in + '-a') + SHOW_AVAIL='y' + ;; + '-o') + case "$2" in + 'csv'|'html'|'human') + FMT="$2" + ;; + *) + usage + ;; + esac + shift + ;; + '-u') + case "$2" in + 'k') + POW="$(echo '1024 ^ 1' | bc)" + ;; + 'm') + POW="$(echo '1024 ^ 2' | bc)" + ;; + 'g') + POW="$(echo '1024 ^ 3' | bc)" + ;; + *) + usage + esac + shift + ;; + *) + usage + esac + shift +done + +for VM in $(virsh list --name --all) +do + echo "$VM" + + # cpu + virsh vcpucount --current "$VM" + + # mem + # libvirt stores memory in KiB, POW must be lowered by 1 + virsh dommemstat "$VM" 2>/dev/null | awk 'BEGIN{ret=1}$1~/^actual$/{print $2 / '$((POW / 1024))';ret=0}END{exit ret}' || + virsh dumpxml "$VM" | awk -F'[<>]' '$2~/^memory unit/{print $3/'$((POW / 1024))'}' + + # disk + for BLK in $(virsh domblklist "$VM" | sed '1,2d;/-$/d;/^$/d' | awk '{print $1}') + do + virsh domblkinfo "$VM" "$BLK" 2>/dev/null + done | awk '/Physical:/ { size += $2 } END { print int(size / '${POW}') }' + + # state + virsh domstate "$VM" | grep -q '^running$' && echo yes || echo no +done | xargs -n5 | { + echo vm vcpu ram disk running + awk '{ print } /yes$/ { vcpu += $2; ram += $3; disk += $4; running++ } END { print "TOTAL(running)", vcpu, ram, disk, running }' + test "$SHOW_AVAIL" && { + nproc + awk '/^MemTotal:/ { print int($2 / '$((POW / 1024))' ) }' /proc/meminfo + } | xargs -r printf 'AVAILABLE %s %s %s %s\n' +} | case "$FMT" in +'human') + column -t + ;; +'html') + awk 'BEGIN{print "\n"}{printf "";for(i=1;i<=NF;i++)printf "", $i;print ""}END{print "
%s
\n"}' + ;; +'csv') + tr ' ' ',' + ;; +esac diff --git a/kvm-host/files/migrate-vm.sh b/kvm-host/files/migrate-vm.sh new file mode 100644 index 00000000..b2244607 --- /dev/null +++ b/kvm-host/files/migrate-vm.sh @@ -0,0 +1,375 @@ +#!/bin/sh + +# WARN: This script is a work in progress! +# The happy path works, but the rest is not finalized yet. + +# TODO: +# * exit with error if there is no DRBD +# * logging (stdout/stderr + syslog) +# * more checks, rollback if needed… +# * different return codes for different errors +# * migrate "from" +# * switch to Bash to use local and readonly variables + +VERSION="21.04.1" + +show_version() { + cat <, + Jérémy Lecour , + Victor Laborie + and others. + +migrate-vm 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 < + or migrate-vm --vm --resource + or migrate-vm --persistent + or migrate-vm --transient + +Options + --vm VM name (from libvirt point of view) + --resource DRBD resource name (default to VM name) + --transient Leave VM as defined on hosts + --persistent Undefine the VM on the source + and define it on the destination (default) + --help Print this message and exit + --version Print version and exit +END +} + +persistent() { + test "${persistent}" -eq 1 +} + +server_ips() { + ip addr show | grep 'inet '| awk '{print $2}' | cut -f1 -d'/' +} + +drbd_config_file() { + echo "/etc/drbd.d/${1:-}.res" +} + +is_drbd_resource() { + resource=${1:-} + test -f "$(drbd_config_file "${resource}")" && drbdadm role "${resource}" >/dev/null 2>&1 +} + +drbd_peers() { + drbd_config_file=$(drbd_config_file "${1:-}") + + awk '$1 ~ /^on$/ { host = $2 } $1 ~ /^address/ { sub(";$", "", $NF); split($NF, a, ":"); ip = a[1]; printf "%s:%s\n", host, ip }' "${drbd_config_file}" +} + +is_vm_running_locally() { + vm=${1:-} + + virsh list --state-running --name | grep --fixed-strings --line-regexp --quiet "${vm}" +} + +execute_remotely() { + remote=${1:-} + shift + command=${*} + + # shellcheck disable=SC2029 + ssh "${remote}" "${command}" +} + +set_drbd_role() { + role=${1:-} + resource=${2:-} + remote=${3:-""} + + case "${role}" in + primary|secondary) + set_command="drbdadm ${role} ${resource}" + verify_command="drbdadm role ${resource} | grep --fixed-strings --ignore-case --quiet ${role}/" + ;; + *) + echo "Unknown DRBD role '${role}'" >&2 + exit 1 + ;; + esac + + if [ -z "${remote}" ]; then + retval=$(eval "${set_command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "An error occured while setting ${resource} as ${role} : ${retval}" >&2 + exit 1 + fi + + retval=$(eval "${verify_command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "Role has not been set to ${role} on ${resource}. Abort!" >&2 + exit 1 + fi + else + retval=$(execute_remotely "${remote}" "${set_command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "An error occured while remotely setting ${resource} as ${role} : ${retval}" >&2 + exit 1 + fi + + retval=$(execute_remotely "${remote}" "${verify_command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "Role has not been remotely set to ${role} on ${resource}. Abort!" >&2 + exit 1 + fi + fi +} + +define_vm() { + vm=${1:-} + remote=${2:-} + + if [ -z "${remote}" ]; then + # retval=$(virsh define "${vm}") + # retcode=$? + # if [ ${retcode} != 0 ]; then + # >&2 echo "An error occured while defining ${vm} : ${retval}" + # exit 1 + # fi + echo "Defining a VM locally is not supported yet. Let's skip this step." >&2 + else + retval=$(virsh dumpxml "${vm}" | ssh "${remote}" virsh define /dev/stdin) + retcode=$? + if [ ${retcode} != 0 ]; then + echo "An error occured while remotely defining ${vm} : ${retval}" >&2 + exit 1 + fi + fi +} + +undefine_vm() { + vm=${1:-} + remote=${2:-} + + command="virsh undefine ${vm}" + + if [ -z "${remote}" ]; then + retval=$(eval "${command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "An error occured while undefining ${vm} : ${retval}" >&2 + exit 1 + fi + else + retval=$(execute_remotely "${remote}" "${command}") + retcode=$? + if [ ${retcode} != 0 ]; then + echo "An error occured while remotely undefining ${vm}: ${retval}" >&2 + exit 1 + fi + fi +} + +migrate_vm_from() { + vm=${1:-} + remote_ip=${2:-} + current_ip=${3:-} + + export VIRSH_DEFAULT_CONNECT_URI="qemu+ssh://${remote_ip}/system" + virsh migrate --live --unsafe --verbose "${vm}" "qemu:///system" "tcp://${current_ip}/" +} + +migrate_vm_to() { + vm=${1:-} + remote_ip=${2:-} + + export VIRSH_DEFAULT_CONNECT_URI="qemu:///system" + virsh migrate --live --unsafe --verbose "${vm}" "qemu+ssh://${remote_ip}/system" "tcp://${remote_ip}/" +} + +migrate_from() { + vm=${1:-} + resource=${2:-} + remote_ip=${3:-} + remote_host=${4:-} + current_ip=${5:-} + current_host=${6:-} + + echo "Start migration of ${vm} from ${remote_ip} (${remote_host})" + + set_drbd_role primary "${resource}" + migrate_vm_from "${vm}" "${remote_ip}" "${current_ip}" + set_drbd_role secondary "${resource}" "${remote_ip}" + if persistent; then + define_vm "${vm}" + undefine_vm "${vm}" "${remote_ip}" + fi +} + +migrate_to() { + vm=${1:-} + resource=${2:-} + remote_ip=${3:-} + remote_host=${4:-} + + echo "Start migration of ${vm} to ${remote_ip} (${remote_host})" + + set_drbd_role primary "${resource}" "${remote_ip}" + migrate_vm_to "${vm}" "${remote_ip}" + set_drbd_role secondary "${resource}" + if persistent; then + define_vm "${vm}" "${remote_ip}" + undefine_vm "${vm}" + fi +} + +main() { + vm=${1:-} + resource=${2:-} + server_ips=$(server_ips) + + if ! is_drbd_resource "${resource}"; then + echo "No DRBD resource found for '${resource}\`." >&2 + exit 1 + fi + + for peer in $(drbd_peers "${resource}"); do + host=$(echo "${peer}" | cut -d':' -f1) + ip=$(echo "${peer}" | cut -d':' -f2) + + # shellcheck disable=SC2086 + if echo ${server_ips} | grep --quiet "${ip}"; then + current_ip="${ip}" + current_host="${host}" + else + remote_ip="${ip}" + remote_host="${host}" + fi + done + + if is_vm_running_locally "${vm}"; then + migrate_to "${vm}" "${resource}" "${remote_ip}" "${remote_host}" + else + echo "Migrating \"from\" is not supported yet" >&2 + exit 1 + + migrate_from "${vm}" "${resource}" "${remote_ip}" "${remote_host}" "${current_ip}" "${current_host}" + fi +} + +if [ "$(id -u)" -ne "0" ] ; then + echo "This script must be run as root." >&2 + exit 1 +fi + +# 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 + ;; + --transient) + transient=1 + persistent=0 + ;; + --persistent) + transient=0 + persistent=1 + ;; + --vm) + # with value separated by space + if [ -n "$2" ]; then + vm=$2 + shift + else + printf 'ERROR: "--vm" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --vm=?*) + # with value speparated by = + vm=${1#*=} + ;; + --vm=) + # without value + printf 'ERROR: "--vm" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + --resource) + # with value separated by space + if [ -n "$2" ]; then + resource=$2 + shift + else + printf 'ERROR: "--resource" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --resource=?*) + # with value speparated by = + resource=${1#*=} + ;; + --resource=) + # without value + printf 'ERROR: "--resource" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + --) + # End of all options. + shift + break + ;; + -?*|[[:alnum:]]*) + # ignore unknown options + printf 'ERROR: Unknown option : %s\n' "$1" >&2 + echo "" >&2 + show_usage >&2 + exit 1 + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +# Initial values +vm=${vm:-} +resource=${resource:-${vm}} +transient=${transient:-0} +persistent=${persistent:-1} + +set -u +set -e + +if [ -z "${vm}" ]; then + echo "You must provide a VM name" >&2 + echo "" >&2 + show_usage >&2 + exit 1 +fi + +main "${vm}" "${resource}" + +exit 0 \ No newline at end of file diff --git a/kvm-host/meta/main.yml b/kvm-host/meta/main.yml index 0976cf88..c8c8988c 100644 --- a/kvm-host/meta/main.yml +++ b/kvm-host/meta/main.yml @@ -1,19 +1,27 @@ +--- + galaxy_info: - author: Evolix + company: Evolix description: Install tools to set-up a KVM host issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster -dependencies: - - { role: evolix/drbd, when: kvm_install_drbd } + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. diff --git a/kvm-host/tasks/images.yml b/kvm-host/tasks/images.yml index 420e83ec..b9ec57a8 100644 --- a/kvm-host/tasks/images.yml +++ b/kvm-host/tasks/images.yml @@ -13,7 +13,7 @@ changed_when: False check_mode: no register: kvm_libvirt_images_current_real_path_test - when: kvm_custom_libvirt_images_path != '' + when: kvm_custom_libvirt_images_path | length > 0 - name: Images directory is moved to custom path block: @@ -35,6 +35,6 @@ dest: '/var/lib/libvirt/images' state: link when: - - kvm_custom_libvirt_images_path != '' + - kvm_custom_libvirt_images_path | length > 0 - kvm_custom_libvirt_images_path != kvm_libvirt_images_current_real_path_test.stdout - not kvm_custom_libvirt_images_path_test.stat.exists diff --git a/kvm-host/tasks/main.yml b/kvm-host/tasks/main.yml index 71fcda41..95cb7090 100644 --- a/kvm-host/tasks/main.yml +++ b/kvm-host/tasks/main.yml @@ -1,5 +1,9 @@ --- +- include_role: + name: evolix/drbd + when: kvm_install_drbd + ## TODO: check why it's disabled #- include: ssh.yml @@ -8,3 +12,5 @@ - include: munin.yml - include: images.yml + +- include: tools.yml diff --git a/kvm-host/tasks/munin.yml b/kvm-host/tasks/munin.yml index fe5c0217..d0bf1b0a 100644 --- a/kvm-host/tasks/munin.yml +++ b/kvm-host/tasks/munin.yml @@ -1,14 +1,42 @@ --- +- include_role: + name: remount-usr + +- name: Create local munin directory + file: + name: /usr/local/share/munin/ + state: directory + mode: "0755" + +- name: Create plugin directory + file: + name: /usr/local/share/munin/plugins/ + state: directory + mode: "0755" + - name: Get Munin plugins get_url: url: "https://raw.githubusercontent.com/munin-monitoring/contrib/master/plugins/libvirt/{{ item }}" - dest: "/etc/munin/plugins/" + dest: "/usr/local/share/munin/plugins/" mode: "0755" - with_items: - - kvm_cpu - - kvm_io - - kvm_mem + force: no + loop: + - kvm_cpu + - kvm_io + - kvm_mem + notify: restart munin-node + +- name: Enable redis munin plugin + file: + src: "/usr/local/share/munin/plugins/{{item}}" + dest: "/etc/munin/plugins/{{item}}" + state: link + force: yes + loop: + - kvm_cpu + - kvm_io + - kvm_mem notify: restart munin-node - name: Copy Munin plugins conf diff --git a/kvm-host/tasks/packages.yml b/kvm-host/tasks/packages.yml index 99790e84..1b58b324 100644 --- a/kvm-host/tasks/packages.yml +++ b/kvm-host/tasks/packages.yml @@ -1,4 +1,5 @@ --- + - name: Install packages for kvm/libvirt apt: name: @@ -9,5 +10,12 @@ - virtinst - libvirt-daemon-system - libvirt-clients - - kvm-tools - vlan + state: present + +- name: Install packages for kvmstats + apt: + name: + - dialog + - html-xml-utils + state: present diff --git a/kvm-host/tasks/ssh.yml b/kvm-host/tasks/ssh.yml index bdfac0d0..fe71c287 100644 --- a/kvm-host/tasks/ssh.yml +++ b/kvm-host/tasks/ssh.yml @@ -21,9 +21,10 @@ state: present key: "{{ item[0] }}" delegate_to: "{{ item[1] }}" - with_nested: - - "{{ ssh_keys.stdout }}" - - "{{ groups['hypervisors'] }}" + loop: "{{ _keys | product(_servers) | list }}" + vars: + _keys: ssh_keys.stdout + _servers: groups['hypervisors'] when: item[1] != inventory_hostname - name: Crontab for sync libvirt xml file @@ -33,7 +34,7 @@ special_time: "hourly" user: root job: "rsync -a --delete /etc/libvirt/qemu/ {{ hostvars[item]['ansible_hostname'] }}:/root/libvirt-{{ inventory_hostname }}/" - with_items: + loop: - "{{ groups['hypervisors'] }}" when: item != inventory_hostname @@ -43,7 +44,7 @@ state: present special_time: "daily" user: root - job: "virsh list | ssh {{ hostvars[item]['ansible_hostname'] }} 'cat >/root/libvirt-{{ inventory_hostname }}/virsh-list.txt'" - with_items: + job: "virsh list --all | ssh {{ hostvars[item]['ansible_hostname'] }} 'cat >/root/libvirt-{{ inventory_hostname }}/virsh-list.txt'" + loop: - "{{ groups['hypervisors'] }}" when: item != inventory_hostname diff --git a/kvm-host/tasks/tools.yml b/kvm-host/tasks/tools.yml new file mode 100644 index 00000000..83845a31 --- /dev/null +++ b/kvm-host/tasks/tools.yml @@ -0,0 +1,67 @@ +--- + +- name: remove old package + apt: + name: kvm-tools + purge: yes + state: absent + +- include_role: + name: remount-usr + when: kvm_scripts_dir is search ("/usr") + +- name: add-vm script is present + copy: + src: add-vm.sh + dest: "{{ kvm_scripts_dir }}/add-vm" + mode: "0700" + owner: root + group: root + force: yes + +- name: migrate-vm script is present + copy: + src: migrate-vm.sh + dest: "{{ kvm_scripts_dir }}/migrate-vm" + mode: "0700" + owner: root + group: root + force: yes + +- name: kvmstats script is present + copy: + src: kvmstats.sh + dest: "{{ kvm_scripts_dir }}/kvmstats" + mode: "0700" + owner: root + group: root + force: yes + +- name: kvmstats cron is present + template: + src: kvmstats.cron.j2 + dest: "/etc/cron.hourly/kvmstats" + mode: "0755" + owner: root + group: root + +- name: entry for kvmstats in web page is present + lineinfile: + dest: /var/www/index.html + insertbefore: '' + line: '
  • kvmstats
  • ' + + +# backward compatibility + +- name: remove old migrate-vm script + file: + path: /usr/share/scripts/migrate-vm + state: absent + when: "'/usr/share/scripts' not in kvm_scripts_dir" + +- name: remove old kvmstats script + file: + path: /usr/share/scripts/kvmstats + state: absent + when: "'/usr/share/scripts' not in kvm_scripts_dir" \ No newline at end of file diff --git a/kvm-host/templates/kvmstats.cron.j2 b/kvm-host/templates/kvmstats.cron.j2 new file mode 100644 index 00000000..947c8dbf --- /dev/null +++ b/kvm-host/templates/kvmstats.cron.j2 @@ -0,0 +1,4 @@ +#!/bin/sh + +{{ kvm_scripts_dir }}/kvmstats -a -o html > /var/www/kvmstats.html +/bin/chmod go+r /var/www/kvmstats.html diff --git a/ldap/defaults/main.yml b/ldap/defaults/main.yml index 450c7a6c..29c51244 100644 --- a/ldap/defaults/main.yml +++ b/ldap/defaults/main.yml @@ -1,5 +1,10 @@ --- -ldap_hostname: "{{ ansible_hostname }}" + ldap_listen: "ldap://127.0.0.1:389/" + +ldap_hostname: "{{ ansible_hostname }}" ldap_domain: "{{ ansible_domain }}" ldap_suffix: "dc={{ ldap_hostname }},dc={{ ldap_domain.split('.')[-2] }},dc={{ ldap_domain.split('.')[-1] }}" + +ldap_admin_password: "" +ldap_nagios_password: "" \ No newline at end of file diff --git a/ldap/meta/main.yml b/ldap/meta/main.yml index aace73c2..94ed8c34 100644 --- a/ldap/meta/main.yml +++ b/ldap/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of ldap. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/ldap/tasks/init.yml b/ldap/tasks/init.yml new file mode 100644 index 00000000..16be0842 --- /dev/null +++ b/ldap/tasks/init.yml @@ -0,0 +1,32 @@ +--- + +- name: upload ldap initial config + template: + src: config_ldapvi.j2 + dest: /root/evolinux_ldap_config.ldapvi + mode: "0640" + +- name: upload ldap initial entries + template: + src: first-entries.ldif.j2 + dest: /root/evolinux_ldap_first-entries.ldif + mode: "0640" + +- name: inject config + command: ldapvi -Y EXTERNAL -h ldapi:// --ldapmodify /root/evolinux_ldap_config.ldapvi + environment: + TERM: xterm + +- name: inject first entries + command: slapadd -l /root/evolinux_ldap_first-entries.ldif + +- name: upload custom schema + copy: + src: "{{ ldap_schema }}" + dest: "/root/{{ ldap_schema }}" + mode: "0640" + when: ldap_schema is defined + +- name: inject custom schema + command: "ldapadd -Y EXTERNAL -H ldapi:/// -f /root/{{ ldap_schema }}" + when: ldap_schema is defined \ No newline at end of file diff --git a/ldap/tasks/ldapvirc.yml b/ldap/tasks/ldapvirc.yml new file mode 100644 index 00000000..f44249d6 --- /dev/null +++ b/ldap/tasks/ldapvirc.yml @@ -0,0 +1,62 @@ +--- + +- name: "Is /root/.ldapvirc present ?" + stat: + path: /root/.ldapvirc + check_mode: no + register: root_ldapvirc_path + +- name: Warning when ldapvirc file is present and ldap_admin_password is given + debug: + msg: "WARNING: an LDAP admin password is given, but an ldapvirc file already exists. It will not be updated." + when: + - ldap_admin_password | length > 0 + - root_ldapvirc_path.stat.exists + +# Generate ldap password if none is given and ldapvirc is absent +- name: apg package is installed + apt: + name: apg + state: present + when: not root_ldapvirc_path.stat.exists + +- name: create a password for cn=admin + command: "apg -n 1 -m 16 -M lcN" + register: new_ldap_admin_password + changed_when: False + when: + - ldap_admin_password | length == 0 + - not root_ldapvirc_path.stat.exists + +# Use the generated password or the one found in the file +- name: overwrite ldap_admin_password + set_fact: + ldap_admin_password: "{{ new_ldap_admin_password.stdout }}" + when: + - ldap_admin_password | length == 0 + - not root_ldapvirc_path.stat.exists + +- name: hash password for cn=admin + command: "slappasswd -s {{ ldap_admin_password }}" + register: ldap_admin_password_ssha + changed_when: False + when: not root_ldapvirc_path.stat.exists + +- name: create ldapvirc config + template: + src: ldapvirc.j2 + dest: /root/.ldapvirc + mode: "0640" + when: not root_ldapvirc_path.stat.exists + +# Read ldap password when none is given and ldapvirc is present +- name: read ldap admin password from ldapvirc file + shell: "grep -E '^password: .+$' /root/.ldapvirc | awk '{print $2}'" + changed_when: False + check_mode: no + register: new_ldap_admin_password + +# Use the password found in the file +- name: overwrite ldap_admin_password + set_fact: + ldap_admin_password: "{{ new_ldap_admin_password.stdout }}" diff --git a/ldap/tasks/main.yml b/ldap/tasks/main.yml index 8f6fbd67..9bfb6517 100644 --- a/ldap/tasks/main.yml +++ b/ldap/tasks/main.yml @@ -6,103 +6,21 @@ - ldapvi - shelldap state: present + update_cache: yes -- name: change sldap listen ip:port +- name: change slapd listen ip:port lineinfile: dest: /etc/default/slapd regexp: 'SLAPD_SERVICES=.*' line: "SLAPD_SERVICES=\"{{ ldap_listen }}\"" notify: restart slapd -- name: "Is /root/.ldapvirc present ?" - stat: - path: /root/.ldapvirc - check_mode: no - register: root_ldapvirc_path +- name: ldapvirc file + include: ldapvirc.yml -- name: apg package is installed - apt: - name: apg - state: present - when: not root_ldapvirc_path.stat.exists +- name: nagios config file for LDAP + include: nagios.yml -- name: create a password for cn=admin - command: "apg -n 1 -m 16 -M lcN" - register: ldap_admin_password - changed_when: False - when: not root_ldapvirc_path.stat.exists - -- name: create a password for cn=nagios - command: "apg -n 1 -m 16 -M lcN" - register: ldap_nagios_password - changed_when: False - when: not root_ldapvirc_path.stat.exists - -- name: hash password for cn=admin - command: "slappasswd -s {{ ldap_admin_password.stdout }}" - register: ldap_admin_password_ssha - changed_when: False - when: not root_ldapvirc_path.stat.exists - -- name: hash password for cn=nagios - command: "slappasswd -s {{ ldap_nagios_password.stdout }}" - register: ldap_nagios_password_ssha - changed_when: False - when: not root_ldapvirc_path.stat.exists - -- name: create ldapvirc config - template: - src: ldapvirc.j2 - dest: /root/.ldapvirc - mode: "0640" - when: not root_ldapvirc_path.stat.exists - -- name: set params for NRPE check - ini_file: - dest: /etc/nagios/monitoring-plugins.ini - owner: root - group: nagios - section: check_ldap - option: "{{ item.option }}" - value: "{{ item.value }}" - mode: 0640 - with_items: - - { option: 'hostname', value: '127.0.0.1' } - - { option: 'base', value: "{{ ldap_suffix }}" } - - { option: 'bind', value: "cn=nagios,ou=ldapusers,{{ ldap_suffix }}" } - - { option: 'pass', value: "{{ ldap_nagios_password.stdout }}" } - -- name: upload ldap initial config - template: - src: config_ldapvi.j2 - dest: /root/evolinux_ldap_config.ldapvi - mode: "0640" - when: not root_ldapvirc_path.stat.exists - -- name: upload ldap initial entries - template: - src: first-entries.ldif.j2 - dest: /root/evolinux_ldap_first-entries.ldif - mode: "0640" - when: not root_ldapvirc_path.stat.exists - -- name: inject config - command: ldapvi -Y EXTERNAL -h ldapi:// --ldapmodify /root/evolinux_ldap_config.ldapvi - environment: - TERM: xterm - when: not root_ldapvirc_path.stat.exists - -- name: inject first entries - command: slapadd -l /root/evolinux_ldap_first-entries.ldif - when: not root_ldapvirc_path.stat.exists - -- name: upload custom schema - copy: - src: "{{ ldap_schema }}" - dest: "/root/{{ ldap_schema }}" - mode: "0640" - when: not root_ldapvirc_path.stat.exists and ldap_schema is defined - -- name: inject custom schema - command: "ldapadd -Y EXTERNAL -H ldapi:/// -f /root/{{ ldap_schema }}" - when: not root_ldapvirc_path.stat.exists and ldap_schema is defined +- name: initialize database + include: init.yml + when: not root_ldapvirc_path.stat.exists \ No newline at end of file diff --git a/ldap/tasks/nagios.yml b/ldap/tasks/nagios.yml new file mode 100644 index 00000000..0c92f7b3 --- /dev/null +++ b/ldap/tasks/nagios.yml @@ -0,0 +1,74 @@ +--- + +- name: "Is /etc/nagios/monitoring-plugins.ini present ?" + stat: + path: /etc/nagios/monitoring-plugins.ini + check_mode: no + register: nagios_monitoring_plugins_path + +- name: Warning when nagios config is present and ldap_nagios_password is given + debug: + msg: "WARNING: an LDAP nagios password is given, but a nagios config already exists. It will not be updated." + when: + - ldap_nagios_password | length > 0 + - nagios_monitoring_plugins_path.stat.exists + +# Generate ldap password if none is given and nagios config is absent +- name: apg package is installed + apt: + name: apg + state: present + when: + - ldap_nagios_password | length == 0 + - not nagios_monitoring_plugins_path.stat.exists + +- name: create a password for cn=admin + command: "apg -n 1 -m 16 -M lcN" + register: new_ldap_nagios_password + changed_when: False + when: + - ldap_nagios_password | length == 0 + - not nagios_monitoring_plugins_path.stat.exists + +# Use the generated password or the one found in the file +- name: overwrite ldap_nagios_password (from apg) + set_fact: + ldap_nagios_password: "{{ new_ldap_nagios_password.stdout }}" + when: + - ldap_nagios_password | length == 0 + - not nagios_monitoring_plugins_path.stat.exists + +- name: set params for NRPE check + ini_file: + dest: /etc/nagios/monitoring-plugins.ini + owner: root + group: nagios + section: check_ldap + option: "{{ item.option }}" + value: "{{ item.value }}" + mode: "0640" + loop: + - { option: 'hostname', value: '127.0.0.1' } + - { option: 'base', value: "{{ ldap_suffix }}" } + - { option: 'bind', value: "cn=nagios,ou=ldapusers,{{ ldap_suffix }}" } + - { option: 'pass', value: "{{ ldap_nagios_password }}" } + when: not nagios_monitoring_plugins_path.stat.exists + +# Read ldap password when none is given and nagios config is present +# We can't parse a remote file, so we have to fetch it first +- name: Fetch /etc/nagios/monitoring-plugins.ini + fetch: + src: /etc/nagios/monitoring-plugins.ini + dest: /tmp/{{ inventory_hostname }}/ + flat: yes + +# Then web can parse it with the 'ini' lookup +# and set the variable +- name: overwrite ldap_nagios_password (from file) + set_fact: + ldap_nagios_password: "{{ lookup('ini', 'pass section=check_ldap file=/tmp/{{ inventory_hostname }}/monitoring-plugins.ini') }}" + +- name: hash password for cn=nagios + command: "slappasswd -s {{ ldap_nagios_password }}" + register: ldap_nagios_password_ssha + changed_when: False \ No newline at end of file diff --git a/ldap/templates/ldapvirc.j2 b/ldap/templates/ldapvirc.j2 index e61a7524..53ece952 100644 --- a/ldap/templates/ldapvirc.j2 +++ b/ldap/templates/ldapvirc.j2 @@ -3,4 +3,4 @@ host: ldap://127.0.0.1 base: {{ ldap_suffix }} user: cn=admin,{{ ldap_suffix }} bind: simple -password: {{ ldap_admin_password.stdout }} +password: {{ ldap_admin_password }} diff --git a/listupgrade/defaults/main.yml b/listupgrade/defaults/main.yml index 3f72fbff..d3bdff78 100644 --- a/listupgrade/defaults/main.yml +++ b/listupgrade/defaults/main.yml @@ -1,3 +1,5 @@ --- general_alert_email: "root@localhost" listupgrade_alert_email: Null + +listupgrade_cron_enabled: true \ No newline at end of file diff --git a/listupgrade/files/listupgrade.sh b/listupgrade/files/listupgrade.sh index d2f4996b..3c64f37e 100644 --- a/listupgrade/files/listupgrade.sh +++ b/listupgrade/files/listupgrade.sh @@ -7,50 +7,54 @@ # - 60 : current release is not in the $r_releases list # - 70 : at least an upgradable package is not in the $r_packages list -set -e +VERSION="21.06.2" -configFile="/etc/evolinux/listupgrade.cnf" +show_version() { + cat <, + Gregory Colpart , + Romain Dessort , + Ludovic Poujol , + Jérémy Lecour + and others. -# Remove temporary files on exit. -trap "rm $packages $packagesHold $servicesToRestart $template" EXIT +listupgrade.sh 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 +} # Parse line in retrieved upgrade file and ensure there is no malicious values. get_value() { file="$1" variable="$2" - value="$(grep "^$2:" $1 |head -n 1 |cut -d ':' -f 2 |sed 's/^ //')" - if echo "$value" |grep -q -E '^[-.: [:alnum:]]*$'; then - echo $value + value="$(grep "^${variable}:" "${file}" | head -n 1 | cut -d ':' -f 2 | sed 's/^ //')" + + if echo "${value}" | grep -q -E '^[-.: [:alnum:]]*$'; then + echo "${value}" else - printf >&2 "Error parsing value \"$value\" for variable $variables.\n" + printf >&2 "Error parsing value \"%s\" for variable %s.\n" "${value}" "${variable}" fi } # Fetch which packages/releases will be upgraded. fetch_upgrade_info() { - upgradeInfo=$(mktemp --tmpdir=/tmp evoupdate.XXX) - wget -q -O $upgradeInfo https://upgrades.evolix.org/upgrade - r_releases="$(get_value $upgradeInfo "releases")" - r_skip_releases="$(get_value $upgradeInfo "skip_releases")" - r_packages="$(get_value $upgradeInfo "packages")" - r_skip_packages="$(get_value $upgradeInfo "skip_packages")" - rm $upgradeInfo + upgradeInfo=$(mktemp --tmpdir=/tmp listupgrade.XXX) + wget --no-check-certificate --quiet --output-document="${upgradeInfo}" https://upgrades.evolix.org/upgrade + + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + printf >&2 "Error fetching upgrade directives.\n" + fi + + r_releases="$(get_value "${upgradeInfo}" "releases")" + r_skip_releases="$(get_value "${upgradeInfo}" "skip_releases")" + r_packages="$(get_value "${upgradeInfo}" "packages")" + r_skip_packages="$(get_value "${upgradeInfo}" "skip_packages")" + + rm "${upgradeInfo}" } # Check if element $element is in (space separated) list $list. @@ -58,142 +62,26 @@ is_in() { list="$1" element="$2" - for i in $list; do - if [ "$element" = "$i" ]; then + for i in ${list}; do + if [ "${element}" = "${i}" ]; then return 0 fi done + return 1 } - -if [[ "$1" != "--cron" ]]; then - echo "À quel date/heure allez vous planifier l'envoi ?" - echo "Exemple : le jeudi 6 mars entre 18h00 et 23h00" - echo -n ">" - read date - echo "À qui envoyer le mail ?" - echo -n ">" - read mailto -fi - -# Update APT cache and get packages to upgrade and packages on hold. -aptUpdateOutput=$(apt update 2>&1 | (egrep -ve '^(Listing|WARNING|$)' -e upgraded -e 'up to date' || true )) - -if (echo "$aptUpdateOutput" | egrep "^Err(:[0-9]+)? http"); then - echo "FATAL - Not able to fetch all sources (probably a pesky (mini)firewall). Please, fix me" - exit 100 -fi - -apt-mark showhold > $packagesHold -apt list --upgradable 2>&1 | grep -v -f $packagesHold | egrep -v '^(Listing|WARNING|$)' > $packages -packagesParsable=$(cut -f 1 -d / <$packages |tr '\n' ' ') - -# No updates? Exit! -test ! -s $packages && exit 0 -test ! -s $packagesHold && echo 'Aucun' > $packagesHold - -fetch_upgrade_info -local_release=$(cut -f 1 -d . >$servicesToRestart - elif echo "$pkg" |grep -q "^nginx"; then - echo "Nginx" >>$servicesToRestart - elif echo "$pkg" |grep -q "^php5-fpm"; then - echo "PHP FPM" >>$servicesToRestart - elif echo "$pkg" |grep -q "^mysql-server"; then - echo "MySQL" >>$servicesToRestart - elif echo "$pkg" |grep -q "^mariadb-server"; then - echo "MariaDB" >>$servicesToRestart - elif echo "$pkg" |grep -qE "^postgresql-[[:digit:]]+\.[[:digit:]]+$"; then - echo "PostgreSQL" >>$servicesToRestart - elif echo "$pkg" |grep -qE "^tomcat[[:digit:]]+$"; then - echo "Tomcat" >>$servicesToRestart - elif [ "$pkg" = "redis-server" ]; then - echo "Redis" >>$servicesToRestart - elif [ "$pkg" = "mongodb-server" ]; then - echo "MondoDB" >>$servicesToRestart - elif echo "$pkg" |grep -qE "^courier-(pop|imap)"; then - echo "Courier POP/IMAP" >>$servicesToRestart - elif echo "$pkg" |grep -qE "^dovecot-(pop|imap)d"; then - echo "Dovecot POP/IMAP" >>$servicesToRestart - elif [ "$pkg" = "samba" ]; then - echo "Samba" >>$servicesToRestart - elif [ "$pkg" = "slapd" ]; then - echo "OpenLDAP" >>$servicesToRestart - elif [ "$pkg" = "bind9" ]; then - echo "Bind9" >>$servicesToRestart - elif [ "$pkg" = "postfix" ]; then - echo "Postfix" >>$servicesToRestart - elif [ "$pkg" = "haproxy" ]; then - echo "HAProxy" >>$servicesToRestart - elif [ "$pkg" = "varnish" ]; then - echo "Varnish" >>$servicesToRestart - elif [ "$pkg" = "squid" ]; then - echo "Squid" >>$servicesToRestart - elif [ "$pkg" = "elasticsearch" ]; then - echo "Elasticsearch" >>$servicesToRestart - elif [ "$pkg" = "logstash" ]; then - echo "Logstash" >>$servicesToRestart - - elif [ "$pkg" = "libc6" ]; then - echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libc6)." >$servicesToRestart - break - elif [ "$pkg" = "libstdc++6" ]; then - echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libstdc++6)." >$servicesToRestart - break - elif echo "$pkg" |grep -q "^libssl"; then - echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libssl)." >$servicesToRestart - break - fi -done -test ! -s $servicesToRestart && echo "Aucun" >$servicesToRestart - -cat << EOT > $template +render_mail_template() { + local template_file=$1 + cat <"${template_file}" Content-Type: text/plain; charset="utf-8" Reply-To: equipe@evolix.fr From: equipe@evolix.net To: ${clientmail} -Subject: Prochain creneau pour mise a jour de votre serveur $hostname -X-Debian-Release: $local_release -X-Packages: $packagesParsable -X-Date: $date +Subject: Prochain creneau pour mise a jour de votre serveur ${hostname} +X-Debian-Release: ${local_release} +X-Packages: ${packagesParsable} +X-Date: ${date} Bonjour, @@ -210,15 +98,15 @@ semaine prochaine. Voici la listes de packages qui seront mis à jour : -$(cat $packages) +$(cat "${packages}") Liste des packages dont la mise-à-jour a été manuellement suspendue : -$(cat $packagesHold) +$(cat "${packagesHold}") Liste des services qui seront redémarrés : -$(cat $servicesToRestart) +$(cat "${servicesToRestart}") N'hésitez pas à nous faire toute remarque sur ce créneau d'intervention le plus tôt possible. @@ -228,37 +116,288 @@ Cordialement, Équipe Evolix - Hébergement et Infogérance Open Source http://evolix.com | Twitter: @Evolix @EvolixNOC | http://blog.evolix.com EOT +} +# Files found in the directory passed as 1st argument +# are executed if they are executable +# and if their name doesn't contain a dot +exec_hooks_in_dir() { + hooks=$(find "${1}" -type f -executable -not -name '*.*') + for hook in ${hooks}; do + if ! cron_mode; then + printf "Running '%s\`\n" "${hook}" + fi + ${hook} + done +} +pre_hooks() { + if [ -d "${hooksDir}/pre" ]; then + exec_hooks_in_dir "${hooksDir}/pre" + fi +} +post_hooks_and_exit() { + status=${1:-0} + if [ -d "${hooksDir}/post" ]; then + exec_hooks_in_dir "${hooksDir}/post" + fi + exit ${status} +} -<$template /usr/sbin/sendmail $mailto +cron_mode() { + test "${cron_mode}" = "1" +} -# Now we try to fetch all the packages for the next update session -downloadstatus=$(apt dist-upgrade --assume-yes --download-only -q2 2>&1) -echo "$downloadstatus" | grep -q 'Download complete and in download only mode' +force_mode() { + test "${force_mode}" = "1" +} -if [ $? -ne 0 ]; then - echo "$downloadstatus" -fi; +main() { + if ! cron_mode; then + echo "Updating lists..." + fi + # Update APT cache and get packages to upgrade and packages on hold. + aptUpdateOutput=$(apt -o Dir::State::Lists="${listupgrade_state_dir}" update 2>&1 | (grep -E -ve '^(Listing|WARNING|$)' -e upgraded -e 'up to date' || true)) + if echo "${aptUpdateOutput}" | grep -E "^Err(:[0-9]+)? http"; then + echo "FATAL - Not able to fetch all sources (probably a pesky (mini)firewall). Please, fix me" >&2 + post_hooks_and_exit 100 + fi -# Also, we try to update each container apt sources -if which lxc-ls > /dev/null; then - for container in $(lxc-ls); do + apt-mark showhold | sed -e 's/\(.\+\)/^\1\//' >"${packagesHold}" + apt -o Dir::State::Lists="${listupgrade_state_dir}" list --upgradable 2>&1 | grep -v -f "${packagesHold}" | grep -v -E '^(Listing|WARNING|$)' >"${packages}" + packagesParsable=$(cut -f 1 -d / <"${packages}" | tr '\n' ' ') - aptUpdateOutput=$(lxc-attach -n $container -- apt update 2>&1 | (egrep -ve '^(Listing|WARNING|$)' -e upgraded -e 'up to date' || true )) + # No updates? Exit! + if [ ! -s "${packages}" ]; then + if ! cron_mode; then + echo "There is nothing to upgrade. Bye." >&2 + fi + post_hooks_and_exit 0 + fi - if (echo "$aptUpdateOutput" | egrep "^Err(:[0-9]+)? http"); then - echo "FATAL CONTAINER - Not able to fetch all sources (probably a pesky (mini)firewall). Please, fix me" - exit 150 + if [ ! -s "${packagesHold}" ]; then + echo 'Aucun' >"${packagesHold}" + fi + + if force_mode; then + if ! cron_mode; then + echo "Force mode is enabled, as if every release/package is available for upgrade." + fi + else + fetch_upgrade_info + local_release=$(cut -f 1 -d . &1) - echo "$downloadstatus" | grep -q 'Download complete and in download only mode' + # Exit if the server's release is in skip_releases. + if [ -n "${r_skip_releases}" ] && is_in "${r_skip_releases}" "${local_release}"; then + post_hooks_and_exit 40 + fi - if [ $? -ne 0 ]; then - echo "$downloadstatus" - fi; + # Exit if all packages to upgrade are listed in skip_packages: + # we remove each package to skip from the $packageToUpgrade list. At the end, + # if there is no additional packages to upgrade, we can exit. + if [ -n "${r_skip_packages}" ]; then + packageToUpgrade="${packagesParsable}" + for pkg in ${r_skip_packages}; do + packageToUpgrade="${packageToUpgrade}/${pkg}" + done + # shellcheck disable=SC2001 + packageToUpgrade=$(echo "${packageToUpgrade}" | sed 's/ \+//g') + if [ -z "${packageToUpgrade}" ]; then + post_hooks_and_exit 50 + fi + fi + # Exit if the server's release is not in releases. + if [ -n "${r_releases}" ] && [ "${r_releases}" != "all" ]; then + is_in "${r_releases}" "${local_release}" || post_hooks_and_exit 60 + fi + + # Exit if there is packages to upgrades that are not in packages list: + # we exit at the first package encountered that is not in packages list. + if [ -n "${r_packages}" ] && [ "${r_packages}" != "all" ]; then + for pkg in ${packagesParsable}; do + is_in "${r_packages}" "${pkg}" || post_hooks_and_exit 70 + done + fi + fi + + # Guess which services will be restarted. + for pkg in ${packagesParsable}; do + if echo "${pkg}" | grep -qE "^(lib)?apache2"; then + echo "Apache2" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -q "^nginx"; then + echo "Nginx" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -q "^php5-fpm"; then + echo "PHP FPM" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -q "^mysql-server"; then + echo "MySQL" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -q "^mariadb-server"; then + echo "MariaDB" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -qE "^postgresql-[[:digit:]]+\.[[:digit:]]+$"; then + echo "PostgreSQL" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -qE "^tomcat[[:digit:]]+$"; then + echo "Tomcat" >>"${servicesToRestart}" + elif [ "${pkg}" = "redis-server" ]; then + echo "Redis" >>"${servicesToRestart}" + elif [ "${pkg}" = "mongodb-server" ]; then + echo "MondoDB" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -qE "^courier-(pop|imap)"; then + echo "Courier POP/IMAP" >>"${servicesToRestart}" + elif echo "${pkg}" | grep -qE "^dovecot-(pop|imap)d"; then + echo "Dovecot POP/IMAP" >>"${servicesToRestart}" + elif [ "${pkg}" = "samba" ]; then + echo "Samba" >>"${servicesToRestart}" + elif [ "${pkg}" = "slapd" ]; then + echo "OpenLDAP" >>"${servicesToRestart}" + elif [ "${pkg}" = "bind9" ]; then + echo "Bind9" >>"${servicesToRestart}" + elif [ "${pkg}" = "postfix" ]; then + echo "Postfix" >>"${servicesToRestart}" + elif [ "${pkg}" = "haproxy" ]; then + echo "HAProxy" >>"${servicesToRestart}" + elif [ "${pkg}" = "varnish" ]; then + echo "Varnish" >>"${servicesToRestart}" + elif [ "${pkg}" = "squid" ]; then + echo "Squid" >>"${servicesToRestart}" + elif [ "${pkg}" = "elasticsearch" ]; then + echo "Elasticsearch" >>"${servicesToRestart}" + elif [ "${pkg}" = "logstash" ]; then + echo "Logstash" >>"${servicesToRestart}" + elif [ "${pkg}" = "kibana" ]; then + echo "Kibana" >>"${servicesToRestart}" + elif [ "${pkg}" = "libc6" ]; then + echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libc6)." >"${servicesToRestart}" + break + elif [ "${pkg}" = "libstdc++6" ]; then + echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libstdc++6)." >"${servicesToRestart}" + break + elif echo "${pkg}" | grep -q "^libssl"; then + echo "Tous les services sont susceptibles d'être redémarrés (mise à jour de libssl)." >"${servicesToRestart}" + break + fi done + test ! -s "${servicesToRestart}" && echo "Aucun" >"${servicesToRestart}" + + render_mail_template "${template}" + /usr/sbin/sendmail "${mailto}" <"${template}" + + if ! cron_mode; then + echo "Dowloading packages..." + fi + # Now we try to fetch all the packages for the next update session + downloadstatus=$(apt -o Dir::State::Lists="${listupgrade_state_dir}" dist-upgrade --assume-yes --download-only -q2 2>&1) + echo "${downloadstatus}" | grep -q 'Download complete and in download only mode' + + # shellcheck disable=SC2181 + if [ $? -ne 0 ]; then + echo "${downloadstatus}" + fi + + # Also, we try to update each container apt sources + if which lxc-ls >/dev/null; then + for container in $(lxc-ls); do + + aptUpdateOutput=$(lxc-attach -n "${container}" -- apt -o Dir::State::Lists="${listupgrade_state_dir}" update 2>&1 | (grep -Eve '^(Listing|WARNING|$)' -e upgraded -e 'up to date' || true)) + + if (echo "${aptUpdateOutput}" | grep -E "^Err(:[0-9]+)? http"); then + echo "FATAL CONTAINER - Not able to fetch all sources (probably a pesky (mini)firewall). Please, fix me" >&2 + post_hooks_and_exit 150 + fi + + # Now we try to fetch all the packages for the next update session + downloadstatus=$(lxc-attach -n "${container}" -- apt -o Dir::State::Lists="${listupgrade_state_dir}" dist-upgrade --assume-yes --download-only -q2 2>&1) + + if echo "${downloadstatus}" | grep -q 'Download complete and in download only mode'; then + echo "${downloadstatus}" + fi + + done + fi +} + +# Options parsing. +while :; do + case ${1} in + -V | --version) + show_version + exit 0 + ;; + --cron) + cron_mode=1 + ;; + -f | --force) + # Ignore exclusions from "upgrade info" and do as if all releases and packages are to be upgraded + force_mode=1 + ;; + -?* | [[:alnum:]]*) + # ignore unknown options + printf 'ERROR: Unknown option : %s\n' "$1" >&2 + exit 1 + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +## Do not stop on error. Instead we should catch them manually +# set -e +## Error on unassigned variables +set -u + +export LC_ALL=C + +configFile="/etc/evolinux/listupgrade.cnf" + +cron_mode=${cron_mode:-0} +force_mode=${force_mode:-0} +clientmail=$(grep EVOMAINTMAIL /etc/evomaintenance.cf | cut -d'=' -f2) +mailto="${clientmail}" +date="Ce jeudi entre 18h00 et 23h00." +hostname=$(grep HOSTNAME /etc/evomaintenance.cf | cut -d'=' -f2) +hostname=${hostname%%.evolix.net} +listupgrade_state_dir="${listupgrade_state_dir:-/var/lib/listupgrade}" +hooksDir="/etc/evolinux/listupgrade-hooks" + +# If hostname is composed with -, remove the first part. +if [[ "${hostname}" =~ "-" ]]; then + hostname=$(echo "${hostname}" | cut -d'-' -f2-) +fi +# Edit $configFile to override some variables. +# shellcheck disable=SC1090,SC1091 +[ -r "${configFile}" ] && . "${configFile}" + +# Create temporary files +packages=$(mktemp --tmpdir=/tmp listupgrade.XXX) +packagesHold=$(mktemp --tmpdir=/tmp listupgrade.XXX) +servicesToRestart=$(mktemp --tmpdir=/tmp listupgrade.XXX) +template=$(mktemp --tmpdir=/tmp listupgrade.XXX) +# Remove temporary files on exit. +# shellcheck disable=SC2064 +trap "rm ${packages} ${packagesHold} ${servicesToRestart} ${template}" EXIT + +if ! cron_mode; then + echo "À quelle date/heure allez vous planifier les mises à jour ?" + echo "Exemple : le jeudi 6 mars entre 18h00 et 23h00" + echo -n "> " + read -r date + echo "À qui envoyer le mail ?" + echo -n "> " + read -r mailto fi +# Execute pre hooks +pre_hooks + +# call main function +main + +# Execute post hooks and exit +post_hooks_and_exit 0 diff --git a/listupgrade/meta/main.yml b/listupgrade/meta/main.yml index 29c56478..1d75ceff 100644 --- a/listupgrade/meta/main.yml +++ b/listupgrade/meta/main.yml @@ -1,17 +1,19 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and configuration of the listupgrade script issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/listupgrade/tasks/main.yml b/listupgrade/tasks/main.yml index a1449b04..3ed23da3 100644 --- a/listupgrade/tasks/main.yml +++ b/listupgrade/tasks/main.yml @@ -53,6 +53,7 @@ owner: root group: root force: no + when: listupgrade_cron_enabled | bool - name: old-kernel-autoremoval script is present copy: diff --git a/logstash/files/elastic.asc b/logstash/files/elastic.asc new file mode 100644 index 00000000..1b50dcca --- /dev/null +++ b/logstash/files/elastic.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/logstash/meta/main.yml b/logstash/meta/main.yml index 489fa419..b2ef1210 100644 --- a/logstash/meta/main.yml +++ b/logstash/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Logstash. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: - { role: evolix/java, java_alternative: 'openjdk', java_version: 8 } diff --git a/logstash/tasks/logs.yml b/logstash/tasks/logs.yml index 4417bd89..975cd8bc 100644 --- a/logstash/tasks/logs.yml +++ b/logstash/tasks/logs.yml @@ -1,10 +1,13 @@ --- - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False register: is_cron_installed - + - name: "log rotation script" template: src: rotate_logstash_logs.j2 diff --git a/logstash/tasks/main.yml b/logstash/tasks/main.yml index e6438abe..4ae70623 100644 --- a/logstash/tasks/main.yml +++ b/logstash/tasks/main.yml @@ -5,17 +5,29 @@ name: apt-transport-https state: present tags: - - logstash - - packages + - logstash + - packages + +- name: Elastic embedded GPG key is absent + apt_key: + id: "D88E42B4" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - logstash + - packages - name: Elastic GPG key is installed - apt_key: - # url: https://artifacts.elastic.co/GPG-KEY-elasticsearch - data: "{{ lookup('file', 'elasticsearch.key') }}" - state: present + copy: + src: elastic.asc + dest: /etc/apt/trusted.gpg.d/elastic.asc + force: yes + mode: "0644" + owner: root + group: root tags: - - logstash - - packages + - logstash + - packages - name: Elastic sources list is available apt_repository: @@ -24,20 +36,23 @@ state: present update_cache: yes tags: - - logstash - - packages + - logstash + - packages - name: Logstash is installed apt: name: logstash state: present tags: + - logstash - packages - name: Logstash service is enabled systemd: name: logstash enabled: yes + tags: + - logstash - name: JVM Heap size (min) is set lineinfile: @@ -45,6 +60,7 @@ regexp: "^-Xms" line: "-Xms{{ logstash_jvm_xms }}" tags: + - logstash - config - name: JVM Heap size (max) is set @@ -53,6 +69,7 @@ regexp: "^-Xmx" line: "-Xmx{{ logstash_jvm_xmx }}" tags: + - logstash - config - name: Add a configuration @@ -63,12 +80,17 @@ group: logstash mode: "0640" force: yes - with_first_found: - - "templates/logstash/logstash.{{ inventory_hostname }}.conf.j2" - - "templates/logstash/logstash.{{ host_group }}.conf.j2" - - "templates/logstash/logstash.default.conf.j2" - - "logstash.default.conf.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/logstash/logstash.{{ inventory_hostname }}.conf.j2" + - "templates/logstash/logstash.{{ host_group | default('all') }}.conf.j2" + - "templates/logstash/logstash.default.conf.j2" + - "templates/logstash.default.conf.j2" register: logstash_template + tags: + - logstash + - config - debug: var: logstash_template diff --git a/logstash/tasks/tmpdir.yml b/logstash/tasks/tmpdir.yml index 4149f5af..e41b1205 100644 --- a/logstash/tasks/tmpdir.yml +++ b/logstash/tasks/tmpdir.yml @@ -8,9 +8,12 @@ check_mode: no - block: - - name: "Create {{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + - set_fact: + _logstash_custom_tmpdir: "{{ logstash_custom_tmpdir | default(logstash_default_tmpdir, True) | mandatory }}" + + - name: "Create {{ _logstash_custom_tmpdir }}" file: - path: "{{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + path: "{{ _logstash_custom_tmpdir }}" owner: logstash group: logstash mode: "0755" @@ -21,11 +24,11 @@ - name: change JVM tmpdir lineinfile: dest: /etc/logstash/jvm.options - line: "-Djava.io.tmpdir={{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + line: "-Djava.io.tmpdir={{ _logstash_custom_tmpdir }}" regexp: "^-Djava.io.tmpdir=" insertafter: "## JVM configuration" notify: - restart logstash tags: - logstash - when: (logstash_custom_tmpdir != '' and logstash_custom_tmpdir != None) or fstab_tmp_noexec.rc == 0 + when: (logstash_custom_tmpdir is not none and logstash_custom_tmpdir | length > 0) or fstab_tmp_noexec.rc == 0 diff --git a/lxc-php/files/reg.asc b/lxc-php/files/reg.asc new file mode 100644 index 00000000..3fadeb07 --- /dev/null +++ b/lxc-php/files/reg.asc @@ -0,0 +1,920 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.6 +Comment: Hostname: keyserver.ubuntu.com + +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 +BWcdiQ== +=iUyJ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/lxc-php/files/sury.gpg b/lxc-php/files/sury.gpg new file mode 100644 index 00000000..384771a0 Binary files /dev/null and b/lxc-php/files/sury.gpg differ diff --git a/lxc-php/meta/main.yml b/lxc-php/meta/main.yml index 3c965d43..58c2298c 100644 --- a/lxc-php/meta/main.yml +++ b/lxc-php/meta/main.yml @@ -1,18 +1,29 @@ +--- galaxy_info: - author: Evolix + company: Evolix description: Creation of LXC Containers & Setting up PHP-FPM for a multiphp setup issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. allow_duplicates: yes diff --git a/lxc-php/tasks/misc.yml b/lxc-php/tasks/misc.yml index 297ee469..c5aa5245 100644 --- a/lxc-php/tasks/misc.yml +++ b/lxc-php/tasks/misc.yml @@ -28,6 +28,9 @@ name: "{{ lxc_php_version }}" container_config: - "lxc.mount.entry = /run/mysqld {{ php_conf_mysql_socket_dir | replace('/', '', 1) }} none bind,create=dir 0 0" - when: lxc_php_create_mysql_link and php_conf_mysql_socket_dir is string + when: + - lxc_php_create_mysql_link | bool + - php_conf_mysql_socket_dir is not none + - php_conf_mysql_socket_dir | length > 0 notify: "Restart container" diff --git a/lxc-php/tasks/php56.yml b/lxc-php/tasks/php56.yml index b10bb772..ece7dc8d 100644 --- a/lxc-php/tasks/php56.yml +++ b/lxc-php/tasks/php56.yml @@ -11,7 +11,7 @@ dest: "{{ line_item }}" mode: "0644" notify: "Reload {{ lxc_php_version }}-fpm" - with_items: + loop: - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php5/fpm/conf.d/z-evolinux-defaults.ini" - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php5/cli/conf.d/z-evolinux-defaults.ini" loop_control: diff --git a/lxc-php/tasks/php70.yml b/lxc-php/tasks/php70.yml index 8cbb0125..2291b386 100644 --- a/lxc-php/tasks/php70.yml +++ b/lxc-php/tasks/php70.yml @@ -11,7 +11,7 @@ dest: "{{ line_item }}" mode: "0644" notify: "Reload {{ lxc_php_version }}-fpm" - with_items: + loop: - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.0/fpm/conf.d/z-evolinux-defaults.ini" - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.0/cli/conf.d/z-evolinux-defaults.ini" loop_control: diff --git a/lxc-php/tasks/php73.yml b/lxc-php/tasks/php73.yml index eae17e4e..d7fd7937 100644 --- a/lxc-php/tasks/php73.yml +++ b/lxc-php/tasks/php73.yml @@ -11,7 +11,7 @@ dest: "{{ line_item }}" mode: "0644" notify: "Reload {{ lxc_php_version }}-fpm" - with_items: + loop: - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.3/fpm/conf.d/z-evolinux-defaults.ini" - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.3/cli/conf.d/z-evolinux-defaults.ini" loop_control: diff --git a/lxc-php/tasks/php74.yml b/lxc-php/tasks/php74.yml index c32820f1..2c4538e8 100644 --- a/lxc-php/tasks/php74.yml +++ b/lxc-php/tasks/php74.yml @@ -1,5 +1,5 @@ --- - + - name: "{{ lxc_php_version }} - Install dependency packages" lxc_container: name: "{{ lxc_php_version }}" @@ -12,29 +12,31 @@ state: present create: yes mode: "0644" - with_items: + loop: - "deb https://packages.sury.org/php/ buster main" - "deb http://pub.evolix.net/ buster-php74/" -- name: Grab pub.evolix.net GPG Key - get_url: - url: https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x0C016D3BD1195D30105837CC44975278B8612B5D +- name: copy pub.evolix.net GPG key + copy: + src: reg.asc dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/reg.asc - mode: 0644 - checksum: sha256:a2e0f56ba433aa0740aad6eeeb43bb67df9ab943d76324382b39948a4c7ce840 + mode: "0644" + owner: root + group: root -- name: Grab packages.sury.org GPG Key - get_url: - url: https://packages.sury.org/php/apt.gpg +- name: copy packages.sury.org GPG Key + copy: + src: sury.gpg dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/sury.gpg - mode: 0644 - checksum: sha256:b3ea944563435e54bb64f181ee8bc26200985d09164cdc4c1702fc3ef051f19d + mode: "0644" + owner: root + group: root - name: "{{ lxc_php_version }} - Update APT cache" lxc_container: name: "{{ lxc_php_version }}" container_command: "DEBIAN_FRONTEND=noninteractive apt update" - + - name: "{{ lxc_php_version }} - Install PHP packages" lxc_container: name: "{{ lxc_php_version }}" @@ -46,7 +48,7 @@ dest: "{{ line_item }}" mode: "0644" notify: "Reload {{ lxc_php_version }}-fpm" - with_items: + loop: - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.4/fpm/conf.d/z-evolinux-defaults.ini" - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/7.4/cli/conf.d/z-evolinux-defaults.ini" loop_control: diff --git a/lxc-solr/tasks/main.yml b/lxc-solr/tasks/main.yml index a18c46dc..3fad863f 100644 --- a/lxc-solr/tasks/main.yml +++ b/lxc-solr/tasks/main.yml @@ -8,9 +8,9 @@ path: "/var/lib/lxc/{{ item.name }}/rootfs" state: directory mode: '0755' - with_items: + loop: - "{{ lxc_containers }}" - include: "solr.yml name={{item.name}} solr_version={{item.solr_version}} solr_port={{item.solr_port}}" - with_items: + loop: - "{{ lxc_containers }}" diff --git a/lxc/meta/main.yml b/lxc/meta/main.yml index f6af051d..cd47f609 100644 --- a/lxc/meta/main.yml +++ b/lxc/meta/main.yml @@ -1,17 +1,28 @@ +--- galaxy_info: - author: Evolix - description: Creation of LXC Containers + company: Evolix + description: Creation of LXC Containers issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. allow_duplicates: yes diff --git a/lxc/tasks/create-container.yml b/lxc/tasks/create-container.yml index 8b8a68e3..ad4f35d6 100644 --- a/lxc/tasks/create-container.yml +++ b/lxc/tasks/create-container.yml @@ -12,7 +12,7 @@ template: debian state: stopped template_options: "--arch amd64 --release {{ release }}" - when: container_exists.stdout_lines == [] + when: container_exists.stdout_lines | length == 0 - name: "Disable network configuration inside container {{ name }}" replace: diff --git a/lxc/tasks/main.yml b/lxc/tasks/main.yml index df8dc86f..a3a31cf5 100644 --- a/lxc/tasks/main.yml +++ b/lxc/tasks/main.yml @@ -24,13 +24,13 @@ failed_when: false changed_when: false register: root_subuids - when: lxc_unprivilegied_containers + when: lxc_unprivilegied_containers | bool - name: Add subuid and subgid ranges to root command: usermod -v 100000-199999 -w 100000-109999 root when: - - lxc_unprivilegied_containers - - root_subuids.rc + - lxc_unprivilegied_containers | bool + - root_subuids.rc != 0 - name: Create containers include: create-container.yml diff --git a/memcached/meta/main.yml b/memcached/meta/main.yml index 6e4ba6d8..022facc7 100644 --- a/memcached/meta/main.yml +++ b/memcached/meta/main.yml @@ -1,17 +1,29 @@ +--- galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of memcached. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/memcached/tasks/main.yml b/memcached/tasks/main.yml index 0bf81713..0159f8d6 100644 --- a/memcached/tasks/main.yml +++ b/memcached/tasks/main.yml @@ -13,7 +13,7 @@ notify: restart memcached tags: - memcached - when: memcached_instance_name == "" + when: memcached_instance_name | length == 0 - name: Memcached is running and enabled on boot. service: @@ -22,7 +22,7 @@ state: started tags: - memcached - when: memcached_instance_name == "" + when: memcached_instance_name | length == 0 - name: Add systemd template copy: @@ -30,7 +30,7 @@ dest: /etc/systemd/system/memcached@.service tags: - memcached - when: memcached_instance_name != "" + when: memcached_instance_name | length > 0 - name: Delete default memcached systemd configuration file systemd: @@ -39,7 +39,7 @@ state: stopped tags: - memcached - when: memcached_instance_name != "" + when: memcached_instance_name | length > 0 - name: Make sure memcached.conf is absent file: @@ -47,7 +47,7 @@ state: absent tags: - memcached - when: memcached_instance_name != "" + when: memcached_instance_name | length > 0 - name: Create a configuration file template: @@ -56,7 +56,7 @@ mode: "0644" tags: - memcached - when: memcached_instance_name != "" + when: memcached_instance_name | length > 0 - name: Enable and start the memcached instance systemd: @@ -67,7 +67,7 @@ masked: no tags: - memcached - when: memcached_instance_name != "" + when: memcached_instance_name | length > 0 - include: munin.yml diff --git a/memcached/tasks/munin.yml b/memcached/tasks/munin.yml index c7ea3da9..6e2f6d6f 100644 --- a/memcached/tasks/munin.yml +++ b/memcached/tasks/munin.yml @@ -2,7 +2,7 @@ - name: Choose packages (Oracle) set_fact: multi: "multi_" - when: memcached_instance_name !="" + when: memcached_instance_name | length > 0 - name: is Munin present ? stat: @@ -26,7 +26,7 @@ src: '/usr/share/munin/plugins/memcached_' dest: /etc/munin/plugins/{{ multi }}{{ item }} state: link - with_items: + loop: - memcached_bytes - memcached_counters - memcached_rates diff --git a/metricbeat/files/elastic.asc b/metricbeat/files/elastic.asc new file mode 100644 index 00000000..1b50dcca --- /dev/null +++ b/metricbeat/files/elastic.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/metricbeat/meta/main.yml b/metricbeat/meta/main.yml index 880790f5..697726d8 100644 --- a/metricbeat/meta/main.yml +++ b/metricbeat/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Metricbeat. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/metricbeat/tasks/main.yml b/metricbeat/tasks/main.yml index d148f1cd..640a8902 100644 --- a/metricbeat/tasks/main.yml +++ b/metricbeat/tasks/main.yml @@ -5,17 +5,29 @@ name: apt-transport-https state: present tags: - - metricbeat - - packages + - metricbeat + - packages + +- name: Elastic embedded GPG key is absent + apt_key: + id: "D88E42B4" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - metricbeat + - packages - name: Elastic GPG key is installed - apt_key: - # url: https://artifacts.elastic.co/GPG-KEY-elasticsearch - data: "{{ lookup('file', 'elasticsearch.key') }}" - state: present + copy: + src: elastic.asc + dest: /etc/apt/trusted.gpg.d/elastic.asc + force: yes + mode: "0644" + owner: root + group: root tags: - - metricbeat - - packages + - metricbeat + - packages - name: Elastic sources list is available apt_repository: @@ -24,8 +36,8 @@ state: present update_cache: yes tags: - - metricbeat - - packages + - metricbeat + - packages - name: Metricbeat is installed apt: @@ -51,8 +63,7 @@ line: " hosts: [\"{{ metricbeat_elasticsearch_hosts | join('\", \"') }}\"]" insertafter: "output.elasticsearch:" notify: restart metricbeat - when: - - metricbeat_elasticsearch_hosts + when: metricbeat_elasticsearch_hosts | length > 0 - name: Metricbeat protocol for Elasticsearch lineinfile: @@ -69,13 +80,13 @@ regexp: '{{ item.regexp }}' line: '{{ item.line }}' insertafter: "output.elasticsearch:" - with_items: + loop: - { regexp: '^ #?username: .*', line: ' username: "{{ metricbeat_elasticsearch_auth_username }}"' } - { regexp: '^ #?password: .*', line: ' password: "{{ metricbeat_elasticsearch_auth_password }}"' } notify: restart metricbeat when: - - metricbeat_elasticsearch_auth_username - - metricbeat_elasticsearch_auth_password + - metricbeat_elasticsearch_auth_username | length > 0 + - metricbeat_elasticsearch_auth_password | length > 0 - name: Metricbeat api_key for Elasticsearch are configured lineinfile: @@ -84,7 +95,7 @@ line: ' api_key: "{{ metricbeat_elasticsearch_auth_api_key }}"' insertafter: "output.elasticsearch:" notify: restart metricbeat - when: metricbeat_elasticsearch_auth_api_key + when: metricbeat_elasticsearch_auth_api_key | length > 0 - name: disable cloud_metadata replace: @@ -92,7 +103,7 @@ regexp: '^(\s+)(- add_cloud_metadata:)' replace: '\1# \2' notify: restart metricbeat - when: not metricbeat_processors_cloud_metadata + when: not (metricbeat_processors_cloud_metadata | bool) - name: cloud_metadata processor is disabled lineinfile: @@ -100,8 +111,8 @@ line: " - add_cloud_metadata: ~" insert_after: '^processors:' notify: restart metricbeat - when: metricbeat_processors_cloud_metadata - when: not metricbeat_use_config_template + when: metricbeat_processors_cloud_metadata | bool + when: not (metricbeat_use_config_template | bool) # When we use a config template - block: @@ -110,11 +121,13 @@ src: "{{ item }}" dest: /etc/metricbeat/metricbeat.yml force: "{{ metricbeat_force_config }}" - with_first_found: + loop: "{{ query('first_found', templates) }}" + vars: + templates: - "templates/metricbeat/metricbeat.{{ inventory_hostname }}.yml.j2" - - "templates/metricbeat/metricbeat.{{ host_group }}.yml.j2" + - "templates/metricbeat/metricbeat.{{ host_group | default('all') }}.yml.j2" - "templates/metricbeat/metricbeat.default.yml.j2" - - "metricbeat.default.yml.j2" + - "templates/metricbeat.default.yml.j2" notify: restart metricbeat - when: metricbeat_update_config - when: metricbeat_use_config_template + when: metricbeat_update_config | bool + when: metricbeat_use_config_template | bool diff --git a/minifirewall/meta/main.yml b/minifirewall/meta/main.yml index b8cca373..51dcd9cb 100644 --- a/minifirewall/meta/main.yml +++ b/minifirewall/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and configuration of Minifirewall issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/minifirewall/tasks/activate.yml b/minifirewall/tasks/activate.yml index 21fb8cfd..e971407b 100644 --- a/minifirewall/tasks/activate.yml +++ b/minifirewall/tasks/activate.yml @@ -12,7 +12,7 @@ replace: '/etc/init.d/minifirewall start' when: - initd_alert5.stat.exists - - minifirewall_autostart + - minifirewall_autostart | bool - name: check if /usr/share/scripts/alert5 exists stat: @@ -26,4 +26,4 @@ replace: '/etc/init.d/minifirewall start' when: - usr_share_scripts_alert5.stat.exists - - minifirewall_autostart + - minifirewall_autostart | bool diff --git a/minifirewall/tasks/config.yml b/minifirewall/tasks/config.yml index 4c852d6b..04ed3a9c 100644 --- a/minifirewall/tasks/config.yml +++ b/minifirewall/tasks/config.yml @@ -39,8 +39,7 @@ - name: Verify that at least 1 trusted IP is provided assert: - that: - - minifirewall_trusted_ips != [] + that: minifirewall_trusted_ips | length > 0 msg: You must provide at least 1 trusted IP - debug: @@ -184,14 +183,14 @@ dest: "{{ minifirewall_main_file }}" line: "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s {{ item }} -m state --state ESTABLISHED,RELATED -j ACCEPT" insertafter: "^# EvoMaintenance" - with_items: "{{ evomaintenance_hosts }}" + loop: "{{ evomaintenance_hosts }}" - name: remove minifirewall example rule for the evomaintenance lineinfile: dest: "{{ minifirewall_main_file }}" regexp: '^#.*(--sport 5432).*(-s X\.X\.X\.X)' state: absent - when: evomaintenance_hosts != [] + when: evomaintenance_hosts | length > 0 - name: Stat minifirewall config file (after) stat: @@ -207,7 +206,7 @@ failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout" changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout" when: - - minifirewall_restart_if_needed + - minifirewall_restart_if_needed | bool - minifirewall_is_running.rc == 0 - minifirewall_before.stat.checksum != minifirewall_after.stat.checksum @@ -216,7 +215,7 @@ register: minifirewall_init_restart failed_when: False changed_when: False - when: not minifirewall_restart_if_needed + when: not (minifirewall_restart_if_needed | bool) - debug: var: minifirewall_init_restart diff --git a/minifirewall/tasks/main.yml b/minifirewall/tasks/main.yml index 99a478e0..2a053d4f 100644 --- a/minifirewall/tasks/main.yml +++ b/minifirewall/tasks/main.yml @@ -2,7 +2,7 @@ - name: Compose minifirewall_restart_handler_name variable set_fact: - minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" + minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" - include: install.yml @@ -13,10 +13,10 @@ - include: activate.yml - include: tail.yml - when: minifirewall_tail_included + when: minifirewall_tail_included | bool - name: Force restart minifirewall command: /bin/true notify: restart minifirewall changed_when: False - when: minifirewall_restart_force + when: minifirewall_restart_force | bool diff --git a/minifirewall/tasks/tail.yml b/minifirewall/tasks/tail.yml index 1f6b715d..c8c4440e 100644 --- a/minifirewall/tasks/tail.yml +++ b/minifirewall/tasks/tail.yml @@ -4,11 +4,13 @@ src: "{{ item }}" dest: "{{ minifirewall_tail_file }}" force: "{{ minifirewall_tail_force | bool }}" - with_first_found: - - "templates/minifirewall-tail/minifirewall.{{ inventory_hostname }}.tail.j2" - - "templates/minifirewall-tail/minifirewall.{{ host_group }}.tail.j2" - - "templates/minifirewall-tail/minifirewall.default.tail.j2" - - "minifirewall.default.tail.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/minifirewall-tail/minifirewall.{{ inventory_hostname }}.tail.j2" + - "templates/minifirewall-tail/minifirewall.{{ host_group | default('all') }}.tail.j2" + - "templates/minifirewall-tail/minifirewall.default.tail.j2" + - "templates/minifirewall.default.tail.j2" register: minifirewall_tail_template - debug: @@ -37,14 +39,14 @@ changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout" when: - minifirewall_tail_template is changed - - minifirewall_restart_if_needed + - minifirewall_restart_if_needed | bool - name: restart minifirewall (noop) meta: noop register: minifirewall_init_restart failed_when: False changed_when: False - when: not minifirewall_restart_if_needed + when: not (minifirewall_restart_if_needed | bool) - debug: var: minifirewall_init_restart diff --git a/mongodb/meta/main.yml b/mongodb/meta/main.yml index 72e764e2..cf463d73 100644 --- a/mongodb/meta/main.yml +++ b/mongodb/meta/main.yml @@ -5,12 +5,14 @@ galaxy_info: license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/mongodb/tasks/main_buster.yml b/mongodb/tasks/main_buster.yml index 5aae2ed3..2e62255a 100644 --- a/mongodb/tasks/main_buster.yml +++ b/mongodb/tasks/main_buster.yml @@ -1,9 +1,19 @@ --- -- name: MongoDB public GPG Key +- name: MongoDB embedded GPG key is absent apt_key: - # url: https://www.mongodb.org/static/pgp/server-4.2.asc - data: "{{ lookup('file', 'server-4.2.asc') }}" + id: "B8612B5D" + keyring: /etc/apt/trusted.gpg + state: absent + +- name: Add MongoDB GPG key + copy: + src: server-4.2.asc + dest: /etc/apt/trusted.gpg.d/mongodb-server-4.2.asc + force: yes + mode: "0644" + owner: root + group: root - name: enable APT sources list apt_repository: @@ -24,7 +34,7 @@ name: mongod enabled: yes state: started - when: _mongodb_install_package.changed + when: _mongodb_install_package is changed - name: install dependency for monitoring apt: @@ -45,12 +55,24 @@ force: yes backup: no +- name: Create plugin directory + file: + name: /usr/local/share/munin/ + state: directory + mode: "0755" + +- name: Create plugin directory + file: + name: /usr/local/share/munin/plugins/ + state: directory + mode: "0755" + - name: Munin plugins are present copy: src: "munin/{{ item }}" dest: '/usr/local/share/munin/plugins/{{ item }}' force: yes - with_items: + loop: - mongo_btree - mongo_collections - mongo_conn @@ -66,7 +88,7 @@ src: '/usr/local/share/munin/plugins/{{ item }}' dest: /etc/munin/plugins/{{ item }} state: link - with_items: + loop: - mongo_btree - mongo_collections - mongo_conn diff --git a/monit/meta/main.yml b/monit/meta/main.yml index 4a22e18c..64d96a7d 100644 --- a/monit/meta/main.yml +++ b/monit/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Monit. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/munin/meta/main.yml b/munin/meta/main.yml index 7b95e655..40eee676 100644 --- a/munin/meta/main.yml +++ b/munin/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of Munin with a selection of plugins issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/munin/tasks/main.yml b/munin/tasks/main.yml index 344962f8..aab79f62 100644 --- a/munin/tasks/main.yml +++ b/munin/tasks/main.yml @@ -35,7 +35,7 @@ file: path: '/etc/munin/plugins/{{ item }}' state: absent - with_items: + loop: - http_loadtime - exim_mailqueue - exim_mailstats @@ -52,7 +52,7 @@ src: "/usr/share/munin/plugins/{{ item }}" dest: "/etc/munin/plugins/{{ item }}" state: link - with_items: + loop: - meminfo - netstat_multi - tcp diff --git a/mysql-oracle/meta/main.yml b/mysql-oracle/meta/main.yml index 963a0494..5479f9db 100644 --- a/mysql-oracle/meta/main.yml +++ b/mysql-oracle/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Install and configure MySQL 5.7 (with Oracle packages) issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/mysql-oracle/tasks/datadir.yml b/mysql-oracle/tasks/datadir.yml index 28beb1ed..c375f5d5 100644 --- a/mysql-oracle/tasks/datadir.yml +++ b/mysql-oracle/tasks/datadir.yml @@ -14,7 +14,7 @@ register: mysql_current_real_datadir_test tags: - mysql - when: mysql_custom_datadir != '' + when: mysql_custom_datadir | length > 0 - block: - name: MySQL is stopped @@ -40,6 +40,6 @@ tags: - mysql when: - - mysql_custom_datadir != '' + - mysql_custom_datadir | length > 0 - mysql_custom_datadir != mysql_current_real_datadir_test.stdout - not mysql_custom_datadir_test.stat.exists diff --git a/mysql-oracle/tasks/munin.yml b/mysql-oracle/tasks/munin.yml index 70e871e1..b9e633b0 100644 --- a/mysql-oracle/tasks/munin.yml +++ b/mysql-oracle/tasks/munin.yml @@ -22,7 +22,7 @@ src: '/usr/share/munin/plugins/{{ item }}' dest: /etc/munin/plugins/{{ item }} state: link - with_items: + loop: - mysql_bytes - mysql_queries - mysql_slowqueries @@ -34,7 +34,7 @@ src: /usr/share/munin/plugins/mysql_ dest: '/etc/munin/plugins/mysql_{{ item }}' state: link - with_items: + loop: - commands - connections - files_tables diff --git a/mysql-oracle/tasks/nrpe.yml b/mysql-oracle/tasks/nrpe.yml index c02fc007..c3457699 100644 --- a/mysql-oracle/tasks/nrpe.yml +++ b/mysql-oracle/tasks/nrpe.yml @@ -44,12 +44,14 @@ section: client option: '{{ item.option }}' value: '{{ item.value }}' - with_items: + loop: - { option: 'user', value: 'nrpe' } - { option: 'password', value: '{{ mysql_nrpe_password.stdout }}' } - when: create_nrpe_user.changed + when: create_nrpe_user is changed - when: nrpe_evolix_config.stat.exists and (not nrpe_my_cnf.stat.exists or mysql_force_new_nrpe_password) + when: + - nrpe_evolix_config.stat.exists + - (not nrpe_my_cnf.stat.exists or (mysql_force_new_nrpe_password | bool)) tags: - mysql - nrpe diff --git a/mysql-oracle/tasks/packages.yml b/mysql-oracle/tasks/packages.yml index af1a0460..5bf8848e 100644 --- a/mysql-oracle/tasks/packages.yml +++ b/mysql-oracle/tasks/packages.yml @@ -87,7 +87,7 @@ tags: - mysql - packages - when: mysql_install_libclient + when: mysql_install_libclient | bool - name: MySQL is started systemd: diff --git a/mysql-oracle/tasks/tmpdir.yml b/mysql-oracle/tasks/tmpdir.yml index 8d518160..790a9f2e 100644 --- a/mysql-oracle/tasks/tmpdir.yml +++ b/mysql-oracle/tasks/tmpdir.yml @@ -20,4 +20,4 @@ notify: "{{ mysql_restart_handler_name }}" tags: - mysql - when: mysql_custom_tmpdir != '' + when: mysql_custom_tmpdir | length > 0 diff --git a/mysql-oracle/tasks/users.yml b/mysql-oracle/tasks/users.yml index 50e0fb58..da1ca05f 100644 --- a/mysql-oracle/tasks/users.yml +++ b/mysql-oracle/tasks/users.yml @@ -36,7 +36,7 @@ option: '{{ item.option }}' value: '{{ item.value }}' create: yes - with_items: + loop: - { option: 'user', value: 'mysqladmin' } - { option: 'password', value: '{{ mysql_admin_password.stdout }}' } when: create_mysqladmin_user is changed @@ -71,11 +71,12 @@ option: '{{ item[1].option }}' value: '{{ item[1].value }}' create: yes - with_nested: - - [ "client", "mysql_upgrade" ] - - [ { option: 'user', value: 'debian-sys-maint' }, - { option: 'password', value: '{{ mysql_debian_password.stdout }}' } - ] + loop: "{{ _sections | product(_credentials) | list }}" + vars: + _sections: [ 'client', 'mysql_upgrade' ] + _credentials: + - { option: 'user', value: 'debian-sys-maint' } + - { option: 'password', value: '{{ mysql_debian_password.stdout }}' } when: create_debian_user is changed tags: - mysql diff --git a/mysql-oracle/tasks/utils.yml b/mysql-oracle/tasks/utils.yml index bf0013df..e7573afe 100644 --- a/mysql-oracle/tasks/utils.yml +++ b/mysql-oracle/tasks/utils.yml @@ -1,12 +1,15 @@ --- +- set_fact: + _mysql_scripts_dir: "{{ mysql_scripts_dir | default(general_scripts_dir, True) | mandatory }}" + - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Scripts directory exists file: - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}" + dest: "{{ _mysql_scripts_dir }}" mode: "0700" state: directory tags: @@ -95,12 +98,12 @@ name: evolix/remount-usr tags: - mysql - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: mysqltuner is installed # copy: # src: mysqltuner.pl - # dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysqltuner.pl" + # dest: "{{ _mysql_scripts_dir }}/mysqltuner.pl" # mode: "0700" apt: name: mysqltuner @@ -121,12 +124,12 @@ name: evolix/remount-usr tags: - mysql - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: mysql-optimize.sh is installed copy: src: mysql-optimize.sh - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysql-optimize.sh" + dest: "{{ _mysql_scripts_dir }}/mysql-optimize.sh" mode: "0700" tags: - mysql @@ -143,7 +146,7 @@ - name: "Enable cron to optimize MySQL" file: - src: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysql-optimize.sh" + src: "{{ _mysql_scripts_dir }}/mysql-optimize.sh" dest: /etc/cron.{{ mysql_cron_optimize_frequency | mandatory }}/mysql-optimize.sh state: link when: mysql_cron_optimize | bool @@ -192,12 +195,12 @@ - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Install my-add.sh copy: src: my-add.sh - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/my-add.sh" + dest: "{{ _mysql_scripts_dir }}/my-add.sh" mode: "0700" tags: - mysql diff --git a/mysql/defaults/main.yml b/mysql/defaults/main.yml index 1e2f673d..2986a869 100644 --- a/mysql/defaults/main.yml +++ b/mysql/defaults/main.yml @@ -41,6 +41,8 @@ mysql_cron_mysqltuner_frequency: monthly mysql_force_new_nrpe_password: False +mysql_force_myadd_script: True + mysql_evolinux_defaults_file: z-evolinux-defaults.cnf mysql_evolinux_custom_file: zzz-evolinux-custom.cnf diff --git a/mysql/meta/main.yml b/mysql/meta/main.yml index 82be1e3c..bd21f0c6 100644 --- a/mysql/meta/main.yml +++ b/mysql/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: your description issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/mysql/tasks/config_stretch.yml b/mysql/tasks/config_stretch.yml index d6d59efd..cfbeedfe 100644 --- a/mysql/tasks/config_stretch.yml +++ b/mysql/tasks/config_stretch.yml @@ -42,4 +42,4 @@ name: mysql daemon_reload: yes notify: "{{ mysql_restart_handler_name }}" - when: mariadb_systemd_override.changed + when: mariadb_systemd_override is changed diff --git a/mysql/tasks/datadir.yml b/mysql/tasks/datadir.yml index 28beb1ed..c375f5d5 100644 --- a/mysql/tasks/datadir.yml +++ b/mysql/tasks/datadir.yml @@ -14,7 +14,7 @@ register: mysql_current_real_datadir_test tags: - mysql - when: mysql_custom_datadir != '' + when: mysql_custom_datadir | length > 0 - block: - name: MySQL is stopped @@ -40,6 +40,6 @@ tags: - mysql when: - - mysql_custom_datadir != '' + - mysql_custom_datadir | length > 0 - mysql_custom_datadir != mysql_current_real_datadir_test.stdout - not mysql_custom_datadir_test.stat.exists diff --git a/mysql/tasks/logdir.yml b/mysql/tasks/logdir.yml index a1b3a8d8..bd6ecab2 100644 --- a/mysql/tasks/logdir.yml +++ b/mysql/tasks/logdir.yml @@ -14,7 +14,7 @@ register: mysql_current_real_logdir_test tags: - mysql - when: mysql_custom_logdir != '' + when: mysql_custom_logdir | length > 0 - block: - name: MySQL is stopped @@ -40,6 +40,6 @@ tags: - mysql when: - - mysql_custom_logdir != '' + - mysql_custom_logdir | length > 0 - mysql_custom_logdir != mysql_current_real_logdir_test.stdout - not mysql_custom_logdir_test.stat.exists diff --git a/mysql/tasks/main.yml b/mysql/tasks/main.yml index 11435c73..ace6299e 100644 --- a/mysql/tasks/main.yml +++ b/mysql/tasks/main.yml @@ -23,7 +23,7 @@ when: ansible_distribution_release == "jessie" - include: replication.yml - when: mysql_replication + when: mysql_replication | bool - include: datadir.yml diff --git a/mysql/tasks/munin.yml b/mysql/tasks/munin.yml index c7017aa2..f2a333e7 100644 --- a/mysql/tasks/munin.yml +++ b/mysql/tasks/munin.yml @@ -22,7 +22,7 @@ src: '/usr/share/munin/plugins/{{ item }}' dest: /etc/munin/plugins/{{ item }} state: link - with_items: + loop: - mysql_bytes - mysql_queries - mysql_slowqueries @@ -34,7 +34,7 @@ src: /usr/share/munin/plugins/mysql_ dest: '/etc/munin/plugins/mysql_{{ item }}' state: link - with_items: + loop: - commands - connections - files_tables diff --git a/mysql/tasks/nrpe.yml b/mysql/tasks/nrpe.yml index c02fc007..c3457699 100644 --- a/mysql/tasks/nrpe.yml +++ b/mysql/tasks/nrpe.yml @@ -44,12 +44,14 @@ section: client option: '{{ item.option }}' value: '{{ item.value }}' - with_items: + loop: - { option: 'user', value: 'nrpe' } - { option: 'password', value: '{{ mysql_nrpe_password.stdout }}' } - when: create_nrpe_user.changed + when: create_nrpe_user is changed - when: nrpe_evolix_config.stat.exists and (not nrpe_my_cnf.stat.exists or mysql_force_new_nrpe_password) + when: + - nrpe_evolix_config.stat.exists + - (not nrpe_my_cnf.stat.exists or (mysql_force_new_nrpe_password | bool)) tags: - mysql - nrpe diff --git a/mysql/tasks/packages_jessie.yml b/mysql/tasks/packages_jessie.yml index 8d27de52..48408433 100644 --- a/mysql/tasks/packages_jessie.yml +++ b/mysql/tasks/packages_jessie.yml @@ -33,7 +33,7 @@ tags: - mysql - packages - when: mysql_install_libclient + when: mysql_install_libclient | bool - name: MySQL is started service: diff --git a/mysql/tasks/packages_stretch.yml b/mysql/tasks/packages_stretch.yml index 901543af..98a8f69d 100644 --- a/mysql/tasks/packages_stretch.yml +++ b/mysql/tasks/packages_stretch.yml @@ -19,7 +19,7 @@ tags: - mysql - packages - when: mysql_install_libclient + when: mysql_install_libclient | bool - name: MySQL is started service: diff --git a/mysql/tasks/tmpdir.yml b/mysql/tasks/tmpdir.yml index e2c13dc5..79a3ac5e 100644 --- a/mysql/tasks/tmpdir.yml +++ b/mysql/tasks/tmpdir.yml @@ -20,4 +20,4 @@ notify: "{{ mysql_restart_handler_name }}" tags: - mysql - when: mysql_custom_tmpdir != '' + when: mysql_custom_tmpdir | length > 0 diff --git a/mysql/tasks/users_jessie.yml b/mysql/tasks/users_jessie.yml index f11e41af..99dd2d04 100644 --- a/mysql/tasks/users_jessie.yml +++ b/mysql/tasks/users_jessie.yml @@ -42,10 +42,10 @@ option: '{{ item.option }}' value: '{{ item.value }}' create: yes - with_items: + loop: - { option: 'user', value: 'mysqladmin' } - { option: 'password', value: '{{ mysql_admin_password.stdout }}' } - when: create_mysqladmin_user.changed + when: create_mysqladmin_user is changed tags: - mysql diff --git a/mysql/tasks/users_stretch.yml b/mysql/tasks/users_stretch.yml index 70ae9933..574399af 100644 --- a/mysql/tasks/users_stretch.yml +++ b/mysql/tasks/users_stretch.yml @@ -37,10 +37,10 @@ option: '{{ item.option }}' value: '{{ item.value }}' create: yes - with_items: + loop: - { option: 'user', value: 'mysqladmin' } - { option: 'password', value: '{{ mysql_admin_password.stdout }}' } - when: create_mysqladmin_user.changed + when: create_mysqladmin_user is changed tags: - mysql @@ -63,7 +63,7 @@ config_file: "/root/.my.cnf" register: create_debian_user tags: - - mysql + - mysql - name: store debian-sys-maint user credentials ini_file: @@ -73,14 +73,15 @@ option: '{{ item[1].option }}' value: '{{ item[1].value }}' create: yes - with_nested: - - [ "client", "mysql_upgrade" ] - - [ { option: 'user', value: 'debian-sys-maint' }, - { option: 'password', value: '{{ mysql_debian_password.stdout }}' } - ] - when: create_debian_user.changed + loop: "{{ _sections | product(_credentials) | list }}" + vars: + _sections: [ 'client', 'mysql_upgrade' ] + _credentials: + - { option: 'user', value: 'debian-sys-maint' } + - { option: 'password', value: '{{ mysql_debian_password.stdout }}' } + when: create_debian_user is changed tags: - - mysql + - mysql - name: remove root user mysql_user: @@ -89,4 +90,4 @@ config_file: "/root/.my.cnf" state: absent tags: - - mysql + - mysql diff --git a/mysql/tasks/utils.yml b/mysql/tasks/utils.yml index 164507aa..b4abf059 100644 --- a/mysql/tasks/utils.yml +++ b/mysql/tasks/utils.yml @@ -1,12 +1,15 @@ --- +- set_fact: + _mysql_scripts_dir: "{{ mysql_scripts_dir | default(general_scripts_dir, True) | mandatory }}" + - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Ensure scripts directory exists file: - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}" + dest: "{{ _mysql_scripts_dir }}" mode: "0700" state: directory tags: @@ -62,12 +65,12 @@ - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Install mysqltuner # copy: # src: mysqltuner.pl - # dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysqltuner.pl" + # dest: "{{ _mysql_scripts_dir }}/mysqltuner.pl" # mode: "0700" apt: name: mysqltuner @@ -98,12 +101,12 @@ - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Optimize script for MySQL copy: src: mysql-optimize.sh - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysql-optimize.sh" + dest: "{{ _mysql_scripts_dir }}/mysql-optimize.sh" mode: "0700" tags: - mysql @@ -118,10 +121,10 @@ - name: "Enable cron to optimize MySQL" file: - src: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/mysql-optimize.sh" + src: "{{ _mysql_scripts_dir }}/mysql-optimize.sh" dest: /etc/cron.{{ mysql_cron_optimize_frequency | mandatory }}/mysql-optimize.sh state: link - when: mysql_cron_optimize + when: mysql_cron_optimize | bool tags: - mysql @@ -129,7 +132,7 @@ file: dest: /etc/cron.{{ mysql_cron_optimize_frequency | mandatory }}/mysql-optimize.sh state: absent - when: not mysql_cron_optimize + when: not (mysql_cron_optimize | bool) tags: - mysql @@ -146,7 +149,7 @@ src: mysqltuner.cron.sh dest: /etc/cron.{{ mysql_cron_mysqltuner_frequency | mandatory }}/mysqltuner.sh mode: "0755" - when: mysql_cron_mysqltuner + when: mysql_cron_mysqltuner | bool tags: - mysql @@ -154,7 +157,7 @@ file: dest: /etc/cron.{{ mysql_cron_mysqltuner_frequency | mandatory }}/mysqltuner.sh state: absent - when: not mysql_cron_mysqltuner + when: not (mysql_cron_mysqltuner | bool) tags: - mysql @@ -162,13 +165,14 @@ - include_role: name: evolix/remount-usr - when: (mysql_scripts_dir or general_scripts_dir) is search ("/usr") + when: _mysql_scripts_dir is search ("/usr") - name: Install my-add.sh copy: src: my-add.sh - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/my-add.sh" + dest: "{{ _mysql_scripts_dir }}/my-add.sh" mode: "0700" + force: "{{ mysql_force_myadd_script }}" tags: - mysql @@ -182,7 +186,7 @@ - name: "Install save_mysql_processlist.sh" copy: src: save_mysql_processlist.sh - dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/save_mysql_processlist.sh" + dest: "{{ _mysql_scripts_dir }}/save_mysql_processlist.sh" mode: "0755" force: no tags: diff --git a/nagios-nrpe/meta/main.yml b/nagios-nrpe/meta/main.yml index acdb111c..0a9458d5 100644 --- a/nagios-nrpe/meta/main.yml +++ b/nagios-nrpe/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and custom configuration of Nagios NRPE server. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/nagios-nrpe/tasks/main.yml b/nagios-nrpe/tasks/main.yml index 065ffacc..77770020 100644 --- a/nagios-nrpe/tasks/main.yml +++ b/nagios-nrpe/tasks/main.yml @@ -42,7 +42,7 @@ regexp: '^allowed_hosts=' insertafter: '# Allowed IPs' notify: restart nagios-nrpe-server - when: nagios_nrpe_force_update_allowed_hosts + when: nagios_nrpe_force_update_allowed_hosts | bool tags: - nagios-nrpe diff --git a/nameserver/tasks/main.yml b/nameserver/tasks/main.yml index 4623fffc..420e65af 100644 --- a/nameserver/tasks/main.yml +++ b/nameserver/tasks/main.yml @@ -12,7 +12,7 @@ dest: /etc/resolv.conf line: "nameserver {{ item }}" state: present - with_items: "{{ nameservers }}" + loop: "{{ nameservers }}" tags: - nameserver @@ -21,7 +21,7 @@ dest: /etc/resolv.conf line: "nameserver {{ item }}" state: absent - with_items: "{{ grep_nameserver.stdout_lines }}" + loop: "{{ grep_nameserver.stdout_lines }}" when: item not in nameservers tags: - nameserver diff --git a/networkd-to-ifconfig/meta/main.yml b/networkd-to-ifconfig/meta/main.yml index 7040a19e..4ecab164 100644 --- a/networkd-to-ifconfig/meta/main.yml +++ b/networkd-to-ifconfig/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Switch back from systemd "networkd" to plain old /etc/network/interfaces. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/networkd-to-ifconfig/tasks/main.yml b/networkd-to-ifconfig/tasks/main.yml index 29ca3b4f..d1ac0ac4 100644 --- a/networkd-to-ifconfig/tasks/main.yml +++ b/networkd-to-ifconfig/tasks/main.yml @@ -7,7 +7,9 @@ - debug: msg: A /etc/network/interfaces file already exists, nothing is done. - when: interfaces_file.stat.exists and not force_update_eni_file + when: + - interfaces_file.stat.exists + - not (force_update_eni_file | bool) - block: - name: "Look for systemd network config" @@ -38,7 +40,7 @@ - eni_ipv6_address | ipv6 - eni_ipv6_gateway | ipv6 msg: "IPv6 configuration is invalid" - when: eni_ipv6_address or eni_ipv6_gateway + when: (eni_ipv6_address | length > 0) or (eni_ipv6_gateway | length > 0) - name: "A new /etc/network/interfaces is generated" template: @@ -63,4 +65,4 @@ - debug: msg: You should verify your configuration, then reboot the server. - when: force_update_eni_file or not interfaces_file.stat.exists + when: (force_update_eni_file | bool) or (not interfaces_file.stat.exists) diff --git a/networkd-to-ifconfig/tasks/set_facts_from_ansible.yml b/networkd-to-ifconfig/tasks/set_facts_from_ansible.yml index 21de7357..5f6f4011 100644 --- a/networkd-to-ifconfig/tasks/set_facts_from_ansible.yml +++ b/networkd-to-ifconfig/tasks/set_facts_from_ansible.yml @@ -4,10 +4,10 @@ set_fact: eni_ipv4_address: "{{ ansible_default_ipv4.address | ipv4 }}" eni_ipv4_gateway: "{{ ansible_default_ipv4.gateway | ipv4 }}" - when: ansible_default_ipv4 + when: ansible_default_ipv4 | length > 0 - name: Prepare variables (IPv6) set_fact: eni_ipv6_address: "{{ ansible_default_ipv6.address | ipv6 | first }}" eni_ipv6_gateway: "{{ ansible_default_ipv6.gateway | ipv6 | first }}" - when: ansible_default_ipv6 + when: ansible_default_ipv6 | length > 0 diff --git a/newrelic/files/548C16BF.gpg b/newrelic/files/newrelic.asc similarity index 100% rename from newrelic/files/548C16BF.gpg rename to newrelic/files/newrelic.asc diff --git a/newrelic/meta/main.yml b/newrelic/meta/main.yml index 0436c6ae..dc077c68 100644 --- a/newrelic/meta/main.yml +++ b/newrelic/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of NewRelic tools. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/newrelic/tasks/main.yml b/newrelic/tasks/main.yml index 7537214d..a4e8f2b3 100644 --- a/newrelic/tasks/main.yml +++ b/newrelic/tasks/main.yml @@ -3,7 +3,7 @@ - include: sources.yml - include: php.yml - when: newrelic_php + when: newrelic_php | bool - include: sysmond.yml - when: newrelic_sysmond + when: newrelic_sysmond | bool diff --git a/newrelic/tasks/php.yml b/newrelic/tasks/php.yml index 7d1177dc..c41dbac9 100644 --- a/newrelic/tasks/php.yml +++ b/newrelic/tasks/php.yml @@ -6,7 +6,7 @@ question: "newrelic-php5/application-name" value: "{{ newrelic_appname }}" vtype: string - when: newrelic_appname != "" + when: newrelic_appname | length > 0 - name: Pre-seed package configuration with license debconf: @@ -14,7 +14,7 @@ question: "newrelic-php5/license-key" value: "{{ newrelic_license }}" vtype: "string" - when: newrelic_license != "" + when: newrelic_license | length > 0 - name: list newrelic config files shell: "find /etc/php* -type f -name newrelic.ini" @@ -27,14 +27,14 @@ dest: "{{ item }}" regexp: '^;?newrelic.daemon.utilization.detect_aws' line: 'newrelic.daemon.utilization.detect_aws = false' - with_items: "{{ find_newrelic_ini.stdout_lines }}" + loop: "{{ find_newrelic_ini.stdout_lines }}" - name: Disable Docker detection lineinfile: dest: "{{ item }}" regexp: '^;?newrelic.daemon.utilization.detect_docker' line: 'newrelic.daemon.utilization.detect_docker = false' - with_items: "{{ find_newrelic_ini.stdout_lines }}" + loop: "{{ find_newrelic_ini.stdout_lines }}" - name: Install package for PHP apt: diff --git a/newrelic/tasks/sources.yml b/newrelic/tasks/sources.yml index b5b35fd0..08a3ae51 100644 --- a/newrelic/tasks/sources.yml +++ b/newrelic/tasks/sources.yml @@ -1,9 +1,19 @@ --- -- name: Add dotdeb GPG key +- name: NewRelic embedded GPG key is absent apt_key: - # url: https://download.newrelic.com/548C16BF.gpg - data: "{{ lookup('file', '548C16BF.gpg') }}" + id: "548C16BF" + keyring: /etc/apt/trusted.gpg + state: absent + +- name: Add NewRelic GPG key + copy: + src: newrelic.asc + dest: /etc/apt/trusted.gpg.d/newrelic.asc + force: yes + mode: "0644" + owner: root + group: root - name: Install NewRelic repository apt_repository: diff --git a/newrelic/tasks/sysmond.yml b/newrelic/tasks/sysmond.yml index 5d72a470..e5c5bab9 100644 --- a/newrelic/tasks/sysmond.yml +++ b/newrelic/tasks/sysmond.yml @@ -9,5 +9,5 @@ dest: /etc/newrelic/nrsysmond.cfg regexp: "license_key=REPLACE_WITH_REAL_KEY" replace: "license_key={{ newrelic_license }}" - when: newrelic_license != "" + when: newrelic_license | length > 0 notify: restart newrelic-sysmond diff --git a/nginx/meta/main.yml b/nginx/meta/main.yml index 39382693..d4530276 100644 --- a/nginx/meta/main.yml +++ b/nginx/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Nginx issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/nginx/tasks/ip_whitelist.yml b/nginx/tasks/ip_whitelist.yml index 10cdcc37..2667d1d3 100644 --- a/nginx/tasks/ip_whitelist.yml +++ b/nginx/tasks/ip_whitelist.yml @@ -5,7 +5,7 @@ dest: /etc/nginx/snippets/ipaddr_whitelist line: "allow {{ item }};" state: present - with_items: "{{ nginx_ipaddr_whitelist_present }}" + loop: "{{ nginx_ipaddr_whitelist_present }}" notify: reload nginx tags: - nginx @@ -16,7 +16,7 @@ dest: /etc/nginx/snippets/ipaddr_whitelist line: "allow {{ item }};" state: absent - with_items: "{{ nginx_ipaddr_whitelist_absent }}" + loop: "{{ nginx_ipaddr_whitelist_absent }}" notify: reload nginx tags: - nginx diff --git a/nginx/tasks/main.yml b/nginx/tasks/main.yml index 6fe9a94e..8a8fc264 100644 --- a/nginx/tasks/main.yml +++ b/nginx/tasks/main.yml @@ -2,7 +2,7 @@ - debug: msg: "Nginx minimal mode has been removed, falling back to normal mode." - when: nginx_minimal + when: nginx_minimal | bool - include: packages.yml @@ -80,7 +80,7 @@ dest: /etc/nginx/snippets/private_htpasswd line: "{{ item }}" state: present - with_items: "{{ nginx_private_htpasswd_present }}" + loop: "{{ nginx_private_htpasswd_present }}" notify: reload nginx tags: - nginx @@ -90,7 +90,7 @@ dest: /etc/nginx/snippets/private_htpasswd line: "{{ item }}" state: absent - with_items: "{{ nginx_private_htpasswd_absent }}" + loop: "{{ nginx_private_htpasswd_absent }}" notify: reload nginx tags: - nginx @@ -112,7 +112,7 @@ state: link force: yes notify: reload nginx - when: nginx_evolinux_default_enabled + when: nginx_evolinux_default_enabled | bool tags: - nginx diff --git a/nginx/tasks/munin_graphs.yml b/nginx/tasks/munin_graphs.yml index 470f8fd6..ae0bb9ac 100644 --- a/nginx/tasks/munin_graphs.yml +++ b/nginx/tasks/munin_graphs.yml @@ -12,7 +12,7 @@ src: '/usr/share/munin/plugins/{{ item }}' dest: '/etc/munin/plugins/{{ item }}' state: link - with_items: + loop: - nginx_request - nginx_status notify: restart munin diff --git a/nginx/tasks/packages.yml b/nginx/tasks/packages.yml index 05c033b4..7d9eead5 100644 --- a/nginx/tasks/packages.yml +++ b/nginx/tasks/packages.yml @@ -2,10 +2,10 @@ - set_fact: nginx_package_name_default: nginx-light - when: nginx_minimal + when: nginx_minimal | bool - include: packages_backports.yml - when: nginx_backports + when: nginx_backports | bool # TODO: install "nginx" + only necessary modules, instead of "nginx-full" diff --git a/nginx/tasks/server_status_read.yml b/nginx/tasks/server_status_read.yml index 570febf9..652bc154 100644 --- a/nginx/tasks/server_status_read.yml +++ b/nginx/tasks/server_status_read.yml @@ -14,7 +14,7 @@ # The last character "\u000A" is a line feed (LF), it's better to keep it content: "{{ nginx_serverstatus_suffix }}\u000A" force: yes - when: nginx_serverstatus_suffix != "" + when: nginx_serverstatus_suffix | length > 0 - name: generate random string for server-status suffix shell: "apg -a 1 -M N -n 1 > {{ nginx_serverstatus_suffix_file }}" diff --git a/nodejs/files/nodesource.gpg.key b/nodejs/files/nodesource.asc similarity index 100% rename from nodejs/files/nodesource.gpg.key rename to nodejs/files/nodesource.asc diff --git a/nodejs/files/yarnpkg.gpg.key b/nodejs/files/yarn.asc similarity index 98% rename from nodejs/files/yarnpkg.gpg.key rename to nodejs/files/yarn.asc index 530eb5e3..e8d9cabb 100644 --- a/nodejs/files/yarnpkg.gpg.key +++ b/nodejs/files/yarn.asc @@ -1,243 +1,243 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=IgpF ------END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=IgpF +-----END PGP PUBLIC KEY BLOCK----- diff --git a/nodejs/meta/main.yml b/nodejs/meta/main.yml index fa8e2dd2..1e928446 100644 --- a/nodejs/meta/main.yml +++ b/nodejs/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of NodeJS from NPM repositories issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/nodejs/tasks/main.yml b/nodejs/tasks/main.yml index bad66d95..4f8c2849 100644 --- a/nodejs/tasks/main.yml +++ b/nodejs/tasks/main.yml @@ -7,11 +7,25 @@ tags: - system - packages + - nodejs + +- name: NodeJS embedded GPG key is absent + apt_key: + id: "68576280" + keyring: /etc/apt/trusted.gpg + state: absent + tags: + - system + - packages + - nodejs - name: NodeJS GPG key is installed - apt_key: - # url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key - data: "{{ lookup('file', 'nodesource.gpg.key') }}" + copy: + src: nodesource.asc + dest: /etc/apt/trusted.gpg.d/nodesource.asc + mode: "0644" + owner: root + group: root tags: - system - packages @@ -32,9 +46,10 @@ apt: name: nodejs state: present + update_cache: yes tags: - packages - nodejs - include: yarn.yml - when: nodejs_install_yarn + when: nodejs_install_yarn | bool diff --git a/nodejs/tasks/yarn.yml b/nodejs/tasks/yarn.yml index 47af5c50..44306d42 100644 --- a/nodejs/tasks/yarn.yml +++ b/nodejs/tasks/yarn.yml @@ -1,16 +1,30 @@ --- -- name: yarn GPG key is installed +- name: Yarn embedded GPG key is absent apt_key: - # url: https://dl.yarnpkg.com/debian/pubkey.gpg - data: "{{ lookup('file', 'yarnpkg.gpg.key') }}" + id: "86E50310" + keyring: /etc/apt/trusted.gpg + state: absent tags: - system - packages - nodejs - yarn -- name: yarn sources list is available +- name: Yarn GPG key is installed + copy: + src: yarn.asc + dest: /etc/apt/trusted.gpg.d/yarn.asc + mode: "0644" + owner: root + group: root + tags: + - system + - packages + - nodejs + - yarn + +- name: Yarn sources list is available apt_repository: repo: "deb https://dl.yarnpkg.com/debian/ stable main" filename: yarn @@ -22,7 +36,7 @@ - nodejs - yarn -- name: yarn is installed +- name: Yarn is installed apt: name: yarn state: present diff --git a/ntpd/templates/ntp.conf.j2 b/ntpd/templates/ntp.conf.j2 index e57dad33..d89a83ee 100644 --- a/ntpd/templates/ntp.conf.j2 +++ b/ntpd/templates/ntp.conf.j2 @@ -2,6 +2,11 @@ driftfile /var/lib/ntp/ntp.drift +{% if ansible_distribution_major_version is version('10', '>=') %} +# Leap seconds definition provided by tzdata +leapfile /usr/share/zoneinfo/leap-seconds.list +{% endif %} + # Enable this if you want statistics to be logged. #statsdir /var/log/ntpstats/ diff --git a/opendkim/tasks/main.yml b/opendkim/tasks/main.yml index 901d03f2..1db961e2 100644 --- a/opendkim/tasks/main.yml +++ b/opendkim/tasks/main.yml @@ -38,7 +38,7 @@ owner: opendkim group: opendkim mode: "0640" - with_items: + loop: - 'KeyTable' - 'SigningTable' changed_when: False diff --git a/packweb-apache/meta/main.yml b/packweb-apache/meta/main.yml index cd4b4f94..7033e7e9 100644 --- a/packweb-apache/meta/main.yml +++ b/packweb-apache/meta/main.yml @@ -1,19 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of Evolix "Pack Web" meta-role issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch - - buster + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. allow_duplicates: true @@ -27,5 +36,6 @@ dependencies: - { role: evolix/lxc-php, lxc_php_version: php56, lxc_php_create_mysql_link: True, when: "'php56' in packweb_multiphp_versions" } - { role: evolix/lxc-php, lxc_php_version: php70, lxc_php_create_mysql_link: True, when: "'php70' in packweb_multiphp_versions" } - { role: evolix/lxc-php, lxc_php_version: php73, lxc_php_create_mysql_link: True, when: "'php73' in packweb_multiphp_versions" } + - { role: evolix/lxc-php, lxc_php_version: php74, lxc_php_create_mysql_link: True, when: "'php74' in packweb_multiphp_versions" } - { role: evolix/webapps/evoadmin-web, evoadmin_enable_vhost: "{{ packweb_enable_evoadmin_vhost }}", evoadmin_multiphp_versions: "{{ packweb_multiphp_versions }}" } - { role: evolix/evoacme } diff --git a/packweb-apache/tasks/apache.yml b/packweb-apache/tasks/apache.yml index 61d37341..57b360ce 100644 --- a/packweb-apache/tasks/apache.yml +++ b/packweb-apache/tasks/apache.yml @@ -28,7 +28,7 @@ apache2_module: name: '{{ item }}' state: present - with_items: + loop: - ssl - include - negotiation @@ -56,6 +56,6 @@ command: "a2enconf {{ item }}" register: command_result changed_when: "'Enabling' in command_result.stderr" - with_items: + loop: - evolinux-evasive - evolinux-modsec diff --git a/packweb-apache/tasks/fhs_retrictions.yml b/packweb-apache/tasks/fhs_retrictions.yml index 1d370038..7fa41478 100644 --- a/packweb-apache/tasks/fhs_retrictions.yml +++ b/packweb-apache/tasks/fhs_retrictions.yml @@ -5,7 +5,7 @@ register: command_result changed_when: "'changed' in command_result.stdout" failed_when: False - with_items: + loop: - / - /etc - /usr @@ -29,7 +29,7 @@ register: command_result changed_when: "'changed' in command_result.stdout" failed_when: False - with_items: + loop: - /var/log/apt - /var/lib/dpkg - /var/log/munin @@ -51,7 +51,7 @@ register: command_result changed_when: "'changed' in command_result.stdout" failed_when: False - with_items: + loop: - /bin/ping - /bin/ping6 - /usr/bin/fping @@ -63,6 +63,6 @@ register: command_result changed_when: "'changed' in command_result.stdout" failed_when: False - with_items: + loop: - /var/log/evolix.log - /etc/warnquota.conf diff --git a/packweb-apache/tasks/main.yml b/packweb-apache/tasks/main.yml index 922dcea8..5e2f9e92 100644 --- a/packweb-apache/tasks/main.yml +++ b/packweb-apache/tasks/main.yml @@ -41,7 +41,7 @@ path: "/etc/skel/{{ item.path }}" state: "{{ item.state }}" mode: "{{ item.mode }}" - with_items: + loop: - { path: log, mode: "0750", state: directory } - { path: awstats, mode: "0750", state: directory } - { path: www, mode: "0750", state: directory } @@ -50,7 +50,7 @@ command: "touch /etc/skel/log/{{ item }}" args: creates: "/etc/skel/log/{{ item }}" - with_items: + loop: - access.log - error.log @@ -58,7 +58,7 @@ file: dest: "/etc/skel/log/{{ item }}" mode: "0644" - with_items: + loop: - access.log - error.log @@ -85,12 +85,11 @@ - include: apache.yml - include: phpmyadmin.yml - when: ansible_distribution_release != "buster" - include: awstats.yml - include: fhs_retrictions.yml - when: packweb_fhs_retrictions + when: packweb_fhs_retrictions | bool - name: Periodically cache ftp directory sizes for ftpadmin.sh cron: diff --git a/packweb-apache/tasks/phpmyadmin.yml b/packweb-apache/tasks/phpmyadmin.yml index fc3e6d32..f83b0a5d 100644 --- a/packweb-apache/tasks/phpmyadmin.yml +++ b/packweb-apache/tasks/phpmyadmin.yml @@ -4,20 +4,25 @@ apt: name: apg -- name: Install phpmyadmin (Debian <=9) +# On Debian 10, we need to install the package from buster-backports +- name: Enable backports (Debian 10) + include_role: + name: evolix/apt + tasks_from: backports.yml + when: ansible_distribution_major_version is version('10', '=') + +- name: Prefer phpMyAdmin package from backports (Debian 10) + template: + src: phpmyadmin_apt_preferences.j2 + dest: /etc/apt/preferences.d/999-phpmyadmin + force: yes + mode: "0644" + when: ansible_distribution_major_version is version('10', '=') + +- name: Install phpmyadmin apt: name: phpmyadmin - when: ansible_distribution_major_version is version('9', '<=') - -- include_role: - name: evolix/remount-usr - -# /!\ Warning: this is a temporary hack as phpmyadmin for Buster is not yet -# available -- name: Install phpmyadmin using sid package (Debian >=10) - apt: - deb: http://mirror.evolix.org/debian/pool/main/p/phpmyadmin/phpmyadmin_4.6.6-4_all.deb - when: ansible_distribution_major_version is version('10', '>=') + update_cache: yes - name: Check if phpmyadmin default configuration is present stat: @@ -48,7 +53,7 @@ # The last character "\u000A" is a line feed (LF), it's better to keep it content: "{{ packweb_phpmyadmin_suffix }}\u000A" force: yes - when: packweb_phpmyadmin_suffix != "" + when: packweb_phpmyadmin_suffix | length > 0 - name: generate random string for phpmyadmin suffix shell: "apg -a 1 -M N -n 1 > {{ packweb_phpmyadmin_suffix_file }}" diff --git a/packweb-apache/templates/phpmyadmin_apt_preferences.j2 b/packweb-apache/templates/phpmyadmin_apt_preferences.j2 new file mode 100644 index 00000000..02578c0d --- /dev/null +++ b/packweb-apache/templates/phpmyadmin_apt_preferences.j2 @@ -0,0 +1,3 @@ +Package: phpmyadmin php-twig +Pin: release a=buster-backports +Pin-Priority: 999 \ No newline at end of file diff --git a/percona/tasks/main.yml b/percona/tasks/main.yml index f0591b0e..b14c4876 100644 --- a/percona/tasks/main.yml +++ b/percona/tasks/main.yml @@ -3,12 +3,26 @@ - set_fact: percona__apt_config_package_file: "percona-release_latest.{{ ansible_distribution_release }}_all.deb" -- name: Add Percona's official GPG key +- name: Percona embedded GPG key is absent apt_key: - data: "{{ lookup('file', 'percona.asc') }}" + id: "8507EFA5" + keyring: /etc/apt/trusted.gpg + state: absent + +- name: Add Percona GPG key + copy: + src: percona.asc + dest: /etc/apt/trusted.gpg.d/percona.asc + force: yes + mode: "0644" + owner: root + group: root - name: Check if percona-release is installed - command: "dpkg -l percona-release" + shell: "set -o pipefail && dpkg -l percona-release 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False register: percona__apt_config_package_installed @@ -17,7 +31,7 @@ copy: src: "{{ percona__apt_config_package_file }}" dest: "/root/{{ percona__apt_config_package_file }}" - when: not percona__apt_config_package_installed + when: not (percona__apt_config_package_installed | bool) # - include_role: # name: evolix/remount-usr @@ -27,14 +41,14 @@ deb: "/root/{{ percona__apt_config_package_file }}" state: present register: percona__apt_config_deb - when: not percona__apt_config_package_installed + when: not (percona__apt_config_package_installed | bool) - name: Percona APT config package is installed from repository apt: name: percona-release state: latest register: percona__apt_config_deb - when: percona__apt_config_package_installed + when: percona__apt_config_package_installed | bool - name: APT cache is up-to-date apt: @@ -42,4 +56,4 @@ when: percona__apt_config_deb is changed - include: xtrabackup.yml - when: percona__install_xtrabackup + when: percona__install_xtrabackup | bool diff --git a/percona/tasks/xtrabackup.yml b/percona/tasks/xtrabackup.yml index 2cf221bb..7d4e29d1 100644 --- a/percona/tasks/xtrabackup.yml +++ b/percona/tasks/xtrabackup.yml @@ -2,7 +2,7 @@ - name: Percona Tools is enabled command: percona-release enable tools release - # changed_when: + # changed_when: # register: percona__release_enable_tools - name: APT cache is up-to-date diff --git a/php/files/sury.gpg b/php/files/sury.gpg new file mode 100644 index 00000000..384771a0 Binary files /dev/null and b/php/files/sury.gpg differ diff --git a/php/meta/main.yml b/php/meta/main.yml index 7f5ff289..3d9f77c3 100644 --- a/php/meta/main.yml +++ b/php/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of php-fpm. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/php/tasks/config_apache.yml b/php/tasks/config_apache.yml index 1ce74733..795678fd 100644 --- a/php/tasks/config_apache.yml +++ b/php/tasks/config_apache.yml @@ -8,7 +8,7 @@ value: "{{ item.value }}" mode: "0644" create: yes - with_items: + loop: - { option: "short_open_tag", value: "Off" } - { option: "expose_php", value: "Off" } - { option: "display_errors", value: "Off" } @@ -42,6 +42,6 @@ option: "{{ item.option }}" value: "{{ item.value }}" mode: "0644" - with_items: + loop: - { option: "date.timezone", value: "Europe/Paris" } - when: php_symfony_requirements + when: php_symfony_requirements | bool diff --git a/php/tasks/config_cli.yml b/php/tasks/config_cli.yml index 23ed695c..d327690a 100644 --- a/php/tasks/config_cli.yml +++ b/php/tasks/config_cli.yml @@ -7,7 +7,7 @@ value: "{{ item.value }}" mode: "0644" create: yes - with_items: + loop: - { option: "display_errors", value: "On" } - { option: "allow_url_fopen", value: "On" } - { option: "disable_functions", value: "" } @@ -33,6 +33,6 @@ option: "{{ item.option }}" value: "{{ item.value }}" mode: "0644" - with_items: + loop: - { option: "date.timezone", value: "Europe/Paris" } - when: php_symfony_requirements + when: php_symfony_requirements | bool diff --git a/php/tasks/config_fpm.yml b/php/tasks/config_fpm.yml index 1644fd6a..ad543f19 100644 --- a/php/tasks/config_fpm.yml +++ b/php/tasks/config_fpm.yml @@ -8,7 +8,7 @@ value: "{{ item.value }}" mode: "0644" create: yes - with_items: + loop: - { option: "short_open_tag", value: "Off" } - { option: "expose_php", value: "Off" } - { option: "display_errors", value: "Off" } @@ -43,7 +43,7 @@ value: "{{ item.value }}" mode: "0644" create: yes - with_items: + loop: - { option: "user", value: "www-data" } - { option: "group", value: "www-data" } - { option: "listen", value: "{{ php_fpm_default_pool_socket }}" } @@ -76,14 +76,14 @@ option: "{{ item.option }}" value: "{{ item.value }}" mode: "0644" - with_items: + loop: - { option: "date.timezone", value: "Europe/Paris" } notify: "restart {{ php_fpm_service_name }}" - when: php_symfony_requirements + when: php_symfony_requirements | bool - name: Delete debian default pool file: - path: "{{ php_fpm_debian_default_pool_file }}" + path: "{{ php_fpm_debian_default_pool_file | mandatory }}" state: absent notify: "restart {{ php_fpm_service_name }}" - when: php_fpm_remove_default_pool + when: php_fpm_remove_default_pool | bool diff --git a/php/tasks/main.yml b/php/tasks/main.yml index 2fd1a250..e9687e67 100644 --- a/php/tasks/main.yml +++ b/php/tasks/main.yml @@ -2,8 +2,7 @@ - fail: msg: only compatible with Debian >= 8 - when: - - ansible_distribution != "Debian" or ansible_distribution_major_version is version('8', '<') + when: ansible_distribution != "Debian" or ansible_distribution_major_version is version('8', '<') - include: main_jessie.yml when: ansible_distribution_release == "jessie" diff --git a/php/tasks/main_buster.yml b/php/tasks/main_buster.yml index 16eed389..fba952ab 100644 --- a/php/tasks/main_buster.yml +++ b/php/tasks/main_buster.yml @@ -36,7 +36,7 @@ - libphp-phpmailer - include: sury_pre.yml - when: php_sury_enable + when: php_sury_enable | bool - name: "Install PHP packages (Debian 9 or later)" apt: @@ -49,7 +49,7 @@ - libapache2-mod-php - php state: present - when: php_apache_enable + when: php_apache_enable | bool - name: "Install PHP FPM packages (Debian 9 or later)" apt: @@ -57,7 +57,7 @@ - php-fpm - php state: present - when: php_fpm_enable + when: php_fpm_enable | bool # Configuration @@ -65,7 +65,7 @@ file: dest: "{{ item }}" mode: "0755" - with_items: + loop: - /etc/php - /etc/php/7.3 @@ -76,22 +76,22 @@ mode: "0755" - include: config_fpm.yml - when: php_fpm_enable + when: php_fpm_enable | bool - name: Enforce permissions on PHP fpm directory file: dest: /etc/php/7.3/fpm mode: "0755" - when: php_fpm_enable + when: php_fpm_enable | bool - include: config_apache.yml - when: php_apache_enable + when: php_apache_enable | bool - name: Enforce permissions on PHP apache2 directory file: dest: /etc/php/7.3/apache2 mode: "0755" - when: php_apache_enable + when: php_apache_enable | bool - include: sury_post.yml - when: php_sury_enable + when: php_sury_enable | bool diff --git a/php/tasks/main_jessie.yml b/php/tasks/main_jessie.yml index 8e99280c..5ec3123d 100644 --- a/php/tasks/main_jessie.yml +++ b/php/tasks/main_jessie.yml @@ -40,7 +40,7 @@ - libapache2-mod-php5 - php5 state: present - when: php_apache_enable + when: php_apache_enable | bool - name: "Install PHP FPM packages (jessie)" apt: @@ -48,7 +48,7 @@ - php5-fpm - php5 state: present - when: php_fpm_enable + when: php_fpm_enable | bool # Configuration @@ -65,19 +65,19 @@ mode: "0755" - include: config_fpm.yml - when: php_fpm_enable + when: php_fpm_enable | bool - name: Enforce permissions on PHP fpm directory file: dest: /etc/php5/fpm mode: "0755" - when: php_fpm_enable + when: php_fpm_enable | bool - include: config_apache.yml - when: php_apache_enable + when: php_apache_enable | bool - name: Enforce permissions on PHP apache2 directory file: dest: /etc/php5/apache2 mode: "0755" - when: php_apache_enable + when: php_apache_enable | bool diff --git a/php/tasks/main_stretch.yml b/php/tasks/main_stretch.yml index 136fa346..dc16c6e4 100644 --- a/php/tasks/main_stretch.yml +++ b/php/tasks/main_stretch.yml @@ -36,7 +36,7 @@ - libphp-phpmailer - include: sury_pre.yml - when: php_sury_enable + when: php_sury_enable | bool - name: "Install PHP packages (Debian 9 or later)" apt: @@ -49,7 +49,7 @@ - libapache2-mod-php - php state: present - when: php_apache_enable + when: php_apache_enable | bool - name: "Install PHP FPM packages (Debian 9 or later)" apt: @@ -57,7 +57,7 @@ - php-fpm - php state: present - when: php_fpm_enable + when: php_fpm_enable | bool # Configuration @@ -65,7 +65,7 @@ file: dest: "{{ item }}" mode: "0755" - with_items: + loop: - /etc/php - /etc/php/7.0 @@ -77,22 +77,22 @@ mode: "0755" - include: config_fpm.yml - when: php_fpm_enable + when: php_fpm_enable | bool - name: Enforce permissions on PHP fpm directory file: dest: /etc/php/7.0/fpm mode: "0755" - when: php_fpm_enable + when: php_fpm_enable | bool - include: config_apache.yml - when: php_apache_enable + when: php_apache_enable | bool - name: Enforce permissions on PHP apache2 directory file: dest: /etc/php/7.0/apache2 mode: "0755" - when: php_apache_enable + when: php_apache_enable | bool - include: sury_post.yml - when: php_sury_enable + when: php_sury_enable | bool diff --git a/php/tasks/sury_post.yml b/php/tasks/sury_post.yml index ecfb13dc..4e706889 100644 --- a/php/tasks/sury_post.yml +++ b/php/tasks/sury_post.yml @@ -6,7 +6,7 @@ dest: "{{ item.dest }}" force: yes state: link - with_items: + loop: - { src: "{{ php_cli_defaults_ini_file }}", dest: "/etc/php/7.4/cli/conf.d/z-evolinux-defaults.ini" } - { src: "{{ php_cli_custom_ini_file }}", dest: "/etc/php/7.4/cli/conf.d/zzz-evolinux-custom.ini" } @@ -21,16 +21,16 @@ dest: "{{ item.dest }}" force: yes state: link - with_items: + loop: - { src: "{{ php_apache_defaults_ini_file }}", dest: "/etc/php/7.4/apache2/conf.d/z-evolinux-defaults.ini" } - { src: "{{ php_apache_custom_ini_file }}", dest: "/etc/php/7.4/apache2/conf.d/zzz-evolinux-custom.ini" } - when: php_apache_enable + when: php_apache_enable | bool - name: Enforce permissions on PHP 7.4/cli directory file: dest: /etc/php/7.4/apache2 mode: "0755" - when: php_apache_enable + when: php_apache_enable | bool - name: Symlink Evolix FPM config files from 7.4 to 7.0 file: @@ -38,15 +38,15 @@ dest: "{{ item.dest }}" force: yes state: link - with_items: + loop: - { src: "{{ php_fpm_defaults_ini_file }}", dest: "/etc/php/7.4/fpm/conf.d/z-evolinux-defaults.ini" } - { src: "{{ php_fpm_custom_ini_file }}", dest: "/etc/php/7.4/fpm/conf.d/zzz-evolinux-custom.ini" } - { src: "{{ php_fpm_defaults_conf_file }}", dest: "/etc/php/7.4/fpm/pool.d/z-evolinux-defaults.conf" } - { src: "{{ php_fpm_custom_conf_file }}", dest: "/etc/php/7.4/fpm/pool.d/zzz-evolinux-custom.conf" } - when: php_fpm_enable + when: php_fpm_enable | bool - name: Enforce permissions on PHP 7.4/cli directory file: dest: /etc/php/7.4/fpm mode: "0755" - when: php_fpm_enable + when: php_fpm_enable | bool diff --git a/php/tasks/sury_pre.yml b/php/tasks/sury_pre.yml index 45d5d005..c421fe04 100644 --- a/php/tasks/sury_pre.yml +++ b/php/tasks/sury_pre.yml @@ -1,10 +1,12 @@ --- - name: Setup deb.sury.org repository - Add GPG key - get_url: - url: https://packages.sury.org/php/apt.gpg + copy: + src: sury.gpg dest: /etc/apt/trusted.gpg.d/sury.gpg mode: "0644" + owner: root + group: root - name: Setup deb.sury.org repository - Install apt-transport-https apt: diff --git a/postfix/meta/main.yml b/postfix/meta/main.yml index fe59228a..188769a2 100644 --- a/postfix/meta/main.yml +++ b/postfix/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Postfix. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: - { role: evolix/ldap, ldap_schema: 'cn4evolix.ldif', when: postfix_packmail == True } diff --git a/postfix/tasks/common.yml b/postfix/tasks/common.yml index 08ee6a56..bcd5ed79 100644 --- a/postfix/tasks/common.yml +++ b/postfix/tasks/common.yml @@ -14,7 +14,7 @@ line: '{{ item }}' state: present create: no - with_items: + loop: - "postfix/sa-blacklist.access" - "postfix/*.db" tags: diff --git a/postfix/tasks/main.yml b/postfix/tasks/main.yml index 0e0fff2d..d8caf2b2 100644 --- a/postfix/tasks/main.yml +++ b/postfix/tasks/main.yml @@ -3,10 +3,10 @@ - include: common.yml - include: minimal.yml - when: postfix_packmail == False + when: not (postfix_packmail | bool) - include: packmail.yml - when: postfix_packmail == True + when: postfix_packmail | bool - include: slow_transport.yml - when: postfix_slow_transport_include + when: postfix_slow_transport_include | bool diff --git a/postfix/tasks/minimal.yml b/postfix/tasks/minimal.yml index ad666532..970b9dcb 100644 --- a/postfix/tasks/minimal.yml +++ b/postfix/tasks/minimal.yml @@ -15,6 +15,6 @@ mode: "0644" force: yes notify: restart postfix - when: postfix_force_main_cf or postfix_maincf_md5_jessie in default_main_cf.stdout or postfix_maincf_md5_stretch in default_main_cf.stdout + when: (postfix_force_main_cf | bool) or (postfix_maincf_md5_jessie in default_main_cf.stdout) or (postfix_maincf_md5_stretch in default_main_cf.stdout) tags: - postfix diff --git a/postfix/tasks/packmail.yml b/postfix/tasks/packmail.yml index f6900639..80f90232 100644 --- a/postfix/tasks/packmail.yml +++ b/postfix/tasks/packmail.yml @@ -19,7 +19,7 @@ mode: "0644" force: yes notify: restart postfix - when: postfix_force_main_cf or postfix_maincf_md5_jessie in default_main_cf.stdout or postfix_maincf_md5_stretch in default_main_cf.stdout + when: (postfix_force_main_cf | bool) or (postfix_maincf_md5_jessie in default_main_cf.stdout) or (postfix_maincf_md5_stretch in default_main_cf.stdout) tags: - postfix @@ -37,7 +37,7 @@ src: filter dest: "/etc/postfix/{{ item }}" force: no - with_items: + loop: - virtual - client.access - client.access_local @@ -55,7 +55,7 @@ - name: postmap filter files command: "postmap /etc/postfix/{{ item }}" - with_items: + loop: - virtual - client.access - client.access_local @@ -67,7 +67,7 @@ - sender.access - sender.access_local - spamd.cidr - when: postfix_copy_filter.changed + when: postfix_copy_filter is changed tags: - postfix @@ -76,7 +76,7 @@ src: "{{ item }}.j2" dest: "/etc/postfix/{{ item }}" mode: "0644" - with_items: + loop: - virtual_aliases.cf - virtual_domains.cf - virtual_mailboxes.cf @@ -98,7 +98,10 @@ - postfix - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False register: is_cron_installed diff --git a/postfix/tasks/slow_transport.yml b/postfix/tasks/slow_transport.yml index 2f4cab1e..2f1867ae 100644 --- a/postfix/tasks/slow_transport.yml +++ b/postfix/tasks/slow_transport.yml @@ -13,7 +13,7 @@ dest: /etc/postfix/transport line: "{{ item }}" create: yes - with_items: + loop: - "orange.fr slow:" - "wanadoo.fr slow:" - "voila.fr slow:" diff --git a/postgresql/files/ACCC4CF8.asc b/postgresql/files/postgresql.asc similarity index 100% rename from postgresql/files/ACCC4CF8.asc rename to postgresql/files/postgresql.asc diff --git a/postgresql/meta/main.yml b/postgresql/meta/main.yml index 53ee0fcb..ccdc1dda 100644 --- a/postgresql/meta/main.yml +++ b/postgresql/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of PostgreSQL issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/postgresql/tasks/locales.yml b/postgresql/tasks/locales.yml index 89687a7c..8cf70989 100644 --- a/postgresql/tasks/locales.yml +++ b/postgresql/tasks/locales.yml @@ -6,7 +6,7 @@ locale_gen: name: "{{ item }}" state: present - with_items: + loop: - "fr_FR.UTF-8" become: yes notify: reconfigure locales diff --git a/postgresql/tasks/main.yml b/postgresql/tasks/main.yml index 292849a0..fbe22989 100644 --- a/postgresql/tasks/main.yml +++ b/postgresql/tasks/main.yml @@ -8,7 +8,10 @@ when: ansible_distribution_major_version is version('9', '=') - include: packages_buster.yml - when: ansible_distribution_major_version is version('10', '>=') + when: ansible_distribution_major_version is version('10', '=') + +- include: packages_bullseye.yml + when: ansible_distribution_major_version is version('11', '>=') - include: config.yml @@ -19,4 +22,4 @@ - include: logrotate.yml - include: postgis.yml - when: postgresql_install_postgis + when: postgresql_install_postgis | bool diff --git a/postgresql/tasks/munin.yml b/postgresql/tasks/munin.yml index e576b4cd..4e62ddf6 100644 --- a/postgresql/tasks/munin.yml +++ b/postgresql/tasks/munin.yml @@ -14,7 +14,7 @@ state: link src: '/usr/share/munin/plugins/{{item}}' dest: '/etc/munin/plugins/{{item}}' - with_items: + loop: - postgres_bgwriter - postgres_checkpoints - postgres_connections_db @@ -28,8 +28,9 @@ state: link src: '/usr/share/munin/plugins/{{item[0]}}' dest: '/etc/munin/plugins/{{item[0]}}{{item[1]}}' - with_nested: - - ['postgres_cache_', 'postgres_connections_', 'postgres_locks_', 'postgres_querylength_', 'postgres_scans_', 'postgres_size_', 'postgres_transactions_', 'postgres_tuples_'] - - '{{postgresql_databases}}' + loop: "{{ _plugins | product(_databases) | list }}" + vars: + _plugins: ['postgres_cache_', 'postgres_connections_', 'postgres_locks_', 'postgres_querylength_', 'postgres_scans_', 'postgres_size_', 'postgres_transactions_', 'postgres_tuples_'] + _databases: postgresql_databases notify: restart munin-node when: etc_munin_plugins.stat.exists and usr_share_munin_plugins.stat.exists diff --git a/postgresql/tasks/nrpe.yml b/postgresql/tasks/nrpe.yml index 8ce178e9..740c7b08 100644 --- a/postgresql/tasks/nrpe.yml +++ b/postgresql/tasks/nrpe.yml @@ -37,5 +37,5 @@ regexp: '^command\[check_pgsql\]=' line: 'command[check_pgsql]=/usr/lib/nagios/plugins/check_pgsql -H localhost -l nrpe -p "{{postgresql_nrpe_password.stdout}}"' notify: restart nagios-nrpe-server - when: postgresql_create_nrpe_user.changed + when: postgresql_create_nrpe_user is changed when: nrpe_evolix_config.stat.exists diff --git a/postgresql/tasks/packages_bullseye.yml b/postgresql/tasks/packages_bullseye.yml new file mode 100644 index 00000000..558578f2 --- /dev/null +++ b/postgresql/tasks/packages_bullseye.yml @@ -0,0 +1,16 @@ +--- + +- name: "Set variables (Debian 11)" + set_fact: + postgresql_version: '13' + when: postgresql_version is none or postgresql_version | length == 0 + +- include: pgdg-repo.yml + when: postgresql_version != '13' + +- name: Install postgresql package + apt: + name: + - postgresql + - pgtop + - libdbd-pg-perl diff --git a/postgresql/tasks/packages_buster.yml b/postgresql/tasks/packages_buster.yml index 3a1a440e..76017545 100644 --- a/postgresql/tasks/packages_buster.yml +++ b/postgresql/tasks/packages_buster.yml @@ -3,7 +3,7 @@ - name: "Set variables (Debian 10)" set_fact: postgresql_version: '11' - when: postgresql_version == "" + when: postgresql_version is none or postgresql_version | length == 0 - include: pgdg-repo.yml when: postgresql_version != '11' diff --git a/postgresql/tasks/packages_jessie.yml b/postgresql/tasks/packages_jessie.yml index 3e21bc0e..cf8f0879 100644 --- a/postgresql/tasks/packages_jessie.yml +++ b/postgresql/tasks/packages_jessie.yml @@ -3,7 +3,7 @@ - name: "Set variables (Debian 8)" set_fact: postgresql_version: '9.4' - when: postgresql_version == "" + when: postgresql_version is none or postgresql_version | length == 0 - include: pgdg-repo.yml when: postgresql_version != '9.4' @@ -11,7 +11,7 @@ - name: Install postgresql package apt: name: '{{item}}' - with_items: + loop: - "postgresql-{{postgresql_version}}" - ptop - libdbd-pg-perl diff --git a/postgresql/tasks/packages_stretch.yml b/postgresql/tasks/packages_stretch.yml index eff513f9..d8ebb9e4 100644 --- a/postgresql/tasks/packages_stretch.yml +++ b/postgresql/tasks/packages_stretch.yml @@ -3,7 +3,7 @@ - name: "Set variables (Debian 9)" set_fact: postgresql_version: '9.6' - when: postgresql_version == "" + when: postgresql_version is none or postgresql_version | length == 0 - include: pgdg-repo.yml when: postgresql_version != '9.6' diff --git a/postgresql/tasks/pgdg-repo.yml b/postgresql/tasks/pgdg-repo.yml index 8d937b82..429e33cc 100644 --- a/postgresql/tasks/pgdg-repo.yml +++ b/postgresql/tasks/pgdg-repo.yml @@ -13,10 +13,20 @@ repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main" update_cache: yes -- name: Add GPG key for PGDG repository +- name: PGDG embedded GPG key is absent apt_key: - #url: http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc - data: "{{ lookup('file', 'ACCC4CF8.asc') }}" + id: "ACCC4CF8" + keyring: /etc/apt/trusted.gpg + state: absent + +- name: Add PGDG GPG key + copy: + src: postgresql.asc + dest: /etc/apt/trusted.gpg.d/postgresql.asc + force: yes + mode: "0644" + owner: root + group: root - name: Update and upgrade apt packages for PGDG repository apt: diff --git a/postgresql/tasks/postgis.yml b/postgresql/tasks/postgis.yml index 0c18cb51..f2300943 100644 --- a/postgresql/tasks/postgis.yml +++ b/postgresql/tasks/postgis.yml @@ -1,5 +1,5 @@ --- -- name: Install PostGIS extention +- name: Install PostGIS extention apt: name: - postgis diff --git a/postgresql/tests/test.yml b/postgresql/tests/test.yml index d8386b29..438eddee 100644 --- a/postgresql/tests/test.yml +++ b/postgresql/tests/test.yml @@ -15,7 +15,7 @@ create: yes state: present changed_when: false - with_items: + loop: - "en_US.UTF-8 UTF-8" - "fr_FR ISO-8859-1" - "fr_FR.UTF-8 UTF-8" @@ -24,7 +24,7 @@ - name: Reconfigure locales command: /usr/sbin/locale-gen changed_when: false - when: test_locales.changed + when: test_locales is changed roles: - role: postgresql diff --git a/proftpd/meta/main.yml b/proftpd/meta/main.yml index 1632f33a..60fb0fa9 100644 --- a/proftpd/meta/main.yml +++ b/proftpd/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of ProFTPd issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/proftpd/tasks/accounts.yml b/proftpd/tasks/accounts.yml index 95098df2..756e0ff0 100644 --- a/proftpd/tasks/accounts.yml +++ b/proftpd/tasks/accounts.yml @@ -1,14 +1,14 @@ --- - include: accounts_password.yml when: item.password is undefined - with_items: "{{ proftpd_accounts }}" + loop: "{{ proftpd_accounts }}" tags: - proftpd - set_fact: proftpd_accounts_final: "{{ proftpd_accounts_final + [ item ] }}" when: item.password is defined - with_items: "{{ proftpd_accounts }}" + loop: "{{ proftpd_accounts }}" tags: - proftpd @@ -20,7 +20,7 @@ mode: "0440" line: "{{ item.name | mandatory }}:{{ item.password }}:{{ item.uid }}:{{ item.gid }}::{{ item.home | mandatory }}:/bin/false" regexp: "^{{ item.name }}:.*" - with_items: "{{ proftpd_accounts_final }}" + loop: "{{ proftpd_accounts_final }}" notify: restart proftpd tags: - proftpd @@ -31,9 +31,9 @@ state: present line: "\tAllowUser {{ item.name }}" insertbefore: "DenyAll" - with_items: "{{ proftpd_accounts_final }}" + loop: "{{ proftpd_accounts_final }}" notify: restart proftpd - when: proftpd_ftp_enable + when: proftpd_ftp_enable | bool tags: - proftpd @@ -43,9 +43,9 @@ state: present line: "\tAllowUser {{ item.name }}" insertbefore: "DenyAll" - with_items: "{{ proftpd_accounts_final }}" + loop: "{{ proftpd_accounts_final }}" notify: restart proftpd - when: proftpd_ftps_enable + when: proftpd_ftps_enable | bool tags: - proftpd @@ -55,8 +55,8 @@ state: present line: "\tAllowUser {{ item.name }}" insertbefore: "DenyAll" - with_items: "{{ proftpd_accounts_final }}" + loop: "{{ proftpd_accounts_final }}" notify: restart proftpd - when: proftpd_sftp_enable + when: proftpd_sftp_enable | bool tags: - proftpd diff --git a/proftpd/tasks/main.yml b/proftpd/tasks/main.yml index 71b95e9b..457887a1 100644 --- a/proftpd/tasks/main.yml +++ b/proftpd/tasks/main.yml @@ -22,7 +22,7 @@ mode: "0644" force: no notify: restart proftpd - when: proftpd_ftp_enable + when: proftpd_ftp_enable | bool tags: - proftpd @@ -33,7 +33,7 @@ mode: "0644" force: no notify: restart proftpd - when: proftpd_ftps_enable + when: proftpd_ftps_enable | bool tags: - proftpd @@ -44,7 +44,7 @@ mode: "0644" force: no notify: restart proftpd - when: proftpd_sftp_enable + when: proftpd_sftp_enable | bool tags: - proftpd @@ -80,4 +80,4 @@ - proftpd - include: accounts.yml - when: proftpd_accounts != "[]" + when: proftpd_accounts | length > 0 diff --git a/rabbitmq/meta/main.yml b/rabbitmq/meta/main.yml index a5c7d425..1fd89e27 100644 --- a/rabbitmq/meta/main.yml +++ b/rabbitmq/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of RabbitMq issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - buster + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/rbenv/meta/main.yml b/rbenv/meta/main.yml index 5da4ee43..41113441 100644 --- a/rbenv/meta/main.yml +++ b/rbenv/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of Rbenv, Ruby and some default gems. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/rbenv/tasks/main.yml b/rbenv/tasks/main.yml index 28f25481..08f8242e 100644 --- a/rbenv/tasks/main.yml +++ b/rbenv/tasks/main.yml @@ -46,7 +46,7 @@ owner: '{{ username }}' group: '{{ username }}' create: yes - with_items: '{{ rbenv_default_gems }}' + loop: '{{ rbenv_default_gems }}' become_user: "{{ username }}" become: yes tags: @@ -68,7 +68,7 @@ version: '{{ item.version }}' accept_hostkey: yes force: yes - with_items: + loop: - "{{ rbenv_plugins }}" become_user: "{{ username }}" become: yes diff --git a/redis/meta/main.yml b/redis/meta/main.yml index 339e926c..f465a547 100644 --- a/redis/meta/main.yml +++ b/redis/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Redis. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/redis/tasks/default-munin.yml b/redis/tasks/default-munin.yml index b7edce3a..3f0fe6f4 100644 --- a/redis/tasks/default-munin.yml +++ b/redis/tasks/default-munin.yml @@ -41,7 +41,7 @@ src: /usr/local/share/munin/plugins/redis_ dest: "/etc/munin/plugins/redis_{{item}}" state: link - with_items: + loop: - connected_clients - key_ratio - keys_per_sec @@ -67,8 +67,8 @@ value: '{{ redis_password }}' notify: restart munin-node when: - - redis_password != '' - - redis_password != None + - redis_password is not none + - redis_password | length > 0 - (munin_redis_blocs_in_config.stdout | int) <= 1 tags: redis @@ -77,6 +77,6 @@ debug: msg: "WARNING - It seems you have multiple redis sections in your munin-node configuration - Munin config NOT changed" when: - - redis_password != '' - - redis_password != None + - redis_password is not none + - redis_password | length > 0 - (munin_redis_blocs_in_config.stdout | int) > 1 diff --git a/redis/tasks/instance-munin.yml b/redis/tasks/instance-munin.yml index 8d0e207c..80c67c6f 100644 --- a/redis/tasks/instance-munin.yml +++ b/redis/tasks/instance-munin.yml @@ -41,7 +41,7 @@ src: /usr/local/share/munin/plugins/redis_ dest: "/etc/munin/plugins/{{ redis_instance_name }}_redis_{{item}}" state: link - with_items: + loop: - connected_clients - key_ratio - keys_per_sec diff --git a/redis/tasks/instance-server.yml b/redis/tasks/instance-server.yml index 1b491d9a..08430eb8 100644 --- a/redis/tasks/instance-server.yml +++ b/redis/tasks/instance-server.yml @@ -3,9 +3,9 @@ - name: Verify Redis port assert: that: - - redis_port != 6379 + - redis_port | int != 6379 msg: "If you want to use port 6379, use the default instance, not a named instance." - when: not redis_force_instance_port + when: not (redis_force_instance_port | bool) - name: "Instance '{{ redis_instance_name }}' group is present" group: @@ -44,7 +44,7 @@ group: "root" follow: yes state: directory - with_items: + loop: - "{{ redis_conf_dir }}/redis-server.pre-up.d" - "{{ redis_conf_dir }}/redis-server.post-up.d" - "{{ redis_conf_dir }}/redis-server.pre-down.d" @@ -59,7 +59,7 @@ command: "cp -a /etc/redis/{{ item }}/00_example {{ redis_conf_dir }}/{{ item }}" args: creates: "{{ redis_conf_dir }}/{{ item }}/00_example" - with_items: + loop: - "redis-server.pre-up.d" - "redis-server.post-up.d" - "redis-server.pre-down.d" @@ -78,7 +78,7 @@ group: "redis-{{ redis_instance_name }}" follow: yes state: directory - with_items: + loop: - "{{ redis_pid_dir }}" - "{{ redis_socket_dir }}" tags: @@ -92,7 +92,7 @@ group: "redis-{{ redis_instance_name }}" follow: yes state: directory - with_items: + loop: - "{{ redis_data_dir }}" - "{{ redis_log_dir }}" tags: @@ -162,6 +162,6 @@ name: "redis-server" enabled: no state: stopped - when: redis_default_server_disabled + when: redis_default_server_disabled | bool tags: - redis diff --git a/redis/tasks/main.yml b/redis/tasks/main.yml index 28fda65a..90f0aa12 100644 --- a/redis/tasks/main.yml +++ b/redis/tasks/main.yml @@ -1,7 +1,7 @@ --- - set_fact: - redis_restart_handler_name: "{{ redis_restart_if_needed | ternary('restart redis', 'restart redis (noop)') }}" + redis_restart_handler_name: "{{ redis_restart_if_needed | bool | ternary('restart redis', 'restart redis (noop)') }}" - name: Redis is installed. apt: @@ -20,7 +20,7 @@ tags: - redis - packages - when: redis_sentinel_install + when: redis_sentinel_install | bool - name: Get Redis version shell: "redis-server -v | grep -Eo '(v=\\S+)' | cut -d'=' -f 2 | grep -E '^([0-9]|\\.)+$'" @@ -137,4 +137,4 @@ - name: Force restart redis command: /bin/true notify: restart redis - when: redis_restart_force + when: redis_restart_force | bool diff --git a/redmine/tasks/config.yml b/redmine/tasks/config.yml index a08ba1c6..d65f8172 100644 --- a/redmine/tasks/config.yml +++ b/redmine/tasks/config.yml @@ -6,7 +6,7 @@ mode: "0750" owner: "{{ redmine_user }}" group: "{{ redmine_user }}" - with_items: + loop: - ".config" - ".config/systemd" - ".config/systemd/user" @@ -50,7 +50,7 @@ owner: "{{ redmine_user }}" group: "{{ redmine_user }}" mode: "0640" - with_items: + loop: - 'configuration.yml' - 'database.yml' - 'additional_environment.rb' diff --git a/redmine/tasks/mysql.yml b/redmine/tasks/mysql.yml index 414da319..6c40a338 100644 --- a/redmine/tasks/mysql.yml +++ b/redmine/tasks/mysql.yml @@ -13,7 +13,7 @@ register: redmine_generate_mysql_password check_mode: no changed_when: False - when: redmine_get_mysql_password.stdout == "" + when: redmine_get_mysql_password.stdout | length == 0 tags: - redmine @@ -42,7 +42,7 @@ section: client option: '{{ item.option }}' value: '{{ item.value }}' - with_items: + loop: - { option: 'host', value: "{{ redmine_db_host }}" } - { option: 'user', value: "{{ redmine_db_username }}" } - { option: 'database', value: "{{ redmine_db_name }}" } diff --git a/redmine/tasks/release.yml b/redmine/tasks/release.yml index 730b0877..548132fc 100644 --- a/redmine/tasks/release.yml +++ b/redmine/tasks/release.yml @@ -98,7 +98,7 @@ chdir: "/home/{{ redmine_user }}/www/" become_user: "{{ redmine_user }}" environment: "{{ user_env }}" - when: redmine_mysql_create.changed + when: redmine_mysql_create is changed tags: - redmine diff --git a/redmine/tasks/source.yml b/redmine/tasks/source.yml index 51427acf..7893a5ad 100644 --- a/redmine/tasks/source.yml +++ b/redmine/tasks/source.yml @@ -6,7 +6,7 @@ owner: "{{ redmine_user }}" group: "{{ redmine_user }}" mode: "0750" - with_items: + loop: - "releases" - "releases/{{ redmine_version }}" tags: @@ -30,7 +30,7 @@ dest: "/home/{{ redmine_user }}/releases/{{ redmine_version }}/config/{{ item }}" owner: "{{ redmine_user }}" group: "{{ redmine_user }}" - with_items: + loop: - 'configuration.yml' - 'database.yml' - 'additional_environment.rb' @@ -46,7 +46,7 @@ group: "{{ redmine_user }}" mode: "0750" when: item.zip is defined - with_items: "{{ redmine_plugins }}" + loop: "{{ redmine_plugins }}" tags: - redmine @@ -58,7 +58,7 @@ umask: "027" become_user: "{{ redmine_user }}" when: item.git is defined - with_items: "{{ redmine_plugins }}" + loop: "{{ redmine_plugins }}" tags: - redmine @@ -71,7 +71,7 @@ group: "{{ redmine_user }}" mode: "0750" when: item.zip is defined - with_items: "{{ redmine_themes }}" + loop: "{{ redmine_themes }}" tags: - redmine @@ -83,7 +83,7 @@ umask: "027" become_user: "{{ redmine_user }}" when: item.git is defined - with_items: "{{ redmine_themes }}" + loop: "{{ redmine_themes }}" tags: - redmine diff --git a/redmine/tasks/user.yml b/redmine/tasks/user.yml index ecc5b6d5..932e049c 100644 --- a/redmine/tasks/user.yml +++ b/redmine/tasks/user.yml @@ -33,7 +33,7 @@ owner: "{{ redmine_user }}" group: "{{ redmine_user }}" mode: "0750" - with_items: + loop: - "/home/{{ redmine_user }}" - "/home/{{ redmine_user }}/files" tags: diff --git a/spamassasin/tasks/main.yml b/spamassasin/tasks/main.yml index 53c6725b..a7568391 100644 --- a/spamassasin/tasks/main.yml +++ b/spamassasin/tasks/main.yml @@ -3,7 +3,6 @@ apt: name: - spamassassin - - evomaintenance state: present tags: - spamassassin @@ -47,6 +46,17 @@ tags: - spamassassin +- name: Check evomaintenance config + stat: + path: /etc/evomaintenance.cf + register: _evomaintenance_config + +- name: Verify sa-update dependency + assert: + that: + - _evomaintenance_config.stat.exists + msg: sa-update.sh needs /etc/evomaintenance.cf + - name: copy sa-update.sh script copy: src: sa-update.sh @@ -56,11 +66,14 @@ - spamassassin - name: Check if cron is installed - shell: "dpkg -l cron 2> /dev/null | grep -q -E '^(i|h)i'" + shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash + check_mode: no failed_when: False changed_when: False register: is_cron_installed - + - name: enable sa-update.sh cron lineinfile: dest: /etc/cron.d/sa-update diff --git a/squid/files/evolinux-whitelist-defaults.conf b/squid/files/evolinux-whitelist-defaults.conf index c0d691c0..83b5e827 100644 --- a/squid/files/evolinux-whitelist-defaults.conf +++ b/squid/files/evolinux-whitelist-defaults.conf @@ -11,6 +11,7 @@ ^pear\.php\.net$ ^repo\.mysql\.com$ ^deb\.nodesource\.com$ +^dl\.yarnpkg\.com$ # Let's Encrypt ^.*\.letsencrypt.org$ diff --git a/squid/meta/main.yml b/squid/meta/main.yml index 1c6287ea..ee20ff5f 100644 --- a/squid/meta/main.yml +++ b/squid/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installatin and configuration of Squid as an outgoing proxy. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/squid/tasks/main.yml b/squid/tasks/main.yml index 68f721f8..9e00dcb0 100644 --- a/squid/tasks/main.yml +++ b/squid/tasks/main.yml @@ -71,7 +71,9 @@ dest: /etc/squid/evolinux-acl.conf force: no notify: "reload squid" - when: squid_localproxy_enable and ansible_distribution_major_version is version('9', '>=') + when: + - squid_localproxy_enable | bool + - ansible_distribution_major_version is version('9', '>=') - name: "evolinux custom acl (Debian 9 or later)" copy: @@ -79,7 +81,9 @@ content: | # Put customized values here. force: no - when: squid_localproxy_enable == False and ansible_distribution_major_version is version('9', '>=') + when: + - not (squid_localproxy_enable | bool) + - ansible_distribution_major_version is version('9', '>=') - name: "evolinux http_access for local proxy (Debian 9 or later)" copy: @@ -87,7 +91,9 @@ dest: /etc/squid/evolinux-httpaccess.conf force: no notify: "reload squid" - when: squid_localproxy_enable and ansible_distribution_major_version is version('9', '>=') + when: + - squid_localproxy_enable | bool + - ansible_distribution_major_version is version('9', '>=') - name: "evolinux custom http_access (Debian 9 or later)" copy: @@ -95,7 +101,9 @@ content: | # Put customized values here. force: no - when: squid_localproxy_enable == False and ansible_distribution_major_version is version('9', '>=') + when: + - not (squid_localproxy_enable | bool) + - ansible_distribution_major_version is version('9', '>=') - name: "evolinux overrides for local proxy (Debian 9 or later)" template: @@ -103,7 +111,9 @@ dest: /etc/squid/evolinux-custom.conf force: no notify: "reload squid" - when: squid_localproxy_enable and ansible_distribution_major_version is version('9', '>=') + when: + - squid_localproxy_enable | bool + - ansible_distribution_major_version is version('9', '>=') - name: "evolinux custom overrides (Debian 9 or later)" copy: @@ -111,7 +121,9 @@ content: | # Put customized values here. force: no - when: squid_localproxy_enable == False and ansible_distribution_major_version is version('9', '>=') + when: + - not (squid_localproxy_enable | bool) + - ansible_distribution_major_version is version('9', '>=') - name: add some URL in whitelist (Debian 8) lineinfile: @@ -119,7 +131,7 @@ dest: /etc/squid3/whitelist.conf line: "{{ item }}" state: present - with_items: '{{ squid_whitelist_items }}' + loop: '{{ squid_whitelist_items }}' notify: "reload squid3" when: ansible_distribution_major_version == '8' @@ -129,7 +141,7 @@ dest: /etc/squid/evolinux-whitelist-custom.conf line: "{{ item }}" state: present - with_items: '{{ squid_whitelist_items }}' + loop: '{{ squid_whitelist_items }}' notify: "reload squid" when: ansible_distribution_major_version is version('9', '>=') diff --git a/squid/tasks/minifirewall.yml b/squid/tasks/minifirewall.yml index 44c7ada6..e878b0a8 100644 --- a/squid/tasks/minifirewall.yml +++ b/squid/tasks/minifirewall.yml @@ -27,7 +27,7 @@ regexp: "^#? *{{ item }}" line: "{{ item }}" insertafter: "^# Proxy" - with_items: + loop: - "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT" - "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d {{ squid_address }} -j ACCEPT" - "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.0/8 -j ACCEPT" diff --git a/squid/tasks/systemd.yml b/squid/tasks/systemd.yml index 4d06fa5d..82b8760c 100644 --- a/squid/tasks/systemd.yml +++ b/squid/tasks/systemd.yml @@ -6,7 +6,7 @@ failed_when: False check_mode: no register: _squid_systemd_active - + - name: Squid systemd overrides directory exists file: dest: /etc/systemd/system/squid.service.d/ @@ -29,4 +29,4 @@ daemon_reload: yes when: - _squid_systemd_active.rc == 0 - - _squid_systemd_override.changed + - _squid_systemd_override is changed diff --git a/ssl/meta/main.yml b/ssl/meta/main.yml index 19ef50ef..575baa70 100644 --- a/ssl/meta/main.yml +++ b/ssl/meta/main.yml @@ -1,18 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Deployment of SSL certificate, key and dhparams issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie - - stretch + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/ssl/tasks/main.yml b/ssl/tasks/main.yml index c6594265..3ec71115 100644 --- a/ssl/tasks/main.yml +++ b/ssl/tasks/main.yml @@ -29,9 +29,11 @@ - ssl - name: Check if Haproxy is installed - command: dpkg -l haproxy + shell: "set -o pipefail && dpkg -l haproxy 2>/dev/null | grep -q -E '^(i|h)i'" + args: + executable: /bin/bash register: haproxy_check - check_mode: False + check_mode: no changed_when: False failed_when: False tags: diff --git a/supervisord/tasks/main.yml b/supervisord/tasks/main.yml index 17d7737a..b35bd03f 100644 --- a/supervisord/tasks/main.yml +++ b/supervisord/tasks/main.yml @@ -12,6 +12,6 @@ mode: "0644" force: no notify: restart supervisor - when: supervisord_enable_http + when: supervisord_enable_http | bool tags: - supervisord diff --git a/tomcat-instance/meta/main.yml b/tomcat-instance/meta/main.yml index 692e2d44..98a9de51 100644 --- a/tomcat-instance/meta/main.yml +++ b/tomcat-instance/meta/main.yml @@ -1,18 +1,29 @@ --- galaxy_info: - author: Evolix + company: Evolix description: Configuration of a Tomcat instance. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: - { role: evolix/tomcat } diff --git a/tomcat-instance/tasks/bootstrap.yml b/tomcat-instance/tasks/bootstrap.yml index c177aea9..001088b1 100644 --- a/tomcat-instance/tasks/bootstrap.yml +++ b/tomcat-instance/tasks/bootstrap.yml @@ -6,7 +6,7 @@ mode: "u=rwx,g=rwxs,o=" owner: "{{ tomcat_instance_name }}" group: "{{ tomcat_instance_name }}" - with_items: + loop: - 'conf' - 'logs' - 'webapps' diff --git a/tomcat-instance/tasks/check.yml b/tomcat-instance/tasks/check.yml index 3c2319d0..eff9d236 100644 --- a/tomcat-instance/tasks/check.yml +++ b/tomcat-instance/tasks/check.yml @@ -8,7 +8,7 @@ register: check_port_gid changed_when: false failed_when: - - check_port_gid|success + - check_port_gid | success - check_port_gid.stdout != "{{ tomcat_instance_name }}" - name: Check use of uid @@ -16,7 +16,7 @@ register: check_port_uid changed_when: false failed_when: - - check_port_uid|success + - check_port_uid | success - check_port_uid.stdout != "{{ tomcat_instance_name }}" #- name: Check use of http port diff --git a/tomcat-instance/tasks/user.yml b/tomcat-instance/tasks/user.yml index 64244799..d4fc8521 100644 --- a/tomcat-instance/tasks/user.yml +++ b/tomcat-instance/tasks/user.yml @@ -2,7 +2,7 @@ - fail: msg: "You must provide a value for the 'tomcat_instance_port' variable." - when: tomcat_instance_port is not defined or tomcat_instance_port == '' + when: tomcat_instance_port is not defined or tomcat_instance_port | length == 0 - name: "Test if uid '{{ tomcat_instance_port }}' exists" diff --git a/tomcat/meta/main.yml b/tomcat/meta/main.yml index 28ecbd53..e612c99c 100644 --- a/tomcat/meta/main.yml +++ b/tomcat/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation of a Tomcat. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/varnish/meta/main.yml b/varnish/meta/main.yml index 855101e1..d969cd4b 100644 --- a/varnish/meta/main.yml +++ b/varnish/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Installation and basic configuration of Varnish issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/varnish/tasks/main.yml b/varnish/tasks/main.yml index 035ae4a4..95a720c8 100644 --- a/varnish/tasks/main.yml +++ b/varnish/tasks/main.yml @@ -10,7 +10,7 @@ file: path: "{{ item }}" state: absent - with_items: + loop: - /etc/default/varnish - /etc/default/varnishncsa - /etc/default/varnishlog @@ -84,15 +84,17 @@ dest: "{{ varnish_config_file }}" mode: "0644" force: yes - with_first_found: - - "templates/varnish/varnish.{{ inventory_hostname }}.vcl.j2" - - "templates/varnish/default.{{ inventory_hostname }}.vcl.j2" - - "templates/varnish/varnish.{{ host_group }}.vcl.j2" - - "templates/varnish/default.{{ host_group }}.vcl.j2" - - "templates/varnish/varnish.default.vcl.j2" - - "templates/varnish/default.default.vcl.j2" - - "varnish.vcl.j2" - - "default.vcl.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/varnish/varnish.{{ inventory_hostname }}.vcl.j2" + - "templates/varnish/default.{{ inventory_hostname }}.vcl.j2" + - "templates/varnish/varnish.{{ host_group | default('all') }}.vcl.j2" + - "templates/varnish/default.{{ host_group | default('all') }}.vcl.j2" + - "templates/varnish/varnish.default.vcl.j2" + - "templates/varnish/default.default.vcl.j2" + - "templates/varnish.vcl.j2" + - "templates/default.vcl.j2" notify: reload varnish tags: - varnish @@ -107,6 +109,7 @@ tags: - varnish - config + - update-config - name: Copy included Varnish config template: diff --git a/varnish/tasks/munin.yml b/varnish/tasks/munin.yml index 6e307c49..1d58aee6 100644 --- a/varnish/tasks/munin.yml +++ b/varnish/tasks/munin.yml @@ -35,7 +35,7 @@ src: /usr/local/share/munin/plugins/varnish4_ dest: "/etc/munin/plugins/varnish4_{{item}}" state: link - with_items: + loop: - backend_traffic - bad - expunge diff --git a/vrrpd/meta/main.yml b/vrrpd/meta/main.yml index 222df302..82eca7a2 100644 --- a/vrrpd/meta/main.yml +++ b/vrrpd/meta/main.yml @@ -1,14 +1,25 @@ galaxy_info: - author: Evolix + company: Evolix description: Install Evolix's patched vrrpd and adjust sysctl params. issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. \ No newline at end of file diff --git a/vrrpd/tasks/main.yml b/vrrpd/tasks/main.yml index b6f4e7f5..84d4f4ee 100644 --- a/vrrpd/tasks/main.yml +++ b/vrrpd/tasks/main.yml @@ -18,7 +18,7 @@ value: "{{ item.value }}" sysctl_set: yes state: present - with_items: + loop: - { name: 'net.ipv4.conf.default.rp_filter', value: 0 } - { name: 'net.ipv4.conf.eth0.rp_filter', value: 0 } - { name: 'net.ipv4.conf.all.rp_filter', value: 0 } diff --git a/webapps/evoadmin-mail/tasks/apache.yml b/webapps/evoadmin-mail/tasks/apache.yml index e83fc09d..f975c5f9 100644 --- a/webapps/evoadmin-mail/tasks/apache.yml +++ b/webapps/evoadmin-mail/tasks/apache.yml @@ -13,7 +13,7 @@ dest: "/etc/apache2/sites-enabled/evoadminmail.conf" state: link notify: reload apache2 - when: evoadminmail_enable_vhost + when: evoadminmail_enable_vhost | bool tags: - evoadmin-mail @@ -22,6 +22,6 @@ dest: "/etc/apache2/sites-enabled/evoadminmail.conf" state: absent notify: reload apache2 - when: not evoadminmail_enable_vhost + when: not (evoadminmail_enable_vhost | bool) tags: - evoadmin-mail diff --git a/webapps/evoadmin-mail/tasks/nginx.yml b/webapps/evoadmin-mail/tasks/nginx.yml index 5ede64e7..2cb490e8 100644 --- a/webapps/evoadmin-mail/tasks/nginx.yml +++ b/webapps/evoadmin-mail/tasks/nginx.yml @@ -15,13 +15,13 @@ tags: - evoadmin-mail -- name: Active evoadminmail VHost +- name: Active evoadminmail VHost file: src: "/etc/nginx/sites-available/evoadminmail.conf" dest: "/etc/nginx/sites-enabled/evoadminmail.conf" state: link notify: reload nginx - when: evoadminmail_enable_vhost + when: evoadminmail_enable_vhost | bool tags: - evoadmin-mail @@ -30,6 +30,6 @@ dest: "/etc/nginx/sites-enabled/evoadminmail.conf" state: absent notify: reload nginx - when: not evoadminmail_enable_vhost + when: not (evoadminmail_enable_vhost | bool) tags: - evoadmin-mail diff --git a/webapps/evoadmin-web/README.md b/webapps/evoadmin-web/README.md index 977764ad..24242d1b 100644 --- a/webapps/evoadmin-web/README.md +++ b/webapps/evoadmin-web/README.md @@ -1,34 +1,34 @@ # Set custom web-add.conf file - "templates/evoadmin-web/web-add.{{ inventory_hostname }}.conf.j2" -- "templates/evoadmin-web/web-add.{{ host_group }}.conf.j2" +- "templates/evoadmin-web/web-add.{{ host_group | default('all') }}.conf.j2" - "templates/evoadmin-web/web-add.conf.j2" And force it to update: evoadmin_add_conf_force: True # Set custom web-mail.tpl - "templates/evoadmin-web/web-mail.{{ inventory_hostname }}.tpl.j2" -- "templates/evoadmin-web/web-mail.{{ host_group }}.tpl.j2" +- "templates/evoadmin-web/web-mail.{{ host_group | default('all') }}.tpl.j2" - "templates/evoadmin-web/web-mail.tpl.j2" And force it to update: evoadmin_mail_tpl_force: True # Set custom evoadmin.conf VHost - "templates/evoadmin-web/evoadmin.{{ inventory_hostname }}.conf.j2" -- "templates/evoadmin-web/evoadmin.{{ host_group }}.conf.j2" +- "templates/evoadmin-web/evoadmin.{{ host_group | default('all') }}.conf.j2" - "templates/evoadmin-web/evoadmin.conf.j2" And force it to update: evoadmin_force_vhost: True # Set custom config.local.php - "templates/evoadmin-web/config.local.{{ inventory_hostname }}.php.j2" -- "templates/evoadmin-web/config.local.{{ host_group }}.php.j2" +- "templates/evoadmin-web/config.local.{{ host_group | default('all') }}.php.j2" - "templates/evoadmin-web/config.local.php.j2" And force it to update: evoadmin_config_local_php_force: True # Set evoadmin-web sudoers file - "templates/evoadmin-web/sudoers.{{ inventory_hostname }}.j2" -- "templates/evoadmin-web/sudoers.{{ host_group }}.j2" +- "templates/evoadmin-web/sudoers.{{ host_group | default('all') }}.j2" - "templates/evoadmin-web/sudoers.j2" - "sudoers.j2" And force it to update: @@ -39,7 +39,7 @@ evoadmin_htpasswd: True Overwrite its template: - "templates/evoadmin-web/htpasswd.{{ inventory_hostname }}.j2" -- "templates/evoadmin-web/htpasswd.{{ host_group }}.j2" +- "templates/evoadmin-web/htpasswd.{{ host_group | default('all') }}.j2" - "templates/evoadmin-web/htpasswd.j2" - "htpasswd.j2" And force it to update: diff --git a/webapps/evoadmin-web/meta/main.yml b/webapps/evoadmin-web/meta/main.yml index cf2ad4e5..2c6da2f4 100644 --- a/webapps/evoadmin-web/meta/main.yml +++ b/webapps/evoadmin-web/meta/main.yml @@ -1,19 +1,29 @@ --- galaxy_info: - author: Evolix + company: Evolix description: Installation of evoadmin-web issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - name: Debian versions: - jessie - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: - { role: evolix/proftpd } diff --git a/webapps/evoadmin-web/tasks/config.yml b/webapps/evoadmin-web/tasks/config.yml index 689a217e..1053360c 100644 --- a/webapps/evoadmin-web/tasks/config.yml +++ b/webapps/evoadmin-web/tasks/config.yml @@ -11,11 +11,13 @@ src: "{{ item }}" dest: /etc/evolinux/web-add.conf force: "{{ evoadmin_add_conf_force }}" - with_first_found: - - "templates/evoadmin-web/web-add.{{ inventory_hostname }}.conf.j2" - - "templates/evoadmin-web/web-add.{{ host_group }}.conf.j2" - - "templates/evoadmin-web/web-add.conf.j2" - - "web-add.conf.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/web-add.{{ inventory_hostname }}.conf.j2" + - "templates/evoadmin-web/web-add.{{ host_group | default('all') }}.conf.j2" + - "templates/evoadmin-web/web-add.conf.j2" + - "templates/web-add.conf.j2" register: evoadmin_add_conf_template - name: Configure web-add template file for mail @@ -23,9 +25,11 @@ src: "{{ item }}" dest: "{{ evoadmin_scripts_dir }}/web-mail.tpl" force: "{{ evoadmin_mail_tpl_force }}" - with_first_found: - - "templates/evoadmin-web/web-mail.{{ inventory_hostname }}.tpl.j2" - - "templates/evoadmin-web/web-mail.{{ host_group }}.tpl.j2" - - "templates/evoadmin-web/web-mail.tpl.j2" - - "web-mail.tpl.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/web-mail.{{ inventory_hostname }}.tpl.j2" + - "templates/evoadmin-web/web-mail.{{ host_group | default('all') }}.tpl.j2" + - "templates/evoadmin-web/web-mail.tpl.j2" + - "templates/web-mail.tpl.j2" register: evoadmin_mail_tpl_template diff --git a/webapps/evoadmin-web/tasks/main.yml b/webapps/evoadmin-web/tasks/main.yml index c03ef979..1acb2aa5 100644 --- a/webapps/evoadmin-web/tasks/main.yml +++ b/webapps/evoadmin-web/tasks/main.yml @@ -3,7 +3,7 @@ - name: "Ensure that evoadmin_contact_email is defined" fail: msg: Please configure var evoadmin_contact_email - when: evoadmin_contact_email is none + when: evoadmin_contact_email is none or evoadmin_contact_email | length == 0 - include: packages.yml diff --git a/webapps/evoadmin-web/tasks/packages.yml b/webapps/evoadmin-web/tasks/packages.yml index 7d3f6051..7044bd43 100644 --- a/webapps/evoadmin-web/tasks/packages.yml +++ b/webapps/evoadmin-web/tasks/packages.yml @@ -19,7 +19,7 @@ apt: deb: '{{ item }}' state: present - with_items: + loop: - 'http://mirror.evolix.org/debian/pool/main/p/php-log/php-log_1.12.9-2_all.deb' when: ansible_distribution_major_version is version('10', '>=') diff --git a/webapps/evoadmin-web/tasks/user.yml b/webapps/evoadmin-web/tasks/user.yml index 7b58270c..68ac91de 100644 --- a/webapps/evoadmin-web/tasks/user.yml +++ b/webapps/evoadmin-web/tasks/user.yml @@ -37,7 +37,7 @@ line: "{{ item.line }}" regexp: "{{ item.regexp }}" state: present - with_items: + loop: - line: 'evoadmin: root' regexp: '^evoadmin:' - line: 'www-evoadmin: root' @@ -112,9 +112,11 @@ mode: "0600" force: "{{ evoadmin_sudoers_conf_force }}" validate: "visudo -cf %s" - with_first_found: - - "templates/evoadmin-web/sudoers.{{ inventory_hostname }}.j2" - - "templates/evoadmin-web/sudoers.{{ host_group }}.j2" - - "templates/evoadmin-web/sudoers.j2" - - "sudoers.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/sudoers.{{ inventory_hostname }}.j2" + - "templates/evoadmin-web/sudoers.{{ host_group | default('all') }}.j2" + - "templates/evoadmin-web/sudoers.j2" + - "templates/sudoers.j2" register: evoadmin_sudoers_conf diff --git a/webapps/evoadmin-web/tasks/web.yml b/webapps/evoadmin-web/tasks/web.yml index cafccc72..7f95c96c 100644 --- a/webapps/evoadmin-web/tasks/web.yml +++ b/webapps/evoadmin-web/tasks/web.yml @@ -32,11 +32,13 @@ src: "{{ item }}" dest: /etc/apache2/sites-available/evoadmin.conf force: "{{ evoadmin_force_vhost }}" - with_first_found: - - "templates/evoadmin-web/evoadmin.{{ inventory_hostname }}.conf.j2" - - "templates/evoadmin-web/evoadmin.{{ host_group }}.conf.j2" - - "templates/evoadmin-web/evoadmin.conf.j2" - - "evoadmin.conf.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/evoadmin.{{ inventory_hostname }}.conf.j2" + - "templates/evoadmin-web/evoadmin.{{ host_group | default('all') }}.conf.j2" + - "templates/evoadmin-web/evoadmin.conf.j2" + - "templates/evoadmin.conf.j2" register: evoadmin_vhost_template notify: reload apache2 @@ -45,14 +47,14 @@ register: cmd_a2ensite changed_when: "'Enabling site' in cmd_a2ensite.stdout" notify: reload apache2 - when: evoadmin_enable_vhost + when: evoadmin_enable_vhost | bool - name: Disable evoadmin vhost command: "a2dissite evoadmin.conf" register: cmd_a2dissite changed_when: "'Disabling site' in cmd_a2dissite.stdout" notify: reload apache2 - when: not evoadmin_enable_vhost + when: not (evoadmin_enable_vhost | bool) - name: Copy htpasswd for evoadmin template: @@ -62,13 +64,15 @@ owner: root group: www-data force: "{{ evoadmin_htpasswd_force }}" - with_first_found: - - "templates/evoadmin-web/htpasswd.{{ inventory_hostname }}.j2" - - "templates/evoadmin-web/htpasswd.{{ host_group }}.j2" - - "templates/evoadmin-web/htpasswd.j2" - - "htpasswd.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/htpasswd.{{ inventory_hostname }}.j2" + - "templates/evoadmin-web/htpasswd.{{ host_group | default('all') }}.j2" + - "templates/evoadmin-web/htpasswd.j2" + - "templates/htpasswd.j2" register: evoadmin_htpasswd_template - when: evoadmin_htpasswd + when: evoadmin_htpasswd | bool - name: Copy config file for evoadmin template: @@ -78,9 +82,11 @@ owner: evoadmin group: evoadmin force: "{{ evoadmin_config_local_php_force }}" - with_first_found: - - "templates/evoadmin-web/config.local.{{ inventory_hostname }}.php.j2" - - "templates/evoadmin-web/config.local.{{ host_group }}.php.j2" - - "templates/evoadmin-web/config.local.php.j2" - - "config.local.php.j2" + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/evoadmin-web/config.local.{{ inventory_hostname }}.php.j2" + - "templates/evoadmin-web/config.local.{{ host_group | default('all') }}.php.j2" + - "templates/evoadmin-web/config.local.php.j2" + - "templates/config.local.php.j2" register: evoadmin_config_local_php_template diff --git a/webapps/nextcloud/defaults/main.yml b/webapps/nextcloud/defaults/main.yml index cb8b70a0..3c1bf40a 100644 --- a/webapps/nextcloud/defaults/main.yml +++ b/webapps/nextcloud/defaults/main.yml @@ -1,6 +1,6 @@ --- nextcloud_webserver: 'nginx' -nextcloud_version: "20.0.0" +nextcloud_version: "21.0.0" nextcloud_archive_name: "nextcloud-{{ nextcloud_version }}.tar.bz2" nextcloud_releases_baseurl: "https://download.nextcloud.com/server/releases/" diff --git a/webapps/nextcloud/tasks/config.yml b/webapps/nextcloud/tasks/config.yml index a4e3a3e7..85142726 100644 --- a/webapps/nextcloud/tasks/config.yml +++ b/webapps/nextcloud/tasks/config.yml @@ -15,7 +15,7 @@ tags: - nextcloud - when: nextcloud_admin_password == "" + when: nextcloud_admin_password | length == 0 - name: Get Nextcloud Status shell: "php ./occ status --output json | grep -v 'Nextcloud is not installed'" diff --git a/webapps/nextcloud/tasks/mysql.yml b/webapps/nextcloud/tasks/mysql.yml index f2fcee32..a12a80f4 100644 --- a/webapps/nextcloud/tasks/mysql.yml +++ b/webapps/nextcloud/tasks/mysql.yml @@ -54,7 +54,7 @@ section: client option: "{{ item.option }}" value: "{{ item.value }}" - with_items: + loop: - { option: "user", value: "{{ nextcloud_db_user }}" } - { option: "database", value: "{{ nextcloud_db_name }}" } - { option: "password", value: "{{ nextcloud_db_pass }}" } diff --git a/webapps/nextcloud/tasks/user.yml b/webapps/nextcloud/tasks/user.yml index 07d5a31a..dd778f87 100644 --- a/webapps/nextcloud/tasks/user.yml +++ b/webapps/nextcloud/tasks/user.yml @@ -14,6 +14,7 @@ shell: '/bin/bash' createhome: True state: present + mode: "0755" tags: - nextcloud @@ -30,7 +31,7 @@ mode: "0770" owner: "{{ nextcloud_user }}" group: "{{ nextcloud_user }}" - with_items: + loop: - "{{ nextcloud_home }}/log" - "{{ nextcloud_home }}/tmp" - "{{ nextcloud_home }}/data" diff --git a/webapps/roundcube/tasks/main.yml b/webapps/roundcube/tasks/main.yml index 2efd1823..08fe73d1 100644 --- a/webapps/roundcube/tasks/main.yml +++ b/webapps/roundcube/tasks/main.yml @@ -5,7 +5,7 @@ question: "{{ item.key }}" value: "{{ item.value }}" vtype: "{{ item.type }}" - with_items: + loop: - { key: 'roundcube/database-type', type: 'select', value: 'sqlite3' } - { key: 'roundcube/db/basepath', type: 'string', value: '/var/lib/roundcube/' } tags: @@ -116,7 +116,7 @@ src: "/etc/nginx/sites-available/roundcube.conf" dest: "/etc/nginx/sites-enabled/roundcube.conf" state: link - when: roundcube_webserver == "nginx" + when: roundcube_webserver == "nginx" notify: reload nginx - name: enable roundcube link in default site index diff --git a/webapps/wordpress/meta/main.yml b/webapps/wordpress/meta/main.yml index 2adf765b..89f9b27b 100644 --- a/webapps/wordpress/meta/main.yml +++ b/webapps/wordpress/meta/main.yml @@ -1,17 +1,28 @@ galaxy_info: - author: Evolix + company: Evolix description: Install Wordpress site issue_tracker_url: https://gitea.evolix.org/evolix/ansible-roles/issues license: GPLv2 - min_ansible_version: 2.2 + min_ansible_version: "2.2" platforms: - - name: Debian - versions: - - jessie + - name: Debian + versions: + - jessie + - stretch + - buster + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is + # a keyword that describes and categorizes the role. + # Users find roles by searching for tags. Be sure to + # remove the '[]' above if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of + # alphanumeric characters. Maximum 20 tags per role. dependencies: [] # List your role dependencies here, one per line. diff --git a/webapps/wordpress/tasks/main.yml b/webapps/wordpress/tasks/main.yml index 6b6a67e2..e1f442c0 100644 --- a/webapps/wordpress/tasks/main.yml +++ b/webapps/wordpress/tasks/main.yml @@ -55,28 +55,28 @@ register: check_version check_mode: no failed_when: false - changed_when: check_version.rc + changed_when: check_version.rc == 1 - name: Update Wordpress shell: '{{ wordpress_wpcli }} core update --version={{ wordpress_version }}' args: removes: "{{ ansible_env.HOME }}/www/index.php" - when: check_version.rc + when: check_version.rc == 1 - name: Install default plugin shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} || {{ wordpress_wpcli }} plugin install {{ item }}' changed_when: false - with_items: "{{ wordpress_plugins }}" + loop: "{{ wordpress_plugins }}" - name: Update default plugins shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin update {{ item }}' changed_when: false - with_items: "{{ wordpress_plugins }}" + loop: "{{ wordpress_plugins }}" - name: Activate default plugins shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin activate {{ item }}' changed_when: false - with_items: "{{ wordpress_plugins }}" + loop: "{{ wordpress_plugins }}" - name: Send a summary mail mail: