-
Notifications
You must be signed in to change notification settings - Fork 0
/
rctmake
executable file
·469 lines (405 loc) · 17.1 KB
/
rctmake
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
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
#!/bin/bash
PROJECT_DIR="$(dirname $(realpath $0))";
SCRIPT_NAME="$(basename $0)"
DEV_MODE=dev
TEST_MODE=test
O2RCT_ID=o2rct
APP_CONTAINER_NAME_BASE="$O2RCT_ID""_application"
APP_CONTAINERS_OPT="$APP_CONTAINER_NAME_BASE-([$DEV_MODE|$TEST_MODE])"
APP_WORKINGDIR='/opt/RunConditionTable'
DB_CONTAINER_NAME_BASE="$O2RCT_ID""_database"
DP_CONTAINERS_OPT="$DB_CONTAINER_NAME-($DEV_MODE|$TEST_MODE))"
DB_WORKINGDIR='/postgres/run'
ITWILLBEDELETED="!(It will be deleted)"
usage() {
ERROR="$1";
if [ -n "$ERROR" ]; then
BORDER_PATTERN="' *'"
ERROR_REASON_MESS=" error reason: $ERROR";
LENGTH=$(expr length "$ERROR_REASON_MESS" / 2 + 2);
HORIZONTAL_BORDER=$(seq -s' *' $LENGTH| tr -d '[:digit:]');
# echo $HORIZONTAL_BORDER # TODO 'xdTODO' : examine why uncommenting cause some rabish text in usage printout
ERROR_MESSAGE_PRINT="
*$HORIZONTAL_BORDER
*$ERROR_REASON_MESS *
*$HORIZONTAL_BORDER
"
fi
cat << USAGE >&2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
This script is intended to provide handy functionalities during
development, testing for building, deployment and managing acquired data.
The script can be run from any location.
The script performs defined tasks sequentially.
Some tasks might or have to be run with dedicated flags.
Tasks are called stages.
Usage:
./$SCRIPT_NAME <STAGES> [<FLAGS>]
where STAGES is comma separeted list of stages performed sequentialy.
By default, failure of any stage causes the stop of pipeline execution, it can be changed via flag --ignore-errors.
It is possible to specify TARGET (default dev). It can be specified via flag -t|--target as test as well as via exporting env var TARGET;
It is possible to specify SUBTARGET from range 1-9 (defualt 1 for TARGET dev). It can be specified via flag -s|--subtarget as test as well as via exporting env var SUBTARGET;
It can be used for running muliple instances of application simultaneously.
For TARGET test, 0 is the only allowed value for SUBTARGET and can be omitted.
Each stage is performed within the context of target.
Using containers built as dev and test is separted and can be performed in parallel.
Is seems that there is one case of target test, just something like ./rctmake run --target test.
STAGE can be a:
1. run|run[RUN_SUBSTATGES] - run application (deploys containers). By defualt
run stage behaves as docker-compose ... up --build.
RUN_SUBSTATGES are / (slash) separated docker-compose tasks like create,up,...
e.g.: ./$SCRIPT_NAME run -t dev
./$SCRIPT_NAME run[create/up] -t test
./$SCRIPT_NAME run[up] -t test
2. stop - stop containers
3. rm - delete containers, all virtual volumens and virtual network
4. follow - like docker-compose follow
5. logs - like docker-compose logs
6. app:attach - like docker attach to $APP_CONTAINERS_OPT - to running application
7. app:battach - run bash on $APP_CONTAINER_NAME
8. app:ip - retrive ip of $DB_CONTAINER_NAME
9. db:attach - run psql on $DB_CONTRAINER_NAME
10. db:battach - run bash on $DB_CONTRAINER_NAME
11. db:clean | db:truncate - truncate database in db container
12. db:ip - print db container ipv4 address
13. db:(counts|ct) - print statistics of data in each table in db
14. dump:(make|mk) - make dump of current database (in docker container) data,
need option -F|--dump-file <FILE> to specify dump file relative path
e.g.: ./$SCRIPT_NAME dump -F dump_file
15. dump:(list|ls) - print list cached dumps
16. dump:tree - print tree of cached dumps
17. dump:(remove|rm) -F|--dump-file <FILE> - remove dump from cache specified by the flag
18. dump:(restore|re) -F|--dump-file <FILE> - restore data from dump specified by the flag
e.g.: ./$SCRIPT_NAME restore -F dump_file
19. dump:(export|ex) -A|--archive-name <FILE> - export cached dump to tar.gz archive specified by the flag
20. dump:(import|im) -A|--archive-name <FILE> - import dumps from tar.gz archvie specified by the flag ito cache
21. prune - remove everything related to RCT and dockers
Other options:
-b|--build) - force to build images, even if they exists already
-S|--service <SERVICE> - flag can be specified for run, follow, stop and rm stages.
<SERVICE> $APP_CONTAINERS_OPT or $DB_CONTAINERS_OPT is the name of the service the stages are performed for.
-p|--rct-http-port PORT - flag for setting env var RCT_HTTP_PORT
-m|--target-modifier START_TARGET_MODIFIER - add modififying sufix to npm task like start:dev:START_TARGET_MODIFIER or start:test:START_TARGET_MODIFIER, depends on choosen TARGET
In case of dev mode modifier ND cause running node instead of nodemon.
-M|--mocha <MOCHA OPTIONS> - pass flags/options to mocha when running tests (see mocha documentation)
e.g.: ./$SCRIPT_NAME run --target test --mocha '--grep SomeTestsDescriptor'
$ERROR_MESSAGE_PRINT
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USAGE
if [ -n "$ERROR" ]; then
exit 1;
else
exit 0;
fi;
}
incorrect_stage_err() {
usage "Incorrect stage: $1";
}
exit_codes_filter() {
LAST_CMD_EXIT_CODE=$?
IGNORABLE_CODES=$@
for ie in $IGNORABLE_CODES; do
if [ $LAST_CMD_EXIT_CODE -eq $ie ]; then
return 0;
fi;
done
return $LAST_CMD_EXIT_CODE
}
PREVIOD_USER_LOC=$(pwd);
DOCKER_DIR="$PROJECT_DIR/docker";
MAIN_DOCKER_COMPOSE_YML="$DOCKER_DIR/docker-compose.yml"
if [[ $# -eq 0 ]]; then
usage 'no option specfied'
else
if [ "$1" = '-h' ] || [ "$1" = '--help' ]; then
usage;
fi;
STAGES=$(echo $1 | tr ',' ' ');
shift 1;
while [[ $# -gt 0 ]]; do
case $1 in
-t|--target)
export TARGET=$2;
shift 2;
;;
-s|--subtarget)
export SUBTARGET=$2;
shift 2;
;;
-m|--target-modifier)
export START_TARGET_MODIFIER=$2;
shift 2;
;;
-p|--rct-http-port)
export RCT_HTTP_PORT=$2;
shift 2;
;;
-S|--service)
SERVICES="$SERVICES $(echo $2 | tr ',' ' ')";
shift 2;
;;
-F|--dump-file)
DUMP_FILE=$2;
shift 2;
;;
-A|--archive-name)
DUMPS_ARCHIVE_NAME=$2;
shift 2;
;;
--ignore-errors)
IGNORE_STAGE_ERRORS='true';
shift 1;
;;
-Y)
ALL_PERMISSIONS='true';
shift 1;
;;
--db-expose)
DB_EXPOSED_PORT=$2;
shift 2;
;;
-b|--build)
BUILD='--build';
shift 1;
;;
-M|--mocha)
export MOCHA_OPTIONS="$2";
shift 2;
;;
*)
usage "Incorrect flag: $1"
;;
esac
done
fi
export TARGET=${TARGET:-dev}
if [[ "$TARGET" = "$DEV_MODE" ]]; then
SUBTARGET=${SUBTARGET:-1};
if ! [[ $SUBTARGET =~ ^[1-9]$ ]]; then
usage "incorrect SUBTARGET $SUBTARGET for target $TARGET";
fi;
elif [[ "$TARGET" = "$TEST_MODE" ]]; then
SUBTARGET=0;
else
usage "incorrect target $TARGET";
fi;
export SUBTARGET;
export APP_CONTAINER_NAME="$O2RCT_ID""_application-$TARGET$SUBTARGET";
export DB_CONTAINER_NAME="$O2RCT_ID""_database-$TARGET$SUBTARGET";
DOCKER_COMP_CMD_NO_ENV="docker compose -p $TARGET$SUBTARGET-$O2RCT_ID
-f $MAIN_DOCKER_COMPOSE_YML
-f $DOCKER_DIR/docker-compose-$TARGET.yml
-f $DOCKER_DIR/docker-compose-network.yml
-f $DOCKER_DIR/docker-compose-volumes.yml
--env-file "$DOCKER_DIR/$TARGET.env"
--project-directory $PROJECT_DIR";
DOCKER_COMP_CMD="$DOCKER_COMP_CMD_NO_ENV -f $DOCKER_DIR/docker-compose-env.yml"
MOCK_DB=${MOCK_DB:-false};
export MOCK_DB;
run() {
SUBCMD_AND_FLAGS="$@";
case $TARGET in
dev)
export DB_EXPOSED_PORT;
OPTIONAL_DB_EXPOSE=$(if [ -n "$DB_EXPOSED_PORT" ]; then echo "-f $DOCKER_DIR/docker-compose-db-expose.yml"; fi);
$DOCKER_COMP_CMD \
$OPTIONAL_DB_EXPOSE \
$SUBCMD_AND_FLAGS $SERVICES;
;;
test)
$DOCKER_COMP_CMD \
$SUBCMD_AND_FLAGS;
;;
*)
usage "Incorrect run target: $TARGET";
;;
esac
}
source $DOCKER_DIR/$TARGET.env
for stage in $STAGES; do
RCT_DB_USER='postgres'; # more privileges than rct-user
echo " *** do $stage";
case $stage in
prune)
# remove contatiner, networks...
for TS in $(docker network ls | grep $O2RCT_ID | awk '{ print $2 }' | awk -F- '{print $1}'); do
T=${TS%?}
S=${TS: -1};
$0 rm --target $T --subtarget $S;
done;
# remove images
docker rmi $(docker images | grep $O2RCT_ID | awk '{ print $1":"$2 }')
;;
rm)
$DOCKER_COMP_CMD_NO_ENV rm --stop --force -v $SERVICES && (docker network rm $TARGET$SUBTARGET-$O2RCT_ID""_network || exit_codes_filter 1);
;;
run*)
RUN_SUBSTATGES=$(echo ${stage#run} | sed -E "s/(\[|\/|\])/ /g");
RUN_SUBSTATGES=$(echo $RUN_SUBSTATGES | sed -E "s/(^[[:space:]]*)|([[:space:]]*$)//g");
if [ -z "$RUN_SUBSTATGES" ]; then
echo 'default run[create/up]; up in detached mode';
RUN_SUBSTATGES="create up";
fi
echo $RUN_SUBSTATGES;
for rs in $RUN_SUBSTATGES; do
if [ "$rs" == 'up' ]; then
if [ "$TARGET" = "$DEV_MODE" ]; then
rs="up --detach";
elif [ "$TARGET" = "$TEST_MODE" ]; then
rs="up --exit-code-from application";
fi;
fi;
rs=$([[ "$rs" == 'create' ]] && echo "$rs $BUILD" || echo "$rs");
echo "*** *** do run : $rs";
run "$rs";
done
;;
follow)
$DOCKER_COMP_CMD logs --follow $SERVICES || exit_codes_filter 1 130;
;;
logs)
$DOCKER_COMP_CMD logs $SERVICES || exit_codes_filter 1;
;;
stop)
$DOCKER_COMP_CMD stop $SERVICES;
;;
db*)
DB_CMD=$(echo ${stage#db:});
case $DB_CMD in
attach)
docker exec -it $DB_CONTAINER_NAME psql -U $RCT_DB_USER -d $RCT_DB_NAME;
;;
battach)
docker exec -it $DB_CONTAINER_NAME /bin/bash;
;;
clean | truncate)
docker cp "$PROJECT_DIR/database/utils/delete-data.sql" "$DB_CONTAINER_NAME:$DB_WORKINGDIR/delete-data.sql" \
&& docker exec $DB_CONTAINER_NAME psql -U $RCT_DB_USER -d $RCT_DB_NAME -f "$DB_WORKINGDIR/delete-data.sql";
;;
ip)
docker inspect $DB_CONTAINER_NAME -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
;;
counts|ct)
docker exec $DB_CONTAINER_NAME /docker-entrypoint-initdb.d/utils/print-data.sh
;;
*)
incorrect_stage_err $stage;
;;
esac
;;
app*)
APP_CMD=$(echo ${stage#app:});
case $APP_CMD in
attach)
docker attach $APP_CONTAINER_NAME || exit_codes_filter 130;
;;
battach)
docker exec -it $APP_CONTAINER_NAME bash
;;
ip)
docker inspect $APP_CONTAINER_NAME -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
;;
*)
incorrect_stage_err $stage;
;;
esac
;;
dump*)
DUMP_CMD=$(echo ${stage#dump:});
DUMPS_DIR="$PROJECT_DIR/database/cache/dumps";
mkdir -p "$DUMPS_DIR";
DUMP_PATH="$DUMPS_DIR/$DUMP_FILE";
CONTAINER_DUMP_PATH="$DB_WORKINGDIR/database/cache/dumps/$DUMP_FILE";
case $DUMP_CMD in
make|mk)
if [ -z "$DUMP_FILE" ]; then
usage "Dump file unspecified, use flag -F|--dump-file <FILE>";
fi
if [ -f "$DUMP_PATH" ]; then
if [[ "$ALL_PERMISSIONS" != 'true' ]]; then
echo "Do you want to overwrite existing file $DUMP_PATH : y|[n] ?";
read permission;
if [[ "$ALL_PERMISSIONS" = 'true' ]] || [[ "$permission" =~ ^y|Y|yes|Yes$ ]]; then
echo "continuing";
else
DO_NOT_PERFORME_WHILE_FILE_EXISTS="true";
echo 'making dump canceled';
fi
fi
fi
if [ -z $DO_NOT_PERFORME_WHILE_FILE_EXISTS ]; then
docker exec $DB_CONTAINER_NAME mkdir -p $(dirname $CONTAINER_DUMP_PATH) \
&& docker exec $DB_CONTAINER_NAME \
pg_dump --data-only --format=tar -d $RCT_DB_NAME -U $RCT_DB_USER --file="$CONTAINER_DUMP_PATH";
fi
;;
list|ls)
ls -lthR "$DUMPS_DIR";
;;
tree)
tree $DUMPS_DIR -t;
;;
browse|br)
DUMPS_HTML="$PROJECT_DIR/reports/dumps.html";
tree -t $DUMPS_DIR -H $DUMPS_DIR -o $DUMPS_HTML;
x-www-browser $DUMPS_HTML &
;;
restore|re)
if [ -z "$DUMP_FILE" ]; then
usage "Dump file name unspecified, use flag -F|--dump-file <FILE>";
fi
docker exec $DB_CONTAINER_NAME psql -U $RCT_DB_USER -d $RCT_DB_NAME -f "$DB_WORKINGDIR/database/utils/delete-data.sql" \
&& docker exec $DB_CONTAINER_NAME pg_restore --data-only -U $RCT_DB_USER -d $RCT_DB_NAME $CONTAINER_DUMP_PATH;
;;
migrate|mg)
if [ -z "$DUMP_FILE" ]; then
usage "Dump file name unspecified, use flag -F|--dump-file <FILE>";
fi
if ! $PROJECT_DIR/rctmake dump:restore -F $DUMP_FILE; then
docker exec $DB_CONTAINER_NAME /docker-entrypoint-initdb.d/utils/print-data.sh
echo Is it ok?
echo "What do you want to do with file: $DUMP_PATH ?";
echo "Cancel operation | Replace | As new File";
echo " : [c]|r|n"
read opt;
if [[ "$opt" =~ ^r$ ]]; then
$PROJECT_DIR/rctmake dump:make -F $DUMP_FILE -Y
elif [[ "$opt" =~ ^n$ ]]; then
$PROJECT_DIR/rctmake dump:make -F $DUMP_FILE.migrated
else
exit 0;
fi
else
echo nothing to do;
fi
;;
remove|rm)
if [ -z "$DUMP_FILE" ]; then
usage "dump file unspecified, use flag -F|--dump-file <FILE>";
fi
rm -rf $DUMP_PATH;
;;
export|ex)
tar -c -f $PREVIOD_USER_LOC/$DUMPS_ARCHIVE_NAME -C $DUMPS_DIR .;
;;
import|im)
tar xvf $PREVIOD_USER_LOC/$DUMPS_ARCHIVE_NAME -C $DUMPS_DIR;
;;
*)
incorrect_stage_err $stage;
;;
esac
;;
*)
incorrect_stage_err $stage
;;
esac
CURRENT_STAGE_STATUS_CODE=$?
if [ $CURRENT_STAGE_STATUS_CODE -ne 0 ]; then
echo "stage $stage ended with code: $CURRENT_STAGE_STATUS_CODE"
if [ -z $IGNORE_STAGE_ERRORS ]; then
exit $CURRENT_STAGE_STATUS_CODE;
fi;
fi;
done
cd $PREVIOD_USER_LOC;