#!/usr/bin/env bash set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' usage() { echo "Usage: $0 [dev|prod]" echo "" echo "Initialize database schema and create admin user." echo "" echo " dev - Initialize dev environment (minikube, default namespace)" echo " prod - Initialize prod environment (requires confirmation)" exit 1 } ENV="${1:-dev}" if [[ "$ENV" != "dev" && "$ENV" != "prod" ]]; then echo -e "${RED}Error: Environment must be 'dev' or 'prod'${NC}" usage fi if [[ "$ENV" == "prod" ]]; then KUBECTL="kubectl --context=prod" BASE_URL="https://dexorder.ai" MCP_URL="https://dexorder.ai/mcp" echo -e "${YELLOW}⚠️ WARNING: Initializing PRODUCTION environment!${NC}" echo -e "${YELLOW}kubectl context: prod${NC}" read -p "Are you sure you want to continue? (yes/no): " confirm if [[ "$confirm" != "yes" ]]; then echo "Aborted." exit 0 fi else KUBECTL="kubectl" BASE_URL="http://dexorder.local" MCP_URL="http://localhost:8080/mcp" fi # ---------- MinIO Bucket Initialization ---------- echo "" echo -e "${BLUE}=== MinIO Storage Setup ===${NC}" echo "" echo -e "${BLUE}Waiting for MinIO pod...${NC}" $KUBECTL wait --for=condition=ready --timeout=120s pod -l app=minio 2>/dev/null || { echo -e "${YELLOW}⚠️ MinIO not ready after 120s, skipping bucket setup${NC}" } MINIO_POD=$($KUBECTL get pods -l app=minio -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) if [ -n "$MINIO_POD" ]; then echo -e "${GREEN}→${NC} Ensuring warehouse bucket exists..." MINIO_USER=$($KUBECTL exec "$MINIO_POD" -- sh -c 'echo $MINIO_ROOT_USER' 2>/dev/null | tr -d '\r') MINIO_PASS=$($KUBECTL exec "$MINIO_POD" -- sh -c 'echo $MINIO_ROOT_PASSWORD' 2>/dev/null | tr -d '\r') $KUBECTL exec "$MINIO_POD" -- mc alias set local http://localhost:9000 "$MINIO_USER" "$MINIO_PASS" > /dev/null 2>&1 $KUBECTL exec "$MINIO_POD" -- mc mb --ignore-existing local/warehouse > /dev/null 2>&1 echo -e "${GREEN}✓ Warehouse bucket ready${NC}" else echo -e "${YELLOW}⚠️ MinIO pod not found, skipping bucket setup${NC}" fi # ---------- Schema Initialization ---------- echo "" echo -e "${BLUE}=== Schema Initialization ===${NC}" echo "" echo -e "${BLUE}Waiting for postgres pod...${NC}" $KUBECTL wait --for=condition=ready --timeout=180s pod -l app=postgres 2>/dev/null || { echo -e "${RED}Postgres not ready after 180s${NC}" exit 1 } PG_POD=$($KUBECTL get pods -l app=postgres -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) if [ -z "$PG_POD" ]; then echo -e "${RED}No postgres pod found${NC}" exit 1 fi echo -e "${GREEN}Found postgres pod: $PG_POD${NC}" # Wait for postgres to accept connections echo -e "${BLUE}Waiting for postgres to accept connections...${NC}" for i in $(seq 1 30); do if $KUBECTL exec "$PG_POD" -- psql -U postgres -d iceberg -c "SELECT 1;" > /dev/null 2>&1; then echo -e "${GREEN}Postgres ready${NC}" break fi if [[ $i -eq 30 ]]; then echo -e "${RED}Postgres not accepting connections after 60s${NC}" exit 1 fi sleep 2 done # Check if schema exists TABLE_COUNT=$($KUBECTL exec "$PG_POD" -- psql -U postgres -d iceberg -t \ -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'user';" \ 2>/dev/null | tr -d ' \n') if [[ "$TABLE_COUNT" == "1" ]]; then echo -e "${GREEN}✓ Schema already initialized${NC}" else echo -e "${BLUE}Applying gateway schema...${NC}" $KUBECTL exec -i "$PG_POD" -- psql -U postgres -d iceberg < "$ROOT_DIR/gateway/schema.sql" echo -e "${GREEN}✓ Schema applied${NC}" fi # ---------- Admin User Creation ---------- echo "" echo -e "${BLUE}=== Admin User Setup ===${NC}" echo "" if [[ "$ENV" == "dev" ]]; then # Dev: use fixed credentials USER_EMAIL="tim@dexorder.ai" USER_PASSWORD="test1234" USER_NAME="Tim" LICENSE_TYPE="pro" echo -e "${BLUE}Using dev defaults: $USER_EMAIL / $USER_PASSWORD ($LICENSE_TYPE)${NC}" else # Prod: prompt for credentials read -p "Admin email: " USER_EMAIL read -rs -p "Admin password (min 8 chars): " USER_PASSWORD echo "" echo -e "${BLUE}Password captured: ${#USER_PASSWORD} characters${NC}" if [[ ${#USER_PASSWORD} -lt 8 ]]; then echo -e "${RED}✗ Password must be at least 8 characters${NC}" exit 1 fi read -p "Admin display name: " USER_NAME read -p "License type [free|pro|enterprise] (default: pro): " LICENSE_TYPE LICENSE_TYPE="${LICENSE_TYPE:-pro}" fi # Check if user already exists EXISTING_ID=$($KUBECTL exec "$PG_POD" -- psql -U postgres -d iceberg -t \ -c "SELECT id FROM \"user\" WHERE email = '$USER_EMAIL';" \ 2>/dev/null | tr -d ' \n') if [ -n "$EXISTING_ID" ]; then echo -e "${GREEN}✓ User already exists in database ($USER_EMAIL)${NC}" USER_ID="$EXISTING_ID" else # Register via API echo -e "${BLUE}Waiting for gateway...${NC}" $KUBECTL wait --for=condition=available --timeout=120s deployment/gateway 2>/dev/null || { echo -e "${YELLOW}⚠️ Gateway not ready after 120s, trying anyway${NC}" } sleep 3 echo -e "${GREEN}→${NC} Registering user via API..." PAYLOAD=$(jq -n \ --arg email "$USER_EMAIL" \ --arg password "$USER_PASSWORD" \ --arg name "$USER_NAME" \ '{email: $email, password: $password, name: $name}') HTTP_CODE=$(curl -s -o /tmp/dexorder-init-response.json -w "%{http_code}" \ -X POST "$BASE_URL/api/auth/register" \ -H "Content-Type: application/json" \ -d "$PAYLOAD") if [[ "$HTTP_CODE" == "200" || "$HTTP_CODE" == "201" ]]; then echo -e "${GREEN}✓ User registered via API${NC}" elif [[ "$HTTP_CODE" == "400" ]]; then RESPONSE=$(cat /tmp/dexorder-init-response.json 2>/dev/null) # Check if this is a "user already exists" 400 vs a validation error if echo "$RESPONSE" | grep -qi "already exist\|user already\|duplicate"; then echo -e "${YELLOW}⚠️ User already exists, continuing...${NC}" else echo -e "${RED}✗ Registration failed (400):${NC}" echo "$RESPONSE" rm -f /tmp/dexorder-init-response.json exit 1 fi else echo -e "${RED}✗ API returned HTTP $HTTP_CODE${NC}" cat /tmp/dexorder-init-response.json 2>/dev/null || true rm -f /tmp/dexorder-init-response.json exit 1 fi rm -f /tmp/dexorder-init-response.json sleep 2 USER_ID=$($KUBECTL exec "$PG_POD" -- psql -U postgres -d iceberg -t \ -c "SELECT id FROM \"user\" WHERE email = '$USER_EMAIL';" \ 2>/dev/null | tr -d ' \n') fi if [ -z "$USER_ID" ]; then echo -e "${RED}User not found in database after registration. Is the gateway running?${NC}" exit 1 fi echo -e "${GREEN}User ID: $USER_ID${NC}" echo -e "${GREEN}→${NC} Setting $LICENSE_TYPE license..." HTTP_CODE=$(curl -s -o /tmp/dexorder-set-tier-response.json -w "%{http_code}" \ -X POST "$BASE_URL/api/admin/users/$USER_ID/set-tier" \ -H "Content-Type: application/json" \ -d "{\"tier\": \"$LICENSE_TYPE\"}") if [[ "$HTTP_CODE" != "200" ]]; then echo -e "${RED}✗ Failed to set license tier (HTTP $HTTP_CODE)${NC}" cat /tmp/dexorder-set-tier-response.json 2>/dev/null exit 1 fi rm -f /tmp/dexorder-set-tier-response.json echo -e "${GREEN}✓ User ready: $USER_EMAIL ($LICENSE_TYPE)${NC}" echo "" echo -e "${BLUE}Initialization complete.${NC}" if [[ "$ENV" == "dev" ]]; then echo -e "${BLUE}Login at http://dexorder.local with $USER_EMAIL / $USER_PASSWORD${NC}" fi