From 3d1675528be67c5f1ffed28761f304558b46199a Mon Sep 17 00:00:00 2001 From: Martin Bauer Date: Tue, 8 Sep 2026 21:28:36 +0200 Subject: [PATCH] Fix tasks that always report changed regardless of actual state Several roles reported "changed" on every playbook run even when nothing on the target had drifted, making real config drift indistinguishable from noise: - 7 systemd tasks across 6 roles used state:restarted, which always issues a restart and always reports changed. Switched to state:started plus notify-driven handlers that only restart when the underlying unit file, script, or config actually changes. - pi_standard_setup's boot mode, timezone, and locale tasks shelled out to raspi-config with changed_when:true hardcoded. Boot mode now checks systemctl get-default first; timezone/locale now use the natively idempotent community.general.timezone/locale_gen modules. - The pi account password task computed password_hash('sha512') without a seed, generating a new random salt (and thus an apparently different hash) on every run. Added a stable seed so the hash only changes when the underlying secret does. Also renamed a mislabeled task in pi_squeezelite_custom and fixed a typo in pi_standard_setup while those files were already touched. Co-Authored-By: Claude Sonnet 5 --- requirements.txt | 1 + requirements.yml | 1 + roles/bluetooth_monitor/handlers/main.yml | 5 +++ roles/bluetooth_monitor/tasks/main.yml | 4 +- roles/pi_dhtsensor/handlers/main.yml | 5 +++ roles/pi_dhtsensor/tasks/main.yml | 6 ++- roles/pi_irserver/handlers/main.yml | 5 +++ roles/pi_irserver/tasks/main.yml | 5 ++- roles/pi_shairport/handlers/main.yml | 5 +++ roles/pi_shairport/tasks/main.yml | 7 +++- roles/pi_squeezelite_custom/handlers/main.yml | 5 +++ roles/pi_squeezelite_custom/tasks/main.yml | 6 ++- roles/pi_standard_setup/handlers/main.yml | 4 ++ roles/pi_standard_setup/tasks/main.yml | 38 ++++++++++++------- roles/pi_sysdweb/handlers/main.yml | 5 +++ roles/pi_sysdweb/tasks/main.yml | 6 ++- 16 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 roles/bluetooth_monitor/handlers/main.yml create mode 100644 roles/pi_dhtsensor/handlers/main.yml create mode 100644 roles/pi_irserver/handlers/main.yml create mode 100644 roles/pi_shairport/handlers/main.yml create mode 100644 roles/pi_squeezelite_custom/handlers/main.yml create mode 100644 roles/pi_sysdweb/handlers/main.yml diff --git a/requirements.txt b/requirements.txt index 7a075da..9afe6fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ ansible-core>=2.14 ansible-lint keepassxc-proxy-client +passlib diff --git a/requirements.yml b/requirements.yml index a0cd255..92a0244 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1,3 +1,4 @@ --- collections: - name: ansible.posix + - name: community.general diff --git a/roles/bluetooth_monitor/handlers/main.yml b/roles/bluetooth_monitor/handlers/main.yml new file mode 100644 index 0000000..cd8061a --- /dev/null +++ b/roles/bluetooth_monitor/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart my_btmonitor + ansible.builtin.service: + name: my_btmonitor + state: restarted diff --git a/roles/bluetooth_monitor/tasks/main.yml b/roles/bluetooth_monitor/tasks/main.yml index aeb87ac..03ede2f 100644 --- a/roles/bluetooth_monitor/tasks/main.yml +++ b/roles/bluetooth_monitor/tasks/main.yml @@ -16,15 +16,17 @@ dest: /usr/bin/my_btmonitor owner: root mode: u+rwx + notify: Restart my_btmonitor - name: Install systemd service file ansible.builtin.copy: src: my_btmonitor.service dest: /etc/systemd/system/ mode: "0644" + notify: Restart my_btmonitor - name: Add script to autostart and start now ansible.builtin.systemd: name: my_btmonitor - state: restarted + state: started enabled: "yes" daemon_reload: "yes" # - name: Add to sysdweb diff --git a/roles/pi_dhtsensor/handlers/main.yml b/roles/pi_dhtsensor/handlers/main.yml new file mode 100644 index 0000000..479e294 --- /dev/null +++ b/roles/pi_dhtsensor/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart dht22_sensing + ansible.builtin.service: + name: dht22_sensing + state: restarted diff --git a/roles/pi_dhtsensor/tasks/main.yml b/roles/pi_dhtsensor/tasks/main.yml index cadbc62..3ebcdf8 100644 --- a/roles/pi_dhtsensor/tasks/main.yml +++ b/roles/pi_dhtsensor/tasks/main.yml @@ -19,26 +19,30 @@ name: adafruit-dht executable: pip3 extra_args: "--break-system-packages" + notify: Restart dht22_sensing - name: Install script config ansible.builtin.template: src: dht22_sensing.json dest: /etc/dht22_sensing.json mode: "0644" + notify: Restart dht22_sensing - name: Install script ansible.builtin.copy: src: dht22_sensing.py dest: /usr/bin/dht22_sensing owner: root mode: u+rwx + notify: Restart dht22_sensing - name: Install systemd service file ansible.builtin.copy: src: dht22_sensing.service dest: /etc/systemd/system/ mode: "0644" + notify: Restart dht22_sensing - name: Add script to autostart and start now ansible.builtin.systemd: name: dht22_sensing - state: restarted + state: started enabled: "yes" daemon_reload: "yes" - name: Add to sysdweb diff --git a/roles/pi_irserver/handlers/main.yml b/roles/pi_irserver/handlers/main.yml new file mode 100644 index 0000000..265612d --- /dev/null +++ b/roles/pi_irserver/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart irserver + ansible.builtin.service: + name: irserver + state: restarted diff --git a/roles/pi_irserver/tasks/main.yml b/roles/pi_irserver/tasks/main.yml index 0a41d98..81c34e4 100644 --- a/roles/pi_irserver/tasks/main.yml +++ b/roles/pi_irserver/tasks/main.yml @@ -4,6 +4,7 @@ src: irserver dest: /usr/bin/irserver mode: u+rx + notify: Restart irserver - name: Make config dir for remotes ansible.builtin.file: path: /usr/bin/remotes @@ -14,15 +15,17 @@ src: hauppauge.rem dest: /usr/bin/remotes/ mode: "0644" + notify: Restart irserver - name: Copy irserver systemd file ansible.builtin.copy: src: irserver.service dest: /lib/systemd/system/ mode: "0644" + notify: Restart irserver - name: Enable irserver autostart ansible.builtin.systemd: name: irserver - state: restarted + state: started enabled: "yes" daemon_reload: "yes" - name: Add irserver to sysdweb diff --git a/roles/pi_shairport/handlers/main.yml b/roles/pi_shairport/handlers/main.yml new file mode 100644 index 0000000..e91d925 --- /dev/null +++ b/roles/pi_shairport/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart shairport-sync + ansible.builtin.service: + name: shairport-sync + state: restarted diff --git a/roles/pi_shairport/tasks/main.yml b/roles/pi_shairport/tasks/main.yml index 27a6c38..d02e702 100644 --- a/roles/pi_shairport/tasks/main.yml +++ b/roles/pi_shairport/tasks/main.yml @@ -21,20 +21,23 @@ ansible.builtin.script: "build-shairport-sync.sh ${shairport_sync_version}" args: creates: /usr/local/bin/shairport-sync + notify: Restart shairport-sync - name: Copy config ansible.builtin.template: src: shairport-sync.conf dest: /etc/shairport-sync.conf mode: "0644" + notify: Restart shairport-sync - name: Modify service file to run as root ansible.builtin.lineinfile: path: /lib/systemd/system/shairport-sync.service regexp: "^#?User=" line: "User=root" -- name: Restart shairport-sync + notify: Restart shairport-sync +- name: Enable shairport-sync autostart ansible.builtin.systemd: name: shairport-sync - state: restarted + state: started enabled: "yes" daemon_reload: "yes" - name: Add to sysdweb diff --git a/roles/pi_squeezelite_custom/handlers/main.yml b/roles/pi_squeezelite_custom/handlers/main.yml new file mode 100644 index 0000000..604b03d --- /dev/null +++ b/roles/pi_squeezelite_custom/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart squeezelite + ansible.builtin.service: + name: squeezelite + state: restarted diff --git a/roles/pi_squeezelite_custom/tasks/main.yml b/roles/pi_squeezelite_custom/tasks/main.yml index 0e9105e..843327b 100644 --- a/roles/pi_squeezelite_custom/tasks/main.yml +++ b/roles/pi_squeezelite_custom/tasks/main.yml @@ -23,15 +23,17 @@ src: squeezelite dest: /opt/squeezelite mode: "700" + notify: Restart squeezelite - name: Install systemd service file ansible.builtin.template: src: squeezelite.service dest: /lib/systemd/system/ mode: "0644" -- name: Enable sysdweb autostart + notify: Restart squeezelite +- name: Enable squeezelite autostart ansible.builtin.systemd: name: squeezelite - state: restarted + state: started enabled: "yes" daemon_reload: "yes" - name: Add to sysdweb diff --git a/roles/pi_standard_setup/handlers/main.yml b/roles/pi_standard_setup/handlers/main.yml index 07ceff9..8ef7e11 100644 --- a/roles/pi_standard_setup/handlers/main.yml +++ b/roles/pi_standard_setup/handlers/main.yml @@ -5,3 +5,7 @@ state: restarted - name: Reboot ansible.builtin.reboot: +- name: Restart raspi-leds-off + ansible.builtin.service: + name: raspi-leds-off + state: restarted diff --git a/roles/pi_standard_setup/tasks/main.yml b/roles/pi_standard_setup/tasks/main.yml index 706cdd8..54dba69 100644 --- a/roles/pi_standard_setup/tasks/main.yml +++ b/roles/pi_standard_setup/tasks/main.yml @@ -38,7 +38,7 @@ changed_when: false - name: Change hostname {{ pi_standard_setup_new_hostname }} ansible.builtin.command: "raspi-config nonint do_hostname {{ pi_standard_setup_new_hostname }}" - when: pi_standard_setup_new_hostname | bool and pi_standard_setup_pi_hostname.stdout != pi_standard_setup_new_hostname + when: pi_standard_setup_new_hostname | length > 0 and pi_standard_setup_pi_hostname.stdout != pi_standard_setup_new_hostname register: pi_standard_setup_set_hostname changed_when: true notify: Reboot @@ -46,21 +46,34 @@ ansible.builtin.command: "raspi-config nonint get_hostname" register: pi_standard_setup_pi_hostname changed_when: false +- name: Get current boot target + ansible.builtin.command: "systemctl get-default" + register: pi_standard_setup_boot_target + changed_when: false - name: Set boot mode to CLI ansible.builtin.command: "raspi-config nonint do_boot_behaviour B1" + when: pi_standard_setup_boot_target.stdout != "multi-user.target" changed_when: true # I2 Change Timezone - name: Change timezone - ansible.builtin.command: "raspi-config nonint do_change_timezone {{ pi_standard_setup_timezone }}" - changed_when: true -- name: Change locale - ansible.builtin.command: "raspi-config nonint do_change_locale en_US.UTF-8" - changed_when: true + community.general.timezone: + name: "{{ pi_standard_setup_timezone }}" +- name: Generate locale + community.general.locale_gen: + name: en_US.UTF-8 + state: present +- name: Set default locale + ansible.builtin.lineinfile: + path: /etc/default/locale + regexp: "^LANG=" + line: "LANG=en_US.UTF-8" + create: true + mode: "0644" - name: Change password of default pi account ansible.builtin.user: name: pi update_password: always - password: "{{ lookup('keepass', 'ansible://default_rpi_password') | password_hash('sha512') }}" + password: "{{ lookup('keepass', 'ansible://default_rpi_password') | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}" - name: Install Packages (vim, git, basic python stuff) ansible.builtin.apt: name: @@ -83,11 +96,6 @@ dest: /root/.gitconfig mode: "0644" # Wifi -- name: Get WiFi country - ansible.builtin.command: "raspi-config nonint get_wifi_country" - register: pi_standard_setup_current_wifi_country - changed_when: false - ignore_errors: true # to avoid error when WiFi is not present - name: Change WiFi country ansible.builtin.command: "raspi-config nonint do_wifi_country {{ pi_standard_setup_wifi_country }}" when: configure_wifi @@ -130,14 +138,16 @@ src: raspi-leds-off.sh dest: /usr/sbin/raspi-leds-off.sh mode: "u+rwx" + notify: Restart raspi-leds-off - name: Copy led off service ansible.builtin.copy: src: raspi-leds-off.service dest: /lib/systemd/system/ mode: "0644" -- name: Activate led off servic + notify: Restart raspi-leds-off +- name: Activate led off service ansible.builtin.systemd: name: raspi-leds-off - state: restarted + state: started enabled: "yes" daemon_reload: "yes" diff --git a/roles/pi_sysdweb/handlers/main.yml b/roles/pi_sysdweb/handlers/main.yml new file mode 100644 index 0000000..06904b4 --- /dev/null +++ b/roles/pi_sysdweb/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart sysdweb-system + ansible.builtin.service: + name: sysdweb-system + state: restarted diff --git a/roles/pi_sysdweb/tasks/main.yml b/roles/pi_sysdweb/tasks/main.yml index 10d9168..731d03b 100644 --- a/roles/pi_sysdweb/tasks/main.yml +++ b/roles/pi_sysdweb/tasks/main.yml @@ -9,6 +9,7 @@ name: sysdweb executable: pip3 extra_args: "--break-system-packages" + notify: Restart sysdweb-system - name: Sysdweb user ansible.builtin.user: name: sysdweb @@ -24,6 +25,7 @@ block: | [DEFAULT] users = sysdweb + notify: Restart sysdweb-system - name: Configure sysdweb ansible.builtin.blockinfile: path: /etc/sysdweb.conf @@ -34,14 +36,16 @@ [{{ pi_sysdweb_name }}] title = {{ pi_sysdweb_name }} unit = {{ pi_sysdweb_name }}.service + notify: Restart sysdweb-system - name: Install systemd service file ansible.builtin.copy: src: sysdweb-system.service dest: /etc/systemd/system/ mode: "0644" + notify: Restart sysdweb-system - name: Enable sysdweb autostart ansible.builtin.systemd: name: sysdweb-system - state: restarted + state: started enabled: "yes" daemon_reload: "yes"