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