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