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