feat: Add redis_exporter role (#299)

* feat: Add redis_exporter role


---------

Signed-off-by: anviar <oleg.kluchkin+github@gmail.com>
This commit is contained in:
Oleg Klyuchkin 2024-02-22 16:43:10 +03:00 committed by GitHub
parent 6e460d7d2a
commit d044d8894b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 972 additions and 0 deletions

View file

@ -0,0 +1,43 @@
<p><img src="https://www.circonus.com/wp-content/uploads/2015/03/sol-icon-itOps.png" alt="graph logo" title="graph" align="right" height="60" /></p>
# Ansible Role: redis_exporter
## Description
Deploy prometheus [redis_exporter](https://github.com/oliver006/redis_exporter/) using ansible.
## Requirements
- Ansible >= 2.9 (It might work on previous versions, but we cannot guarantee it)
- gnu-tar on Mac deployer host (`brew install gnu-tar`)
## Role Variables
All variables which can be overridden are stored in [defaults/main.yml](defaults/main.yml) file as well as in [meta/argument_specs.yml](meta/argument_specs.yml).
Please refer to the [collection docs](https://prometheus-community.github.io/ansible/branch/main/redis_exporter_role.html) for description and default values of the variables.
## Example
### Demo site
We provide demo site for full monitoring solution based on prometheus and grafana. Repository with code and links to running instances is [available on github](https://github.com/prometheus/demo-site) and site is hosted on [DigitalOcean](https://digitalocean.com).
## Local Testing
The preferred way of locally testing the role is to use Docker and [molecule](https://github.com/ansible-community/molecule) (v3.x). You will have to install Docker on your system. See "Get started" for a Docker package suitable to for your system. Running your tests is as simple as executing `molecule test`.
## Continuous Intergation
Combining molecule and circle CI allows us to test how new PRs will behave when used with multiple ansible versions and multiple operating systems. This also allows use to create test scenarios for different role configurations. As a result we have a quite large test matrix which can take more time than local testing, so please be patient.
## Contributing
See [contributor guideline](CONTRIBUTING.md).
## Troubleshooting
See [troubleshooting](TROUBLESHOOTING.md).
## License
This project is licensed under MIT License. See [LICENSE](/LICENSE) for more details.

View file

@ -0,0 +1,51 @@
---
redis_exporter_version: 1.58.0
redis_exporter_binary_local_dir: ""
redis_exporter_binary_url: "https://github.com/{{ _redis_exporter_repo }}/releases/download/v{{ redis_exporter_version }}/\
redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
redis_exporter_checksums_url: "https://github.com/{{ _redis_exporter_repo }}/releases/download/v{{ redis_exporter_version }}/sha256sums.txt"
redis_exporter_skip_install: false
# https://github.com/oliver006/redis_exporter?tab=readme-ov-file#command-line-flags
redis_exporter_addr: "redis://localhost:6379"
redis_exporter_user: ""
redis_exporter_password: ""
redis_exporter_passwords: {}
redis_exporter_check_keys: []
redis_exporter_check_single_keys: []
redis_exporter_check_streams: []
redis_exporter_check_single_streams: []
redis_exporter_check_keys_batch_size: 1000
redis_exporter_count_keys: []
redis_exporter_script: []
redis_exporter_debug: false
redis_exporter_log_format: "txt"
redis_exporter_namespace: "redis"
redis_exporter_connection_timeout: "15s"
redis_exporter_web_listen_address: "0.0.0.0:9121"
redis_exporter_web_telemetry_path: "/metrics"
redis_exporter_redis_only_metrics: false
redis_exporter_incl_config_metrics: false
redis_exporter_incl_system_metrics: false
redis_exporter_redact_config_metrics: false
redis_exporter_ping_on_connect: false
redis_exporter_is_tile38: false
redis_exporter_is_cluster: false
redis_exporter_export_client_list: false
redis_exporter_export_client_port: false
redis_exporter_skip_tls_verification: false
redis_exporter_tls_client_key_file: ""
redis_exporter_tls_client_cert_file: ""
redis_exporter_tls_server_key_file: ""
redis_exporter_tls_server_cert_file: ""
redis_exporter_tls_server_ca_cert_file: ""
redis_exporter_tls_server_min_version: "TLS1.2"
redis_exporter_tls_ca_cert_file: ""
redis_exporter_set_client_name: true
redis_exporter_check_key_groups: []
redis_exporter_max_distinct_key_groups: 100
redis_exporter_config_command: "CONFIG"
redis_exporter_binary_install_dir: "/usr/local/bin"
redis_exporter_system_group: "redis-exp"
redis_exporter_system_user: "{{ redis_exporter_system_group }}"

View file

@ -0,0 +1,10 @@
---
- name: Restart redis_exporter
listen: "restart redis_exporter"
become: true
ansible.builtin.systemd:
daemon_reload: true
name: redis_exporter
state: restarted
when:
- not ansible_check_mode

View file

@ -0,0 +1,181 @@
---
# yamllint disable rule:line-length
argument_specs:
main:
short_description: "Prometheus redis_exporter"
description:
- "Deploy prometheus L(redis exporter,https://github.com/oliver006/redis_exporter) using ansible"
author:
- "Prometheus Community"
options:
redis_exporter_version:
description: "redis_exporter package version. Also accepts latest as parameter."
default: "1.58.0"
redis_exporter_skip_install:
description: "redis_exporter installation tasks gets skipped when set to true."
type: bool
default: false
redis_exporter_binary_local_dir:
description:
- "Enables the use of local packages instead of those distributed on github."
- "The parameter may be set to a directory where the C(redis_exporter) binary is stored on the host where ansible is run."
- "This overrides the I(redis_exporter_version) parameter"
redis_exporter_binary_url:
description: "URL of the redis_exporter binaries .tar.gz file"
default: "https://github.com/{{ _redis_exporter_repo }}/releases/download/v{{ redis_exporter_version }}/redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
redis_exporter_checksums_url:
description: "URL of the redis_exporter checksums file"
default: "https://github.com/{{ _redis_exporter_repo }}/releases/download/v{{ redis_exporter_version }}/sha256sums.txt"
redis_exporter_addr:
description: "Address of the Redis instance"
default: "redis://localhost:6379"
redis_exporter_user:
description: "User name to use for authentication (Redis ACL for Redis 6.0 and newer)"
default: ""
redis_exporter_password:
description: "Password of the Redis instance"
default: ""
redis_exporter_passwords:
description:
- "Dictionary with passwords for instances."
- "Read more official L(documentation, https://github.com/oliver006/redis_exporter?tab=readme-ov-file#authenticating-with-redis)"
type: "dict"
default: {}
redis_exporter_check_keys:
description: "List of key patterns to export value and length/size, eg: db3=user_count will export key user_count from db 3. db defaults to 0 if omitted. The key patterns specified with this flag will be found using SCAN. Use this option if you need glob pattern matching; check-single-keys is faster for non-pattern keys. Warning: using --check-keys to match a very large number of keys can slow down the exporter to the point where it doesn't finish scraping the redis instance."
type: "list"
default: []
redis_exporter_check_single_keys:
description: "List of keys to export value and length/size, eg: db3=user_count will export key user_count from db 3. db defaults to 0 if omitted. The keys specified with this flag will be looked up directly without any glob pattern matching. Use this option if you don't need glob pattern matching; it is faster than check-keys."
type: "list"
default: []
redis_exporter_check_streams:
description: "List of stream-patterns to export info about streams, groups and consumers. Syntax is the same as check-keys."
type: "list"
default: []
redis_exporter_check_single_streams:
description: "List of streams to export info about streams, groups and consumers. The streams specified with this flag will be looked up directly without any glob pattern matching. Use this option if you don't need glob pattern matching; it is faster than check-streams."
type: "list"
default: []
redis_exporter_check_keys_batch_size:
description: "Approximate number of keys to process in each execution. This is basically the COUNT option that will be passed into the SCAN command as part of the execution of the key or key group metrics, see COUNT option. Larger value speeds up scanning. Still Redis is a single-threaded app, huge COUNT can affect production environment."
type: "int"
default: 1000
redis_exporter_count_keys:
description: "List of patterns to count, eg: db3=sessions:* will count all keys with prefix sessions: from db 3. db defaults to 0 if omitted. Warning: The exporter runs SCAN to count the keys. This might not perform well on large databases."
type: "list"
default: []
redis_exporter_script:
description: "List of path(s) to Redis Lua script(s) for gathering extra metrics."
type: "list"
default: []
redis_exporter_debug:
description: "Verbose debug output"
type: bool
default: false
redis_exporter_log_format:
description: "Output format of log messages. One of: [txt, json]"
default: "txt"
redis_exporter_namespace:
description: "Namespace for the metrics"
default: "redis"
redis_exporter_connection_timeout:
description: "Timeout for connection to Redis instance"
default: "15s"
redis_exporter_web_listen_address:
description: "Address to listen on for web interface and telemetry"
default: "0.0.0.0:9121"
redis_exporter_web_telemetry_path:
description: "Path under which to expose metrics"
default: "/metrics"
redis_exporter_redis_only_metrics:
description: "Whether to also export go runtime metrics"
type: bool
default: false
redis_exporter_incl_config_metrics:
description: "Whether to include all config settings as metrics"
type: bool
default: false
redis_exporter_incl_system_metrics:
description: "Whether to include system metrics like total_system_memory_bytes"
type: bool
default: false
redis_exporter_redact_config_metrics:
description: "Whether to redact config settings that include potentially sensitive information like passwords."
type: bool
default: false
redis_exporter_ping_on_connect:
description: "Whether to ping the redis instance after connecting and record the duration as a metric."
type: bool
default: false
redis_exporter_is_tile38:
description: "Whether to scrape Tile38 specific metrics"
type: bool
default: false
redis_exporter_is_cluster:
description: "Whether this is a redis cluster (Enable this if you need to fetch key level data on a Redis Cluster)."
type: bool
default: false
redis_exporter_export_client_list:
description: "Whether to scrape Client List specific metrics"
type: bool
default: false
redis_exporter_export_client_port:
description: "Whether to include the client's port when exporting the client list. Warning: including the port increases the number of metrics generated and will make your Prometheus server take up more memory"
type: bool
default: false
redis_exporter_skip_tls_verification:
description: "Whether to to skip TLS verification when the exporter connects to a Redis instance"
type: bool
default: false
redis_exporter_tls_client_key_file:
description: "Name of the client key file (including full path) if the server requires TLS client authentication"
default: ""
redis_exporter_tls_client_cert_file:
description: "Name the client cert file (including full path) if the server requires TLS client authentication"
default: ""
redis_exporter_tls_server_key_file:
description: "Name of the server key file (including full path) if the web interface and telemetry should use TLS"
default: ""
redis_exporter_tls_server_cert_file:
description: "Name of the server certificate file (including full path) if the web interface and telemetry should use TLS"
default: ""
redis_exporter_tls_server_ca_cert_file:
description: "Name of the CA certificate file (including full path) if the web interface and telemetry should use TLS"
default: ""
redis_exporter_tls_server_min_version:
description: "Minimum TLS version that is acceptable by the web interface and telemetry when using TLS"
default: "TLS1.2"
redis_exporter_tls_ca_cert_file:
description: "Name of the CA certificate file (including full path) if the server requires TLS client authentication"
default: ""
redis_exporter_set_client_name:
description: "Whether to set client name to redis_exporter"
type: bool
default: true
redis_exporter_check_key_groups:
description: "List of LUA regexes for classifying keys into groups. The regexes are applied in specified order to individual keys, and the group name is generated by concatenating all capture groups of the first regex that matches a key. A key will be tracked under the unclassified group if none of the specified regexes matches it."
type: "list"
default: []
redis_exporter_max_distinct_key_groups:
description: "Maximum number of distinct key groups that can be tracked independently per Redis database. If exceeded, only key groups with the highest memory consumption within the limit will be tracked separately, all remaining key groups will be tracked under a single overflow key group."
type: "int"
default: 100
redis_exporter_config_command:
description: "What to use for the CONFIG command"
default: "CONFIG"
redis_exporter_binary_install_dir:
description:
- "I(Advanced)"
- "Directory to install redis_exporter binary"
default: "/usr/local/bin"
redis_exporter_system_group:
description:
- "I(Advanced)"
- "System group for redis_exporter"
default: "redis-exp"
redis_exporter_system_user:
description:
- "I(Advanced)"
- "redis_exporter user"
default: "redis-exp"

View file

@ -0,0 +1,31 @@
---
galaxy_info:
author: "Prometheus Community"
description: "Prometheus redis_exporter"
license: "Apache"
min_ansible_version: "2.9"
platforms:
- name: "Ubuntu"
versions:
- "focal"
- "jammy"
- name: "Debian"
versions:
- "bullseye"
- "buster"
- name: "EL"
versions:
- "7"
- "8"
- "9"
- name: "Fedora"
versions:
- "37"
- '38'
galaxy_tags:
- "monitoring"
- "prometheus"
- "exporter"
- "metrics"
- "system"
- "redis"

View file

@ -0,0 +1,13 @@
---
provisioner:
inventory:
group_vars:
all:
redis_exporter_binary_local_dir: "/tmp/redis_exporter-linux-amd64"
redis_exporter_web_listen_address: "127.0.0.1:8080"
redis_exporter_tls_server_ca_cert_file: /etc/redis_exporter/tls.cert
redis_exporter_tls_server_cert_file: /etc/redis_exporter/tls.cert
redis_exporter_tls_server_key_file: /etc/redis_exporter/tls.key
go_arch: amd64
redis_exporter_version: 1.58.0

View file

@ -0,0 +1,78 @@
---
- name: Run local preparation
hosts: localhost
gather_facts: false
tasks:
- name: Download redis_exporter binary to local folder
become: false
ansible.builtin.get_url:
url: "https://github.com/oliver006/redis_exporter/releases/download/v{{\
\ redis_exporter_version }}/redis_exporter-v{{ redis_exporter_version }}.linux-{{\
\ go_arch }}.tar.gz"
dest: "/tmp/redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
mode: 0644
register: _download_binary
until: _download_binary is succeeded
retries: 5
delay: 2
check_mode: false
- name: Unpack redis_exporter binary
become: false
ansible.builtin.unarchive:
src: "/tmp/redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
dest: "/tmp"
creates: "/tmp/redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch\
\ }}/redis_exporter"
check_mode: false
- name: Link to redis_exporter binaries directory
become: false
ansible.builtin.file:
src: "/tmp/redis_exporter-v{{ redis_exporter_version }}.linux-amd64"
dest: "/tmp/redis_exporter-linux-amd64"
state: link
check_mode: false
- name: Install pyOpenSSL for certificate generation
ansible.builtin.pip:
name: "pyOpenSSL"
- name: Create private key
community.crypto.openssl_privatekey:
path: "/tmp/tls.key"
- name: Create CSR
community.crypto.openssl_csr:
path: "/tmp/tls.csr"
privatekey_path: "/tmp/tls.key"
- name: Create certificate
community.crypto.x509_certificate:
path: "/tmp/tls.cert"
csr_path: "/tmp/tls.csr"
privatekey_path: "/tmp/tls.key"
provider: selfsigned
- name: Run target preparation
hosts: all
any_errors_fatal: true
tasks:
- name: Create redis_exporter cert dir
ansible.builtin.file:
path: "{{ redis_exporter_tls_server_cert_file | dirname }}"
state: directory
owner: root
group: root
mode: u+rwX,g+rwX,o=rX
- name: Copy cert and key
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode | default('0644') }}"
loop:
- src: "/tmp/tls.cert"
dest: "{{ redis_exporter_tls_server_cert_file }}"
- src: "/tmp/tls.key"
dest: "{{ redis_exporter_tls_server_key_file }}"

View file

@ -0,0 +1,46 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_directories(host):
dirs = [
"/etc/redis_exporter"
]
for dir in dirs:
d = host.file(dir)
assert d.is_directory
assert d.exists
def test_service(host):
s = host.service("redis_exporter")
try:
assert s.is_running
except AssertionError:
# Capture service logs
journal_output = host.run('journalctl -u redis_exporter --since "1 hour ago"')
print("\n==== journalctl -u redis_exporter Output ====\n")
print(journal_output)
print("\n============================================\n")
raise # Re-raise the original assertion error
def test_protecthome_property(host):
s = host.service("redis_exporter")
p = s.systemd_properties
assert p.get("ProtectHome") == "yes"
def test_socket(host):
sockets = [
"tcp://127.0.0.1:8080"
]
for socket in sockets:
s = host.socket(socket)
assert s.is_listening

View file

@ -0,0 +1,6 @@
---
provisioner:
inventory:
group_vars:
all:
redis_exporter_web_listen_address: "127.0.0.1:9121"

View file

@ -0,0 +1,64 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_directories(host):
dirs = [
"/etc/redis_exporter"
]
for dir in dirs:
d = host.file(dir)
assert d.is_directory
assert d.exists
def test_files(host):
files = [
"/etc/systemd/system/redis_exporter.service",
"/usr/local/bin/redis_exporter"
]
for file in files:
f = host.file(file)
assert f.exists
assert f.is_file
def test_user(host):
assert host.group("redis-exp").exists
assert "redis-exp" in host.user("redis-exp").groups
assert host.user("redis-exp").shell == "/usr/sbin/nologin"
assert host.user("redis-exp").home == "/"
def test_service(host):
s = host.service("redis_exporter")
try:
assert s.is_running
except AssertionError:
# Capture service logs
journal_output = host.run('journalctl -u redis_exporter --since "1 hour ago"')
print("\n==== journalctl -u redis_exporter Output ====\n")
print(journal_output)
print("\n============================================\n")
raise # Re-raise the original assertion error
def test_protecthome_property(host):
s = host.service("redis_exporter")
p = s.systemd_properties
assert p.get("ProtectHome") == "yes"
def test_socket(host):
sockets = [
"tcp://127.0.0.1:9121"
]
for socket in sockets:
s = host.socket(socket)
assert s.is_listening

View file

@ -0,0 +1,6 @@
---
provisioner:
inventory:
group_vars:
all:
redis_exporter_version: latest

View file

@ -0,0 +1,43 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import testinfra.utils.ansible_runner
import pytest
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
@pytest.mark.parametrize("files", [
"/etc/systemd/system/redis_exporter.service",
"/usr/local/bin/redis_exporter"
])
def test_files(host, files):
f = host.file(files)
assert f.exists
assert f.is_file
def test_service(host):
s = host.service("redis_exporter")
try:
assert s.is_running
except AssertionError:
# Capture service logs
journal_output = host.run('journalctl -u redis_exporter --since "1 hour ago"')
print("\n==== journalctl -u redis_exporter Output ====\n")
print(journal_output)
print("\n============================================\n")
raise # Re-raise the original assertion error
def test_protecthome_property(host):
s = host.service("redis_exporter")
p = s.systemd_properties
assert p.get("ProtectHome") == "yes"
def test_socket(host):
s = host.socket("tcp://0.0.0.0:9121")
assert s.is_listening

View file

@ -0,0 +1,37 @@
---
- name: Copy the redis_exporter systemd service file
ansible.builtin.template:
src: redis_exporter.service.j2
dest: /etc/systemd/system/redis_exporter.service
owner: root
group: root
mode: 0644
notify: restart redis_exporter
- name: Create redis_exporter config directory
ansible.builtin.file:
path: "/etc/redis_exporter"
state: directory
owner: root
group: root
mode: u+rwX,g+rwX,o=rX
- name: Copy the passwords file
ansible.builtin.copy:
dest: /etc/redis_exporter/passwords.json
content: "{{ redis_exporter_passwords | to_json(indent=2, sort_keys=True) }}"
owner: root
group: root
mode: 0644
notify: restart redis_exporter
when: redis_exporter_passwords | length > 0
- name: Allow redis_exporter port in SELinux on RedHat OS family
community.general.seport:
ports: "{{ redis_exporter_web_listen_address.split(':')[-1] }}"
proto: tcp
setype: http_port_t
state: present
when:
- ansible_version.full is version_compare('2.4', '>=')
- ansible_selinux.status == "enabled"

View file

@ -0,0 +1,69 @@
---
- name: Create the redis_exporter group
ansible.builtin.group:
name: "{{ redis_exporter_system_group }}"
state: present
system: true
when: redis_exporter_system_group != "root"
- name: Create the redis_exporter user
ansible.builtin.user:
name: "{{ redis_exporter_system_user }}"
groups: "{{ redis_exporter_system_group }}"
append: true
shell: /usr/sbin/nologin
system: true
create_home: false
home: /
when: redis_exporter_system_user != "root"
- name: Get binary
when:
- redis_exporter_binary_local_dir | length == 0
- not redis_exporter_skip_install
block:
- name: Download redis_exporter binary to local folder
become: false
ansible.builtin.get_url:
url: "{{ redis_exporter_binary_url }}"
dest: "/tmp/redis_exporter-{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
checksum: "sha256:{{ __redis_exporter_checksum }}"
mode: '0644'
register: _download_binary
until: _download_binary is succeeded
retries: 5
delay: 2
delegate_to: localhost
check_mode: false
- name: Unpack redis_exporter binary
become: false
ansible.builtin.unarchive:
src: "/tmp/redis_exporter-{{ redis_exporter_version }}.linux-{{ go_arch }}.tar.gz"
dest: "/tmp"
creates: "/tmp/redis_exporter-{{ redis_exporter_version }}.linux-{{ go_arch }}/redis_exporter"
delegate_to: localhost
check_mode: false
- name: Propagate redis_exporter binaries
ansible.builtin.copy:
src: "/tmp/redis_exporter-v{{ redis_exporter_version }}.linux-{{ go_arch }}/redis_exporter"
dest: "{{ redis_exporter_binary_install_dir }}/redis_exporter"
mode: 0755
owner: root
group: root
notify: restart redis_exporter
when: not ansible_check_mode
- name: Propagate locally distributed redis_exporter binary
ansible.builtin.copy:
src: "{{ redis_exporter_binary_local_dir }}/redis_exporter"
dest: "{{ redis_exporter_binary_install_dir }}/redis_exporter"
mode: 0755
owner: root
group: root
when:
- redis_exporter_binary_local_dir | length > 0
- not redis_exporter_skip_install
notify: restart redis_exporter

View file

@ -0,0 +1,63 @@
---
- name: Preflight
ansible.builtin.include_tasks:
file: preflight.yml
apply:
tags:
- redis_exporter_install
- redis_exporter_configure
- redis_exporter_run
tags:
- redis_exporter_install
- redis_exporter_configure
- redis_exporter_run
- name: Install
ansible.builtin.include_tasks:
file: install.yml
apply:
become: true
tags:
- redis_exporter_install
when:
( not __redis_exporter_is_installed.stat.exists ) or
( (__redis_exporter_current_version_output.stderr_lines | length > 0)
and (__redis_exporter_current_version_output.stderr_lines[0].split(" ")[2] != redis_exporter_version) ) or
( (__redis_exporter_current_version_output.stdout_lines | length > 0)
and (__redis_exporter_current_version_output.stdout_lines[0].split(" ")[2] != redis_exporter_version) ) or
( redis_exporter_binary_local_dir | length > 0 )
tags:
- redis_exporter_install
- name: SELinux
ansible.builtin.include_tasks:
file: selinux.yml
apply:
become: true
tags:
- redis_exporter_configure
when: ansible_selinux.status == "enabled"
tags:
- redis_exporter_configure
- name: Configure
ansible.builtin.include_tasks:
file: configure.yml
apply:
become: true
tags:
- redis_exporter_configure
tags:
- redis_exporter_configure
- name: Ensure redis_exporter is enabled on boot
become: true
ansible.builtin.systemd:
daemon_reload: true
name: redis_exporter
enabled: true
state: started
when:
- not ansible_check_mode
tags:
- redis_exporter_run

View file

@ -0,0 +1,112 @@
---
- name: Assert usage of systemd as an init system
ansible.builtin.assert:
that: ansible_service_mgr == 'systemd'
msg: "This role only works with systemd"
- name: Install package fact dependencies
become: true
ansible.builtin.package:
name: "{{ _pkg_fact_req }}"
state: present
when: (_pkg_fact_req)
vars:
_pkg_fact_req: "{% if (ansible_pkg_mgr == 'apt') %}\
{{ ('python-apt' if ansible_python_version is version('3', '<') else 'python3-apt') }}
{% else %}\
{% endif %}"
- name: Gather package facts
ansible.builtin.package_facts:
when: "not 'packages' in ansible_facts"
- name: Assert that used version supports listen address type
ansible.builtin.assert:
that:
- >-
redis_exporter_web_listen_address is string
- name: Naive assertion of proper listen address
ansible.builtin.assert:
that:
- >-
[redis_exporter_web_listen_address] |
flatten |
reject('match', '.+:\\d+$') |
list |
length == 0
- name: Assert that TLS config is correct
when:
- redis_exporter_tls_server_key_file | length > 0
- redis_exporter_tls_server_cert_file | length > 0
block:
- name: Assert that TLS key and cert path are set
ansible.builtin.assert:
that:
- "redis_exporter_tls_server_cert_file is defined"
- "redis_exporter_tls_server_key_file is defined"
- name: Check existence of TLS cert file
ansible.builtin.stat:
path: "{{ redis_exporter_tls_server_cert_file }}"
register: __redis_exporter_cert_file
- name: Check existence of TLS key file
ansible.builtin.stat:
path: "{{ redis_exporter_tls_server_key_file }}"
register: __redis_exporter_key_file
- name: Assert that TLS key and cert are present
ansible.builtin.assert:
that:
- "__redis_exporter_cert_file.stat.exists"
- "__redis_exporter_key_file.stat.exists"
- name: Check if redis_exporter is installed
ansible.builtin.stat:
path: "{{ redis_exporter_binary_install_dir }}/redis_exporter"
register: __redis_exporter_is_installed
check_mode: false
tags:
- redis_exporter_install
- name: Gather currently installed redis_exporter version (if any)
ansible.builtin.command: "{{ redis_exporter_binary_install_dir }}/redis_exporter --version"
changed_when: false
register: __redis_exporter_current_version_output
check_mode: false
when: __redis_exporter_is_installed.stat.exists
tags:
- redis_exporter_install
- name: Discover latest version
ansible.builtin.set_fact:
redis_exporter_version: "{{ (lookup('url', 'https://api.github.com/repos/{{ _redis_exporter_repo }}/releases/latest', headers=_github_api_headers,
split_lines=False) | from_json).get('tag_name') | replace('v', '') }}"
run_once: true
until: redis_exporter_version is version('0.0.0', '>=')
retries: 10
when:
- redis_exporter_version == "latest"
- redis_exporter_binary_local_dir | length == 0
- not redis_exporter_skip_install
- name: Get redis_exporter binary checksum
when:
- redis_exporter_binary_local_dir | length == 0
- not redis_exporter_skip_install
block:
- name: Get checksum list from github
ansible.builtin.set_fact:
__redis_exporter_checksums: "{{ lookup('url', redis_exporter_checksums_url, headers=_github_api_headers, wantlist=True) | list }}"
run_once: true
until: __redis_exporter_checksums is search('linux-' + go_arch + '.tar.gz')
retries: 10
- name: "Get checksum for {{ go_arch }}"
ansible.builtin.set_fact:
__redis_exporter_checksum: "{{ item.split(' ')[0] }}"
with_items: "{{ __redis_exporter_checksums }}"
when:
- "('linux-' + go_arch + '.tar.gz') in item"

View file

@ -0,0 +1,23 @@
---
- 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: _install_selinux_packages
until: _install_selinux_packages is success
retries: 5
delay: 2
when: ansible_os_family | lower == "redhat"
- name: Install selinux python packages [clearlinux]
ansible.builtin.package:
name: sysadmin-basic
state: present
register: _install_selinux_packages
until: _install_selinux_packages is success
retries: 5
delay: 2
when:
- ansible_distribution | lower == "clearlinux"

View file

@ -0,0 +1,73 @@
{{ ansible_managed | comment }}
[Unit]
Description=Prometheus redis_exporter
After=network-online.target
[Service]
Type=simple
User={{ redis_exporter_system_user }}
Group={{ redis_exporter_system_group }}
Environment="REDIS_ADDR={{ redis_exporter_addr }}"
Environment="REDIS_USER={{ redis_exporter_user }}"
Environment="REDIS_PASSWORD={{ redis_exporter_password }}"
{% if redis_exporter_passwords | length > 0 -%}
Environment="REDIS_PASSWORD_FILE=/etc/redis_exporter/passwords.json"
{% endif -%}
Environment="REDIS_EXPORTER_CHECK_KEYS={{ redis_exporter_check_keys | join(',') }}"
Environment="REDIS_EXPORTER_CHECK_SINGLE_KEYS={{ redis_exporter_check_single_keys | join(',') }}"
Environment="REDIS_EXPORTER_CHECK_STREAMS={{ redis_exporter_check_streams | join(',') }}"
Environment="REDIS_EXPORTER_CHECK_SINGLE_STREAMS={{ redis_exporter_check_single_streams | join(',') }}"
Environment="REDIS_EXPORTER_CHECK_KEYS_BATCH_SIZE={{ redis_exporter_check_keys_batch_size }}"
Environment="REDIS_EXPORTER_COUNT_KEYS={{ redis_exporter_count_keys | join(',') }}"
Environment="REDIS_EXPORTER_SCRIPT={{ redis_exporter_script | join(',') }}"
Environment="REDIS_EXPORTER_DEBUG={{ redis_exporter_debug }}"
Environment="REDIS_EXPORTER_LOG_FORMAT={{ redis_exporter_log_format }}"
Environment="REDIS_EXPORTER_NAMESPACE={{ redis_exporter_namespace }}"
Environment="REDIS_EXPORTER_CONNECTION_TIMEOUT={{ redis_exporter_connection_timeout }}"
Environment="REDIS_EXPORTER_WEB_LISTEN_ADDRESS={{ redis_exporter_web_listen_address }}"
Environment="REDIS_EXPORTER_WEB_TELEMETRY_PATH={{ redis_exporter_web_telemetry_path }}"
Environment="REDIS_EXPORTER_REDIS_ONLY_METRICS={{ redis_exporter_redis_only_metrics }}"
Environment="REDIS_EXPORTER_INCL_CONFIG_METRICS={{ redis_exporter_incl_config_metrics }}"
Environment="REDIS_EXPORTER_INCL_SYSTEM_METRICS={{ redis_exporter_incl_system_metrics }}"
Environment="REDIS_EXPORTER_REDACT_CONFIG_METRICS={{ redis_exporter_redact_config_metrics }}"
Environment="REDIS_EXPORTER_PING_ON_CONNECT={{ redis_exporter_ping_on_connect }}"
Environment="REDIS_EXPORTER_IS_TILE38={{ redis_exporter_is_tile38 }}"
Environment="REDIS_EXPORTER_IS_CLUSTER={{ redis_exporter_is_cluster }}"
Environment="REDIS_EXPORTER_EXPORT_CLIENT_LIST={{ redis_exporter_export_client_list }}"
Environment="REDIS_EXPORTER_EXPORT_CLIENT_PORT={{ redis_exporter_export_client_port }}"
Environment="REDIS_EXPORTER_SKIP_TLS_VERIFICATION={{ redis_exporter_skip_tls_verification }}"
Environment="REDIS_EXPORTER_TLS_CLIENT_KEY_FILE={{ redis_exporter_tls_client_key_file }}"
Environment="REDIS_EXPORTER_TLS_CLIENT_CERT_FILE={{ redis_exporter_tls_client_cert_file }}"
Environment="REDIS_EXPORTER_TLS_SERVER_KEY_FILE={{ redis_exporter_tls_server_key_file }}"
Environment="REDIS_EXPORTER_TLS_SERVER_CERT_FILE={{ redis_exporter_tls_server_cert_file }}"
Environment="REDIS_EXPORTER_TLS_SERVER_CA_CERT_FILE={{ redis_exporter_tls_server_ca_cert_file }}"
Environment="REDIS_EXPORTER_TLS_SERVER_MIN_VERSION={{ redis_exporter_tls_server_min_version }}"
Environment="REDIS_EXPORTER_TLS_CA_CERT_FILE={{ redis_exporter_tls_ca_cert_file }}"
Environment="REDIS_EXPORTER_SET_CLIENT_NAME={{ redis_exporter_set_client_name }}"
Environment="REDIS_EXPORTER_CHECK_KEY_GROUPS={{ redis_exporter_check_key_groups | join(',') }}"
Environment="REDIS_EXPORTER_MAX_DISTINCT_KEY_GROUPS={{ redis_exporter_max_distinct_key_groups }}"
Environment="REDIS_EXPORTER_CONFIG_COMMAND={{ redis_exporter_config_command }}"
ExecStart={{ redis_exporter_binary_install_dir }}/redis_exporter
SyslogIdentifier=redis_exporter
Restart=always
RestartSec=1
StartLimitInterval=0
ProtectHome=yes
NoNewPrivileges=yes
{% if (ansible_facts.packages.systemd | first).version is version('232', '>=') %}
ProtectSystem=strict
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=yes
{% else %}
ProtectSystem=full
{% endif %}
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,11 @@
---
go_arch_map:
i386: '386'
x86_64: 'amd64'
aarch64: 'arm64'
armv7l: 'armv7'
armv6l: 'armv6'
go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}"
_redis_exporter_repo: "oliver006/redis_exporter"
_github_api_headers: "{{ {'GITHUB_TOKEN': lookup('ansible.builtin.env', 'GITHUB_TOKEN')} if (lookup('ansible.builtin.env', 'GITHUB_TOKEN')) else {} }}"

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+")
source "$collection_root/tests/integration/molecule.sh"

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+")
source "$collection_root/tests/integration/molecule.sh"

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+")
source "$collection_root/tests/integration/molecule.sh"