#!/usr/bin/env bash # Landscape Program (ЛП) end-to-end check on the acceptance stand: # 1. lp_gen.py — 13 synthetic input rasters (default 3000 x 2000) # 2. upload — POST /landscape/slots/{code} for the 13 slots # 3. run — POST /landscape/runs {"from_stage":0}, wait for it # 4. lp_verify.py — pixel-by-pixel check of all 15 outputs (mode a) # # test/acceptance/lp_run.sh # BASE_URL defaults to http://localhost:18080 # LP_WIDTH=6000 LP_HEIGHT=4000 test/acceptance/lp_run.sh # # The uploaded inputs and the run's outputs are left in place so the run can be # re-verified later (python lp_verify.py --run ); they are ordinary datasets # of the "landscape" category. WRITES to the stand: never point it at production. set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" BASE_URL="${BASE_URL:-http://localhost:18080}" BASE_URL="${BASE_URL%/}" PYTHON="${PYTHON:-python3}" WAIT_TIMEOUT="${WAIT_TIMEOUT:-600}" LP_WIDTH="${LP_WIDTH:-3000}" LP_HEIGHT="${LP_HEIGHT:-2000}" case "$BASE_URL" in *dssgis.dwh.kz*) echo "refusing to write to $BASE_URL (production); use lp_verify.py for read-only checks" >&2; exit 2;; esac TMP="$(mktemp -d "${TMPDIR:-/tmp}/gis-lp.XXXXXX")" trap 'rm -rf "$TMP"' EXIT STAMP="$(date +%Y%m%d-%H%M%S)" SLOTS="lp-z-biodiversity lp-z-lcr lp-z-soil-protection lp-z-wr lp-u-surf-water lp-u-soil lp-u-crop lp-u-veg lp-p-irrigation lp-p-snow lp-p-crop lp-p-pasture lp-p-tourism" echo "== 1. generate inputs (${LP_WIDTH}x${LP_HEIGHT})" "$PYTHON" "$HERE/lp_gen.py" --out "$TMP/in" --width "$LP_WIDTH" --height "$LP_HEIGHT" echo "== 2. upload into 13 slots ($BASE_URL)" ids="" for s in $SLOTS; do out="$(curl -sS -w ' %{http_code}' -X POST "$BASE_URL/landscape/slots/$s" -F "file=@$TMP/in/$s.tif" \ -F "name=ЛП приёмка $s $STAMP" -F start_date=2025-01-01 -F end_date=2025-12-31)" code="${out##* }"; body="${out% *}" [ "$code" = 201 ] || { echo "upload $s failed: HTTP $code $body" >&2; exit 1; } id="$(jq -r .id <<< "$body")"; ids="$ids $id" printf ' %-22s %s HTTP %s\n' "$s" "$id" "$code" done for id in $ids; do deadline=$(( $(date +%s) + WAIT_TIMEOUT )) until [ "$(curl -sS "$BASE_URL/datasets/$id" | jq -r .status)" = ready ]; do [ "$(date +%s)" -lt "$deadline" ] || { echo "dataset $id not ready" >&2; exit 1; } sleep 1 done done echo " all 13 inputs ready" echo "== 3. run {\"from_stage\":0}" run="$(curl -sS -X POST "$BASE_URL/landscape/runs" -H 'Content-Type: application/json' -d '{"from_stage":0}')" RUN="$(jq -r .id <<< "$run")" [ -n "$RUN" ] && [ "$RUN" != null ] || { echo "run not created: $run" >&2; exit 1; } echo " run $RUN queued" deadline=$(( $(date +%s) + WAIT_TIMEOUT )) while :; do st="$(curl -sS "$BASE_URL/landscape/runs/$RUN" | jq -r .status)" case "$st" in succeeded|failed) break;; esac [ "$(date +%s)" -lt "$deadline" ] || { echo "run $RUN still $st" >&2; exit 1; } sleep 1 done curl -sS "$BASE_URL/landscape/runs/$RUN" > "$TMP/run.json" echo " run $RUN $st: $(jq -r '[.nodes[] | "\(.node_code):\(.status)"] | sort | join(" ")' "$TMP/run.json")" "$PYTHON" "$HERE/lib/helpers.py" durations "$TMP/run.json" | sed 's/^/ /' [ "$st" = succeeded ] || { echo "run failed: $(jq -r .error "$TMP/run.json")" >&2; exit 1; } echo "== 4. lp_verify.py --base-url $BASE_URL --run $RUN" "$PYTHON" "$HERE/lp_verify.py" --base-url "$BASE_URL" --run "$RUN" --cache "$TMP/cache"