From c9c812343831be1bb56965b2aeff41eecdae0a11 Mon Sep 17 00:00:00 2001 From: Colin Wilk Date: Wed, 11 Oct 2023 15:34:10 +0200 Subject: Add run_once option for handlers This adds the run_once option for the two handler types (shell and command). The variables `prometheus_target_handler_command_run_once` and `prometheus_target_handler_shell_run_once` are introduced to control this behavior. For this change a switch from the Ansible Handlers to regular tasks was necessary to enforce run_once behavior with delegated hosts. If you don't rely on handler specific features such as deferring, nothing changes when using the role. Signed-off-by: Colin Wilk --- CHANGELOG.md | 15 ++++++++-- README.md | 6 ++++ defaults/main.yml | 12 ++++++++ handlers/main.yml | 32 -------------------- meta/argument_specs.yml | 10 +++++++ molecule/default/converge.yml | 12 ++++---- molecule/default/molecule.yml | 9 ++++++ .../default/tests/test_check_prometheus_targets.py | 14 +++++++-- tasks/handlers.yml | 34 ++++++++++++++++++++++ tasks/lineinfile.yml | 8 +++-- tasks/main.yml | 7 +++++ 11 files changed, 113 insertions(+), 46 deletions(-) delete mode 100644 handlers/main.yml create mode 100644 tasks/handlers.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eb3f70..e5721e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,19 @@ # Changelog +## [1.2.0] - 2023-10-11 + +### Added + +- Add `run_once` option for command and shell handlers. + +### Changed + +- Handlers now use Ansible tasks instead of handlers to allow `run_once` + option to work properly. + ## [1.1.0] - 2023-06-15 ### Added -- Prefix option for target files (`579b168`) -- Ability to define exporters without id (`232bdca`) +- Prefix option for target files (`579b168`). +- Ability to define exporters without id (`232bdca`). diff --git a/README.md b/README.md index 0cfe278..3a1c3a9 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,10 @@ You can enable or disable the handlers via the `prometheus_target_handler_comman behavior via `prometheus_target_handler_command_become*`/ `prometheus_target_handler_shell_become*`. +To run the hook per play instead of per hosts, meaning it only runs once, you +can set the `prometheus_target_handler_command_run_once` / +`prometheus_target_handler_shell_run_once` hooks to `true`. + The `prometheus_target_handler_command` and `prometheus_target_handler_shell` variables map the options of their respective Ansible [command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html) @@ -153,12 +157,14 @@ prometheus_target_handler_command_enabled: false prometheus_target_handler_command_become: true # prometheus_target_handler_command_become_method: # prometheus_target_handler_command_become_user: +prometheus_target_handler_command_run_once: false prometheus_target_handler_command: {} prometheus_target_handler_shell_enabled: false prometheus_target_handler_shell_become: true # prometheus_target_handler_shell_become_method: # prometheus_target_handler_shell_become_user: +prometheus_target_handler_shell_run_once: false prometheus_target_handler_shell: {} ``` diff --git a/defaults/main.yml b/defaults/main.yml index 0a8e9ba..807f507 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -31,6 +31,14 @@ prometheus_target_handler_command_become: true # prometheus_target_handler_command_become_method: # prometheus_target_handler_command_become_user: +# By default the target handler will run for every host added on the delegated +# host. This means that if you add 20 hosts as your target, you will run the +# handler 20 times on your delegated host. This is useful if you need some host +# specific variables to run on the delegated host however often times, such as +# when using it to create a commit in a repository, you only need to do it once +# per run and not per host. +prometheus_target_handler_command_run_once: false + # This is the configuration for the command module. For documentation see: # https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html # --- @@ -55,6 +63,10 @@ prometheus_target_handler_shell_become: true # prometheus_target_handler_shell_become_method: # prometheus_target_handler_shell_become_user: +# This will configure the shell handler to run once. +# See documentation for prometheus_target_handler_command_run_once above. +prometheus_target_handler_shell_run_once: false + # This is the configuration for the shell module. For documentation see: # https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html # --- diff --git a/handlers/main.yml b/handlers/main.yml deleted file mode 100644 index 8b77084..0000000 --- a/handlers/main.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -- name: Run command hook # noqa inline-env-var - ansible.builtin.command: - argv: '{{ prometheus_target_handler_command.argv | default(omit) }}' - chdir: '{{ prometheus_target_handler_command.chdir | default(omit) }}' - cmd: '{{ prometheus_target_handler_command.cmd | default(omit) }}' - creates: '{{ prometheus_target_handler_command.creates | default(omit) }}' - free_form: '{{ prometheus_target_handler_command.free_form | default(omit) }}' - removes: '{{ prometheus_target_handler_command.removes | default(omit) }}' - stdin: '{{ prometheus_target_handler_command.stdin | default(omit) }}' - stdin_add_newline: '{{ prometheus_target_handler_command.stdin_add_newline | default(omit) }}' - become: '{{ prometheus_target_handler_command_become }}' - become_method: '{{ prometheus_target_handler_command_become_method | default(omit) }}' - become_user: '{{ prometheus_target_handler_command_become_user | default(omit) }}' - delegate_to: '{{ prometheus_target_host }}' - when: prometheus_target_handler_command_enabled - -- name: Run shell hook - ansible.builtin.shell: - chdir: '{{ prometheus_target_handler_shell.chdir | default(omit) }}' - cmd: '{{ prometheus_target_handler_shell.cmd | default(omit) }}' - creates: '{{ prometheus_target_handler_shell.creates | default(omit) }}' - executable: '{{ prometheus_target_handler_shell.executable | default(omit) }}' - free_form: '{{ prometheus_target_handler_shell.free_form | default(omit) }}' - removes: '{{ prometheus_target_handler_shell.removes | default(omit) }}' - stdin: '{{ prometheus_target_handler_shell.stdin | default(omit) }}' - stdin_add_newline: '{{ prometheus_target_handler_shell.stdin_add_newline | default(omit) }}' - become: '{{ prometheus_target_handler_shell_become }}' - become_method: '{{ prometheus_target_handler_shell_become_method | default(omit) }}' - become_user: '{{ prometheus_target_handler_shell_become_user | default(omit) }}' - delegate_to: '{{ prometheus_target_host }}' - when: prometheus_target_handler_shell_enabled diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml index 502c640..9126bb8 100644 --- a/meta/argument_specs.yml +++ b/meta/argument_specs.yml @@ -36,6 +36,11 @@ argument_specs: required: false default: true + prometheus_target_handler_command_run_once: + type: bool + required: false + default: false + prometheus_target_handler_command: type: dict required: false @@ -52,6 +57,11 @@ argument_specs: required: false default: true + prometheus_target_handler_shell_run_once: + type: bool + required: false + default: false + prometheus_target_handler_shell: type: dict required: false diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 9346988..cb6a281 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -83,7 +83,7 @@ ################################################################################ ################################################################################ - name: Deploy with hooks - hosts: application + hosts: application_group pre_tasks: - name: Create targets ansible.builtin.file: @@ -96,23 +96,23 @@ delegate_to: '{{ prometheus_target_host }}' loop: - /opt/hook_target.yml - - /opt/hook1 - - /opt/hook1 + - /opt/hook2 vars: prometheus_target_host: prometheus prometheus_target_handler_command_enabled: true prometheus_target_handler_command: - cmd: touch /opt/hook1 + cmd: mkdir /opt/hook1 # Fails if run twice + prometheus_target_handler_command_run_once: true prometheus_target_handler_shell_enabled: true prometheus_target_handler_shell: - cmd: touch /opt/hook2 + cmd: echo hello >> /opt/hook2 roles: - role: kliwniloc.prometheus_target prometheus_target_exporter: - id: node_exporter - host: application + host: '{{ inventory_hostname }}' path: /opt/hook_target.yml ################################################################################ diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index a8623d0..de1ac40 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -20,6 +20,15 @@ platforms: com.docker.network.driver.mtu: 1420 networks: - name: molecule-container-net + groups: [application_group] + + - name: application2 + image: ${MOLECULE_DISTRO:-debian:10} + dockerfile: Dockerfile.j2 + pre_build_image: false + networks: + - name: molecule-container-net + groups: [application_group] - name: prometheus image: ${MOLECULE_DISTRO:-debian:10} diff --git a/molecule/default/tests/test_check_prometheus_targets.py b/molecule/default/tests/test_check_prometheus_targets.py index ddf3a22..2eeb21b 100644 --- a/molecule/default/tests/test_check_prometheus_targets.py +++ b/molecule/default/tests/test_check_prometheus_targets.py @@ -58,12 +58,20 @@ def test_check_hosts_added_hooks(host): t2 = host.file('/opt/hook1') t3 = host.file('/opt/hook2') - assert t1.content_string == \ - ' - application\n' - + assert t1.exists assert t2.exists assert t3.exists + assert t1.content_string == \ + ' - application\n' \ + ' - application2\n' \ + or t1.content_string == \ + ' - application2\n' \ + ' - application\n' + + assert t3.content_string == \ + 'hello\n' \ + 'hello\n' """ Test lineinfile strategy parameters diff --git a/tasks/handlers.yml b/tasks/handlers.yml new file mode 100644 index 0000000..b1d9b59 --- /dev/null +++ b/tasks/handlers.yml @@ -0,0 +1,34 @@ +--- +- name: Run command hook # noqa inline-env-var + ansible.builtin.command: + argv: '{{ prometheus_target_handler_command.argv | default(omit) }}' + chdir: '{{ prometheus_target_handler_command.chdir | default(omit) }}' + cmd: '{{ prometheus_target_handler_command.cmd | default(omit) }}' + creates: '{{ prometheus_target_handler_command.creates | default(omit) }}' + free_form: '{{ prometheus_target_handler_command.free_form | default(omit) }}' + removes: '{{ prometheus_target_handler_command.removes | default(omit) }}' + stdin: '{{ prometheus_target_handler_command.stdin | default(omit) }}' + stdin_add_newline: '{{ prometheus_target_handler_command.stdin_add_newline | default(omit) }}' + become: '{{ prometheus_target_handler_command_become }}' + become_method: '{{ prometheus_target_handler_command_become_method | default(omit) }}' + become_user: '{{ prometheus_target_handler_command_become_user | default(omit) }}' + delegate_to: '{{ prometheus_target_host }}' + run_once: '{{ prometheus_target_handler_command_run_once }}' + when: prometheus_target_handler_command_enabled + +- name: Run shell hook + ansible.builtin.shell: + chdir: '{{ prometheus_target_handler_shell.chdir | default(omit) }}' + cmd: '{{ prometheus_target_handler_shell.cmd | default(omit) }}' + creates: '{{ prometheus_target_handler_shell.creates | default(omit) }}' + executable: '{{ prometheus_target_handler_shell.executable | default(omit) }}' + free_form: '{{ prometheus_target_handler_shell.free_form | default(omit) }}' + removes: '{{ prometheus_target_handler_shell.removes | default(omit) }}' + stdin: '{{ prometheus_target_handler_shell.stdin | default(omit) }}' + stdin_add_newline: '{{ prometheus_target_handler_shell.stdin_add_newline | default(omit) }}' + become: '{{ prometheus_target_handler_shell_become }}' + become_method: '{{ prometheus_target_handler_shell_become_method | default(omit) }}' + become_user: '{{ prometheus_target_handler_shell_become_user | default(omit) }}' + delegate_to: '{{ prometheus_target_host }}' + run_once: '{{ prometheus_target_handler_shell_run_once }}' + when: prometheus_target_handler_shell_enabled diff --git a/tasks/lineinfile.yml b/tasks/lineinfile.yml index 0367be9..8c60ba0 100644 --- a/tasks/lineinfile.yml +++ b/tasks/lineinfile.yml @@ -17,6 +17,8 @@ delegate_to: '{{ prometheus_target_host }}' loop: '{{ prometheus_target_exporter + ([] if prometheus_target_skip_default_exporters else prometheus_target_default_exporters) }}' - notify: - - Run command hook - - Run shell hook + register: lineinfile + +- name: Export fact + ansible.builtin.set_fact: + changed: '{{ changed or lineinfile.changed }}' diff --git a/tasks/main.yml b/tasks/main.yml index 158191d..f8d6caa 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,3 +2,10 @@ - name: Select strategy ansible.builtin.include_tasks: file: '{{ prometheus_target_strategy }}.yml' + vars: + changed: false + +- name: Run handlers + ansible.builtin.include_tasks: + file: handlers.yml + when: changed -- cgit v1.2.3