2026-06-24 20:17:46 -04:00
SHELL := /usr/bin/env bash
export ANSIBLE_HOME ?= $( CURDIR) /.ansible
export ANSIBLE_LOCAL_TEMP ?= $( CURDIR) /.ansible/tmp
export ANSIBLE_SSH_CONTROL_PATH_DIR ?= $( CURDIR) /.ansible/cp
export ANSIBLE_SSH_ARGS ?= -F /dev/null -o ControlMaster = no
export SETOPS_INSTANCE ?= instance
2026-06-30 16:08:25 -04:00
# Inventaire de l'instance : un seul par instance dans le modèle « séparation par
# instance ». Détection rétro-compatible : principal > production > lab.
# Surchargeable : make … SETOPS_INVENTAIRE=chemin/hosts.yml
SETOPS_INVENTAIRE ?= $( firstword $( wildcard $( SETOPS_INSTANCE) /inventories/principal/hosts.yml) $( wildcard $( SETOPS_INSTANCE) /inventories/production/hosts.yml) $( SETOPS_INSTANCE) /inventories/principal/hosts.yml)
export SETOPS_INVENTAIRE
# Inventaire « modèle » (construction du golden template) : lab > principal > production.
INVENTAIRE_LAB ?= $( firstword $( wildcard $( SETOPS_INSTANCE) /inventories/lab/hosts.yml) $( wildcard $( SETOPS_INSTANCE) /inventories/principal/hosts.yml) $( SETOPS_INSTANCE) /inventories/production/hosts.yml)
INVENTAIRE_PRODUCTION ?= $( SETOPS_INVENTAIRE)
FICHIER_INVENTAIRE ?= $( SETOPS_INVENTAIRE)
2026-06-24 20:17:46 -04:00
FICHIER_DEPENDANCES ?= docs/dependances-groupes.yml
GROUPE_MODELE ?= modeles_vm
GROUPE_DEBIAN ?= serveur_debian
GROUPE_HOTES_ACTIFS ?= hotes_actifs
LIMITE ?= $( GROUPE_DEBIAN)
HOTE ?=
ADRESSE_IP ?=
GROUPES ?= $( GROUPE_DEBIAN)
GROUPE ?= $( GROUPE_DEBIAN)
UTILISATEUR_ANSIBLE ?= ansible
VMID_MODELE ?=
VMID ?=
NOEUD_PROXMOX ?=
STOCKAGE_PROXMOX ?=
FORMAT_DISQUE ?=
TAILLE_DISQUE ?=
DISQUE_PROXMOX ?=
CIDR ?= 24
PASSERELLE ?=
DNS ?=
DHCP ?= false
CIUSER ?=
CLE_SSH_PUBLIQUE ?=
PONT_PROXMOX ?=
VLAN ?=
DEMARRER ?=
CLONE_COMPLET ?=
CONFIRMER ?= false
VERIFICATION ?= false
DIFF ?= false
ETIQUETTES ?=
SAUTER_ETIQUETTES ?=
VARIABLES ?=
OPTIONS_PLAYBOOK :=
i f n e q ( $( LIMITE ) , )
OPTIONS_PLAYBOOK += --limit $( LIMITE)
e n d i f
i f e q ( $( VERIFICATION ) , t r u e )
OPTIONS_PLAYBOOK += --check
e n d i f
i f e q ( $( DIFF ) , t r u e )
OPTIONS_PLAYBOOK += --diff
e n d i f
i f n e q ( $( ETIQUETTES ) , )
OPTIONS_PLAYBOOK += --tags $( ETIQUETTES)
e n d i f
i f n e q ( $( SAUTER_ETIQUETTES ) , )
OPTIONS_PLAYBOOK += --skip-tags $( SAUTER_ETIQUETTES)
e n d i f
i f n e q ( $( VARIABLES ) , )
OPTIONS_PLAYBOOK += -e $( VARIABLES)
e n d i f
PLAYBOOK_PREPARER_MODELE := playbooks/modeles_vm/debian13_proxmox_preparer.yml
PLAYBOOK_VERIFIER_MODELE := playbooks/modeles_vm/debian13_proxmox_verifier.yml
PLAYBOOK_NETTOYER_MODELE := playbooks/modeles_vm/debian13_proxmox_nettoyer.yml
PLAYBOOK_VERIFIER_HOTE := playbooks/maintenance/verifier_hote_debian.yml
PLAYBOOK_PROXMOX_CLONER_VM := playbooks/proxmox/cloner_vm_debian.yml
DOSSIER_PLAYBOOKS_GROUPES := playbooks/groupes
.DEFAULT_GOAL := aide
.PHONY : ansible -runtime
ansible-runtime :
@mkdir -p " $( ANSIBLE_LOCAL_TEMP) "
@mkdir -p " $( ANSIBLE_SSH_CONTROL_PATH_DIR) "
.PHONY : _instance -requise
_instance-requise :
@if [ [ ! -f " $( SETOPS_INSTANCE) /plan/serveurs.yml " ] ] ; then \
printf '%s\n' " Aucune instance configuree : ' $( SETOPS_INSTANCE) /plan' introuvable. " ; \
printf '%s\n' "Demarre avec QUICKSTART.md. En bref :" ; \
printf '%s\n' " cp -r exemples/modeles/<modele> ../mon-instance && ln -s ../mon-instance instance" ; \
printf '%s\n' " modeles disponibles : $$ (ls exemples/modeles 2>/dev/null | grep -v '\.md' | tr '\n' ' ') " ; \
exit 2; \
fi
.PHONY : aide
aide :
@printf '%s\n' 'Set-OPS — moteur d ecosystemes numeriques souverains'
@printf '%s\n' ''
@printf '%s\n' 'Nouveau ? -> QUICKSTART.md (de zero a ton ecosysteme sur Proxmox)'
@printf '%s\n' 'Flux: editer le plan -> make instancier -> make instancier-appliquer -> make deployer'
@printf '%s\n' ''
@printf '%s\n' 'VM'
@printf '%s\n' ' Creer une VM (VMID/IP/VLAN/passerelle lus dans le plan):'
@printf '%s\n' ' make creer-vm HOTE=web-frontal-01'
@printf '%s\n' ' Cloner seulement, sans passer par le plan:'
@printf '%s\n' ' make cloner-vm HOTE=web-frontal-01 VMID=95301 VLAN=15 ADRESSE_IP=10.0.2.31 PASSERELLE=10.0.2.1'
2026-06-30 12:19:14 -04:00
@printf '%s\n' ' Configurer Proxmox et le Vault API (parametres: docs/config-proxmox.md):'
2026-06-24 20:17:46 -04:00
@printf '%s\n' ' make config'
@printf '%s\n' ''
@printf '%s\n' 'Hotes'
@printf '%s\n' ' Planifier/modifier un hote: editer le plan, puis regenerer:'
@printf '%s\n' ' editer instance/plan/serveurs.yml (ou la vue Serveurs du GUI)'
@printf '%s\n' ' make instancier-appliquer'
@printf '%s\n' ' Verifier un deploiement a blanc (dry-run):'
@printf '%s\n' ' make verifier-deploiement HOTE=web-frontal-01'
@printf '%s\n' ' Remettre un hote en conformite selon ses groupes:'
@printf '%s\n' ' make deployer HOTE=web-frontal-01'
@printf '%s\n' ' Afficher un hote:'
@printf '%s\n' ' make hote-afficher HOTE=web-frontal-01'
@printf '%s\n' ' Diagnostiquer:'
@printf '%s\n' ' make verifier-hote LIMITE=web-frontal-01'
@printf '%s\n' ''
@printf '%s\n' 'Groupes'
@printf '%s\n' ' Appliquer un groupe complet:'
@printf '%s\n' ' make deployer-groupe GROUPE=serveur_debian'
@printf '%s\n' ' Convention:'
@printf '%s\n' ' groupe serveur_debian -> playbooks/groupes/serveur_debian.yml'
@printf '%s\n' ''
2026-07-07 03:08:09 -04:00
@printf '%s\n' 'Ecosysteme complet (orchestrateur)'
@printf '%s\n' ' Ordre de deploiement (couches + graphe):'
@printf '%s\n' ' make site-verifier # valide la coherence couches/graphe'
@printf '%s\n' ' python3 scripts/orchestrer.py ordre'
@printf '%s\n' ' (Re)generer playbooks/site.yml ordonne:'
@printf '%s\n' ' make site'
@printf '%s\n' ' CONFIGURER la flotte existante, couche par couche (2b, VM deja creees):'
@printf '%s\n' ' make deployer-tout CONFIRMER=true # (MODE_CHECK=1 pour un essai a blanc idempotent)'
@printf '%s\n' ' CREER toutes les VM du plan (2a, clone Proxmox):'
@printf '%s\n' ' make flotte-creer CONFIRMER=true'
@printf '%s\n' ' RECONSTRUIRE from-zero = creer les VM PUIS deployer (2a+2b, VM inexistantes):'
@printf '%s\n' ' make reconstruire CONFIRMER=true # alias: make myDay CONFIRMER=true'
@printf '%s\n' ''
@printf '%s\n' 'Flux reseau (pare-feu / audit)'
@printf '%s\n' ' Matrice d audit + apercus nftables resolus (NON actives):'
@printf '%s\n' ' make flux # -> docs/registre-flux.md + instance/flux-genere/*.nft'
@printf '%s\n' ' make flux-verifier # valide schema + coherence de matrice'
@printf '%s\n' ''
@printf '%s\n' 'Wiki pedagogique'
@printf '%s\n' ' Publier wiki/ dans le wiki Forgejo (source versionnee -> vue browsable):'
@printf '%s\n' ' make wiki-publier WIKI_REMOTE=https://forge.<domaine>/<proprio>/<depot>.wiki.git'
@printf '%s\n' ''
2026-06-24 20:17:46 -04:00
@printf '%s\n' 'Inventaires'
@printf '%s\n' ' Graphe de production:'
@printf '%s\n' ' make inventaire'
@printf '%s\n' ' Graphe explicite:'
@printf '%s\n' ' make inventaire-graphe FICHIER_INVENTAIRE=$(SETOPS_INSTANCE)/inventories/production/hosts.yml'
@printf '%s\n' ' Verifier les inventaires:'
@printf '%s\n' ' make inventaire-verifier'
@printf '%s\n' ' Lister les donnees brutes:'
@printf '%s\n' ' make inventaire-lister'
@printf '%s\n' ' Interface locale de gestion:'
@printf '%s\n' ' make inventaire-ui'
@printf '%s\n' ''
@printf '%s\n' 'Modele Debian 13 Proxmox'
@printf '%s\n' ' Construire et verifier:'
@printf '%s\n' ' make preparer-modele'
@printf '%s\n' ' make verifier-modele'
@printf '%s\n' ' Nettoyage final protege:'
@printf '%s\n' ' make nettoyer-modele CONFIRMER=true'
@printf '%s\n' ''
@printf '%s\n' 'Validation'
@printf '%s\n' ' make syntaxe'
@printf '%s\n' ' make lint'
@printf '%s\n' ' make verifier'
@printf '%s\n' ''
@printf '%s\n' 'Variables frequentes'
@printf '%s\n' ' HOTE=web-frontal-01 GROUPE=serveur_debian GROUPES="serveur_debian serveur_durci"'
@printf '%s\n' ' VMID=95301 VLAN=15 ADRESSE_IP=10.0.2.31 PASSERELLE=10.0.2.1'
@printf '%s\n' ' FICHIER_INVENTAIRE=$(SETOPS_INSTANCE)/inventories/production/hosts.yml FICHIER_DEPENDANCES=docs/dependances-groupes.yml CONFIRMER=true'
.PHONY : lint
lint : ansible -runtime
ansible-lint
.PHONY : syntaxe syntaxe -modele syntaxe -nettoyage syntaxe -verification -modele syntaxe -verification -hote syntaxe -groupes syntaxe -proxmox
syntaxe : syntaxe -modele syntaxe -verification -modele syntaxe -nettoyage syntaxe -verification -hote syntaxe -groupes syntaxe -proxmox
syntaxe-modele : ansible -runtime
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_PREPARER_MODELE) --syntax-check
syntaxe-verification-modele : ansible -runtime
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_VERIFIER_MODELE) --syntax-check
syntaxe-nettoyage : ansible -runtime
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_NETTOYER_MODELE) --syntax-check
syntaxe-verification-hote : ansible -runtime
ansible-playbook -i $( INVENTAIRE_PRODUCTION) $( PLAYBOOK_VERIFIER_HOTE) --syntax-check
syntaxe-groupes : ansible -runtime
@for playbook in $( DOSSIER_PLAYBOOKS_GROUPES) /*.yml; do \
ansible-playbook -i $( INVENTAIRE_PRODUCTION) " $$ playbook " --syntax-check; \
done
syntaxe-proxmox : ansible -runtime
ansible-playbook -i localhost, $( PLAYBOOK_PROXMOX_CLONER_VM) --syntax-check
.PHONY : test
test :
python3 scripts/tests/test_inventory_host.py
.PHONY : verifier
2026-07-07 03:08:09 -04:00
verifier : lint test inventaire -verifier site -verifier flux -verifier syntaxe
2026-06-24 20:17:46 -04:00
2026-06-30 16:31:42 -04:00
.PHONY : inventaire hote -planifier hote -ajouter hote -groupes hote -afficher appliquer deployer deployer -groupe cloner -vm creer -vm config inventaire -ui inventaire -verifier inventaire -lister inventaire -graphe inventaire -hote inventaire -lab inventaire -production instance -utiliser instance -courante
2026-06-24 20:17:46 -04:00
inventaire : inventaire -production
2026-06-30 16:31:42 -04:00
# Bascule le symlink 'instance' vers un autre dépôt d'instance (séparation par
# instance : prod vs bac à sable). Ex. : make instance-utiliser NOM=OPS-Chezlepro-lab
instance-utiliser :
@if [ [ -z " $( NOM) " ] ] ; then printf '%s\n' "Usage: make instance-utiliser NOM=<dossier-frère> (ex. OPS-Chezlepro-lab)" ; exit 2; fi
@if [ [ ! -d " ../ $( NOM) " ] ] ; then printf '%s\n' " Introuvable: ../ $( NOM) " ; exit 2; fi
@if [ [ -e instance && ! -L instance ] ] ; then printf '%s\n' "Refus: 'instance' existe et n'est pas un symlink." ; exit 2; fi
@rm -f instance && ln -s " ../ $( NOM) " instance
@printf 'instance -> %s\n' " $$ (readlink instance) "
instance-courante :
@printf 'instance -> %s\n' " $$ (readlink instance 2>/dev/null || echo '(non monté)') "
2026-06-24 20:17:46 -04:00
config :
python3 scripts/config_proxmox.py
inventaire-ui : _instance -requise
python3 scripts/inventory_gui.py --inventaire $( FICHIER_INVENTAIRE)
hote-ajouter hote-planifier hote-groupes :
@printf '%s\n' 'Cible depreciee: l inventaire est GENERE depuis le plan, il ne s edite plus a la main.'
@printf '%s\n' 'Declare ou modifie l hote dans instance/plan/serveurs.yml (ou la vue Serveurs du GUI), puis :'
@printf '%s\n' ' make instancier-appliquer'
@printf '%s\n' '(creer-vm lit desormais VMID/IP/VLAN/passerelle directement dans l inventaire genere.)'
@exit 2
hote-afficher : ansible -runtime
@if [ [ -z " $( HOTE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote.' ; \
exit 2; \
fi
python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) afficher --hote $( HOTE)
appliquer : ansible -runtime
@if [ [ -z " $( GROUPE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec GROUPE=nom_groupe.' ; \
exit 2; \
fi
@if [ [ ! -f " $( DOSSIER_PLAYBOOKS_GROUPES) / $( GROUPE) .yml " ] ] ; then \
printf '%s\n' 'Refus: aucun playbook pour ce groupe: $(DOSSIER_PLAYBOOKS_GROUPES)/$(GROUPE).yml' ; \
exit 2; \
fi
python3 scripts/inventory_host.py --inventaire $( INVENTAIRE_PRODUCTION) --dependances $( FICHIER_DEPENDANCES) verifier-dependances-groupe --groupe $( GROUPE)
ansible-playbook -i $( INVENTAIRE_PRODUCTION) " $( DOSSIER_PLAYBOOKS_GROUPES) / $( GROUPE) .yml " --limit '$(GROUPE):&$(GROUPE_HOTES_ACTIFS)'
deployer : _instance -requise
@set -e; \
if [ [ -z " $( HOTE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote.' ; \
exit 2; \
fi ; \
python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) verifier-actif --hote $( HOTE) ; \
python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) --dependances $( FICHIER_DEPENDANCES) verifier-dependances-hote --hote $( HOTE) ; \
playbooks = " $$ (python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) playbooks --hote $( HOTE) --dossier-playbooks $( DOSSIER_PLAYBOOKS_GROUPES) ) " ; \
if [ [ -z " $$ playbooks " ] ] ; then \
printf '%s\n' 'Refus: aucun playbook applicable pour HOTE=$(HOTE).' ; \
exit 2; \
fi ; \
2026-07-07 03:08:09 -04:00
vault_chiffre = " $$ (grep -rlsIF ' $$ ANSIBLE_VAULT' $( dir $( INVENTAIRE_PRODUCTION) ) group_vars 2>/dev/null | head -1 || true) " ; \
2026-06-24 20:17:46 -04:00
if [ [ -n " $$ vault_chiffre " && -z " $$ {ANSIBLE_VAULT_PASSWORD_FILE:-} " ] ] ; then \
if [ [ -t 0 ] ] ; then \
read -r -s -p 'Mot de passe du vault Ansible: ' mdp; echo; \
vf = " $$ (mktemp) " ; printf '%s' " $$ mdp " > " $$ vf " ; chmod 600 " $$ vf " ; \
export ANSIBLE_VAULT_PASSWORD_FILE = " $$ vf " ; \
trap 'rm -f "$$vf"' EXIT; \
else \
printf '%s\n' 'Refus: vault chiffre detecte mais aucun mot de passe (entree non interactive). Fournir ANSIBLE_VAULT_PASSWORD_FILE ou le champ vault de la GUI.' ; \
exit 2; \
fi ; \
fi ; \
$( MAKE) _verifier-acces-hote LIMITE = " $( HOTE) " ; \
$( MAKE) _verifier-privileges-hote LIMITE = " $( HOTE) " ; \
for playbook in $$ playbooks; do \
ansible-playbook -i $( INVENTAIRE_PRODUCTION) " $$ playbook " --limit " $( HOTE) " ; \
done ; \
$( MAKE) verifier-hote LIMITE = " $( HOTE) "
2026-07-07 03:08:09 -04:00
.PHONY : site site -verifier deployer -tout
site : ansible -runtime
python3 scripts/orchestrer.py ecrire
ansible-playbook -i $( INVENTAIRE_PRODUCTION) playbooks/site.yml --syntax-check
site-verifier :
python3 scripts/orchestrer.py verifier
.PHONY : flux flux -verifier
flux : ansible -runtime
python3 scripts/resoudre_flux.py registre
python3 scripts/resoudre_flux.py nftables
flux-verifier :
python3 scripts/resoudre_flux.py verifier
2026-07-07 03:19:51 -04:00
.PHONY : valider
valider : ansible -runtime
ansible-playbook -i $( INVENTAIRE_PRODUCTION) playbooks/valider.yml
2026-07-07 03:08:09 -04:00
.PHONY : wiki -publier
wiki-publier :
@set -e; \
if [ [ -z " $( WIKI_REMOTE) " ] ] ; then \
printf '%s\n' 'Refus: URL du wiki Forgejo requise.' ; \
printf '%s\n' 'Ex: make wiki-publier WIKI_REMOTE=https://forge.<domaine>/<proprio>/<depot>.wiki.git' ; \
exit 2; \
fi ; \
src = " $( CURDIR) /wiki " ; \
tmp = " $$ (mktemp -d) " ; \
trap 'rm -rf "$$tmp"' EXIT; \
printf '%s\n' " Clonage du wiki: $( WIKI_REMOTE) " ; \
if ! git clone --quiet --depth 1 " $( WIKI_REMOTE) " " $$ tmp/wiki " ; then \
printf '%s\n' 'Echec du clone (URL ou acces ?). Le wiki doit exister (creer une 1re page dans Forgejo).' ; \
exit 1; \
fi ; \
find " $$ tmp/wiki " -maxdepth 1 -name '*.md' -delete; \
for f in " $$ src " /*.md; do \
bn = " $$ (basename " $$ f")" ; \
[ [ " $$ bn " = = "README.md" ] ] && continue ; \
cp " $$ f " " $$ tmp/wiki/ $$ bn " ; \
done ; \
cd " $$ tmp/wiki " ; \
if [ [ -z " $$ (git status --porcelain) " ] ] ; then \
printf '%s\n' 'Wiki deja a jour (aucun changement).' ; \
exit 0; \
fi ; \
git add -A; \
sha = " $$ (git -C " $( CURDIR) " rev-parse --short HEAD 2>/dev/null || echo inconnu)" ; \
git commit --quiet -m " Publication du wiki depuis le depot (source: $$ sha) " ; \
git push --quiet; \
printf '%s\n' 'Wiki publie.'
deployer-tout : _instance -requise
@set -e; \
if [ [ " $( CONFIRMER) " != "true" ] ] ; then \
printf '%s\n' 'Refus: deploiement ORCHESTRE de TOUTE la flotte (action impactante).' ; \
printf '%s\n' 'Relancer avec CONFIRMER=true. Astuce: tester d abord en idempotent avec MODE_CHECK=1.' ; \
exit 2; \
fi ; \
python3 scripts/orchestrer.py verifier; \
python3 scripts/orchestrer.py ecrire; \
vault_chiffre = " $$ (grep -rlsIF ' $$ ANSIBLE_VAULT' $( dir $( INVENTAIRE_PRODUCTION) ) group_vars 2>/dev/null | head -1 || true) " ; \
if [ [ -n " $$ vault_chiffre " && -z " $$ {ANSIBLE_VAULT_PASSWORD_FILE:-} " ] ] ; then \
if [ [ -t 0 ] ] ; then \
read -r -s -p 'Mot de passe du vault Ansible: ' mdp; echo; \
vf = " $$ (mktemp) " ; printf '%s' " $$ mdp " > " $$ vf " ; chmod 600 " $$ vf " ; \
export ANSIBLE_VAULT_PASSWORD_FILE = " $$ vf " ; \
trap 'rm -f "$$vf"' EXIT; \
else \
printf '%s\n' 'Refus: vault chiffre detecte mais aucun mot de passe (entree non interactive). Fournir ANSIBLE_VAULT_PASSWORD_FILE ou le champ vault de la GUI.' ; \
exit 2; \
fi ; \
fi ; \
$( MAKE) _verifier-acces-hote LIMITE = " $( GROUPE_HOTES_ACTIFS) " ; \
$( MAKE) _verifier-privileges-hote LIMITE = " $( GROUPE_HOTES_ACTIFS) " ; \
mode = " $$ ([[ -n " $( MODE_CHECK) " ]] && printf -- '--check --diff' || true)" ; \
ansible-playbook -i $( INVENTAIRE_PRODUCTION) playbooks/site.yml --limit " $( GROUPE_HOTES_ACTIFS) " $$ mode
# --- Reconstruction from-zero : creer TOUTES les VM (2a) puis deployer (2b) ---
.PHONY : flotte -creer
flotte-creer : _instance -requise
@set -e; \
if [ [ " $( CONFIRMER) " != "true" ] ] ; then \
printf '%s\n' 'Refus: creation de TOUTES les VM actives du plan (clone Proxmox).' ; \
printf '%s\n' 'Relancer avec CONFIRMER=true.' ; \
exit 2; \
fi ; \
hotes = " $$ (python3 scripts/inventory_host.py --inventaire $( INVENTAIRE_PRODUCTION) lister-actifs) " ; \
if [ [ -z " $$ hotes " ] ] ; then printf '%s\n' 'Refus: aucun hote actif dans le plan.' ; exit 2; fi ; \
for h in $$ hotes; do \
printf '\n=== Creation VM: %s ===\n' " $$ h " ; \
$( MAKE) creer-vm HOTE = " $$ h " ; \
done ; \
printf '\nToutes les VM actives sont creees.\n'
.PHONY : _attendre -flotte
_attendre-flotte : ansible -runtime
@set -e; \
max = " $$ {ATTENTE_MAX:-600} " ; deadline = $$ ( ( $$ ( date +%s) + max ) ) ; \
printf 'Attente que la flotte reponde en SSH (max %ss)...\n' " $$ max " ; \
until ansible -i $( INVENTAIRE_PRODUCTION) $( GROUPE_HOTES_ACTIFS) -m ping -e ansible_become = false >/dev/null 2>& 1; do \
if ( ( $$ ( date +%s) > deadline ) ) ; then printf 'Timeout: flotte injoignable apres %ss.\n' " $$ max " ; exit 1; fi ; \
sleep 10; \
done ; \
printf 'Flotte joignable.\n'
.PHONY : reconstruire
reconstruire : _instance -requise
@set -e; \
if [ [ " $( CONFIRMER) " != "true" ] ] ; then \
printf '%s\n' 'Refus: RECONSTRUCTION — cree les VM manquantes (2a) PUIS deploie tout (2b).' ; \
printf '%s\n' 'Idempotent : une VM deja presente est sautee (clone par nom), le deploiement converge.' ; \
printf '%s\n' 'Relancer avec CONFIRMER=true.' ; \
exit 2; \
fi ; \
$( MAKE) flotte-creer CONFIRMER = true; \
$( MAKE) _attendre-flotte; \
$( MAKE) deployer-tout CONFIRMER = true
# « Go ahead, make my day. » — LE bouton rouge : alias de reconstruire (Clint Eastwood).
# Cree toutes les VM puis deploie tout, en une commande. Garde CONFIRMER=true.
.PHONY : myDay
myDay : reconstruire
2026-06-24 20:17:46 -04:00
deployer-groupe :
@if [ [ -z " $( GROUPE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec GROUPE=nom_groupe.' ; \
exit 2; \
fi
$( MAKE) appliquer GROUPE = " $( GROUPE) "
.PHONY : verifier -deploiement
verifier-deploiement : ansible -runtime
@set -e; \
if [ [ -z " $( HOTE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote.' ; \
exit 2; \
fi ; \
python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) verifier-actif --hote $( HOTE) ; \
python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) --dependances $( FICHIER_DEPENDANCES) verifier-dependances-hote --hote $( HOTE) ; \
playbooks = " $$ (python3 scripts/inventory_host.py --inventaire $( FICHIER_INVENTAIRE) playbooks --hote $( HOTE) --dossier-playbooks $( DOSSIER_PLAYBOOKS_GROUPES) ) " ; \
if [ [ -z " $$ playbooks " ] ] ; then \
printf '%s\n' 'Refus: aucun playbook applicable pour HOTE=$(HOTE).' ; \
exit 2; \
fi ; \
2026-07-07 03:08:09 -04:00
vault_chiffre = " $$ (grep -rlsIF ' $$ ANSIBLE_VAULT' $( dir $( INVENTAIRE_PRODUCTION) ) group_vars 2>/dev/null | head -1 || true) " ; \
2026-06-24 20:17:46 -04:00
if [ [ -n " $$ vault_chiffre " && -z " $$ {ANSIBLE_VAULT_PASSWORD_FILE:-} " ] ] ; then \
if [ [ -t 0 ] ] ; then \
read -r -s -p 'Mot de passe du vault Ansible: ' mdp; echo; \
vf = " $$ (mktemp) " ; printf '%s' " $$ mdp " > " $$ vf " ; chmod 600 " $$ vf " ; \
export ANSIBLE_VAULT_PASSWORD_FILE = " $$ vf " ; \
trap 'rm -f "$$vf"' EXIT; \
else \
printf '%s\n' 'Refus: vault chiffre detecte mais aucun mot de passe (entree non interactive). Fournir ANSIBLE_VAULT_PASSWORD_FILE ou le champ vault de la GUI.' ; \
exit 2; \
fi ; \
fi ; \
for playbook in $$ playbooks; do \
ansible-playbook -i $( INVENTAIRE_PRODUCTION) " $$ playbook " --limit " $( HOTE) " --check --diff; \
done
cloner-vm : ansible -runtime
@if [ [ -z " $( HOTE) " || -z " $( VMID) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom VMID=id_clone.' ; \
exit 2; \
fi
@if [ [ -z " $( VLAN) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec VLAN=id_vlan.' ; \
exit 2; \
fi
@if ! [ [ " $( VLAN) " = ~ ^[ 0-9] +$$ ] ] || ( ( 10#$( VLAN) < 1 || 10#$( VLAN) > 4094 ) ) ; then \
printf '%s\n' 'Refus: VLAN doit etre un nombre entre 1 et 4094.' ; \
exit 2; \
fi
@if [ [ -n " $( CLE_SSH_PUBLIQUE) " && ! -f " $( CLE_SSH_PUBLIQUE) " ] ] ; then \
printf '%s\n' 'Refus: cle publique SSH introuvable: $(CLE_SSH_PUBLIQUE)' ; \
exit 2; \
fi
@if [ [ " $( DHCP) " != "true" && ( -z " $( ADRESSE_IP) " || -z " $( CIDR) " || -z " $( PASSERELLE) " ) ] ] ; then \
printf '%s\n' 'Refus: fournir ADRESSE_IP, CIDR et PASSERELLE, ou utiliser DHCP=true.' ; \
exit 2; \
fi
@ipconfig= 'ip=dhcp' ; \
if [ [ " $( DHCP) " != "true" ] ] ; then \
ipconfig = 'ip=$(ADRESSE_IP)/$(CIDR),gw=$(PASSERELLE)' ; \
fi ; \
extra_vars = ( \
-e proxmox_clone_nom = " $( HOTE) " \
-e proxmox_clone_vmid = " $( VMID) " \
-e proxmox_clone_ipconfig0 = " $$ ipconfig " \
) ; \
[ [ -n " $( VMID_MODELE) " ] ] && extra_vars += ( -e proxmox_clone_vmid_modele = " $( VMID_MODELE) " ) ; \
[ [ -n " $( NOEUD_PROXMOX) " ] ] && extra_vars += ( -e proxmox_clone_noeud = " $( NOEUD_PROXMOX) " ) ; \
[ [ -n " $( STOCKAGE_PROXMOX) " ] ] && extra_vars += ( -e proxmox_clone_stockage = " $( STOCKAGE_PROXMOX) " ) ; \
[ [ -n " $( FORMAT_DISQUE) " ] ] && extra_vars += ( -e proxmox_clone_format = " $( FORMAT_DISQUE) " ) ; \
[ [ -n " $( CLONE_COMPLET) " ] ] && extra_vars += ( -e proxmox_clone_complet = " $( CLONE_COMPLET) " ) ; \
[ [ -n " $( TAILLE_DISQUE) " ] ] && extra_vars += ( -e proxmox_clone_taille_disque = " $( TAILLE_DISQUE) " ) ; \
2026-06-30 10:07:04 -04:00
[ [ -n " $( COEURS) " ] ] && extra_vars += ( -e proxmox_clone_coeurs = " $( COEURS) " ) ; \
[ [ -n " $( MEMOIRE) " ] ] && extra_vars += ( -e proxmox_clone_memoire = " $( MEMOIRE) " ) ; \
2026-06-24 20:17:46 -04:00
[ [ -n " $( DISQUE_PROXMOX) " ] ] && extra_vars += ( -e proxmox_clone_disque = " $( DISQUE_PROXMOX) " ) ; \
[ [ -n " $( DNS) " ] ] && extra_vars += ( -e proxmox_clone_dns = " $( DNS) " ) ; \
[ [ -n " $( CIUSER) " ] ] && extra_vars += ( -e proxmox_clone_ciuser = " $( CIUSER) " ) ; \
[ [ -n " $( CLE_SSH_PUBLIQUE) " ] ] && extra_vars += ( -e proxmox_clone_cle_publique_fichier = " $( CLE_SSH_PUBLIQUE) " ) ; \
[ [ -n " $( PONT_PROXMOX) " ] ] && extra_vars += ( -e proxmox_clone_pont = " $( PONT_PROXMOX) " ) ; \
extra_vars += ( -e proxmox_clone_vlan = " $( VLAN) " ) ; \
[ [ -n " $( DEMARRER) " ] ] && extra_vars += ( -e proxmox_clone_demarrer = " $( DEMARRER) " ) ; \
vault_args = ( ) ; \
2026-07-01 15:38:42 -04:00
vault_file = "" ; \
for d in lab principal production; do \
f = " $( SETOPS_INSTANCE) /inventories/ $$ d/group_vars/proxmox.vault.yml " ; \
[ [ -f " $$ f " ] ] && vault_file = " $$ f " && break; \
done ; \
if [ [ -n " $$ vault_file " && -f " $$ vault_file " ] ] ; then \
2026-06-24 20:17:46 -04:00
read -r premiere_ligne < " $$ vault_file " || true; \
case " $$ premiere_ligne " in \
'$$ANSIBLE_VAULT' *) \
if [ [ -z " $$ {ANSIBLE_VAULT_PASSWORD_FILE:-} " ] ] ; then \
vault_args += ( --ask-vault-pass ) ; \
fi ; \
; ; \
esac ; \
fi ; \
ansible-playbook -i localhost, $( PLAYBOOK_PROXMOX_CLONER_VM) " $$ {vault_args[@]} " " $$ {extra_vars[@]} "
creer-vm : _instance -requise
@set -e; \
if [ [ -z " $( HOTE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote (declare dans le plan).' ; \
exit 2; \
fi ; \
params = " $$ (python3 scripts/inventory_host.py --inventaire $( INVENTAIRE_PRODUCTION) parametres-proxmox --hote $( HOTE) ) " ; \
eval " $$ params " ; \
$( MAKE) cloner-vm \
HOTE = " $( HOTE) " \
VMID = " $$ SETOPS_VMID " \
ADRESSE_IP = " $$ SETOPS_IP " \
CIDR = " $$ SETOPS_CIDR " \
PASSERELLE = " $$ SETOPS_PASSERELLE " \
VLAN = " $$ SETOPS_VLAN " \
STOCKAGE_PROXMOX = " $$ {SETOPS_STOCKAGE:- $( STOCKAGE_PROXMOX) } " \
TAILLE_DISQUE = " $$ {SETOPS_DISQUE:- $( TAILLE_DISQUE) } " \
2026-06-30 10:07:04 -04:00
COEURS = " $$ {SETOPS_COEURS:- $( COEURS) } " \
MEMOIRE = " $$ {SETOPS_MEMOIRE:- $( MEMOIRE) } " \
2026-06-24 20:17:46 -04:00
NOEUD_PROXMOX = " $$ {SETOPS_NOEUD:- $( NOEUD_PROXMOX) } " \
VMID_MODELE = " $( VMID_MODELE) " \
FORMAT_DISQUE = " $( FORMAT_DISQUE) " \
DISQUE_PROXMOX = " $( DISQUE_PROXMOX) " \
DNS = " $( DNS) " \
DHCP = " $( DHCP) " \
CIUSER = " $( CIUSER) " \
CLE_SSH_PUBLIQUE = " $( CLE_SSH_PUBLIQUE) " \
PONT_PROXMOX = " $( PONT_PROXMOX) " \
DEMARRER = " $( DEMARRER) " \
CLONE_COMPLET = " $( CLONE_COMPLET) "
inventaire-verifier : ansible -runtime _instance -requise
ansible-inventory -i $( INVENTAIRE_LAB) --list > /dev/null
ansible-inventory -i $( INVENTAIRE_PRODUCTION) --list > /dev/null
python3 scripts/inventory_host.py --inventaire $( INVENTAIRE_PRODUCTION) verifier-playbooks --dossier-playbooks $( DOSSIER_PLAYBOOKS_GROUPES)
python3 scripts/inventory_host.py --inventaire $( INVENTAIRE_PRODUCTION) --dependances $( FICHIER_DEPENDANCES) verifier-dependances --dossier-playbooks $( DOSSIER_PLAYBOOKS_GROUPES)
python3 scripts/verifier_gui.py
python3 scripts/serveurs.py verifier
python3 scripts/applications.py verifier
python3 scripts/bases_donnees.py verifier
python3 scripts/domaines.py verifier
.PHONY : bases bases -verifier domaines domaines -verifier applications applications -verifier applications -bootstrap serveurs serveurs -verifier serveurs -bootstrap
serveurs :
python3 scripts/serveurs.py lister
serveurs-verifier :
python3 scripts/serveurs.py verifier
serveurs-bootstrap :
python3 scripts/serveurs.py bootstrap
.PHONY : instancier instancier -appliquer
instancier : _instance -requise
python3 scripts/instancier.py generer
python3 scripts/instancier.py comparer
instancier-appliquer : _instance -requise
2026-06-25 09:29:08 -04:00
python3 scripts/instancier.py appliquer $( if $( FORCE) ,--force)
2026-06-24 20:17:46 -04:00
bases :
python3 scripts/bases_donnees.py lister
bases-verifier :
python3 scripts/bases_donnees.py verifier
domaines :
python3 scripts/domaines.py lister
domaines-verifier :
python3 scripts/domaines.py verifier
applications :
python3 scripts/applications.py lister
applications-verifier :
python3 scripts/applications.py verifier
applications-bootstrap :
python3 scripts/applications.py bootstrap
inventaire-lister : ansible -runtime
ansible-inventory -i $( FICHIER_INVENTAIRE) --list
inventaire-graphe : ansible -runtime
ansible-inventory -i $( FICHIER_INVENTAIRE) --graph
inventaire-hote : ansible -runtime
@if [ [ -z " $( HOTE) " ] ] ; then \
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote.' ; \
exit 2; \
fi
ansible-inventory -i $( FICHIER_INVENTAIRE) --host $( HOTE)
inventaire-lab :
$( MAKE) inventaire-graphe FICHIER_INVENTAIRE = " $( INVENTAIRE_LAB) "
inventaire-production :
$( MAKE) inventaire-graphe FICHIER_INVENTAIRE = " $( INVENTAIRE_PRODUCTION) "
.PHONY : _verifier -acces -modele _verifier -privileges -modele preparer -modele verifier -modele nettoyer -modele
_verifier-acces-modele : ansible -runtime
ansible -i $( INVENTAIRE_LAB) $( GROUPE_MODELE) -m ping -e ansible_become = false
_verifier-privileges-modele : ansible -runtime
ansible -i $( INVENTAIRE_LAB) $( GROUPE_MODELE) -b -m command -a "whoami"
preparer-modele : ansible -runtime _verifier -acces -modele _verifier -privileges -modele
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_PREPARER_MODELE)
verifier-modele : ansible -runtime
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_VERIFIER_MODELE)
nettoyer-modele : ansible -runtime
@if [ [ " $( CONFIRMER) " != "true" ] ] ; then \
printf '%s\n' 'Refus: relancer avec CONFIRMER=true pour le nettoyage final du modele.' ; \
exit 2; \
fi
ansible-playbook -i $( INVENTAIRE_LAB) $( PLAYBOOK_NETTOYER_MODELE) -e template_cleanup_confirm = true
.PHONY : _verifier -acces -hote _verifier -privileges -hote faits verifier -hote
_verifier-acces-hote : ansible -runtime
ansible -i $( INVENTAIRE_PRODUCTION) $( LIMITE) -m ping -e ansible_become = false
_verifier-privileges-hote : ansible -runtime
ansible -i $( INVENTAIRE_PRODUCTION) $( LIMITE) -b -m command -a "whoami"
faits : ansible -runtime
ansible -i $( INVENTAIRE_PRODUCTION) $( LIMITE) -m setup -a "filter=ansible_distribution*"
verifier-hote : ansible -runtime
ansible-playbook -i $( INVENTAIRE_PRODUCTION) $( PLAYBOOK_VERIFIER_HOTE) $( OPTIONS_PLAYBOOK)