diff --git a/README.md b/README.md index 2a47c66..461a6d9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ es steht deshalb **kein Passwort, kein Token und keine Kundenangabe** in diesem | `autoinstall/` | NoCloud-Seed für die Basis-VM (`user-data`, `meta-data`) | | `rmm-tasks/` | Skripte, die als Task im ConnectWise RMM hinterlegt sind (Quelle für Änderungen) | | `bin/` | Skripte, die auf der VM unter `/srv/espo/bin/` liegen und von Tasks aufgerufen werden | -| `compose/` | Compose-Vorlage der Kundeninstanz und die EspoCRM-Grundeinstellungen (`config-override.php`) | +| `docker/` | je Ring ein Ordner mit der `docker-compose.yml` dieses Standes, dazu die EspoCRM-Grundeinstellungen (`config-override.php`) | Konzept, Entscheidungen und Runbooks liegen im internen Repository `espoCRM/espo-fleet-ops`. @@ -20,12 +20,21 @@ autoinstall ds=nocloud-net\;s=https://gitea.subcura.net/EspoCRM_Public/espo-depl Das Semikolon muss maskiert werden – in GRUB trennt ein unmaskiertes `;` zwei Befehle. -## Compose +## Compose und Ringe -`compose/docker-compose.vorlage.yml` ist für alle Kunden identisch und enthält genau einen Platzhalter: `__FQDN__`. -`bin/espo-compose-rendern ` setzt ihn ein und schreibt `/srv/espo/docker-compose.yml`. Diese Datei auf der VM ist -ein **Erzeugnis** – sie wird bei jedem Lauf neu geschrieben, Änderungen von Hand gehen verloren. Geändert wird die -Vorlage hier im Repository. +| Ordner | Ring | Inhalt | +|---|---|---| +| `docker/0 - intern/` | 0 | der aktuelle Stand, hier wird entwickelt und getestet | +| `docker/1 - Pilotkunde/` | 1 | freigegebener Stand für Pilotkunden | +| `docker/2 - Produktivkunde/` | 2 | freigegebener Stand für den Regelbetrieb | + +Jeder Ordner enthält eine vollständige `docker-compose.yml` mit genau einem Platzhalter: `__FQDN__`. +**Eine Freigabe ist das Kopieren dieser Datei in den nächsten Ordner** – damit steht in jedem `git diff`, welche +Instanzen den neuen Stand bekommen. + +`bin/espo-compose-rendern ` holt den Stand des Rings, setzt den FQDN ein und schreibt +`/srv/espo/docker-compose.yml`. Diese Datei auf der VM ist ein **Erzeugnis** – sie wird bei jedem Lauf neu geschrieben, +Änderungen von Hand gehen verloren. Geändert wird im Repository. ## Kundenspezifisches diff --git a/bin/espo-compose-rendern b/bin/espo-compose-rendern index 9dae1bf..617b609 100755 --- a/bin/espo-compose-rendern +++ b/bin/espo-compose-rendern @@ -1,13 +1,13 @@ #!/bin/bash -# espo-compose-rendern - erzeugt /srv/espo/docker-compose.yml aus der versionierten Vorlage. -# Einziger kundenspezifischer Wert ist der FQDN; er kommt aus dem Custom Field espo_fqdn. -# Aufruf: espo-compose-rendern (von ESPO-10 und ESPO-30) +# espo-compose-rendern - schreibt /srv/espo/docker-compose.yml aus dem Stand des jeweiligen Rings. +# Aufruf: espo-compose-rendern (aus ESPO-10-Deploy; fqdn und ring kommen aus den Custom Fields) # Idempotent: gleiche Eingabe, gleiche Datei; geschrieben wird nur bei Unterschied. set -u -VORLAGE_URL=https://gitea.subcura.net/EspoCRM_Public/espo-deploy/raw/branch/main/compose/docker-compose.vorlage.yml +BASIS_URL=https://gitea.subcura.net/EspoCRM_Public/espo-deploy/raw/branch/main/docker ZIEL=/srv/espo/docker-compose.yml FQDN="${1:-}" +RING="${2:-}" # 1. Ohne gueltigen FQDN waeren Site-URL und WebSocket-Adresse falsch - hier abbrechen, nicht spaeter raten. if ! printf '%s' "$FQDN" | grep -Eq '^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$'; then @@ -15,29 +15,38 @@ if ! printf '%s' "$FQDN" | grep -Eq '^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([ echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1 fi -# 2. Vorlage holen - geheimnisfrei und ohne Anmeldung abrufbar. +# 2. Der Ring bestimmt, welcher Stand gilt. Die Ordnernamen im Repo tragen Leerzeichen, daher kodiert. +case "$RING" in + 0) ORDNER="0%20-%20intern" ; KLAR="0 - intern" ;; + 1) ORDNER="1%20-%20Pilotkunde" ; KLAR="1 - Pilotkunde" ;; + 2) ORDNER="2%20-%20Produktivkunde" ; KLAR="2 - Produktivkunde" ;; + *) echo "FEHLER: unbekannter Ring '$RING' (erwartet 0, 1 oder 2)" + echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1 ;; +esac + +# 3. Stand des Rings holen - geheimnisfrei und ohne Anmeldung abrufbar. TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT -curl -fsSL "$VORLAGE_URL" -o "$TMP/vorlage.yml" || { - echo "FEHLER: Vorlage nicht abrufbar ($VORLAGE_URL)" +curl -fsSL "$BASIS_URL/$ORDNER/docker-compose.yml" -o "$TMP/stand.yml" || { + echo "FEHLER: fuer Ring '$KLAR' ist kein Stand hinterlegt oder das Repository ist nicht erreichbar" echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1; } -# 3. Platzhalter ersetzen. -sed "s|__FQDN__|${FQDN}|g" "$TMP/vorlage.yml" > "$TMP/neu.yml" +# 4. Platzhalter ersetzen. +sed "s|__FQDN__|${FQDN}|g" "$TMP/stand.yml" > "$TMP/neu.yml" -# 4. Kein Platzhalter darf uebrig bleiben, sonst startete Docker mit einer unfertigen Datei. +# 5. Kein Platzhalter darf uebrig bleiben, sonst startete Docker mit einer unfertigen Datei. OFFEN="$(grep -oE '__[A-Z][A-Z0-9_]*__' "$TMP/neu.yml" | sort -u | tr '\n' ' ')" if [ -n "$OFFEN" ]; then echo "FEHLER: unersetzte Platzhalter: $OFFEN" echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1 fi -# 5. Die drei EspoCRM-Dienste teilen ueber volumes_from denselben Code - verschiedene Images waeren ein Fehler. +# 6. Die drei EspoCRM-Dienste teilen ueber volumes_from denselben Code - verschiedene Images waeren ein Fehler. if [ "$(grep -E '^[[:space:]]+image: espocrm' "$TMP/neu.yml" | sort -u | wc -l)" -ne 1 ]; then echo "FEHLER: die EspoCRM-Dienste verwenden verschiedene Images" echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1 fi -# 6. Nur bei Unterschied schreiben, damit wiederholte Laeufe nichts anfassen. +# 7. Nur bei Unterschied schreiben, damit wiederholte Laeufe nichts anfassen. install -d -m 0755 /srv/espo if [ -f "$ZIEL" ] && cmp -s "$TMP/neu.yml" "$ZIEL"; then STATUS=UNVERAENDERT @@ -46,12 +55,12 @@ else STATUS=GEAENDERT fi -# 7. Docker selbst pruefen lassen, sobald die Geheimnisdateien liegen - startet nichts. +# 8. Docker selbst pruefen lassen, sobald die Geheimnisdateien liegen - startet nichts. if [ -r /srv/espo/secrets/db_password ]; then docker compose -f "$ZIEL" config -q || { echo "FEHLER: Compose-Datei nicht gueltig" echo "ESPO_COMPOSE_ERGEBNIS: FEHLER"; exit 1; } fi -echo "$ZIEL $STATUS (FQDN $FQDN)" +echo "$ZIEL $STATUS (Ring '$KLAR', FQDN $FQDN)" echo "ESPO_COMPOSE_ERGEBNIS: OK" diff --git a/compose/docker-compose.vorlage.yml b/docker/0 - intern/docker-compose.yml similarity index 94% rename from compose/docker-compose.vorlage.yml rename to docker/0 - intern/docker-compose.yml index 3cdb30c..ac4c095 100644 --- a/compose/docker-compose.vorlage.yml +++ b/docker/0 - intern/docker-compose.yml @@ -1,6 +1,7 @@ -# Vorlage fuer die Kunden-VM. Einziger kundenspezifischer Wert: __FQDN__. -# Gerendert von bin/espo-compose-rendern nach /srv/espo/docker-compose.yml. +# Stand fuer Ring 0 (intern). Einziger kundenspezifischer Wert: __FQDN__. +# espo-compose-rendern setzt ihn ein und schreibt /srv/espo/docker-compose.yml. # Aenderungen ausschliesslich hier im Repository, nie auf der VM. +# Freigabe in den naechsten Ring = diese Datei in dessen Ordner kopieren. name: espocrm services: diff --git a/docker/1 - Pilotkunde/LIESMICH.md b/docker/1 - Pilotkunde/LIESMICH.md new file mode 100644 index 0000000..2405c89 --- /dev/null +++ b/docker/1 - Pilotkunde/LIESMICH.md @@ -0,0 +1,4 @@ +# Ring 1 - Pilotkunde + +Für diesen Ring ist noch **kein Stand freigegeben**. Sobald ein Stand aus Ring 0 freigegeben wird, kommt die +dazugehörige `docker-compose.yml` hierher. Bis dahin bricht `espo-compose-rendern` für diesen Ring ab. diff --git a/docker/2 - Produktivkunde/LIESMICH.md b/docker/2 - Produktivkunde/LIESMICH.md new file mode 100644 index 0000000..46a96a4 --- /dev/null +++ b/docker/2 - Produktivkunde/LIESMICH.md @@ -0,0 +1,4 @@ +# Ring 2 - Produktivkunde + +Für diesen Ring ist noch **kein Stand freigegeben**. Sobald ein Stand aus Ring 0 freigegeben wird, kommt die +dazugehörige `docker-compose.yml` hierher. Bis dahin bricht `espo-compose-rendern` für diesen Ring ab. diff --git a/compose/config-override.php b/docker/config-override.php similarity index 100% rename from compose/config-override.php rename to docker/config-override.php