forked from hotosm/fAIr
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmanage-dev.sh
More file actions
342 lines (300 loc) · 8.95 KB
/
manage-dev.sh
File metadata and controls
342 lines (300 loc) · 8.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#!/bin/bash
# fAIr Application Management Script - Development Only
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
APP_DIR="$(pwd)"
DATA_DIR="${DATA_DIR:-$(pwd)/fair-app-data}"
RAMP_DIR="${RAMP_HOME:-$(pwd)/fair-app-data/ramp}"
TRAINING_DIR="${TRAINING_WORKSPACE:-$(pwd)/fair-app-data/trainings}"
POSTGRES_DATA_DIR="${POSTGRES_DATA:-$(pwd)/fair-app-data/postgres}"
REDIS_DATA_DIR="${REDIS_DATA:-$(pwd)/fair-app-data/redis}"
LOG_PATH_DIR="${LOG_PATH:-$(pwd)/fair-app-data/logs}"
ENV_FILE="$(pwd)/.env.dev"
COMPOSE_FILE="$(pwd)/docker-compose.dev.yml"
PROFILE="${PROFILE:-cpu}" # Default profile (can be 'gpu' or 'cpu')
USER_NAME="${USER}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-dev_pg_pass}"
# Header
show_header() {
echo -e "${BLUE}==============================================${NC}"
echo -e "${BLUE} fAIr AI Application (DEV) ${NC}"
echo -e "${BLUE} Management Tool ${NC}"
echo -e "${BLUE}==============================================${NC}"
echo -e "${YELLOW}User: $USER_NAME Date: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo -e "${BLUE}Profile: ${GREEN}${PROFILE}${NC}"
echo -e "${BLUE}==============================================${NC}"
}
# Command exists check
command_exists() {
command -v "$1" &> /dev/null
}
# Ensure directories exist
ensure_directories() {
for dir in "$APP_DIR" "$DATA_DIR" "$RAMP_DIR" "$TRAINING_DIR" "$POSTGRES_DATA_DIR" "$REDIS_DATA_DIR" "$LOG_PATH_DIR"; do
[ -d "$dir" ] || mkdir -p "$dir"
done
}
# Load environment variables from file
load_env() {
if [ -f "$ENV_FILE" ]; then
export $(grep -v '^#' "$ENV_FILE" | xargs)
fi
}
# Setup function
setup() {
show_header
echo -e "${GREEN}Setting up fAIr development environment...${NC}"
for cmd in docker docker-compose; do
if ! command_exists $cmd; then
echo -e "${RED}Error: $cmd is not installed${NC}"
exit 1
fi
done
ensure_directories
if [ -f "docker-compose.dev.yml" ]; then
cp docker-compose.dev.yml $COMPOSE_FILE
elif [ ! -f "$COMPOSE_FILE" ]; then
echo -e "${RED}docker-compose.dev.yml not found. Please provide a dev compose file.${NC}"
exit 1
fi
# Create env file if it doesn't exist
if [ ! -f "$ENV_FILE" ]; then
echo -e "${YELLOW}Creating development environment file...${NC}"
cat > "$ENV_FILE" <<EOF
# Auto-generated .env.dev from manage-dev.sh
ENV_FILE=$ENV_FILE
DEBUG=True
# Database configuration
POSTGRES_DB=ai
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
# Redis configuration
REDIS_HOST=redis
REDIS_PORT=6379
TAG=develop
# Mount points
DATA_DIR=$DATA_DIR
RAMP_HOME=$RAMP_DIR
TRAINING_WORKSPACE=$TRAINING_DIR
LOG_PATH=$LOG_PATH_DIR
POSTGRES_DATA=$POSTGRES_DATA_DIR
REDIS_DATA=$REDIS_DATA_DIR
# Application configuration
SECRET_KEY=dev_secret_key
DATABASE_URL=postgis://postgres:$POSTGRES_PASSWORD@postgres:5432/ai
CELERY_BROKER_URL="redis://redis:6379/0"
CELERY_RESULT_BACKEND="redis://redis:6379/0"
OSM_CLIENT_ID=dev_osm_client_id
OSM_CLIENT_SECRET=dev_osm_client_secret
OSM_URL=https://www.openstreetmap.org
OSM_SCOPE=read_prefs
OSM_LOGIN_REDIRECT_URI=http://localhost:8000/authenticate/
OSM_SECRET_KEY=dev_osm_secret_key
ALLOWED_ORIGINS="http://localhost:3000/,localhost:3000"
FRONTEND_URL=http://localhost:3000
EMAIL_HOST=localhost
EMAIL_PORT=1025
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
DEFAULT_FROM_EMAIL=noreply@localhost
EMAIL_USE_TLS=False
EMAIL_USE_SSL=False
EOF
fi
echo -e "${GREEN}Setup completed! You can now start the application with:${NC}"
echo -e "${YELLOW}./manage-dev.sh start${NC}"
}
# Start application
start() {
show_header
echo -e "${GREEN}Starting fAIr development application...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE --profile $PROFILE up -d
sleep 3
wait_for_api_healthy_with_logs
status
echo -e "${YELLOW}Initializing application (migrations, web server)...${NC}"
initialize_app
}
# Stop application
stop() {
show_header
echo -e "${YELLOW}Stopping fAIr development application...${NC}"
docker compose -f $COMPOSE_FILE down
}
# Restart application
restart() {
show_header
echo -e "${YELLOW}Restarting fAIr development application...${NC}"
stop
start
}
# Status
status() {
show_header
echo -e "${GREEN}Container Status:${NC}"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "(pgsql|redis|api|worker|flower|frontend|dev|db)" || true
}
# Logs
logs() {
show_header
local service=$1
if [ -z "$service" ]; then
echo -e "${GREEN}Showing logs for all services (Ctrl+C to exit):${NC}"
docker compose -f $COMPOSE_FILE logs --tail=100 -f
else
echo -e "${GREEN}Showing logs for $service (Ctrl+C to exit):${NC}"
docker compose -f $COMPOSE_FILE logs --tail=100 -f $service
fi
}
wait_for_api_healthy_with_logs() {
echo -e "${YELLOW}Waiting for backend-api to be healthy... Showing logs below (Ctrl+C to stop viewing logs)${NC}"
# Start logs in background, save PID
docker compose -f $COMPOSE_FILE logs -f api &
LOGS_PID=$!
local retries=60
while [[ $retries -gt 0 ]]; do
health_status=$(docker inspect --format='{{.State.Health.Status}}' api 2>/dev/null)
if [[ "$health_status" == "healthy" ]]; then
echo -e "${GREEN}backend-api is healthy!${NC}"
kill $LOGS_PID 2>/dev/null
wait $LOGS_PID 2>/dev/null
return 0
fi
sleep 2
retries=$((retries-1))
done
echo -e "${RED}backend-api did not become healthy in time.${NC}"
kill $LOGS_PID 2>/dev/null
wait $LOGS_PID 2>/dev/null
docker logs api
exit 1
}
# Initialize application
initialize_app() {
echo -e "${YELLOW}Running migrations...${NC}"
run_migrations
if [ $? -ne 0 ]; then
echo -e "${RED}Migrations failed. Application may not function correctly.${NC}"
return 1
fi
echo -e "${YELLOW}Starting dev server in API container...${NC}"
docker exec -d api bash -c "python manage.py runserver 0.0.0.0:8000"
echo -e "${GREEN}Application initialized successfully!${NC}"
}
# Run migrations
run_migrations() {
docker exec api bash -c "python manage.py makemigrations" || echo -e "${YELLOW}makemigrations failed (possibly no changes)${NC}"
docker exec api bash -c "python manage.py makemigrations core login" || echo -e "${YELLOW}makemigrations failed (possibly no changes)${NC}"
docker exec api bash -c "python manage.py migrate" || {
echo -e "${RED}Migration failed!${NC}"
docker logs api --tail 50
return 1
}
return 0
}
# Run migrations directly
migrations() {
show_header
if ! docker ps | grep -q "api"; then
echo -e "${RED}API container is not running. Please start the application first.${NC}"
return 1
fi
run_migrations
echo -e "${GREEN}Migrations completed.${NC}"
}
# Create superuser
createsuperuser() {
show_header
if ! docker ps | grep -q "api"; then
echo -e "${RED}API container is not running. Please start the application first.${NC}"
return 1
fi
docker exec -it api bash -c "python manage.py createsuperuser"
}
# Help
show_help() {
show_header
echo -e "Usage: $0 [options] command"
echo -e ""
echo -e "Options:"
echo -e " ${BLUE}-p, --profile${NC} - Set profile (cpu|gpu), default: gpu"
echo -e " ${BLUE}-d, --dir${NC} - Set base directory (defaults to current directory)"
echo -e ""
echo -e "Commands:"
echo -e " ${GREEN}setup${NC} - Set up the development environment"
echo -e " ${GREEN}start${NC} - Start the app stack"
echo -e " ${GREEN}stop${NC} - Stop the app stack"
echo -e " ${GREEN}restart${NC} - Restart the app stack"
echo -e " ${GREEN}status${NC} - Show container status"
echo -e " ${GREEN}logs [service]${NC} - View logs, optionally for a service"
echo -e " ${GREEN}migrations${NC} - Run Django database migrations"
echo -e " ${GREEN}createsuperuser${NC} - Create a Django superuser account"
echo -e ""
echo -e "Examples:"
echo -e " ${YELLOW}$0 setup${NC} - Set up"
echo -e " ${YELLOW}$0 -p cpu start${NC} - Start with CPU profile"
echo -e " ${YELLOW}$0 migrations${NC} - Run migrations"
echo -e " ${YELLOW}$0 logs api${NC} - Show backend API logs"
}
# Parse options
while [[ "$#" -gt 0 ]]; do
case $1 in
-p|--profile)
PROFILE="$2"
if [[ "$PROFILE" != "cpu" && "$PROFILE" != "gpu" ]]; then
echo -e "${RED}Invalid profile. Use 'cpu' or 'gpu'${NC}"
exit 1
fi
shift 2
;;
-d|--dir)
APP_DIR="$2"
DATA_DIR="$APP_DIR/fair-app-data"
ENV_FILE="$APP_DIR/.env.dev"
COMPOSE_FILE="$APP_DIR/docker-compose.dev.yml"
shift 2
;;
*)
break
;;
esac
done
load_env
case "$1" in
setup)
setup
;;
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
logs)
logs $2
;;
migrations)
migrations
;;
createsuperuser)
createsuperuser
;;
*)
show_help
exit 0
;;
esac
exit 0