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