#!/usr/bin/env bash # start.sh — pornire gateway RAR AUTOPASS (api / worker) pe mediu test sau prod. # # Exemple: # ./start.sh test api # API pe :8010, mediu test # ./start.sh test worker --send # worker care TRIMITE la RAR test (creds din settings.xml) # ./start.sh test both --send # API + worker impreuna (dev end-to-end) # ./start.sh prod api --port 8010 # API mediu prod # ./start.sh prod worker --send # worker prod (NU foloseste creds de test) # ./start.sh status # stare procese + /healthz # ./start.sh stop # opreste procesele pornite cu "both" # ./start.sh test finalizate # ce prezentari sunt inregistrate la RAR (au ajuns?) # # Pentru productie reala se recomanda docker compose (vezi docker-compose.yml). # start.sh e pentru rulare directa pe VPS/LXC sau dezvoltare locala. set -euo pipefail cd "$(dirname "$0")" # --- valori implicite --- PORT=8010 HOST=0.0.0.0 RELOAD=0 SEND=0 USE_TEST_CREDS="auto" # auto: pornit doar pe mediul test cand --send e activ RUN_DIR=".run" PY=python3 usage() { sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//' exit "${1:-0}" } # --- citeste .env daca exista (AUTOPASS_CREDS_KEY etc.) --- if [ -f .env ]; then set -a; . ./.env; set +a fi # --- parsare argumente: env si rol = pozitionale; restul = flag-uri --- ENVIRONMENT="" ROLE="" POSITIONAL=() while [ $# -gt 0 ]; do case "$1" in --port) PORT="$2"; shift 2 ;; --host) HOST="$2"; shift 2 ;; --reload) RELOAD=1; shift ;; --send) SEND=1; shift ;; --test-creds) USE_TEST_CREDS="true"; shift ;; --no-test-creds) USE_TEST_CREDS="false"; shift ;; -h|--help) usage 0 ;; -*) echo "Optiune necunoscuta: $1" >&2; usage 1 ;; *) POSITIONAL+=("$1"); shift ;; esac done # Comenzi fara mediu (stop/status accepta lipsa mediului). case "${POSITIONAL[0]:-}" in stop|status) ROLE="${POSITIONAL[0]}" ;; test|prod) ENVIRONMENT="${POSITIONAL[0]}" ROLE="${POSITIONAL[1]:-}" ;; "") usage 1 ;; *) echo "Mediu invalid: ${POSITIONAL[0]} (asteptat: test | prod | stop | status)" >&2 usage 1 ;; esac mkdir -p "$RUN_DIR" # --- helperi --- ensure_creds_key() { # API cripteaza creds RAR, worker le decripteaza: trebuie ACEEASI cheie. # Daca ruleaza ambele din aceeasi invocare (both), o cheie efemera exportata # acum e partajata de copii. Daca lipseste si rulezi separat, avertizeaza. if [ -z "${AUTOPASS_CREDS_KEY:-}" ]; then if [ "$ROLE" = "both" ]; then AUTOPASS_CREDS_KEY="$($PY -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" export AUTOPASS_CREDS_KEY echo "[start] AUTOPASS_CREDS_KEY negasita -> cheie efemera generata pentru aceasta rulare." echo "[start] (Nu supravietuieste restartului. Pune o cheie persistenta in .env pentru prod.)" else echo "[start] ATENTIE: AUTOPASS_CREDS_KEY nesetata. API si worker pornite SEPARAT vor folosi" echo "[start] chei diferite -> worker-ul NU poate decripta creds-urile. Seteaz-o in .env." fi fi } export_common() { export AUTOPASS_RAR_ENV="$ENVIRONMENT" # use_test_creds: auto -> true doar pe test cand trimitem local utc="$USE_TEST_CREDS" if [ "$utc" = "auto" ]; then if [ "$ENVIRONMENT" = "test" ] && [ "$SEND" -eq 1 ]; then utc="true"; else utc="false"; fi fi export AUTOPASS_WORKER_USE_TEST_CREDS="$utc" if [ "$SEND" -eq 1 ]; then export AUTOPASS_WORKER_SEND_ENABLED="true" else export AUTOPASS_WORKER_SEND_ENABLED="${AUTOPASS_WORKER_SEND_ENABLED:-false}" fi } start_api() { local args=(uvicorn app.main:app --host "$HOST" --port "$PORT") [ "$RELOAD" -eq 1 ] && args+=(--reload) echo "[start] API ($ENVIRONMENT) -> http://$HOST:$PORT (docs: /docs, dashboard: /)" exec "$PY" -m "${args[@]}" } start_worker() { echo "[start] worker ($ENVIRONMENT) send_enabled=$AUTOPASS_WORKER_SEND_ENABLED use_test_creds=$AUTOPASS_WORKER_USE_TEST_CREDS" [ "$AUTOPASS_WORKER_SEND_ENABLED" = "true" ] || \ echo "[start] NOTA: send dezactivat — worker proceseaza coada dar NU trimite la RAR. Adauga --send." exec "$PY" -m app.worker } start_both() { local alog="$RUN_DIR/api.log" wlog="$RUN_DIR/worker.log" echo "[start] API + worker ($ENVIRONMENT). Loguri: $alog , $wlog. Ctrl-C opreste ambele." "$PY" -m uvicorn app.main:app --host "$HOST" --port "$PORT" >"$alog" 2>&1 & echo $! > "$RUN_DIR/api.pid" "$PY" -m app.worker >"$wlog" 2>&1 & echo $! > "$RUN_DIR/worker.pid" trap 'echo; echo "[start] opresc..."; kill $(cat "$RUN_DIR"/*.pid 2>/dev/null) 2>/dev/null || true; exit 0' INT TERM echo "[start] API pid $(cat "$RUN_DIR/api.pid"), worker pid $(cat "$RUN_DIR/worker.pid")" tail -n +1 -f "$alog" "$wlog" } cmd_stop() { local killed=0 for f in "$RUN_DIR"/api.pid "$RUN_DIR"/worker.pid; do [ -f "$f" ] || continue local pid; pid="$(cat "$f")" if kill "$pid" 2>/dev/null; then echo "[stop] oprit pid $pid ($(basename "$f"))"; killed=1; fi rm -f "$f" done [ "$killed" -eq 1 ] || echo "[stop] niciun proces urmarit (.run/*.pid)." } cmd_status() { for f in "$RUN_DIR"/api.pid "$RUN_DIR"/worker.pid; do [ -f "$f" ] || continue local pid; pid="$(cat "$f")" if kill -0 "$pid" 2>/dev/null; then echo "[status] $(basename "$f" .pid): pid $pid VIU" else echo "[status] $(basename "$f" .pid): pid $pid MORT"; fi done echo "[status] /healthz:" curl -s "http://localhost:$PORT/healthz" 2>/dev/null | "$PY" -m json.tool 2>/dev/null \ || echo " (API nu raspunde pe :$PORT)" } # --- dispatch --- case "$ROLE" in api) ensure_creds_key; export_common; start_api ;; worker) ensure_creds_key; export_common; start_worker ;; both) ensure_creds_key; export_common; start_both ;; finalizate) export AUTOPASS_RAR_ENV="$ENVIRONMENT"; exec "$PY" -m tools.rar_finalizate ;; stop) cmd_stop ;; status) cmd_status ;; "") echo "Lipseste rolul (api|worker|both|finalizate)" >&2; usage 1 ;; *) echo "Rol invalid: $ROLE" >&2; usage 1 ;; esac