remote_users_fact
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é.
flowchart LR
A[assert.yml] --> B{remote_users_fact_state}
B -->|noop| C[Aucune action]
B -->|present| D[present.yml]
B -->|absent| E[absent.yml]
D --> F{validate ?}
F -->|oui| G[validate.yml]
F -->|non| H{summary ?}
G --> H
H -->|oui| I[summary.yml]
H -->|non| J[Fin]
I --> J
E --> J
C --> J
Arborescence
├── site.yml # Playbook principal
├── inventories/
│ └── hosts.yml # Inventaire exemple
└── roles/
└── remote_users_fact/
├── defaults/main.yml # Variables (dont state)
├── files/remote_users.fact # Script fact
├── handlers/main.yml # Rechargement facts
├── meta/main.yml # Métadonnées Galaxy
└── tasks/
├── 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
Usage
# Appliquer le state défini dans l'inventaire
ansible-playbook -i inventories/hosts.yml site.yml
# Forcer le déploiement partout (override)
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=present
# Supprimer partout
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=absent
# Sur un groupe spécifique
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
| 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_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 |
Assertions
Le rôle valide le paramétrage avant toute action :
remote_users_fact_stateest défini et vautpresent,absentounoopremote_users_fact_direst un chemin absolu (si state != noop)remote_users_fact_namerespecte le pattern*.fact(si state != noop)remote_users_fact_owneretgroupsont définis (si state == present)remote_users_fact_validateetdisplay_summarysont des booléensremote_users_fact_warn_verdictsest 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é
Accessible via ansible_local.remote_users :
{
"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 |
|---|---|
FIABLE |
who == total → compteurs alignés |
OK |
Écart <= 1 → tolérable |
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 |
Exemple d'inventaire avec states
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
CI / Tests
Le rôle est testé automatiquement sur toutes les distributions déclarées dans meta/main.yml via Docker.
flowchart LR
A[meta/main.yml] --> B[build_matrix.py]
B --> C[JSON matrix]
C --> D{Makefile}
D --> E[Dockerfile.el]
D --> F[Dockerfile.debian]
E --> G[docker build + run]
F --> G
G --> H[test_playbook.yml]
H --> I[role: assert + present + validate + summary]
Commandes Make
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 |
|---|---|---|
DOCKER_REGISTRY |
(vide = Docker Hub) | registry.nuevolia.dev |
DOCKER_REGISTRY_PREFIX |
(vide) | library/ |
# 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 |
|---|---|---|
.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.
Utilisation dans d'autres playbooks
- hosts: all
gather_facts: true
tasks:
- name: Bloquer un déploiement si trop de sessions
ansible.builtin.fail:
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