From f16bc68e7aeff59969f4b32391af5bcae62bc386 Mon Sep 17 00:00:00 2001
From: Autodistries <autodistries@protonmail.com>
Date: Thu, 3 Oct 2024 11:50:19 +0200
Subject: [PATCH] finished tests and refactored playbooks

---
 .vscode/settings.json                         |  3 +
 config/test.yml                               | 19 +++---
 docs/DOCUMENTATION.md                         |  4 +-
 playbooks/data_transfer.yml                   |  2 +-
 playbooks/device_setup.yml                    |  2 +-
 playbooks/microstask_GPS_setup.yml            |  4 +-
 playbooks/microtask_getty_autologin_setup.yml |  4 +-
 playbooks/microtask_hosts_update.yml          | 10 ++--
 playbooks/microtask_mitik_sens_update.yml     |  2 +-
 .../microtask_network_drivers_update.yml      |  4 +-
 ...sk_networking_naming_scheme_udev_setup.yml |  4 +-
 ...rotask_networkmanager_un_manager_setup.yml |  2 +-
 playbooks/microtask_reboot.yml                |  2 +-
 playbooks/ssh_setup.yml                       | 10 ++--
 playbooks/start_sens_sniffer.yml              |  2 +-
 playbooks/test_GPIO_GPS_PPS_status.yml        | 59 +++++++++++--------
 playbooks/test_config_files.yml               | 37 +++++++-----
 playbooks/test_hostname.yml                   | 13 ++++
 playbooks/test_interfaces_status.yml          | 36 +++++------
 playbooks/test_meta.yml                       | 15 ++++-
 playbooks/test_packages.yml                   | 30 ++++++++++
 playbooks/test_systemctl_services.yml         | 38 ++++++------
 playbooks/test_time.yml                       | 42 +++++++++----
 23 files changed, 218 insertions(+), 126 deletions(-)
 create mode 100644 .vscode/settings.json
 create mode 100644 playbooks/test_hostname.yml
 create mode 100644 playbooks/test_packages.yml

diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..9d14cfb
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "ansible.python.interpreterPath": "/bin/python"
+}
\ No newline at end of file
diff --git a/config/test.yml b/config/test.yml
index 4e87a5f..f3f531c 100644
--- a/config/test.yml
+++ b/config/test.yml
@@ -1,11 +1,12 @@
-- hosts:  all
-  become: yes
+- hosts:  localhost
   tasks:
     
-    - debug:
-        msg: >
-            {% if inventory_hostname is match('^ss[0-9]-s[0-9]$') %}
-              "../results/{{ ansible_date_time.date }}/{{ inventory_hostname[0:3] }}/{{ inventory_hostname[4:6] }}/"
-            {% else %}
-              "../results/{{ ansible_date_time.date }}/nogroup/{{ inventory_hostname }}/"
-            {% endif %}
\ No newline at end of file
+    - name: Install sshpass and keychain to master device
+      tags: ssh-setup ssh-keygen config keychain sshpass master
+      package:
+        name:
+          - sshpass # for the first login into nodes, using password auth
+          - keychain # to load the private key when opening a terminal
+        state: present
+      run_once: True
+      become: true
\ No newline at end of file
diff --git a/docs/DOCUMENTATION.md b/docs/DOCUMENTATION.md
index 64cc841..7cdc81e 100644
--- a/docs/DOCUMENTATION.md
+++ b/docs/DOCUMENTATION.md
@@ -90,9 +90,9 @@ For this to be solved, we're going to transfer the master's ssh key to the nodes
 
 Run the `ssh_setup.yml` playbook from the `config` folder :
 ```
-ansible-playbook ../playbooks/ssh_setup.yml
+sudo ansible-playbook ../playbooks/ssh_setup.yml
 ```
-Fill in the prompt for nodes' ssh passord and your master's admin password, then wait for completion. From there on, you won't need to provide authentication.
+Fill in the prompt for nodes' ssh passord and your master's admin password, then wait for completion. From there on, you won't need to provide any authentication.
 
 
 ### Testing the connection to your nodes
diff --git a/playbooks/data_transfer.yml b/playbooks/data_transfer.yml
index 1bc5b4c..a3c4365 100644
--- a/playbooks/data_transfer.yml
+++ b/playbooks/data_transfer.yml
@@ -29,5 +29,5 @@
       fetch: 
         src: "{{ item.path }}"
         dest: "{{_dest | trim}}"
-        flat: yes
+        flat: true
       with_items: "{{ files_to_copy.files }}"
diff --git a/playbooks/device_setup.yml b/playbooks/device_setup.yml
index 0e5e873..afeb218 100644
--- a/playbooks/device_setup.yml
+++ b/playbooks/device_setup.yml
@@ -4,7 +4,7 @@
 
 - name: Set up the sniffers
   hosts: sniffers
-  become: yes
+  become: true
   become_user: root
   tasks:
 
diff --git a/playbooks/microstask_GPS_setup.yml b/playbooks/microstask_GPS_setup.yml
index 9a3ce1e..5211229 100644
--- a/playbooks/microstask_GPS_setup.yml
+++ b/playbooks/microstask_GPS_setup.yml
@@ -1,5 +1,5 @@
 - hosts: sniffers
-  become: yes
+  become: true
   become_user: root
   tasks:
 
@@ -29,7 +29,7 @@
       sudo systemctl restart chrony
 
    - name: Copy a new config gpsd device functionality
-     become: yes
+     become: true
      become_user: root
      blockinfile:
       dest: /boot/firmware/config.txt
diff --git a/playbooks/microtask_getty_autologin_setup.yml b/playbooks/microtask_getty_autologin_setup.yml
index bde3b58..4bd0287 100644
--- a/playbooks/microtask_getty_autologin_setup.yml
+++ b/playbooks/microtask_getty_autologin_setup.yml
@@ -1,5 +1,5 @@
 - hosts:  s6
-  become: yes
+  become: true
   become_user: root
   tasks:
     - name: Configure Getty Console Autologin
@@ -9,4 +9,4 @@
             [Service]
             ExecStart=
             ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin {{ansible_ssh_user}} %I $TERM
-        create: yes
+        create: true
diff --git a/playbooks/microtask_hosts_update.yml b/playbooks/microtask_hosts_update.yml
index 85f88e2..1f438ea 100644
--- a/playbooks/microtask_hosts_update.yml
+++ b/playbooks/microtask_hosts_update.yml
@@ -6,19 +6,19 @@
 # 192.168.1.246 ss2-s5
 # 192.168.1.244 ss2-s6
 # It works when this line does not exist before; it also updates existing lines if necessary
-- name: host file update - Local DNS setup across all the nodes
-  gather_facts: yes
+- name: host file update - Local DNS setup across all nodes and master
+  gather_facts: true
   tags: etchosts device-update
-  become: yes
+  become: true
   become_user: root
-  hosts: sniffers
+  hosts: sniffers, localhost
   tasks:
 
     - name: Add IP address of all hosts to all hosts
       lineinfile:
             dest: "/etc/hosts"
             regexp: '.*{{ item }}$'
-            line: "{{ hostvars[item].ansible_host }} {{ group_names[1] | default(group_names[0] | default('nogroup')) }}-{{item}}"
+            line: "{{ hostvars[item].ansible_host }} {{item}}"
             state: present
       when: hostvars[item].ansible_host is defined
       with_items: "{{ groups.sniffers }}"
diff --git a/playbooks/microtask_mitik_sens_update.yml b/playbooks/microtask_mitik_sens_update.yml
index da6ce57..e2622c0 100644
--- a/playbooks/microtask_mitik_sens_update.yml
+++ b/playbooks/microtask_mitik_sens_update.yml
@@ -3,7 +3,7 @@
 
 - name: Clone and/or update sens repository
   hosts: sniffers
-  become: yes
+  become: true
   become_user: root
   tasks:
     - name: Install git if necessary
diff --git a/playbooks/microtask_network_drivers_update.yml b/playbooks/microtask_network_drivers_update.yml
index 4333925..1965812 100644
--- a/playbooks/microtask_network_drivers_update.yml
+++ b/playbooks/microtask_network_drivers_update.yml
@@ -2,7 +2,7 @@
 
 - name: Update the drivers for external adapters
   hosts: sniffers
-  become: yes
+  become: true
   become_user: root
   tasks:
     - name: Install required packages
@@ -12,7 +12,7 @@
           # required
           - git # to clone rtl8188 repo
           - bc # required to compile the rtl8188 driver
-        update_cache: yes
+        update_cache: true
 
     - name: Clone or update rtl8188eus repository if necessary
       ansible.builtin.git:
diff --git a/playbooks/microtask_networking_naming_scheme_udev_setup.yml b/playbooks/microtask_networking_naming_scheme_udev_setup.yml
index e67f49d..c9d19e9 100644
--- a/playbooks/microtask_networking_naming_scheme_udev_setup.yml
+++ b/playbooks/microtask_networking_naming_scheme_udev_setup.yml
@@ -1,5 +1,5 @@
 # Copies network interfaces naming scheme (based on physical usb location)
-- become: yes
+- become: true
   hosts: sniffers
   become_user: root
   tags: nodes device-setup udev naming-scheme
@@ -16,7 +16,7 @@
 
     - name: Query current interface names
       shell: "ip a | grep wlan"
-      ignore_errors: yes
+      ignore_errors: true
       register: any_wlans
     - name: Query active connections
       shell: "nmcli -t -f name,uuid con show --active | grep -v lo"
diff --git a/playbooks/microtask_networkmanager_un_manager_setup.yml b/playbooks/microtask_networkmanager_un_manager_setup.yml
index d2b7258..7e3f21e 100644
--- a/playbooks/microtask_networkmanager_un_manager_setup.yml
+++ b/playbooks/microtask_networkmanager_un_manager_setup.yml
@@ -3,7 +3,7 @@
 
 - name: Setup NetworkManager to ignore wifi5..8
   hosts: sniffers
-  become: yes
+  become: true
   become_user: root
   tasks:
 
diff --git a/playbooks/microtask_reboot.yml b/playbooks/microtask_reboot.yml
index c4ea582..a97f393 100644
--- a/playbooks/microtask_reboot.yml
+++ b/playbooks/microtask_reboot.yml
@@ -1,7 +1,7 @@
 
 - name: nodes reboot
   hosts: s5
-  become: yes
+  become: true
   become_user: root
   vars_prompt:
     - name: user_reboot
diff --git a/playbooks/ssh_setup.yml b/playbooks/ssh_setup.yml
index cebdbdd..d0e1b04 100644
--- a/playbooks/ssh_setup.yml
+++ b/playbooks/ssh_setup.yml
@@ -4,7 +4,7 @@
   vars_prompt:
     - name: ansible_ssh_pass
       prompt: Enter the nodes' SSH password
-      private: yes
+      private: true
   vars:
     ansible_host_key_checking: False
 
@@ -12,13 +12,15 @@
 
     - name: Install sshpass and keychain to master device
       tags: ssh-setup ssh-keygen config keychain sshpass master
-      apt:
-        pkg:
+      package:
+        name:
           - sshpass # for the first login into nodes, using password auth
           - keychain # to load the private key when opening a terminal
+        state: present
       delegate_to: 127.0.0.1
       run_once: True
-      when: false
+      become: true
+      # when: false
 
 
     - name: SSH KeyGen command on master device
diff --git a/playbooks/start_sens_sniffer.yml b/playbooks/start_sens_sniffer.yml
index 2d538da..effb9f8 100644
--- a/playbooks/start_sens_sniffer.yml
+++ b/playbooks/start_sens_sniffer.yml
@@ -1,6 +1,6 @@
 # Start the sniffer. SUpports multiple sniffers and starting channels
 - hosts: sniffers
-  #become: yes
+  #become: true
   #become_user: root
 
   vars_prompt:
diff --git a/playbooks/test_GPIO_GPS_PPS_status.yml b/playbooks/test_GPIO_GPS_PPS_status.yml
index fa271f0..4de3ab6 100644
--- a/playbooks/test_GPIO_GPS_PPS_status.yml
+++ b/playbooks/test_GPIO_GPS_PPS_status.yml
@@ -1,26 +1,28 @@
-- hosts: sniffers
+- name: Check for output from gps/pps
+  hosts: sniffers
   gather_facts: false
-  become: yes
+  become: true
   become_user: root
   any_errors_fatal: true
 
 
   tasks:
 
-#GPIO status
+    # GPIO status
     - name: GPIO status test
-      shell: pinctrl get 18 |  awk -F" " '{print $9}'
+      ansible.builtin.shell: pinctrl get 18 |  awk -F" " '{print $9}'
       register: result
+      changed_when: false
 
 
-    - name: test if GPS module disabled
-      set_fact:
+    - name: Test if GPS module disabled
+      ansible.builtin.set_fact:
         falg_failed_gpio_off: "GPS module is disabled"
       when: result.stdout != 'input'
 
 
     # when something is connected, running this prevents gpsd from using that data which forces a reboot
-    - name: try to get data from the GPIO pins (disabled)
+    - name: Try to get data from the GPIO pins (disabled)
       shell: |
         gpioPresenceTest=$(mktemp  /tmp/test-XXXXXX.gpio)
         if [ $(type gpsmon >/dev/null; echo $?) != 0 ]; then
@@ -30,32 +32,32 @@
         if [ $(cat $gpioPresenceTest | sort | uniq | wc -l) != 2 ]; then
         echo 2
         fi
-        echo 0 
+        echo 0
       register: _gpiotest
       failed_when: false
       when: false
       no_log: true
-      # sudo gpiomon 4 15 is too brutal and prevents further communication. 
+      # sudo gpiomon 4 15 is too brutal and prevents further communication.
       # gpioget 4 15 is the same. idk what to do
 
 
-    - name: interpret gpio reception failure (disabled)
-      fail:
+    - name: Interpret gpio reception failure (disabled)
+      ansible.builtin.fail:
         msg: >-
           {% if _gpiotest.rc == 2 %}
           no output from GPIO was found. did you plug in the gps correctly ?
           {% elif _gpiotest.rc == 3 %}
           the command gpsmon does not exist. Is gpsd properly installed?
           {% else %}
-          Unexpected return code: {{ _gpiotest.rc }}. Check stderr: {{_gpiotest}}
+          Unexpected return code: {{ _gpiotest.rc }}. Check stderr: {{ _gpiotest }}
           {% endif %}
-      when: false and _gpiotest.rc != 0 
+      when: false and _gpiotest.rc != 0
       ignore_errors: true
 
 
 
 
-    - name: check pps reception
+    - name: Check pps reception
       shell: |
           ppsPresenceTest=$(mktemp  /tmp/test-XXXXXX.pps)
           if [ $(type ppstest >/dev/null; echo $?) != 0 ]; then
@@ -65,17 +67,17 @@
           if [ $(cat $ppsPresenceTest | wc -l) -lt 4 ]; then
           exit 2
           fi
-          exit 0 
+          exit 0
       register: _ppscheck
       ignore_errors: true
       no_log: true
       failed_when: false
 
-    - name: interpret pps reception failure
-      fail:
+    - name: Interpret pps reception failure
+      ansible.builtin.fail:
         msg: >-
           {% if _ppscheck.rc == 2 %}
-          no output from PPS was found 
+          no output from PPS was found
           {% elif _ppscheck.rc == 3 %}
           the command ppstest does not exist. Is pps properly installed?
           {% else %}
@@ -85,22 +87,22 @@
       ignore_errors: true
 
 
-    - name: check gps position reception
-      shell: |
+    - name: Check gps position reception
+      ansible.builtin.shell: |
         if [ $(type gpspipe >/dev/null; echo $?) != 0 ]; then
         exit 3
         fi
         if [ $(timeout 1.2s gpspipe --nmea -n 10 >/dev/null ; echo $?) != 0 ]; then
         exit 2
         fi
-        exit 0 
+        exit 0
       register: _gpscheck
       failed_when: false
       no_log: true
       ignore_errors: true
 
-    - name: interpret gps reception failure
-      fail:
+    - name: Interpret gps reception failure
+      ansible.builtin.fail:
         msg: >-
           {% if _gpscheck.rc == 2 %}
           no position from GPS was found. Either wait a minute, or reboot the device
@@ -112,7 +114,12 @@
       when: _gpscheck.rc != 0
       ignore_errors: true
 
-    - name: stop if fails encountered
-      fail: 
+    - name: Stop if fails encountered
+      ansible.builtin.fail:
         msg: GPIO components and gps seem badly configured; see previous errors for this device !
-      when: _gpiotest.rc | default(0) != 0  or _gpscheck.rc != 0 or _ppscheck.rc != 0 
+      when: _gpiotest.rc | default(0) != 0 or _gpscheck.rc != 0 or _ppscheck.rc != 0
+
+
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "GPS and PPS seem fine !"
diff --git a/playbooks/test_config_files.yml b/playbooks/test_config_files.yml
index b7624bb..ba346bc 100644
--- a/playbooks/test_config_files.yml
+++ b/playbooks/test_config_files.yml
@@ -1,8 +1,8 @@
-- hosts: sniffers
-  name: Check remote config files
-  #gather_facts: false
-  gather_facts: no
+- name: Check that local and remote config files are the same
+  hosts: sniffers
+  gather_facts: true
   vars:
+    _errors: []
     file_combinations:
       - local_file: "../files/99-unmanaged-devices.conf"
         remote_file: "/etc/NetworkManager/conf.d/99-unmanaged-devices.conf"
@@ -18,32 +18,39 @@
         remote_file: "/home/{{ansible_ssh_user}}/positionGetter.sh"
   tasks:
     - name: Get SHA256 checksum for each remote file
-      stat:
+      ansible.builtin.stat:
         path: "{{ item.remote_file }}"
         checksum_algorithm: sha256
       register: remote_file_checksums
       loop: "{{ file_combinations }}"
 
     - name: Get SHA256 checksum for each local file
-      stat:
+      ansible.builtin.stat:
         follow: true
         path: "{{ item.local_file | realpath }}"
         checksum_algorithm: sha256
+      loop: "{{ file_combinations }}"
       register: local_file_checksums
       delegate_to: localhost
-      loop: "{{ file_combinations }}"
-
 
-    - debug:
-        var: item
-      loop: "{{ local_file_checksums.results | zip(remote_file_checksums.results) | list }}"
 
-    - name: Compare local and remote files
-      fail:
-        msg: "Local and remote files are different"
-      when: item[0].stat.checksum != item[1].stat.checksum
+    - name: Compare local and remote files and store differences
+      ansible.builtin.set_fact:
+        _errors: "{{ _errors + [item[0].item.remote_file + (' does not exist, ' if not item[1].stat.exists else ' and ') + item[0].item.local_file + (' does not exist' if not item[0].stat.exists else ' are different') + ' !'] }}"
+      when: item[0].stat.exists is false or item[1].stat.exists is false or item[0].stat.checksum != item[1].stat.checksum
       loop: "{{ local_file_checksums.results | zip(remote_file_checksums.results) | list }}"
       loop_control:
         label: "{{ item[0].item }}"
       delegate_to: localhost
 
+    - name: Print errors if any and interrupt the playbook
+      ansible.builtin.debug:
+        msg: "{{ _errors }}"
+      when: _errors | length > 0
+      failed_when: true
+      any_errors_fatal: true
+
+
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Config files seem fine !"
diff --git a/playbooks/test_hostname.yml b/playbooks/test_hostname.yml
new file mode 100644
index 0000000..da82a1d
--- /dev/null
+++ b/playbooks/test_hostname.yml
@@ -0,0 +1,13 @@
+- name: Check hostnames on remote nodes
+  hosts: sniffers
+  tasks:
+    - name: Hostname check
+      ansible.builtin.fail:
+        msg: "The hostname {{ ansible_hostname }} looks invalid."
+      when: ansible_hostname is not match('^ss[0-9]-s[0-9]$')
+      any_errors_fatal: true
+
+
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Hostnames seem fine !"
diff --git a/playbooks/test_interfaces_status.yml b/playbooks/test_interfaces_status.yml
index 1e8a52f..9b31f80 100644
--- a/playbooks/test_interfaces_status.yml
+++ b/playbooks/test_interfaces_status.yml
@@ -1,6 +1,7 @@
-- hosts: all
+- name: Test interfaces' statuses
+  hosts: all
   gather_facts: true
-  become: yes
+  become: true
   become_user: root
 
 
@@ -26,45 +27,46 @@
   tasks:
     # Interfaces status
     - name: Interfaces connected
-      debug:
+      ansible.builtin.debug:
         msg: "{{ interfaces_unformated_list | map('join', ', ') }}"
-    - name: warn about wlan devices (should be wifi)
-      debug:
+    - name: Warn about wlan devices (should be wifi)
+      ansible.builtin.debug:
         msg: "device has interfaces named wlanX; this is unusual"
       when: interfaces_unformated_list | flatten | select('search', '^wlan.+') | length != 0
 
     # Set the length of the first host's interface list
     - name: Set length of the first host's interface list
-      set_fact:
+      ansible.builtin.set_fact:
         first_host_interface_length: "{{ interfaces_unformated_list | length }}"
       when: inventory_hostname == groups['all'][0]
 
     # Propagate the length to all hosts
     - name: Propagate first host's interface length to all hosts
-      set_fact:
+      ansible.builtin.set_fact:
         first_host_interface_length: "{{ hostvars[groups['all'][0]].first_host_interface_length }}"
       when: inventory_hostname != groups['all'][0]
 
     # Check if the lists are of the same length
-    - name: set failed flag if the number of interfaces is not the same across nodes
-      fail:
+    - name: Set failed flag if the number of interfaces is not the same across nodes
+      ansible.builtin.fail:
         msg: "The number of interfaces is not the same across hosts."
       when: interfaces_unformated_list | length != first_host_interface_length | int
-      ignore_errors: yes
+      ignore_errors: true
 
     # Check if any interface that is not wifi0 has a type other than unknown
-    - name: set failed flag if non-wifi0 interfaces have a type other than unknown (this means no monitor mode)
-      fail:
+    - name: Set failed flag if non-wifi0 interfaces have a type other than unknown (this means no monitor mode)
+      ansible.builtin.fail:
         msg: "wifiX interfaces found in non-monitor mode !!"
       when: interfaces_unformated_list | selectattr(2, 'ne', 'unknown') | selectattr(0, 'ne', 'wifi0') | list | length > 0
-      ignore_errors: yes
+      ignore_errors: true
 
-    - name: failure, stop the playbook
-      fail: 
+    - name: Failure ? stop the playbook
+      ansible.builtin.fail:
         msg: interfaces tests failed. check the two previous tasks !
       when: interfaces_unformated_list | selectattr(2, 'ne', 'unknown') | selectattr(0, 'ne', 'wifi0') | list | length > 0 or interfaces_unformated_list | length != first_host_interface_length | int
       any_errors_fatal: true
 
 
-    - debug:
-        msg: "Interfaces seem to be fine !"
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Interfaces seem fine !"
diff --git a/playbooks/test_meta.yml b/playbooks/test_meta.yml
index 05cba76..ce55621 100644
--- a/playbooks/test_meta.yml
+++ b/playbooks/test_meta.yml
@@ -1,4 +1,13 @@
-# - import_playbook: test_interfaces_status.yml
-# - import_playbook: test_GPIO_status.yml
-- import_playbook: test_systemctl_services.yml
+- name: Run all tests
+  hosts: sniffers
+  tasks: 
+    - ansible.builtin.debug:
+        msg: "global test ! Any failure will stop the tests"
+
 - import_playbook: test_time.yml
+- import_playbook: test_hostname.yml
+- import_playbook: test_packages.yml
+- import_playbook: test_interfaces_status.yml
+- import_playbook: test_systemctl_services.yml
+- import_playbook: test_config_files.yml
+- import_playbook: test_GPIO_GPS_PPS_status.yml
diff --git a/playbooks/test_packages.yml b/playbooks/test_packages.yml
new file mode 100644
index 0000000..2320b7b
--- /dev/null
+++ b/playbooks/test_packages.yml
@@ -0,0 +1,30 @@
+---
+- name: Check if packages are installed
+  hosts: sniffers
+  gather_facts: true
+  vars:
+    _packages:
+      # gps
+      - gpsd 
+      - gpsd-clients
+      - pps-tools
+      - chrony
+      # for the custom rtl8188 drivers
+      - git 
+      - bc 
+  tasks:
+    - name: Gather package facts
+      ansible.builtin.package_facts:
+        manager: auto
+      register: package_facts
+
+    - name: Display packages that are not installed
+      ansible.builtin.debug:
+        msg: "{{ item }} is not installed on {{ ansible_hostname }}"
+      with_items: "{{ _packages }}"
+      when: item not in package_facts.ansible_facts.packages
+      any_errors_fatal: true
+
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Packages seem fine !"
diff --git a/playbooks/test_systemctl_services.yml b/playbooks/test_systemctl_services.yml
index ca180ab..b86d196 100644
--- a/playbooks/test_systemctl_services.yml
+++ b/playbooks/test_systemctl_services.yml
@@ -1,4 +1,5 @@
-- hosts: sniffers
+- name: Check for presence of required packages in nodes
+  hosts: sniffers
   gather_facts: true
   any_errors_fatal: true
   vars:
@@ -18,35 +19,34 @@
       ]
 
   tasks:
-    - name: systemd existence checks
-      systemd: 
-        name: "{{item}}"
-      loop: "{{services_list.splitlines()}}"
+    - name: Systemd existence checks
+      ansible.builtin.systemd:
+        name: "{{ item }}"
+      loop: "{{ services_list.splitlines() }}"
       register: _test
 
 
     - name: Initialize service status list
-      set_fact:
+      ansible.builtin.set_fact:
         service_statuses: []
         newline: "\n"
 
 
     - name: Service status
-      set_fact:
-        service_statuses: "{{ service_statuses + [item.name+', '+item.status.LoadState + ' '+item.status.ActiveState + ' ' + item.status.SubState + ' ' + item.status.UnitFileState | default('does-not-exist')] }}"
-      loop: "{{_test.results}}"
+      ansible.builtin.set_fact:
+        service_statuses: "{{ service_statuses + [item.name + ', ' + item.status.LoadState + ' ' + item.status.ActiveState + ' ' + item.status.SubState + ' ' + item.status.UnitFileState | default('does-not-exist')] }}"
+      loop: "{{ _test.results }}"
       no_log: true
 
-    - name: print current statuses
-      debug:
-        msg: "{{service_statuses}}"
+    - name: Print current statuses
+      ansible.builtin.debug:
+        msg: "{{ service_statuses }}"
 
     - name: Failure check
-      fail: 
-        msg: "{{ansible_hostname}} failed systemctl checks"
-      when: "not service_statuses is subset(expected_statuses)"
+      ansible.builtin.fail:
+        msg: "{{ ansible_hostname }} failed systemd checks"
+      when: not service_statuses is subset(expected_statuses)
 
-    - debug:
-        msg: "systemctl and systemd seem to be fine !"
-
-    
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Systemctl and systemd services seem fine !"
diff --git a/playbooks/test_time.yml b/playbooks/test_time.yml
index 0fc1153..2d44f72 100644
--- a/playbooks/test_time.yml
+++ b/playbooks/test_time.yml
@@ -1,17 +1,35 @@
-# gets time for all hosts. 
-# %T is time; same as %H:%M:%S
-# %N     nanoseconds
-- hosts: sniffers
+---
+- name: Compare time since epoch between remote devices and the first node reached
+  hosts: sniffers
   gather_facts: false
+  vars:
+    first_node_time: 0
+
   tasks:
-    - name: date
-      command: date +"%T.%N"
-      register: result_date
 
-    - name: Time verification
+
+    - name: Get time since epoch on all nodes
+      ansible.builtin.command: date +%s%N
+      register: result_time
+      changed_when: false
+
+    - name: Set first node time
+      ansible.builtin.set_fact:
+        first_node_time: "{{ hostvars[groups['sniffers'][0]]['result_time'].stdout }}"
+      changed_when: false
+
+    - name: Compare time since epoch with the first node
       debug:
-        msg: "Time: {{ result_date.stdout }}"
-      
-    
+        msg: "{{ inventory_hostname }} is {{ 'behind' if result_time.stdout < first_node_time else 'ahead' if result_time.stdout > first_node_time else 'equal' }} the first node by {{ (result_time.stdout | int - first_node_time | int) / 1000000 }} milliseconds"
+      when: true
+
+
+    - name: Interrupt if dime diff is greater than one second
+      ansible.builtin.fail:
+        msg: "Cheack previous task ! Time seems off."
+      when: ((result_time.stdout | int - first_node_time | int) / 1000000) > 1000
+      any_errors_fatal: true
 
-    
+    - name: All good !
+      ansible.builtin.debug:
+        msg: "Time seems fine !"
-- 
GitLab