enhancement: add role for common tasks

Signed-off-by: gardar <gardar@users.noreply.github.com>
This commit is contained in:
gardar 2024-10-15 16:50:28 +00:00
parent b5b43e2118
commit 8734f607db
No known key found for this signature in database
GPG key ID: 75FAE37CBA8C13C2
11 changed files with 470 additions and 0 deletions

View file

@ -4,4 +4,5 @@ warn_list:
- galaxy[version-incorrect] # until collection gets bumped to 1.x.x - galaxy[version-incorrect] # until collection gets bumped to 1.x.x
- name[casing] # https://github.com/ansible/ansible-lint/issues/4035#issuecomment-2116272270 - name[casing] # https://github.com/ansible/ansible-lint/issues/4035#issuecomment-2116272270
skip_list: skip_list:
- role-name # Allow underscore prefix in role name for internal role
- var-naming[no-role-prefix] # https://github.com/ansible/ansible-lint/pull/3422#issuecomment-1549584988 - var-naming[no-role-prefix] # https://github.com/ansible/ansible-lint/pull/3422#issuecomment-1549584988

3
roles/_common/README.md Normal file
View file

@ -0,0 +1,3 @@
---
# Internal use only
This role is for common tasks shared between roles and should not be used directly

View file

@ -0,0 +1,15 @@
---
- name: "Restart {{ _common_service_name }}"
# listen: "restart_service"
become: true
ansible.builtin.service:
daemon_reload: true
name: "{{ _common_service_name }}"
state: restarted
- name: "Reload {{ _common_service_name }}"
# listen: "reload_service"
become: true
ansible.builtin.service:
name: "{{ _common_service_name }}"
state: reloaded

View file

@ -0,0 +1,91 @@
---
argument_specs:
configure:
short_description: "Internal only - common configuration tasks"
description: "Internal only - selinux requirements"
author:
- "Prometheus Community"
options:
_common_service_name:
description:
- "Name of the system service (systemd)"
- "Usually matches the role name"
default: "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
_common_config_dir:
description: "Path to directory to install configuration."
default: ""
_common_system_user:
description: "System user for running the service."
default: ""
_common_system_group:
description: "User group for the system user."
default: ""
_common_tls_server_config:
description: "Configuration for TLS authentication."
default: ""
_common_http_server_config:
description: "Configuration for HTTP/2 support."
default: ""
_common_common_basic_auth_users:
description: "Dictionary of users and password for basic authentication. Passwords are automatically hashed with bcrypt."
default: ""
install:
short_description: "Internal only - common installation tasks"
description: "Internal only - selinux requirements"
author:
- "Prometheus Community"
options:
_common_binaries:
description: "List of binaries to install"
default: []
type: "list"
elements: "str"
_common_binary_install_dir:
description: "Directory to install binaries"
default: ""
_common_binary_name:
description: "Name of main binary"
default: "{{ __common_binary_basename }}"
_common_binary_unarchive_opts:
description: "Extra options to pass to binary unarchive task"
default: []
type: "list"
elements: "str"
_common_binary_url:
description: "URL of the binaries to install"
default: ""
_common_checksums_url:
description: "URL of the checksums file for the binaries"
default: ""
_common_config_dir:
description: "Path to the configuration dir"
default: ""
_common_local_cache_path:
description: "Local path to stash the archive and its extraction"
default: ""
_common_system_user:
description: "System user for running the service."
default: ""
_common_system_group:
description: "User group for the system user."
default: ""
preflight:
short_description: "Internal only - common preflight tasks"
description: "Internal only - selinux requirements"
author:
- "Prometheus Community"
options:
_common_dependencies:
description: "Package dependencies to install"
default: "{% if (ansible_pkg_mgr == 'apt') %}\
{{ ('python-apt' if ansible_python_version is version('3', '<') else 'python3-apt') }}
{% else %}\
{% endif %}"
selinux:
short_description: "Internal only - common selinux configuration tasks"
description: "Internal only - selinux requirements"
author:
- "Prometheus Community"
options:
_common_selinux_port:
description: "Port to allow in SELinux"

View file

@ -0,0 +1,6 @@
---
galaxy_info:
author: "Prometheus Community"
description: "Internal role for common tasks shared between roles"
license: "Apache"
min_ansible_version: "2.9"

View file

@ -0,0 +1,70 @@
---
- name: "Validate invocation of _common role"
ansible.builtin.assert:
that:
- "ansible_parent_role_names is defined"
- "ansible_parent_role_names | default() | length > 0"
fail_msg: "Error: The '_common' role is a internal role and cannot be invoked directly."
tags:
- always
- name: "Create systemd service unit {{ _common_service_name }}"
ansible.builtin.template:
src: "{{ _common_service_name }}.service.j2"
dest: "/etc/systemd/system/{{ _common_service_name }}.service"
owner: root
group: root
mode: 0644
become: true
notify:
- "{{ ansible_parent_role_names | first }} : Restart {{ _common_service_name }}"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: "Create config dir {{ _common_config_dir }}"
ansible.builtin.file:
path: "{{ _common_config_dir }}"
state: directory
owner: "{{ _common_system_user }}"
group: "{{ _common_system_group }}"
mode: u+rwX,g+rwX,o=rX
become: true
notify:
- "{{ ansible_parent_role_names | first }} : Restart {{ _common_service_name }}"
when: (_common_config_dir)
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: "Install web config for {{ _common_service_name }}"
ansible.builtin.template:
src: "web_config.yml.j2"
dest: "{{ _common_config_dir }}/web_config.yml"
owner: "{{ _common_system_user }}"
group: "{{ _common_system_group }}"
mode: 0644
become: true
notify:
- "{{ ansible_parent_role_names | first }} : Restart {{ _common_service_name }}"
when: "[_common_tls_server_config, _common_http_server_config, _common_basic_auth_users] | map('length') | select('>', 0) | list is any"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
#
# - name: "Configure {{ _common_service_name }}"
# ansible.builtin.template:
# # src: "{{ ansible_parent_role_paths | first }}/templates/{{ _common_service_name }}.yml.j2"
# src: "{{ _config_template | default(ansible_parent_role_paths | first ~ '/templates/' ~ _common_service_name ~ '.yml.j2') }}"
# # dest: "/etc/{{ _common_service_name }}.yml"
# dest: "{{ _config_dest | default('/etc/' ~ _common_service_name ~ '.yml') }}"
# owner: "{{ _system_user }}"
# group: "{{ _system_group }}"
# mode: 0644
# notify:
# - reload_service
# when: (ansible_parent_role_paths | first '/templates/' _common_service_name '.yml.j2')

View file

@ -0,0 +1,108 @@
---
- name: "Validate invocation of _common role"
ansible.builtin.assert:
that:
- "ansible_parent_role_names is defined"
- "ansible_parent_role_names | default() | length > 0"
fail_msg: "Error: The '_common' role is a internal role and cannot be invoked directly."
tags:
- always
- name: "Create system group {{ _common_system_group }}"
ansible.builtin.group:
name: "{{ _common_system_group }}"
system: true
state: present
become: true
when: _common_system_group != "root"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- name: "Create system user {{ _common_system_user }}"
ansible.builtin.user:
name: "{{ _common_system_user }}"
system: true
shell: "/usr/sbin/nologin"
group: "{{ _common_system_group }}"
home: "{{ _common_config_dir | default('/') }}"
create_home: false
become: true
when: _common_system_user != "root"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- name: "Create localhost binary cache path"
ansible.builtin.file:
path: "{{ _common_local_cache_path }}"
state: directory
mode: 0755
delegate_to: localhost
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- download
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_download"
- name: "Download binary {{ __common_binary_basename }}"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- download
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_download"
block:
- name: "Get checksum list for {{ __common_binary_basename }}"
ansible.builtin.set_fact:
__common_binary_checksums: "{{ dict(lookup('url', _common_checksums_url, headers=__common_github_api_headers, wantlist=True)
| map('regex_replace', '^([a-fA-F0-9]+)\\s+', 'sha256:\\1 ')
| map('regex_findall', '^(sha256:[a-fA-F0-9]+)\\s+(.+)$') | map('flatten') | map('reverse')) }}"
run_once: true
when: (_common_checksums_url)
- name: "Download {{ __common_binary_basename }}"
ansible.builtin.get_url:
url: "{{ _common_binary_url }}"
dest: "{{ _common_local_cache_path }}/{{ _common_binary_name | default(__common_binary_basename) }}"
headers: "{{ __common_github_api_headers }}"
checksum: "{{ __common_binary_checksums[__common_binary_basename] | default(omit) }}"
mode: 0644
register: __common_download
until: __common_download is succeeded
retries: 5
delay: 2
# run_once: true # <-- this can't be set due to multi-arch support
delegate_to: localhost
check_mode: false
- name: "Unpack binary archive {{ __common_binary_basename }}"
ansible.builtin.unarchive:
src: "{{ _common_local_cache_path }}/{{ __common_binary_basename }}"
dest: "{{ _common_local_cache_path }}"
mode: 0755
list_files: true
extra_opts: "{{ _common_binary_unarchive_opts | default(omit, true) }}"
register: __common_unpack
delegate_to: localhost
check_mode: false
when: __common_binary_basename is search('\.zip$|\.tar\.gz$')
- name: "Propagate binaries"
ansible.builtin.copy:
src: "{{ _common_local_cache_path }}/{{ item }}"
dest: "{{ _common_binary_install_dir }}/{{ item }}"
mode: 0755
owner: root
group: root
loop: "{{ _common_binaries }}"
become: true
notify:
- "{{ ansible_parent_role_names | first }} : Restart {{ _common_service_name }}"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"

View file

@ -0,0 +1,76 @@
---
- name: "Validate invocation of _common role"
ansible.builtin.assert:
that:
- "ansible_parent_role_names is defined"
- "ansible_parent_role_names | default() | length > 0"
fail_msg: "Error: The '_common' role is a internal role and cannot be invoked directly."
tags:
- always
- name: "Check for deprecated skip_install variable"
ansible.builtin.assert:
that:
- __common_parent_role_short_name ~ '_skip_install' not in vars
fail_msg: "The variable {{ __common_parent_role_short_name ~ '_skip_install' }} is deprecated.
Please use `--skip-tags {{ __common_parent_role_short_name }}_install` instead to skip the installation."
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: "Check for deprecated binary_local_dir variable"
ansible.builtin.assert:
that:
- __common_parent_role_short_name ~ '_binary_local_dir' not in vars
fail_msg: "The variable {{ __common_parent_role_short_name ~ '_binary_local_dir' }} is deprecated.
Please use the variable {{ __common_parent_role_short_name ~ '_local_cache_path' }} instead"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: "Check for deprecated archive_path variable"
ansible.builtin.assert:
that:
- __common_parent_role_short_name ~ '_archive_path' not in vars
fail_msg: "The variable {{ __common_parent_role_short_name ~ '_archive_path' }} is deprecated.
Please use the variable {{ __common_parent_role_short_name ~ '_local_cache_path' }} instead"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: Assert usage of systemd as an init system
ansible.builtin.assert:
that: ansible_service_mgr == 'systemd'
msg: "This module only works with systemd"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- name: Install dependencies
become: true
ansible.builtin.package:
name: "{{ _common_dependencies }}"
state: present
when: (_common_dependencies)
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"
- name: Gather package facts
ansible.builtin.package_facts:
when: "not 'packages' in ansible_facts"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- install
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_install"

View file

@ -0,0 +1,58 @@
---
- name: "Validate invocation of _common role"
ansible.builtin.assert:
that:
- "ansible_parent_role_names is defined"
- "ansible_parent_role_names | default() | length > 0"
fail_msg: "Error: The '_common' role is a internal role and cannot be invoked directly."
tags:
- always
- name: Install selinux python packages [RedHat]
ansible.builtin.package:
name: "{{ ['libselinux-python', 'policycoreutils-python']
if ansible_python_version is version('3', '<') else
['python3-libselinux', 'python3-policycoreutils'] }}"
state: present
register: __common_install_selinux_packages
until: __common_install_selinux_packages is success
retries: 5
delay: 2
become: true
when: ansible_os_family | lower == "redhat"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: Install selinux python packages [clearlinux]
ansible.builtin.package:
name: sysadmin-basic
state: present
register: __common_install_selinux_packages
until: __common_install_selinux_packages is success
retries: 5
delay: 2
become: true
when:
- ansible_distribution | lower == "clearlinux"
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"
- name: Allow port in SELinux
community.general.seport:
ports: "{{ _common_selinux_port }}"
proto: tcp
setype: http_port_t
state: present
become: true
when:
- ansible_version.full is version_compare('2.4', '>=')
- ansible_selinux.status == "enabled"
- (_common_selinux_port)
tags:
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"
- configure
- "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}_configure"

View file

@ -0,0 +1,18 @@
---
{{ ansible_managed | comment }}
{% if _common_tls_server_config | length > 0 %}
tls_server_config:
{{ _common_tls_server_config | to_nice_yaml | indent(2, true) }}
{% endif %}
{% if _common_http_server_config | length > 0 %}
http_server_config:
{{ _common_http_server_config | to_nice_yaml | indent(2, true) }}
{% endif %}
{% if _common_basic_auth_users | length > 0 %}
basic_auth_users:
{% for k, v in _common_basic_auth_users.items() %}
{{ k }}: {{ v | string | password_hash('bcrypt', ('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' | shuffle(seed=inventory_hostname) | join)[:22], rounds=9) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,24 @@
---
_common_local_cache_path: ""
_common_binaries: []
_common_binary_name: "{{ __common_binary_basename }}"
_common_binary_install_dir:
_common_config_dir: ""
_common_binary_url: ""
_common_checksums_url: ""
_common_selinux_port: ""
_common_service_name: "{{ __common_parent_role_short_name }}"
_common_system_user: ""
_common_system_group: ""
_common_dependencies: "{% if (ansible_pkg_mgr == 'apt') %}\
{{ ('python-apt' if ansible_python_version is version('3', '<') else 'python3-apt') }}
{% else %}\
{% endif %}"
_common_binary_unarchive_opts: ""
_common_tls_server_config: {}
_common_http_server_config: {}
_common_basic_auth_users: {}
# Variables that should not be overwritten
__common_binary_basename: "{{ _common_binary_url | urlsplit('path') | basename }}"
__common_github_api_headers: "{{ {'GITHUB_TOKEN': lookup('ansible.builtin.env', 'GITHUB_TOKEN')} if (lookup('ansible.builtin.env', 'GITHUB_TOKEN')) else {} }}"
__common_parent_role_short_name: "{{ ansible_parent_role_names | first | regex_replace(ansible_collection_name ~ '.', '') }}"