Suppression de toute trace Chezlepro de l'outil (roles, scripts, docs publiques, exemples, LICENSE). Prouve par scan exhaustif : git grep vide pour chezlepro, asgard/TrueNAS, supernet reel 10.1.x. Corrige 5 defauts de genericite fonctionnels (motd, app.ini Forgejo, organisation openldap, nom AC step-ca, et IP reelles codees en dur dans les defaults de roles -> plage d'exemple 10.0.x). LICENSE -> Alliance Boreale. Fichiers mainteneur + CHANGELOG conserves (par decision). La separation moteur/instance tient : OPS-Chezlepro surcharge deja ses vraies valeurs de topologie. Verifie : make verifier exit 0 (4 tests). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
179 lines
8.3 KiB
Markdown
179 lines
8.3 KiB
Markdown
# Le plan et la génération d'inventaire (méta-classe)
|
||
|
||
Set-OPS ne s'édite plus comme un inventaire à la main : on **décrit un plan**, et
|
||
l'inventaire Ansible en est **généré**. Le dépôt est la définition ; chaque VM en
|
||
est une instance. Ce document décrit le modèle, les registres, les commandes et
|
||
le flux de travail.
|
||
|
||
> Règle d'or : **`instance/inventories/production/hosts.yml` est GÉNÉRÉ. Ne jamais l'éditer
|
||
> à la main.** On édite le *plan* puis on régénère (`make instancier-appliquer`).
|
||
|
||
---
|
||
|
||
## 1. Le modèle : deux ancres, cinq liens
|
||
|
||
L'écosystème = des **serveurs** (VM) et des **applications**, reliés à leurs
|
||
**bases**, leurs **domaines** et leurs dépendances :
|
||
|
||
```
|
||
serveur (VM) ──fournit──▶ capacités (= groupes/rôles Ansible)
|
||
application ──tourne_sur──▶ serveur (une VM peut porter N applications)
|
||
application ──requiert──▶ application(s) (DNS, PKI, BD…)
|
||
application ──utilise──▶ base(s) (via le DSN)
|
||
application ──expose──▶ domaine(s) public(s) (le FQDN, derrière l'edge)
|
||
base ──hébergée_sur──▶ serveur de BD
|
||
```
|
||
|
||
L'**application** est l'entité pivot : tout ce qui décrit « ce qui tourne et à
|
||
quoi c'est connecté » pend d'elle. Le **groupe** Ansible n'est plus une cible de
|
||
liaison — seulement une **capacité** qu'une VM fournit (le rôle appliqué).
|
||
|
||
---
|
||
|
||
## 2. Les registres (source unique de vérité)
|
||
|
||
Tous sous `docs/`, machine-lisibles, validés, consommés par le GUI, le CLI et Ansible.
|
||
|
||
| Registre | Décrit | Champs clés |
|
||
| --- | --- | --- |
|
||
| `nomenclature.yml` | nommage & adressage | `fonctions` (catégorie/service), `categories` (VLAN/sous-réseau/passerelle), `supernet` |
|
||
| `serveurs.yml` | les VM du plan | `fonction`, `etat` (actif/planifie), placement Proxmox (`noeud`/`stockage`/`disque`/`memoire`/`coeurs`), `integrations` (les `clients_*`) |
|
||
| `applications.yml` | les applications | `groupe` (capacité/rôle), `hote` (VM), `port`, `requiert`, `expose`, (+ bases via consommateur) |
|
||
| `bases-donnees.yml` | serveurs de BD + bases | `serveurs_bd` ; `bases_donnees` : `serveur`/`base`/`proprietaire`/`secret`(Vault), `consommateur` + `portee` (`application`/`groupe`/`hote`), `usage` |
|
||
| `domaines.yml` | zones DNS publiques | `domaines_publics` : `autorite`, `edge`, `secondaires`, `dnssec`, `mail` |
|
||
| `dependances-groupes.yml` | prérequis entre groupes | `requiert_groupes_actifs` |
|
||
|
||
### Dérivations clés
|
||
- **Nommage/adressage** : tout part de la `fonction` de l'hôte (`web-frontal-03`).
|
||
`VMID = 9·catégorie·service·NN`, `VLAN = catégorie.vlan`,
|
||
`IP = 10.0.<vlan>.(service×10 + NN)`. Voir `docs/nomenclature-vm.md`.
|
||
- **DSN** (lien application↔base) : `<type>://<proprietaire>:<secret>@<hôte>:<port>/<base>`.
|
||
Une application reçoit les bases où `(portee=application ET consommateur=elle)`
|
||
OU `(portee=groupe ET consommateur=son groupe)` OU `(portee=hote ET consommateur=son hôte)`.
|
||
- **Exposition DNS** : `application.expose: [fqdn]` + l'`edge` du domaine parent →
|
||
`serveur_nginx` génère le vhost (`application → hôte → IP:port`).
|
||
|
||
---
|
||
|
||
## 3. La génération (méta-classe)
|
||
|
||
`make instancier` produit `hosts.yml` **depuis le plan** :
|
||
|
||
- **host vars** : `ansible_host`/`ansible_user` + `proxmox_*` (IP/VMID/VLAN/passerelle
|
||
**dérivés** de la nomenclature ; placement/taille depuis `serveurs.yml`).
|
||
- **groupes** d'une VM = socle (`serveur_debian` + `serveur_durci`)
|
||
+ **services** (les `groupe` des applications de l'hôte)
|
||
+ **intégrations** (`serveurs.yml: integrations`)
|
||
+ **état** (`hotes_actifs` / `hotes_planifies`).
|
||
|
||
La comparaison est **sémantique** (via `ansible-inventory --list`, formatage
|
||
ignoré). « **Diff vide** » = le plan reproduit exactement l'inventaire courant ;
|
||
c'est le feu vert pour appliquer.
|
||
|
||
---
|
||
|
||
## 4. Le flux de travail
|
||
|
||
```
|
||
éditer le PLAN ──▶ make instancier (revoir le diff) ──▶ make instancier-appliquer ──▶ déployer
|
||
(GUI ou CLI) (que va-t-il changer ?) (régénère hosts.yml) (make deployer)
|
||
```
|
||
|
||
### Via le GUI — `make inventaire-ui`
|
||
Cinq vues :
|
||
|
||
| Vue | Rôle |
|
||
| --- | --- |
|
||
| **Inventaire** | **lecture seule** (inventaire généré) — vue d'ensemble des hôtes |
|
||
| **Serveurs** | éditer les VM du plan : fonction/état/placement/intégrations (VMID·IP·VLAN dérivés en direct) ; bouton **« Appliquer le plan »** |
|
||
| **Chaîne** | vue holistique par hôte : groupes → rôles, et par application ses `expose` / `requiert` / bases (DSN) |
|
||
| **Applications** | éditer les applications : groupe/hôte/port/requiert/expose |
|
||
| **Bases** | éditer serveurs de BD et bases (portée + consommateur), DSN affiché |
|
||
|
||
Édition → **Sauvegarder** (écrit le registre) → **Appliquer le plan** (régénère
|
||
`hosts.yml`). L'écriture directe de l'inventaire est refusée (409).
|
||
|
||
### Via le CLI / `make`
|
||
Chaque registre a son script miroir et ses cibles `make` :
|
||
|
||
| Domaine | Lister | Vérifier | Bootstrap (depuis l'inventaire) |
|
||
| --- | --- | --- | --- |
|
||
| Serveurs | `make serveurs` | `make serveurs-verifier` | `make serveurs-bootstrap` |
|
||
| Applications | `make applications` | `make applications-verifier` | `make applications-bootstrap` |
|
||
| Bases | `make bases` | `make bases-verifier` | — |
|
||
| Domaines | `make domaines` | `make domaines-verifier` | — |
|
||
|
||
Génération :
|
||
|
||
```bash
|
||
make instancier # génère hosts.genere.yml (gitignoré) + diff sémantique
|
||
make instancier-appliquer # régénère hosts.yml (refuse si diff non vide ; FORCE=1 pour forcer)
|
||
```
|
||
|
||
Validation globale : `make inventaire-verifier` (ansible-inventory + tous les
|
||
registres + **`node --check` du JS du GUI**).
|
||
|
||
---
|
||
|
||
## 5. Garde-fous
|
||
|
||
- **Validateurs** : chaque registre est validé (références connues, énumérations,
|
||
unicité). Un `expose` sans domaine parent, un `requiert` fantôme, une `portee`
|
||
inconnue, une `fonction` absente → rejet.
|
||
- **Diff vide** : `instancier-appliquer` refuse d'écraser l'inventaire si le plan
|
||
ne le reproduit pas (sauf `FORCE=1` pour un changement intentionnel).
|
||
- **`node --check`** : le JS embarqué du GUI est vérifié (`scripts/verifier_gui.py`,
|
||
intégré à `make inventaire-verifier`) — une erreur de syntaxe JS casse toute la page.
|
||
- **git** : `hosts.yml` est versionné ; `git diff` / `git checkout` est le filet.
|
||
- **Secrets** : jamais en clair ; `secret:` nomme une variable Ansible Vault.
|
||
|
||
---
|
||
|
||
## 6. Réutilisation de la règle (Ansible)
|
||
|
||
La règle de résolution vit **une seule fois**, en Python (`scripts/inventory_rules.py`),
|
||
et est exposée à Ansible par un *filter plugin* (`filter_plugins/registres.py`) :
|
||
`bases_de_application`, `applications_de_hote`, `expositions_des_applications`,
|
||
`chaine_connexion`. Les playbooks par application (`serveur_web_dorsal`/`_frontaux`)
|
||
itèrent ainsi sur les applications de l'hôte et résolvent leurs DSN.
|
||
|
||
---
|
||
|
||
## 7. Amorçage / reconstruction
|
||
|
||
Pour (re)construire le plan depuis un inventaire existant :
|
||
|
||
```bash
|
||
make serveurs-bootstrap # VM -> instance/plan/serveurs.yml (fonction/état/placement/integrations)
|
||
make applications-bootstrap # services serveurs_* (hors socle) -> instance/plan/applications.yml
|
||
make instancier # vérifier le diff vide
|
||
```
|
||
|
||
C'est ainsi que le plan a été initialisé sans perte, avec diff vide vérifié.
|
||
|
||
---
|
||
|
||
## 8. Moteur et instance : deux dépôts
|
||
|
||
Le **moteur** (ce dépôt, `Set-OPS`) est générique et partageable ; il ne contient
|
||
aucune donnée d'instance. Une **instance** (le plan + l'inventaire d'un loup) vit
|
||
dans son **propre dépôt** (ex. `OPS-monatelier`).
|
||
|
||
Le moteur localise l'instance via **`SETOPS_INSTANCE`** (défaut : `instance`). Deux
|
||
modèles :
|
||
|
||
- **Modèle A — dépôts frères** (en cours) : moteur et instance côte à côte ; un
|
||
symlink `instance -> ../OPS-monatelier` (gitignoré) fait que le défaut résout
|
||
l'instance sans configuration. Idéal quand on développe le moteur *et* l'instance.
|
||
- **Modèle B — moteur en sous-module** (futur, pour la meute) : l'instance épingle
|
||
une version du moteur ; `SETOPS_INSTANCE` pointe la racine de l'instance.
|
||
|
||
Pour brancher une instance (modèle A) :
|
||
|
||
```bash
|
||
cd Set-OPS
|
||
ln -s ../OPS-monatelier instance # ou : export SETOPS_INSTANCE=/chemin/instance
|
||
make inventaire-verifier # lit l'instance via le symlink
|
||
```
|
||
|
||
Le moteur écrit `hosts.yml` (généré) **dans le dépôt d'instance**, jamais dans le sien.
|