574 lines
23 KiB
Bash
574 lines
23 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# DIDI Platform - Full Build From Scratch
|
|
# =============================================================================
|
|
# Ridica intreaga platforma de la zero.
|
|
# Ordinea: network -> data-layer -> production (redis, keycloak, kong) ->
|
|
# framework (sync redis) -> agent-v3 + workers -> admin dashboard
|
|
#
|
|
# Cerinte: docker, docker compose v2+, conexiune la PG cluster 10.11.50.167:5000
|
|
# Rulare: chmod +x full-build.sh && ./full-build.sh [HOSTNAME]
|
|
# Exemplu: ./full-build.sh <hostname>
|
|
# ./full-build.sh didi365.eu
|
|
# Daca nu specifici hostname, il detecteaza automat din hostname -f.
|
|
# =============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# -- Hostname ---------------------------------------------------------------
|
|
if [ -n "${1:-}" ]; then
|
|
PLATFORM_HOSTNAME="$1"
|
|
else
|
|
PLATFORM_HOSTNAME=$(hostname -f 2>/dev/null || hostname)
|
|
fi
|
|
|
|
# -- Culori ----------------------------------------------------------------
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
|
|
|
# -- Paths -----------------------------------------------------------------
|
|
BACKEND="/home/admin365/didi_mono/backend"
|
|
DATA_LAYER="$BACKEND/services/data-layer"
|
|
PRODUCTION="$BACKEND/production"
|
|
FRAMEWORK="$BACKEND/services/orchestration-layer/didiFramework"
|
|
AGENT_V3="$BACKEND/services/orchestration-layer/agent-v3"
|
|
KONG_DIR="$BACKEND/services/gateway-auth-layer/didiKong"
|
|
|
|
# -- Conexiune PG cluster --------------------------------------------------
|
|
PG_HOST="10.11.50.167"
|
|
PG_PORT="5000"
|
|
PG_USER="bos_interface"
|
|
PG_PASS="interface"
|
|
PG_DB="DIDI"
|
|
|
|
# -- Functii helper ---------------------------------------------------------
|
|
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $*"; }
|
|
ok() { echo -e "${GREEN} OK${NC} $*"; }
|
|
warn() { echo -e "${YELLOW} WARN${NC} $*"; }
|
|
fail() { echo -e "${RED} FAIL${NC} $*"; exit 1; }
|
|
|
|
wait_healthy() {
|
|
local container="$1"
|
|
local max_wait="${2:-120}"
|
|
local elapsed=0
|
|
log "Astept container $container sa fie healthy (max ${max_wait}s)..."
|
|
while [ $elapsed -lt $max_wait ]; do
|
|
local status
|
|
status=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "missing")
|
|
if [ "$status" = "healthy" ]; then
|
|
ok "$container este healthy"
|
|
return 0
|
|
fi
|
|
sleep 3
|
|
elapsed=$((elapsed + 3))
|
|
done
|
|
warn "$container nu a devenit healthy in ${max_wait}s (status: $status)"
|
|
return 1
|
|
}
|
|
|
|
pg_query() {
|
|
# Executa query PG prin orice container care are psql/node disponibil
|
|
local query="$1"
|
|
if docker ps --format '{{.Names}}' | grep -q staging-dataLayer-postgres; then
|
|
docker exec -e PGPASSWORD="$PG_PASS" staging-dataLayer-postgres \
|
|
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -tAc "$query" 2>/dev/null
|
|
elif docker ps --format '{{.Names}}' | grep -q didi-framework; then
|
|
docker exec didi-framework node -e "
|
|
const {Pool}=require('pg');
|
|
const p=new Pool({host:'$PG_HOST',port:$PG_PORT,database:'$PG_DB',user:'$PG_USER',password:'$PG_PASS'});
|
|
p.query(\`$query\`).then(r=>{r.rows.forEach(row=>console.log(Object.values(row).join('|')));p.end()}).catch(e=>{console.error(e.message);p.end();process.exit(1)});
|
|
" 2>/dev/null
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
section() {
|
|
echo ""
|
|
echo -e "${YELLOW}====================================================================${NC}"
|
|
echo -e "${YELLOW} $*${NC}"
|
|
echo -e "${YELLOW}====================================================================${NC}"
|
|
}
|
|
|
|
# =============================================================================
|
|
section "FAZA 0: Verificari preliminare"
|
|
# =============================================================================
|
|
|
|
log "Verific docker..."
|
|
docker info >/dev/null 2>&1 || fail "Docker nu ruleaza"
|
|
ok "Docker activ"
|
|
|
|
log "Verific docker compose..."
|
|
docker compose version >/dev/null 2>&1 || fail "Docker Compose v2 nu este instalat"
|
|
ok "Docker Compose disponibil"
|
|
|
|
# =============================================================================
|
|
section "FAZA 1: Docker Network"
|
|
# =============================================================================
|
|
|
|
log "Creez reteaua didi-network (daca nu exista)..."
|
|
docker network create didi-network 2>/dev/null && ok "Retea creata" || ok "Reteaua exista deja"
|
|
|
|
# =============================================================================
|
|
section "FAZA 2: Data Layer (PostgreSQL local, RabbitMQ, MinIO, PgAdmin)"
|
|
# =============================================================================
|
|
|
|
log "Verific daca volumele externe exista..."
|
|
for vol in didi-staging-postgres-data didi-staging-minio-data didi-staging-pgadmin-data; do
|
|
docker volume inspect "$vol" >/dev/null 2>&1 && ok "Volum $vol exista" || {
|
|
log "Creez volum $vol..."
|
|
docker volume create "$vol"
|
|
ok "Volum $vol creat"
|
|
}
|
|
done
|
|
|
|
log "Build + start data-layer..."
|
|
cd "$DATA_LAYER"
|
|
|
|
# Nota: containerul PG local este doar pentru waitlist.
|
|
# Baza de date principala (DIDI) este pe clusterul extern 10.11.50.167:5000.
|
|
# Dockerfile-ul custom necesita init.sql + health-check.sh care nu sunt in git (*.sql in .gitignore).
|
|
# Daca Dockerfile exista SI init.sql e fisier (nu director gol), build custom; altfel, skip.
|
|
if [ -f didiDatabase/Dockerfile ] && [ -f didiDatabase/init.sql ]; then
|
|
log "Build imagine didi-staging-postgres..."
|
|
docker build -t didi-staging-postgres:latest didiDatabase/ 2>&1 | tail -3
|
|
ok "Imagine postgres construita"
|
|
else
|
|
log "Skip build custom PG (init.sql lipseste). Se foloseste imaginea standard postgres:15-alpine."
|
|
fi
|
|
|
|
docker compose up -d --build 2>&1 | tail -5
|
|
ok "Data layer pornit"
|
|
|
|
# Astept serviciile critice
|
|
wait_healthy staging-dataLayer-rabbitmq 90
|
|
wait_healthy staging-dataLayer-minio 60
|
|
|
|
# =============================================================================
|
|
section "FAZA 3: Verificare PostgreSQL Cluster extern"
|
|
# =============================================================================
|
|
|
|
log "Testez conexiunea la PG cluster $PG_HOST:$PG_PORT..."
|
|
|
|
# Astept sa avem un container cu psql sau node
|
|
sleep 5
|
|
|
|
SCHEMA_COUNT=$(pg_query "SELECT count(*) FROM information_schema.schemata WHERE schema_name IN ('bos_analysis','bos_parammgmt','bos_sysadmin','bos_subscriber')" 2>/dev/null || echo "0")
|
|
|
|
if [ "$SCHEMA_COUNT" = "4" ]; then
|
|
ok "Toate 4 schemele exista in PG cluster — nu ating nimic"
|
|
elif [ "$SCHEMA_COUNT" = "0" ]; then
|
|
warn "ZERO scheme bos_* gasite — baza DIDI este goala"
|
|
|
|
# Caut exportul complet
|
|
DIDI_EXPORT=""
|
|
for candidate in \
|
|
"$BACKEND/services/data-layer/didiDatabase/DIDI_full_export_2026-07-02.sql" \
|
|
"$BACKEND/services/data-layer/didiDatabase"/DIDI_full_export_*.sql; do
|
|
if [ -f "$candidate" ]; then
|
|
DIDI_EXPORT="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "$DIDI_EXPORT" ]; then
|
|
EXPORT_SIZE=$(du -h "$DIDI_EXPORT" | cut -f1)
|
|
log "Gasit export: $DIDI_EXPORT ($EXPORT_SIZE)"
|
|
log "Baza este GOALA (0 scheme). Import exportul complet..."
|
|
|
|
# Astept container-ul postgres local sa fie up (are psql)
|
|
wait_healthy staging-dataLayer-postgres 60 || true
|
|
|
|
# Copiez fisierul in container si import prin psql
|
|
docker cp "$DIDI_EXPORT" staging-dataLayer-postgres:/tmp/didi_import.sql
|
|
docker exec -e PGPASSWORD="$PG_PASS" staging-dataLayer-postgres \
|
|
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" \
|
|
-f /tmp/didi_import.sql 2>&1 | tail -20
|
|
|
|
# Verificare post-import
|
|
SCHEMA_COUNT_POST=$(pg_query "SELECT count(*) FROM information_schema.schemata WHERE schema_name IN ('bos_analysis','bos_parammgmt','bos_sysadmin','bos_subscriber')" 2>/dev/null || echo "0")
|
|
if [ "$SCHEMA_COUNT_POST" = "4" ]; then
|
|
ok "Import reusit — toate 4 schemele exista acum"
|
|
else
|
|
fail "Import esuat — doar $SCHEMA_COUNT_POST/4 scheme dupa import"
|
|
fi
|
|
|
|
# Cleanup
|
|
docker exec staging-dataLayer-postgres rm -f /tmp/didi_import.sql
|
|
else
|
|
warn "Nu gasesc fisier DIDI_full_export_*.sql in $BACKEND/services/data-layer/didiDatabase/"
|
|
warn "Baza DIDI este goala si nu pot importa automat."
|
|
read -p "Continui fara baza de date? (y/N): " answer
|
|
[ "$answer" = "y" ] || [ "$answer" = "Y" ] || exit 1
|
|
fi
|
|
else
|
|
warn "Gasit $SCHEMA_COUNT/4 scheme (partial). Nu ating — nu e gol, dar nici complet."
|
|
pg_query "SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'bos_%' ORDER BY 1" || true
|
|
echo ""
|
|
warn "Verifica manual ce lipseste. Importul automat ruleaza DOAR pe baza complet goala."
|
|
read -p "Continui oricum? (y/N): " answer
|
|
[ "$answer" = "y" ] || [ "$answer" = "Y" ] || exit 1
|
|
fi
|
|
|
|
# Verific tabelele critice per schema
|
|
log "Verific tabele critice..."
|
|
|
|
CRITICAL_TABLES=(
|
|
"bos_analysis|analysis_session"
|
|
"bos_analysis|analysis_verdict"
|
|
"bos_parammgmt|dimension"
|
|
"bos_parammgmt|technique"
|
|
"bos_parammgmt|verdict_category"
|
|
"bos_parammgmt|component_weight"
|
|
"bos_parammgmt|component_config"
|
|
"bos_parammgmt|input_type_profile"
|
|
"bos_sysadmin|internet_user"
|
|
"bos_sysadmin|user_credential"
|
|
"bos_sysadmin|subscription_plan"
|
|
)
|
|
|
|
MISSING=0
|
|
for entry in "${CRITICAL_TABLES[@]}"; do
|
|
schema="${entry%%|*}"
|
|
table="${entry##*|}"
|
|
EXISTS=$(pg_query "SELECT count(*) FROM information_schema.tables WHERE table_schema='$schema' AND table_name='$table'" 2>/dev/null || echo "0")
|
|
if [ "$EXISTS" = "1" ]; then
|
|
ok " $schema.$table"
|
|
else
|
|
warn " LIPSA: $schema.$table"
|
|
MISSING=$((MISSING + 1))
|
|
fi
|
|
done
|
|
|
|
if [ "$MISSING" -gt 0 ]; then
|
|
warn "$MISSING tabele critice lipsa. Migrari necesare."
|
|
fi
|
|
|
|
# =============================================================================
|
|
section "FAZA 4: Production Services (Redis, Keycloak, Kong)"
|
|
# =============================================================================
|
|
|
|
cd "$PRODUCTION"
|
|
|
|
# -- Seteaza KC_HOSTNAME_URL in .env pe baza hostname-ului platformei --------
|
|
log "Configurez Keycloak hostname: $PLATFORM_HOSTNAME"
|
|
if grep -q "^KC_HOSTNAME_URL=" .env 2>/dev/null; then
|
|
sed -i "s|^KC_HOSTNAME_URL=.*|KC_HOSTNAME_URL=https://${PLATFORM_HOSTNAME}/auth|" .env
|
|
ok "KC_HOSTNAME_URL actualizat in .env"
|
|
else
|
|
echo "KC_HOSTNAME_URL=https://${PLATFORM_HOSTNAME}/auth" >> .env
|
|
ok "KC_HOSTNAME_URL adaugat in .env"
|
|
fi
|
|
|
|
log "Start Redis + Keycloak + Kong..."
|
|
docker compose up -d --build 2>&1 | tail -5
|
|
ok "Production services pornite"
|
|
|
|
wait_healthy didi-cache 30
|
|
|
|
log "Verific conexiunea Redis..."
|
|
REDIS_PONG=$(docker exec didi-cache redis-cli -a redis123 ping 2>/dev/null || echo "FAIL")
|
|
if [ "$REDIS_PONG" = "PONG" ]; then
|
|
ok "Redis raspunde"
|
|
else
|
|
warn "Redis nu raspunde: $REDIS_PONG"
|
|
fi
|
|
|
|
wait_healthy keycloak 180
|
|
wait_healthy kong 90
|
|
|
|
# -- Configurare Keycloak redirect URIs via Admin API -----------------------
|
|
section "FAZA 4b: Keycloak - Configurare redirect URIs pentru $PLATFORM_HOSTNAME"
|
|
|
|
log "Obtin token admin Keycloak..."
|
|
KC_ADMIN_USER=$(grep "^KEYCLOAK_ADMIN=" .env | cut -d= -f2-)
|
|
KC_ADMIN_PASS=$(grep "^KEYCLOAK_ADMIN_PASSWORD=" .env | cut -d= -f2-)
|
|
|
|
KC_TOKEN=$(curl -s -X POST "http://localhost:28000/realms/master/protocol/openid-connect/token" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "username=${KC_ADMIN_USER}" -d "password=${KC_ADMIN_PASS}" \
|
|
-d "grant_type=password" -d "client_id=admin-cli" 2>/dev/null \
|
|
| python3 -c "import sys,json;print(json.load(sys.stdin).get('access_token',''))" 2>/dev/null || echo "")
|
|
|
|
if [ -z "$KC_TOKEN" ]; then
|
|
warn "Nu am obtinut token admin Keycloak. Redirect URIs trebuie configurate manual."
|
|
else
|
|
ok "Token admin obtinut"
|
|
|
|
# Configureaza didi-web-app
|
|
log "Configurez client didi-web-app..."
|
|
WEB_CLIENT_UUID=$(curl -s "http://localhost:28000/admin/realms/didi-clients/clients?clientId=didi-web-app" \
|
|
-H "Authorization: Bearer $KC_TOKEN" 2>/dev/null \
|
|
| python3 -c "import sys,json;d=json.load(sys.stdin);print(d[0]['id'] if d else '')" 2>/dev/null || echo "")
|
|
|
|
if [ -n "$WEB_CLIENT_UUID" ]; then
|
|
curl -s -X PUT "http://localhost:28000/admin/realms/didi-clients/clients/$WEB_CLIENT_UUID" \
|
|
-H "Authorization: Bearer $KC_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"redirectUris\": [
|
|
\"https://${PLATFORM_HOSTNAME}/*\",
|
|
\"http://localhost:3001/*\",
|
|
\"http://localhost:5173/*\"
|
|
],
|
|
\"webOrigins\": [
|
|
\"https://${PLATFORM_HOSTNAME}\",
|
|
\"http://localhost:3001\",
|
|
\"http://localhost:5173\"
|
|
]
|
|
}" -w "" -o /dev/null 2>/dev/null
|
|
ok "didi-web-app: redirect URI -> https://${PLATFORM_HOSTNAME}/*"
|
|
else
|
|
warn "Client didi-web-app nu gasit in Keycloak"
|
|
fi
|
|
|
|
# Configureaza admin-dashboard
|
|
log "Configurez client admin-dashboard..."
|
|
ADMIN_CLIENT_UUID=$(curl -s "http://localhost:28000/admin/realms/didi-clients/clients?clientId=admin-dashboard" \
|
|
-H "Authorization: Bearer $KC_TOKEN" 2>/dev/null \
|
|
| python3 -c "import sys,json;d=json.load(sys.stdin);print(d[0]['id'] if d else '')" 2>/dev/null || echo "")
|
|
|
|
if [ -n "$ADMIN_CLIENT_UUID" ]; then
|
|
curl -s -X PUT "http://localhost:28000/admin/realms/didi-clients/clients/$ADMIN_CLIENT_UUID" \
|
|
-H "Authorization: Bearer $KC_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"redirectUris\": [
|
|
\"https://${PLATFORM_HOSTNAME}/*\",
|
|
\"https://${PLATFORM_HOSTNAME}/admin/*\",
|
|
\"http://localhost:3003/*\"
|
|
],
|
|
\"webOrigins\": [
|
|
\"https://${PLATFORM_HOSTNAME}\",
|
|
\"http://localhost:3003\"
|
|
]
|
|
}" -w "" -o /dev/null 2>/dev/null
|
|
ok "admin-dashboard: redirect URI -> https://${PLATFORM_HOSTNAME}/*"
|
|
else
|
|
warn "Client admin-dashboard nu gasit in Keycloak"
|
|
fi
|
|
fi
|
|
|
|
# =============================================================================
|
|
section "FAZA 5: didiFramework (CRUD backend + sync Redis)"
|
|
# =============================================================================
|
|
|
|
cd "$FRAMEWORK"
|
|
|
|
log "Build + start didiFramework..."
|
|
docker compose up -d --build 2>&1 | tail -5
|
|
ok "didiFramework pornit"
|
|
|
|
wait_healthy didi-framework 60
|
|
|
|
# Verific health-ul complet (PG + MinIO)
|
|
log "Verific health didiFramework..."
|
|
HEALTH=$(docker exec didi-framework wget -qO- "http://127.0.0.1:3005/health/all" 2>/dev/null || echo "{}")
|
|
echo " $HEALTH"
|
|
|
|
# =============================================================================
|
|
section "FAZA 6: Sincronizare Framework -> Redis"
|
|
# =============================================================================
|
|
|
|
log "Trigger sync-redis (incarca parametri framework in Redis)..."
|
|
SYNC_RESULT=$(docker exec didi-framework wget -qO- --post-data='' "http://127.0.0.1:3005/api/sync-redis" 2>/dev/null || echo "FAIL")
|
|
if echo "$SYNC_RESULT" | grep -q '"success"'; then
|
|
ok "Sync Redis reusit"
|
|
echo " $SYNC_RESULT" | head -c 200
|
|
echo ""
|
|
else
|
|
warn "Sync Redis posibil esuat: $SYNC_RESULT"
|
|
warn "Poti face sync manual mai tarziu: POST http://localhost:3005/api/sync-redis"
|
|
fi
|
|
|
|
# Verific ca cheile au fost scrise
|
|
log "Verific chei framework in Redis..."
|
|
KEY_COUNT=$(docker exec didi-cache redis-cli -a redis123 keys "didi:framework:*" 2>/dev/null | wc -l)
|
|
CONFIG_COUNT=$(docker exec didi-cache redis-cli -a redis123 keys "didi:config:*" 2>/dev/null | wc -l)
|
|
ok "Chei framework: $KEY_COUNT | Chei config: $CONFIG_COUNT"
|
|
|
|
if [ "$KEY_COUNT" -lt 5 ]; then
|
|
warn "Prea putine chei framework ($KEY_COUNT). Sync-ul poate sa nu fi functionat."
|
|
warn "Verifica manual: docker exec didi-cache redis-cli -a redis123 keys 'didi:framework:*'"
|
|
fi
|
|
|
|
# =============================================================================
|
|
section "FAZA 7: MinIO - Initializare bucket-uri"
|
|
# =============================================================================
|
|
|
|
log "Verific bucket-urile MinIO..."
|
|
BUCKET_LIST=$(docker exec staging-dataLayer-minio mc ls local/ 2>/dev/null || echo "")
|
|
|
|
REQUIRED_BUCKETS=("uploads" "text-files" "image-files" "audio-files" "video-files" "document-files" "pipeline-artifacts" "backups")
|
|
BUCKETS_MISSING=0
|
|
|
|
for bucket in "${REQUIRED_BUCKETS[@]}"; do
|
|
if echo "$BUCKET_LIST" | grep -q "$bucket"; then
|
|
ok " Bucket: $bucket"
|
|
else
|
|
warn " LIPSA bucket: $bucket"
|
|
BUCKETS_MISSING=$((BUCKETS_MISSING + 1))
|
|
fi
|
|
done
|
|
|
|
if [ "$BUCKETS_MISSING" -gt 0 ]; then
|
|
log "Rulez init-buckets.sh..."
|
|
if [ -f "$DATA_LAYER/didiStorage/init-buckets.sh" ]; then
|
|
docker exec -e MINIO_HOST=localhost -e MINIO_PORT=9000 \
|
|
-e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minio123 \
|
|
staging-dataLayer-minio sh -c "$(cat $DATA_LAYER/didiStorage/init-buckets.sh)" 2>&1 | tail -5
|
|
ok "Bucket-uri initializate"
|
|
else
|
|
warn "init-buckets.sh nu exista. Creeaza bucket-urile manual."
|
|
fi
|
|
else
|
|
ok "Toate bucket-urile exista"
|
|
fi
|
|
|
|
# =============================================================================
|
|
section "FAZA 8: Agent V3 + Workers"
|
|
# =============================================================================
|
|
|
|
cd "$AGENT_V3"
|
|
|
|
# Verific ca .env exista (contine API keys)
|
|
if [ ! -f .env ]; then
|
|
warn ".env lipseste in $AGENT_V3"
|
|
warn "Fisierul trebuie sa contina: OPENROUTER_API_KEY, OPENAI_API_KEY, GROQ_API_KEY, M17_WHISPER_TOKEN"
|
|
warn "Fara aceste chei, analizele LLM nu vor functiona."
|
|
read -p "Continui fara .env? (y/N): " answer
|
|
[ "$answer" = "y" ] || [ "$answer" = "Y" ] || exit 1
|
|
else
|
|
ok ".env exista (API keys configurate)"
|
|
# Verific cheile critice
|
|
for key in OPENROUTER_API_KEY OPENAI_API_KEY GROQ_API_KEY; do
|
|
val=$(grep "^$key=" .env 2>/dev/null | cut -d= -f2-)
|
|
if [ -z "$val" ]; then
|
|
warn " $key este gol in .env"
|
|
else
|
|
ok " $key configurat (${#val} caractere)"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
log "Build + start agent-v3 + toti workerii..."
|
|
docker compose up -d --build 2>&1 | tail -10
|
|
ok "Agent V3 + workers porniti"
|
|
|
|
wait_healthy didi-agent-v3 60
|
|
|
|
# Verific health
|
|
log "Verific health agent-v3..."
|
|
AGENT_HEALTH=$(docker exec didi-agent-v3 wget -qO- "http://localhost:24803/api/v3/health" 2>/dev/null || echo "FAIL")
|
|
echo " $AGENT_HEALTH"
|
|
|
|
# Verific workerii
|
|
log "Verific workerii..."
|
|
WORKERS=$(docker ps --format '{{.Names}}' | grep -c "agent-v3-worker" || true)
|
|
AGGREGATORS=$(docker ps --format '{{.Names}}' | grep -c "verdict-aggregator" || true)
|
|
ok "Workers activi: $WORKERS | Aggregators: $AGGREGATORS"
|
|
|
|
# =============================================================================
|
|
section "FAZA 9: Admin Dashboard"
|
|
# =============================================================================
|
|
|
|
# Admin dashboard este in data-layer docker-compose (didi-admin container)
|
|
log "Verific admin dashboard..."
|
|
if docker ps --format '{{.Names}}' | grep -q didi-admin; then
|
|
ok "didi-admin deja ruleaza"
|
|
else
|
|
log "Admin dashboard nu ruleaza. Rebuild..."
|
|
cd "$BACKEND/admin-dashboard"
|
|
if [ -f Dockerfile ]; then
|
|
docker build -t didi-admin:latest . 2>&1 | tail -5
|
|
ok "Imagine admin-dashboard construita"
|
|
fi
|
|
cd "$DATA_LAYER"
|
|
docker compose up -d didi-admin 2>&1 | tail -3
|
|
fi
|
|
|
|
wait_healthy didi-admin 60 || true
|
|
|
|
# =============================================================================
|
|
section "FAZA 10: Kong Build (imagine custom)"
|
|
# =============================================================================
|
|
|
|
log "Verific imaginea Kong..."
|
|
if docker images didi-kong:latest --format '{{.ID}}' | head -1 | grep -q .; then
|
|
ok "Imaginea didi-kong:latest exista"
|
|
else
|
|
log "Build imagine didi-kong..."
|
|
if [ -d "$KONG_DIR" ] && [ -f "$KONG_DIR/Dockerfile" ]; then
|
|
docker build -t didi-kong:latest "$KONG_DIR" 2>&1 | tail -3
|
|
ok "Imaginea Kong construita. Restart Kong..."
|
|
cd "$PRODUCTION"
|
|
docker compose up -d kong 2>&1 | tail -3
|
|
wait_healthy kong 90 || true
|
|
else
|
|
warn "Nu gasesc Dockerfile Kong la $KONG_DIR"
|
|
fi
|
|
fi
|
|
|
|
# =============================================================================
|
|
section "VERIFICARE FINALA"
|
|
# =============================================================================
|
|
|
|
echo ""
|
|
log "Status toate containerele DIDI:"
|
|
echo ""
|
|
printf "%-45s %-20s %s\n" "CONTAINER" "STATUS" "PORTS"
|
|
printf "%-45s %-20s %s\n" "---------" "------" "-----"
|
|
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" --filter "network=didi-network" 2>/dev/null | tail -n +2 | sort | while read line; do
|
|
echo " $line"
|
|
done
|
|
|
|
echo ""
|
|
log "Health checks rapide:"
|
|
|
|
# Lista de verificari
|
|
declare -A CHECKS=(
|
|
["Redis"]="docker exec didi-cache redis-cli -a redis123 ping 2>/dev/null"
|
|
["Framework"]="docker exec didi-framework wget -qO- http://127.0.0.1:3005/health 2>/dev/null"
|
|
["Agent-V3"]="docker exec didi-agent-v3 wget -qO- http://localhost:24803/api/v3/health 2>/dev/null"
|
|
["RabbitMQ"]="docker exec staging-dataLayer-rabbitmq rabbitmq-diagnostics -q ping 2>/dev/null"
|
|
["MinIO"]="docker exec staging-dataLayer-minio mc ready local 2>/dev/null"
|
|
)
|
|
|
|
for name in Redis Framework Agent-V3 RabbitMQ MinIO; do
|
|
result=$(eval "${CHECKS[$name]}" || echo "FAIL")
|
|
if echo "$result" | grep -qiE "PONG|ok|healthy|ready|service|READY"; then
|
|
ok "$name"
|
|
else
|
|
warn "$name: $result"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
|
|
# Verific chei Redis finale
|
|
FRAMEWORK_KEYS=$(docker exec didi-cache redis-cli -a redis123 keys "didi:framework:*" 2>/dev/null | wc -l)
|
|
CONFIG_KEYS=$(docker exec didi-cache redis-cli -a redis123 keys "didi:config:*" 2>/dev/null | wc -l)
|
|
log "Redis: $FRAMEWORK_KEYS chei framework, $CONFIG_KEYS chei config"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}====================================================================${NC}"
|
|
echo -e "${GREEN} BUILD COMPLET${NC}"
|
|
echo -e "${GREEN}====================================================================${NC}"
|
|
echo ""
|
|
echo "Platforma configurata pe: $PLATFORM_HOSTNAME"
|
|
echo ""
|
|
echo "Endpoint-uri disponibile:"
|
|
echo " Frontend: https://${PLATFORM_HOSTNAME}"
|
|
echo " Admin Dashboard: https://${PLATFORM_HOSTNAME}/admin"
|
|
echo " Agent V3 API: http://localhost:24803/api/v3/health (doar local)"
|
|
echo " Framework API: intern pe Docker network (port 3005)"
|
|
echo " Kong Gateway: https://localhost:443"
|
|
echo " Keycloak: http://localhost:28000"
|
|
echo " Keycloak Auth: https://${PLATFORM_HOSTNAME}/auth"
|
|
echo " RabbitMQ UI: http://localhost:15672 (admin/rabbitmq123)"
|
|
echo " MinIO Console: http://localhost:9001 (minioadmin/minio123)"
|
|
echo " PgAdmin: http://localhost:5050 (admin@example.com/admin123)"
|
|
echo ""
|
|
echo "Daca sync Redis nu a mers, ruleaza manual:"
|
|
echo " curl -X POST http://localhost:3005/api/sync-redis"
|
|
echo " (sau din interiorul Docker: docker exec didi-framework wget -qO- --post-data='' http://127.0.0.1:3005/api/sync-redis)"
|
|
echo ""
|