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