6d61b7c3ec163016442c343dca2980c7c3d0c6dd
[discourse_docker.git] / launcher
1 #!/usr/bin/env bash
2
3 usage () {
4 echo "Usage: launcher COMMAND CONFIG [--skip-prereqs] [--docker-args STRING]"
5 echo "Commands:"
6 echo " start: Start/initialize a container"
7 echo " stop: Stop a running container"
8 echo " restart: Restart a container"
9 echo " destroy: Stop and remove a container"
10 echo " enter: Open a shell to run commands inside the container"
11 echo " logs: View the Docker logs for a container"
12 echo " bootstrap: Bootstrap a container for the config based on a template"
13 echo " run: Run the given command with the config in the context of the last bootstrapped image"
14 echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
15 echo " cleanup: Remove all containers that have stopped for > 24 hours"
16 echo " start-cmd: Generate docker command used to start container"
17 echo
18 echo "Options:"
19 echo " --skip-prereqs Don't check launcher prerequisites"
20 echo " --docker-args Extra arguments to pass when running docker"
21 echo " --skip-mac-address Don't assign a mac address"
22 echo " --run-image Override the image used for running the container"
23 exit 1
24 }
25
26 # for potential re-exec later
27 SAVED_ARGV=("$@")
28
29 command=$1
30 config=$2
31
32 # user_args_argv is assigned once when the argument vector is parsed.
33 user_args_argv=""
34 # user_args is mutable: its value may change when templates are parsed.
35 # Superset of user_args_argv.
36 user_args=""
37
38 user_run_image=""
39
40 if [[ $command == "run" ]]; then
41 run_command=$3
42 fi
43
44 while [ ${#} -gt 0 ]; do
45 case "${1}" in
46 --debug)
47 DEBUG="1"
48 ;;
49 --skip-prereqs)
50 SKIP_PREREQS="1"
51 ;;
52 --skip-mac-address)
53 SKIP_MAC_ADDRESS="1"
54 ;;
55 --docker-args)
56 user_args_argv="$2"
57 user_args="$user_args_argv"
58 shift
59 ;;
60 --run-image)
61 user_run_image="$2"
62 shift
63 ;;
64 esac
65
66 shift 1
67 done
68
69 if [ -z "$command" -o -z "$config" -a "$command" != "cleanup" ]; then
70 usage
71 fi
72
73 # Docker doesn't like uppercase characters, spaces or special characters, catch it now before we build everything out and then find out
74 re='[[:upper:]/ !@#$%^&*()+~`=]'
75 if [[ $config =~ $re ]];
76 then
77 echo
78 echo "ERROR: Config name '$config' must not contain upper case characters, spaces or special characters. Correct config name and rerun $0."
79 echo
80 exit 1
81 fi
82
83 cd "$(dirname "$0")"
84
85 pups_version='v1.0.3'
86 docker_min_version='17.03.1'
87 docker_rec_version='17.06.2'
88 git_min_version='1.8.0'
89 git_rec_version='1.8.0'
90
91 config_file=containers/"$config".yml
92 cidbootstrap=cids/"$config"_bootstrap.cid
93 local_discourse=local_discourse
94 image="discourse/base:2.0.20210408-1612"
95 docker_path=`which docker.io 2> /dev/null || which docker`
96 git_path=`which git`
97
98 if [ "${SUPERVISED}" = "true" ]; then
99 restart_policy="--restart=no"
100 attach_on_start="-a"
101 attach_on_run="-a stdout -a stderr"
102 else
103 attach_on_run="-d"
104 fi
105
106 if [ -n "$DOCKER_HOST" ]; then
107 docker_ip=`sed -e 's/^tcp:\/\/\(.*\):.*$/\1/' <<< "$DOCKER_HOST"`
108 elif [ -x "$(which ip 2>/dev/null)" ]; then
109 docker_ip=`ip addr show docker0 | \
110 grep 'inet ' | \
111 awk '{ split($2,a,"/"); print a[1] }';`
112 else
113 docker_ip=`ifconfig | \
114 grep -B1 "inet addr" | \
115 awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
116 grep docker0 | \
117 awk -F: '{ print $3 }';`
118 fi
119
120 # From https://stackoverflow.com/a/44660519/702738
121 compare_version() {
122 if [[ $1 == $2 ]]; then
123 return 1
124 fi
125 local IFS=.
126 local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
127 local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
128 for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
129 if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
130 return 1
131 elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
132 return 0
133 fi
134 done
135 if [ "$arem" '<' "$brem" ]; then
136 return 1
137 elif [ "$arem" '>' "$brem" ]; then
138 return 0
139 fi
140 return 1
141 }
142
143
144 install_docker() {
145 echo "Docker is not installed, you will need to install Docker in order to run Launcher"
146 echo "See https://docs.docker.com/installation/"
147 exit 1
148 }
149
150 pull_image() {
151 # Add a single retry to work around dockerhub TLS errors
152 $docker_path pull $image || $docker_path pull $image
153 }
154
155 check_prereqs() {
156
157 if [ -z $docker_path ]; then
158 install_docker
159 fi
160
161 # 1. docker daemon running?
162 # we send stderr to /dev/null cause we don't care about warnings,
163 # it usually complains about swap which does not matter
164 test=`$docker_path info 2> /dev/null`
165 if [[ $? -ne 0 ]] ; then
166 echo "Cannot connect to the docker daemon - verify it is running and you have access"
167 exit 1
168 fi
169
170 # 2. running an approved storage driver?
171 if ! $docker_path info 2> /dev/null | egrep -q 'Storage Driver: (aufs|zfs|overlay2)$'; then
172 echo "Your Docker installation is not using a supported storage driver. If we were to proceed you may have a broken install."
173 echo "overlay2 is the recommended storage driver, although zfs and aufs may work as well."
174 echo "Other storage drivers are known to be problematic."
175 echo "You can tell what filesystem you are using by running \"docker info\" and looking at the 'Storage Driver' line."
176 echo
177 echo "If you wish to continue anyway using your existing unsupported storage driver,"
178 echo "read the source code of launcher and figure out how to bypass this check."
179 exit 1
180 fi
181
182 # 3. running recommended docker version
183 test=($($docker_path --version)) # Get docker version string
184 test=${test[2]//,/} # Get version alone and strip comma if exists
185
186 # At least minimum docker version
187 if compare_version "${docker_min_version}" "${test}"; then
188 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
189 exit 1
190 fi
191
192 # Recommend newer docker version
193 if compare_version "${docker_rec_version}" "${test}"; then
194 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
195 fi
196
197 # 4. discourse docker image is downloaded
198 test=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$image"`
199
200 if [ -z "$test" ]; then
201 echo
202 echo "WARNING: We are about to start downloading the Discourse base image"
203 echo "This process may take anywhere between a few minutes to an hour, depending on your network speed"
204 echo
205 echo "Please be patient"
206 echo
207
208 pull_image
209 fi
210
211 # 5. running recommended git version
212 test=($($git_path --version)) # Get git version string
213 test=${test[2]//,/} # Get version alone and strip comma if exists
214
215 # At least minimum version
216 if compare_version "${git_min_version}" "${test}"; then
217 echo "ERROR: Git version ${test} not supported, please upgrade to at least ${git_min_version}, or recommended ${git_rec_version}"
218 exit 1
219 fi
220
221 # Recommend best version
222 if compare_version "${git_rec_version}" "${test}"; then
223 echo "WARNING: Git version ${test} deprecated, recommend upgrade to ${git_rec_version} or newer."
224 fi
225
226 # 6. able to attach stderr / out / tty
227 test=`$docker_path run $user_args -i --rm -a stdout -a stderr $image echo working`
228 if [[ "$test" =~ "working" ]] ; then : ; else
229 echo "Your Docker installation is not working correctly"
230 echo
231 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
232 exit 1
233 fi
234
235 # 7. enough space for the bootstrap on docker folder
236 folder=`$docker_path info --format '{{.DockerRootDir}}'`
237 safe_folder=${folder:-/var/lib/docker}
238 test=$(($(stat -f --format="%a*%S" $safe_folder)/1024**3 < 5))
239 if [[ $test -ne 0 ]] ; then
240 echo "You have less than 5GB of free space on the disk where $safe_folder is located. You will need more space to continue"
241 df -h $safe_folder
242 echo
243 if tty >/dev/null; then
244 read -p "Would you like to attempt to recover space by cleaning docker images and containers in the system? (y/N)" -n 1 -r
245 echo
246 if [[ $REPLY =~ ^[Yy]$ ]]
247 then
248 $docker_path container prune --force --filter until=24h >/dev/null
249 $docker_path image prune --all --force --filter until=24h >/dev/null
250 echo "If the cleanup was successful, you may try again now"
251 fi
252 fi
253 exit 1
254 fi
255 }
256
257
258 if [ -z "$SKIP_PREREQS" ] && [ "$command" != "cleanup" ]; then
259 check_prereqs
260 fi
261
262 set_volumes() {
263 volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
264 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
265 }
266
267 set_links() {
268 links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
269 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
270 }
271
272 find_templates() {
273 local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
274 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
275
276 local arrTemplates=${templates// / }
277
278 if [ ! -z "$templates" ]; then
279 for template in "${arrTemplates[@]}"
280 do
281 local nested_templates=$(find_templates $template)
282
283 if [ ! -z "$nested_templates" ]; then
284 templates="$nested_templates $templates"
285 fi
286 done
287
288 echo $templates
289 else
290 echo ""
291 fi
292 }
293
294 set_template_info() {
295 templates=$(find_templates $config_file)
296
297 arrTemplates=(${templates// / })
298 config_data=$(cat $config_file)
299
300 input="hack: true"
301
302 for template in "${arrTemplates[@]}"
303 do
304 [ ! -z $template ] && {
305 input="$input _FILE_SEPERATOR_ $(cat $template)"
306 }
307 done
308
309 # we always want our config file last so it takes priority
310 input="$input _FILE_SEPERATOR_ $config_data"
311
312 read -r -d '' env_ruby << 'RUBY'
313 require 'yaml'
314
315 input=STDIN.readlines.join
316 # default to UTF-8 for the dbs sake
317 env = {'LANG' => 'en_US.UTF-8'}
318 input.split('_FILE_SEPERATOR_').each do |yml|
319 yml.strip!
320 begin
321 env.merge!(YAML.load(yml)['env'] || {})
322 rescue Psych::SyntaxError => e
323 puts e
324 puts "*ERROR."
325 rescue => e
326 puts yml
327 p e
328 end
329 end
330 env.each{|k,v| puts "*ERROR." if v.is_a?(Hash)}
331 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
332 RUBY
333
334 tmp_input_file=$(mktemp)
335
336 echo "$input" > "$tmp_input_file"
337 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
338
339 rm -f "$tmp_input_file"
340
341 env=()
342 ok=1
343 while read i; do
344 if [ "$i" == "*ERROR." ]; then
345 ok=0
346 elif [ -n "$i" ]; then
347 env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
348 fi
349 done <<< "$raw"
350
351 if [ "$ok" -ne 1 ]; then
352 echo "${env[@]}"
353 echo "YAML syntax error. Please check your containers/*.yml config files."
354 exit 1
355 fi
356
357 # labels
358 read -r -d '' labels_ruby << 'RUBY'
359 require 'yaml'
360
361 input=STDIN.readlines.join
362 labels = {}
363 input.split('_FILE_SEPERATOR_').each do |yml|
364 yml.strip!
365 begin
366 labels.merge!(YAML.load(yml)['labels'] || {})
367 rescue Psych::SyntaxError => e
368 puts e
369 puts "*ERROR."
370 rescue => e
371 puts yml
372 p e
373 end
374 end
375 puts labels.map{|k,v| "-l\n#{k}=#{v}" }.join("\n")
376 RUBY
377
378 tmp_input_file=$(mktemp)
379
380 echo "$input" > "$tmp_input_file"
381 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$labels_ruby"`
382
383 rm -f "$tmp_input_file"
384
385 labels=()
386 ok=1
387 while read i; do
388 if [ "$i" == "*ERROR." ]; then
389 ok=0
390 elif [ -n "$i" ]; then
391 labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
392 fi
393 done <<< "$raw"
394
395 if [ "$ok" -ne 1 ]; then
396 echo "${labels[@]}"
397 echo "YAML syntax error. Please check your containers/*.yml config files."
398 exit 1
399 fi
400
401 # expose
402 read -r -d '' ports_ruby << 'RUBY'
403 require 'yaml'
404
405 input=STDIN.readlines.join
406 ports = []
407 input.split('_FILE_SEPERATOR_').each do |yml|
408 yml.strip!
409 begin
410 ports += (YAML.load(yml)['expose'] || [])
411 rescue Psych::SyntaxError => e
412 puts e
413 puts "*ERROR."
414 rescue => e
415 puts yml
416 p e
417 end
418 end
419 puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
420 RUBY
421
422 tmp_input_file=$(mktemp)
423
424 echo "$input" > "$tmp_input_file"
425 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`
426
427 rm -f "$tmp_input_file"
428
429 ports=()
430 ok=1
431 while read i; do
432 if [ "$i" == "*ERROR." ]; then
433 ok=0
434 elif [ -n "$i" ]; then
435 ports[${#ports[@]}]=$i
436 fi
437 done <<< "$raw"
438
439 if [ "$ok" -ne 1 ]; then
440 echo "${ports[@]}"
441 echo "YAML syntax error. Please check your containers/*.yml config files."
442 exit 1
443 fi
444
445 merge_user_args
446 }
447
448 if [ -z $docker_path ]; then
449 install_docker
450 fi
451
452 [ "$command" == "cleanup" ] && {
453 $docker_path container prune --filter until=1h
454 $docker_path image prune --all --filter until=1h
455
456 if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
457 echo
458 echo "Old PostgreSQL backup data cluster detected taking up $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detected"
459 read -p "Would you like to remove it? (y/N): " -n 1 -r && echo
460
461 if [[ $REPLY =~ ^[Yy]$ ]]; then
462 echo "removing old PostgreSQL data cluster at /var/discourse/shared/standalone/postgres_data_old..."
463 rm -rf /var/discourse/shared/standalone/postgres_data_old*
464 else
465 exit 1
466 fi
467 fi
468
469 exit 0
470 }
471
472 if [ ! "$command" == "setup" ]; then
473 if [[ ! -e $config_file ]]; then
474 echo "Config file was not found, ensure $config_file exists"
475 echo
476 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
477 exit 1
478 fi
479 fi
480
481 docker_version=($($docker_path --version))
482 docker_version=${test[2]//,/}
483 restart_policy=${restart_policy:---restart=always}
484
485 set_existing_container(){
486 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
487 }
488
489 run_stop() {
490
491 set_existing_container
492
493 if [ ! -z $existing ]
494 then
495 (
496 set -x
497 $docker_path stop -t 30 $config
498 )
499 else
500 echo "$config was not started !"
501 echo "./discourse-doctor may help diagnose the problem."
502 exit 1
503 fi
504 }
505
506 set_run_image() {
507 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
508 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
509
510 if [ -n "$user_run_image" ]; then
511 run_image=$user_run_image
512 elif [ -z "$run_image" ]; then
513 run_image="$local_discourse/$config"
514 fi
515 }
516
517 set_boot_command() {
518 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
519 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
520
521 if [ -z "$boot_command" ]; then
522
523 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
524 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
525
526 if [ -z "$no_boot_command" ]; then
527 boot_command="/sbin/boot"
528 fi
529 fi
530 }
531
532 merge_user_args() {
533 local docker_args
534
535 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
536 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
537
538 if [[ -n "$docker_args" ]]; then
539 user_args="$user_args_argv $docker_args"
540 fi
541 }
542
543 run_start() {
544
545 if [ -z "$START_CMD_ONLY" ]
546 then
547 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
548 echo $existing
549 if [ ! -z $existing ]
550 then
551 echo "Nothing to do, your container has already started!"
552 exit 0
553 fi
554
555 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
556 if [ ! -z $existing ]
557 then
558 echo "starting up existing container"
559 (
560 set -x
561 $docker_path start $config
562 )
563 exit 0
564 fi
565 fi
566
567 set_template_info
568 set_volumes
569 set_links
570 set_run_image
571 set_boot_command
572
573 # get hostname and settings from container configuration
574 for envar in "${env[@]}"
575 do
576 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
577 then
578 # use as environment variable
579 eval $envar
580 fi
581 done
582
583 (
584 hostname=`hostname -s`
585 # overwrite hostname
586 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
587 then
588 hostname=$DISCOURSE_HOSTNAME
589 else
590 hostname=$hostname-$config
591 fi
592
593 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
594 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
595 # docker added more hostname rules
596 hostname=${hostname//_/-}
597
598
599 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
600 mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
601 fi
602
603 if [ ! -z "$START_CMD_ONLY" ] ; then
604 docker_path="true"
605 fi
606
607 set -x
608
609 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
610 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
611 $run_image $boot_command
612
613 )
614 exit 0
615
616 }
617
618 run_run() {
619 set_template_info
620 set_volumes
621 set_links
622 set_run_image
623
624 unset ERR
625 (exec $docker_path run --rm --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" -i -a stdin -a stdout -a stderr $volumes $run_image \
626 /bin/bash -c "$run_command") || ERR=$?
627
628 if [[ $ERR > 0 ]]; then
629 exit 1
630 fi
631 }
632
633 run_bootstrap() {
634 # Is the image available?
635 # If not, pull it here so the user is aware what's happening.
636 $docker_path history $image >/dev/null 2>&1 || pull_image
637
638 set_template_info
639
640 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
641 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
642
643 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
644 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
645
646 if [[ ! X"" = X"$base_image" ]]; then
647 image=$base_image
648 fi
649
650 set_volumes
651 set_links
652
653 rm -f $cidbootstrap
654
655 run_command="cd /pups &&"
656 if [[ ! "false" = $update_pups ]]; then
657 run_command="$run_command git pull && git checkout $pups_version &&"
658 fi
659 run_command="$run_command /pups/bin/pups --stdin"
660
661 echo $run_command
662
663 unset ERR
664
665 tmp_input_file=$(mktemp)
666
667 echo "$input" > "$tmp_input_file"
668 (exec cat "$tmp_input_file" | $docker_path run --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" --cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
669 /bin/bash -c "$run_command") || ERR=$?
670
671 rm -f "$tmp_input_file"
672
673 unset FAILED
674 # magic exit code that indicates a retry
675 if [[ "$ERR" == 77 ]]; then
676 $docker_path rm `cat $cidbootstrap`
677 rm $cidbootstrap
678 exit 77
679 elif [[ "$ERR" > 0 ]]; then
680 FAILED=TRUE
681 fi
682
683 if [[ $FAILED = "TRUE" ]]; then
684 if [[ ! -z "$DEBUG" ]]; then
685 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
686 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
687 fi
688
689 $docker_path rm `cat $cidbootstrap`
690 rm $cidbootstrap
691 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one."
692 echo "./discourse-doctor may help diagnose the problem."
693 exit 1
694 fi
695
696 sleep 5
697
698 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
699 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
700 }
701
702 case "$command" in
703 bootstrap)
704 run_bootstrap
705 echo "Successfully bootstrapped, to startup use ./launcher start $config"
706 exit 0
707 ;;
708
709 run)
710 run_run
711 exit 0
712 ;;
713
714 enter)
715 exec $docker_path exec -it $config /bin/bash --login
716 ;;
717
718 stop)
719 run_stop
720 exit 0
721 ;;
722
723 logs)
724
725 $docker_path logs $config
726 exit 0
727 ;;
728
729 restart)
730 run_stop
731 run_start
732 exit 0
733 ;;
734
735 start-cmd)
736 START_CMD_ONLY="1"
737 run_start
738 exit 0;
739 ;;
740
741 start)
742 run_start
743 exit 0
744 ;;
745
746 rebuild)
747 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
748 echo "Ensuring launcher is up to date"
749
750 git remote update
751
752 LOCAL=$(git rev-parse HEAD)
753 REMOTE=$(git rev-parse @{u})
754 BASE=$(git merge-base HEAD @{u})
755
756 if [ $LOCAL = $REMOTE ]; then
757 echo "Launcher is up-to-date"
758
759 elif [ $LOCAL = $BASE ]; then
760 echo "Updating Launcher..."
761 git pull || (echo 'failed to update' && exit 1)
762
763 echo "Launcher updated, restarting..."
764 exec "$0" "${SAVED_ARGV[@]}"
765
766 elif [ $REMOTE = $BASE ]; then
767 echo "Your version of Launcher is ahead of origin"
768
769 else
770 echo "Launcher has diverged source, this is only expected in Dev mode"
771 fi
772
773 fi
774
775 set_existing_container
776
777 if [ ! -z $existing ]
778 then
779 echo "Stopping old container"
780 (
781 set -x
782 $docker_path stop -t 60 $config
783 )
784 fi
785
786 run_bootstrap
787
788 if [ ! -z $existing ]
789 then
790 echo "Removing old container"
791 (
792 set -x
793 $docker_path rm $config
794 )
795 fi
796
797 run_start
798 exit 0
799 ;;
800
801
802 destroy)
803 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
804 exit 0
805 ;;
806 esac
807
808 usage