feat(ansible-role-remote_users_fact): set remote_users_fact_state default var
This commit is contained in:
@@ -1,6 +1,18 @@
|
|||||||
# remote_users_fact
|
# remote_users_fact
|
||||||
|
|
||||||
Rôle Ansible qui déploie un **local fact** comptant les sessions distantes par protocole (SSH, Citrix, Horizon) et évaluant la fiabilité en comparant avec `who`.
|
Rôle Ansible qui gère un **local fact** comptant les sessions distantes par protocole (SSH, Citrix, Horizon) et évaluant la fiabilité en comparant avec `who`.
|
||||||
|
|
||||||
|
## Gestion du state
|
||||||
|
|
||||||
|
Le rôle est piloté par la variable `remote_users_fact_state` :
|
||||||
|
|
||||||
|
| State | Comportement |
|
||||||
|
|---|---|
|
||||||
|
| `noop` (défaut) | Aucune action — le rôle ne touche à rien |
|
||||||
|
| `present` | Déploie le fact, valide le JSON, affiche le résumé |
|
||||||
|
| `absent` | Supprime le fact, purge ansible_local, nettoie le répertoire si vide |
|
||||||
|
|
||||||
|
Le state peut être défini à tout niveau (all, groupe, hôte, extra-vars). `noop` par défaut garantit qu'un hôte ajouté à l'inventaire sans configuration explicite ne sera pas impacté.
|
||||||
|
|
||||||
## Arborescence
|
## Arborescence
|
||||||
|
|
||||||
@@ -10,37 +22,47 @@ Rôle Ansible qui déploie un **local fact** comptant les sessions distantes par
|
|||||||
│ └── hosts.yml # Inventaire exemple
|
│ └── hosts.yml # Inventaire exemple
|
||||||
└── roles/
|
└── roles/
|
||||||
└── remote_users_fact/
|
└── remote_users_fact/
|
||||||
├── defaults/main.yml # Variables par défaut
|
├── defaults/main.yml # Variables (dont state)
|
||||||
├── files/remote_users.fact # Script fact déployé
|
├── files/remote_users.fact # Script fact
|
||||||
├── handlers/main.yml # Handler rechargement facts
|
├── handlers/main.yml # Rechargement facts
|
||||||
├── meta/main.yml # Métadonnées Galaxy
|
├── meta/main.yml # Métadonnées Galaxy
|
||||||
└── tasks/
|
└── tasks/
|
||||||
├── main.yml # Orchestration
|
├── main.yml # Assertions → routage par state
|
||||||
├── deploy.yml # Création répertoire + copie
|
├── assert.yml # Validation stricte du paramétrage
|
||||||
├── validate.yml # Exécution + parsing JSON
|
├── present.yml # Déploiement (state=present)
|
||||||
└── summary.yml # Affichage résumé + alertes
|
├── absent.yml # Suppression (state=absent)
|
||||||
|
├── validate.yml # Exécution + assert structure JSON
|
||||||
|
└── summary.yml # Affichage matrice + alertes
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Déploiement complet
|
# Appliquer le state défini dans l'inventaire
|
||||||
ansible-playbook -i inventories/hosts.yml site.yml
|
ansible-playbook -i inventories/hosts.yml site.yml
|
||||||
|
|
||||||
# Déploiement seul
|
# Forcer le déploiement partout (override)
|
||||||
ansible-playbook -i inventories/hosts.yml site.yml --tags deploy
|
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=present
|
||||||
|
|
||||||
# Vérification seule (fact déjà déployé)
|
# Supprimer partout
|
||||||
ansible-playbook -i inventories/hosts.yml site.yml --tags validate,summary
|
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=absent
|
||||||
|
|
||||||
# Sur un groupe spécifique
|
# Sur un groupe spécifique
|
||||||
ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
|
ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
|
||||||
|
|
||||||
|
# Tags disponibles
|
||||||
|
ansible-playbook ... --tags assert # Assertions seules
|
||||||
|
ansible-playbook ... --tags present,deploy # Déploiement seul
|
||||||
|
ansible-playbook ... --tags validate # Validation seule
|
||||||
|
ansible-playbook ... --tags summary # Résumé seul
|
||||||
|
ansible-playbook ... --tags absent,remove # Suppression seule
|
||||||
```
|
```
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
| Variable | Défaut | Description |
|
| Variable | Défaut | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| `remote_users_fact_state` | `noop` | `present` / `absent` / `noop` |
|
||||||
| `remote_users_fact_dir` | `/etc/ansible/facts.d` | Répertoire de destination |
|
| `remote_users_fact_dir` | `/etc/ansible/facts.d` | Répertoire de destination |
|
||||||
| `remote_users_fact_name` | `remote_users.fact` | Nom du script |
|
| `remote_users_fact_name` | `remote_users.fact` | Nom du script |
|
||||||
| `remote_users_fact_owner` | `root` | Propriétaire |
|
| `remote_users_fact_owner` | `root` | Propriétaire |
|
||||||
@@ -49,6 +71,26 @@ ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
|
|||||||
| `remote_users_fact_display_summary` | `true` | Afficher le résumé |
|
| `remote_users_fact_display_summary` | `true` | Afficher le résumé |
|
||||||
| `remote_users_fact_warn_verdicts` | voir defaults | Verdicts déclenchant un warning |
|
| `remote_users_fact_warn_verdicts` | voir defaults | Verdicts déclenchant un warning |
|
||||||
|
|
||||||
|
## Assertions
|
||||||
|
|
||||||
|
Le rôle valide le paramétrage **avant** toute action :
|
||||||
|
|
||||||
|
- `remote_users_fact_state` est défini et vaut `present`, `absent` ou `noop`
|
||||||
|
- `remote_users_fact_dir` est un chemin absolu (si state != noop)
|
||||||
|
- `remote_users_fact_name` respecte le pattern `*.fact` (si state != noop)
|
||||||
|
- `remote_users_fact_owner` et `group` sont définis (si state == present)
|
||||||
|
- `remote_users_fact_validate` et `display_summary` sont des booléens
|
||||||
|
- `remote_users_fact_warn_verdicts` est une liste de verdicts valides
|
||||||
|
|
||||||
|
En cas de state `present`, la validation post-déploiement vérifie aussi :
|
||||||
|
- Le script s'exécute sans erreur (rc == 0)
|
||||||
|
- La sortie est du JSON parsable
|
||||||
|
- Toutes les clés obligatoires sont présentes
|
||||||
|
- Les compteurs sont >= 0
|
||||||
|
- `total_by_protocol == ssh + citrix + horizon`
|
||||||
|
- Le verdict est dans la liste des verdicts connus
|
||||||
|
- Le fact est chargé dans `ansible_local`
|
||||||
|
|
||||||
## Fact déployé
|
## Fact déployé
|
||||||
|
|
||||||
Accessible via `ansible_local.remote_users` :
|
Accessible via `ansible_local.remote_users` :
|
||||||
@@ -84,21 +126,48 @@ Accessible via `ansible_local.remote_users` :
|
|||||||
| Verdict | Signification |
|
| Verdict | Signification |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `FIABLE` | who == total → compteurs alignés |
|
| `FIABLE` | who == total → compteurs alignés |
|
||||||
| `OK` | Écart ≤ 1 → tolérable |
|
| `OK` | Écart <= 1 → tolérable |
|
||||||
| `WHO_SUP_TOTAL` | who > total → protocole non surveillé |
|
| `WHO_SUP_TOTAL` | who > total → protocole non surveillé |
|
||||||
| `WHO_INF_TOTAL` | who < total → sessions headless sans TTY |
|
| `WHO_INF_TOTAL` | who < total → sessions headless sans TTY |
|
||||||
| `WHO_SEUL` | total == 0 → protocoles non détectés |
|
| `WHO_SEUL` | total == 0 → protocoles non détectés |
|
||||||
| `PROTO_SEUL` | who == 0 → sessions sans allocation TTY |
|
| `PROTO_SEUL` | who == 0 → sessions sans allocation TTY |
|
||||||
| `NEUTRE` | 0 == 0 → aucune session |
|
| `NEUTRE` | 0 == 0 → aucune session |
|
||||||
|
|
||||||
|
## Exemple d'inventaire avec states
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
all:
|
||||||
|
vars:
|
||||||
|
remote_users_fact_state: present # Défaut global
|
||||||
|
|
||||||
|
children:
|
||||||
|
prod_servers:
|
||||||
|
hosts:
|
||||||
|
srv-01: {}
|
||||||
|
srv-02: {}
|
||||||
|
|
||||||
|
# Hôte exclu
|
||||||
|
dev_servers:
|
||||||
|
hosts:
|
||||||
|
dev-01:
|
||||||
|
remote_users_fact_state: noop
|
||||||
|
|
||||||
|
# Groupe en décommission
|
||||||
|
legacy:
|
||||||
|
vars:
|
||||||
|
remote_users_fact_state: absent
|
||||||
|
```
|
||||||
|
|
||||||
## Utilisation dans d'autres playbooks
|
## Utilisation dans d'autres playbooks
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- hosts: all
|
- hosts: all
|
||||||
gather_facts: true
|
gather_facts: true
|
||||||
tasks:
|
tasks:
|
||||||
- name: Refuser un déploiement si trop de sessions actives
|
- name: Bloquer un déploiement si trop de sessions
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: "{{ ansible_local.remote_users.sessions.total_by_protocol }} sessions actives, déploiement annulé"
|
msg: "{{ ansible_local.remote_users.sessions.total_by_protocol }} sessions actives"
|
||||||
when: ansible_local.remote_users.sessions.total_by_protocol | int > 10
|
when:
|
||||||
|
- ansible_local.remote_users is defined
|
||||||
|
- ansible_local.remote_users.sessions.total_by_protocol | int > 10
|
||||||
```
|
```
|
||||||
|
|||||||
+33
-7
@@ -1,9 +1,29 @@
|
|||||||
---
|
---
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# inventories/hosts.yml — Exemple d'inventaire
|
# inventories/hosts.yml — Exemple d'inventaire avec gestion du state
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# remote_users_fact_state:
|
||||||
|
# present → déploie le fact
|
||||||
|
# absent → supprime le fact
|
||||||
|
# noop → ne fait rien (défaut si non spécifié)
|
||||||
|
#
|
||||||
|
# Le state peut être défini à n'importe quel niveau :
|
||||||
|
# - all:vars → défaut global
|
||||||
|
# - group:vars → surcharge par groupe
|
||||||
|
# - host:vars → surcharge par hôte
|
||||||
|
# - extra-vars (-e) → surcharge absolue
|
||||||
|
#
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
vars:
|
||||||
|
ansible_user: ansible
|
||||||
|
ansible_become: true
|
||||||
|
ansible_become_method: sudo
|
||||||
|
# Défaut global : déployer partout
|
||||||
|
remote_users_fact_state: present
|
||||||
|
|
||||||
children:
|
children:
|
||||||
|
|
||||||
ssh_servers:
|
ssh_servers:
|
||||||
@@ -12,6 +32,10 @@ all:
|
|||||||
ansible_host: 192.168.1.10
|
ansible_host: 192.168.1.10
|
||||||
srv-linux-02:
|
srv-linux-02:
|
||||||
ansible_host: 192.168.1.11
|
ansible_host: 192.168.1.11
|
||||||
|
# Exemple : désactiver sur un hôte spécifique
|
||||||
|
srv-linux-03:
|
||||||
|
ansible_host: 192.168.1.12
|
||||||
|
remote_users_fact_state: noop
|
||||||
|
|
||||||
citrix_servers:
|
citrix_servers:
|
||||||
hosts:
|
hosts:
|
||||||
@@ -20,8 +44,7 @@ all:
|
|||||||
ctx-vda-02:
|
ctx-vda-02:
|
||||||
ansible_host: 192.168.2.11
|
ansible_host: 192.168.2.11
|
||||||
vars:
|
vars:
|
||||||
# Optionnel : surcharger les verdicts d'alerte pour Citrix
|
# Surcharge par groupe : WHO_INF_TOTAL est normal sur Citrix
|
||||||
# car WHO_INF_TOTAL est fréquent (apps publiées sans TTY)
|
|
||||||
remote_users_fact_warn_verdicts:
|
remote_users_fact_warn_verdicts:
|
||||||
- WHO_SUP_TOTAL
|
- WHO_SUP_TOTAL
|
||||||
- WHO_SEUL
|
- WHO_SEUL
|
||||||
@@ -33,7 +56,10 @@ all:
|
|||||||
hrz-agent-02:
|
hrz-agent-02:
|
||||||
ansible_host: 192.168.3.11
|
ansible_host: 192.168.3.11
|
||||||
|
|
||||||
vars:
|
# Exemple : groupe en cours de décommission
|
||||||
ansible_user: ansible
|
legacy_servers:
|
||||||
ansible_become: true
|
hosts:
|
||||||
ansible_become_method: sudo
|
old-srv-01:
|
||||||
|
ansible_host: 192.168.9.10
|
||||||
|
vars:
|
||||||
|
remote_users_fact_state: absent
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
# defaults/main.yml — Variables par défaut du rôle remote_users_fact
|
# defaults/main.yml — Variables par défaut du rôle remote_users_fact
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
# État souhaité du fact :
|
||||||
|
# present → déploie le fact + validation + résumé
|
||||||
|
# absent → supprime le fact + recharge les facts
|
||||||
|
# noop → ne fait rien (utile pour désactiver par host/groupe)
|
||||||
|
remote_users_fact_state: noop
|
||||||
|
|
||||||
# Répertoire de destination des local facts
|
# Répertoire de destination des local facts
|
||||||
remote_users_fact_dir: /etc/ansible/facts.d
|
remote_users_fact_dir: /etc/ansible/facts.d
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
# =============================================================================
|
||||||
|
# tasks/absent.yml — Suppression du fact (state=absent)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- name: "Absent | Vérifier si le fact existe"
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
|
||||||
|
register: _remote_users_fact_file
|
||||||
|
|
||||||
|
- name: "Absent | Supprimer le script remote_users.fact"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
|
||||||
|
state: absent
|
||||||
|
register: _remote_users_fact_removed
|
||||||
|
when: _remote_users_fact_file.stat.exists
|
||||||
|
notify: Recharger les local facts
|
||||||
|
|
||||||
|
- name: "Absent | Recharger les facts pour purger ansible_local"
|
||||||
|
ansible.builtin.setup:
|
||||||
|
filter: ansible_local
|
||||||
|
when: _remote_users_fact_removed.changed | default(false)
|
||||||
|
|
||||||
|
- name: "Absent | Vérifier que le fact n'est plus chargé"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- ansible_local.remote_users is not defined
|
||||||
|
fail_msg: >-
|
||||||
|
Le fact remote_users est toujours présent dans ansible_local
|
||||||
|
après suppression. Vérifier le rechargement des facts.
|
||||||
|
success_msg: "Fact remote_users correctement supprimé et purgé d'ansible_local"
|
||||||
|
when: _remote_users_fact_removed.changed | default(false)
|
||||||
|
|
||||||
|
- name: "Absent | Info suppression"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
{{ 'Fact supprimé de ' ~ remote_users_fact_dir
|
||||||
|
if _remote_users_fact_removed.changed | default(false)
|
||||||
|
else 'Fact déjà absent, rien à faire' }}
|
||||||
|
|
||||||
|
- name: "Absent | Nettoyer le répertoire facts.d si vide"
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "find {{ remote_users_fact_dir }} -maxdepth 0 -empty -type d"
|
||||||
|
register: _remote_users_factdir_empty
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "Absent | Supprimer le répertoire facts.d si vide"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ remote_users_fact_dir }}"
|
||||||
|
state: absent
|
||||||
|
when: _remote_users_factdir_empty.stdout | length > 0
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
---
|
||||||
|
# =============================================================================
|
||||||
|
# tasks/assert.yml — Validation stricte du paramétrage avant exécution
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_state est défini"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_state is defined
|
||||||
|
- remote_users_fact_state | length > 0
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_state n'est pas défini.
|
||||||
|
Valeurs acceptées : present, absent, noop
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_state contient une valeur valide"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_state in _remote_users_fact_valid_states
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_state='{{ remote_users_fact_state }}' invalide.
|
||||||
|
Valeurs acceptées : {{ _remote_users_fact_valid_states | join(', ') }}
|
||||||
|
quiet: true
|
||||||
|
vars:
|
||||||
|
_remote_users_fact_valid_states:
|
||||||
|
- present
|
||||||
|
- absent
|
||||||
|
- noop
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_dir est un chemin absolu"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_dir is defined
|
||||||
|
- remote_users_fact_dir | length > 0
|
||||||
|
- remote_users_fact_dir is match('^/')
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_dir='{{ remote_users_fact_dir | default('') }}'
|
||||||
|
doit être un chemin absolu (ex: /etc/ansible/facts.d)
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state != "noop"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_name est défini et valide"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_name is defined
|
||||||
|
- remote_users_fact_name | length > 0
|
||||||
|
- remote_users_fact_name is match('^[a-zA-Z0-9_.-]+\.fact$')
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_name='{{ remote_users_fact_name | default('') }}'
|
||||||
|
doit correspondre au pattern [a-zA-Z0-9_.-]+.fact
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state != "noop"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_owner est défini"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_owner is defined
|
||||||
|
- remote_users_fact_owner | length > 0
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_owner ne peut pas être vide
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_group est défini"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_group is defined
|
||||||
|
- remote_users_fact_group | length > 0
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_group ne peut pas être vide
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_validate est un booléen"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_validate | string | lower in ['true', 'false', 'yes', 'no']
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_validate='{{ remote_users_fact_validate }}'
|
||||||
|
doit être un booléen (true/false)
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_display_summary est un booléen"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_display_summary | string | lower in ['true', 'false', 'yes', 'no']
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_display_summary='{{ remote_users_fact_display_summary }}'
|
||||||
|
doit être un booléen (true/false)
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_warn_verdicts est une liste"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- remote_users_fact_warn_verdicts is defined
|
||||||
|
- remote_users_fact_warn_verdicts is iterable
|
||||||
|
- remote_users_fact_warn_verdicts is not string
|
||||||
|
fail_msg: >-
|
||||||
|
remote_users_fact_warn_verdicts doit être une liste
|
||||||
|
(ex: [WHO_SUP_TOTAL, WHO_INF_TOTAL])
|
||||||
|
quiet: true
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | remote_users_fact_warn_verdicts contient des verdicts valides"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- item in _remote_users_fact_valid_verdicts
|
||||||
|
fail_msg: >-
|
||||||
|
Verdict '{{ item }}' invalide dans remote_users_fact_warn_verdicts.
|
||||||
|
Valeurs acceptées : {{ _remote_users_fact_valid_verdicts | join(', ') }}
|
||||||
|
quiet: true
|
||||||
|
loop: "{{ remote_users_fact_warn_verdicts }}"
|
||||||
|
vars:
|
||||||
|
_remote_users_fact_valid_verdicts:
|
||||||
|
- FIABLE
|
||||||
|
- OK
|
||||||
|
- NEUTRE
|
||||||
|
- WHO_SUP_TOTAL
|
||||||
|
- WHO_INF_TOTAL
|
||||||
|
- WHO_SEUL
|
||||||
|
- PROTO_SEUL
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
|
||||||
|
- name: "Assert | Résumé du paramétrage validé"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
Assertions OK — state={{ remote_users_fact_state }}
|
||||||
|
{% if remote_users_fact_state == 'present' %}
|
||||||
|
dir={{ remote_users_fact_dir }}
|
||||||
|
name={{ remote_users_fact_name }}
|
||||||
|
validate={{ remote_users_fact_validate }}
|
||||||
|
summary={{ remote_users_fact_display_summary }}
|
||||||
|
{% endif %}
|
||||||
@@ -1,24 +1,55 @@
|
|||||||
---
|
---
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# tasks/main.yml — Déploiement et validation du local fact remote_users
|
# tasks/main.yml — Point d'entrée : assertions puis routage par état
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
- name: Inclure les tâches de déploiement
|
- name: Inclure les assertions de paramétrage
|
||||||
ansible.builtin.include_tasks: deploy.yml
|
ansible.builtin.include_tasks: assert.yml
|
||||||
tags:
|
tags:
|
||||||
- remote_users_fact
|
- remote_users_fact
|
||||||
|
- assert
|
||||||
|
|
||||||
|
- name: "État noop — aucune action"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
remote_users_fact_state=noop sur {{ inventory_hostname }},
|
||||||
|
aucune action effectuée.
|
||||||
|
when: remote_users_fact_state == "noop"
|
||||||
|
tags:
|
||||||
|
- remote_users_fact
|
||||||
|
|
||||||
|
- name: "État present — déploiement du fact"
|
||||||
|
ansible.builtin.include_tasks: present.yml
|
||||||
|
when: remote_users_fact_state == "present"
|
||||||
|
tags:
|
||||||
|
- remote_users_fact
|
||||||
|
- present
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
- name: Inclure les tâches de validation
|
- name: "État present — validation"
|
||||||
ansible.builtin.include_tasks: validate.yml
|
ansible.builtin.include_tasks: validate.yml
|
||||||
when: remote_users_fact_validate | bool
|
when:
|
||||||
|
- remote_users_fact_state == "present"
|
||||||
|
- remote_users_fact_validate | bool
|
||||||
tags:
|
tags:
|
||||||
- remote_users_fact
|
- remote_users_fact
|
||||||
|
- present
|
||||||
- validate
|
- validate
|
||||||
|
|
||||||
- name: Inclure les tâches de résumé
|
- name: "État present — résumé"
|
||||||
ansible.builtin.include_tasks: summary.yml
|
ansible.builtin.include_tasks: summary.yml
|
||||||
when: remote_users_fact_display_summary | bool
|
when:
|
||||||
|
- remote_users_fact_state == "present"
|
||||||
|
- remote_users_fact_display_summary | bool
|
||||||
tags:
|
tags:
|
||||||
- remote_users_fact
|
- remote_users_fact
|
||||||
|
- present
|
||||||
- summary
|
- summary
|
||||||
|
|
||||||
|
- name: "État absent — suppression du fact"
|
||||||
|
ansible.builtin.include_tasks: absent.yml
|
||||||
|
when: remote_users_fact_state == "absent"
|
||||||
|
tags:
|
||||||
|
- remote_users_fact
|
||||||
|
- absent
|
||||||
|
- remove
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# =============================================================================
|
||||||
|
# tasks/present.yml — Déploiement du fact (state=present)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- name: "Present | Créer le répertoire facts.d"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ remote_users_fact_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ remote_users_fact_owner }}"
|
||||||
|
group: "{{ remote_users_fact_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: "Present | Déployer le script remote_users.fact"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ remote_users_fact_name }}"
|
||||||
|
dest: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
|
||||||
|
owner: "{{ remote_users_fact_owner }}"
|
||||||
|
group: "{{ remote_users_fact_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
backup: true
|
||||||
|
register: _remote_users_fact_deployed
|
||||||
|
notify: Recharger les local facts
|
||||||
|
|
||||||
|
- name: "Present | Info déploiement"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
Fact {{ 'mis à jour' if _remote_users_fact_deployed.changed else 'déjà en place' }}
|
||||||
|
→ {{ remote_users_fact_dir }}/{{ remote_users_fact_name }}
|
||||||
@@ -3,11 +3,12 @@
|
|||||||
# tasks/summary.yml — Affichage du résumé et alertes éventuelles
|
# tasks/summary.yml — Affichage du résumé et alertes éventuelles
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
- name: Afficher le résumé des sessions distantes
|
- name: "Summary | Résumé des sessions distantes"
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg:
|
msg:
|
||||||
- "══════════════════════════════════════════"
|
- "══════════════════════════════════════════"
|
||||||
- "Host : {{ inventory_hostname }}"
|
- "Host : {{ inventory_hostname }}"
|
||||||
|
- "State : {{ remote_users_fact_state }}"
|
||||||
- "Timestamp : {{ ansible_local.remote_users.timestamp }}"
|
- "Timestamp : {{ ansible_local.remote_users.timestamp }}"
|
||||||
- "──────────────────────────────────────────"
|
- "──────────────────────────────────────────"
|
||||||
- "SSH : {{ ansible_local.remote_users.sessions.ssh }}"
|
- "SSH : {{ ansible_local.remote_users.sessions.ssh }}"
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
- "Horizon Agt : {{ ansible_local.remote_users.detection.horizon_agent_installed }}"
|
- "Horizon Agt : {{ ansible_local.remote_users.detection.horizon_agent_installed }}"
|
||||||
- "══════════════════════════════════════════"
|
- "══════════════════════════════════════════"
|
||||||
|
|
||||||
- name: Alerter si le verdict est anormal
|
- name: "Summary | Alerte si verdict anormal"
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: >-
|
msg: >-
|
||||||
⚠ ATTENTION sur {{ inventory_hostname }} —
|
⚠ ATTENTION sur {{ inventory_hostname }} —
|
||||||
|
|||||||
@@ -3,35 +3,111 @@
|
|||||||
# tasks/validate.yml — Validation du fact (exécution + parsing JSON)
|
# tasks/validate.yml — Validation du fact (exécution + parsing JSON)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
- name: Forcer le rechargement des facts si déploiement effectué
|
- name: "Validate | Forcer le rechargement des facts"
|
||||||
ansible.builtin.meta: flush_handlers
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
- name: Exécuter le script fact manuellement pour validation
|
- name: "Validate | Exécuter le script fact pour validation"
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
cmd: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
|
cmd: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
|
||||||
register: _remote_users_fact_output
|
register: _remote_users_fact_output
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: _remote_users_fact_output.rc != 0
|
failed_when: _remote_users_fact_output.rc != 0
|
||||||
|
|
||||||
- name: Valider que la sortie est du JSON parsable
|
- name: "Validate | Parser la sortie JSON"
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
_remote_users_fact_parsed: "{{ _remote_users_fact_output.stdout | from_json }}"
|
_remote_users_fact_parsed: "{{ _remote_users_fact_output.stdout | from_json }}"
|
||||||
|
|
||||||
- name: Vérifier la présence des clés obligatoires
|
- name: "Validate | Vérifier la structure JSON — clés racine"
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
|
- _remote_users_fact_parsed.timestamp is defined
|
||||||
- _remote_users_fact_parsed.sessions is defined
|
- _remote_users_fact_parsed.sessions is defined
|
||||||
|
- _remote_users_fact_parsed.users_remote is defined
|
||||||
|
- _remote_users_fact_parsed.reliability is defined
|
||||||
|
- _remote_users_fact_parsed.detection is defined
|
||||||
|
fail_msg: "Clés racine manquantes dans la sortie JSON du fact"
|
||||||
|
success_msg: "Clés racine OK"
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: "Validate | Vérifier la structure JSON — sessions"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
- _remote_users_fact_parsed.sessions.ssh is defined
|
- _remote_users_fact_parsed.sessions.ssh is defined
|
||||||
- _remote_users_fact_parsed.sessions.citrix is defined
|
- _remote_users_fact_parsed.sessions.citrix is defined
|
||||||
- _remote_users_fact_parsed.sessions.horizon is defined
|
- _remote_users_fact_parsed.sessions.horizon is defined
|
||||||
- _remote_users_fact_parsed.sessions.total_by_protocol is defined
|
- _remote_users_fact_parsed.sessions.total_by_protocol is defined
|
||||||
- _remote_users_fact_parsed.sessions.who_remote is defined
|
- _remote_users_fact_parsed.sessions.who_remote is defined
|
||||||
- _remote_users_fact_parsed.reliability is defined
|
- _remote_users_fact_parsed.sessions.ssh | int >= 0
|
||||||
- _remote_users_fact_parsed.reliability.verdict is defined
|
- _remote_users_fact_parsed.sessions.citrix | int >= 0
|
||||||
- _remote_users_fact_parsed.detection is defined
|
- _remote_users_fact_parsed.sessions.horizon | int >= 0
|
||||||
fail_msg: "Le fact remote_users ne retourne pas la structure JSON attendue"
|
- _remote_users_fact_parsed.sessions.total_by_protocol | int >= 0
|
||||||
success_msg: "Structure JSON validée avec succès"
|
- _remote_users_fact_parsed.sessions.who_remote | int >= 0
|
||||||
|
fail_msg: "Structure 'sessions' invalide ou valeurs négatives"
|
||||||
|
success_msg: "Structure sessions OK"
|
||||||
|
quiet: true
|
||||||
|
|
||||||
- name: Recharger les ansible_local facts
|
- name: "Validate | Vérifier la cohérence total = ssh + citrix + horizon"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- >-
|
||||||
|
_remote_users_fact_parsed.sessions.total_by_protocol | int ==
|
||||||
|
(_remote_users_fact_parsed.sessions.ssh | int +
|
||||||
|
_remote_users_fact_parsed.sessions.citrix | int +
|
||||||
|
_remote_users_fact_parsed.sessions.horizon | int)
|
||||||
|
fail_msg: >-
|
||||||
|
total_by_protocol ({{ _remote_users_fact_parsed.sessions.total_by_protocol }})
|
||||||
|
!= ssh+citrix+horizon
|
||||||
|
({{ _remote_users_fact_parsed.sessions.ssh }}
|
||||||
|
+{{ _remote_users_fact_parsed.sessions.citrix }}
|
||||||
|
+{{ _remote_users_fact_parsed.sessions.horizon }})
|
||||||
|
success_msg: "Cohérence total OK"
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: "Validate | Vérifier la structure JSON — reliability"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- _remote_users_fact_parsed.reliability.ratio_who_over_total is defined
|
||||||
|
- _remote_users_fact_parsed.reliability.verdict is defined
|
||||||
|
- _remote_users_fact_parsed.reliability.detail is defined
|
||||||
|
- _remote_users_fact_parsed.reliability.verdict in _remote_users_fact_valid_verdicts
|
||||||
|
fail_msg: >-
|
||||||
|
Structure 'reliability' invalide ou verdict inconnu :
|
||||||
|
'{{ _remote_users_fact_parsed.reliability.verdict | default('UNDEFINED') }}'
|
||||||
|
success_msg: "Structure reliability OK"
|
||||||
|
quiet: true
|
||||||
|
vars:
|
||||||
|
_remote_users_fact_valid_verdicts:
|
||||||
|
- FIABLE
|
||||||
|
- OK
|
||||||
|
- NEUTRE
|
||||||
|
- WHO_SUP_TOTAL
|
||||||
|
- WHO_INF_TOTAL
|
||||||
|
- WHO_SEUL
|
||||||
|
- PROTO_SEUL
|
||||||
|
|
||||||
|
- name: "Validate | Vérifier la structure JSON — detection"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- _remote_users_fact_parsed.detection.citrix_vda_installed is defined
|
||||||
|
- _remote_users_fact_parsed.detection.horizon_agent_installed is defined
|
||||||
|
- _remote_users_fact_parsed.detection.ssh_method is defined
|
||||||
|
- _remote_users_fact_parsed.detection.citrix_method is defined
|
||||||
|
- _remote_users_fact_parsed.detection.horizon_method is defined
|
||||||
|
fail_msg: "Structure 'detection' invalide"
|
||||||
|
success_msg: "Structure detection OK"
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: "Validate | Recharger ansible_local"
|
||||||
ansible.builtin.setup:
|
ansible.builtin.setup:
|
||||||
filter: ansible_local
|
filter: ansible_local
|
||||||
|
|
||||||
|
- name: "Validate | Confirmer la présence dans ansible_local"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- ansible_local.remote_users is defined
|
||||||
|
- ansible_local.remote_users.sessions is defined
|
||||||
|
- ansible_local.remote_users.reliability is defined
|
||||||
|
fail_msg: >-
|
||||||
|
Le fact remote_users n'est pas visible dans ansible_local
|
||||||
|
après rechargement. Vérifier les permissions et le format.
|
||||||
|
success_msg: "Fact remote_users chargé dans ansible_local avec succès"
|
||||||
|
|||||||
@@ -1,23 +1,33 @@
|
|||||||
---
|
---
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# site.yml — Playbook de déploiement du local fact remote_users
|
# site.yml — Playbook de gestion du local fact remote_users
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
#
|
#
|
||||||
# Usage :
|
# Usage :
|
||||||
|
# # Déployer sur tous les hôtes (state défini dans l'inventaire) :
|
||||||
# ansible-playbook -i inventories/hosts.yml site.yml
|
# ansible-playbook -i inventories/hosts.yml site.yml
|
||||||
#
|
#
|
||||||
# # Déploiement seul (sans validation ni résumé) :
|
# # Forcer le déploiement sur tous (override du state) :
|
||||||
# ansible-playbook -i inventories/hosts.yml site.yml --tags deploy
|
# ansible-playbook -i inventories/hosts.yml site.yml \
|
||||||
|
# -e remote_users_fact_state=present
|
||||||
#
|
#
|
||||||
# # Validation + résumé seul (fact déjà déployé) :
|
# # Supprimer partout :
|
||||||
# ansible-playbook -i inventories/hosts.yml site.yml --tags validate,summary
|
# ansible-playbook -i inventories/hosts.yml site.yml \
|
||||||
|
# -e remote_users_fact_state=absent
|
||||||
#
|
#
|
||||||
# # Limiter à un groupe :
|
# # Limiter à un groupe :
|
||||||
# ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
|
# ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
|
||||||
#
|
#
|
||||||
|
# # Tags disponibles :
|
||||||
|
# --tags assert → assertions seules
|
||||||
|
# --tags present,deploy → déploiement seul
|
||||||
|
# --tags validate → validation seule
|
||||||
|
# --tags summary → résumé seul
|
||||||
|
# --tags absent,remove → suppression seule
|
||||||
|
#
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
- name: Déployer et valider le local fact remote_users
|
- name: Gérer le local fact remote_users
|
||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
gather_facts: true
|
gather_facts: true
|
||||||
|
|||||||
Reference in New Issue
Block a user