diff --git a/roles/serveur_nginx/templates/expositions.conf.j2 b/roles/serveur_nginx/templates/expositions.conf.j2 index c8344b5..f6c9e89 100644 --- a/roles/serveur_nginx/templates/expositions.conf.j2 +++ b/roles/serveur_nginx/templates/expositions.conf.j2 @@ -6,6 +6,10 @@ # amont = http://:. Une exposition # non resolvable (application sans hote actif, ou sans port) est listee mais # NON publiee (binding declare, pas encore cablable). +{% if serveur_nginx_expositions | default([]) | selectattr('websocket', 'defined') | selectattr('websocket') | list | length > 0 %} +# Une exposition au moins est WebSocket-aware (ex. Collabora) : map d'upgrade. +map $http_upgrade $connection_upgrade { default upgrade; "" close; } +{% endif %} {% for expo in serveur_nginx_expositions | default([]) %} {% set ns = namespace(amont='') %} {% if expo.hote in hostvars and hostvars[expo.hote].ansible_host is defined and expo.port %} @@ -37,6 +41,13 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; +{% if expo.websocket | default(false) %} + # Collabora & co : editeur en direct via WebSocket (upgrade + longue tenue). + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_read_timeout 3600s; +{% endif %} } } {% else %} diff --git a/scripts/instancier.py b/scripts/instancier.py index b8f027e..bafdb61 100644 --- a/scripts/instancier.py +++ b/scripts/instancier.py @@ -27,10 +27,12 @@ import yaml from inventory_rules import ( charger_applications, + charger_domaines, charger_nomenclature, charger_serveurs, deriver_nomenclature, deriver_ressources, + expositions_des_applications, fonction_seq, ) @@ -55,6 +57,7 @@ GENERE = INVENTAIRE.with_name("hosts.genere.yml") FICHIER_SERVEURS = INSTANCE / "plan/serveurs.yml" FICHIER_APPLICATIONS = INSTANCE / "plan/applications.yml" FICHIER_NOMENCLATURE = INSTANCE / "plan/nomenclature.yml" +FICHIER_DOMAINES = INSTANCE / "plan/domaines.yml" GROUPES_SOCLE = ["serveur_debian", "serveur_durci"] PLACEMENT = [("noeud", "proxmox_noeud"), ("stockage", "proxmox_stockage"), @@ -151,6 +154,9 @@ def generer() -> dict: apps = charger_applications(FICHIER_APPLICATIONS).get("applications", {}) nomenclature = charger_nomenclature(FICHIER_NOMENCLATURE) injections = resoudre_liens(apps, serveurs, nomenclature) + # Expositions du plan (champ 'expose') -> pour deriver les SANs de chaque edge. + domaines = charger_domaines(FICHIER_DOMAINES) + expositions = expositions_des_applications({"applications": apps}, domaines) services_par_hote: dict = {} for app in apps.values(): @@ -184,9 +190,14 @@ def generer() -> dict: # Variables derivees des liens (bindings) declares par les applications. for var, val in injections.get(nom, {}).items(): hostvars[var] = val + groupes = set(GROUPES_SOCLE) | services_par_hote.get(nom, set()) | set(srv.get("integrations") or []) + # SANs d'exposition : les FQDN que cet edge sert (derives du plan) -> cert edge + # (client_pki_sans), au lieu d'une liste manuelle. Vide si l'hote n'est pas un edge. + sans = sorted({e["fqdn"] for e in expositions if e.get("edge") in groupes}) + if sans: + hostvars["sans_exposition"] = sans etat = "hotes_actifs" if srv.get("etat") == "actif" else "hotes_planifies" children[etat]["hosts"][nom] = hostvars - groupes = set(GROUPES_SOCLE) | services_par_hote.get(nom, set()) | set(srv.get("integrations") or []) for groupe in sorted(groupes): children.setdefault(groupe, {"hosts": {}})["hosts"][nom] = None return {"all": {"children": children}} diff --git a/scripts/inventory_rules.py b/scripts/inventory_rules.py index c7fa77d..cb276f8 100644 --- a/scripts/inventory_rules.py +++ b/scripts/inventory_rules.py @@ -200,6 +200,9 @@ def expositions_des_applications(applications: dict, domaines: dict, edge: str | "fqdn": fqdn, "application": app_id, "groupe": app.get("groupe"), "hote": app.get("hote"), "port": app.get("port"), "edge": edge_dom, "domaine": dom, + # Exposition WebSocket-aware (ex. Collabora) : le vhost ajoute + # alors l'upgrade Upgrade/Connection. Declare par l'app (websocket: true). + "websocket": bool(app.get("websocket")), }) return resultat