From 4c2902f20971ea4d5513151f3b18a4ffdef409bb Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 23 Feb 2024 00:39:05 +0000 Subject: [PATCH 01/20] feat: add process_exporter role Signed-off-by: gardar --- roles/process_exporter/README.md | 51 +++++++++++++ roles/process_exporter/defaults/main.yml | 24 ++++++ roles/process_exporter/handlers/main.yml | 8 ++ roles/process_exporter/meta/main.yml | 30 ++++++++ .../molecule/default/molecule.yml | 1 + .../molecule/default/tests/test_default.py | 48 ++++++++++++ roles/process_exporter/tasks/configure.yml | 40 ++++++++++ roles/process_exporter/tasks/install.yml | 69 ++++++++++++++++++ roles/process_exporter/tasks/main.yml | 56 ++++++++++++++ roles/process_exporter/tasks/preflight.yml | 73 +++++++++++++++++++ roles/process_exporter/tasks/selinux.yml | 23 ++++++ .../templates/process_exporter.service.j2 | 23 ++++++ roles/process_exporter/vars/main.yml | 11 +++ .../runme.sh | 4 + 14 files changed, 461 insertions(+) create mode 100644 roles/process_exporter/README.md create mode 100644 roles/process_exporter/defaults/main.yml create mode 100644 roles/process_exporter/handlers/main.yml create mode 100644 roles/process_exporter/meta/main.yml create mode 100644 roles/process_exporter/molecule/default/molecule.yml create mode 100644 roles/process_exporter/molecule/default/tests/test_default.py create mode 100644 roles/process_exporter/tasks/configure.yml create mode 100644 roles/process_exporter/tasks/install.yml create mode 100644 roles/process_exporter/tasks/main.yml create mode 100644 roles/process_exporter/tasks/preflight.yml create mode 100644 roles/process_exporter/tasks/selinux.yml create mode 100644 roles/process_exporter/templates/process_exporter.service.j2 create mode 100644 roles/process_exporter/vars/main.yml create mode 100755 tests/integration/targets/molecule-process_exporter-default/runme.sh diff --git a/roles/process_exporter/README.md b/roles/process_exporter/README.md new file mode 100644 index 000000000..483108252 --- /dev/null +++ b/roles/process_exporter/README.md @@ -0,0 +1,51 @@ +# Ansible Role: process_exporter + +[![Build Status](https://travis-ci.com/cloudalchemy/ansible-process_exporter.svg?branch=master)](https://travis-ci.com/cloudalchemy/ansible-process_exporter) +[![License](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg)](https://opensource.org/licenses/MIT) +[![Ansible Role](https://img.shields.io/badge/ansible%20role-cloudalchemy.process_exporter-blue.svg)](https://galaxy.ansible.com/cloudalchemy/process_exporter/) +[![GitHub tag](https://img.shields.io/github/tag/cloudalchemy/ansible-process_exporter.svg)](https://github.com/cloudalchemy/ansible-process_exporter/tags) + +## Description + +Deploy [process-exporter](https://github.com/ncabatoff/process-exporter) using ansible. + +Note. This repository and role uses the name process_exporter to conform with ansible galaxy constraints. + +## Requirements + +- Ansible >= 2.9 (It might work on previous versions, but we cannot guarantee it) + +## Role Variables + +All variables which can be overridden are stored in [defaults/main.yml](defaults/main.yml) file as well as in table below. + +| Name | Default Value | Description | +| -------------- | ------------- | -----------------------------------| +| `process_exporter_version` | 0.7.5 | Process exporter package version. Also accepts latest as parameter | +| `process_exporter_web_listen_address` | "0.0.0.0:9256" | Address on which process_exporter will listen | +| `process_exporter_config_dir` | "/etc/process_exporter" | Path to directory with process_exporter configuration | +`process_exporter_names` handling has been set up in an unusual way to handle recommended process-exporter 'Template variables' (such as {{.Comm}}). Follow the example in [defaults/main.yml](defaults/main.yml) if you want to define custom filtering/grouping of processes that use Template variables and make sure to keep the {% raw %} block delimiters. + +## Example + +### Playbook + +Use it in a playbook as follows: +```yaml +- hosts: all + roles: + - prometheus.prometheus.process_exporter +``` + + +## 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. diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml new file mode 100644 index 000000000..47c22fc25 --- /dev/null +++ b/roles/process_exporter/defaults/main.yml @@ -0,0 +1,24 @@ +--- +process_exporter_version: 0.7.5 +process_exporter_binary_local_dir: "" +process_exporter_binary_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/\ + process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" +process_exporter_checksums_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/sha256sums.txt" +process_exporter_skip_install: false + + +process_exporter_web_listen_address: "0.0.0.0:9256" + +# Process names +# "raw" section is needed to avoid attempted interpretation +# of process-exporter Template varables (like {{.Comm}}) +process_exporter_names: | + {% raw %} + - name: "{{.Comm}}" + cmdline: + - '.+' + {% endraw %} + +process_exporter_binary_install_dir: "/usr/local/bin" +process_exporter_system_group: "process-exp" +process_exporter_system_user: "{{ process_exporter_system_group }}" diff --git a/roles/process_exporter/handlers/main.yml b/roles/process_exporter/handlers/main.yml new file mode 100644 index 000000000..7b17604f9 --- /dev/null +++ b/roles/process_exporter/handlers/main.yml @@ -0,0 +1,8 @@ +--- +- name: Restart process_exporter + listen: "restart process_exporter" + become: true + ansible.builtin.systemd: + daemon_reload: true + name: process_exporter + state: restarted diff --git a/roles/process_exporter/meta/main.yml b/roles/process_exporter/meta/main.yml new file mode 100644 index 000000000..5c89712fa --- /dev/null +++ b/roles/process_exporter/meta/main.yml @@ -0,0 +1,30 @@ +--- +galaxy_info: + author: "Prometheus Community" + description: "Prometheus Process 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" diff --git a/roles/process_exporter/molecule/default/molecule.yml b/roles/process_exporter/molecule/default/molecule.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/roles/process_exporter/molecule/default/molecule.yml @@ -0,0 +1 @@ +--- diff --git a/roles/process_exporter/molecule/default/tests/test_default.py b/roles/process_exporter/molecule/default/tests/test_default.py new file mode 100644 index 000000000..6d2130997 --- /dev/null +++ b/roles/process_exporter/molecule/default/tests/test_default.py @@ -0,0 +1,48 @@ +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/process_exporter" + ] + for dir in dirs: + d = host.file(dir) + assert d.is_directory + assert d.exists + + +def test_files(host): + files = [ + "/etc/systemd/system/process_exporter.service", + "/usr/local/bin/process_exporter", + ] + for file in files: + f = host.file(file) + assert f.exists + assert f.is_file + + +def test_user(host): + assert host.group("process-exp").exists + assert "process-exp" in host.user("process-exp").groups + assert host.user("process-exp").shell == "/usr/sbin/nologin" + assert host.user("process-exp").home == "/" + + +def test_service(host): + s = host.service("process_exporter") +# assert s.is_enabled + assert s.is_running + + +def test_socket(host): + sockets = [ + "tcp://0.0.0.0:9256" + ] + for socket in sockets: + s = host.socket(socket) + assert s.is_listening diff --git a/roles/process_exporter/tasks/configure.yml b/roles/process_exporter/tasks/configure.yml new file mode 100644 index 000000000..e3acf1eb7 --- /dev/null +++ b/roles/process_exporter/tasks/configure.yml @@ -0,0 +1,40 @@ +--- +- name: Copy the process_exporter systemd service file + ansible.builtin.template: + src: process_exporter.service.j2 + dest: /etc/systemd/system/process_exporter.service + owner: root + group: root + mode: 0644 + notify: restart process_exporter + +- name: Create process_exporter config directory + ansible.builtin.file: + path: "/etc/process_exporter" + state: directory + owner: root + group: root + mode: u+rwX,g+rwX,o=rX + +- name: Create/Update configuration file + ansible.builtin.copy: + dest: "/etc/process_exporter/config.yml" + content: | + process_names: + {{ process_exporter_names }} + owner: root + group: root + mode: 0644 + when: + - process_exporter_names != [] + notify: restart process_exporter + +- name: Allow process_exporter port in SELinux on RedHat OS family + community.general.seport: + ports: "{{ process_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" diff --git a/roles/process_exporter/tasks/install.yml b/roles/process_exporter/tasks/install.yml new file mode 100644 index 000000000..7af968284 --- /dev/null +++ b/roles/process_exporter/tasks/install.yml @@ -0,0 +1,69 @@ +--- +- name: Create the process_exporter group + ansible.builtin.group: + name: "{{ process_exporter_system_group }}" + state: present + system: true + when: process_exporter_system_group != "root" + +- name: Create the process_exporter user + ansible.builtin.user: + name: "{{ process_exporter_system_user }}" + groups: "{{ process_exporter_system_group }}" + append: true + shell: /usr/sbin/nologin + system: true + create_home: false + home: / + when: process_exporter_system_user != "root" + +- name: Get binary + when: + - process_exporter_binary_local_dir | length == 0 + - not process_exporter_skip_install + block: + + - name: Download process_exporter binary to local folder + become: false + ansible.builtin.get_url: + url: "{{ process_exporter_binary_url }}" + dest: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + checksum: "sha256:{{ __process_exporter_checksum }}" + mode: '0644' + register: _download_binary + until: _download_binary is succeeded + retries: 5 + delay: 2 + delegate_to: localhost + check_mode: false + + - name: Unpack process_exporter binary + become: false + ansible.builtin.unarchive: + src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + dest: "/tmp" + creates: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process_exporter" + delegate_to: localhost + check_mode: false + + - name: Propagate process_exporter binaries + ansible.builtin.copy: + src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process_exporter" + dest: "{{ process_exporter_binary_install_dir }}/process_exporter" + mode: 0755 + owner: root + group: root + notify: restart process_exporter + when: not ansible_check_mode + +- name: Propagate locally distributed process_exporter binary + ansible.builtin.copy: + src: "{{ process_exporter_binary_local_dir }}/process_exporter" + dest: "{{ process_exporter_binary_install_dir }}/process_exporter" + mode: 0755 + owner: root + group: root + when: + - process_exporter_binary_local_dir | length > 0 + - not process_exporter_skip_install + notify: restart process_exporter diff --git a/roles/process_exporter/tasks/main.yml b/roles/process_exporter/tasks/main.yml new file mode 100644 index 000000000..44ee66d6a --- /dev/null +++ b/roles/process_exporter/tasks/main.yml @@ -0,0 +1,56 @@ +--- +- name: Preflight + ansible.builtin.include_tasks: + file: preflight.yml + apply: + tags: + - process_exporter_install + - process_exporter_configure + - process_exporter_run + tags: + - process_exporter_install + - process_exporter_configure + - process_exporter_run + +- name: Install + ansible.builtin.include_tasks: + file: install.yml + apply: + become: true + tags: + - process_exporter_install + tags: + - process_exporter_install + +- name: SELinux + ansible.builtin.include_tasks: + file: selinux.yml + apply: + become: true + tags: + - process_exporter_configure + when: ansible_selinux.status == "enabled" + tags: + - process_exporter_configure + +- name: Configure + ansible.builtin.include_tasks: + file: configure.yml + apply: + become: true + tags: + - process_exporter_configure + tags: + - process_exporter_configure + +- name: Ensure process_exporter is enabled on boot + become: true + ansible.builtin.systemd: + daemon_reload: true + name: process_exporter + enabled: true + state: started + when: + - not ansible_check_mode + tags: + - process_exporter_run diff --git a/roles/process_exporter/tasks/preflight.yml b/roles/process_exporter/tasks/preflight.yml new file mode 100644 index 000000000..77bb34735 --- /dev/null +++ b/roles/process_exporter/tasks/preflight.yml @@ -0,0 +1,73 @@ +--- +- 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: Naive assertion of proper listen address + ansible.builtin.assert: + that: + - "':' in process_exporter_web_listen_address" + +- name: Check if process_exporter is installed + ansible.builtin.stat: + path: "{{ process_exporter_binary_install_dir }}/process_exporter" + register: __process_exporter_is_installed + check_mode: false + tags: + - process_exporter_install + +- name: Gather currently installed process_exporter version (if any) + ansible.builtin.command: "{{ process_exporter_binary_install_dir }}/process_exporter --version" + changed_when: false + register: __process_exporter_current_version_output + check_mode: false + when: __process_exporter_is_installed.stat.exists + tags: + - process_exporter_install + +- name: Discover latest version + ansible.builtin.set_fact: + process_exporter_version: "{{ (lookup('url', 'https://api.github.com/repos/{{ _process_exporter_repo }}/releases/latest', headers=_github_api_headers, + split_lines=False) | from_json).get('tag_name') | replace('v', '') }}" + run_once: true + until: process_exporter_version is version('0.0.0', '>=') + retries: 10 + when: + - process_exporter_version == "latest" + - process_exporter_binary_local_dir | length == 0 + - not process_exporter_skip_install + +- name: Get process_exporter binary checksum + when: + - process_exporter_binary_local_dir | length == 0 + - not process_exporter_skip_install + block: + - name: Get checksum list from github + ansible.builtin.set_fact: + __process_exporter_checksums: "{{ lookup('url', process_exporter_checksums_url, headers=_github_api_headers, wantlist=True) | list }}" + run_once: true + until: __process_exporter_checksums is search('linux-' + go_arch + '.tar.gz') + retries: 10 + + - name: "Get checksum for {{ go_arch }}" + ansible.builtin.set_fact: + __process_exporter_checksum: "{{ item.split(' ')[0] }}" + with_items: "{{ __process_exporter_checksums }}" + when: "('linux-' + go_arch + '.tar.gz') in item" diff --git a/roles/process_exporter/tasks/selinux.yml b/roles/process_exporter/tasks/selinux.yml new file mode 100644 index 000000000..754cbd0a2 --- /dev/null +++ b/roles/process_exporter/tasks/selinux.yml @@ -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" diff --git a/roles/process_exporter/templates/process_exporter.service.j2 b/roles/process_exporter/templates/process_exporter.service.j2 new file mode 100644 index 000000000..977a760b3 --- /dev/null +++ b/roles/process_exporter/templates/process_exporter.service.j2 @@ -0,0 +1,23 @@ +{{ ansible_managed | comment }} + +[Unit] +Description=Prometheus Process Exporter +After=network-online.target + +[Service] +Type=simple +User={{ process_exporter_system_user }} +Group={{ process_exporter_system_group }} +ExecStart={{ process_exporter_binary_install_dir/process_exporter \ +{% if process_exporter_names != [] -%} + '--config.path=/etc/process_exporter/config.yml' \ +{% endif -%} + '--web.listen-address={{ process_exporter_web_listen_address }}' + +SyslogIdentifier=process_exporter +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/roles/process_exporter/vars/main.yml b/roles/process_exporter/vars/main.yml new file mode 100644 index 000000000..0a6b669b8 --- /dev/null +++ b/roles/process_exporter/vars/main.yml @@ -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) }}" +_process_exporter_repo: "ncabatoff/process_exporter" +_github_api_headers: "{{ {'GITHUB_TOKEN': lookup('ansible.builtin.env', 'GITHUB_TOKEN')} if (lookup('ansible.builtin.env', 'GITHUB_TOKEN')) else {} }}" diff --git a/tests/integration/targets/molecule-process_exporter-default/runme.sh b/tests/integration/targets/molecule-process_exporter-default/runme.sh new file mode 100755 index 000000000..d094c3e1b --- /dev/null +++ b/tests/integration/targets/molecule-process_exporter-default/runme.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+") +source "$collection_root/tests/integration/molecule.sh" From e44a2345d3f9b8de682c3f4775347946e1f6d9e1 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 23 Feb 2024 03:11:02 +0000 Subject: [PATCH 02/20] docs: add argument_specs Signed-off-by: gardar --- .../process_exporter/meta/argument_specs.yml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 roles/process_exporter/meta/argument_specs.yml diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml new file mode 100644 index 000000000..7b416be84 --- /dev/null +++ b/roles/process_exporter/meta/argument_specs.yml @@ -0,0 +1,52 @@ +--- +# yamllint disable rule:line-length +argument_specs: + main: + short_description: "Prometheus Process exporter" + description: + - "Deploy prometheus L(Process exporter,https://github.com/ncabatoff/process_exporter) using ansible" + author: + - "Prometheus Community" + options: + process_exporter_version: + description: "Process exporter package version. Also accepts latest as parameter." + default: "0.7.5" + process_exporter_skip_install: + description: "Process exporter installation tasks gets skipped when set to true." + type: bool + default: false + process_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(process_exporter) binary is stored on the host where ansible is run." + - "This overrides the I(process_exporter_version) parameter" + process_exporter_binary_url: + description: "URL of the Process exporter binaries .tar.gz file" + default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + process_exporter_checksums_url: + description: "URL of the Process exporter checksums file" + default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/sha256sums.txt" + process_exporter_web_listen_address: + description: "Address on which Process exporter will listen" + default: "0.0.0.0:9256" + process_exporter_names: + description: + - "Processes which should be monitored." + - "Syntax is the same as in" + - "L(using-a-config-file Default is consistent with deb/rpm packages,https://github.com/ncabatoff/process-exporter#using-a-config-file Default is consistent with deb/rpm packages)" + default: "[{name: '{{.Comm}}', cmdline: [.+]}]" + process_exporter_binary_install_dir: + description: + - "I(Advanced)" + - "Directory to install process_exporter binary" + default: "/usr/local/bin" + process_exporter_system_group: + description: + - "I(Advanced)" + - "System group for Process exporter" + default: "process-exp" + process_exporter_system_user: + description: + - "I(Advanced)" + - "Process exporter user" + default: "process-exp" From 0ae35a0b80c670344482ea297e21d0973149b085 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 23 Feb 2024 03:23:33 +0000 Subject: [PATCH 03/20] fix: url/binary names Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 2 +- roles/process_exporter/tasks/install.yml | 6 +++--- roles/process_exporter/vars/main.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 47c22fc25..107610c24 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -2,7 +2,7 @@ process_exporter_version: 0.7.5 process_exporter_binary_local_dir: "" process_exporter_binary_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/\ - process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" process_exporter_checksums_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/sha256sums.txt" process_exporter_skip_install: false diff --git a/roles/process_exporter/tasks/install.yml b/roles/process_exporter/tasks/install.yml index 7af968284..0f77ab21e 100644 --- a/roles/process_exporter/tasks/install.yml +++ b/roles/process_exporter/tasks/install.yml @@ -42,13 +42,13 @@ ansible.builtin.unarchive: src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" dest: "/tmp" - creates: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process_exporter" + creates: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" delegate_to: localhost check_mode: false - name: Propagate process_exporter binaries ansible.builtin.copy: - src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process_exporter" + src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" dest: "{{ process_exporter_binary_install_dir }}/process_exporter" mode: 0755 owner: root @@ -58,7 +58,7 @@ - name: Propagate locally distributed process_exporter binary ansible.builtin.copy: - src: "{{ process_exporter_binary_local_dir }}/process_exporter" + src: "{{ process_exporter_binary_local_dir }}/process-exporter" dest: "{{ process_exporter_binary_install_dir }}/process_exporter" mode: 0755 owner: root diff --git a/roles/process_exporter/vars/main.yml b/roles/process_exporter/vars/main.yml index 0a6b669b8..b31254ff6 100644 --- a/roles/process_exporter/vars/main.yml +++ b/roles/process_exporter/vars/main.yml @@ -7,5 +7,5 @@ go_arch_map: armv6l: 'armv6' go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}" -_process_exporter_repo: "ncabatoff/process_exporter" +_process_exporter_repo: "ncabatoff/process-exporter" _github_api_headers: "{{ {'GITHUB_TOKEN': lookup('ansible.builtin.env', 'GITHUB_TOKEN')} if (lookup('ansible.builtin.env', 'GITHUB_TOKEN')) else {} }}" From 65de2ec726ca76e7b275cbeaa5cd629282dd1692 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 23 Feb 2024 03:40:15 +0000 Subject: [PATCH 04/20] fix: raw string argument validation error Signed-off-by: gardar --- roles/process_exporter/meta/argument_specs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml index 7b416be84..931308c92 100644 --- a/roles/process_exporter/meta/argument_specs.yml +++ b/roles/process_exporter/meta/argument_specs.yml @@ -34,7 +34,7 @@ argument_specs: - "Processes which should be monitored." - "Syntax is the same as in" - "L(using-a-config-file Default is consistent with deb/rpm packages,https://github.com/ncabatoff/process-exporter#using-a-config-file Default is consistent with deb/rpm packages)" - default: "[{name: '{{.Comm}}', cmdline: [.+]}]" + default: !unsafe "[{name: '{{.Comm}}', cmdline: [.+]}]" process_exporter_binary_install_dir: description: - "I(Advanced)" From 7401eb83b457b6e38f3d9113c9c1447f14678781 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 23 Feb 2024 03:52:07 +0000 Subject: [PATCH 05/20] fix: checksums url Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 2 +- roles/process_exporter/meta/argument_specs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 107610c24..6ff26eab1 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -3,7 +3,7 @@ process_exporter_version: 0.7.5 process_exporter_binary_local_dir: "" process_exporter_binary_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/\ process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" -process_exporter_checksums_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/sha256sums.txt" +process_exporter_checksums_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/checksums.txt" process_exporter_skip_install: false diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml index 931308c92..1e88b6dd2 100644 --- a/roles/process_exporter/meta/argument_specs.yml +++ b/roles/process_exporter/meta/argument_specs.yml @@ -25,7 +25,7 @@ argument_specs: default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" process_exporter_checksums_url: description: "URL of the Process exporter checksums file" - default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/sha256sums.txt" + default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/checksums.txt" process_exporter_web_listen_address: description: "Address on which Process exporter will listen" default: "0.0.0.0:9256" From 5ef563a501da322f05cabb17e11784a54b38adff Mon Sep 17 00:00:00 2001 From: gardar Date: Sat, 24 Feb 2024 01:14:40 +0000 Subject: [PATCH 06/20] fix: typo Signed-off-by: gardar --- roles/process_exporter/templates/process_exporter.service.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/process_exporter/templates/process_exporter.service.j2 b/roles/process_exporter/templates/process_exporter.service.j2 index 977a760b3..951e01efc 100644 --- a/roles/process_exporter/templates/process_exporter.service.j2 +++ b/roles/process_exporter/templates/process_exporter.service.j2 @@ -8,7 +8,7 @@ After=network-online.target Type=simple User={{ process_exporter_system_user }} Group={{ process_exporter_system_group }} -ExecStart={{ process_exporter_binary_install_dir/process_exporter \ +ExecStart={{ process_exporter_binary_install_dir }}/process_exporter \ {% if process_exporter_names != [] -%} '--config.path=/etc/process_exporter/config.yml' \ {% endif -%} From a63fd464df1d6602a25a9dbc493fa44d602db57a Mon Sep 17 00:00:00 2001 From: gardar Date: Sat, 24 Feb 2024 01:15:15 +0000 Subject: [PATCH 07/20] fix: extracted dir name Signed-off-by: gardar --- roles/process_exporter/tasks/install.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/process_exporter/tasks/install.yml b/roles/process_exporter/tasks/install.yml index 0f77ab21e..e207afbd0 100644 --- a/roles/process_exporter/tasks/install.yml +++ b/roles/process_exporter/tasks/install.yml @@ -42,13 +42,14 @@ ansible.builtin.unarchive: src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" dest: "/tmp" - creates: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + creates: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + include: process-exporter delegate_to: localhost check_mode: false - name: Propagate process_exporter binaries ansible.builtin.copy: - src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + src: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" dest: "{{ process_exporter_binary_install_dir }}/process_exporter" mode: 0755 owner: root From 2a3f56e859662da6bbbb89bd932181061fb13805 Mon Sep 17 00:00:00 2001 From: gardar Date: Sat, 24 Feb 2024 04:51:29 +0000 Subject: [PATCH 08/20] fix: remove include parameter which is not supported in all ansible version the collection supports Signed-off-by: gardar --- roles/process_exporter/tasks/install.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/process_exporter/tasks/install.yml b/roles/process_exporter/tasks/install.yml index e207afbd0..aaa47beec 100644 --- a/roles/process_exporter/tasks/install.yml +++ b/roles/process_exporter/tasks/install.yml @@ -43,7 +43,6 @@ src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" dest: "/tmp" creates: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" - include: process-exporter delegate_to: localhost check_mode: false From 8b1b6e36e2e65fd4d03b99cc1e5484318f416bb6 Mon Sep 17 00:00:00 2001 From: gardar Date: Sun, 25 Feb 2024 03:42:29 +0000 Subject: [PATCH 09/20] minor: add protecthome Signed-off-by: gardar --- .../molecule/default/tests/test_default.py | 35 +++++++++++++++++-- .../templates/process_exporter.service.j2 | 19 ++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/roles/process_exporter/molecule/default/tests/test_default.py b/roles/process_exporter/molecule/default/tests/test_default.py index 6d2130997..71ea4d365 100644 --- a/roles/process_exporter/molecule/default/tests/test_default.py +++ b/roles/process_exporter/molecule/default/tests/test_default.py @@ -1,3 +1,6 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + import os import testinfra.utils.ansible_runner @@ -26,6 +29,21 @@ def test_files(host): assert f.is_file +def test_permissions_didnt_change(host): + dirs = [ + "/etc", + "/root", + "/usr", + "/var" + ] + for file in dirs: + f = host.file(file) + assert f.exists + assert f.is_directory + assert f.user == "root" + assert f.group == "root" + + def test_user(host): assert host.group("process-exp").exists assert "process-exp" in host.user("process-exp").groups @@ -35,8 +53,21 @@ def test_user(host): def test_service(host): s = host.service("process_exporter") -# assert s.is_enabled - assert s.is_running + try: + assert s.is_running + except AssertionError: + # Capture service logs + journal_output = host.run('journalctl -u process_exporter --since "1 hour ago"') + print("\n==== journalctl -u process_exporter Output ====\n") + print(journal_output) + print("\n============================================\n") + raise # Re-raise the original assertion error + + +def test_protecthome_property(host): + s = host.service("process_exporter") + p = s.systemd_properties + assert p.get("ProtectHome") == "yes" def test_socket(host): diff --git a/roles/process_exporter/templates/process_exporter.service.j2 b/roles/process_exporter/templates/process_exporter.service.j2 index 951e01efc..05d5de302 100644 --- a/roles/process_exporter/templates/process_exporter.service.j2 +++ b/roles/process_exporter/templates/process_exporter.service.j2 @@ -19,5 +19,24 @@ Restart=always RestartSec=1 StartLimitInterval=0 +{% set ns = namespace(protect_home = 'yes') %} +{% for m in ansible_mounts if m.mount.startswith('/home') %} +{% set ns.protect_home = 'read-only' %} +{% endfor %} +{% if node_exporter_textfile_dir.startswith('/home') %} +{% set ns.protect_home = 'read-only' %} +{% endif %} +ProtectHome={{ ns.protect_home }} +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 From 953b0b14c3b360cd961e9eb745d06670808721d3 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 18:40:23 +0000 Subject: [PATCH 10/20] fix: bump to latest version Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 6ff26eab1..811392a06 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -1,5 +1,5 @@ --- -process_exporter_version: 0.7.5 +process_exporter_version: 0.7.10 process_exporter_binary_local_dir: "" process_exporter_binary_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/\ process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" From 7def6b81a4679c8c8d9244535d7e79cef71f9306 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 19:17:25 +0000 Subject: [PATCH 11/20] feat: make web telemetry path configurable Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 1 + roles/process_exporter/meta/argument_specs.yml | 3 +++ roles/process_exporter/templates/process_exporter.service.j2 | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 811392a06..85e3bafe8 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -8,6 +8,7 @@ process_exporter_skip_install: false process_exporter_web_listen_address: "0.0.0.0:9256" +process_exporter_web_telemetry_path: "/metrics" # Process names # "raw" section is needed to avoid attempted interpretation diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml index 1e88b6dd2..90327ff96 100644 --- a/roles/process_exporter/meta/argument_specs.yml +++ b/roles/process_exporter/meta/argument_specs.yml @@ -29,6 +29,9 @@ argument_specs: process_exporter_web_listen_address: description: "Address on which Process exporter will listen" default: "0.0.0.0:9256" + process_exporter_web_telemetry_path: + description: "Path under which to expose metrics" + default: "/metrics" process_exporter_names: description: - "Processes which should be monitored." diff --git a/roles/process_exporter/templates/process_exporter.service.j2 b/roles/process_exporter/templates/process_exporter.service.j2 index 05d5de302..f29f3bb10 100644 --- a/roles/process_exporter/templates/process_exporter.service.j2 +++ b/roles/process_exporter/templates/process_exporter.service.j2 @@ -12,7 +12,8 @@ ExecStart={{ process_exporter_binary_install_dir }}/process_exporter \ {% if process_exporter_names != [] -%} '--config.path=/etc/process_exporter/config.yml' \ {% endif -%} - '--web.listen-address={{ process_exporter_web_listen_address }}' + '--web.listen-address={{ process_exporter_web_listen_address }}' \ + '--web.telemetry-path={{ process_exporter_web_telemetry_path }}' SyslogIdentifier=process_exporter Restart=always From 894db57168eb8c958b5cc36cd70c0783d356be01 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 19:22:39 +0000 Subject: [PATCH 12/20] refactor: move config to template Signed-off-by: gardar --- roles/process_exporter/tasks/configure.yml | 8 ++------ roles/process_exporter/templates/config.yml.j2 | 5 +++++ 2 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 roles/process_exporter/templates/config.yml.j2 diff --git a/roles/process_exporter/tasks/configure.yml b/roles/process_exporter/tasks/configure.yml index e3acf1eb7..0087f849b 100644 --- a/roles/process_exporter/tasks/configure.yml +++ b/roles/process_exporter/tasks/configure.yml @@ -17,16 +17,12 @@ mode: u+rwX,g+rwX,o=rX - name: Create/Update configuration file - ansible.builtin.copy: + ansible.builtin.template: + src: "config.yml.j2" dest: "/etc/process_exporter/config.yml" - content: | - process_names: - {{ process_exporter_names }} owner: root group: root mode: 0644 - when: - - process_exporter_names != [] notify: restart process_exporter - name: Allow process_exporter port in SELinux on RedHat OS family diff --git a/roles/process_exporter/templates/config.yml.j2 b/roles/process_exporter/templates/config.yml.j2 new file mode 100644 index 000000000..8769eed84 --- /dev/null +++ b/roles/process_exporter/templates/config.yml.j2 @@ -0,0 +1,5 @@ +--- +{{ ansible_managed | comment }} + +process_names: +{{ process_exporter_names }} From 457da4282b1e23c0891a7169ab3308df7f8fd680 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 19:59:03 +0000 Subject: [PATCH 13/20] feat: add tls/http/basic auth web config Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 6 ++++++ .../process_exporter/meta/argument_specs.yml | 11 +++++++++++ roles/process_exporter/tasks/configure.yml | 15 +++++++++++++++ .../templates/process_exporter.service.j2 | 6 +++--- .../templates/web_config.yml.j2 | 19 +++++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 roles/process_exporter/templates/web_config.yml.j2 diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 85e3bafe8..0038926fc 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -10,6 +10,12 @@ process_exporter_skip_install: false process_exporter_web_listen_address: "0.0.0.0:9256" process_exporter_web_telemetry_path: "/metrics" +process_exporter_tls_server_config: {} + +process_exporter_http_server_config: {} + +process_exporter_basic_auth_users: {} + # Process names # "raw" section is needed to avoid attempted interpretation # of process-exporter Template varables (like {{.Comm}}) diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml index 90327ff96..8ea777866 100644 --- a/roles/process_exporter/meta/argument_specs.yml +++ b/roles/process_exporter/meta/argument_specs.yml @@ -32,6 +32,17 @@ argument_specs: process_exporter_web_telemetry_path: description: "Path under which to expose metrics" default: "/metrics" + process_exporter_tls_server_config: + description: + - "Configuration for TLS authentication." + type: "dict" + process_exporter_http_server_config: + description: + - "Config for HTTP/2 support." + type: "dict" + process_exporter_basic_auth_users: + description: "Dictionary of users and password for basic authentication. Passwords are automatically hashed with bcrypt." + type: "dict" process_exporter_names: description: - "Processes which should be monitored." diff --git a/roles/process_exporter/tasks/configure.yml b/roles/process_exporter/tasks/configure.yml index 0087f849b..de82483f4 100644 --- a/roles/process_exporter/tasks/configure.yml +++ b/roles/process_exporter/tasks/configure.yml @@ -23,6 +23,21 @@ owner: root group: root mode: 0644 + when: + - process_exporter_names != [] + notify: restart process_exporter + +- name: Configure process_exporter web config + ansible.builtin.template: + src: "web_config.yml.j2" + dest: "/etc/process_exporter/web_config.yml" + owner: root + group: root + mode: 0644 + when: + ( process_exporter_tls_server_config | length > 0 ) or + ( process_exporter_http_server_config | length > 0 ) or + ( process_exporter_basic_auth_users | length > 0 ) notify: restart process_exporter - name: Allow process_exporter port in SELinux on RedHat OS family diff --git a/roles/process_exporter/templates/process_exporter.service.j2 b/roles/process_exporter/templates/process_exporter.service.j2 index f29f3bb10..b45f7031a 100644 --- a/roles/process_exporter/templates/process_exporter.service.j2 +++ b/roles/process_exporter/templates/process_exporter.service.j2 @@ -12,6 +12,9 @@ ExecStart={{ process_exporter_binary_install_dir }}/process_exporter \ {% if process_exporter_names != [] -%} '--config.path=/etc/process_exporter/config.yml' \ {% endif -%} +{% if process_exporter_tls_server_config | length > 0 or process_exporter_http_server_config | length > 0 or process_exporter_basic_auth_users | length > 0 %} + '--web.config.file=/etc/process_exporter/web_config.yml' \ +{% endif %} '--web.listen-address={{ process_exporter_web_listen_address }}' \ '--web.telemetry-path={{ process_exporter_web_telemetry_path }}' @@ -24,9 +27,6 @@ StartLimitInterval=0 {% for m in ansible_mounts if m.mount.startswith('/home') %} {% set ns.protect_home = 'read-only' %} {% endfor %} -{% if node_exporter_textfile_dir.startswith('/home') %} -{% set ns.protect_home = 'read-only' %} -{% endif %} ProtectHome={{ ns.protect_home }} NoNewPrivileges=yes diff --git a/roles/process_exporter/templates/web_config.yml.j2 b/roles/process_exporter/templates/web_config.yml.j2 new file mode 100644 index 000000000..3ebf90d59 --- /dev/null +++ b/roles/process_exporter/templates/web_config.yml.j2 @@ -0,0 +1,19 @@ +--- +{{ ansible_managed | comment }} + +{% if process_exporter_tls_server_config | length > 0 %} +tls_server_config: +{{ process_exporter_tls_server_config | to_nice_yaml | indent(2, true) }} +{% endif %} + +{% if process_exporter_http_server_config | length > 0 %} +http_server_config: +{{ process_exporter_http_server_config | to_nice_yaml | indent(2, true) }} +{% endif %} + +{% if process_exporter_basic_auth_users | length > 0 %} +basic_auth_users: +{% for k, v in process_exporter_basic_auth_users.items() %} + {{ k }}: {{ v | string | password_hash('bcrypt', ('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' | shuffle(seed=inventory_hostname) | join)[:22], rounds=9) }} +{% endfor %} +{% endif %} From 02ff0e7219ffd1e26e5012fc8d155dd71217b8fb Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:04:30 +0000 Subject: [PATCH 14/20] fix: add missing alternative/latest molecule scenarios Signed-off-by: gardar --- .../molecule/alternative/molecule.yml | 28 +++++++ .../molecule/alternative/prepare.yml | 77 +++++++++++++++++++ .../alternative/tests/test_alternative.py | 46 +++++++++++ .../molecule/latest/molecule.yml | 6 ++ .../molecule/latest/tests/test_latest.py | 43 +++++++++++ .../runme.sh | 4 + .../molecule-process_exporter-latest/runme.sh | 4 + 7 files changed, 208 insertions(+) create mode 100644 roles/process_exporter/molecule/alternative/molecule.yml create mode 100644 roles/process_exporter/molecule/alternative/prepare.yml create mode 100644 roles/process_exporter/molecule/alternative/tests/test_alternative.py create mode 100644 roles/process_exporter/molecule/latest/molecule.yml create mode 100644 roles/process_exporter/molecule/latest/tests/test_latest.py create mode 100755 tests/integration/targets/molecule-process_exporter-alternative/runme.sh create mode 100755 tests/integration/targets/molecule-process_exporter-latest/runme.sh diff --git a/roles/process_exporter/molecule/alternative/molecule.yml b/roles/process_exporter/molecule/alternative/molecule.yml new file mode 100644 index 000000000..8b6b51fc4 --- /dev/null +++ b/roles/process_exporter/molecule/alternative/molecule.yml @@ -0,0 +1,28 @@ +--- +provisioner: + inventory: + group_vars: + all: + process_exporter_binary_local_dir: "/tmp/process_exporter-linux-amd64" + process_exporter_web_listen_address: "127.0.0.1:8080" + process_exporter_tls_server_config: + cert_file: /etc/process_exporter/tls.cert + key_file: /etc/process_exporter/tls.key + process_exporter_http_server_config: + http2: true + process_exporter_basic_auth_users: + randomuser: examplepassword + go_arch: amd64 + process_exporter_version: 0.7.10 + process_exporter_names: | + {% raw %} + - name: "{{.Comm}}" + cmdline: + - systemd + - name: "{{.Comm}}" + cmdline: + - systemd-journald + - name: "{{.Comm}}" + cmdline: + - crond + {% endraw %} diff --git a/roles/process_exporter/molecule/alternative/prepare.yml b/roles/process_exporter/molecule/alternative/prepare.yml new file mode 100644 index 000000000..dbee71b90 --- /dev/null +++ b/roles/process_exporter/molecule/alternative/prepare.yml @@ -0,0 +1,77 @@ +--- +- name: Run local preparation + hosts: localhost + gather_facts: false + tasks: + - name: Download process_exporter binary to local folder + become: false + ansible.builtin.get_url: + url: "https://github.com/ncabatoff/process-exporter/releases/download/v{{\ + \ process_exporter_version }}/process_exporter-{{ process_exporter_version }}.linux-{{\ + \ go_arch }}.tar.gz" + dest: "/tmp/process_exporter-{{ process_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 process_exporter binary + become: false + ansible.builtin.unarchive: + src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + dest: "/tmp" + creates: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + check_mode: false + + - name: Link to process_exporter binaries directory + become: false + ansible.builtin.file: + src: "/tmp/process-exporter-{{ process_exporter_version }}.linux-amd64" + dest: "/tmp/process_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 process_exporter cert dir + ansible.builtin.file: + path: "{{ process_exporter_tls_server_config.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: "{{ process_exporter_tls_server_config.cert_file }}" + - src: "/tmp/tls.key" + dest: "{{ process_exporter_tls_server_config.key_file }}" diff --git a/roles/process_exporter/molecule/alternative/tests/test_alternative.py b/roles/process_exporter/molecule/alternative/tests/test_alternative.py new file mode 100644 index 000000000..7b6218dea --- /dev/null +++ b/roles/process_exporter/molecule/alternative/tests/test_alternative.py @@ -0,0 +1,46 @@ +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') + + +def test_directories(host): + dirs = [ + "/var/lib/process_exporter" + ] + for dir in dirs: + d = host.file(dir) + assert not d.exists + + +def test_service(host): + s = host.service("process_exporter") + try: + assert s.is_running + except AssertionError: + # Capture service logs + journal_output = host.run('journalctl -u process_exporter --since "1 hour ago"') + print("\n==== journalctl -u process_exporter Output ====\n") + print(journal_output) + print("\n============================================\n") + raise # Re-raise the original assertion error + + +def test_protecthome_property(host): + s = host.service("process_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 diff --git a/roles/process_exporter/molecule/latest/molecule.yml b/roles/process_exporter/molecule/latest/molecule.yml new file mode 100644 index 000000000..66b930bc2 --- /dev/null +++ b/roles/process_exporter/molecule/latest/molecule.yml @@ -0,0 +1,6 @@ +--- +provisioner: + inventory: + group_vars: + all: + process_exporter_version: latest diff --git a/roles/process_exporter/molecule/latest/tests/test_latest.py b/roles/process_exporter/molecule/latest/tests/test_latest.py new file mode 100644 index 000000000..66733656e --- /dev/null +++ b/roles/process_exporter/molecule/latest/tests/test_latest.py @@ -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/process_exporter.service", + "/usr/local/bin/process_exporter" +]) +def test_files(host, files): + f = host.file(files) + assert f.exists + assert f.is_file + + +def test_service(host): + s = host.service("process_exporter") + try: + assert s.is_running + except AssertionError: + # Capture service logs + journal_output = host.run('journalctl -u process_exporter --since "1 hour ago"') + print("\n==== journalctl -u process_exporter Output ====\n") + print(journal_output) + print("\n============================================\n") + raise # Re-raise the original assertion error + + +def test_protecthome_property(host): + s = host.service("process_exporter") + p = s.systemd_properties + assert p.get("ProtectHome") == "read-only" + + +def test_socket(host): + s = host.socket("tcp://0.0.0.0:9256") + assert s.is_listening diff --git a/tests/integration/targets/molecule-process_exporter-alternative/runme.sh b/tests/integration/targets/molecule-process_exporter-alternative/runme.sh new file mode 100755 index 000000000..d094c3e1b --- /dev/null +++ b/tests/integration/targets/molecule-process_exporter-alternative/runme.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+") +source "$collection_root/tests/integration/molecule.sh" diff --git a/tests/integration/targets/molecule-process_exporter-latest/runme.sh b/tests/integration/targets/molecule-process_exporter-latest/runme.sh new file mode 100755 index 000000000..d094c3e1b --- /dev/null +++ b/tests/integration/targets/molecule-process_exporter-latest/runme.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +collection_root=$(pwd | grep -oP ".+\/ansible_collections\/\w+?\/\w+") +source "$collection_root/tests/integration/molecule.sh" From 143e66d78c7ea86745a41a9449debf3492ff7733 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:14:03 +0000 Subject: [PATCH 15/20] minor: allow configuring temporary dir for binary archive Signed-off-by: gardar --- roles/process_exporter/defaults/main.yml | 1 + roles/process_exporter/meta/argument_specs.yml | 3 +++ roles/process_exporter/tasks/install.yml | 10 +++++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/roles/process_exporter/defaults/main.yml b/roles/process_exporter/defaults/main.yml index 0038926fc..e12050a3b 100644 --- a/roles/process_exporter/defaults/main.yml +++ b/roles/process_exporter/defaults/main.yml @@ -5,6 +5,7 @@ process_exporter_binary_url: "https://github.com/{{ _process_exporter_repo }}/re process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" process_exporter_checksums_url: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/checksums.txt" process_exporter_skip_install: false +process_exporter_archive_path: /tmp process_exporter_web_listen_address: "0.0.0.0:9256" diff --git a/roles/process_exporter/meta/argument_specs.yml b/roles/process_exporter/meta/argument_specs.yml index 8ea777866..0d959a863 100644 --- a/roles/process_exporter/meta/argument_specs.yml +++ b/roles/process_exporter/meta/argument_specs.yml @@ -20,6 +20,9 @@ argument_specs: - "Enables the use of local packages instead of those distributed on github." - "The parameter may be set to a directory where the C(process_exporter) binary is stored on the host where ansible is run." - "This overrides the I(process_exporter_version) parameter" + process_exporter_archive_path: + description: "Local path to stash the archive and its extraction" + default: "/tmp" process_exporter_binary_url: description: "URL of the Process exporter binaries .tar.gz file" default: "https://github.com/{{ _process_exporter_repo }}/releases/download/v{{ process_exporter_version }}/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" diff --git a/roles/process_exporter/tasks/install.yml b/roles/process_exporter/tasks/install.yml index aaa47beec..e4e2a984e 100644 --- a/roles/process_exporter/tasks/install.yml +++ b/roles/process_exporter/tasks/install.yml @@ -27,7 +27,7 @@ become: false ansible.builtin.get_url: url: "{{ process_exporter_binary_url }}" - dest: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + dest: "{{ process_exporter_archive_path }}/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" checksum: "sha256:{{ __process_exporter_checksum }}" mode: '0644' register: _download_binary @@ -40,15 +40,15 @@ - name: Unpack process_exporter binary become: false ansible.builtin.unarchive: - src: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" - dest: "/tmp" - creates: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + src: "{{ process_exporter_archive_path }}/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" + dest: "{{ process_exporter_archive_path }}" + creates: "{{ process_exporter_archive_path }}/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" delegate_to: localhost check_mode: false - name: Propagate process_exporter binaries ansible.builtin.copy: - src: "/tmp/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" + src: "{{ process_exporter_archive_path }}/process-exporter-{{ process_exporter_version }}.linux-{{ go_arch }}/process-exporter" dest: "{{ process_exporter_binary_install_dir }}/process_exporter" mode: 0755 owner: root From 9dd6aa9fb850faab9f13f63599992c81732f80b8 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:19:58 +0000 Subject: [PATCH 16/20] fix: remove unused pytest import Signed-off-by: gardar --- .../molecule/alternative/tests/test_alternative.py | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/process_exporter/molecule/alternative/tests/test_alternative.py b/roles/process_exporter/molecule/alternative/tests/test_alternative.py index 7b6218dea..4922514b0 100644 --- a/roles/process_exporter/molecule/alternative/tests/test_alternative.py +++ b/roles/process_exporter/molecule/alternative/tests/test_alternative.py @@ -3,7 +3,6 @@ import os import testinfra.utils.ansible_runner -import pytest testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') From c940d8463003a6695b8ca424ae38a5e317cc315a Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:20:59 +0000 Subject: [PATCH 17/20] fix: add bcrypt test requirement Signed-off-by: gardar --- roles/process_exporter/test-requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 roles/process_exporter/test-requirements.txt diff --git a/roles/process_exporter/test-requirements.txt b/roles/process_exporter/test-requirements.txt new file mode 100644 index 000000000..7f0b6e759 --- /dev/null +++ b/roles/process_exporter/test-requirements.txt @@ -0,0 +1 @@ +bcrypt From d702d95af48aeda86b09ffad3c024d719d2394c9 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:25:29 +0000 Subject: [PATCH 18/20] docs: remove outdated info from README Signed-off-by: gardar --- roles/process_exporter/README.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/roles/process_exporter/README.md b/roles/process_exporter/README.md index 483108252..c00f825ed 100644 --- a/roles/process_exporter/README.md +++ b/roles/process_exporter/README.md @@ -1,10 +1,5 @@ # Ansible Role: process_exporter -[![Build Status](https://travis-ci.com/cloudalchemy/ansible-process_exporter.svg?branch=master)](https://travis-ci.com/cloudalchemy/ansible-process_exporter) -[![License](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg)](https://opensource.org/licenses/MIT) -[![Ansible Role](https://img.shields.io/badge/ansible%20role-cloudalchemy.process_exporter-blue.svg)](https://galaxy.ansible.com/cloudalchemy/process_exporter/) -[![GitHub tag](https://img.shields.io/github/tag/cloudalchemy/ansible-process_exporter.svg)](https://github.com/cloudalchemy/ansible-process_exporter/tags) - ## Description Deploy [process-exporter](https://github.com/ncabatoff/process-exporter) using ansible. @@ -17,14 +12,8 @@ Note. This repository and role uses the name process_exporter to conform with an ## Role Variables -All variables which can be overridden are stored in [defaults/main.yml](defaults/main.yml) file as well as in table below. - -| Name | Default Value | Description | -| -------------- | ------------- | -----------------------------------| -| `process_exporter_version` | 0.7.5 | Process exporter package version. Also accepts latest as parameter | -| `process_exporter_web_listen_address` | "0.0.0.0:9256" | Address on which process_exporter will listen | -| `process_exporter_config_dir` | "/etc/process_exporter" | Path to directory with process_exporter configuration | -`process_exporter_names` handling has been set up in an unusual way to handle recommended process-exporter 'Template variables' (such as {{.Comm}}). Follow the example in [defaults/main.yml](defaults/main.yml) if you want to define custom filtering/grouping of processes that use Template variables and make sure to keep the {% raw %} block delimiters. +All variables which can be overridden are stored in [meta/argument_specs.yml](meta/argument_specs.yml) file. +See the [prometheus.prometheus.process_exporter](https://prometheus-community.github.io/ansible/branch/main/process_exporter_role.html) docs. ## Example @@ -36,16 +25,3 @@ Use it in a playbook as follows: roles: - prometheus.prometheus.process_exporter ``` - - -## 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. From 3c4733bb092f6447f1dd1e951b9feb9ae0352e7b Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:39:44 +0000 Subject: [PATCH 19/20] fix: archive name typo Signed-off-by: gardar --- roles/process_exporter/molecule/alternative/prepare.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/process_exporter/molecule/alternative/prepare.yml b/roles/process_exporter/molecule/alternative/prepare.yml index dbee71b90..92769f434 100644 --- a/roles/process_exporter/molecule/alternative/prepare.yml +++ b/roles/process_exporter/molecule/alternative/prepare.yml @@ -7,7 +7,7 @@ become: false ansible.builtin.get_url: url: "https://github.com/ncabatoff/process-exporter/releases/download/v{{\ - \ process_exporter_version }}/process_exporter-{{ process_exporter_version }}.linux-{{\ + \ process_exporter_version }}/process-exporter-{{ process_exporter_version }}.linux-{{\ \ go_arch }}.tar.gz" dest: "/tmp/process_exporter-{{ process_exporter_version }}.linux-{{ go_arch }}.tar.gz" mode: 0644 From 0e6ed3d18785a1cc98a903654b4948837ee977b6 Mon Sep 17 00:00:00 2001 From: gardar Date: Fri, 8 Mar 2024 20:40:30 +0000 Subject: [PATCH 20/20] fix: adopt protecthome test to latest molecule scenario Signed-off-by: gardar --- roles/process_exporter/molecule/latest/tests/test_latest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/process_exporter/molecule/latest/tests/test_latest.py b/roles/process_exporter/molecule/latest/tests/test_latest.py index 66733656e..63e5d1563 100644 --- a/roles/process_exporter/molecule/latest/tests/test_latest.py +++ b/roles/process_exporter/molecule/latest/tests/test_latest.py @@ -35,7 +35,7 @@ def test_service(host): def test_protecthome_property(host): s = host.service("process_exporter") p = s.systemd_properties - assert p.get("ProtectHome") == "read-only" + assert p.get("ProtectHome") == "yes" def test_socket(host):