Update docker base image
[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 "$command" -o -z "$config" -a "$command" != "cleanup" ]; 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.20190217
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_path system prune -af
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//\{\{config\}\}/${config}}"
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 # labels
367 read -r -d '' labels_ruby << 'RUBY'
368 require 'yaml'
369
370 input=STDIN.readlines.join
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 # expose
411 read -r -d '' ports_ruby << 'RUBY'
412 require 'yaml'
413
414 input=STDIN.readlines.join
415 ports = []
416 input.split('_FILE_SEPERATOR_').each do |yml|
417 yml.strip!
418 begin
419 ports += (YAML.load(yml)['expose'] || [])
420 rescue Psych::SyntaxError => e
421 puts e
422 puts "*ERROR."
423 rescue => e
424 puts yml
425 p e
426 end
427 end
428 puts ports.map {|p| "-p\n#{p}"}.join("\n")
429 RUBY
430
431 tmp_input_file=$(mktemp)
432
433 echo "$input" > "$tmp_input_file"
434 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`
435
436 rm -f "$tmp_input_file"
437
438 ports=()
439 ok=1
440 while read i; do
441 if [ "$i" == "*ERROR." ]; then
442 ok=0
443 elif [ -n "$i" ]; then
444 ports[${#ports[@]}]=$i
445 fi
446 done <<< "$raw"
447
448 if [ "$ok" -ne 1 ]; then
449 echo "${ports[@]}"
450 echo "YAML syntax error. Please check your containers/*.yml config files."
451 exit 1
452 fi
453
454 merge_user_args
455 }
456
457 if [ -z $docker_path ]; then
458 install_docker
459 fi
460
461 [ "$command" == "cleanup" ] && {
462 $docker_path system prune -a
463
464 if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
465 echo
466 echo "Old PostgreSQL backup data cluster detected taking up $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detected"
467 read -p "Would you like to remove it? (Y/n): " -n 1 -r && echo
468
469 if [[ $REPLY =~ ^[Yy]$ ]]; then
470 echo "removing old PostgreSQL data cluster at /var/discourse/shared/standalone/postgres_data_old..."
471 rm -rf /var/discourse/shared/standalone/postgres_data_old
472 else
473 exit 1
474 fi
475 fi
476
477 exit 0
478 }
479
480 if [ ! "$command" == "setup" ]; then
481 if [[ ! -e $config_file ]]; then
482 echo "Config file was not found, ensure $config_file exists"
483 echo
484 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
485 exit 1
486 fi
487 fi
488
489 docker_version=($($docker_path --version))
490 docker_version=${test[2]//,/}
491 restart_policy=${restart_policy:---restart=always}
492
493 set_existing_container(){
494 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
495 }
496
497 run_stop() {
498
499 set_existing_container
500
501 if [ ! -z $existing ]
502 then
503 (
504 set -x
505 $docker_path stop -t 10 $config
506 )
507 else
508 echo "$config was not started !"
509 exit 1
510 fi
511 }
512
513 set_run_image() {
514 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
515 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
516
517 if [ -n "$user_run_image" ]; then
518 run_image=$user_run_image
519 elif [ -z "$run_image" ]; then
520 run_image="$local_discourse/$config"
521 fi
522 }
523
524 set_boot_command() {
525 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
526 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
527
528 if [ -z "$boot_command" ]; then
529
530 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
531 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
532
533 if [ -z "$no_boot_command" ]; then
534 boot_command="/sbin/boot"
535 fi
536 fi
537 }
538
539 merge_user_args() {
540 local docker_args
541
542 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
543 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
544
545 if [[ -n "$docker_args" ]]; then
546 user_args="$user_args $docker_args"
547 fi
548 }
549
550 run_start() {
551
552 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
553 echo $existing
554 if [ ! -z $existing ]
555 then
556 echo "Nothing to do, your container has already started!"
557 exit 0
558 fi
559
560 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
561 if [ ! -z $existing ]
562 then
563 echo "starting up existing container"
564 (
565 set -x
566 $docker_path start $config
567 )
568 exit 0
569 fi
570
571 host_run
572
573 set_template_info
574 set_volumes
575 set_links
576 set_run_image
577 set_boot_command
578
579 # get hostname and settings from container configuration
580 for envar in "${env[@]}"
581 do
582 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
583 then
584 # use as environment variable
585 eval $envar
586 fi
587 done
588
589 (
590 hostname=`hostname -s`
591 # overwrite hostname
592 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
593 then
594 hostname=$DISCOURSE_HOSTNAME
595 else
596 hostname=$hostname-$config
597 fi
598
599 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
600 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
601 # docker added more hostname rules
602 hostname=${hostname//_/-}
603
604
605 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
606 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/'")"
607 fi
608
609 set -x
610 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
611 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
612 $run_image $boot_command
613
614 )
615 exit 0
616
617 }
618
619 run_run() {
620 set_template_info
621 set_volumes
622 set_links
623 set_run_image
624
625 unset ERR
626 (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 \
627 /bin/bash -c "$run_command") || ERR=$?
628
629 if [[ $ERR > 0 ]]; then
630 exit 1
631 fi
632 }
633
634 run_bootstrap() {
635 host_run
636
637 # Is the image available?
638 # If not, pull it here so the user is aware what's happening.
639 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
640
641 set_template_info
642
643 base_image=`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)['base_image']"`
645
646 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
647 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
648
649 if [[ ! X"" = X"$base_image" ]]; then
650 image=$base_image
651 fi
652
653 set_volumes
654 set_links
655
656 rm -f $cidbootstrap
657
658 run_command="cd /pups &&"
659 if [[ ! "false" = $update_pups ]]; then
660 run_command="$run_command git pull &&"
661 fi
662 run_command="$run_command /pups/bin/pups --stdin"
663
664 echo $run_command
665
666 unset ERR
667
668 tmp_input_file=$(mktemp)
669
670 echo "$input" > "$tmp_input_file"
671 (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 \
672 /bin/bash -c "$run_command") || ERR=$?
673
674 rm -f "$tmp_input_file"
675
676 unset FAILED
677 # magic exit code that indicates a retry
678 if [[ "$ERR" == 77 ]]; then
679 $docker_path rm `cat $cidbootstrap`
680 rm $cidbootstrap
681 exit 77
682 elif [[ "$ERR" > 0 ]]; then
683 FAILED=TRUE
684 fi
685
686 if [[ $FAILED = "TRUE" ]]; then
687 if [[ ! -z "$DEBUG" ]]; then
688 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
689 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
690 fi
691
692 $docker_path rm `cat $cidbootstrap`
693 rm $cidbootstrap
694 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one"
695 exit 1
696 fi
697
698 sleep 5
699
700 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
701 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
702 }
703
704 case "$command" in
705 bootstrap)
706 run_bootstrap
707 echo "Successfully bootstrapped, to startup use ./launcher start $config"
708 exit 0
709 ;;
710
711 run)
712 run_run
713 exit 0
714 ;;
715
716 enter)
717 exec $docker_path exec -it $config /bin/bash --login
718 ;;
719
720 stop)
721 run_stop
722 exit 0
723 ;;
724
725 logs)
726
727 $docker_path logs $config
728 exit 0
729 ;;
730
731 restart)
732 run_stop
733 run_start
734 exit 0
735 ;;
736
737 start)
738 run_start
739 exit 0
740 ;;
741
742 rebuild)
743 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
744 echo "Ensuring launcher is up to date"
745
746 git remote update
747
748 LOCAL=$(git rev-parse @)
749 REMOTE=$(git rev-parse @{u})
750 BASE=$(git merge-base @ @{u})
751
752 if [ $LOCAL = $REMOTE ]; then
753 echo "Launcher is up-to-date"
754
755 elif [ $LOCAL = $BASE ]; then
756 echo "Updating Launcher"
757 git pull || (echo 'failed to update' && exit 1)
758
759 for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
760 do
761 args[$j]=${BASH_ARGV[$i]}
762 done
763 exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
764
765 elif [ $REMOTE = $BASE ]; then
766 echo "Your version of Launcher is ahead of origin"
767
768 else
769 echo "Launcher has diverged source, this is only expected in Dev mode"
770 fi
771
772 fi
773
774 set_existing_container
775
776 if [ ! -z $existing ]
777 then
778 echo "Stopping old container"
779 (
780 set -x
781 $docker_path stop -t 10 $config
782 )
783 fi
784
785 run_bootstrap
786
787 if [ ! -z $existing ]
788 then
789 echo "Removing old container"
790 (
791 set -x
792 $docker_path rm $config
793 )
794 fi
795
796 run_start
797 exit 0
798 ;;
799
800
801 destroy)
802 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
803 exit 0
804 ;;
805 esac
806
807 usage