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