2026-04-13 23:25:51 +02:00
# remote_users_fact
2026-04-13 23:40:52 +02:00
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 |
2026-04-14 00:30:05 +02:00
| --- | --- |
2026-04-13 23:40:52 +02:00
| `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é.
2026-04-13 23:25:51 +02:00
## Arborescence
2026-04-14 00:31:25 +02:00
``` text
2026-04-13 23:25:51 +02:00
├── site.yml # Playbook principal
├── inventories/
│ └── hosts.yml # Inventaire exemple
└── roles/
└── remote_users_fact/
2026-04-13 23:40:52 +02:00
├── defaults/main.yml # Variables (dont state)
├── files/remote_users.fact # Script fact
├── handlers/main.yml # Rechargement facts
2026-04-13 23:25:51 +02:00
├── meta/main.yml # Métadonnées Galaxy
└── tasks/
2026-04-13 23:40:52 +02:00
├── main.yml # Assertions → routage par state
├── assert.yml # Validation stricte du paramétrage
├── present.yml # Déploiement (state=present)
├── absent.yml # Suppression (state=absent)
├── validate.yml # Exécution + assert structure JSON
└── summary.yml # Affichage matrice + alertes
2026-04-13 23:25:51 +02:00
```
## Usage
``` bash
2026-04-13 23:40:52 +02:00
# Appliquer le state défini dans l'inventaire
2026-04-13 23:25:51 +02:00
ansible-playbook -i inventories/hosts.yml site.yml
2026-04-13 23:40:52 +02:00
# Forcer le déploiement partout (override)
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state = present
2026-04-13 23:25:51 +02:00
2026-04-13 23:40:52 +02:00
# Supprimer partout
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state = absent
2026-04-13 23:25:51 +02:00
# Sur un groupe spécifique
ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers
2026-04-13 23:40:52 +02:00
# 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
2026-04-13 23:25:51 +02:00
```
## Variables
| Variable | Défaut | Description |
2026-04-14 00:30:05 +02:00
| --- | --- | --- |
2026-04-13 23:40:52 +02:00
| `remote_users_fact_state` | `noop` | `present` / `absent` / `noop` |
2026-04-13 23:25:51 +02:00
| `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_owner` | `root` | Propriétaire |
| `remote_users_fact_group` | `root` | Groupe |
| `remote_users_fact_validate` | `true` | Activer la validation post-deploy |
| `remote_users_fact_display_summary` | `true` | Afficher le résumé |
| `remote_users_fact_warn_verdicts` | voir defaults | Verdicts déclenchant un warning |
2026-04-13 23:40:52 +02:00
## 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 :
2026-04-14 00:31:25 +02:00
2026-04-13 23:40:52 +02:00
- 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`
2026-04-13 23:25:51 +02:00
## Fact déployé
Accessible via `ansible_local.remote_users` :
``` json
{
"timestamp" : "2026-04-13T10:30:00Z" ,
"sessions" : {
"ssh" : 3 ,
"citrix" : 12 ,
"horizon" : 0 ,
"total_by_protocol" : 15 ,
"who_remote" : 14
} ,
"users_remote" : "alice,bob,charlie" ,
"reliability" : {
"ratio_who_over_total" : 0.93 ,
"verdict" : "WHO_INF_TOTAL" ,
"detail" : "who manque 1 session(s) sans TTY"
} ,
"detection" : {
"citrix_vda_installed" : true ,
"horizon_agent_installed" : false ,
"ssh_method" : "sshd_process_and_ss" ,
"citrix_method" : "ctxquery" ,
"horizon_method" : "fallback_ports"
}
}
```
## Verdicts
| Verdict | Signification |
2026-04-14 00:30:05 +02:00
| --- | --- |
2026-04-13 23:25:51 +02:00
| `FIABLE` | who == total → compteurs alignés |
2026-04-13 23:40:52 +02:00
| `OK` | Écart <= 1 → tolérable |
2026-04-13 23:25:51 +02:00
| `WHO_SUP_TOTAL` | who > total → protocole non surveillé |
| `WHO_INF_TOTAL` | who < total → sessions headless sans TTY |
| `WHO_SEUL` | total == 0 → protocoles non détectés |
| `PROTO_SEUL` | who == 0 → sessions sans allocation TTY |
| `NEUTRE` | 0 == 0 → aucune session |
2026-04-13 23:40:52 +02:00
## 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
```
2026-04-14 00:28:40 +02:00
## CI / Tests
Le rôle est testé automatiquement sur toutes les distributions déclarées dans `meta/main.yml` via Docker.
### Commandes Make
``` bash
make help # Affiche les cibles disponibles
make matrix # Affiche la matrice JSON des distros
make lint # yamllint + ansible-lint
make test # Teste toutes les distros
make test-el9 # Teste une seule distro
make clean # Supprime les images Docker de test
```
### Registry privée
Par défaut les images sont tirées depuis Docker Hub. Pour utiliser une registry privée (Artifactory, Harbor, etc.), définir les variables d'environnement :
| Variable | Défaut | Exemple |
2026-04-14 00:30:05 +02:00
| --- | --- | --- |
2026-04-14 00:28:40 +02:00
| `DOCKER_REGISTRY` | * (vide = Docker Hub) * | `registry.nuevolia.dev` |
| `DOCKER_REGISTRY_PREFIX` | * (vide) * | `library/` |
``` bash
# Artifactory
DOCKER_REGISTRY = registry.nuevolia.dev DOCKER_REGISTRY_PREFIX = library/ make test
# Harbor
DOCKER_REGISTRY = harbor.local DOCKER_REGISTRY_PREFIX = proxy/ make test
```
### Pipelines CI
Trois configurations sont fournies :
| Fichier | Système | Stratégie |
2026-04-14 00:30:05 +02:00
| --- | --- | --- |
2026-04-14 00:28:40 +02:00
| `.gitea/workflows/ci.yml` | Gitea Actions | Matrix dynamique parallèle |
| `.gitlab-ci.yml` | GitLab CI | Séquentiel |
| `Jenkinsfile` | Jenkins | Stages parallèles |
Les variables `DOCKER_REGISTRY` et `DOCKER_REGISTRY_PREFIX` peuvent être définies dans les secrets/variables de chaque CI.
2026-04-13 23:25:51 +02:00
## Utilisation dans d'autres playbooks
``` yaml
- hosts : all
gather_facts : true
tasks :
2026-04-13 23:40:52 +02:00
- name : Bloquer un déploiement si trop de sessions
2026-04-13 23:25:51 +02:00
ansible.builtin.fail :
2026-04-13 23:40:52 +02:00
msg : "{{ ansible_local.remote_users.sessions.total_by_protocol }} sessions actives"
when :
- ansible_local.remote_users is defined
- ansible_local.remote_users.sessions.total_by_protocol | int > 10
2026-04-13 23:25:51 +02:00
```