i18n: English default, French for FrancPaysan (v1.1)
This commit is contained in:
parent
a2afe690b7
commit
2465347fd4
13 changed files with 483 additions and 86 deletions
|
|
@ -360,3 +360,7 @@ LADDER_LOAD=0 ./taler-monitoring.sh ladder
|
|||
- SSH `koopa` or `koopa-external` (inside / load / sanity server bits)
|
||||
- secrets under `koopa-admin-secrets/...` for e2e
|
||||
- `taler-wallet-cli` for e2e
|
||||
|
||||
## Languages (i18n)
|
||||
|
||||
Default **English**. FrancPaysan stacks use **French** (`TALER_MON_LANG=fr`, auto for `*lefrancpaysan*`). See `VERSIONS.md` and `i18n.sh`.
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.0.0
|
||||
1.1.0
|
||||
30
VERSIONS.md
30
VERSIONS.md
|
|
@ -1,14 +1,36 @@
|
|||
# VERSIONS — taler-monitoring
|
||||
|
||||
Release history for the standalone **taler-monitoring** suite
|
||||
(https://git.hacktivism.ch/hernani/taler-monitoring).
|
||||
|
||||
| Tag | Date (UTC) | Notes |
|
||||
|-----|------------|--------|
|
||||
| **v1.0** | 2026-07-18 | Initial standalone release. Split from `koopa-admin-log` at `scripts/taler-monitoring/` (tip after monitoring host-agent/site-gen split commits). |
|
||||
| **v1.1** | 2026-07-18 | **i18n**: default UI/console language **English**; **French** for FrancPaysan (`TALER_MON_LANG=fr`, auto on `*lefrancpaysan*`). Sticky bar “what this monitors” EN/FR; badge/summary chrome + message translation via `i18n.sh`. |
|
||||
| **v1.0** | 2026-07-18 | Initial standalone release. Split from `koopa-admin-log` (`scripts/taler-monitoring/`). Host-agent HTML, surface, aptdeploy, sticky bar. |
|
||||
|
||||
Source: https://git.hacktivism.ch/hernani/taler-monitoring
|
||||
## Language (v1.1+)
|
||||
|
||||
| Context | Language |
|
||||
|---------|----------|
|
||||
| Default / GOA / hacktivism | **English** |
|
||||
| FrancPaysan prod + stage (`*lefrancpaysan*`) | **French** (auto or `TALER_MON_LANG=fr`) |
|
||||
|
||||
```bash
|
||||
# force
|
||||
TALER_MON_LANG=fr ./taler-monitoring.sh -d lefrancpaysan.ch urls
|
||||
TALER_MON_LANG=en ./taler-monitoring.sh -d lefrancpaysan.ch urls
|
||||
```
|
||||
|
||||
Host-agent env examples:
|
||||
- `host-agent/env/francpaysan.env.example` → `TALER_MON_LANG=fr`
|
||||
- `host-agent/env/stagepaysan.env.example` → `TALER_MON_LANG=fr`
|
||||
- `host-agent/env/hacktivism.env.example` → `TALER_MON_LANG=en`
|
||||
|
||||
## Pin a release
|
||||
|
||||
```bash
|
||||
git clone https://git.hacktivism.ch/hernani/taler-monitoring.git ~/src/taler-monitoring
|
||||
cd ~/src/taler-monitoring && git checkout v1.0 # or stay on main
|
||||
cd ~/src/taler-monitoring && git checkout v1.1
|
||||
```
|
||||
|
||||
Default host-agent tracks `origin/main` (`SUITE_UPDATE_MODE=reset`). Pin with `SUITE_GIT_REF=v1.0` in `~/.config/taler-monitoring/env`.
|
||||
Default host-agent tracks `origin/main`. Pin with `SUITE_GIT_REF=v1.1` in `~/.config/taler-monitoring/env`.
|
||||
|
|
|
|||
|
|
@ -24,3 +24,4 @@
|
|||
# HTML_OUT=$HOME/monitoring-sites-staging
|
||||
# MON_HOSTS="bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch"
|
||||
# SOURCE_REPO_WEB=https://git.hacktivism.ch/hernani/taler-monitoring
|
||||
# TALER_MON_LANG=en # en default; fr for FrancPaysan (auto if domain *lefrancpaysan*)
|
||||
|
|
|
|||
3
host-agent/env/francpaysan.env.example
vendored
3
host-agent/env/francpaysan.env.example
vendored
|
|
@ -22,3 +22,6 @@ SUITE_UPDATE_MODE=reset
|
|||
SOURCE_REPO_WEB=https://git.hacktivism.ch/hernani/taler-monitoring
|
||||
|
||||
# DEPLOY_WWW_ROOT=/var/www/monitoring-sites
|
||||
|
||||
# UI language for console + HTML sticky bar (en|fr)
|
||||
TALER_MON_LANG=fr
|
||||
|
|
|
|||
2
host-agent/env/hacktivism.env.example
vendored
2
host-agent/env/hacktivism.env.example
vendored
|
|
@ -22,3 +22,5 @@ SUITE_UPDATE_MODE=reset
|
|||
SOURCE_REPO_WEB=https://git.hacktivism.ch/hernani/taler-monitoring
|
||||
|
||||
DEPLOY_WWW_ROOT=/var/www/monitoring-sites
|
||||
|
||||
TALER_MON_LANG=en
|
||||
|
|
|
|||
3
host-agent/env/stagepaysan.env.example
vendored
3
host-agent/env/stagepaysan.env.example
vendored
|
|
@ -25,3 +25,6 @@ SOURCE_REPO_WEB=https://git.hacktivism.ch/hernani/taler-monitoring
|
|||
|
||||
# Optional public docroot if this user can write it
|
||||
# DEPLOY_WWW_ROOT=/var/www/monitoring-sites
|
||||
|
||||
# UI language for console + HTML sticky bar (en|fr)
|
||||
TALER_MON_LANG=fr
|
||||
|
|
|
|||
|
|
@ -72,6 +72,15 @@ export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
|||
export AUTH401_CONTINUE="${AUTH401_CONTINUE:-${CONTINUE_ON_ERROR}}"
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-600}"
|
||||
export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}"
|
||||
# UI language: en default; fr for FrancPaysan (override with TALER_MON_LANG)
|
||||
if [ -z "${TALER_MON_LANG:-}" ]; then
|
||||
case "$TALER_DOMAIN" in
|
||||
*lefrancpaysan*|*francpaysan*) export TALER_MON_LANG=fr ;;
|
||||
*) export TALER_MON_LANG=en ;;
|
||||
esac
|
||||
fi
|
||||
export TALER_MON_LANG
|
||||
|
||||
PHASES="${PHASES:-urls inside versions}"
|
||||
HTML_BASE="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
MON_HOSTS="${MON_HOSTS:-}"
|
||||
|
|
@ -285,6 +294,7 @@ htmlify_host() {
|
|||
|
||||
if [ -n "$SITE_GEN" ] && [ -f "$SITE_GEN/console_to_html.py" ]; then
|
||||
python3 "$SITE_GEN/console_to_html.py" \
|
||||
--lang "${TALER_MON_LANG:-en}" \
|
||||
--log "$LOG" \
|
||||
--out "$mon_err" \
|
||||
--hostname "$host" \
|
||||
|
|
@ -297,6 +307,7 @@ htmlify_host() {
|
|||
--link-other "$HTML_URL_OK"
|
||||
if [ "$ec" -eq 0 ]; then
|
||||
python3 "$SITE_GEN/console_to_html.py" \
|
||||
--lang "${TALER_MON_LANG:-en}" \
|
||||
--log "$LOG" \
|
||||
--out "$mon" \
|
||||
--hostname "$host" \
|
||||
|
|
@ -311,6 +322,7 @@ htmlify_host() {
|
|||
echo "html $host → ${HTML_URL_OK} only (clean · ${COMMIT_SHORT:-?})"
|
||||
else
|
||||
python3 "$SITE_GEN/console_to_html.py" \
|
||||
--lang "${TALER_MON_LANG:-en}" \
|
||||
--log "$LOG" \
|
||||
--out "$mon" \
|
||||
--hostname "$host" \
|
||||
|
|
|
|||
101
i18n.sh
Normal file
101
i18n.sh
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env bash
|
||||
# i18n.sh — language for taler-monitoring console + HTML chrome
|
||||
#
|
||||
# TALER_MON_LANG=en|fr (default en)
|
||||
# Auto: domains *lefrancpaysan* → fr unless TALER_MON_LANG is set explicitly.
|
||||
|
||||
: "${TALER_MON_LANG:=}"
|
||||
: "${TALER_MON_LANG_SET:=0}"
|
||||
|
||||
i18n_init() {
|
||||
if [ -n "${TALER_MON_LANG:-}" ]; then
|
||||
TALER_MON_LANG_SET=1
|
||||
fi
|
||||
if [ "${TALER_MON_LANG_SET}" != "1" ]; then
|
||||
case "${TALER_DOMAIN:-}" in
|
||||
*lefrancpaysan*|*francpaysan*)
|
||||
TALER_MON_LANG=fr
|
||||
;;
|
||||
*)
|
||||
TALER_MON_LANG=en
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case "${TALER_MON_LANG}" in
|
||||
fr|FR|fra|french) TALER_MON_LANG=fr ;;
|
||||
*) TALER_MON_LANG=en ;;
|
||||
esac
|
||||
export TALER_MON_LANG
|
||||
}
|
||||
|
||||
i18n_tag() {
|
||||
local t="$1"
|
||||
if [ "${TALER_MON_LANG:-en}" != "fr" ]; then
|
||||
printf '%s' "$t"
|
||||
return 0
|
||||
fi
|
||||
case "$t" in
|
||||
OK) printf 'OK' ;;
|
||||
ERROR) printf 'ERREUR' ;;
|
||||
WARN) printf 'AVERT' ;;
|
||||
INFO) printf 'INFO' ;;
|
||||
BLOCKER) printf 'BLOCAGE' ;;
|
||||
BLOCK) printf 'BLOC' ;;
|
||||
SUMMARY) printf 'RESUME' ;;
|
||||
PROG|PROGRESS) printf 'PROG' ;;
|
||||
*) printf '%s' "$t" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
i18n_text() {
|
||||
local s="$*"
|
||||
if [ "${TALER_MON_LANG:-en}" != "fr" ] || [ -z "$s" ]; then
|
||||
printf '%s' "$s"
|
||||
return 0
|
||||
fi
|
||||
case "$s" in
|
||||
"numbered checks this run:") printf 'controles numerotes de cette execution :' ;;
|
||||
"failed — see list above"|"failed - see list above") printf 'echec — voir la liste ci-dessus' ;;
|
||||
"BLOCKERS · pay/withdraw cannot finish") printf 'BLOCAGES · paiement/retrait impossible' ;;
|
||||
"BLOCKERS (pay/withdraw cannot finish)") printf 'BLOCAGES (paiement/retrait impossible)' ;;
|
||||
"ERRORS · failed checks") printf 'ERREURS · controles en echec' ;;
|
||||
"ERRORS (failed checks)") printf 'ERREURS (controles en echec)' ;;
|
||||
"pay/withdraw cannot finish") printf 'paiement/retrait impossible a terminer' ;;
|
||||
"SUMMARY") printf 'RESUME' ;;
|
||||
"totals:") printf 'totaux :' ;;
|
||||
"container") printf 'conteneur' ;;
|
||||
"disk") printf 'disque' ;;
|
||||
"package") printf 'paquet' ;;
|
||||
"version") printf 'version' ;;
|
||||
"reachability") printf 'accessibilite' ;;
|
||||
"server-header") printf 'en-tete Server' ;;
|
||||
"inventory") printf 'inventaire' ;;
|
||||
"flags") printf 'options' ;;
|
||||
"target domain") printf 'domaine cible' ;;
|
||||
"currency") printf 'devise' ;;
|
||||
"phases") printf 'phases' ;;
|
||||
"access") printf 'acces' ;;
|
||||
*)
|
||||
local out="$s"
|
||||
out=${out//shared library missing/bibliotheque partagee manquante}
|
||||
out=${out//shared library error/erreur de bibliotheque partagee}
|
||||
out=${out//not active/non actif}
|
||||
out=${out//after_start/apres_demarrage}
|
||||
out=${out//catalogued but not reachable/catalogue mais inaccessible}
|
||||
out=${out//does not resolve/ne resout pas}
|
||||
out=${out//protocol confirmed/protocole confirme}
|
||||
out=${out//catalogued service OK/service catalogue OK}
|
||||
out=${out//from Server header/depuis en-tete Server}
|
||||
out=${out//OSV clean/OSV sans vulnerabilite}
|
||||
out=${out//actionable vuln/vuln. actionnable}
|
||||
out=${out//header version · not Debian pkg/version en-tete · pas paquet Debian}
|
||||
out=${out//RUN_TIMEOUT exceeded/RUN_TIMEOUT depasse}
|
||||
out=${out//public HTTPS/HTTPS public}
|
||||
out=${out//container status/etat du conteneur}
|
||||
out=${out//remote-only/uniquement distant}
|
||||
out=${out//no SSH/sans SSH}
|
||||
out=${out//failed — see list above/echec — voir la liste ci-dessus}
|
||||
printf '%s' "$out"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
61
lib.sh
61
lib.sh
|
|
@ -2,6 +2,18 @@
|
|||
# Shared helpers for taler-monitoring (laptop or koopa).
|
||||
|
||||
# Default stack = GOA / hacktivism (overridden by TALER_DOMAIN / --domain)
|
||||
# i18n (en default; fr for FrancPaysan — see i18n.sh / TALER_MON_LANG)
|
||||
_I18N_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
if [ -f "$_I18N_DIR/i18n.sh" ]; then
|
||||
# shellcheck source=i18n.sh
|
||||
source "$_I18N_DIR/i18n.sh"
|
||||
i18n_init
|
||||
else
|
||||
i18n_tag() { printf '%s' "$1"; }
|
||||
i18n_text() { printf '%s' "$*"; }
|
||||
i18n_init() { :; }
|
||||
fi
|
||||
|
||||
: "${TALER_DOMAIN:=hacktivism.ch}"
|
||||
: "${BANK_PUBLIC:=https://bank.hacktivism.ch}"
|
||||
: "${EXCHANGE_PUBLIC:=https://exchange.hacktivism.ch}"
|
||||
|
|
@ -114,6 +126,11 @@ set_taler_stack() {
|
|||
BANK_PUBLIC=${BANK_PUBLIC%/}
|
||||
EXCHANGE_PUBLIC=${EXCHANGE_PUBLIC%/}
|
||||
MERCHANT_PUBLIC=${MERCHANT_PUBLIC%/}
|
||||
# re-evaluate language after domain profile (FrancPaysan → fr)
|
||||
if [ "${TALER_MON_LANG_SET:-0}" != "1" ]; then
|
||||
TALER_MON_LANG=
|
||||
i18n_init
|
||||
fi
|
||||
}
|
||||
|
||||
# Load first matching profile from domains.conf.
|
||||
|
|
@ -265,6 +282,11 @@ apply_taler_domain() {
|
|||
BANK_PUBLIC=${BANK_PUBLIC%/}
|
||||
EXCHANGE_PUBLIC=${EXCHANGE_PUBLIC%/}
|
||||
MERCHANT_PUBLIC=${MERCHANT_PUBLIC%/}
|
||||
# re-evaluate language after domain profile (FrancPaysan → fr)
|
||||
if [ "${TALER_MON_LANG_SET:-0}" != "1" ]; then
|
||||
TALER_MON_LANG=
|
||||
i18n_init
|
||||
fi
|
||||
|
||||
# Koopa SSH only for LOCAL_STACK=1. Stage LFP uses INSIDE_SSH (stagepaysan) separately.
|
||||
if [ "${LOCAL_STACK}" != "1" ]; then
|
||||
|
|
@ -679,6 +701,10 @@ _fmt_badge() {
|
|||
# $1=badge style $2=tag text $3=label colour $4=label $5=detail
|
||||
_msg_line() {
|
||||
local badge="$1" tag="$2" lcol="$3" label="$4" detail="${5:-}"
|
||||
# i18n: tags + free text (en default; fr for FrancPaysan)
|
||||
tag=$(i18n_tag "$tag")
|
||||
label=$(i18n_text "$label")
|
||||
[ -n "$detail" ] && detail=$(i18n_text "$detail")
|
||||
if [ -n "$detail" ]; then
|
||||
printf -- '%s %s%s%s%s %s·%s %s%s%s\n' \
|
||||
"$(_fmt_badge "$badge" "$tag")" "$(_fmt_tid)" "$lcol" "$label" "$N" "$D" "$N" "$D" "$detail" "$N"
|
||||
|
|
@ -749,7 +775,8 @@ blocker() {
|
|||
}
|
||||
section() {
|
||||
# Boxed section header (3 lines when colour on)
|
||||
local title="$*"
|
||||
local title
|
||||
title=$(i18n_text "$*")
|
||||
local w=${#title}
|
||||
[ "$w" -lt 24 ] && w=24
|
||||
[ "$w" -gt 56 ] && w=56
|
||||
|
|
@ -783,13 +810,13 @@ summary() {
|
|||
_progress_bar_line "$PROGRESS_DONE" "$PROGRESS_TOTAL"
|
||||
fi
|
||||
if [ "$GLOBAL_N" -gt 0 ]; then
|
||||
printf -- '%s numbered checks this run: #001…#%03d%s\n' "$D" "$GLOBAL_N" "$N"
|
||||
printf -- '%s %s #001…#%03d%s\n' "$D" "$(i18n_text 'numbered checks this run:')" "$GLOBAL_N" "$N"
|
||||
fi
|
||||
if [ "$blk_n" -gt 0 ]; then
|
||||
if [ "${BOX:-0}" = "1" ]; then
|
||||
printf -- '%s┌ BLOCKERS · pay/withdraw cannot finish ┐%s\n' "$BG_BLK" "$N"
|
||||
printf -- '%s┌ %s ┐%s\n' "$BG_BLK" "$(i18n_text 'BLOCKERS · pay/withdraw cannot finish')" "$N"
|
||||
else
|
||||
printf -- '%s--- BLOCKERS (pay/withdraw cannot finish) ---%s\n' "$M" "$N"
|
||||
printf -- '%s--- %s ---%s\n' "$M" "$(i18n_text 'BLOCKERS (pay/withdraw cannot finish)')" "$N"
|
||||
fi
|
||||
local b
|
||||
for b in "${BLOCKERS[@]}"; do
|
||||
|
|
@ -798,9 +825,9 @@ summary() {
|
|||
fi
|
||||
if [ "${#ERRORS[@]}" -gt 0 ] && [ "$blk_n" -lt "${#ERRORS[@]}" ]; then
|
||||
if [ "${BOX:-0}" = "1" ]; then
|
||||
printf -- '%s┌ ERRORS · failed checks ┐%s\n' "$BG_ERR" "$N"
|
||||
printf -- '%s┌ %s ┐%s\n' "$BG_ERR" "$(i18n_text 'ERRORS · failed checks')" "$N"
|
||||
else
|
||||
printf -- '%s--- ERRORS (failed checks) ---%s\n' "$R" "$N"
|
||||
printf -- '%s--- %s ---%s\n' "$R" "$(i18n_text 'ERRORS (failed checks)')" "$N"
|
||||
fi
|
||||
local e
|
||||
for e in "${ERRORS[@]}"; do
|
||||
|
|
@ -811,9 +838,11 @@ summary() {
|
|||
|
||||
# Coloured totals — same severity badges as check lines (always; NO_COLOR blanks ANSI)
|
||||
if [ "${BOX:-0}" = "1" ]; then
|
||||
printf -- '\n%s┌ SUMMARY ┐%s\n' "$BG_SEC" "$N"
|
||||
printf -- '\n%s┌ %s ┐%s\n' "$BG_SEC" "$(i18n_tag SUMMARY)" "$N"
|
||||
_sum_badge() { # $1=bg $2=tag $3=fg $4=n
|
||||
printf -- ' %s┌ %-5s┐%s %s%4d%s\n' "$1" "$2" "$N" "$3" "$4" "$N"
|
||||
local _tg
|
||||
_tg=$(i18n_tag "$2")
|
||||
printf -- ' %s┌ %-5s┐%s %s%4d%s\n' "$1" "$_tg" "$N" "$3" "$4" "$N"
|
||||
}
|
||||
_sum_badge "$BG_OK" "OK" "$G" "$PASS_N"
|
||||
[ "$FAIL_N" -gt 0 ] && _sum_badge "$BG_ERR" "ERROR" "$R" "$FAIL_N"
|
||||
|
|
@ -821,12 +850,12 @@ summary() {
|
|||
[ "$INFO_N" -gt 0 ] && _sum_badge "$BG_INFO" "INFO" "$C" "$INFO_N"
|
||||
[ "$blk_n" -gt 0 ] && _sum_badge "$BG_BLK" "BLOCK" "$M" "$blk_n"
|
||||
else
|
||||
printf -- '\n[ SUMMARY ]\n'
|
||||
printf -- ' [ OK ] %s%4d%s\n' "$G" "$PASS_N" "$N"
|
||||
[ "$FAIL_N" -gt 0 ] && printf -- ' [ ERROR ] %s%4d%s\n' "$R" "$FAIL_N" "$N"
|
||||
[ "$WARN_N" -gt 0 ] && printf -- ' [ WARN ] %s%4d%s\n' "$Y" "$WARN_N" "$N"
|
||||
[ "$INFO_N" -gt 0 ] && printf -- ' [ INFO ] %s%4d%s\n' "$C" "$INFO_N" "$N"
|
||||
[ "$blk_n" -gt 0 ] && printf -- ' [ BLOCK ] %s%4d%s\n' "$M" "$blk_n" "$N"
|
||||
printf -- '\n[ %s ]\n' "$(i18n_tag SUMMARY)"
|
||||
printf -- ' [ %-5s ] %s%4d%s\n' "$(i18n_tag OK)" "$G" "$PASS_N" "$N"
|
||||
[ "$FAIL_N" -gt 0 ] && printf -- ' [ %-5s ] %s%4d%s\n' "$(i18n_tag ERROR)" "$R" "$FAIL_N" "$N"
|
||||
[ "$WARN_N" -gt 0 ] && printf -- ' [ %-5s ] %s%4d%s\n' "$(i18n_tag WARN)" "$Y" "$WARN_N" "$N"
|
||||
[ "$INFO_N" -gt 0 ] && printf -- ' [ %-5s ] %s%4d%s\n' "$(i18n_tag INFO)" "$C" "$INFO_N" "$N"
|
||||
[ "$blk_n" -gt 0 ] && printf -- ' [ %-5s ] %s%4d%s\n' "$(i18n_tag BLOCK)" "$M" "$blk_n" "$N"
|
||||
fi
|
||||
# one-line rollup (bold label, severity-coloured counts)
|
||||
printf -- ' %stotals:%s %s%d OK%s' "$B" "$N" "$G" "$PASS_N" "$N"
|
||||
|
|
@ -850,9 +879,9 @@ summary() {
|
|||
fi
|
||||
else
|
||||
if [ "${BOX:-0}" = "1" ]; then
|
||||
printf -- ' %s┌ ERROR ┐%s %sfailed — see list above%s\n' "$BG_ERR" "$N" "$R" "$N"
|
||||
printf -- ' %s┌ ERROR ┐%s %s"$(i18n_text "failed — see list above")"%s\n' "$BG_ERR" "$N" "$R" "$N"
|
||||
else
|
||||
printf -- ' %s[ ERROR ] failed — see list above%s\n' "$R" "$N"
|
||||
printf -- ' %s[ ERROR ] "$(i18n_text "failed — see list above")"%s\n' "$R" "$N"
|
||||
fi
|
||||
fi
|
||||
[ "$FAIL_N" -eq 0 ]
|
||||
|
|
|
|||
|
|
@ -8,6 +8,129 @@ import re
|
|||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
def ui_lang(explicit: str = "") -> str:
|
||||
"""en (default) or fr. Env: TALER_MON_LANG; auto fr for lefrancpaysan hosts."""
|
||||
import os
|
||||
lang = (explicit or os.environ.get("TALER_MON_LANG") or "").strip().lower()
|
||||
if lang in ("fr", "fra", "french"):
|
||||
return "fr"
|
||||
if lang in ("en", "eng", "english"):
|
||||
return "en"
|
||||
return "en"
|
||||
|
||||
|
||||
def ui(lang: str, key: str, **kwargs) -> str:
|
||||
"""UI chrome strings for sticky bar (English default; French for FrancPaysan)."""
|
||||
en = {
|
||||
"errors": "ERRORS",
|
||||
"warnings": "WARNINGS",
|
||||
"ok": "OK",
|
||||
"error_one": "{n} error",
|
||||
"error_many": "{n} errors",
|
||||
"warn_one": "{n} warning",
|
||||
"warn_many": "{n} warnings",
|
||||
"jump_first_error": "Jump to first error",
|
||||
"jump_first_warn": "Jump to first warning",
|
||||
"generated": "generated",
|
||||
"source": "source",
|
||||
"what_monitors": "What this monitors",
|
||||
"what_monitors_title": "Expand: what this page checks",
|
||||
"surface_title": "Remote ecosystem surface inventory",
|
||||
"surface_summary": "Public catalog hosts · DNS / TCP / HTTPS / TLS · Server version · CVE",
|
||||
"surface_i1": "Outside-in only: no SSH and no podman exec on remote targets",
|
||||
"surface_i2": "Catalog (surface-catalog.conf): taler.net, demo/test, gnunet.org, taler-ops.ch, taler-systems.com, deb.taler.net, ftp.gnu.org, …",
|
||||
"surface_i3": "Per host: DNS resolve, ICMP (info), open ports, protocol probes, TLS cert expiry, Server-header software version, optional CVE check",
|
||||
"surface_i4": "HTML published only on taler.hacktivism.ch (this page host: {host})",
|
||||
"surface_i5": "Timer: taler-monitoring-surface.timer (hourly)",
|
||||
"apt_title": "apt-src merchant deploy tests (podman on koopa)",
|
||||
"apt_summary": "4 containers · fresh + upgrade tracks · trixie & trixie-testing",
|
||||
"apt_i1": "koopa-taler-deploy-test-apt-src-trixie (fresh, suite trixie)",
|
||||
"apt_i2": "koopa-taler-deploy-test-apt-src-trixie-testing (fresh, trixie-testing)",
|
||||
"apt_i3": "koopa-taler-deploy-test-apt-src-trixie-upgrade (upgrade track)",
|
||||
"apt_i4": "koopa-taler-deploy-test-apt-src-trixie-testing-upgrade (upgrade track)",
|
||||
"apt_i5": "Checks: packages, taler-merchant-httpd --version / ldd, systemd unit, optional local /config probe — not public nginx/HTTPS",
|
||||
"apt_i6": "HTML published only on taler.hacktivism.ch (this page host: {host})",
|
||||
"apt_i7": "Timer: taler-monitoring-aptdeploy.timer (4h)",
|
||||
"focus_bank": "Libeufin bank public HTTPS + container inside checks",
|
||||
"focus_exchange": "Exchange public HTTPS + container inside checks",
|
||||
"focus_merchant": "Merchant backend / SPA public HTTPS + container inside checks",
|
||||
"focus_stack": "Taler stack public + inside checks",
|
||||
"stack_title": "Stack monitoring · {host}",
|
||||
"stack_summary": "{phases} · public + inside",
|
||||
"stack_i1": "Focus: {focus}",
|
||||
"stack_i2": "Phases this run: {phases}",
|
||||
"stack_i3": "Typical: public URLs (HTTPS, QR, perf), inside (podman/ssh), package versions",
|
||||
"stack_i4": "HTML host: {host}",
|
||||
"stack_i5": "Timer: host-agent path + 4h · /monitoring on bank, exchange, merchant fronts",
|
||||
"stack_i_phases": "Log header phases= {phases}",
|
||||
"footer": "Console-style render of taler-monitoring output. Sticky bar: green = clean · yellow = warnings · red = errors. Commit pins the exact tree used for this run.",
|
||||
"redirect_fail": "has failures.",
|
||||
"redirect_see": "See {link} for the full console log, error index, and sticky status bar.",
|
||||
"ago_s": "{n}s ago",
|
||||
"ago_m": "{n}m ago",
|
||||
"ago_h": "{n}h ago",
|
||||
"ago_d": "{n}d ago",
|
||||
"age_title": "page age · updates every second",
|
||||
}
|
||||
fr = {
|
||||
"errors": "ERREURS",
|
||||
"warnings": "AVERTISSEMENTS",
|
||||
"ok": "OK",
|
||||
"error_one": "{n} erreur",
|
||||
"error_many": "{n} erreurs",
|
||||
"warn_one": "{n} avertissement",
|
||||
"warn_many": "{n} avertissements",
|
||||
"jump_first_error": "Aller à la première erreur",
|
||||
"jump_first_warn": "Aller au premier avertissement",
|
||||
"generated": "généré",
|
||||
"source": "source",
|
||||
"what_monitors": "Ce que cette page contrôle",
|
||||
"what_monitors_title": "Déplier : ce que cette page vérifie",
|
||||
"surface_title": "Inventaire de surface de l'écosystème (distant)",
|
||||
"surface_summary": "Hôtes du catalogue public · DNS / TCP / HTTPS / TLS · version serveur · CVE",
|
||||
"surface_i1": "Uniquement de l'extérieur : pas de SSH ni de podman exec sur les cibles distantes",
|
||||
"surface_i2": "Catalogue (surface-catalog.conf) : taler.net, demo/test, gnunet.org, taler-ops.ch, taler-systems.com, deb.taler.net, ftp.gnu.org, …",
|
||||
"surface_i3": "Par hôte : résolution DNS, ICMP (info), ports ouverts, sondes de protocole, expiration du certificat TLS, version logicielle (en-tête Server), CVE optionnel",
|
||||
"surface_i4": "HTML publié uniquement sur taler.hacktivism.ch (hôte de cette page : {host})",
|
||||
"surface_i5": "Minuterie : taler-monitoring-surface.timer (horaire)",
|
||||
"apt_title": "Tests de déploiement apt-src marchand (podman sur koopa)",
|
||||
"apt_summary": "4 conteneurs · pistes fresh + upgrade · trixie et trixie-testing",
|
||||
"apt_i1": "koopa-taler-deploy-test-apt-src-trixie (fresh, suite trixie)",
|
||||
"apt_i2": "koopa-taler-deploy-test-apt-src-trixie-testing (fresh, trixie-testing)",
|
||||
"apt_i3": "koopa-taler-deploy-test-apt-src-trixie-upgrade (piste upgrade)",
|
||||
"apt_i4": "koopa-taler-deploy-test-apt-src-trixie-testing-upgrade (piste upgrade)",
|
||||
"apt_i5": "Contrôles : paquets, taler-merchant-httpd --version / ldd, unité systemd, sonde locale /config optionnelle — pas de nginx/HTTPS public",
|
||||
"apt_i6": "HTML publié uniquement sur taler.hacktivism.ch (hôte de cette page : {host})",
|
||||
"apt_i7": "Minuterie : taler-monitoring-aptdeploy.timer (4 h)",
|
||||
"focus_bank": "Banque Libeufin HTTPS public + contrôles inside conteneur",
|
||||
"focus_exchange": "Exchange HTTPS public + contrôles inside conteneur",
|
||||
"focus_merchant": "Backend marchand / SPA HTTPS public + contrôles inside conteneur",
|
||||
"focus_stack": "Pile Taler public + inside",
|
||||
"stack_title": "Surveillance de pile · {host}",
|
||||
"stack_summary": "{phases} · public + inside",
|
||||
"stack_i1": "Focus : {focus}",
|
||||
"stack_i2": "Phases de cette exécution : {phases}",
|
||||
"stack_i3": "Typique : URL publiques (HTTPS, QR, perf), inside (podman/ssh), versions des paquets",
|
||||
"stack_i4": "Hôte HTML : {host}",
|
||||
"stack_i5": "Minuterie : host-agent path + 4 h · /monitoring sur bank, exchange, fronts marchands",
|
||||
"stack_i_phases": "En-tête de journal phases= {phases}",
|
||||
"footer": "Rendu console de taler-monitoring. Barre collante : vert = OK · jaune = avertissements · rouge = erreurs. Le commit fixe l'arbre exact de cette exécution.",
|
||||
"redirect_fail": "a des échecs.",
|
||||
"redirect_see": "Voir {link} pour le journal console complet, l'index d'erreurs et la barre de statut.",
|
||||
"ago_s": "il y a {n}s",
|
||||
"ago_m": "il y a {n} min",
|
||||
"ago_h": "il y a {n} h",
|
||||
"ago_d": "il y a {n} j",
|
||||
"age_title": "âge de la page · mise à jour chaque seconde",
|
||||
}
|
||||
table = fr if lang == "fr" else en
|
||||
s = table.get(key) or en.get(key) or key
|
||||
try:
|
||||
return s.format(**kwargs)
|
||||
except Exception:
|
||||
return s
|
||||
|
||||
|
||||
# ANSI strip
|
||||
ANSI_RE = re.compile(r"\x1b\[[0-9;]*m")
|
||||
ERR_BULLET_RE = re.compile(r"^\s*[•·*-]\s+(?P<body>.+)$")
|
||||
|
|
@ -192,82 +315,84 @@ def extract_phases(log_text: str) -> str:
|
|||
return ""
|
||||
|
||||
|
||||
|
||||
def monitoring_scope(
|
||||
page_label: str,
|
||||
hostname: str,
|
||||
log_text: str = "",
|
||||
lang: str = "en",
|
||||
) -> dict[str, object]:
|
||||
"""
|
||||
Human-readable description of what this monitoring page covers.
|
||||
Returned keys: title, summary, items (list[str]), kind
|
||||
"""
|
||||
"""Human-readable description of what this page monitors (en default; fr for FP)."""
|
||||
label = (page_label or "monitoring").lower().replace("_", "-")
|
||||
phases = extract_phases(log_text)
|
||||
host = hostname or "?"
|
||||
# Auto-fr for FrancPaysan hosts if lang not forced
|
||||
if lang == "en" and re.search(r"lefrancpaysan|francpaysan", host + " " + log_text, re.I):
|
||||
import os
|
||||
if not (os.environ.get("TALER_MON_LANG") or "").strip():
|
||||
lang = "fr"
|
||||
|
||||
if "surface" in label:
|
||||
return {
|
||||
"kind": "surface",
|
||||
"title": "Remote ecosystem surface inventory",
|
||||
"summary": "Public catalog hosts · DNS / TCP / HTTPS / TLS · Server version · CVE",
|
||||
"lang": lang,
|
||||
"title": ui(lang, "surface_title"),
|
||||
"summary": ui(lang, "surface_summary"),
|
||||
"items": [
|
||||
"Outside-in only: no SSH and no podman exec on remote targets",
|
||||
"Catalog (surface-catalog.conf): taler.net, demo/test, gnunet.org, "
|
||||
"taler-ops.ch, taler-systems.com, deb.taler.net, ftp.gnu.org, …",
|
||||
"Per host: DNS resolve, ICMP (info), open ports, protocol probes, "
|
||||
"TLS cert expiry, Server-header software version, optional CVE check",
|
||||
f"HTML published only on taler.hacktivism.ch "
|
||||
f"(this page host: {host})",
|
||||
"Timer: taler-monitoring-surface.timer (hourly)",
|
||||
ui(lang, "surface_i1"),
|
||||
ui(lang, "surface_i2"),
|
||||
ui(lang, "surface_i3"),
|
||||
ui(lang, "surface_i4", host=host),
|
||||
ui(lang, "surface_i5"),
|
||||
],
|
||||
}
|
||||
|
||||
if "aptdeploy" in label or "apt-deploy" in label or "apt_src" in label:
|
||||
return {
|
||||
"kind": "aptdeploy",
|
||||
"title": "apt-src merchant deploy tests (podman on koopa)",
|
||||
"summary": "4 containers · fresh + upgrade tracks · trixie & trixie-testing",
|
||||
"lang": lang,
|
||||
"title": ui(lang, "apt_title"),
|
||||
"summary": ui(lang, "apt_summary"),
|
||||
"items": [
|
||||
"koopa-taler-deploy-test-apt-src-trixie (fresh, suite trixie)",
|
||||
"koopa-taler-deploy-test-apt-src-trixie-testing (fresh, trixie-testing)",
|
||||
"koopa-taler-deploy-test-apt-src-trixie-upgrade (upgrade track)",
|
||||
"koopa-taler-deploy-test-apt-src-trixie-testing-upgrade (upgrade track)",
|
||||
"Checks: packages, taler-merchant-httpd --version / ldd, systemd unit, "
|
||||
"optional local /config probe — not public nginx/HTTPS",
|
||||
f"HTML published only on taler.hacktivism.ch (this page host: {host})",
|
||||
"Timer: taler-monitoring-aptdeploy.timer (4h)",
|
||||
ui(lang, "apt_i1"),
|
||||
ui(lang, "apt_i2"),
|
||||
ui(lang, "apt_i3"),
|
||||
ui(lang, "apt_i4"),
|
||||
ui(lang, "apt_i5"),
|
||||
ui(lang, "apt_i6", host=host),
|
||||
ui(lang, "apt_i7"),
|
||||
],
|
||||
}
|
||||
|
||||
# Default: stack /monitoring pages (bank, exchange, merchant)
|
||||
phase_txt = phases or "urls · inside · versions"
|
||||
role = "stack"
|
||||
if host.startswith("bank."):
|
||||
if host.startswith("bank.") or "bank." in host:
|
||||
role = "bank"
|
||||
focus = "Libeufin bank public HTTPS + container inside checks"
|
||||
elif host.startswith("exchange.") or host.startswith("stage.exchange."):
|
||||
focus = ui(lang, "focus_bank")
|
||||
elif "exchange." in host:
|
||||
role = "exchange"
|
||||
focus = "Exchange public HTTPS + container inside checks"
|
||||
elif host.startswith("taler.") or "merchant" in host or host.startswith("monnaie."):
|
||||
focus = ui(lang, "focus_exchange")
|
||||
elif host.startswith("taler.") or "merchant" in host or "monnaie." in host:
|
||||
role = "merchant"
|
||||
focus = "Merchant backend / SPA public HTTPS + container inside checks"
|
||||
focus = ui(lang, "focus_merchant")
|
||||
else:
|
||||
focus = "Taler stack public + inside checks"
|
||||
focus = ui(lang, "focus_stack")
|
||||
|
||||
items = [
|
||||
f"Focus: {focus}",
|
||||
f"Phases this run: {phase_txt}",
|
||||
"Typical: public URLs (HTTPS, QR, perf), inside (podman/ssh), package versions",
|
||||
f"HTML host: {host}",
|
||||
"Timer: taler-monitoring-hacktivism (path + 4h) · /monitoring on bank, exchange, taler",
|
||||
ui(lang, "stack_i1", focus=focus),
|
||||
ui(lang, "stack_i2", phases=phase_txt),
|
||||
ui(lang, "stack_i3"),
|
||||
ui(lang, "stack_i4", host=host),
|
||||
ui(lang, "stack_i5"),
|
||||
]
|
||||
if phases:
|
||||
items.insert(2, f"Log header phases= {phases}")
|
||||
items.insert(2, ui(lang, "stack_i_phases", phases=phases))
|
||||
|
||||
return {
|
||||
"kind": role,
|
||||
"title": f"Stack monitoring · {host}",
|
||||
"summary": f"{phase_txt} · public + inside",
|
||||
"lang": lang,
|
||||
"title": ui(lang, "stack_title", host=host),
|
||||
"summary": ui(lang, "stack_summary", phases=phase_txt),
|
||||
"items": items,
|
||||
}
|
||||
|
||||
|
|
@ -289,28 +414,41 @@ def sticky_bar_html(
|
|||
scope: dict[str, object] | None = None,
|
||||
) -> str:
|
||||
level = status_level(n_err, n_warn)
|
||||
if level == "red":
|
||||
status_txt = "ERRORS"
|
||||
elif level == "yellow":
|
||||
status_txt = "WARNINGS"
|
||||
lang = "en"
|
||||
if scope and scope.get("lang"):
|
||||
lang = str(scope.get("lang"))
|
||||
else:
|
||||
status_txt = "OK"
|
||||
lang = ui_lang()
|
||||
# auto-fr for FP hostnames
|
||||
if lang == "en" and re.search(r"lefrancpaysan|francpaysan", hostname or "", re.I):
|
||||
lang = "fr"
|
||||
|
||||
if level == "red":
|
||||
status_txt = ui(lang, "errors")
|
||||
elif level == "yellow":
|
||||
status_txt = ui(lang, "warnings")
|
||||
else:
|
||||
status_txt = ui(lang, "ok")
|
||||
|
||||
if first_err_href and n_err:
|
||||
err_lbl = ui(lang, "error_one", n=n_err) if n_err == 1 else ui(lang, "error_many", n=n_err)
|
||||
err_stat = (
|
||||
f'<a class="stat err" href="{html.escape(first_err_href)}" '
|
||||
f'title="Jump to first error">{n_err} error{"s" if n_err != 1 else ""}</a>'
|
||||
f'title="{html.escape(ui(lang, "jump_first_error"))}">{html.escape(err_lbl)}</a>'
|
||||
)
|
||||
else:
|
||||
err_stat = f'<span class="stat err muted">{n_err} errors</span>'
|
||||
err_lbl = ui(lang, "error_many", n=n_err)
|
||||
err_stat = f'<span class="stat err muted">{html.escape(err_lbl)}</span>'
|
||||
|
||||
if first_warn_href and n_warn:
|
||||
warn_lbl = ui(lang, "warn_one", n=n_warn) if n_warn == 1 else ui(lang, "warn_many", n=n_warn)
|
||||
warn_stat = (
|
||||
f'<a class="stat warn" href="{html.escape(first_warn_href)}" '
|
||||
f'title="Jump to first warning">{n_warn} warning{"s" if n_warn != 1 else ""}</a>'
|
||||
f'title="{html.escape(ui(lang, "jump_first_warn"))}">{html.escape(warn_lbl)}</a>'
|
||||
)
|
||||
else:
|
||||
warn_stat = f'<span class="stat warn muted">{n_warn} warnings</span>'
|
||||
warn_lbl = ui(lang, "warn_many", n=n_warn)
|
||||
warn_stat = f'<span class="stat warn muted">{html.escape(warn_lbl)}</span>'
|
||||
|
||||
other = ""
|
||||
if link_other:
|
||||
|
|
@ -320,7 +458,7 @@ def sticky_bar_html(
|
|||
)
|
||||
|
||||
if scope is None:
|
||||
scope = monitoring_scope(page_label, hostname, "")
|
||||
scope = monitoring_scope(page_label, hostname, "", lang=ui_lang())
|
||||
scope_title = html.escape(str(scope.get("title") or "Monitoring"))
|
||||
scope_summary = html.escape(str(scope.get("summary") or ""))
|
||||
scope_kind = html.escape(str(scope.get("kind") or "monitoring"))
|
||||
|
|
@ -347,21 +485,21 @@ def sticky_bar_html(
|
|||
<span class="generated"
|
||||
data-generated-iso="{html.escape(generated_iso)}"
|
||||
title="{html.escape(generated_at)}">
|
||||
generated <time datetime="{html.escape(generated_iso)}">{html.escape(generated_at)}</time>
|
||||
{html.escape(ui(lang, "generated"))} <time datetime="{html.escape(generated_iso)}">{html.escape(generated_at)}</time>
|
||||
<span class="age" id="generated-age"></span>
|
||||
</span>
|
||||
<button type="button" class="scope-toggle" id="scope-toggle"
|
||||
aria-expanded="false" aria-controls="sticky-scope-panel"
|
||||
title="Aufklappen: was diese Seite prüft">
|
||||
title="{html.escape(ui(lang, "what_monitors_title"))}">
|
||||
<span class="scope-chevron" aria-hidden="true"></span>
|
||||
<span class="scope-toggle-label">Was geprüft wird</span>
|
||||
<span class="scope-toggle-label">{html.escape(ui(lang, "what_monitors"))}</span>
|
||||
<span class="scope-toggle-hint">{scope_summary}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sticky-scope-panel" id="sticky-scope-panel" hidden>
|
||||
<div class="sticky-bar-row secondary">
|
||||
<span class="badge mode-{html.escape(mode)}">{html.escape(mode.upper())}</span>
|
||||
source {commit_html}{suite_bit}
|
||||
{html.escape(ui(lang, "source"))} {commit_html}{suite_bit}
|
||||
{(" · " + other) if other else ""}
|
||||
</div>
|
||||
<div class="scope-body">
|
||||
|
|
@ -531,10 +669,22 @@ STICKY_JS = """
|
|||
(function () {
|
||||
function fmtAge(sec) {
|
||||
if (sec < 0) sec = 0;
|
||||
if (sec < 60) return sec + "s ago";
|
||||
if (sec < 3600) return Math.floor(sec / 60) + "m ago";
|
||||
if (sec < 86400) return Math.floor(sec / 3600) + "h ago";
|
||||
return Math.floor(sec / 86400) + "d ago";
|
||||
var lang = (document.documentElement.getAttribute("lang") || "en").toLowerCase();
|
||||
var n;
|
||||
if (sec < 60) {
|
||||
n = sec;
|
||||
return lang === "fr" ? ("il y a " + n + "s") : (n + "s ago");
|
||||
}
|
||||
if (sec < 3600) {
|
||||
n = Math.floor(sec / 60);
|
||||
return lang === "fr" ? ("il y a " + n + " min") : (n + "m ago");
|
||||
}
|
||||
if (sec < 86400) {
|
||||
n = Math.floor(sec / 3600);
|
||||
return lang === "fr" ? ("il y a " + n + " h") : (n + "h ago");
|
||||
}
|
||||
n = Math.floor(sec / 86400);
|
||||
return lang === "fr" ? ("il y a " + n + " j") : (n + "d ago");
|
||||
}
|
||||
function tick() {
|
||||
var el = document.querySelector("[data-generated-iso]");
|
||||
|
|
@ -546,7 +696,9 @@ STICKY_JS = """
|
|||
if (isNaN(t)) return;
|
||||
var sec = Math.floor((Date.now() - t) / 1000);
|
||||
age.textContent = fmtAge(sec);
|
||||
age.title = "page age · updates every second";
|
||||
age.title = (document.documentElement.getAttribute("lang") || "en").toLowerCase() === "fr"
|
||||
? "âge de la page · mise à jour chaque seconde"
|
||||
: "page age · updates every second";
|
||||
}
|
||||
tick();
|
||||
setInterval(tick, 1000);
|
||||
|
|
@ -679,8 +831,15 @@ def build_html(
|
|||
|
||||
first_err_href = "#first-error" if first_err_i is not None else None
|
||||
first_warn_href = "#first-warn" if first_warn_i is not None else None
|
||||
scope = monitoring_scope(page_label, hostname, log_text)
|
||||
lang = ui_lang()
|
||||
if re.search(r"lefrancpaysan|francpaysan", hostname + "\n" + log_text, re.I):
|
||||
import os
|
||||
if not (os.environ.get("TALER_MON_LANG") or "").strip():
|
||||
lang = "fr"
|
||||
scope = monitoring_scope(page_label, hostname, log_text, lang=lang)
|
||||
|
||||
page_lang = lang
|
||||
footer_txt = ui(lang, "footer")
|
||||
bar = sticky_bar_html(
|
||||
generated_at=generated_at,
|
||||
generated_iso=generated_iso,
|
||||
|
|
@ -698,7 +857,7 @@ def build_html(
|
|||
)
|
||||
|
||||
return f"""<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="{html.escape(lang if "lang" in dir() else "en")}">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
|
|
@ -775,9 +934,7 @@ footer {{
|
|||
{"".join(body_lines)}
|
||||
</div>
|
||||
<footer>
|
||||
Console-style render of taler-monitoring output.
|
||||
Sticky bar: green = clean · yellow = warnings · red = errors.
|
||||
Commit pins the exact tree used for this run.
|
||||
{html.escape(footer_txt)}
|
||||
</footer>
|
||||
</main>
|
||||
{STICKY_JS}
|
||||
|
|
@ -830,7 +987,7 @@ def build_redirect_html(
|
|||
scope=scope,
|
||||
)
|
||||
return f"""<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="{html.escape(lang if "lang" in dir() else "en")}">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="refresh" content="2; url={html.escape(link)}"/>
|
||||
|
|
@ -882,6 +1039,11 @@ def main() -> None:
|
|||
default="/monitoring_err/",
|
||||
help="URL path for error page (redirect target)",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--lang",
|
||||
default="",
|
||||
help="UI language en|fr (default: env TALER_MON_LANG or auto)",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--page-label",
|
||||
default="monitoring",
|
||||
|
|
@ -889,6 +1051,9 @@ def main() -> None:
|
|||
)
|
||||
args = ap.parse_args()
|
||||
|
||||
if getattr(args, "lang", ""):
|
||||
import os
|
||||
os.environ["TALER_MON_LANG"] = args.lang
|
||||
log_text = args.log.read_text(errors="replace") if args.log.is_file() else ""
|
||||
now = datetime.now(timezone.utc)
|
||||
generated_iso = now.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
|
|
|||
51
site-gen/settings.conf
Normal file
51
site-gen/settings.conf
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# monitoring site-gen — non-secret settings (safe as example)
|
||||
# Copy: cp settings.conf.example settings.conf
|
||||
# Never put passwords/tokens here.
|
||||
|
||||
# Runner: public DNS path (firecuda-external)
|
||||
RUNNER_SSH=
|
||||
RUNNER_SSH_FALLBACKS=
|
||||
RUNNER_REMOTE_WORKDIR=/tmp/taler-monitoring-site-gen
|
||||
MONITORING_ROOT=..
|
||||
|
||||
# Deploy: host Caddy on koopa (root service — not in container)
|
||||
DEPLOY_SSH=koopa-external
|
||||
DEPLOY_SSH_FALLBACKS=koopa
|
||||
# Static files for Caddy file_server (created per hostname)
|
||||
DEPLOY_WWW_ROOT=/var/www/monitoring-sites
|
||||
DEPLOY_SUDO=sudo
|
||||
CADDY_CONFIG=/etc/caddy/Caddyfile
|
||||
CADDY_MIRROR_REL=configs/caddy/Caddyfile
|
||||
# Working tree on deploy host for apply (optional)
|
||||
KOOPA_CADDY_DIR=/home/hernani/koopa-caddy
|
||||
|
||||
# Source link for HTML footer (Forgejo)
|
||||
SOURCE_REPO_WEB=https://git.hacktivism.ch/hernani/koopa-admin-log
|
||||
SOURCE_COMMIT_URL_TMPL={repo}/src/commit/{commit}
|
||||
SOURCE_SUITE_PATH=scripts/taler-monitoring
|
||||
|
||||
CONTINUE_ON_ERROR=1
|
||||
PHASES_ERR=urls versions
|
||||
PHASES_OK=urls versions
|
||||
SKIP_E2E=1
|
||||
|
||||
# Local work dir for logs + HTML
|
||||
WORK_ROOT=/tmp/taler-monitoring-sites-work
|
||||
|
||||
# Sites: hostname|domain_profile (9 fronts)
|
||||
# Start with hacktivism; stage + prod LFP follow
|
||||
SITES="
|
||||
bank.hacktivism.ch|hacktivism.ch
|
||||
exchange.hacktivism.ch|hacktivism.ch
|
||||
taler.hacktivism.ch|hacktivism.ch
|
||||
stage.bank.lefrancpaysan.ch|stage.lefrancpaysan.ch
|
||||
stage.exchange.lefrancpaysan.ch|stage.lefrancpaysan.ch
|
||||
stage.monnaie.lefrancpaysan.ch|stage.lefrancpaysan.ch
|
||||
bank.lefrancpaysan.ch|lefrancpaysan.ch
|
||||
exchange.lefrancpaysan.ch|lefrancpaysan.ch
|
||||
monnaie.lefrancpaysan.ch|lefrancpaysan.ch
|
||||
"
|
||||
|
||||
# Only process this subset (space-separated hostnames). Empty = all SITES.
|
||||
# Example for first deploy: ONLY_HOSTS=bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch
|
||||
ONLY_HOSTS=
|
||||
|
|
@ -95,6 +95,7 @@ Env (same meaning):
|
|||
SURFACE_CVE_LEVEL=warn|error bare Server-header versions default warn
|
||||
(Debian package versions default error)
|
||||
SURFACE_CATALOG=path override surface-catalog.conf
|
||||
TALER_MON_LANG=en|fr console+HTML language (default en; auto fr for *lefrancpaysan*)
|
||||
|
||||
Full load (GOA / hacktivism):
|
||||
./taler-monitoring.sh -d hacktivism.ch full
|
||||
|
|
@ -116,6 +117,8 @@ EOF
|
|||
|
||||
# shellcheck source=lib.sh
|
||||
source "$ROOT/lib.sh"
|
||||
# ensure i18n after domain may change later
|
||||
i18n_init 2>/dev/null || true
|
||||
# Optional gitignored secrets.env next to this suite (or MONITORING_SECRETS_ENV=)
|
||||
load_monitoring_secrets_env 2>/dev/null || true
|
||||
|
||||
|
|
@ -235,6 +238,7 @@ export LADDER_MAX_AMOUNT LADDER_INCLUDE_ZERO LADDER_INCLUDE_MAX
|
|||
export LADDER_HIGH_FROM LADDER_HIGH_RUNGS LADDER_LOAD
|
||||
export LADDER_PAY LADDER_WITHDRAW_SCALE LADDER_PAY_SETTLE_ROUNDS
|
||||
export TALER_DOMAIN_APPLIED=1
|
||||
i18n_init 2>/dev/null || true
|
||||
# Optional: auth401 and other phases may honor CONTINUE_ON_ERROR
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-}"
|
||||
export AUTH401_CONTINUE="${AUTH401_CONTINUE:-${CONTINUE_ON_ERROR:-}}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue