spacing
[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
S
518 echo "$config was not started !"
519 exit 1
520 fi
521}
337a89aa 522
8877f99e
S
523set_run_image() {
524 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
525 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
526
c786ffcd
GXT
527 if [ -n "$user_run_image" ]; then
528 run_image=$user_run_image
529 elif [ -z "$run_image" ]; then
8877f99e
S
530 run_image="$local_discourse/$config"
531 fi
532}
533
534set_boot_command() {
535 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
536 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
537
538 if [ -z "$boot_command" ]; then
539
540 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
541 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
542
543 if [ -z "$no_boot_command" ]; then
544 boot_command="/sbin/boot"
545 fi
546 fi
547}
548
bfc79e77
DE
549merge_user_args() {
550 local docker_args
551
552 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
553 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
554
555 if [[ -n "$docker_args" ]]; then
47890a9a 556 user_args="$user_args_argv $docker_args"
bfc79e77
DE
557 fi
558}
559
665468eb 560run_start() {
337a89aa 561
7d49dbe7 562 if [ -z "$START_CMD_ONLY" ]
30835a52 563 then
7d49dbe7
SS
564 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
565 echo $existing
566 if [ ! -z $existing ]
567 then
568 echo "Nothing to do, your container has already started!"
569 exit 0
570 fi
30835a52 571
7d49dbe7
SS
572 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
573 if [ ! -z $existing ]
574 then
575 echo "starting up existing container"
576 (
577 set -x
578 $docker_path start $config
579 )
580 exit 0
581 fi
30835a52
S
582 fi
583
584 host_run
1f656469 585
30835a52
S
586 set_template_info
587 set_volumes
588 set_links
8877f99e
S
589 set_run_image
590 set_boot_command
30835a52 591
c6dd6f9d
FB
592 # get hostname and settings from container configuration
593 for envar in "${env[@]}"
594 do
595 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
596 then
597 # use as environment variable
598 eval $envar
599 fi
600 done
601
30835a52 602 (
c834fdd1 603 hostname=`hostname -s`
c6dd6f9d
FB
604 # overwrite hostname
605 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
606 then
607 hostname=$DISCOURSE_HOSTNAME
608 else
609 hostname=$hostname-$config
610 fi
611
a0606001
S
612 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
613 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
614 # docker added more hostname rules
fd2e7637 615 hostname=${hostname//_/-}
a0606001 616
cad2919f
GXT
617
618 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
619 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/'")"
620 fi
d2a86ee1 621
7d49dbe7
SS
622 if [ ! -z "$START_CMD_ONLY" ] ; then
623 docker_path="true"
624 fi
625
30835a52 626 set -x
7d49dbe7 627
27c21012 628 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
bfc79e77 629 -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
d2a86ee1 630 $run_image $boot_command
30835a52
S
631
632 )
633 exit 0
337a89aa
S
634
635}
636
2791af60
GXT
637run_run() {
638 set_template_info
639 set_volumes
640 set_links
641 set_run_image
642
643 unset ERR
644 (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 \
645 /bin/bash -c "$run_command") || ERR=$?
646
647 if [[ $ERR > 0 ]]; then
648 exit 1
649 fi
650}
651
652run_bootstrap() {
60f9f04c
S
653 host_run
654
680dd4ea
S
655 # Is the image available?
656 # If not, pull it here so the user is aware what's happening.
4807b1b8 657 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
88126eba 658
680dd4ea 659 set_template_info
93149421 660
e02c1511 661 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 662 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
93149421 663
e02c1511 664 update_pups=`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)['update_pups']"`
b9c7b50e 666
680dd4ea
S
667 if [[ ! X"" = X"$base_image" ]]; then
668 image=$base_image
669 fi
b9c7b50e 670
680dd4ea 671 set_volumes
41daa523 672 set_links
f126bcc6 673
680dd4ea 674 rm -f $cidbootstrap
d90671f3 675
680dd4ea
S
676 run_command="cd /pups &&"
677 if [[ ! "false" = $update_pups ]]; then
678 run_command="$run_command git pull &&"
679 fi
ca2ce907 680 run_command="$run_command /pups/bin/pups --stdin"
2162f1d4 681
680dd4ea 682 echo $run_command
b9c7b50e 683
b4ab14c2 684 unset ERR
fb827907
EP
685
686 tmp_input_file=$(mktemp)
687
688 echo "$input" > "$tmp_input_file"
689 (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
690 /bin/bash -c "$run_command") || ERR=$?
691
fb827907
EP
692 rm -f "$tmp_input_file"
693
b4ab14c2
S
694 unset FAILED
695 # magic exit code that indicates a retry
696 if [[ "$ERR" == 77 ]]; then
382c8e40
S
697 $docker_path rm `cat $cidbootstrap`
698 rm $cidbootstrap
b4ab14c2 699 exit 77
382c8e40 700 elif [[ "$ERR" > 0 ]]; then
b4ab14c2
S
701 FAILED=TRUE
702 fi
19e3a6c0
S
703
704 if [[ $FAILED = "TRUE" ]]; then
705 if [[ ! -z "$DEBUG" ]]; then
706 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
707 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
708 fi
88126eba 709
19e3a6c0
S
710 $docker_path rm `cat $cidbootstrap`
711 rm $cidbootstrap
712 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one"
713 exit 1
714 fi
9fb5f2d3 715
680dd4ea 716 sleep 5
2162f1d4 717
4807b1b8
MB
718 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
719 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
680dd4ea 720}
9fb5f2d3 721
680dd4ea
S
722case "$command" in
723 bootstrap)
680dd4ea 724 run_bootstrap
2dd2e330 725 echo "Successfully bootstrapped, to startup use ./launcher start $config"
4b3aebe1 726 exit 0
5f803fb4 727 ;;
1acce9e4 728
1ec142a1
GXT
729 run)
730 run_run
731 exit 0
732 ;;
733
2fc6ff36 734 enter)
0c456e8c 735 exec $docker_path exec -it $config /bin/bash --login
2fc6ff36
S
736 ;;
737
5f803fb4 738 stop)
337a89aa
S
739 run_stop
740 exit 0
5f803fb4 741 ;;
7e738616 742
5f803fb4 743 logs)
7e738616 744
30835a52
S
745 $docker_path logs $config
746 exit 0
5f803fb4 747 ;;
7e738616 748
337a89aa
S
749 restart)
750 run_stop
751 run_start
752 exit 0
753 ;;
80c11be3 754
7d49dbe7
SS
755 start-cmd)
756 START_CMD_ONLY="1"
757 run_start
758 exit 0;
759 ;;
760
337a89aa
S
761 start)
762 run_start
763 exit 0
5f803fb4 764 ;;
7e738616 765
680dd4ea 766 rebuild)
4b6456ef 767 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
c2d3ee4a 768 echo "Ensuring launcher is up to date"
098533cb
S
769
770 git remote update
771
755ab5ac 772 LOCAL=$(git rev-parse HEAD)
098533cb 773 REMOTE=$(git rev-parse @{u})
755ab5ac 774 BASE=$(git merge-base HEAD @{u})
098533cb
S
775
776 if [ $LOCAL = $REMOTE ]; then
c2d3ee4a 777 echo "Launcher is up-to-date"
098533cb
S
778
779 elif [ $LOCAL = $BASE ]; then
c2d3ee4a 780 echo "Updating Launcher"
098533cb 781 git pull || (echo 'failed to update' && exit 1)
88ee2e35 782
8100fab0
PD
783 for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
784 do
785 args[$j]=${BASH_ARGV[$i]}
786 done
787 exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
098533cb
S
788
789 elif [ $REMOTE = $BASE ]; then
c2d3ee4a 790 echo "Your version of Launcher is ahead of origin"
098533cb
S
791
792 else
c2d3ee4a 793 echo "Launcher has diverged source, this is only expected in Dev mode"
098533cb
S
794 fi
795
4b6456ef 796 fi
30835a52
S
797
798 set_existing_container
799
800 if [ ! -z $existing ]
680dd4ea
S
801 then
802 echo "Stopping old container"
30835a52
S
803 (
804 set -x
805 $docker_path stop -t 10 $config
806 )
680dd4ea
S
807 fi
808
809 run_bootstrap
810
30835a52 811 if [ ! -z $existing ]
680dd4ea 812 then
30835a52
S
813 echo "Removing old container"
814 (
815 set -x
816 $docker_path rm $config
817 )
680dd4ea
S
818 fi
819
820 run_start
821 exit 0
822 ;;
823
7e738616 824
5f803fb4 825 destroy)
98bd0edf 826 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
30835a52 827 exit 0
5f803fb4
SS
828 ;;
829esac
7e738616 830
5f803fb4 831usage