FIX: discourse-doctor plugin check too loose (#478)
[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 exit 1
72 fi
73
74 # Docker doesn't like uppercase characters, spaces or special characters, catch it now before we build everything out and then find out
75 re='[[:upper:]/ !@#$%^&*()+~`=]'
76 if [[ $config =~ $re ]];
77 then
78 echo
79 echo "ERROR: Config name '$config' must not contain upper case characters, spaces or special characters. Correct config name and rerun $0."
80 echo
81 exit 1
82 fi
83
84 cd "$(dirname "$0")"
85
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.20200724-1815"
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=1h >/dev/null
249 $docker_path image prune --all --force --filter until=1h >/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 host_run() {
263 read -r -d '' env_ruby << 'RUBY'
264 require 'yaml'
265
266 input = STDIN.readlines.join
267 yaml = YAML.load(input)
268
269 if host_run = yaml['host_run']
270 params = yaml['params'] || {}
271 host_run.each do |run|
272 params.each do |k,v|
273 run = run.gsub("$#{k}", v)
274 end
275 STDOUT.write "#{run}--SEP--"
276 end
277 end
278 RUBY
279
280 host_run=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
281
282 while [ "$host_run" ] ; do
283 iter=${host_run%%--SEP--*}
284 echo
285 echo "Host run: $iter"
286 $iter || exit 1
287 echo
288 host_run="${host_run#*--SEP--}"
289 done
290 }
291
292
293 set_volumes() {
294 volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
295 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
296 }
297
298 set_links() {
299 links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
300 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
301 }
302
303 find_templates() {
304 local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
305 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
306
307 local arrTemplates=${templates// / }
308
309 if [ ! -z "$templates" ]; then
310 for template in "${arrTemplates[@]}"
311 do
312 local nested_templates=$(find_templates $template)
313
314 if [ ! -z "$nested_templates" ]; then
315 templates="$templates $nested_templates"
316 fi
317 done
318
319 echo $templates
320 else
321 echo ""
322 fi
323 }
324
325 set_template_info() {
326 templates=$(find_templates $config_file)
327
328 arrTemplates=(${templates// / })
329 config_data=$(cat $config_file)
330
331 input="hack: true"
332
333 for template in "${arrTemplates[@]}"
334 do
335 [ ! -z $template ] && {
336 input="$input _FILE_SEPERATOR_ $(cat $template)"
337 }
338 done
339
340 # we always want our config file last so it takes priority
341 input="$input _FILE_SEPERATOR_ $config_data"
342
343 read -r -d '' env_ruby << 'RUBY'
344 require 'yaml'
345
346 input=STDIN.readlines.join
347 # default to UTF-8 for the dbs sake
348 env = {'LANG' => 'en_US.UTF-8'}
349 input.split('_FILE_SEPERATOR_').each do |yml|
350 yml.strip!
351 begin
352 env.merge!(YAML.load(yml)['env'] || {})
353 rescue Psych::SyntaxError => e
354 puts e
355 puts "*ERROR."
356 rescue => e
357 puts yml
358 p e
359 end
360 end
361 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
362 RUBY
363
364 tmp_input_file=$(mktemp)
365
366 echo "$input" > "$tmp_input_file"
367 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
368
369 rm -f "$tmp_input_file"
370
371 env=()
372 ok=1
373 while read i; do
374 if [ "$i" == "*ERROR." ]; then
375 ok=0
376 elif [ -n "$i" ]; then
377 env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
378 fi
379 done <<< "$raw"
380
381 if [ "$ok" -ne 1 ]; then
382 echo "${env[@]}"
383 echo "YAML syntax error. Please check your containers/*.yml config files."
384 exit 1
385 fi
386
387 # labels
388 read -r -d '' labels_ruby << 'RUBY'
389 require 'yaml'
390
391 input=STDIN.readlines.join
392 labels = {}
393 input.split('_FILE_SEPERATOR_').each do |yml|
394 yml.strip!
395 begin
396 labels.merge!(YAML.load(yml)['labels'] || {})
397 rescue Psych::SyntaxError => e
398 puts e
399 puts "*ERROR."
400 rescue => e
401 puts yml
402 p e
403 end
404 end
405 puts labels.map{|k,v| "-l\n#{k}=#{v}" }.join("\n")
406 RUBY
407
408 tmp_input_file=$(mktemp)
409
410 echo "$input" > "$tmp_input_file"
411 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$labels_ruby"`
412
413 rm -f "$tmp_input_file"
414
415 labels=()
416 ok=1
417 while read i; do
418 if [ "$i" == "*ERROR." ]; then
419 ok=0
420 elif [ -n "$i" ]; then
421 labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
422 fi
423 done <<< "$raw"
424
425 if [ "$ok" -ne 1 ]; then
426 echo "${labels[@]}"
427 echo "YAML syntax error. Please check your containers/*.yml config files."
428 exit 1
429 fi
430
431 # expose
432 read -r -d '' ports_ruby << 'RUBY'
433 require 'yaml'
434
435 input=STDIN.readlines.join
436 ports = []
437 input.split('_FILE_SEPERATOR_').each do |yml|
438 yml.strip!
439 begin
440 ports += (YAML.load(yml)['expose'] || [])
441 rescue Psych::SyntaxError => e
442 puts e
443 puts "*ERROR."
444 rescue => e
445 puts yml
446 p e
447 end
448 end
449 puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
450 RUBY
451
452 tmp_input_file=$(mktemp)
453
454 echo "$input" > "$tmp_input_file"
455 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`
456
457 rm -f "$tmp_input_file"
458
459 ports=()
460 ok=1
461 while read i; do
462 if [ "$i" == "*ERROR." ]; then
463 ok=0
464 elif [ -n "$i" ]; then
465 ports[${#ports[@]}]=$i
466 fi
467 done <<< "$raw"
468
469 if [ "$ok" -ne 1 ]; then
470 echo "${ports[@]}"
471 echo "YAML syntax error. Please check your containers/*.yml config files."
472 exit 1
473 fi
474
475 merge_user_args
476 }
477
478 if [ -z $docker_path ]; then
479 install_docker
480 fi
481
482 [ "$command" == "cleanup" ] && {
483 $docker_path container prune --filter until=1h
484 $docker_path image prune --all --filter until=1h
485
486 if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
487 echo
488 echo "Old PostgreSQL backup data cluster detected taking up $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detected"
489 read -p "Would you like to remove it? (Y/n): " -n 1 -r && echo
490
491 if [[ $REPLY =~ ^[Yy]$ ]]; then
492 echo "removing old PostgreSQL data cluster at /var/discourse/shared/standalone/postgres_data_old..."
493 rm -rf /var/discourse/shared/standalone/postgres_data_old*
494 else
495 exit 1
496 fi
497 fi
498
499 exit 0
500 }
501
502 if [ ! "$command" == "setup" ]; then
503 if [[ ! -e $config_file ]]; then
504 echo "Config file was not found, ensure $config_file exists"
505 echo
506 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
507 exit 1
508 fi
509 fi
510
511 docker_version=($($docker_path --version))
512 docker_version=${test[2]//,/}
513 restart_policy=${restart_policy:---restart=always}
514
515 set_existing_container(){
516 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
517 }
518
519 run_stop() {
520
521 set_existing_container
522
523 if [ ! -z $existing ]
524 then
525 (
526 set -x
527 $docker_path stop -t 10 $config
528 )
529 else
530 echo "$config was not started !"
531 echo "./discourse-doctor may help diagnose the problem."
532 exit 1
533 fi
534 }
535
536 set_run_image() {
537 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
538 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
539
540 if [ -n "$user_run_image" ]; then
541 run_image=$user_run_image
542 elif [ -z "$run_image" ]; then
543 run_image="$local_discourse/$config"
544 fi
545 }
546
547 set_boot_command() {
548 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
549 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
550
551 if [ -z "$boot_command" ]; then
552
553 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
554 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
555
556 if [ -z "$no_boot_command" ]; then
557 boot_command="/sbin/boot"
558 fi
559 fi
560 }
561
562 merge_user_args() {
563 local docker_args
564
565 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
566 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
567
568 if [[ -n "$docker_args" ]]; then
569 user_args="$user_args_argv $docker_args"
570 fi
571 }
572
573 run_start() {
574
575 if [ -z "$START_CMD_ONLY" ]
576 then
577 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
578 echo $existing
579 if [ ! -z $existing ]
580 then
581 echo "Nothing to do, your container has already started!"
582 exit 0
583 fi
584
585 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
586 if [ ! -z $existing ]
587 then
588 echo "starting up existing container"
589 (
590 set -x
591 $docker_path start $config
592 )
593 exit 0
594 fi
595 fi
596
597 host_run
598
599 set_template_info
600 set_volumes
601 set_links
602 set_run_image
603 set_boot_command
604
605 # get hostname and settings from container configuration
606 for envar in "${env[@]}"
607 do
608 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
609 then
610 # use as environment variable
611 eval $envar
612 fi
613 done
614
615 (
616 hostname=`hostname -s`
617 # overwrite hostname
618 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
619 then
620 hostname=$DISCOURSE_HOSTNAME
621 else
622 hostname=$hostname-$config
623 fi
624
625 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
626 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
627 # docker added more hostname rules
628 hostname=${hostname//_/-}
629
630
631 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
632 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/'")"
633 fi
634
635 if [ ! -z "$START_CMD_ONLY" ] ; then
636 docker_path="true"
637 fi
638
639 set -x
640
641 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
642 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
643 $run_image $boot_command
644
645 )
646 exit 0
647
648 }
649
650 run_run() {
651 set_template_info
652 set_volumes
653 set_links
654 set_run_image
655
656 unset ERR
657 (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 \
658 /bin/bash -c "$run_command") || ERR=$?
659
660 if [[ $ERR > 0 ]]; then
661 exit 1
662 fi
663 }
664
665 run_bootstrap() {
666 host_run
667
668 # Is the image available?
669 # If not, pull it here so the user is aware what's happening.
670 $docker_path history $image >/dev/null 2>&1 || pull_image
671
672 set_template_info
673
674 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
675 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
676
677 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
678 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
679
680 if [[ ! X"" = X"$base_image" ]]; then
681 image=$base_image
682 fi
683
684 set_volumes
685 set_links
686
687 rm -f $cidbootstrap
688
689 run_command="cd /pups &&"
690 if [[ ! "false" = $update_pups ]]; then
691 run_command="$run_command git pull &&"
692 fi
693 run_command="$run_command /pups/bin/pups --stdin"
694
695 echo $run_command
696
697 unset ERR
698
699 tmp_input_file=$(mktemp)
700
701 echo "$input" > "$tmp_input_file"
702 (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 \
703 /bin/bash -c "$run_command") || ERR=$?
704
705 rm -f "$tmp_input_file"
706
707 unset FAILED
708 # magic exit code that indicates a retry
709 if [[ "$ERR" == 77 ]]; then
710 $docker_path rm `cat $cidbootstrap`
711 rm $cidbootstrap
712 exit 77
713 elif [[ "$ERR" > 0 ]]; then
714 FAILED=TRUE
715 fi
716
717 if [[ $FAILED = "TRUE" ]]; then
718 if [[ ! -z "$DEBUG" ]]; then
719 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
720 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
721 fi
722
723 $docker_path rm `cat $cidbootstrap`
724 rm $cidbootstrap
725 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one."
726 echo "./discourse-doctor may help diagnose the problem."
727 exit 1
728 fi
729
730 sleep 5
731
732 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
733 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
734 }
735
736 case "$command" in
737 bootstrap)
738 run_bootstrap
739 echo "Successfully bootstrapped, to startup use ./launcher start $config"
740 exit 0
741 ;;
742
743 run)
744 run_run
745 exit 0
746 ;;
747
748 enter)
749 exec $docker_path exec -it $config /bin/bash --login
750 ;;
751
752 stop)
753 run_stop
754 exit 0
755 ;;
756
757 logs)
758
759 $docker_path logs $config
760 exit 0
761 ;;
762
763 restart)
764 run_stop
765 run_start
766 exit 0
767 ;;
768
769 start-cmd)
770 START_CMD_ONLY="1"
771 run_start
772 exit 0;
773 ;;
774
775 start)
776 run_start
777 exit 0
778 ;;
779
780 rebuild)
781 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
782 echo "Ensuring launcher is up to date"
783
784 git remote update
785
786 LOCAL=$(git rev-parse HEAD)
787 REMOTE=$(git rev-parse @{u})
788 BASE=$(git merge-base HEAD @{u})
789
790 if [ $LOCAL = $REMOTE ]; then
791 echo "Launcher is up-to-date"
792
793 elif [ $LOCAL = $BASE ]; then
794 echo "Updating Launcher..."
795 git pull || (echo 'failed to update' && exit 1)
796
797 echo "Launcher updated, restarting..."
798 exec "$0" "${SAVED_ARGV[@]}"
799
800 elif [ $REMOTE = $BASE ]; then
801 echo "Your version of Launcher is ahead of origin"
802
803 else
804 echo "Launcher has diverged source, this is only expected in Dev mode"
805 fi
806
807 fi
808
809 set_existing_container
810
811 if [ ! -z $existing ]
812 then
813 echo "Stopping old container"
814 (
815 set -x
816 $docker_path stop -t 60 $config
817 )
818 fi
819
820 run_bootstrap
821
822 if [ ! -z $existing ]
823 then
824 echo "Removing old container"
825 (
826 set -x
827 $docker_path rm $config
828 )
829 fi
830
831 run_start
832 exit 0
833 ;;
834
835
836 destroy)
837 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
838 exit 0
839 ;;
840 esac
841
842 usage