Update ruby to 2.6.4
[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
7d72cf05 91image="discourse/base:2.0.20190625-0946"
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
238 $docker_path system prune -af
239 echo "If the cleanup was successful, you may try again now"
240 fi
49b2fcc4
RSS
241 fi
242 exit 1
243 fi
6e784be6
MP
244}
245
6828238a 246
cf3dd6f2 247if [ -z "$SKIP_PREREQS" ] && [ "$command" != "cleanup" ]; then
87c4f221 248 check_prereqs
55d17203 249fi
a3e18d95 250
60f9f04c
S
251host_run() {
252 read -r -d '' env_ruby << 'RUBY'
253 require 'yaml'
254
255 input = STDIN.readlines.join
256 yaml = YAML.load(input)
257
258 if host_run = yaml['host_run']
259 params = yaml['params'] || {}
260 host_run.each do |run|
261 params.each do |k,v|
262 run = run.gsub("$#{k}", v)
263 end
264 STDOUT.write "#{run}--SEP--"
265 end
266 end
267RUBY
268
e02c1511 269 host_run=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
60f9f04c
S
270
271 while [ "$host_run" ] ; do
272 iter=${host_run%%--SEP--*}
273 echo
274 echo "Host run: $iter"
275 $iter || exit 1
276 echo
277 host_run="${host_run#*--SEP--}"
278 done
279}
280
281
d90671f3 282set_volumes() {
e02c1511 283 volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
02d9a654 284 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
d90671f3
SS
285}
286
41daa523 287set_links() {
e02c1511 288 links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
41daa523 289 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
290}
291
06310c73
GXT
292find_templates() {
293 local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
7f77c274
SS
294 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
295
06310c73
GXT
296 local arrTemplates=${templates// / }
297
2ec550f7 298 if [ ! -z "$templates" ]; then
06310c73
GXT
299 for template in "${arrTemplates[@]}"
300 do
301 local nested_templates=$(find_templates $template)
302
303 if [ ! -z "$nested_templates" ]; then
304 templates="$templates $nested_templates"
305 fi
306 done
307
308 echo $templates
309 else
310 echo ""
311 fi
312}
313
314set_template_info() {
315 templates=$(find_templates $config_file)
316
7f77c274
SS
317 arrTemplates=(${templates// / })
318 config_data=$(cat $config_file)
319
320 input="hack: true"
321
7f77c274
SS
322 for template in "${arrTemplates[@]}"
323 do
324 [ ! -z $template ] && {
325 input="$input _FILE_SEPERATOR_ $(cat $template)"
326 }
327 done
328
329 # we always want our config file last so it takes priority
330 input="$input _FILE_SEPERATOR_ $config_data"
331
332 read -r -d '' env_ruby << 'RUBY'
333 require 'yaml'
334
335 input=STDIN.readlines.join
093e6628 336 # default to UTF-8 for the dbs sake
3cb3d9c4 337 env = {'LANG' => 'en_US.UTF-8'}
7f77c274
SS
338 input.split('_FILE_SEPERATOR_').each do |yml|
339 yml.strip!
340 begin
341 env.merge!(YAML.load(yml)['env'] || {})
f3824347 342 rescue Psych::SyntaxError => e
343 puts e
344 puts "*ERROR."
7f77c274
SS
345 rescue => e
346 puts yml
347 p e
348 end
349 end
0138494b 350 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
7f77c274
SS
351RUBY
352
fb827907
EP
353 tmp_input_file=$(mktemp)
354
355 echo "$input" > "$tmp_input_file"
356 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
357
358 rm -f "$tmp_input_file"
4b563ee8
SS
359
360 env=()
f3824347 361 ok=1
4b563ee8 362 while read i; do
f3824347 363 if [ "$i" == "*ERROR." ]; then
364 ok=0
365 elif [ -n "$i" ]; then
0138494b 366 env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
16f2d250 367 fi
4b563ee8
SS
368 done <<< "$raw"
369
f3824347 370 if [ "$ok" -ne 1 ]; then
371 echo "${env[@]}"
c2d3ee4a 372 echo "YAML syntax error. Please check your containers/*.yml config files."
f3824347 373 exit 1
374 fi
762d9bbf 375
8f57aae5 376 # labels
762d9bbf
MP
377 read -r -d '' labels_ruby << 'RUBY'
378 require 'yaml'
379
380 input=STDIN.readlines.join
762d9bbf
MP
381 labels = {}
382 input.split('_FILE_SEPERATOR_').each do |yml|
383 yml.strip!
384 begin
385 labels.merge!(YAML.load(yml)['labels'] || {})
386 rescue Psych::SyntaxError => e
387 puts e
388 puts "*ERROR."
389 rescue => e
390 puts yml
391 p e
392 end
393 end
394 puts labels.map{|k,v| "-l\n#{k}=#{v}" }.join("\n")
395RUBY
396
fb827907
EP
397 tmp_input_file=$(mktemp)
398
399 echo "$input" > "$tmp_input_file"
400 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$labels_ruby"`
401
402 rm -f "$tmp_input_file"
762d9bbf
MP
403
404 labels=()
405 ok=1
406 while read i; do
407 if [ "$i" == "*ERROR." ]; then
408 ok=0
409 elif [ -n "$i" ]; then
daddbf86 410 labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
762d9bbf
MP
411 fi
412 done <<< "$raw"
413
414 if [ "$ok" -ne 1 ]; then
415 echo "${labels[@]}"
416 echo "YAML syntax error. Please check your containers/*.yml config files."
417 exit 1
418 fi
8f57aae5
NL
419
420 # expose
421 read -r -d '' ports_ruby << 'RUBY'
422 require 'yaml'
423
424 input=STDIN.readlines.join
425 ports = []
426 input.split('_FILE_SEPERATOR_').each do |yml|
427 yml.strip!
428 begin
429 ports += (YAML.load(yml)['expose'] || [])
430 rescue Psych::SyntaxError => e
431 puts e
432 puts "*ERROR."
433 rescue => e
434 puts yml
435 p e
436 end
437 end
16fb17cf 438 puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
8f57aae5
NL
439RUBY
440
441 tmp_input_file=$(mktemp)
442
443 echo "$input" > "$tmp_input_file"
444 raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`
445
446 rm -f "$tmp_input_file"
447
448 ports=()
449 ok=1
450 while read i; do
451 if [ "$i" == "*ERROR." ]; then
452 ok=0
453 elif [ -n "$i" ]; then
454 ports[${#ports[@]}]=$i
455 fi
456 done <<< "$raw"
457
458 if [ "$ok" -ne 1 ]; then
459 echo "${ports[@]}"
460 echo "YAML syntax error. Please check your containers/*.yml config files."
461 exit 1
462 fi
bfc79e77
DE
463
464 merge_user_args
7f77c274
SS
465}
466
665468eb 467if [ -z $docker_path ]; then
52388b87 468 install_docker
665468eb 469fi
52388b87 470
de869404 471[ "$command" == "cleanup" ] && {
fa9acf1a 472 $docker_path system prune -a
2dfd2c6d
GXT
473
474 if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
475 echo
476 echo "Old PostgreSQL backup data cluster detected taking up $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detected"
477 read -p "Would you like to remove it? (Y/n): " -n 1 -r && echo
478
479 if [[ $REPLY =~ ^[Yy]$ ]]; then
480 echo "removing old PostgreSQL data cluster at /var/discourse/shared/standalone/postgres_data_old..."
481 rm -rf /var/discourse/shared/standalone/postgres_data_old
482 else
483 exit 1
484 fi
485 fi
486
a8b66f98
L
487 exit 0
488}
5f803fb4 489
65573a0e
GXT
490if [ ! "$command" == "setup" ]; then
491 if [[ ! -e $config_file ]]; then
7e738616 492 echo "Config file was not found, ensure $config_file exists"
5dfdf9a3 493 echo
71680b16 494 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
7e738616 495 exit 1
65573a0e 496 fi
7e738616
S
497fi
498
e2ed1fb6
S
499docker_version=($($docker_path --version))
500docker_version=${test[2]//,/}
69545efd 501restart_policy=${restart_policy:---restart=always}
e2ed1fb6 502
30835a52 503set_existing_container(){
295e8f19 504 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
337a89aa
S
505}
506
665468eb 507run_stop() {
337a89aa 508
30835a52 509 set_existing_container
60f9f04c 510
30835a52 511 if [ ! -z $existing ]
337a89aa 512 then
30835a52
S
513 (
514 set -x
a9cba0fc 515 $docker_path stop -t 10 $config
30835a52 516 )
337a89aa 517 else
30835a52 518 echo "$config was not started !"
f73c2d03 519 echo "./discourse-doctor may help diagnose the problem."
30835a52
S
520 exit 1
521 fi
522}
337a89aa 523
8877f99e
S
524set_run_image() {
525 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
526 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
527
c786ffcd
GXT
528 if [ -n "$user_run_image" ]; then
529 run_image=$user_run_image
530 elif [ -z "$run_image" ]; then
8877f99e
S
531 run_image="$local_discourse/$config"
532 fi
533}
534
535set_boot_command() {
536 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
537 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
538
539 if [ -z "$boot_command" ]; then
540
541 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
542 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
543
544 if [ -z "$no_boot_command" ]; then
545 boot_command="/sbin/boot"
546 fi
547 fi
548}
549
bfc79e77
DE
550merge_user_args() {
551 local docker_args
552
553 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
554 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
555
556 if [[ -n "$docker_args" ]]; then
47890a9a 557 user_args="$user_args_argv $docker_args"
bfc79e77
DE
558 fi
559}
560
665468eb 561run_start() {
337a89aa 562
7d49dbe7 563 if [ -z "$START_CMD_ONLY" ]
30835a52 564 then
7d49dbe7
SS
565 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
566 echo $existing
567 if [ ! -z $existing ]
568 then
569 echo "Nothing to do, your container has already started!"
570 exit 0
571 fi
30835a52 572
7d49dbe7
SS
573 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
574 if [ ! -z $existing ]
575 then
576 echo "starting up existing container"
577 (
578 set -x
579 $docker_path start $config
580 )
581 exit 0
582 fi
30835a52
S
583 fi
584
585 host_run
1f656469 586
30835a52
S
587 set_template_info
588 set_volumes
589 set_links
8877f99e
S
590 set_run_image
591 set_boot_command
30835a52 592
c6dd6f9d
FB
593 # get hostname and settings from container configuration
594 for envar in "${env[@]}"
595 do
596 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
597 then
598 # use as environment variable
599 eval $envar
600 fi
601 done
602
30835a52 603 (
c834fdd1 604 hostname=`hostname -s`
c6dd6f9d
FB
605 # overwrite hostname
606 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
607 then
608 hostname=$DISCOURSE_HOSTNAME
609 else
610 hostname=$hostname-$config
611 fi
612
a0606001
S
613 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
614 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
615 # docker added more hostname rules
fd2e7637 616 hostname=${hostname//_/-}
a0606001 617
cad2919f
GXT
618
619 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
620 mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
621 fi
d2a86ee1 622
7d49dbe7
SS
623 if [ ! -z "$START_CMD_ONLY" ] ; then
624 docker_path="true"
625 fi
626
30835a52 627 set -x
7d49dbe7 628
27c21012 629 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
bfc79e77 630 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
d2a86ee1 631 $run_image $boot_command
30835a52
S
632
633 )
634 exit 0
337a89aa
S
635
636}
637
2791af60
GXT
638run_run() {
639 set_template_info
640 set_volumes
641 set_links
642 set_run_image
643
644 unset ERR
645 (exec $docker_path run --rm --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" -i -a stdin -a stdout -a stderr $volumes $run_image \
646 /bin/bash -c "$run_command") || ERR=$?
647
648 if [[ $ERR > 0 ]]; then
649 exit 1
650 fi
651}
652
653run_bootstrap() {
60f9f04c
S
654 host_run
655
680dd4ea
S
656 # Is the image available?
657 # If not, pull it here so the user is aware what's happening.
4807b1b8 658 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
88126eba 659
680dd4ea 660 set_template_info
93149421 661
e02c1511 662 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 663 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
93149421 664
e02c1511 665 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 666 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
b9c7b50e 667
680dd4ea
S
668 if [[ ! X"" = X"$base_image" ]]; then
669 image=$base_image
670 fi
b9c7b50e 671
680dd4ea 672 set_volumes
41daa523 673 set_links
f126bcc6 674
680dd4ea 675 rm -f $cidbootstrap
d90671f3 676
680dd4ea
S
677 run_command="cd /pups &&"
678 if [[ ! "false" = $update_pups ]]; then
679 run_command="$run_command git pull &&"
680 fi
ca2ce907 681 run_command="$run_command /pups/bin/pups --stdin"
2162f1d4 682
680dd4ea 683 echo $run_command
b9c7b50e 684
b4ab14c2 685 unset ERR
fb827907
EP
686
687 tmp_input_file=$(mktemp)
688
689 echo "$input" > "$tmp_input_file"
690 (exec cat "$tmp_input_file" | $docker_path run --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" --cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
b4ab14c2
S
691 /bin/bash -c "$run_command") || ERR=$?
692
fb827907
EP
693 rm -f "$tmp_input_file"
694
b4ab14c2
S
695 unset FAILED
696 # magic exit code that indicates a retry
697 if [[ "$ERR" == 77 ]]; then
382c8e40
S
698 $docker_path rm `cat $cidbootstrap`
699 rm $cidbootstrap
b4ab14c2 700 exit 77
382c8e40 701 elif [[ "$ERR" > 0 ]]; then
b4ab14c2
S
702 FAILED=TRUE
703 fi
19e3a6c0
S
704
705 if [[ $FAILED = "TRUE" ]]; then
706 if [[ ! -z "$DEBUG" ]]; then
707 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
708 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
709 fi
88126eba 710
19e3a6c0
S
711 $docker_path rm `cat $cidbootstrap`
712 rm $cidbootstrap
f73c2d03
JP
713 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one."
714 echo "./discourse-doctor may help diagnose the problem."
19e3a6c0
S
715 exit 1
716 fi
9fb5f2d3 717
680dd4ea 718 sleep 5
2162f1d4 719
4807b1b8
MB
720 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
721 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
680dd4ea 722}
9fb5f2d3 723
680dd4ea
S
724case "$command" in
725 bootstrap)
680dd4ea 726 run_bootstrap
2dd2e330 727 echo "Successfully bootstrapped, to startup use ./launcher start $config"
4b3aebe1 728 exit 0
5f803fb4 729 ;;
1acce9e4 730
1ec142a1
GXT
731 run)
732 run_run
733 exit 0
734 ;;
735
2fc6ff36 736 enter)
0c456e8c 737 exec $docker_path exec -it $config /bin/bash --login
2fc6ff36
S
738 ;;
739
5f803fb4 740 stop)
337a89aa
S
741 run_stop
742 exit 0
5f803fb4 743 ;;
7e738616 744
5f803fb4 745 logs)
7e738616 746
30835a52
S
747 $docker_path logs $config
748 exit 0
5f803fb4 749 ;;
7e738616 750
337a89aa
S
751 restart)
752 run_stop
753 run_start
754 exit 0
755 ;;
80c11be3 756
7d49dbe7
SS
757 start-cmd)
758 START_CMD_ONLY="1"
759 run_start
760 exit 0;
761 ;;
762
337a89aa
S
763 start)
764 run_start
765 exit 0
5f803fb4 766 ;;
7e738616 767
680dd4ea 768 rebuild)
4b6456ef 769 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
c2d3ee4a 770 echo "Ensuring launcher is up to date"
098533cb
S
771
772 git remote update
773
755ab5ac 774 LOCAL=$(git rev-parse HEAD)
098533cb 775 REMOTE=$(git rev-parse @{u})
755ab5ac 776 BASE=$(git merge-base HEAD @{u})
098533cb
S
777
778 if [ $LOCAL = $REMOTE ]; then
c2d3ee4a 779 echo "Launcher is up-to-date"
098533cb
S
780
781 elif [ $LOCAL = $BASE ]; then
c2d3ee4a 782 echo "Updating Launcher"
098533cb 783 git pull || (echo 'failed to update' && exit 1)
88ee2e35 784
8100fab0
PD
785 for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
786 do
787 args[$j]=${BASH_ARGV[$i]}
788 done
789 exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
098533cb
S
790
791 elif [ $REMOTE = $BASE ]; then
c2d3ee4a 792 echo "Your version of Launcher is ahead of origin"
098533cb
S
793
794 else
c2d3ee4a 795 echo "Launcher has diverged source, this is only expected in Dev mode"
098533cb
S
796 fi
797
4b6456ef 798 fi
30835a52
S
799
800 set_existing_container
801
802 if [ ! -z $existing ]
680dd4ea
S
803 then
804 echo "Stopping old container"
30835a52
S
805 (
806 set -x
807 $docker_path stop -t 10 $config
808 )
680dd4ea
S
809 fi
810
811 run_bootstrap
812
30835a52 813 if [ ! -z $existing ]
680dd4ea 814 then
30835a52
S
815 echo "Removing old container"
816 (
817 set -x
818 $docker_path rm $config
819 )
680dd4ea
S
820 fi
821
822 run_start
823 exit 0
824 ;;
825
7e738616 826
5f803fb4 827 destroy)
98bd0edf 828 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
30835a52 829 exit 0
5f803fb4
SS
830 ;;
831esac
7e738616 832
5f803fb4 833usage