FEATURE: Don't use fully qualified path for bash in host (#458)
[discourse_docker.git] / launcher
CommitLineData
7dafe1c0 1#!/usr/bin/env 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"
7d49dbe7 16 echo " start-cmd: Generate docker command used to start container"
5cb39519
JA
17 echo
18 echo "Options:"
1f656469 19 echo " --skip-prereqs Don't check launcher prerequisites"
1f656469 20 echo " --docker-args Extra arguments to pass when running docker"
cad2919f 21 echo " --skip-mac-address Don't assign a mac address"
c786ffcd 22 echo " --run-image Override the image used for running the container"
5cb39519
JA
23 exit 1
24}
25
7e738616
S
26command=$1
27config=$2
47890a9a
SG
28
29# user_args_argv is assigned once when the argument vector is parsed.
30user_args_argv=""
31# user_args is mutable: its value may change when templates are parsed.
32# Superset of user_args_argv.
65573a0e 33user_args=""
47890a9a 34
c786ffcd 35user_run_image=""
87c4f221 36
1ec142a1
GXT
37if [[ $command == "run" ]]; then
38 run_command=$3
39fi
40
1f656469 41while [ ${#} -gt 0 ]; do
65573a0e 42 case "${1}" in
19e3a6c0
S
43 --debug)
44 DEBUG="1"
45 ;;
1f656469 46 --skip-prereqs)
4f36bb43 47 SKIP_PREREQS="1"
1f656469 48 ;;
cad2919f
GXT
49 --skip-mac-address)
50 SKIP_MAC_ADDRESS="1"
51 ;;
1f656469 52 --docker-args)
47890a9a
SG
53 user_args_argv="$2"
54 user_args="$user_args_argv"
1f656469
GXT
55 shift
56 ;;
c786ffcd
GXT
57 --run-image)
58 user_run_image="$2"
59 shift
60 ;;
1f656469
GXT
61 esac
62
63 shift 1
64done
55d17203 65
ea4428d7 66if [ -z "$command" -o -z "$config" -a "$command" != "cleanup" ]; then
f80e6a37
GXT
67 usage
68 exit 1
69fi
70
87756d6d 71# Docker doesn't like uppercase characters, spaces or special characters, catch it now before we build everything out and then find out
abcf2a97 72re='[[:upper:]/ !@#$%^&*()+~`=]'
87756d6d
EH
73if [[ $config =~ $re ]];
74 then
8877f99e 75 echo
abcf2a97 76 echo "ERROR: Config name '$config' must not contain upper case characters, spaces or special characters. Correct config name and rerun $0."
87756d6d
EH
77 echo
78 exit 1
79fi
80
7936ebaa 81cd "$(dirname "$0")"
55d17203 82
0998a7c8 83docker_min_version='17.03.1'
ddf8c54c 84docker_rec_version='17.06.2'
6828238a
JP
85git_min_version='1.8.0'
86git_rec_version='1.8.0'
60668406 87
8dea575c 88config_file=containers/"$config".yml
5201a40c 89cidbootstrap=cids/"$config"_bootstrap.cid
5efded6a 90local_discourse=local_discourse
456dcfe1 91image="discourse/base:2.0.20200220-2221"
9eeb324e 92docker_path=`which docker.io 2> /dev/null || which docker`
6828238a 93git_path=`which git`
8877f99e 94
e0fd1f5b
TB
95if [ "${SUPERVISED}" = "true" ]; then
96 restart_policy="--restart=no"
97 attach_on_start="-a"
98 attach_on_run="-a stdout -a stderr"
99else
100 attach_on_run="-d"
101fi
102
f2a3edee
AY
103if [ -n "$DOCKER_HOST" ]; then
104 docker_ip=`sed -e 's/^tcp:\/\/\(.*\):.*$/\1/' <<< "$DOCKER_HOST"`
105elif [ -x "$(which ip 2>/dev/null)" ]; then
813fef38 106 docker_ip=`ip addr show docker0 | \
03bb0735
LG
107 grep 'inet ' | \
108 awk '{ split($2,a,"/"); print a[1] }';`
109else
813fef38 110 docker_ip=`ifconfig | \
03bb0735
LG
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 }';`
115fi
80c11be3 116
7a96c86d 117# From https://stackoverflow.com/a/44660519/702738
60668406 118compare_version() {
7a96c86d
RSS
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
60668406 127 return 1
7a96c86d
RSS
128 elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
129 return 0
60668406
DP
130 fi
131 done
7a96c86d
RSS
132 if [ "$arem" '<' "$brem" ]; then
133 return 1
134 elif [ "$arem" '>' "$brem" ]; then
135 return 0
136 fi
137 return 1
60668406
DP
138}
139
665468eb
JA
140
141install_docker() {
c2d3ee4a 142 echo "Docker is not installed, you will need to install Docker in order to run Launcher"
bf6d49b5 143 echo "See https://docs.docker.com/installation/"
665468eb
JA
144 exit 1
145}
146
87c4f221 147check_prereqs() {
794e44d5
GXT
148
149 if [ -z $docker_path ]; then
665468eb
JA
150 install_docker
151 fi
a3e18d95 152
e741295a 153 # 1. docker daemon running?
30835a52
S
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`
e741295a
MB
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
90287f8e 162 # 2. running an approved storage driver?
98c5fec4 163 if ! $docker_path info 2> /dev/null | egrep -q 'Storage Driver: (aufs|zfs|overlay2)$'; then
90287f8e 164 echo "Your Docker installation is not using a supported storage driver. If we were to proceed you may have a broken install."
64716d41 165 echo "aufs is the recommended storage driver, although zfs and overlay2 may work as well."
90287f8e
MP
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."
5dfdf9a3 168 echo
90287f8e
MP
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."
48f22d14 171 exit 1
a3e18d95
S
172 fi
173
60668406
DP
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
a3e18d95 177
87c4f221 178 # At least minimum docker version
cf00fce0 179 if compare_version "${docker_min_version}" "${test}"; then
60668406 180 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
a3e18d95
S
181 exit 1
182 fi
183
87c4f221 184 # Recommend newer docker version
60668406
DP
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
405948ee
S
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
405948ee 199 fi
405948ee 200
6828238a
JP
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
e02c1511 217 test=`$docker_path run $user_args -i --rm -a stdout -a stderr $image echo working`
a3e18d95
S
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
4770834b 224
49b2fcc4 225 # 7. enough space for the bootstrap on docker folder
8cdc533d
RSS
226 folder=`$docker_path info --format '{{.DockerRootDir}}'`
227 safe_folder=${folder:-/var/lib/docker}
49b2fcc4
RSS
228 test=$(($(stat -f --format="%a*%S" $safe_folder)/1024**3 < 5))
229 if [[ $test -ne 0 ]] ; then
da095c30
RSS
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
49b2fcc4 232 echo
623f1073
MB
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
70aaf454
SG
238 $docker_path container prune --force --filter until=1h >/dev/null
239 $docker_path image prune --all --force --filter until=1h >/dev/null
623f1073
MB
240 echo "If the cleanup was successful, you may try again now"
241 fi
49b2fcc4
RSS
242 fi
243 exit 1
244 fi
6e784be6
MP
245}
246
6828238a 247
cf3dd6f2 248if [ -z "$SKIP_PREREQS" ] && [ "$command" != "cleanup" ]; then
87c4f221 249 check_prereqs
55d17203 250fi
a3e18d95 251
60f9f04c
S
252host_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
268RUBY
269
e02c1511 270 host_run=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
60f9f04c
S
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
d90671f3 283set_volumes() {
e02c1511 284 volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
02d9a654 285 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
d90671f3
SS
286}
287
41daa523 288set_links() {
e02c1511 289 links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
41daa523 290 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
291}
292
06310c73
GXT
293find_templates() {
294 local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
7f77c274
SS
295 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
296
06310c73
GXT
297 local arrTemplates=${templates// / }
298
2ec550f7 299 if [ ! -z "$templates" ]; then
06310c73
GXT
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
315set_template_info() {
316 templates=$(find_templates $config_file)
317
7f77c274
SS
318 arrTemplates=(${templates// / })
319 config_data=$(cat $config_file)
320
321 input="hack: true"
322
7f77c274
SS
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
093e6628 337 # default to UTF-8 for the dbs sake
3cb3d9c4 338 env = {'LANG' => 'en_US.UTF-8'}
7f77c274
SS
339 input.split('_FILE_SEPERATOR_').each do |yml|
340 yml.strip!
341 begin
342 env.merge!(YAML.load(yml)['env'] || {})
f3824347 343 rescue Psych::SyntaxError => e
344 puts e
345 puts "*ERROR."
7f77c274
SS
346 rescue => e
347 puts yml
348 p e
349 end
350 end
0138494b 351 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
7f77c274
SS
352RUBY
353
fb827907
EP
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"
4b563ee8
SS
360
361 env=()
f3824347 362 ok=1
4b563ee8 363 while read i; do
f3824347 364 if [ "$i" == "*ERROR." ]; then
365 ok=0
366 elif [ -n "$i" ]; then
0138494b 367 env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
16f2d250 368 fi
4b563ee8
SS
369 done <<< "$raw"
370
f3824347 371 if [ "$ok" -ne 1 ]; then
372 echo "${env[@]}"
c2d3ee4a 373 echo "YAML syntax error. Please check your containers/*.yml config files."
f3824347 374 exit 1
375 fi
762d9bbf 376
8f57aae5 377 # labels
762d9bbf
MP
378 read -r -d '' labels_ruby << 'RUBY'
379 require 'yaml'
380
381 input=STDIN.readlines.join
762d9bbf
MP
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")
396RUBY
397
fb827907
EP
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"
762d9bbf
MP
404
405 labels=()
406 ok=1
407 while read i; do
408 if [ "$i" == "*ERROR." ]; then
409 ok=0
410 elif [ -n "$i" ]; then
daddbf86 411 labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
762d9bbf
MP
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
8f57aae5
NL
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
16fb17cf 439 puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
8f57aae5
NL
440RUBY
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
bfc79e77
DE
464
465 merge_user_args
7f77c274
SS
466}
467
665468eb 468if [ -z $docker_path ]; then
52388b87 469 install_docker
665468eb 470fi
52388b87 471
de869404 472[ "$command" == "cleanup" ] && {
b54cb8ea
SG
473 $docker_path container prune --filter until=1h
474 $docker_path image prune --all --filter until=1h
2dfd2c6d
GXT
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
a8b66f98
L
489 exit 0
490}
5f803fb4 491
65573a0e
GXT
492if [ ! "$command" == "setup" ]; then
493 if [[ ! -e $config_file ]]; then
7e738616 494 echo "Config file was not found, ensure $config_file exists"
5dfdf9a3 495 echo
71680b16 496 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
7e738616 497 exit 1
65573a0e 498 fi
7e738616
S
499fi
500
e2ed1fb6
S
501docker_version=($($docker_path --version))
502docker_version=${test[2]//,/}
69545efd 503restart_policy=${restart_policy:---restart=always}
e2ed1fb6 504
30835a52 505set_existing_container(){
295e8f19 506 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
337a89aa
S
507}
508
665468eb 509run_stop() {
337a89aa 510
30835a52 511 set_existing_container
60f9f04c 512
30835a52 513 if [ ! -z $existing ]
337a89aa 514 then
30835a52
S
515 (
516 set -x
a9cba0fc 517 $docker_path stop -t 10 $config
30835a52 518 )
337a89aa 519 else
30835a52 520 echo "$config was not started !"
f73c2d03 521 echo "./discourse-doctor may help diagnose the problem."
30835a52
S
522 exit 1
523 fi
524}
337a89aa 525
8877f99e
S
526set_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
c786ffcd
GXT
530 if [ -n "$user_run_image" ]; then
531 run_image=$user_run_image
532 elif [ -z "$run_image" ]; then
8877f99e
S
533 run_image="$local_discourse/$config"
534 fi
535}
536
537set_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
bfc79e77
DE
552merge_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
47890a9a 559 user_args="$user_args_argv $docker_args"
bfc79e77
DE
560 fi
561}
562
665468eb 563run_start() {
337a89aa 564
7d49dbe7 565 if [ -z "$START_CMD_ONLY" ]
30835a52 566 then
7d49dbe7
SS
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
30835a52 574
7d49dbe7
SS
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
30835a52
S
585 fi
586
587 host_run
1f656469 588
30835a52
S
589 set_template_info
590 set_volumes
591 set_links
8877f99e
S
592 set_run_image
593 set_boot_command
30835a52 594
c6dd6f9d
FB
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
30835a52 605 (
c834fdd1 606 hostname=`hostname -s`
c6dd6f9d
FB
607 # overwrite hostname
608 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
609 then
610 hostname=$DISCOURSE_HOSTNAME
611 else
612 hostname=$hostname-$config
613 fi
614
a0606001
S
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
fd2e7637 618 hostname=${hostname//_/-}
a0606001 619
cad2919f
GXT
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
d2a86ee1 624
7d49dbe7
SS
625 if [ ! -z "$START_CMD_ONLY" ] ; then
626 docker_path="true"
627 fi
628
30835a52 629 set -x
7d49dbe7 630
27c21012 631 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
bfc79e77 632 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
d2a86ee1 633 $run_image $boot_command
30835a52
S
634
635 )
636 exit 0
337a89aa
S
637
638}
639
2791af60
GXT
640run_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
655run_bootstrap() {
60f9f04c
S
656 host_run
657
680dd4ea
S
658 # Is the image available?
659 # If not, pull it here so the user is aware what's happening.
4807b1b8 660 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
88126eba 661
680dd4ea 662 set_template_info
93149421 663
e02c1511 664 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 665 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
93149421 666
e02c1511 667 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 668 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
b9c7b50e 669
680dd4ea
S
670 if [[ ! X"" = X"$base_image" ]]; then
671 image=$base_image
672 fi
b9c7b50e 673
680dd4ea 674 set_volumes
41daa523 675 set_links
f126bcc6 676
680dd4ea 677 rm -f $cidbootstrap
d90671f3 678
680dd4ea
S
679 run_command="cd /pups &&"
680 if [[ ! "false" = $update_pups ]]; then
681 run_command="$run_command git pull &&"
682 fi
ca2ce907 683 run_command="$run_command /pups/bin/pups --stdin"
2162f1d4 684
680dd4ea 685 echo $run_command
b9c7b50e 686
b4ab14c2 687 unset ERR
fb827907
EP
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 \
b4ab14c2
S
693 /bin/bash -c "$run_command") || ERR=$?
694
fb827907
EP
695 rm -f "$tmp_input_file"
696
b4ab14c2
S
697 unset FAILED
698 # magic exit code that indicates a retry
699 if [[ "$ERR" == 77 ]]; then
382c8e40
S
700 $docker_path rm `cat $cidbootstrap`
701 rm $cidbootstrap
b4ab14c2 702 exit 77
382c8e40 703 elif [[ "$ERR" > 0 ]]; then
b4ab14c2
S
704 FAILED=TRUE
705 fi
19e3a6c0
S
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
88126eba 712
19e3a6c0
S
713 $docker_path rm `cat $cidbootstrap`
714 rm $cidbootstrap
f73c2d03
JP
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."
19e3a6c0
S
717 exit 1
718 fi
9fb5f2d3 719
680dd4ea 720 sleep 5
2162f1d4 721
4807b1b8
MB
722 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
723 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
680dd4ea 724}
9fb5f2d3 725
680dd4ea
S
726case "$command" in
727 bootstrap)
680dd4ea 728 run_bootstrap
2dd2e330 729 echo "Successfully bootstrapped, to startup use ./launcher start $config"
4b3aebe1 730 exit 0
5f803fb4 731 ;;
1acce9e4 732
1ec142a1
GXT
733 run)
734 run_run
735 exit 0
736 ;;
737
2fc6ff36 738 enter)
0c456e8c 739 exec $docker_path exec -it $config /bin/bash --login
2fc6ff36
S
740 ;;
741
5f803fb4 742 stop)
337a89aa
S
743 run_stop
744 exit 0
5f803fb4 745 ;;
7e738616 746
5f803fb4 747 logs)
7e738616 748
30835a52
S
749 $docker_path logs $config
750 exit 0
5f803fb4 751 ;;
7e738616 752
337a89aa
S
753 restart)
754 run_stop
755 run_start
756 exit 0
757 ;;
80c11be3 758
7d49dbe7
SS
759 start-cmd)
760 START_CMD_ONLY="1"
761 run_start
762 exit 0;
763 ;;
764
337a89aa
S
765 start)
766 run_start
767 exit 0
5f803fb4 768 ;;
7e738616 769
680dd4ea 770 rebuild)
4b6456ef 771 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
c2d3ee4a 772 echo "Ensuring launcher is up to date"
098533cb
S
773
774 git remote update
775
755ab5ac 776 LOCAL=$(git rev-parse HEAD)
098533cb 777 REMOTE=$(git rev-parse @{u})
755ab5ac 778 BASE=$(git merge-base HEAD @{u})
098533cb
S
779
780 if [ $LOCAL = $REMOTE ]; then
c2d3ee4a 781 echo "Launcher is up-to-date"
098533cb
S
782
783 elif [ $LOCAL = $BASE ]; then
c2d3ee4a 784 echo "Updating Launcher"
098533cb 785 git pull || (echo 'failed to update' && exit 1)
88ee2e35 786
8100fab0
PD
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
3d746e72 791 exec bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
098533cb
S
792
793 elif [ $REMOTE = $BASE ]; then
c2d3ee4a 794 echo "Your version of Launcher is ahead of origin"
098533cb
S
795
796 else
c2d3ee4a 797 echo "Launcher has diverged source, this is only expected in Dev mode"
098533cb
S
798 fi
799
4b6456ef 800 fi
30835a52
S
801
802 set_existing_container
803
804 if [ ! -z $existing ]
680dd4ea
S
805 then
806 echo "Stopping old container"
30835a52
S
807 (
808 set -x
809 $docker_path stop -t 10 $config
810 )
680dd4ea
S
811 fi
812
813 run_bootstrap
814
30835a52 815 if [ ! -z $existing ]
680dd4ea 816 then
30835a52
S
817 echo "Removing old container"
818 (
819 set -x
820 $docker_path rm $config
821 )
680dd4ea
S
822 fi
823
824 run_start
825 exit 0
826 ;;
827
7e738616 828
5f803fb4 829 destroy)
98bd0edf 830 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
30835a52 831 exit 0
5f803fb4
SS
832 ;;
833esac
7e738616 834
5f803fb4 835usage