taler-monitoring v1.13.12
Multi-phase global SUMMARY, warn-filter dimmed context, SUMMARY chrome as meta; FP stage host-agent via francpaysan-stage-user (stagepaysan); monpages GOA + FP stage.
This commit is contained in:
commit
5a5431bfa9
88 changed files with 21996 additions and 0 deletions
193
host-agent/README.md
Normal file
193
host-agent/README.md
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
# host-agent — reporting generation (GOA + FP + any stack)
|
||||
|
||||
**Global pipeline** lives in **`run-host-report.sh`** (all stacks share it):
|
||||
|
||||
| Behaviour | Default |
|
||||
|-----------|---------|
|
||||
| Suite refresh | **`update-suite.sh` every run** → `git fetch --tags` + hard reset to `origin/main` |
|
||||
| Update strict | `SUITE_UPDATE_STRICT=1` (default): **abort** if fetch/reset fails — no silent old tree |
|
||||
| Wall clock | `RUN_TIMEOUT=600` |
|
||||
| Log | line-buffered `run-*.log` (continuous write) |
|
||||
| HTML | always (first run / empty tree too) + commit URL; **bootstrap install stubs are monpages ERROR** |
|
||||
| Timeout notice | end of log + top jump on `/monitoring_err/` |
|
||||
|
||||
**Rule:** public mon pages must show a **current suite tag/commit**, not install bootstrap or months-old trees. Timers exist so this keeps working without manual SSH.
|
||||
|
||||
Thin wrappers only set stack defaults:
|
||||
|
||||
| Wrapper | Stack | Typical user |
|
||||
|---------|-------|----------------|
|
||||
| `run-hacktivism-monitoring.sh` | GOA `hacktivism.ch` | `hernani` @ koopa |
|
||||
| `run-fp-stage-monitoring.sh` | FP stage | `stagepaysan` |
|
||||
| `run-host-report.sh` + `taler-monitoring-mytops-stage.{service,timer}` | mytops **stage / betel** only | `taler-monitoring` @ betel (4h) |
|
||||
| `run-aptdeploy.sh` | CLI: ensure + **aptdeploy** (no HTML) | local if hostname=koopa, else **ssh $DEPLOY_SSH** |
|
||||
| `run-aptdeploy-monitoring.sh` | apt-src tests → `/taler-monitoring-aptdeploy*` | `hernani` @ koopa (4h) |
|
||||
| `run-surface-monitoring.sh` | **surface** → only `/taler-monitoring-surface*` (ecosystem + mail + mattermost + versions) | `hernani` @ koopa (hourly) |
|
||||
|
||||
Deprecated mail/mattermost wrappers: **`../meta/deprecated/`** (not installed).
|
||||
|
||||
### apt-src deploy tests (hacktivism `/monitoring`)
|
||||
|
||||
| Container | Mode |
|
||||
|-----------|------|
|
||||
| `koopa-taler-deploy-test-apt-src-trixie` | **fresh**: recreate when repo package fingerprint changes |
|
||||
| `koopa-taler-deploy-test-apt-src-trixie-testing` | **fresh** for `trixie-testing` |
|
||||
| `koopa-taler-deploy-test-apt-src-trixie-upgrade` | **upgrade**: initial install, then mytops-style `apt install` + `upgrade` |
|
||||
| `koopa-taler-deploy-test-apt-src-trixie-testing-upgrade` | **upgrade** for testing suite |
|
||||
|
||||
```bash
|
||||
# from ops workstation → triggers on koopa-external
|
||||
./host-agent/run-aptdeploy.sh
|
||||
./host-agent/run-aptdeploy.sh upgrade
|
||||
./host-agent/run-aptdeploy.sh fresh
|
||||
./host-agent/run-aptdeploy.sh check-only
|
||||
|
||||
# on koopa
|
||||
./taler-monitoring.sh -d hacktivism.ch aptdeploy
|
||||
```
|
||||
|
||||
Checks: package table, `httpd --version`, libtalerutil/`ldd` on failure, `systemctl` for
|
||||
`taler-merchant.target`, basic local `/config` probe. No nginx/HTTPS in containers.
|
||||
|
||||
### Public HTML layout (v1.8.0 simplified)
|
||||
|
||||
| URL | Role |
|
||||
|-----|------|
|
||||
| `https://{bank,exchange,merchant}/monitoring/` (+ `_err`) | **Landing-stack** report — GOA 3 + FP **stage** 3 (+ mytops stage as configured) |
|
||||
| `https://taler.hacktivism.ch/taler-monitoring-surface/` (+ `_err`) | **Only** ecosystem page: software/versions in the Taler universe (nmap OS, mail firefly+anastasis, mattermost, …) |
|
||||
|
||||
No separate public pages for mail/mattermost. Staging under `~/monitoring-sites-staging/`.
|
||||
|
||||
```bash
|
||||
systemctl --user enable --now taler-monitoring-surface.timer
|
||||
systemctl --user start taler-monitoring-surface.service
|
||||
```
|
||||
|
||||
Env examples: **`env/*.env.example`**. FP stage: `run-fp-stage-monitoring.sh` (same `run-host-report.sh` pipeline).
|
||||
|
||||
## GOA (koopa) — host-podman
|
||||
|
||||
Runs **as user `hernani`** (systemd user, linger). **Primary** mode:
|
||||
|
||||
- **`INSIDE_PODMAN=1`** / **`INSIDE_MODE=local-podman`**: access mode **`host-podman`** —
|
||||
`podman exec` on this host into
|
||||
`taler-hacktivism-bank` / `taler-hacktivism-exchange-ansible` / `taler-hacktivism`
|
||||
(IDs `inside.host-*`, not `inside.ssh-*`).
|
||||
From an **ops workstation**, leave `INSIDE_PODMAN` off → access mode **`ssh`** via `KOOPA_SSH`
|
||||
(`inside.ssh-*`).
|
||||
- Public **`urls` + `versions`** for the stack (`-d hacktivism.ch`).
|
||||
- Writes console HTML for all three sites under
|
||||
`~/monitoring-sites-staging/{bank,exchange,taler}.hacktivism.ch/`.
|
||||
|
||||
Caddy (host root) can serve that tree at `/monitoring` — you configure Caddy.
|
||||
|
||||
## Latest software + config isolation
|
||||
|
||||
**Source of truth is always Forgejo** (`git.hacktivism.ch`), not a laptop rsync copy.
|
||||
|
||||
Every host-agent / aptdeploy run:
|
||||
|
||||
1. **`update-suite.sh`**: `git fetch` + **`SUITE_UPDATE_MODE=reset`** (default) → `origin/main`
|
||||
into `SUITE_DIR` (prefer `~/src/taler-monitoring`).
|
||||
2. **Re-exec** host-agent scripts from that tree so the running code matches `COMMIT_URL`.
|
||||
3. Local overrides only in **`~/.config/taler-monitoring/env`** — never overwritten by git.
|
||||
4. HTML footer = exact commit:
|
||||
`https://git.hacktivism.ch/hernani/taler-monitoring/src/commit/<full-sha>`
|
||||
5. **`RUN_TIMEOUT=600`**, line-buffered logs, HTML always written.
|
||||
|
||||
If fetch fails → previous tree + WARN.
|
||||
**To ship features (aptdeploy, surface, …): push to `origin/main`.** Local-only edits vanish on the next reset.
|
||||
|
||||
If pull fails (no network / auth), the previous tree is used and a WARN is logged.
|
||||
|
||||
## Install (on koopa as hernani)
|
||||
|
||||
```bash
|
||||
# once: local config (optional)
|
||||
mkdir -p ~/.config/taler-monitoring
|
||||
cp ~/src/taler-monitoring/host-agent/env.example \
|
||||
~/.config/taler-monitoring/env
|
||||
|
||||
# ops workstation:
|
||||
./host-agent/install-host-agent.sh --remote $DEPLOY_SSH
|
||||
|
||||
# or on koopa:
|
||||
~/src/taler-monitoring/host-agent/install-host-agent.sh
|
||||
```
|
||||
|
||||
Units:
|
||||
|
||||
| Unit | Role |
|
||||
|------|------|
|
||||
| `taler-monitoring-hacktivism.path` | fires on software stamp (`touch-software-stamp.sh`) |
|
||||
| `taler-monitoring-hacktivism.timer` | every **4h** fallback |
|
||||
| `taler-monitoring-hacktivism.service` | oneshot → `/monitoring*` (urls inside versions) |
|
||||
| `taler-monitoring-surface.timer` | every **1h** |
|
||||
| `taler-monitoring-surface.service` | → `/taler-monitoring-surface*` (taler only) |
|
||||
| `taler-monitoring-aptdeploy.timer` | every **4h** |
|
||||
| `taler-monitoring-aptdeploy.service` | → `/taler-monitoring-aptdeploy*` (taler only) |
|
||||
|
||||
## After package / image / landing upgrades
|
||||
|
||||
```bash
|
||||
~/src/taler-monitoring/host-agent/touch-software-stamp.sh
|
||||
# → path unit starts the service
|
||||
```
|
||||
|
||||
## Manual
|
||||
|
||||
```bash
|
||||
systemctl --user start taler-monitoring-hacktivism.service
|
||||
systemctl --user status taler-monitoring-hacktivism.service --no-pager
|
||||
journalctl --user -u taler-monitoring-hacktivism.service -n 50 --no-pager
|
||||
ls ~/monitoring-sites-staging/bank.hacktivism.ch/monitoring_err/
|
||||
```
|
||||
|
||||
## Relation to optional outside-only timer
|
||||
|
||||
| | host-agent (koopa) | outside-runner site-gen |
|
||||
|--|--------------------|-------------------|
|
||||
| Access | **podman on host** | public HTTPS only |
|
||||
| Phases | urls **inside** versions | urls versions |
|
||||
| Trigger | software path + 4h | *could* launchd 4h |
|
||||
| Primary for GOA | **yes** | **off** (optional only) |
|
||||
|
||||
**outside-runner is not scheduled** right now (launchd disabled). Scripts under
|
||||
`site-gen/` can still one-shot a public run if needed; see `site-gen/README.md`.
|
||||
|
||||
No secrets required for default phases. `secrets.env` optional for e2e later.
|
||||
|
||||
## Git commit on HTML pages
|
||||
|
||||
Header of each generated page includes a link like:
|
||||
|
||||
`https://git.hacktivism.ch/hernani/taler-monitoring/src/commit/<full-sha>`
|
||||
|
||||
That SHA is the tree **after** `update-suite.sh` for that run.
|
||||
|
||||
## Packages on koopa
|
||||
|
||||
See **[../DEPENDENCIES.md](../DEPENDENCIES.md)**.
|
||||
|
||||
**Default host-agent needs no new packages** if curl/python3/podman/git are present (they are).
|
||||
|
||||
**Root once** only for full QR checks in `urls`:
|
||||
|
||||
```bash
|
||||
zypper in qrencode zbar
|
||||
```
|
||||
|
||||
Without them, monitoring still runs; QR group WARNs and skips encode/decode.
|
||||
|
||||
Caddy `/var/www/monitoring-sites` is separate (you configured hernani write access).
|
||||
|
||||
|
||||
## Exit codes (v1.7.1+)
|
||||
|
||||
Host-agent jobs default to **`STRICT_EXIT=1`**: non-zero exit if suite checks fail, `DEPLOY_WWW_ROOT` is not writable, or public monpages (FQDN) fail.
|
||||
|
||||
Set `STRICT_EXIT=0` only if you want timers to stay green while still logging errors (not recommended for production).
|
||||
|
||||
## Monitoring pages (suite)
|
||||
|
||||
Public sticky-bar HTML under `/monitoring*` and `/taler-monitoring-*` is part of **taler-monitoring** (not a separate product). See main [README — Monitoring pages](../README.md#monitoring-pages-part-of-the-suite). Phase **monpages** is obligatory (**ERROR** if missing): GOA checks the full suite inventory; FP only FP mon hosts.
|
||||
74
host-agent/ROOT-APPLY-MONITORING.md
Normal file
74
host-agent/ROOT-APPLY-MONITORING.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Root: make monitoring pages live on koopa (GOA)
|
||||
|
||||
## Detection (v1.3.1+)
|
||||
|
||||
Suite phase **`monpages`** and the host-agent **post-check** curl each public
|
||||
FQDN (`https://taler.hacktivism.ch/monitoring/` …). Merchant JSON **code 21**
|
||||
or non-HTML is an **ERROR** until this apply is done.
|
||||
|
||||
## Symptom if not applied
|
||||
|
||||
Public URLs return **merchant/bank JSON** like:
|
||||
|
||||
```json
|
||||
{ "code": 21, "hint": "There is no endpoint defined for the URL provided..." }
|
||||
```
|
||||
|
||||
or a **404 HTML** page from the app reverse_proxy.
|
||||
|
||||
Cause: live `/etc/caddy/Caddyfile` has **no** `handle /monitoring*` (falls through to
|
||||
API). Prepared config is only under **`$KOOPA_CADDY_DIR/Caddyfile`**.
|
||||
|
||||
## One-shot as root (recommended)
|
||||
|
||||
```bash
|
||||
# absolute path required: as root, ~ is /root (not /home/hernani)
|
||||
sudo $APPLY_MONITORING_LIVE
|
||||
# or already root:
|
||||
# $APPLY_MONITORING_LIVE
|
||||
```
|
||||
|
||||
**Caddy bare-path redir (v1.9.2+):** inside a `handle` block use
|
||||
`redir * /path/ 302` — never `redir /path/ 302` alone (Caddy treats the first
|
||||
token as matcher and sets `Location: 302`, so bare URLs fall through to the
|
||||
merchant API as JSON **code 21**).
|
||||
|
||||
That script:
|
||||
|
||||
1. `rsync` staging HTML → `/var/www/monitoring-sites/` (incl. surface + aptdeploy)
|
||||
2. Makes tree writable for `hernani` (group `caddy` + ACL) so later runs self-sync
|
||||
3. Installs prepared Caddyfile → `/etc/caddy/Caddyfile`, validates, reloads Caddy
|
||||
4. Smoke-curls all monitoring URLs (must **not** be JSON `code:21`)
|
||||
|
||||
## Paths (only three families — suite name ≠ URL)
|
||||
|
||||
There is **no** public page `/taler-monitoring`. Each family needs **bare and slash**
|
||||
(`redir * /path/ 302` inside Caddy `handle`):
|
||||
|
||||
| Family | Paths | Host | Source timer |
|
||||
|--------|-------|------|----------------|
|
||||
| **monitoring** | `/monitoring` · `/monitoring/` · `/monitoring_err` · `/monitoring_err/` | bank + exchange + taler (and other landings) | `taler-monitoring-hacktivism.timer` (4h) |
|
||||
| **taler-monitoring-surface** | bare + slash + `_err` | **taler.hacktivism.ch only** | `taler-monitoring-surface.timer` (1h) |
|
||||
| **taler-monitoring-aptdeploy** | bare + slash + `_err` | **taler.hacktivism.ch only** | `taler-monitoring-aptdeploy.timer` (4h) |
|
||||
|
||||
HTML is generated as **hernani** into
|
||||
`$DEPLOY_STAGING (or $HOME/monitoring-sites-staging)/`.
|
||||
|
||||
## Manual equivalent
|
||||
|
||||
```bash
|
||||
rsync -a --delete $DEPLOY_STAGING (or $HOME/monitoring-sites-staging)/ /var/www/monitoring-sites/
|
||||
chown -R hernani:caddy /var/www/monitoring-sites && chmod -R g+rwX /var/www/monitoring-sites
|
||||
sudo $KOOPA_CADDY_DIR/apply.sh # or apply-monitoring-live.sh
|
||||
```
|
||||
|
||||
Expect **200** (HTML with sticky bar). Not merchant JSON `code:21`.
|
||||
|
||||
## After each monitoring run (if www is not hernani-writable)
|
||||
|
||||
```bash
|
||||
rsync -a --delete $DEPLOY_STAGING (or $HOME/monitoring-sites-staging)/ /var/www/monitoring-sites/
|
||||
chown -R caddy:caddy /var/www/monitoring-sites
|
||||
```
|
||||
|
||||
Or grant `hernani` write on `/var/www/monitoring-sites` once so the host-agent can rsync itself.
|
||||
91
host-agent/apply-monitoring-live.sh
Executable file
91
host-agent/apply-monitoring-live.sh
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/env bash
|
||||
# ONE-SHOT as root: publish monitoring HTML + enable Caddy handles
|
||||
#
|
||||
# Suite copy (taler-monitoring host-agent). Live install path on koopa:
|
||||
# ${KOOPA_CADDY_DIR}/apply-monitoring-live.sh
|
||||
# Prefer absolute path ( ~ expands to /root when already root ):
|
||||
# sudo ${KOOPA_CADDY_DIR}/apply-monitoring-live.sh
|
||||
# ${KOOPA_CADDY_DIR}/apply-monitoring-live.sh # if already root
|
||||
#
|
||||
# After editing here: rsync to koopa ~/koopa-caddy/ before root apply.
|
||||
set -euo pipefail
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
exec sudo -E "$0" "$@"
|
||||
fi
|
||||
|
||||
STAGING="${DEPLOY_STAGING:-${HTML_OUT:-$HOME/monitoring-sites-staging}}"
|
||||
WWW="${DEPLOY_WWW_ROOT:?set DEPLOY_WWW_ROOT in env}"
|
||||
SRC="${KOOPA_CADDY_DIR:?set KOOPA_CADDY_DIR in env}/Caddyfile"
|
||||
DST=/etc/caddy/Caddyfile
|
||||
|
||||
if [[ ! -f "$SRC" ]]; then
|
||||
echo "ERROR: missing Caddyfile source: $SRC" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$STAGING" ]]; then
|
||||
echo "ERROR: missing staging HTML: $STAGING" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "== 1) HTML staging → www =="
|
||||
mkdir -p "$WWW"
|
||||
rsync -a --delete "$STAGING/" "$WWW/"
|
||||
# allow hernani to update future runs without root
|
||||
chown -R hernani:caddy "$WWW"
|
||||
chmod -R g+rwX "$WWW"
|
||||
find "$WWW" -type d -exec chmod g+s {} \;
|
||||
# ACL default if available
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
setfacl -R -m u:hernani:rwx,g:caddy:rwx "$WWW" || true
|
||||
setfacl -R -d -m u:hernani:rwx,g:caddy:rwx "$WWW" || true
|
||||
fi
|
||||
ls -la "$WWW" "$WWW/taler.hacktivism.ch" || true
|
||||
|
||||
echo "== 2) Caddyfile (backup + install) =="
|
||||
ts=$(date +%Y%m%d-%H%M%S)
|
||||
cp -a "$DST" "/etc/caddy/Caddyfile.bak-monitoring-${ts}"
|
||||
cp -a "$SRC" "$DST"
|
||||
chown root:caddy "$DST" 2>/dev/null || chown root:root "$DST"
|
||||
chmod 644 "$DST"
|
||||
caddy validate --config "$DST"
|
||||
systemctl reload caddy
|
||||
systemctl is-active caddy
|
||||
|
||||
echo "== 3) smoke =="
|
||||
# bash: every continued line except the last must end with \
|
||||
urls=(
|
||||
https://taler.hacktivism.ch/monitoring/
|
||||
https://bank.hacktivism.ch/monitoring/
|
||||
https://exchange.hacktivism.ch/monitoring/
|
||||
https://taler.hacktivism.ch/taler-monitoring-surface
|
||||
https://taler.hacktivism.ch/taler-monitoring-surface/
|
||||
https://taler.hacktivism.ch/taler-monitoring-surface_err/
|
||||
https://taler.hacktivism.ch/taler-monitoring-aptdeploy/
|
||||
https://taler.hacktivism.ch/taler-monitoring-aptdeploy_err/
|
||||
)
|
||||
smoke_fail=0
|
||||
for url in "${urls[@]}"; do
|
||||
code=$(curl -sS -o /tmp/monchk -w '%{http_code}' -L --max-redirs 3 -m 12 "$url" || echo ERR)
|
||||
ct=$(file -b /tmp/monchk 2>/dev/null | head -c 40)
|
||||
echo " $code $url ($ct)"
|
||||
if grep -qE '"code":[[:space:]]*21' /tmp/monchk 2>/dev/null; then
|
||||
echo " STILL merchant JSON code 21 — Caddy handles not active?"
|
||||
smoke_fail=1
|
||||
fi
|
||||
done
|
||||
# bare path must redirect (or land on HTML), not merchant JSON
|
||||
bare_code=$(curl -sS -o /tmp/monbare -w '%{http_code}' --max-redirs 0 -m 12 \
|
||||
https://taler.hacktivism.ch/taler-monitoring-surface || echo ERR)
|
||||
if grep -qE '"code":[[:space:]]*21' /tmp/monbare 2>/dev/null; then
|
||||
echo "ERROR: bare /taler-monitoring-surface still merchant code 21 (HTTP $bare_code)" >&2
|
||||
smoke_fail=1
|
||||
elif [[ "$bare_code" != "302" && "$bare_code" != "301" && "$bare_code" != "200" ]]; then
|
||||
echo "WARN: bare /taler-monitoring-surface HTTP $bare_code (want 302/301/200 HTML)" >&2
|
||||
fi
|
||||
echo " bare_no_follow=$bare_code https://taler.hacktivism.ch/taler-monitoring-surface"
|
||||
|
||||
if [[ "$smoke_fail" -ne 0 ]]; then
|
||||
echo "ERROR: smoke failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "OK apply-monitoring-live done"
|
||||
368
host-agent/ensure-apt-deploy-test-containers.sh
Executable file
368
host-agent/ensure-apt-deploy-test-containers.sh
Executable file
|
|
@ -0,0 +1,368 @@
|
|||
#!/usr/bin/env bash
|
||||
# ensure-apt-deploy-test-containers.sh
|
||||
#
|
||||
# Four rootless podman containers on koopa (no nginx / no HTTPS):
|
||||
#
|
||||
# Fresh rebuild when repo fingerprint changes:
|
||||
# koopa-taler-deploy-test-apt-src-trixie
|
||||
# koopa-taler-deploy-test-apt-src-trixie-testing
|
||||
#
|
||||
# Persistent upgrade path (mytops upgrade.sh style):
|
||||
# koopa-taler-deploy-test-apt-src-trixie-upgrade
|
||||
# koopa-taler-deploy-test-apt-src-trixie-testing-upgrade
|
||||
#
|
||||
# Run as hernani on koopa. From elsewhere use run-aptdeploy.sh (ssh $DEPLOY_SSH or $APT_DEPLOY_SSH).
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
PODMAN_BIN="${APT_DEPLOY_PODMAN:-podman}"
|
||||
IMG="${APT_DEPLOY_BASE_IMAGE:-docker.io/library/debian:trixie}"
|
||||
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/taler-apt-deploy"
|
||||
URI_BASE="${APT_DEPLOY_URI:-https://deb.taler.net/apt/debian}"
|
||||
mkdir -p "$STATE_DIR"
|
||||
|
||||
# Packages we track for "new version → rebuild fresh containers"
|
||||
TRACK_PKGS="${APT_DEPLOY_TRACK_PKGS:-taler-merchant libtalermerchant libtalerexchange libdonau}"
|
||||
|
||||
# Canonical four containers (keep). Everything else matching legacy names is removed.
|
||||
CANONICAL_CONTAINERS=(
|
||||
koopa-taler-deploy-test-apt-src-trixie
|
||||
koopa-taler-deploy-test-apt-src-trixie-testing
|
||||
koopa-taler-deploy-test-apt-src-trixie-upgrade
|
||||
koopa-taler-deploy-test-apt-src-trixie-testing-upgrade
|
||||
)
|
||||
|
||||
# Legacy / typo names from earlier iterations — always delete if present
|
||||
LEGACY_CONTAINERS=(
|
||||
koopa-taler-build-test-apt-trixie
|
||||
koopa-taler-build-test-apt-trixie-testing
|
||||
koopa-taler-deploy-test-apt-trixie
|
||||
koopa-taler-deploy-test-apt-trixie-testing
|
||||
koopa-taler-buidl-test-apt-trixie
|
||||
koopa-taler-buidl-test-apt-trixie-testing
|
||||
)
|
||||
|
||||
cleanup_legacy() {
|
||||
local n img
|
||||
echo "======== cleanup legacy containers / images ========"
|
||||
for n in "${LEGACY_CONTAINERS[@]}"; do
|
||||
if "$PODMAN_BIN" container exists "$n" 2>/dev/null; then
|
||||
echo "remove legacy container $n"
|
||||
"$PODMAN_BIN" rm -f "$n" 2>/dev/null || true
|
||||
fi
|
||||
# old setup images for that name
|
||||
if "$PODMAN_BIN" image exists "localhost/${n}:setup" 2>/dev/null; then
|
||||
echo "remove legacy image localhost/${n}:setup"
|
||||
"$PODMAN_BIN" rmi -f "localhost/${n}:setup" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
# dangling setup images not in canonical set
|
||||
while read -r img; do
|
||||
[ -n "$img" ] || continue
|
||||
local base keep=0
|
||||
base=${img#localhost/}
|
||||
base=${base%:setup}
|
||||
for n in "${CANONICAL_CONTAINERS[@]}"; do
|
||||
[ "$base" = "$n" ] && keep=1 && break
|
||||
done
|
||||
if [ "$keep" -eq 0 ] && [[ "$img" == localhost/koopa-taler-*-test-apt* ]]; then
|
||||
echo "remove non-canonical image $img"
|
||||
"$PODMAN_BIN" rmi -f "$img" 2>/dev/null || true
|
||||
fi
|
||||
done < <("$PODMAN_BIN" images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep -E 'localhost/koopa-taler-.*-test-apt' || true)
|
||||
}
|
||||
|
||||
# Prefer single suite tree: ~/src/taler-monitoring vs ~/taler-monitoring
|
||||
# (legacy koopa-admin-log paths are not used). Keep the newer git clone; symlink the other.
|
||||
dedupe_suite_repos() {
|
||||
local a="$HOME/src/taler-monitoring" b="$HOME/taler-monitoring"
|
||||
local ta tb
|
||||
[ "${APT_DEPLOY_DEDUPE_REPOS:-1}" = "1" ] || return 0
|
||||
if [ -d "$a/.git" ] && [ -d "$b/.git" ] && [ ! -L "$a" ] && [ ! -L "$b" ] \
|
||||
&& [ "$(readlink -f "$a" 2>/dev/null || echo "$a")" != "$(readlink -f "$b" 2>/dev/null || echo "$b")" ]; then
|
||||
ta=$(git -C "$a" log -1 --format=%ct 2>/dev/null || echo 0)
|
||||
tb=$(git -C "$b" log -1 --format=%ct 2>/dev/null || echo 0)
|
||||
echo "======== dedupe suite repos (both are git clones) ========"
|
||||
echo " $a HEAD_ts=$ta"
|
||||
echo " $b HEAD_ts=$tb"
|
||||
if [ "$ta" -ge "$tb" ]; then
|
||||
echo "keep $a · remove $b · symlink $b → $a"
|
||||
rm -rf "$b"
|
||||
ln -sfn "$a" "$b"
|
||||
else
|
||||
echo "keep $b · remove $a · symlink $a → $b"
|
||||
rm -rf "$a"
|
||||
mkdir -p "$(dirname "$a")"
|
||||
ln -sfn "$b" "$a"
|
||||
fi
|
||||
elif [ -d "$a/.git" ] && [ ! -e "$b" ]; then
|
||||
ln -sfn "$a" "$b"
|
||||
elif [ -d "$b/.git" ] && [ ! -e "$a" ]; then
|
||||
mkdir -p "$(dirname "$a")"
|
||||
ln -sfn "$b" "$a"
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup_legacy
|
||||
dedupe_suite_repos
|
||||
# ---------------------------------------------------------------------------
|
||||
# Repo fingerprint: Version: lines from suite Packages index
|
||||
# ---------------------------------------------------------------------------
|
||||
repo_pkg_version() {
|
||||
local suite=$1 pkg=$2
|
||||
curl -fsS --max-time 45 \
|
||||
"${URI_BASE}/dists/${suite}/main/binary-amd64/Packages" 2>/dev/null \
|
||||
| awk -v p="$pkg" '
|
||||
$0 == "Package: " p { want=1; next }
|
||||
/^Package: / { want=0 }
|
||||
want && /^Version: / { print $2; exit }
|
||||
'
|
||||
}
|
||||
|
||||
repo_fingerprint() {
|
||||
local suite=$1 pkg v line=""
|
||||
for pkg in $TRACK_PKGS; do
|
||||
v=$(repo_pkg_version "$suite" "$pkg" || true)
|
||||
[ -n "$v" ] || v="?"
|
||||
line="${line}${pkg}=${v};"
|
||||
done
|
||||
printf '%s' "$line"
|
||||
}
|
||||
|
||||
container_fingerprint() {
|
||||
local name=$1
|
||||
"$PODMAN_BIN" exec "$name" bash -lc '
|
||||
for p in '"$TRACK_PKGS"'; do
|
||||
v=$(dpkg-query -W -f="\${Version}" "$p" 2>/dev/null || echo missing)
|
||||
printf "%s=%s;" "$p" "$v"
|
||||
done
|
||||
' 2>/dev/null || echo "missing"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bootstrap: install base + taler source + packages (shared)
|
||||
# ---------------------------------------------------------------------------
|
||||
install_base_and_merchant() {
|
||||
local name=$1 suite=$2 srcfile=$3
|
||||
"$PODMAN_BIN" exec -u root "$name" bash -lc '
|
||||
set -euo pipefail
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq ca-certificates curl wget gnupg systemd systemd-sysv \
|
||||
dbus procps iproute2
|
||||
'
|
||||
"$PODMAN_BIN" exec -u root "$name" bash -lc "
|
||||
set -euo pipefail
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
mkdir -p /etc/apt/keyrings
|
||||
wget -q -O /etc/apt/keyrings/taler-systems.gpg https://taler.net/taler-systems.gpg
|
||||
cat >/etc/apt/sources.list.d/${srcfile} <<EOF
|
||||
Architectures: amd64
|
||||
Components: main
|
||||
X-Repolib-Name: Taler
|
||||
Signed-By: /etc/apt/keyrings/taler-systems.gpg
|
||||
Suites: ${suite}
|
||||
Types: deb
|
||||
URIs: ${URI_BASE}
|
||||
EOF
|
||||
apt-get update -qq
|
||||
apt-get install -y \
|
||||
taler-merchant \
|
||||
taler-merchant-typst \
|
||||
taler-merchant-webui \
|
||||
taler-terms-generator \
|
||||
postgresql \
|
||||
s-nail \
|
||||
jq
|
||||
"
|
||||
}
|
||||
|
||||
commit_and_systemd() {
|
||||
local name=$1
|
||||
"$PODMAN_BIN" stop "$name"
|
||||
"$PODMAN_BIN" commit "$name" "localhost/${name}:setup"
|
||||
"$PODMAN_BIN" rm "$name"
|
||||
"$PODMAN_BIN" run -d --name "$name" \
|
||||
--hostname "$name" \
|
||||
--systemd=always \
|
||||
--cgroupns=host \
|
||||
"localhost/${name}:setup" \
|
||||
/lib/systemd/systemd
|
||||
sleep 5
|
||||
# enable merchant stack if unit exists
|
||||
"$PODMAN_BIN" exec "$name" bash -lc '
|
||||
set +e
|
||||
systemctl daemon-reload 2>/dev/null
|
||||
systemctl enable taler-merchant.target 2>/dev/null
|
||||
systemctl start taler-merchant.target 2>/dev/null
|
||||
sleep 2
|
||||
systemctl is-active taler-merchant-httpd.service 2>/dev/null || true
|
||||
' || true
|
||||
}
|
||||
|
||||
create_from_scratch() {
|
||||
local name=$1 suite=$2 srcfile=$3
|
||||
echo "======== CREATE (fresh) $name Suites: $suite ========"
|
||||
"$PODMAN_BIN" pull "$IMG" >/dev/null
|
||||
"$PODMAN_BIN" rm -f "$name" 2>/dev/null || true
|
||||
# drop previous setup image so we do not accumulate duplicates
|
||||
"$PODMAN_BIN" rmi -f "localhost/${name}:setup" 2>/dev/null || true
|
||||
"$PODMAN_BIN" run -d --name "$name" --hostname "$name" "$IMG" sleep infinity
|
||||
install_base_and_merchant "$name" "$suite" "$srcfile"
|
||||
commit_and_systemd "$name"
|
||||
printf '%s\n' "$(repo_fingerprint "$suite")" >"$STATE_DIR/${name}.fp"
|
||||
printf '%s\n' "$(container_fingerprint "$name")" >"$STATE_DIR/${name}.installed"
|
||||
echo "created $name fp=$(cat "$STATE_DIR/${name}.fp")"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Upgrade path (mytops-admin-log upgrade.sh merchant packages, no restic/nginx)
|
||||
# Prints a markdown-ish table of before → after versions.
|
||||
# ---------------------------------------------------------------------------
|
||||
upgrade_inside() {
|
||||
local name=$1
|
||||
local before after pkg v0 v1
|
||||
echo "======== UPGRADE $name (mytops-style apt install + upgrade) ========"
|
||||
|
||||
before=$("$PODMAN_BIN" exec "$name" bash -lc '
|
||||
for p in taler-merchant libtalermerchant libtalerexchange libdonau libgnunet \
|
||||
taler-merchant-webui taler-merchant-typst taler-terms-generator; do
|
||||
v=$(dpkg-query -W -f="\${Version}" "$p" 2>/dev/null || echo "-")
|
||||
printf "%s %s\n" "$p" "$v"
|
||||
done
|
||||
' 2>/dev/null || true)
|
||||
|
||||
# capture upgrade output
|
||||
set +e
|
||||
"$PODMAN_BIN" exec -u root "$name" bash -lc '
|
||||
set -euo pipefail
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
systemctl stop taler-merchant.target 2>/dev/null || true
|
||||
systemctl stop taler-merchant-donaukeyupdate.service 2>/dev/null || true
|
||||
apt-get update -qq
|
||||
apt-get install -y \
|
||||
taler-merchant \
|
||||
taler-merchant-typst \
|
||||
taler-merchant-webui \
|
||||
taler-terms-generator \
|
||||
|| true
|
||||
if dpkg -l challenger-httpd 2>/dev/null | grep -q "^ii"; then
|
||||
apt-get remove -y challenger-httpd || true
|
||||
fi
|
||||
apt-get upgrade -y
|
||||
systemctl daemon-reload 2>/dev/null || true
|
||||
systemctl enable taler-merchant.target 2>/dev/null || true
|
||||
# try dbconfig if present (may no-op without full config)
|
||||
command -v taler-merchant-dbconfig >/dev/null && taler-merchant-dbconfig 2>/dev/null || true
|
||||
systemctl reset-failed "taler-merchant*" 2>/dev/null || true
|
||||
systemctl start taler-merchant.target 2>/dev/null || true
|
||||
sleep 2
|
||||
' 2>&1 | tee "$STATE_DIR/${name}.upgrade.log" | tail -30
|
||||
set -e
|
||||
|
||||
after=$("$PODMAN_BIN" exec "$name" bash -lc '
|
||||
for p in taler-merchant libtalermerchant libtalerexchange libdonau libgnunet \
|
||||
taler-merchant-webui taler-merchant-typst taler-terms-generator; do
|
||||
v=$(dpkg-query -W -f="\${Version}" "$p" 2>/dev/null || echo "-")
|
||||
printf "%s %s\n" "$p" "$v"
|
||||
done
|
||||
' 2>/dev/null || true)
|
||||
|
||||
echo
|
||||
echo "| package | before | after | change |"
|
||||
echo "|---------|--------|-------|--------|"
|
||||
while read -r pkg v0; do
|
||||
[ -n "${pkg:-}" ] || continue
|
||||
v1=$(printf '%s\n' "$after" | awk -v p="$pkg" '$1==p {print $2; exit}')
|
||||
v1=${v1:--}
|
||||
if [ "$v0" = "$v1" ]; then
|
||||
ch="="
|
||||
else
|
||||
ch="UPGRADED"
|
||||
fi
|
||||
echo "| $pkg | $v0 | $v1 | $ch |"
|
||||
done <<<"$before"
|
||||
|
||||
printf '%s\n' "$(container_fingerprint "$name")" >"$STATE_DIR/${name}.installed"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Fresh mode: recreate if missing / not running / repo fp changed
|
||||
# ---------------------------------------------------------------------------
|
||||
ensure_fresh() {
|
||||
local name=$1 suite=$2 srcfile=$3
|
||||
local want have running
|
||||
|
||||
want=$(repo_fingerprint "$suite")
|
||||
echo "repo fingerprint [$suite]: $want"
|
||||
|
||||
if ! "$PODMAN_BIN" container exists "$name" 2>/dev/null; then
|
||||
create_from_scratch "$name" "$suite" "$srcfile"
|
||||
return
|
||||
fi
|
||||
|
||||
running=$("$PODMAN_BIN" inspect -f '{{.State.Running}}' "$name" 2>/dev/null || echo false)
|
||||
have=$(container_fingerprint "$name")
|
||||
echo "installed in $name: $have"
|
||||
|
||||
if [ "$running" != "true" ] \
|
||||
|| ! "$PODMAN_BIN" exec "$name" bash -lc 'command -v taler-merchant-httpd' >/dev/null 2>&1 \
|
||||
|| [ "$want" != "$have" ]; then
|
||||
echo "rebuild $name (running=$running fp_match=$([ "$want" = "$have" ] && echo yes || echo NO))"
|
||||
create_from_scratch "$name" "$suite" "$srcfile"
|
||||
else
|
||||
echo "OK $name up-to-date (fresh container matches repo)"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Upgrade mode: create once, then always upgrade_inside
|
||||
# ---------------------------------------------------------------------------
|
||||
ensure_upgrade() {
|
||||
local name=$1 suite=$2 srcfile=$3
|
||||
local running
|
||||
|
||||
if ! "$PODMAN_BIN" container exists "$name" 2>/dev/null; then
|
||||
create_from_scratch "$name" "$suite" "$srcfile"
|
||||
echo "(initial install for upgrade-track container $name)"
|
||||
return
|
||||
fi
|
||||
|
||||
running=$("$PODMAN_BIN" inspect -f '{{.State.Running}}' "$name" 2>/dev/null || echo false)
|
||||
if [ "$running" != "true" ]; then
|
||||
echo "start $name"
|
||||
"$PODMAN_BIN" start "$name" || {
|
||||
echo "recreate broken $name"
|
||||
create_from_scratch "$name" "$suite" "$srcfile"
|
||||
return
|
||||
}
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
if ! "$PODMAN_BIN" exec "$name" bash -lc 'command -v taler-merchant-httpd' >/dev/null 2>&1; then
|
||||
echo "recreate $name (no httpd after start)"
|
||||
create_from_scratch "$name" "$suite" "$srcfile"
|
||||
return
|
||||
fi
|
||||
|
||||
upgrade_inside "$name"
|
||||
}
|
||||
|
||||
MODE="${1:-all}" # all | fresh | upgrade
|
||||
|
||||
case "$MODE" in
|
||||
all|fresh)
|
||||
ensure_fresh koopa-taler-deploy-test-apt-src-trixie trixie taler.sources
|
||||
ensure_fresh koopa-taler-deploy-test-apt-src-trixie-testing trixie-testing taler-testing.sources
|
||||
;;&
|
||||
all|upgrade)
|
||||
ensure_upgrade koopa-taler-deploy-test-apt-src-trixie-upgrade trixie taler.sources
|
||||
ensure_upgrade koopa-taler-deploy-test-apt-src-trixie-testing-upgrade trixie-testing taler-testing.sources
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 [all|fresh|upgrade]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "done ensure-apt-deploy-test-containers mode=$MODE"
|
||||
26
host-agent/env.example
Normal file
26
host-agent/env.example
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copy to: ~/.config/taler-monitoring/env
|
||||
# This file is NOT inside the git tree and is never overwritten by update-suite.sh.
|
||||
#
|
||||
# Full stack examples (same reporting generation for all):
|
||||
# env/hacktivism.env.example
|
||||
# env/stagepaysan.env.example
|
||||
#
|
||||
# SUITE_GIT_URL=https://git.hacktivism.ch/hernani/taler-monitoring.git
|
||||
# SUITE_GIT_REF=main
|
||||
# SUITE_DIR=$HOME/src/taler-monitoring
|
||||
# SUITE_UPDATE_MODE=reset
|
||||
#
|
||||
# TALER_DOMAIN=hacktivism.ch
|
||||
# INSIDE_PODMAN=1
|
||||
# INSIDE_MODE=local-podman
|
||||
# CONTINUE_ON_ERROR=1
|
||||
# PHASES for the *default* hacktivism timer only (urls inside versions).
|
||||
# Dedicated wrappers always override PHASES + HTML paths:
|
||||
# run-surface-monitoring.sh → /taler-monitoring-surface*
|
||||
# run-aptdeploy-monitoring.sh → /taler-monitoring-aptdeploy*
|
||||
# PHASES="urls inside versions"
|
||||
# RUN_TIMEOUT=600
|
||||
# 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*)
|
||||
26
host-agent/env/hacktivism.env.example
vendored
Normal file
26
host-agent/env/hacktivism.env.example
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copy to: ~/.config/taler-monitoring/env (user hernani on koopa)
|
||||
# Shared reporting generation: RUN_TIMEOUT, line-buffered log, always HTML.
|
||||
|
||||
TALER_DOMAIN=hacktivism.ch
|
||||
INSIDE_PODMAN=1
|
||||
INSIDE_MODE=local-podman
|
||||
LOCAL_STACK=1
|
||||
CONTINUE_ON_ERROR=1
|
||||
PHASES="urls inside versions"
|
||||
# aptdeploy HTML: run-aptdeploy-monitoring.sh → /taler-monitoring-aptdeploy*
|
||||
RUN_TIMEOUT=600
|
||||
# APT_DEPLOY_ENSURE=1
|
||||
# APT_DEPLOY_SKIP=0
|
||||
|
||||
HTML_OUT=$HOME/monitoring-sites-staging
|
||||
MON_HOSTS="bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch"
|
||||
|
||||
SUITE_DIR=$HOME/src/taler-monitoring
|
||||
SUITE_GIT_URL=https://git.hacktivism.ch/hernani/taler-monitoring.git
|
||||
SUITE_GIT_REF=main
|
||||
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
|
||||
35
host-agent/env/mytops-stage.env.example
vendored
Normal file
35
host-agent/env/mytops-stage.env.example
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Copy to: ~/.config/taler-monitoring/env (user taler-monitoring @ betel)
|
||||
# mytops CHF stage — NOT lifeline / production
|
||||
#
|
||||
SUITE_GIT_URL=https://git.hacktivism.ch/hernani/taler-monitoring.git
|
||||
SUITE_GIT_REF=main
|
||||
SUITE_DIR=$HOME/src/taler-monitoring
|
||||
TALER_DOMAIN=stage.taler-ops.ch
|
||||
MON_HOSTS="stage.my.taler-ops.ch stage.taler-ops.ch"
|
||||
HTML_OUT=$HOME/monitoring-sites-staging
|
||||
DEPLOY_WWW_ROOT=/var/www/monitoring-sites
|
||||
HTML_URL_OK=/monitoring/
|
||||
HTML_URL_ERR=/monitoring_err/
|
||||
HTML_OK_DIR=monitoring
|
||||
HTML_ERR_DIR=monitoring_err
|
||||
# urls + monpages + fake-franken CHF (rusty.taler-ops.ch)
|
||||
PHASES="urls monpages devtesting"
|
||||
SKIP_SSH=1
|
||||
LOCAL_STACK=0
|
||||
INSIDE_PODMAN=0
|
||||
CONTINUE_ON_ERROR=1
|
||||
RUN_TIMEOUT=600
|
||||
STRICT_EXIT=1
|
||||
MONPAGES_REQUIRE_PUBLIC=1
|
||||
MONPAGES_INVENTORY=job
|
||||
TALER_MON_LANG=en
|
||||
AGENT_LABEL=mytops-stage-host-agent
|
||||
STATE_NAME=taler-monitoring-mytops-stage
|
||||
SUITE_UPDATE_STRICT=1
|
||||
CHECK_BANK=0
|
||||
MERCHANT_REQUIRED=1
|
||||
CHECK_LANDING=0
|
||||
# rusty devtesting (SSH Host taler-rusty-devtesting → devtesting@rusty.taler-ops.ch)
|
||||
DEVTESTING_SSH=taler-rusty-devtesting
|
||||
DEVTESTING_AMOUNT=CHF:1.00
|
||||
# DEVTESTING_SKIP=1
|
||||
30
host-agent/env/stagepaysan.env.example
vendored
Normal file
30
host-agent/env/stagepaysan.env.example
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Copy to: ~/.config/taler-monitoring/env (user stagepaysan)
|
||||
# Never inside the git tree — update-suite never overwrites this file.
|
||||
#
|
||||
# Shared reporting generation (run-host-report.sh / run-fp-stage-monitoring.sh):
|
||||
# RUN_TIMEOUT, line-buffered log, always HTML, commit link on git.hacktivism.ch
|
||||
|
||||
TALER_DOMAIN=stage.lefrancpaysan.ch
|
||||
INSIDE_PODMAN=1
|
||||
INSIDE_MODE=local-podman
|
||||
INSIDE_PROFILE=stage-lfp
|
||||
LOCAL_STACK=0
|
||||
CONTINUE_ON_ERROR=1
|
||||
PHASES="urls inside versions"
|
||||
RUN_TIMEOUT=600
|
||||
|
||||
HTML_OUT=$HOME/monitoring-sites-staging
|
||||
MON_HOSTS="stage.bank.lefrancpaysan.ch stage.exchange.lefrancpaysan.ch stage.monnaie.lefrancpaysan.ch"
|
||||
|
||||
# Git clone of taler-monitoring (repo root, not …/taler-monitoring (repo root))
|
||||
SUITE_DIR=$HOME/src/taler-monitoring
|
||||
SUITE_GIT_URL=https://git.hacktivism.ch/hernani/taler-monitoring.git
|
||||
SUITE_GIT_REF=main
|
||||
SUITE_UPDATE_MODE=reset
|
||||
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
|
||||
114
host-agent/install-host-agent.sh
Executable file
114
host-agent/install-host-agent.sh
Executable file
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/env bash
|
||||
# install-host-agent.sh — install hernani user systemd units on koopa
|
||||
#
|
||||
# # on koopa as hernani:
|
||||
# ~/src/taler-monitoring/host-agent/install-host-agent.sh
|
||||
# # or from laptop:
|
||||
# ./install-host-agent.sh --remote $DEPLOY_SSH
|
||||
#
|
||||
# Suite tree is ONLY ~/src/taler-monitoring (standalone repo). No koopa-admin-log.
|
||||
#
|
||||
set -euo pipefail
|
||||
ROOT=$(cd "$(dirname "$0")" && pwd)
|
||||
REMOTE="${1:-}"
|
||||
[ "${1:-}" = "--remote" ] && REMOTE="${2:-${DEPLOY_SSH:-}}"
|
||||
|
||||
SUITE_URL="${SUITE_GIT_URL:-https://git.hacktivism.ch/hernani/taler-monitoring.git}"
|
||||
|
||||
install_local() {
|
||||
local mon home_unit
|
||||
mon=$(cd "$ROOT/.." && pwd)
|
||||
if [ -d "$HOME/src/taler-monitoring/.git" ] || [ -d "$HOME/src/taler-monitoring" ]; then
|
||||
mon="$HOME/src/taler-monitoring"
|
||||
fi
|
||||
home_unit="$HOME/.config/systemd/user"
|
||||
mkdir -p "$home_unit" \
|
||||
"$HOME/.local/state/taler-hacktivism-monitoring" \
|
||||
"$HOME/monitoring-sites-staging" \
|
||||
"$HOME/.config/taler-monitoring" \
|
||||
"$HOME/src"
|
||||
|
||||
# Local env (never in git) — create from example if missing
|
||||
if [ ! -f "$HOME/.config/taler-monitoring/env" ] && [ -f "$ROOT/env.example" ]; then
|
||||
cp "$ROOT/env.example" "$HOME/.config/taler-monitoring/env"
|
||||
echo "created ~/.config/taler-monitoring/env"
|
||||
fi
|
||||
|
||||
# Ensure suite git clone at canonical path
|
||||
if [ ! -d "$HOME/src/taler-monitoring/.git" ]; then
|
||||
if [ -d "$mon/.git" ] && [ "$mon" != "$HOME/src/taler-monitoring" ]; then
|
||||
mkdir -p "$HOME/src"
|
||||
ln -sfn "$mon" "$HOME/src/taler-monitoring"
|
||||
echo "symlink $HOME/src/taler-monitoring → $mon"
|
||||
else
|
||||
echo "clone $SUITE_URL → $HOME/src/taler-monitoring"
|
||||
git clone "$SUITE_URL" "$HOME/src/taler-monitoring" \
|
||||
|| echo "WARN: clone failed (auth/network) — using tree at $mon if present"
|
||||
fi
|
||||
fi
|
||||
mon="$HOME/src/taler-monitoring"
|
||||
# Convenience link (update-suite.sh also creates this)
|
||||
ln -sfn "$mon" "$HOME/taler-monitoring" 2>/dev/null || true
|
||||
|
||||
# Ensure suite is executable
|
||||
chmod +x "$mon"/taler-monitoring.sh "$mon"/check_*.sh 2>/dev/null || true
|
||||
chmod +x "$mon/host-agent"/*.sh 2>/dev/null || true
|
||||
chmod +x "$mon/site-gen"/*.sh "$mon/site-gen/console_to_html.py" 2>/dev/null || true
|
||||
|
||||
install -m 644 "$ROOT/taler-monitoring-hacktivism.service" "$home_unit/"
|
||||
install -m 644 "$ROOT/taler-monitoring-hacktivism.path" "$home_unit/"
|
||||
install -m 644 "$ROOT/taler-monitoring-hacktivism.timer" "$home_unit/"
|
||||
install -m 644 "$ROOT/taler-monitoring-surface.service" "$home_unit/"
|
||||
install -m 644 "$ROOT/taler-monitoring-surface.timer" "$home_unit/"
|
||||
# optional aptdeploy (not a public mon page layout — v1.8.0 simplified overview)
|
||||
install -m 644 "$ROOT/taler-monitoring-aptdeploy.service" "$home_unit/"
|
||||
install -m 644 "$ROOT/taler-monitoring-aptdeploy.timer" "$home_unit/"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now taler-monitoring-hacktivism.path
|
||||
systemctl --user enable --now taler-monitoring-hacktivism.timer
|
||||
systemctl --user enable --now taler-monitoring-surface.timer
|
||||
systemctl --user enable --now taler-monitoring-aptdeploy.timer
|
||||
# Remove leftover mail/mattermost units if present (moved to meta/deprecated/)
|
||||
systemctl --user disable --now taler-monitoring-mattermost.timer 2>/dev/null || true
|
||||
systemctl --user disable --now taler-monitoring-mail.timer 2>/dev/null || true
|
||||
rm -f "$home_unit/taler-monitoring-mattermost.service" \
|
||||
"$home_unit/taler-monitoring-mattermost.timer" \
|
||||
"$home_unit/taler-monitoring-mail.service" \
|
||||
"$home_unit/taler-monitoring-mail.timer" 2>/dev/null || true
|
||||
systemctl --user daemon-reload 2>/dev/null || true
|
||||
# initial stamp so path exists
|
||||
"$ROOT/touch-software-stamp.sh"
|
||||
systemctl --user start taler-monitoring-hacktivism.service || true
|
||||
systemctl --user start taler-monitoring-surface.service || true
|
||||
systemctl --user start taler-monitoring-aptdeploy.service || true
|
||||
|
||||
echo "--- status ---"
|
||||
systemctl --user status taler-monitoring-hacktivism.path --no-pager -l | head -15
|
||||
systemctl --user status taler-monitoring-hacktivism.timer --no-pager -l | head -12
|
||||
systemctl --user status taler-monitoring-surface.timer --no-pager -l | head -12
|
||||
systemctl --user status taler-monitoring-aptdeploy.timer --no-pager -l | head -12
|
||||
systemctl --user list-timers --all | grep taler-monitoring || true
|
||||
echo "OK host-agent (v1.8.0 simplified):"
|
||||
echo " · hacktivism 4h → /monitoring on bank/exchange/taler (landing stacks)"
|
||||
echo " · surface 1h → /taler-monitoring-surface* (ecosystem versions/software)"
|
||||
echo " · aptdeploy 4h (optional tests; not a public mon-page type)"
|
||||
echo " · mail/mattermost: not installed (meta/deprecated/; content in surface)"
|
||||
echo "suite: $mon"
|
||||
echo "manual surface: systemctl --user start taler-monitoring-surface.service"
|
||||
echo "after upgrades: $ROOT/touch-software-stamp.sh"
|
||||
}
|
||||
|
||||
if [ -n "$REMOTE" ] && [ "$REMOTE" != "--remote" ]; then
|
||||
echo "install on $REMOTE …"
|
||||
# ROOT = …/taler-monitoring/host-agent → suite root is parent
|
||||
rsync -az --delete \
|
||||
--exclude secrets.env \
|
||||
--exclude 'android-test/artifacts' \
|
||||
--exclude '.git' \
|
||||
"$ROOT/../" \
|
||||
"${REMOTE}:src/taler-monitoring/"
|
||||
ssh -o BatchMode=yes "$REMOTE" \
|
||||
'bash $HOME/src/taler-monitoring/host-agent/install-host-agent.sh'
|
||||
else
|
||||
install_local
|
||||
fi
|
||||
45
host-agent/run-aptdeploy-monitoring.sh
Executable file
45
host-agent/run-aptdeploy-monitoring.sh
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env bash
|
||||
# run-aptdeploy-monitoring.sh — apt-src deploy tests → public HTML
|
||||
# Public only on taler.hacktivism.ch:
|
||||
# https://taler.hacktivism.ch/taler-monitoring-aptdeploy/
|
||||
# https://taler.hacktivism.ch/taler-monitoring-aptdeploy_err/
|
||||
#
|
||||
# CLI one-shot without HTML remains: run-aptdeploy.sh [all|fresh|upgrade|check-only]
|
||||
#
|
||||
set -uo pipefail
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
export AGENT_LABEL="${AGENT_LABEL:-aptdeploy-host-agent}"
|
||||
export STATE_NAME="${STATE_NAME:-taler-aptdeploy-monitoring}"
|
||||
export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}"
|
||||
# containers are local on koopa
|
||||
export INSIDE_PODMAN=1
|
||||
export INSIDE_MODE=local-podman
|
||||
export LOCAL_STACK=1
|
||||
export SKIP_SSH=0
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
||||
# four containers + checks; allow long wall
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-1800}"
|
||||
# dedicated job: always aptdeploy only (force — do not inherit main-timer env)
|
||||
export PHASES="aptdeploy monpages"
|
||||
# Public HTML only on taler.hacktivism.ch (not bank/exchange landings)
|
||||
export MON_HOSTS="taler.hacktivism.ch"
|
||||
export HTML_OUT="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
export DEPLOY_WWW_ROOT="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
||||
|
||||
export HTML_OK_DIR="taler-monitoring-aptdeploy"
|
||||
export HTML_ERR_DIR="taler-monitoring-aptdeploy_err"
|
||||
export HTML_URL_OK="/taler-monitoring-aptdeploy/"
|
||||
export HTML_URL_ERR="/taler-monitoring-aptdeploy_err/"
|
||||
export PAGE_LABEL="taler-monitoring-aptdeploy"
|
||||
# monpages: only this job’s paths on taler.hacktivism.ch
|
||||
export MONPAGES_INVENTORY="job"
|
||||
|
||||
# Ensure all four apt-src containers (fresh rebuild + upgrade track)
|
||||
if [ "${APT_DEPLOY_ENSURE:-1}" = "1" ] \
|
||||
&& [ -x "$AGENT_DIR/ensure-apt-deploy-test-containers.sh" ]; then
|
||||
bash "$AGENT_DIR/ensure-apt-deploy-test-containers.sh" all \
|
||||
|| echo "WARN: ensure-apt-deploy-test-containers failed (aptdeploy may ERROR)" >&2
|
||||
fi
|
||||
|
||||
exec bash "$AGENT_DIR/run-host-report.sh" "$@"
|
||||
150
host-agent/run-aptdeploy.sh
Executable file
150
host-agent/run-aptdeploy.sh
Executable file
|
|
@ -0,0 +1,150 @@
|
|||
#!/usr/bin/env bash
|
||||
# run-aptdeploy.sh — ensure containers + aptdeploy phase only.
|
||||
#
|
||||
# Keep monitoring current:
|
||||
# 1) Prefer Forgejo origin/main (update-suite reset)
|
||||
# 2) If Forgejo is behind (no aptdeploy yet), re-apply suite-overlay saved
|
||||
# from this agent tree before reset (rsync from laptop fills that tree)
|
||||
# 3) Run ensure + taler-monitoring.sh aptdeploy
|
||||
#
|
||||
# Host: on koopa → local; else ssh APT_DEPLOY_SSH + rsync mon tree first.
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
BOOT_MON=$(cd "$AGENT_DIR/.." && pwd)
|
||||
MODE="${1:-all}"
|
||||
APT_DEPLOY_SSH="${APT_DEPLOY_SSH:-${DEPLOY_SSH:-}}"
|
||||
OVERLAY_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/taler-monitoring/suite-overlay"
|
||||
|
||||
on_koopa() {
|
||||
local h
|
||||
h=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
||||
case "$h" in koopa|koopa.*) return 0 ;; esac
|
||||
[ "${KOOPA_FORCE_LOCAL:-0}" = "1" ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
mon_has_aptdeploy() {
|
||||
local mon=$1
|
||||
[ -f "$mon/taler-monitoring.sh" ] && grep -qE 'aptdeploy\|apt-deploy' "$mon/taler-monitoring.sh"
|
||||
}
|
||||
|
||||
save_overlay_from() {
|
||||
local src=$1
|
||||
mon_has_aptdeploy "$src" || return 0
|
||||
mkdir -p "$OVERLAY_DIR"
|
||||
rsync -a --delete \
|
||||
--exclude secrets.env \
|
||||
--exclude 'android-test/artifacts' \
|
||||
--exclude 'android-test/apks' \
|
||||
--exclude 'android-test/out*' \
|
||||
--exclude '__pycache__' \
|
||||
"$src/" "$OVERLAY_DIR/"
|
||||
echo "saved suite-overlay from $src → $OVERLAY_DIR"
|
||||
}
|
||||
|
||||
apply_overlay_to() {
|
||||
local dest=$1
|
||||
[ -f "$OVERLAY_DIR/taler-monitoring.sh" ] || return 1
|
||||
mon_has_aptdeploy "$OVERLAY_DIR" || return 1
|
||||
mkdir -p "$dest"
|
||||
rsync -a \
|
||||
--exclude secrets.env \
|
||||
--exclude 'android-test/artifacts' \
|
||||
--exclude 'android-test/apks' \
|
||||
--exclude 'android-test/out*' \
|
||||
--exclude '__pycache__' \
|
||||
"$OVERLAY_DIR/" "$dest/"
|
||||
echo "applied suite-overlay → $dest (Forgejo lag; push origin/main when possible)"
|
||||
return 0
|
||||
}
|
||||
|
||||
pick_mon_tree() {
|
||||
# Preserve working mon before reset wipes tracked files
|
||||
save_overlay_from "$BOOT_MON"
|
||||
|
||||
# shellcheck source=update-suite.sh
|
||||
source "$AGENT_DIR/update-suite.sh"
|
||||
|
||||
local suite_mon="$SUITE_DIR"
|
||||
mkdir -p "$suite_mon"
|
||||
|
||||
if mon_has_aptdeploy "$suite_mon"; then
|
||||
MON_DIR="$suite_mon"
|
||||
echo "using Forgejo suite mon @ ${COMMIT_SHORT:-?} · $MON_DIR"
|
||||
elif apply_overlay_to "$suite_mon" && mon_has_aptdeploy "$suite_mon"; then
|
||||
MON_DIR="$suite_mon"
|
||||
echo "using suite mon + overlay @ ${COMMIT_SHORT:-?} · $MON_DIR"
|
||||
elif mon_has_aptdeploy "$BOOT_MON"; then
|
||||
MON_DIR="$BOOT_MON"
|
||||
echo "WARN: using boot mon $MON_DIR (overlay apply failed)" >&2
|
||||
else
|
||||
echo "ERROR: no mon tree with aptdeploy (Forgejo + overlay empty)" >&2
|
||||
echo " rsync suite from laptop or push to git.hacktivism.ch" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
AGENT_DIR="$MON_DIR/host-agent"
|
||||
export MON_DIR AGENT_DIR SUITE_DIR COMMIT COMMIT_SHORT COMMIT_URL
|
||||
chmod +x "$AGENT_DIR"/*.sh "$MON_DIR"/taler-monitoring.sh "$MON_DIR"/check_*.sh 2>/dev/null || true
|
||||
}
|
||||
|
||||
run_local() {
|
||||
export PATH="${HOME}/.local/bin:/usr/local/bin:/usr/bin:/bin:${PATH:-}"
|
||||
export PYTHONUNBUFFERED=1
|
||||
export PROGRESS_OFF="${PROGRESS_OFF:-0}"
|
||||
|
||||
echo "======== aptdeploy local on $(hostname) mode=$MODE ========"
|
||||
pick_mon_tree
|
||||
|
||||
if [ "$MODE" != "check-only" ]; then
|
||||
bash "$AGENT_DIR/ensure-apt-deploy-test-containers.sh" "$MODE"
|
||||
fi
|
||||
|
||||
cd "$MON_DIR"
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
||||
export INSIDE_PODMAN="${INSIDE_PODMAN:-1}"
|
||||
export LOCAL_STACK="${LOCAL_STACK:-1}"
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-600}"
|
||||
echo "run: $MON_DIR/taler-monitoring.sh -d hacktivism.ch aptdeploy · suite=${COMMIT_SHORT:-?}"
|
||||
./taler-monitoring.sh -d hacktivism.ch aptdeploy
|
||||
}
|
||||
|
||||
run_remote() {
|
||||
echo "======== aptdeploy remote via ssh ${APT_DEPLOY_SSH} mode=$MODE ========"
|
||||
if [ "${APT_DEPLOY_RSYNC:-1}" = "1" ]; then
|
||||
echo "rsync mon suite → ${APT_DEPLOY_SSH}:src/taler-monitoring/"
|
||||
rsync -az \
|
||||
--exclude secrets.env \
|
||||
--exclude 'android-test/artifacts' \
|
||||
--exclude 'android-test/apks' \
|
||||
--exclude 'android-test/out*' \
|
||||
--exclude '__pycache__' \
|
||||
"$BOOT_MON/" \
|
||||
"${APT_DEPLOY_SSH}:src/taler-monitoring/" \
|
||||
|| echo "WARN: rsync failed" >&2
|
||||
fi
|
||||
ssh -o BatchMode=yes -o ConnectTimeout=25 "$APT_DEPLOY_SSH" bash -s -- "$MODE" <<'EOS'
|
||||
set -euo pipefail
|
||||
MODE=${1:-all}
|
||||
export PATH="${HOME}/.local/bin:/usr/local/bin:/usr/bin:/bin:${PATH:-}"
|
||||
export KOOPA_FORCE_LOCAL=1
|
||||
AGENT="$HOME/src/taler-monitoring/host-agent"
|
||||
if [ ! -x "$AGENT/run-aptdeploy.sh" ]; then
|
||||
AGENT="$HOME/src/taler-monitoring/host-agent"
|
||||
fi
|
||||
if [ ! -x "$AGENT/run-aptdeploy.sh" ]; then
|
||||
echo "ERROR: run-aptdeploy.sh missing on remote" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "remote AGENT=$AGENT"
|
||||
exec bash "$AGENT/run-aptdeploy.sh" "$MODE"
|
||||
EOS
|
||||
}
|
||||
|
||||
if on_koopa; then
|
||||
run_local
|
||||
else
|
||||
run_remote
|
||||
fi
|
||||
27
host-agent/run-fp-stage-monitoring.sh
Executable file
27
host-agent/run-fp-stage-monitoring.sh
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bash
|
||||
# FrancPaysan STAGE host-agent (user stagepaysan via francpaysan-stage-user).
|
||||
# Shared reporting: run-host-report.sh (timeout, line-buffered log, first-run HTML).
|
||||
set -uo pipefail
|
||||
|
||||
# Language: en|fr (selectable). Default for this wrapper: fr
|
||||
export TALER_MON_LANG="${TALER_MON_LANG:-fr}"
|
||||
export TALER_MON_LANG_SET=1
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
export AGENT_LABEL="${AGENT_LABEL:-fp-stage-host-agent}"
|
||||
export STATE_NAME="${STATE_NAME:-taler-monitoring-stage-lfp}"
|
||||
export TALER_DOMAIN="${TALER_DOMAIN:-stage.lefrancpaysan.ch}"
|
||||
export INSIDE_PODMAN="${INSIDE_PODMAN:-1}"
|
||||
export INSIDE_MODE="${INSIDE_MODE:-local-podman}"
|
||||
export INSIDE_PROFILE="${INSIDE_PROFILE:-stage-lfp}"
|
||||
export LOCAL_STACK="${LOCAL_STACK:-0}"
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
||||
# monpages obligatory (ERROR): only FP stage mon hosts below — never GOA inventory
|
||||
export MONPAGES_REQUIRE_PUBLIC="${MONPAGES_REQUIRE_PUBLIC:-1}"
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-600}"
|
||||
export PHASES="${PHASES:-urls inside versions monpages}"
|
||||
export MON_HOSTS="${MON_HOSTS:-stage.bank.lefrancpaysan.ch stage.exchange.lefrancpaysan.ch stage.monnaie.lefrancpaysan.ch}"
|
||||
export HTML_OUT="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
export DEPLOY_WWW_ROOT="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
||||
|
||||
exec bash "$AGENT_DIR/run-host-report.sh" "$@"
|
||||
31
host-agent/run-hacktivism-monitoring.sh
Executable file
31
host-agent/run-hacktivism-monitoring.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
# GOA / hacktivism host-agent on koopa (hernani).
|
||||
# Stack defaults only — reporting pipeline is shared: run-host-report.sh
|
||||
set -uo pipefail
|
||||
|
||||
# Language: en|fr (selectable). Default for this wrapper: en
|
||||
export TALER_MON_LANG="${TALER_MON_LANG:-en}"
|
||||
export TALER_MON_LANG_SET=1
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
export AGENT_LABEL="${AGENT_LABEL:-hacktivism-host-agent}"
|
||||
export STATE_NAME="${STATE_NAME:-taler-hacktivism-monitoring}"
|
||||
export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}"
|
||||
export INSIDE_PODMAN="${INSIDE_PODMAN:-1}"
|
||||
export INSIDE_MODE="${INSIDE_MODE:-local-podman}"
|
||||
export LOCAL_STACK="${LOCAL_STACK:-1}"
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-600}"
|
||||
# stack checks + full monpages inventory (landings + surface + aptdeploy bare/slash).
|
||||
# Specialized pages also have their own timers; full outside-in inventory lives here.
|
||||
# run-aptdeploy-monitoring.sh → monpages job-only for /taler-monitoring-aptdeploy*
|
||||
# run-surface-monitoring.sh → monpages job-only for /taler-monitoring-surface*
|
||||
export PHASES="${PHASES:-urls inside versions monpages}"
|
||||
export MON_HOSTS="${MON_HOSTS:-bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch}"
|
||||
export HTML_OUT="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
export DEPLOY_WWW_ROOT="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
||||
export APT_DEPLOY_ENSURE=0
|
||||
# full GOA mon catalog (not job-only)
|
||||
export MONPAGES_INVENTORY="${MONPAGES_INVENTORY:-auto}"
|
||||
|
||||
exec bash "$AGENT_DIR/run-host-report.sh" "$@"
|
||||
495
host-agent/run-host-report.sh
Executable file
495
host-agent/run-host-report.sh
Executable file
|
|
@ -0,0 +1,495 @@
|
|||
#!/usr/bin/env bash
|
||||
# run-host-report.sh — global reporting generation for all stacks
|
||||
# (GOA/hacktivism, FP stage, mytops stage, …).
|
||||
#
|
||||
# Shared behaviour (always):
|
||||
# 1) update-suite → latest git.hacktivism.ch (local ~/.config never overwritten)
|
||||
# 2) line-buffered run log (written continuously)
|
||||
# 3) RUN_TIMEOUT wall clock for taler-monitoring.sh (default 600s)
|
||||
# 4) always write HTML (first run / empty staging too) + Forgejo commit link
|
||||
# 5) rsync to DEPLOY_WWW_ROOT (ERROR if not writable — v1.3.1)
|
||||
# 6) monpages post-check: public FQDN must serve monitoring HTML
|
||||
# 7) exit code: STRICT_EXIT default 1 (v1.7.1) — unit fails if publish/public pages fail
|
||||
#
|
||||
# Configure via env file (not in git):
|
||||
# ${XDG_CONFIG_HOME:-$HOME/.config}/taler-monitoring/env
|
||||
# or TALER_MONITORING_ENV=/path/to/env
|
||||
#
|
||||
# Thin wrappers only set stack defaults then exec this script:
|
||||
# run-hacktivism-monitoring.sh
|
||||
# run-fp-stage-monitoring.sh
|
||||
#
|
||||
set -uo pipefail
|
||||
|
||||
export PATH="${HOME}/.local/bin:/usr/local/bin:/usr/bin:/bin:${PATH:-}"
|
||||
export PYTHONUNBUFFERED=1
|
||||
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
AGENT_MON=$(cd "$AGENT_DIR/.." && pwd)
|
||||
CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/taler-monitoring"
|
||||
ENV_FILE="${TALER_MONITORING_ENV:-$CFG_DIR/env}"
|
||||
mkdir -p "$CFG_DIR"
|
||||
|
||||
# Thin wrappers (surface, aptdeploy-only, …) export stack knobs before exec.
|
||||
# Snapshot them so ~/.config/taler-monitoring/env cannot clobber dedicated jobs
|
||||
# (env often has PHASES="urls inside versions aptdeploy" for the main timer).
|
||||
_wrap_keys=(
|
||||
PHASES HTML_OUT HTML_OK_DIR HTML_ERR_DIR HTML_URL_OK HTML_URL_ERR PAGE_LABEL
|
||||
RUN_TIMEOUT STATE_NAME AGENT_LABEL MON_HOSTS TALER_DOMAIN DEPLOY_WWW_ROOT
|
||||
INSIDE_PODMAN INSIDE_MODE LOCAL_STACK SKIP_SSH CONTINUE_ON_ERROR AUTH401_CONTINUE
|
||||
APT_DEPLOY_ENSURE SURFACE_SCOPE TALER_DOMAIN_FROM_CLI STRICT_EXIT SOURCE_SUITE_PATH
|
||||
MONPAGES_INVENTORY MONPAGES_CHECK_BARE MONPAGES_BARE_STRICT MONPAGES_REQUIRE_PUBLIC
|
||||
CHECK_BANK MERCHANT_REQUIRED CHECK_LANDING
|
||||
)
|
||||
for _k in "${_wrap_keys[@]}"; do
|
||||
if [ -n "${!_k+x}" ]; then
|
||||
printf -v "_WRAP_SET_${_k}" '%s' 1
|
||||
printf -v "_WRAP_VAL_${_k}" '%s' "${!_k}"
|
||||
fi
|
||||
done
|
||||
unset _k
|
||||
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
fi
|
||||
# Tell update-suite.sh not to re-source env (would clobber wrapper PHASES etc.)
|
||||
export _TALER_MON_ENV_LOADED=1
|
||||
|
||||
# Restore wrapper overrides (dedicated jobs win over shared env file)
|
||||
for _k in "${_wrap_keys[@]}"; do
|
||||
_set_var="_WRAP_SET_${_k}"
|
||||
_val_var="_WRAP_VAL_${_k}"
|
||||
if [ "${!_set_var:-}" = "1" ]; then
|
||||
printf -v "$_k" '%s' "${!_val_var}"
|
||||
export "$_k"
|
||||
fi
|
||||
done
|
||||
unset _k _set_var _val_var
|
||||
|
||||
# --- global report defaults (env file / wrapper wins if already set) ---
|
||||
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: selectable via TALER_MON_LANG / --lang (en|fr).
|
||||
# If unset, auto: FrancPaysan domains → fr, else en.
|
||||
if [ "${TALER_MON_LANG_SET:-0}" != "1" ] && [ -z "${TALER_MON_LANG:-}" ]; then
|
||||
case "$TALER_DOMAIN" in
|
||||
*lefrancpaysan*|*francpaysan*) export TALER_MON_LANG=fr ;;
|
||||
*) export TALER_MON_LANG=en ;;
|
||||
esac
|
||||
elif [ -n "${TALER_MON_LANG:-}" ]; then
|
||||
case "$TALER_MON_LANG" in
|
||||
fr|FR|fra|french) export TALER_MON_LANG=fr ;;
|
||||
*) export TALER_MON_LANG=en ;;
|
||||
esac
|
||||
export TALER_MON_LANG_SET=1
|
||||
fi
|
||||
export TALER_MON_LANG
|
||||
|
||||
PHASES="${PHASES:-urls inside versions monpages}"
|
||||
HTML_BASE="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
MON_HOSTS="${MON_HOSTS:-}"
|
||||
SUITE_PATH="${SOURCE_SUITE_PATH:-.}"
|
||||
AGENT_LABEL="${AGENT_LABEL:-host-report}"
|
||||
STATE_NAME="${STATE_NAME:-taler-monitoring-${TALER_DOMAIN}}"
|
||||
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/${STATE_NAME}"
|
||||
LOG_DIR="$STATE_DIR/logs"
|
||||
DEPLOY_WWW="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
||||
# HTML path layout under each host (monitoring / surface / …)
|
||||
HTML_OK_DIR="${HTML_OK_DIR:-monitoring}"
|
||||
HTML_ERR_DIR="${HTML_ERR_DIR:-monitoring_err}"
|
||||
HTML_URL_OK="${HTML_URL_OK:-/monitoring/}"
|
||||
HTML_URL_ERR="${HTML_URL_ERR:-/monitoring_err/}"
|
||||
PAGE_LABEL="${PAGE_LABEL:-monitoring}"
|
||||
SUITE_VERSION="${SUITE_VERSION:-}"
|
||||
SUITE_VERSION_URL="${SUITE_VERSION_URL:-}"
|
||||
if [ -z "$SUITE_VERSION" ] && [ -d "${ROOT:-$AGENT_MON}/.git" ]; then
|
||||
_vd="${ROOT:-$AGENT_MON}"
|
||||
SUITE_VERSION=$(git -C "$_vd" describe --tags --exact-match 2>/dev/null || git -C "$_vd" describe --tags --abbrev=0 2>/dev/null || true)
|
||||
fi
|
||||
if [ -z "$SUITE_VERSION" ] && [ -f "${ROOT:-$AGENT_MON}/VERSION" ]; then
|
||||
SUITE_VERSION="v$(tr -d '[:space:]' <"${ROOT:-$AGENT_MON}/VERSION" | sed 's/^v//')"
|
||||
fi
|
||||
[ -z "$SUITE_VERSION" ] && SUITE_VERSION="unknown"
|
||||
case "$SUITE_VERSION" in unknown|v*) ;; *) SUITE_VERSION="v$SUITE_VERSION" ;; esac
|
||||
# Prefer commit URL over /src/tag/… (tags lag push → sticky version 404 on Forgejo).
|
||||
if [ -z "$SUITE_VERSION_URL" ]; then
|
||||
_web="${SOURCE_REPO_WEB:-https://git.hacktivism.ch/hernani/taler-monitoring}"
|
||||
if [ -n "${COMMIT:-}" ] && [ "$COMMIT" != "unknown" ]; then
|
||||
SUITE_VERSION_URL="${_web}/src/commit/${COMMIT}"
|
||||
elif [ "$SUITE_VERSION" != "unknown" ]; then
|
||||
SUITE_VERSION_URL="${_web}/src/tag/${SUITE_VERSION}"
|
||||
fi
|
||||
fi
|
||||
export SUITE_VERSION SUITE_VERSION_URL
|
||||
|
||||
|
||||
# Sensible MON_HOSTS from domain if not set
|
||||
if [ -z "$MON_HOSTS" ]; then
|
||||
case "$TALER_DOMAIN" in
|
||||
hacktivism.ch|koopa)
|
||||
MON_HOSTS="bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch"
|
||||
;;
|
||||
stage.lefrancpaysan.ch|stage.*lefrancpaysan*)
|
||||
MON_HOSTS="stage.bank.lefrancpaysan.ch stage.exchange.lefrancpaysan.ch stage.monnaie.lefrancpaysan.ch"
|
||||
;;
|
||||
lefrancpaysan.ch)
|
||||
MON_HOSTS="bank.lefrancpaysan.ch exchange.lefrancpaysan.ch monnaie.lefrancpaysan.ch"
|
||||
;;
|
||||
*)
|
||||
MON_HOSTS="${TALER_DOMAIN}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
mkdir -p "$LOG_DIR" "$HTML_BASE"
|
||||
|
||||
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||
LOG="$LOG_DIR/run-${STAMP}.log"
|
||||
UPD_LOG="$LOG_DIR/suite-update-${STAMP}.log"
|
||||
: >"$LOG"
|
||||
|
||||
# --- suite auto-upgrade BEFORE the HTML log (git noise must not pollute mon pages) ---
|
||||
OVERLAY_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/taler-monitoring/suite-overlay"
|
||||
if [ -f "$AGENT_MON/taler-monitoring.sh" ]; then
|
||||
mkdir -p "$OVERLAY_DIR"
|
||||
rsync -a \
|
||||
--exclude secrets.env --exclude 'android-test/artifacts' --exclude 'android-test/apks' \
|
||||
--exclude 'android-test/out*' --exclude '__pycache__' \
|
||||
"$AGENT_MON/" "$OVERLAY_DIR/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# shellcheck source=update-suite.sh
|
||||
if ! source "$AGENT_DIR/update-suite.sh" >"$UPD_LOG" 2>&1; then
|
||||
echo "ERROR: suite auto-update failed — refusing to run with stale tree" >&2
|
||||
echo " detail: $UPD_LOG" >&2
|
||||
tail -n 30 "$UPD_LOG" >&2 || true
|
||||
echo " fix git/network or set SUITE_UPDATE_STRICT=0 only as emergency" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "${SUITE_DIR:-}/host-agent" ]; then
|
||||
AGENT_DIR="${SUITE_DIR}/host-agent"
|
||||
fi
|
||||
|
||||
# Now open the public HTML log (clean agent header + suite summary only)
|
||||
if command -v stdbuf >/dev/null 2>&1; then
|
||||
exec > >(stdbuf -oL -eL tee -a "$LOG") 2>&1
|
||||
else
|
||||
exec > >(tee -a "$LOG") 2>&1
|
||||
fi
|
||||
|
||||
echo "======== $(date -Iseconds 2>/dev/null || date) ${AGENT_LABEL} ========"
|
||||
echo "env_file=$ENV_FILE"
|
||||
echo "domain=$TALER_DOMAIN · phases=$PHASES · RUN_TIMEOUT=${RUN_TIMEOUT}s"
|
||||
echo "hosts=$MON_HOSTS"
|
||||
echo "flags INSIDE_PODMAN=${INSIDE_PODMAN:-} INSIDE_MODE=${INSIDE_MODE:-} LOCAL_STACK=${LOCAL_STACK:-} SKIP_SSH=${SKIP_SSH:-} INSIDE_PROFILE=${INSIDE_PROFILE:-}"
|
||||
# One-line suite pin (no git M/checkout noise)
|
||||
echo "suite ${SUITE_VERSION:-?} @ ${COMMIT_SHORT:-?} ${COMMIT_URL:-}"
|
||||
echo " dir=${SUITE_DIR:-}"
|
||||
|
||||
SUITE_MON="${SUITE_DIR}"
|
||||
ROOT="$SUITE_MON"
|
||||
_need_overlay=0
|
||||
# Detect missing features in Forgejo tree (untracked helper files alone are not enough —
|
||||
# taler-monitoring.sh must accept the phase name).
|
||||
case " $PHASES " in
|
||||
*" aptdeploy "*|*" apt-deploy "*|*" apt_src "*)
|
||||
if ! grep -qE 'aptdeploy\|apt-deploy' "$SUITE_MON/taler-monitoring.sh" 2>/dev/null; then
|
||||
_need_overlay=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
case " $PHASES " in
|
||||
*" surface "*|*" ecosystem "*)
|
||||
if ! grep -qE 'surface\|ecosystem' "$SUITE_MON/taler-monitoring.sh" 2>/dev/null \
|
||||
|| [ ! -f "$SUITE_MON/check_surface.sh" ]; then
|
||||
_need_overlay=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
# Wrapper-preserve + HTML path knobs may live only in local overlay until pushed
|
||||
if [ -f "$OVERLAY_DIR/host-agent/run-host-report.sh" ] \
|
||||
&& ! grep -q '_wrap_keys\|_WRAP_SET_' "$SUITE_MON/host-agent/run-host-report.sh" 2>/dev/null \
|
||||
&& grep -q '_wrap_keys\|_WRAP_SET_' "$OVERLAY_DIR/host-agent/run-host-report.sh" 2>/dev/null; then
|
||||
_need_overlay=1
|
||||
fi
|
||||
if [ "$_need_overlay" = "1" ] && [ -f "$OVERLAY_DIR/taler-monitoring.sh" ]; then
|
||||
echo "WARN: Forgejo @ ${COMMIT_SHORT:-?} lagging local suite-overlay (phases=[$PHASES])" >&2
|
||||
echo " re-applying suite-overlay → $SUITE_MON" >&2
|
||||
mkdir -p "$SUITE_MON"
|
||||
rsync -a \
|
||||
--exclude secrets.env --exclude 'android-test/artifacts' --exclude 'android-test/apks' \
|
||||
--exclude 'android-test/out*' --exclude '__pycache__' \
|
||||
"$OVERLAY_DIR/" "$SUITE_MON/"
|
||||
ROOT="$SUITE_MON"
|
||||
elif [ "$_need_overlay" = "1" ]; then
|
||||
echo "WARN: Forgejo missing features and no suite-overlay — using agent mon $AGENT_MON" >&2
|
||||
ROOT="$AGENT_MON"
|
||||
else
|
||||
echo "using suite mon @ ${COMMIT_SHORT:-?} · $ROOT"
|
||||
# Do NOT rsync suite-overlay over a fresh Forgejo tree — that reintroduced
|
||||
# stale site-gen/host-agent (bootstrap sticky, old monpages) on stage/betel.
|
||||
fi
|
||||
unset _need_overlay
|
||||
|
||||
if [ -f "$ROOT/site-gen/console_to_html.py" ]; then
|
||||
SITE_GEN="$ROOT/site-gen"
|
||||
elif [ -f "$AGENT_MON/site-gen/console_to_html.py" ]; then
|
||||
SITE_GEN="$AGENT_MON/site-gen"
|
||||
echo "note: using agent site-gen at $SITE_GEN"
|
||||
elif [ -f "$SUITE_MON/site-gen/console_to_html.py" ]; then
|
||||
SITE_GEN="$SUITE_MON/site-gen"
|
||||
else
|
||||
SITE_GEN=""
|
||||
fi
|
||||
|
||||
if [ ! -x "$ROOT/taler-monitoring.sh" ]; then
|
||||
if [ -x "$AGENT_MON/taler-monitoring.sh" ]; then
|
||||
ROOT="$AGENT_MON"
|
||||
echo "note: using agent mon tree $ROOT"
|
||||
else
|
||||
echo "ERROR: suite missing at $ROOT" >&2
|
||||
COMMIT="${COMMIT:-unknown}"
|
||||
COMMIT_SHORT="${COMMIT_SHORT:-unknown}"
|
||||
COMMIT_URL="${COMMIT_URL:-}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "commit=${COMMIT_SHORT:-?} · ${COMMIT_URL:-}"
|
||||
|
||||
ec=1
|
||||
if [ -x "${ROOT:-}/taler-monitoring.sh" ]; then
|
||||
cd "$ROOT" || exit 1
|
||||
chmod +x taler-monitoring.sh check_*.sh host-agent/*.sh site-gen/*.sh site-gen/*.py 2>/dev/null || true
|
||||
|
||||
# Overlay newer inside/versions host-podman bits if suite clone is stale
|
||||
for f in check_inside.sh check_versions.sh taler-monitoring.sh lib.sh; do
|
||||
if [ -f "$AGENT_MON/$f" ] && [ -f "$ROOT/$f" ]; then
|
||||
if ! grep -q 'host-podman\|INSIDE_ACCESS\|RUN_TIMEOUT' "$ROOT/$f" 2>/dev/null \
|
||||
&& grep -q 'host-podman\|INSIDE_ACCESS\|RUN_TIMEOUT' "$AGENT_MON/$f" 2>/dev/null; then
|
||||
echo "note: overlay $f from agent install"
|
||||
cp -f "$AGENT_MON/$f" "$ROOT/$f"
|
||||
chmod +x "$ROOT/$f" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# monpages inside PHASES runs *before* htmlify/publish — content failures would
|
||||
# race with concurrent publishes or reflect last run's incomplete redirect stub.
|
||||
# Soft-content there; post-check after rsync stays hard (authoritative).
|
||||
case " $PHASES " in
|
||||
*" monpages "*|*" pages "*) export MONPAGES_PRE_PUBLISH=1 ;;
|
||||
*) unset MONPAGES_PRE_PUBLISH 2>/dev/null || true ;;
|
||||
esac
|
||||
# shellcheck disable=SC2086
|
||||
./taler-monitoring.sh -d "$TALER_DOMAIN" $PHASES
|
||||
ec=$?
|
||||
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# --- always generate HTML (first run / missing pages / every run) ---
|
||||
write_bootstrap_html() {
|
||||
local out="$1" host="$2" mode="$3"
|
||||
mkdir -p "$(dirname "$out")"
|
||||
local cshort="${COMMIT_SHORT:-unknown}"
|
||||
local curl="${COMMIT_URL:-}"
|
||||
local clink="$cshort"
|
||||
local gen iso
|
||||
# Local wall clock (CEST/CET · MESZ/MEZ on CH/DE hosts), not UTC Z
|
||||
if TZ=Europe/Zurich date +"%Y-%m-%d %H:%M:%S %Z" >/dev/null 2>&1; then
|
||||
gen=$(TZ=Europe/Zurich date +"%Y-%m-%d %H:%M:%S %Z")
|
||||
iso=$(TZ=Europe/Zurich date +"%Y-%m-%dT%H:%M:%S%z" | sed 's/\([+-][0-9][0-9]\)\([0-9][0-9]\)$/\1:\2/')
|
||||
else
|
||||
gen=$(date +"%Y-%m-%d %H:%M:%S %Z" 2>/dev/null || date)
|
||||
iso=$(date -Iseconds 2>/dev/null || date)
|
||||
fi
|
||||
if [ -n "$curl" ]; then
|
||||
clink="<a href=\"$(printf '%s' "$curl" | sed 's/&/\&/g')\">$cshort</a>"
|
||||
fi
|
||||
local tmp
|
||||
tmp=$(mktemp "${out}.XXXXXX")
|
||||
cat >"$tmp" <<EOF
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="utf-8"/>
|
||||
<meta name="generated" content="${iso}"/>
|
||||
<meta name="taler-mon-page" content="incomplete"/>
|
||||
<title>monitoring ${mode} · ${host}</title>
|
||||
<style>
|
||||
body{margin:0;background:#0c0c0c;color:#c8c8c8;font-family:ui-monospace,monospace}
|
||||
a{color:#61afef}.err{color:#ff5c5c}
|
||||
.sticky-bar{position:sticky;top:0;z-index:100;padding:10px 14px;background:#2a1010f2;border-bottom:2px solid #a33}
|
||||
.sticky-bar .pill{font-weight:800;color:#ff5c5c;margin-right:8px}
|
||||
.version-link{color:#61afef}
|
||||
main{padding:1.5rem}
|
||||
</style></head><body>
|
||||
<!-- taler-mon:top -->
|
||||
<div class="sticky-bar" id="status-bar">
|
||||
<span class="pill">BOOTSTRAP</span>
|
||||
${PAGE_LABEL:-monitoring} · ${host} ·
|
||||
<span class="version-link muted">bootstrap</span> ·
|
||||
<span data-generated-iso="${iso}">generated ${gen}</span>
|
||||
· source ${clink}
|
||||
</div>
|
||||
<main>
|
||||
<p class="err">Bootstrap page (converter missing or first install). See host-agent log.</p>
|
||||
<pre style="white-space:pre-wrap;font-size:12px">$(tail -n 80 "$LOG" 2>/dev/null | sed 's/&/\&/g;s/</\</g' || true)</pre>
|
||||
</main>
|
||||
<!-- taler-mon:bottom:incomplete -->
|
||||
</body></html>
|
||||
EOF
|
||||
mv -f "$tmp" "$out"
|
||||
echo "bootstrap html → $out"
|
||||
}
|
||||
|
||||
htmlify_host() {
|
||||
local host="$1"
|
||||
local mon="$HTML_BASE/$host/${HTML_OK_DIR}/index.html"
|
||||
local mon_err="$HTML_BASE/$host/${HTML_ERR_DIR}/index.html"
|
||||
mkdir -p "$HTML_BASE/$host/${HTML_OK_DIR}" "$HTML_BASE/$host/${HTML_ERR_DIR}"
|
||||
|
||||
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" \
|
||||
--mode err \
|
||||
--commit "${COMMIT:-}" \
|
||||
--commit-url "${COMMIT_URL:-}" \
|
||||
--suite-version "${SUITE_VERSION:-unknown}" \
|
||||
--suite-version-url "${SUITE_VERSION_URL:-}" \
|
||||
--suite-path "$SUITE_PATH" \
|
||||
--page-label "$PAGE_LABEL" \
|
||||
--path-err "$HTML_URL_ERR" \
|
||||
--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" \
|
||||
--mode ok \
|
||||
--commit "${COMMIT:-}" \
|
||||
--commit-url "${COMMIT_URL:-}" \
|
||||
--suite-version "${SUITE_VERSION:-unknown}" \
|
||||
--suite-version-url "${SUITE_VERSION_URL:-}" \
|
||||
--suite-path "$SUITE_PATH" \
|
||||
--page-label "$PAGE_LABEL" \
|
||||
--path-err "$HTML_URL_ERR" \
|
||||
--link-other ""
|
||||
rm -rf "$HTML_BASE/$host/${HTML_ERR_DIR}"
|
||||
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" \
|
||||
--mode redirect \
|
||||
--commit "${COMMIT:-}" \
|
||||
--commit-url "${COMMIT_URL:-}" \
|
||||
--suite-version "${SUITE_VERSION:-unknown}" \
|
||||
--suite-version-url "${SUITE_VERSION_URL:-}" \
|
||||
--suite-path "$SUITE_PATH" \
|
||||
--page-label "$PAGE_LABEL" \
|
||||
--path-err "$HTML_URL_ERR"
|
||||
echo "html $host → ${HTML_URL_OK} stub + ${HTML_URL_ERR} (ec=$ec · ${COMMIT_SHORT:-?})"
|
||||
fi
|
||||
else
|
||||
echo "WARN: console_to_html.py missing — bootstrap pages"
|
||||
write_bootstrap_html "$mon_err" "$host" "err"
|
||||
if [ "$ec" -eq 0 ]; then
|
||||
write_bootstrap_html "$mon" "$host" "ok"
|
||||
rm -rf "$HTML_BASE/$host/${HTML_ERR_DIR}"
|
||||
else
|
||||
write_bootstrap_html "$mon" "$host" "redirect"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$mon" ]; then
|
||||
write_bootstrap_html "$mon" "$host" "err"
|
||||
fi
|
||||
|
||||
printf '%s\n' "${COMMIT:-unknown}" >"$HTML_BASE/$host/COMMIT"
|
||||
printf '%s\n' "${COMMIT_URL:-}" >"$HTML_BASE/$host/COMMIT_URL"
|
||||
}
|
||||
for host in $MON_HOSTS; do
|
||||
htmlify_host "$host"
|
||||
echo "public URL (expected): https://${host}${HTML_URL_OK}"
|
||||
done
|
||||
|
||||
# Publish to live web root when possible (v1.3.1+: never silent-skip)
|
||||
if [ -n "$DEPLOY_WWW" ]; then
|
||||
if [ -w "$DEPLOY_WWW" ] 2>/dev/null; then
|
||||
# --delay-updates: write to temp names then rename (less partial-file exposure)
|
||||
if rsync -a --delete --delay-updates "$HTML_BASE/" "$DEPLOY_WWW/"; then
|
||||
echo "synced → $DEPLOY_WWW/ (delay-updates)"
|
||||
# brief settle so concurrent monpages curls do not hit mid-rename FS views
|
||||
sleep "${MONPAGES_PUBLISH_SETTLE_S:-0.3}" 2>/dev/null || sleep 1
|
||||
else
|
||||
echo "ERROR: rsync to DEPLOY_WWW_ROOT=$DEPLOY_WWW failed" >&2
|
||||
ec=1
|
||||
fi
|
||||
elif [ -e "$DEPLOY_WWW" ]; then
|
||||
echo "ERROR: DEPLOY_WWW_ROOT=$DEPLOY_WWW exists but is not writable by $(id -un)" >&2
|
||||
echo " public FQDN pages will stay missing/stale — fix ownership or run:" >&2
|
||||
echo " sudo ${APPLY_MONITORING_LIVE}" >&2
|
||||
ec=1
|
||||
else
|
||||
echo "ERROR: DEPLOY_WWW_ROOT=$DEPLOY_WWW missing — public pages not published" >&2
|
||||
echo " create tree + Caddy handles: sudo ${APPLY_MONITORING_LIVE}" >&2
|
||||
ec=1
|
||||
fi
|
||||
else
|
||||
echo "WARN: DEPLOY_WWW_ROOT empty — skipping live publish (staging only: $HTML_BASE)" >&2
|
||||
fi
|
||||
|
||||
# Post-publish: monpages obligatory (v1.7.6+) — GOA full inventory / FP only FP hosts
|
||||
_monpages_failed=0
|
||||
if [ "${MONPAGES_POSTCHECK:-1}" = "1" ] && [ -x "$ROOT/check_monitoring_pages.sh" ]; then
|
||||
echo "--- monpages post-check (public FQDN, obligatory) ---"
|
||||
export MON_HOSTS HTML_URL_OK HTML_URL_ERR TALER_DOMAIN HTML_OUT HTML_BASE
|
||||
export MONPAGES_STAGING_BASE="${HTML_BASE}"
|
||||
export DEPLOY_WWW_ROOT="${DEPLOY_WWW:-${DEPLOY_WWW_ROOT:-}}"
|
||||
export MONPAGES_REQUIRE_PUBLIC="${MONPAGES_REQUIRE_PUBLIC:-1}"
|
||||
# auto: GOA = all suite mon sites; FP = only FP mon hosts; job paths always included
|
||||
export MONPAGES_INVENTORY="${MONPAGES_INVENTORY:-auto}"
|
||||
# Hard check (not pre-publish soft)
|
||||
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
|
||||
export MONPAGES_PRE_PUBLISH=0
|
||||
if ! bash "$ROOT/check_monitoring_pages.sh"; then
|
||||
echo "ERROR: public monitoring page(s) missing or not suite HTML via FQDN" >&2
|
||||
echo " staging HTML_OUT=${HTML_BASE} · DEPLOY_WWW=${DEPLOY_WWW:-}" >&2
|
||||
ec=1
|
||||
_monpages_failed=1
|
||||
fi
|
||||
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# If public check failed after first HTML write, rewrite pages so sticky bar shows monpages ERRORs
|
||||
if [ "$_monpages_failed" = "1" ]; then
|
||||
echo "--- re-htmlify after monpages failure (include public outage in report) ---"
|
||||
# append marker to log so converter sees ERROR lines if monpages was post-only
|
||||
{
|
||||
echo ""
|
||||
echo "ERROR monpages: public FQDN monitoring HTML missing or merchant JSON code 21"
|
||||
echo "ERROR monpages: fix with sudo ${APPLY_MONITORING_LIVE} (www + Caddy handles)"
|
||||
} >>"$LOG"
|
||||
for host in $MON_HOSTS; do
|
||||
htmlify_host "$host"
|
||||
done
|
||||
fi
|
||||
|
||||
ls -1t "$LOG_DIR"/run-*.log 2>/dev/null | tail -n +30 | xargs rm -f 2>/dev/null || true
|
||||
|
||||
echo "======== done ec=$ec · log=$LOG · ${COMMIT_URL:-} ========"
|
||||
# v1.7.1: default STRICT_EXIT=1 so systemd/timer reflects publish/public failures
|
||||
if [ "${STRICT_EXIT:-1}" = "1" ]; then
|
||||
exit "$ec"
|
||||
fi
|
||||
exit 0
|
||||
51
host-agent/run-surface-monitoring.sh
Executable file
51
host-agent/run-surface-monitoring.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
# run-surface-monitoring.sh — ecosystem surface report (v1.8.0+ simplified)
|
||||
#
|
||||
# Public HTML only on taler.hacktivism.ch:
|
||||
# https://taler.hacktivism.ch/taler-monitoring-surface/
|
||||
# https://taler.hacktivism.ch/taler-monitoring-surface_err/
|
||||
#
|
||||
# This page covers remote ecosystem inventory: host/port probes, nmap OS
|
||||
# fingerprint, Mattermost, mail (firefly + anastasis), package/version signals.
|
||||
# There are NO separate public pages for mail / mattermost (folded here).
|
||||
# Apt-src deploy tests keep their own page + timer:
|
||||
# run-aptdeploy-monitoring.sh → /taler-monitoring-aptdeploy(+_err)/
|
||||
#
|
||||
# Landing-stack reports stay on each of the 9 fronts as /monitoring(/_err).
|
||||
#
|
||||
set -uo pipefail
|
||||
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
export AGENT_LABEL="${AGENT_LABEL:-surface-host-agent}"
|
||||
export STATE_NAME="${STATE_NAME:-taler-surface-monitoring}"
|
||||
export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}"
|
||||
# surface is primarily remote; versions may use host podman when available
|
||||
export INSIDE_PODMAN="${INSIDE_PODMAN:-1}"
|
||||
export LOCAL_STACK="${LOCAL_STACK:-0}"
|
||||
export SKIP_SSH="${SKIP_SSH:-1}"
|
||||
export INSIDE_MODE="${INSIDE_MODE:-local-podman}"
|
||||
export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}"
|
||||
export RUN_TIMEOUT="${RUN_TIMEOUT:-2400}"
|
||||
|
||||
# All ecosystem checks → one surface HTML report (force — do not inherit main-timer env)
|
||||
export PHASES="surface mattermost mail versions monpages"
|
||||
|
||||
export MON_HOSTS="taler.hacktivism.ch"
|
||||
export HTML_OUT="${HTML_OUT:-$HOME/monitoring-sites-staging}"
|
||||
export DEPLOY_WWW_ROOT="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
||||
|
||||
export HTML_OK_DIR="taler-monitoring-surface"
|
||||
export HTML_ERR_DIR="taler-monitoring-surface_err"
|
||||
export HTML_URL_OK="/taler-monitoring-surface/"
|
||||
export HTML_URL_ERR="/taler-monitoring-surface_err/"
|
||||
export PAGE_LABEL="taler-monitoring-surface"
|
||||
|
||||
export SURFACE_SCOPE="${SURFACE_SCOPE:-ecosystem}"
|
||||
export TALER_DOMAIN_FROM_CLI=0
|
||||
export APT_DEPLOY_ENSURE=0
|
||||
# monpages job-only for surface paths on taler.hacktivism.ch
|
||||
export MONPAGES_INVENTORY="job"
|
||||
# package behind → ERROR (v1.8.0)
|
||||
export TALER_PKG_BEHIND="${TALER_PKG_BEHIND:-error}"
|
||||
|
||||
exec bash "$AGENT_DIR/run-host-report.sh" "$@"
|
||||
18
host-agent/taler-monitoring-aptdeploy.service
Normal file
18
host-agent/taler-monitoring-aptdeploy.service
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description=Taler monitoring aptdeploy (apt-src container deploy tests)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
|
||||
Environment=CONTINUE_ON_ERROR=1
|
||||
Environment=RUN_TIMEOUT=1800
|
||||
WorkingDirectory=%h/src/taler-monitoring
|
||||
ExecStart=%h/src/taler-monitoring/host-agent/run-aptdeploy-monitoring.sh
|
||||
Nice=10
|
||||
TimeoutStartSec=45min
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
14
host-agent/taler-monitoring-aptdeploy.timer
Normal file
14
host-agent/taler-monitoring-aptdeploy.timer
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Periodic taler-monitoring aptdeploy (apt-src deploy tests)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
|
||||
[Timer]
|
||||
OnBootSec=35min
|
||||
OnUnitActiveSec=4h
|
||||
AccuracySec=5min
|
||||
Persistent=true
|
||||
RandomizedDelaySec=10min
|
||||
Unit=taler-monitoring-aptdeploy.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
15
host-agent/taler-monitoring-hacktivism.path
Normal file
15
host-agent/taler-monitoring-hacktivism.path
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[Unit]
|
||||
Description=Watch hacktivism software/config changes → re-run monitoring
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
|
||||
[Path]
|
||||
# Explicit stamp after package/image upgrades (touch-software-stamp.sh)
|
||||
# Landing/caddy ops live outside this suite (host admin-log) — touch the stamp there.
|
||||
PathChanged=%h/.local/state/taler-hacktivism-monitoring/software.stamp
|
||||
PathModified=%h/.local/state/taler-hacktivism-monitoring/software.stamp
|
||||
# Debounce: wait for quiet period before firing
|
||||
TriggerLimitIntervalSec=120
|
||||
TriggerLimitBurst=3
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
21
host-agent/taler-monitoring-hacktivism.service
Normal file
21
host-agent/taler-monitoring-hacktivism.service
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[Unit]
|
||||
Description=Taler monitoring GOA/hacktivism (host-podman inside + public urls)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Primary: host can podman-exec into taler-hacktivism* containers
|
||||
Environment=INSIDE_PODMAN=1
|
||||
Environment=CONTINUE_ON_ERROR=1
|
||||
Environment=RUN_TIMEOUT=600
|
||||
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
|
||||
WorkingDirectory=%h/src/taler-monitoring
|
||||
ExecStart=%h/src/taler-monitoring/host-agent/run-hacktivism-monitoring.sh
|
||||
Nice=10
|
||||
# Suite budget is RUN_TIMEOUT (10m) + git/HTML overhead
|
||||
TimeoutStartSec=15min
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
14
host-agent/taler-monitoring-hacktivism.timer
Normal file
14
host-agent/taler-monitoring-hacktivism.timer
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Periodic hacktivism monitoring (fallback if no path events)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
|
||||
[Timer]
|
||||
# Every 4h + boot
|
||||
OnBootSec=10min
|
||||
OnUnitActiveSec=4h
|
||||
AccuracySec=5min
|
||||
Persistent=true
|
||||
Unit=taler-monitoring-hacktivism.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
20
host-agent/taler-monitoring-mytops-stage.service
Normal file
20
host-agent/taler-monitoring-mytops-stage.service
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[Unit]
|
||||
Description=taler-monitoring mytops stage (betel) — auto-update suite + urls/monpages
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Env: ~/.config/taler-monitoring/env (SUITE_GIT_*, MON_HOSTS, PHASES=urls monpages, …)
|
||||
EnvironmentFile=-%h/.config/taler-monitoring/env
|
||||
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
|
||||
Environment=SUITE_UPDATE_STRICT=1
|
||||
WorkingDirectory=%h/src/taler-monitoring
|
||||
# run-host-report sources update-suite.sh first (strict fetch/reset to main)
|
||||
ExecStart=%h/src/taler-monitoring/host-agent/run-host-report.sh
|
||||
Nice=10
|
||||
TimeoutStartSec=20min
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
11
host-agent/taler-monitoring-mytops-stage.timer
Normal file
11
host-agent/taler-monitoring-mytops-stage.timer
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[Unit]
|
||||
Description=taler-monitoring mytops stage (betel) every 4h — suite auto-upgrade + mon HTML
|
||||
|
||||
[Timer]
|
||||
OnBootSec=5min
|
||||
OnUnitActiveSec=4h
|
||||
Persistent=true
|
||||
Unit=taler-monitoring-mytops-stage.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
18
host-agent/taler-monitoring-surface.service
Normal file
18
host-agent/taler-monitoring-surface.service
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description=Taler monitoring surface (remote ecosystem inventory)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
|
||||
Environment=CONTINUE_ON_ERROR=1
|
||||
Environment=RUN_TIMEOUT=2400
|
||||
WorkingDirectory=%h/src/taler-monitoring
|
||||
ExecStart=%h/src/taler-monitoring/host-agent/run-surface-monitoring.sh
|
||||
Nice=10
|
||||
TimeoutStartSec=50min
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
14
host-agent/taler-monitoring-surface.timer
Normal file
14
host-agent/taler-monitoring-surface.timer
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Hourly taler-monitoring surface scan (ecosystem)
|
||||
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||
|
||||
[Timer]
|
||||
OnBootSec=20min
|
||||
OnUnitActiveSec=1h
|
||||
AccuracySec=2min
|
||||
Persistent=true
|
||||
RandomizedDelaySec=5min
|
||||
Unit=taler-monitoring-surface.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
17
host-agent/touch-software-stamp.sh
Executable file
17
host-agent/touch-software-stamp.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
# Call after upgrading hacktivism packages / redeploying landings / image rebuilds.
|
||||
# systemd path unit watches this stamp → re-runs monitoring.
|
||||
set -euo pipefail
|
||||
STATE="${XDG_STATE_HOME:-$HOME/.local/state}/taler-hacktivism-monitoring"
|
||||
mkdir -p "$STATE"
|
||||
STAMP="$STATE/software.stamp"
|
||||
date -Iseconds >"$STAMP"
|
||||
# also record container image ids for debugging
|
||||
if command -v podman >/dev/null 2>&1; then
|
||||
{
|
||||
echo "# images $(date -Iseconds)"
|
||||
podman images --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Digest}}' 2>/dev/null | grep -i hacktivism || true
|
||||
podman ps --format '{{.Names}} {{.ImageID}} {{.Status}}' 2>/dev/null | grep -i hacktivism || true
|
||||
} >"$STATE/software-images.txt" || true
|
||||
fi
|
||||
echo "touched $STAMP"
|
||||
132
host-agent/update-suite.sh
Executable file
132
host-agent/update-suite.sh
Executable file
|
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/env bash
|
||||
# update-suite.sh — pull latest taler-monitoring from Forgejo (standalone repo root).
|
||||
#
|
||||
# Sourced by run-host-report.sh / wrappers. Every host-agent run must land on
|
||||
# current origin/$SUITE_GIT_REF (default main). Stale clones are not acceptable.
|
||||
#
|
||||
# Env:
|
||||
# SUITE_GIT_URL default https://git.hacktivism.ch/hernani/taler-monitoring.git
|
||||
# SUITE_GIT_REF default main
|
||||
# SUITE_DIR default ~/src/taler-monitoring
|
||||
# SUITE_UPDATE_MODE reset (default) | pull
|
||||
# SUITE_UPDATE_STRICT 1 (default) = fetch/reset failure aborts the agent run
|
||||
# 0 = warn and continue on old tree (emergency only)
|
||||
#
|
||||
set -uo pipefail
|
||||
CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/taler-monitoring"
|
||||
ENV_FILE="${TALER_MONITORING_ENV:-$CFG_DIR/env}"
|
||||
if [ -f "$ENV_FILE" ] && [ "${_TALER_MON_ENV_LOADED:-0}" != "1" ]; then
|
||||
set -a; source "$ENV_FILE"; set +a
|
||||
fi
|
||||
SUITE_GIT_URL="${SUITE_GIT_URL:-https://git.hacktivism.ch/hernani/taler-monitoring.git}"
|
||||
SUITE_GIT_REF="${SUITE_GIT_REF:-main}"
|
||||
SUITE_UPDATE_MODE="${SUITE_UPDATE_MODE:-reset}"
|
||||
SUITE_UPDATE_STRICT="${SUITE_UPDATE_STRICT:-1}"
|
||||
if [ -z "${SUITE_DIR:-}" ]; then
|
||||
if [ -d "$HOME/src/taler-monitoring/.git" ]; then SUITE_DIR="$HOME/src/taler-monitoring"
|
||||
elif [ -d "$HOME/taler-monitoring/.git" ]; then SUITE_DIR="$HOME/taler-monitoring"
|
||||
else SUITE_DIR="$HOME/src/taler-monitoring"; fi
|
||||
fi
|
||||
export SUITE_DIR
|
||||
|
||||
_upd_die() {
|
||||
echo "ERROR suite-update: $*" >&2
|
||||
if [ "${SUITE_UPDATE_STRICT}" = "1" ]; then
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
echo "WARN suite-update: continuing on existing tree (SUITE_UPDATE_STRICT=0)" >&2
|
||||
return 0
|
||||
}
|
||||
|
||||
mkdir -p "$(dirname "$SUITE_DIR")" "$CFG_DIR"
|
||||
if [ ! -d "$SUITE_DIR/.git" ]; then
|
||||
echo "clone $SUITE_GIT_URL → $SUITE_DIR"
|
||||
if ! git clone --branch "$SUITE_GIT_REF" "$SUITE_GIT_URL" "$SUITE_DIR" \
|
||||
&& ! git clone "$SUITE_GIT_URL" "$SUITE_DIR"; then
|
||||
_upd_die "git clone failed"
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
fi
|
||||
cd "$SUITE_DIR" || { _upd_die "cd $SUITE_DIR failed"; return 1 2>/dev/null || exit 1; }
|
||||
git remote set-url origin "$SUITE_GIT_URL" 2>/dev/null || true
|
||||
|
||||
_before=$(git rev-parse --short=12 HEAD 2>/dev/null || echo none)
|
||||
_before_ver=$(git describe --tags --exact-match 2>/dev/null \
|
||||
|| git describe --tags --abbrev=0 2>/dev/null \
|
||||
|| echo unknown)
|
||||
|
||||
echo "fetch origin ($SUITE_GIT_REF) + tags …"
|
||||
if ! git fetch --tags --force --prune origin 2>&1; then
|
||||
_upd_die "git fetch failed — suite would stay at ${_before} (${_before_ver})"
|
||||
# fall through only if STRICT=0
|
||||
else
|
||||
case "$SUITE_UPDATE_MODE" in
|
||||
reset)
|
||||
if ! git checkout -B "$SUITE_GIT_REF" "origin/$SUITE_GIT_REF" 2>/dev/null \
|
||||
&& ! git checkout -B "$SUITE_GIT_REF" FETCH_HEAD; then
|
||||
_upd_die "git checkout $SUITE_GIT_REF failed"
|
||||
fi
|
||||
if ! git reset --hard "origin/$SUITE_GIT_REF" 2>/dev/null \
|
||||
&& ! git reset --hard FETCH_HEAD; then
|
||||
_upd_die "git reset --hard origin/$SUITE_GIT_REF failed"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if ! git pull --ff-only origin "$SUITE_GIT_REF" 2>&1; then
|
||||
_upd_die "git pull --ff-only failed"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
COMMIT=$(git rev-parse HEAD)
|
||||
COMMIT_SHORT=$(git rev-parse --short=12 HEAD)
|
||||
SOURCE_REPO_WEB="${SOURCE_REPO_WEB:-https://git.hacktivism.ch/hernani/taler-monitoring}"
|
||||
COMMIT_URL="${SOURCE_REPO_WEB}/src/commit/${COMMIT}"
|
||||
export COMMIT COMMIT_SHORT COMMIT_URL SOURCE_REPO_WEB
|
||||
|
||||
# Release tag for sticky bar (exact tag if HEAD is tagged, else nearest)
|
||||
SUITE_VERSION=""
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
SUITE_VERSION=$(git describe --tags --exact-match 2>/dev/null || true)
|
||||
if [ -z "$SUITE_VERSION" ]; then
|
||||
SUITE_VERSION=$(git describe --tags --abbrev=0 2>/dev/null || true)
|
||||
fi
|
||||
fi
|
||||
if [ -z "$SUITE_VERSION" ] && [ -f "$SUITE_DIR/VERSION" ]; then
|
||||
SUITE_VERSION="v$(tr -d '[:space:]' <"$SUITE_DIR/VERSION" | sed 's/^v//')"
|
||||
fi
|
||||
[ -z "$SUITE_VERSION" ] && SUITE_VERSION="unknown"
|
||||
case "$SUITE_VERSION" in
|
||||
unknown|v*) ;;
|
||||
*) SUITE_VERSION="v${SUITE_VERSION}" ;;
|
||||
esac
|
||||
# Sticky version badge: prefer commit URL (exact tree of this run).
|
||||
# Tag URLs (/src/tag/vX.Y.Z) 404 when the tag is not yet pushed to Forgejo;
|
||||
# commit URLs work as soon as main (or the tree) is on the remote.
|
||||
SUITE_VERSION_URL=""
|
||||
if [ -n "$SOURCE_REPO_WEB" ] && [ -n "${COMMIT:-}" ] && [ "$COMMIT" != "unknown" ]; then
|
||||
SUITE_VERSION_URL="${SOURCE_REPO_WEB}/src/commit/${COMMIT}"
|
||||
elif [ -n "$SOURCE_REPO_WEB" ] && [ "$SUITE_VERSION" != "unknown" ]; then
|
||||
SUITE_VERSION_URL="${SOURCE_REPO_WEB}/src/tag/${SUITE_VERSION}"
|
||||
fi
|
||||
export SUITE_VERSION SUITE_VERSION_URL
|
||||
|
||||
if [ "$_before" != "$COMMIT_SHORT" ]; then
|
||||
echo " upgraded ${_before} (${_before_ver}) → ${COMMIT_SHORT} (${SUITE_VERSION})"
|
||||
else
|
||||
echo " already at ${COMMIT_SHORT} (${SUITE_VERSION})"
|
||||
fi
|
||||
echo " version=$SUITE_VERSION ${SUITE_VERSION_URL:+· $SUITE_VERSION_URL}"
|
||||
echo "suite @ $COMMIT_SHORT $COMMIT_URL"
|
||||
echo " dir=$SUITE_DIR"
|
||||
|
||||
# Sanity: must have suite entrypoint after update
|
||||
if [ ! -x "$SUITE_DIR/taler-monitoring.sh" ] && [ ! -f "$SUITE_DIR/taler-monitoring.sh" ]; then
|
||||
_upd_die "taler-monitoring.sh missing after update"
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
|
||||
ln -sfn "$SUITE_DIR" "$HOME/taler-monitoring" 2>/dev/null || true
|
||||
chmod +x taler-monitoring.sh check_*.sh host-agent/*.sh site-gen/*.sh site-gen/*.py 2>/dev/null || true
|
||||
return 0 2>/dev/null || true
|
||||
Loading…
Add table
Add a link
Reference in a new issue