Make sshd compatible with Debian 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
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.20190901-2315"
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 echo "./discourse-doctor may help diagnose the problem."
520 exit 1
521 fi
522 }
523
524 set_run_image() {
525 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
526 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
527
528 if [ -n "$user_run_image" ]; then
529 run_image=$user_run_image
530 elif [ -z "$run_image" ]; then
531 run_image="$local_discourse/$config"
532 fi
533 }
534
535 set_boot_command() {
536 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
537 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
538
539 if [ -z "$boot_command" ]; then
540
541 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
542 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
543
544 if [ -z "$no_boot_command" ]; then
545 boot_command="/sbin/boot"
546 fi
547 fi
548 }
549
550 merge_user_args() {
551 local docker_args
552
553 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
554 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
555
556 if [[ -n "$docker_args" ]]; then
557 user_args="$user_args_argv $docker_args"
558 fi
559 }
560
561 run_start() {
562
563 if [ -z "$START_CMD_ONLY" ]
564 then
565 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
566 echo $existing
567 if [ ! -z $existing ]
568 then
569 echo "Nothing to do, your container has already started!"
570 exit 0
571 fi
572
573 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
574 if [ ! -z $existing ]
575 then
576 echo "starting up existing container"
577 (
578 set -x
579 $docker_path start $config
580 )
581 exit 0
582 fi
583 fi
584
585 host_run
586
587 set_template_info
588 set_volumes
589 set_links
590 set_run_image
591 set_boot_command
592
593 # get hostname and settings from container configuration
594 for envar in "${env[@]}"
595 do
596 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
597 then
598 # use as environment variable
599 eval $envar
600 fi
601 done
602
603 (
604 hostname=`hostname -s`
605 # overwrite hostname
606 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
607 then
608 hostname=$DISCOURSE_HOSTNAME
609 else
610 hostname=$hostname-$config
611 fi
612
613 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
614 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
615 # docker added more hostname rules
616 hostname=${hostname//_/-}
617
618
619 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
620 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/'")"
621 fi
622
623 if [ ! -z "$START_CMD_ONLY" ] ; then
624 docker_path="true"
625 fi
626
627 set -x
628
629 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
630 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
631 $run_image $boot_command
632
633 )
634 exit 0
635
636 }
637
638 run_run() {
639 set_template_info
640 set_volumes
641 set_links
642 set_run_image
643
644 unset ERR
645 (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 \
646 /bin/bash -c "$run_command") || ERR=$?
647
648 if [[ $ERR > 0 ]]; then
649 exit 1
650 fi
651 }
652
653 run_bootstrap() {
654 host_run
655
656 # Is the image available?
657 # If not, pull it here so the user is aware what's happening.
658 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
659
660 set_template_info
661
662 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
663 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
664
665 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
666 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
667
668 if [[ ! X"" = X"$base_image" ]]; then
669 image=$base_image
670 fi
671
672 set_volumes
673 set_links
674
675 rm -f $cidbootstrap
676
677 run_command="cd /pups &&"
678 if [[ ! "false" = $update_pups ]]; then
679 run_command="$run_command git pull &&"
680 fi
681 run_command="$run_command /pups/bin/pups --stdin"
682
683 echo $run_command
684
685 unset ERR
686
687 tmp_input_file=$(mktemp)
688
689 echo "$input" > "$tmp_input_file"
690 (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 \
691 /bin/bash -c "$run_command") || ERR=$?
692
693 rm -f "$tmp_input_file"
694
695 unset FAILED
696 # magic exit code that indicates a retry
697 if [[ "$ERR" == 77 ]]; then
698 $docker_path rm `cat $cidbootstrap`
699 rm $cidbootstrap
700 exit 77
701 elif [[ "$ERR" > 0 ]]; then
702 FAILED=TRUE
703 fi
704
705 if [[ $FAILED = "TRUE" ]]; then
706 if [[ ! -z "$DEBUG" ]]; then
707 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
708 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
709 fi
710
711 $docker_path rm `cat $cidbootstrap`
712 rm $cidbootstrap
713 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one."
714 echo "./discourse-doctor may help diagnose the problem."
715 exit 1
716 fi
717
718 sleep 5
719
720 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
721 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
722 }
723
724 case "$command" in
725 bootstrap)
726 run_bootstrap
727 echo "Successfully bootstrapped, to startup use ./launcher start $config"
728 exit 0
729 ;;
730
731 run)
732 run_run
733 exit 0
734 ;;
735
736 enter)
737 exec $docker_path exec -it $config /bin/bash --login
738 ;;
739
740 stop)
741 run_stop
742 exit 0
743 ;;
744
745 logs)
746
747 $docker_path logs $config
748 exit 0
749 ;;
750
751 restart)
752 run_stop
753 run_start
754 exit 0
755 ;;
756
757 start-cmd)
758 START_CMD_ONLY="1"
759 run_start
760 exit 0;
761 ;;
762
763 start)
764 run_start
765 exit 0
766 ;;
767
768 rebuild)
769 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
770 echo "Ensuring launcher is up to date"
771
772 git remote update
773
774 LOCAL=$(git rev-parse HEAD)
775 REMOTE=$(git rev-parse @{u})
776 BASE=$(git merge-base HEAD @{u})
777
778 if [ $LOCAL = $REMOTE ]; then
779 echo "Launcher is up-to-date"
780
781 elif [ $LOCAL = $BASE ]; then
782 echo "Updating Launcher"
783 git pull || (echo 'failed to update' && exit 1)
784
785 for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
786 do
787 args[$j]=${BASH_ARGV[$i]}
788 done
789 exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
790
791 elif [ $REMOTE = $BASE ]; then
792 echo "Your version of Launcher is ahead of origin"
793
794 else
795 echo "Launcher has diverged source, this is only expected in Dev mode"
796 fi
797
798 fi
799
800 set_existing_container
801
802 if [ ! -z $existing ]
803 then
804 echo "Stopping old container"
805 (
806 set -x
807 $docker_path stop -t 10 $config
808 )
809 fi
810
811 run_bootstrap
812
813 if [ ! -z $existing ]
814 then
815 echo "Removing old container"
816 (
817 set -x
818 $docker_path rm $config
819 )
820 fi
821
822 run_start
823 exit 0
824 ;;
825
826
827 destroy)
828 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
829 exit 0
830 ;;
831 esac
832
833 usage