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