* re-enable SPDY
[discourse_docker.git] / launcher
CommitLineData
ace450bd 1#!/bin/bash
7e738616
S
2
3command=$1
4config=$2
55d17203
RW
5opt=$3
6
7936ebaa 7cd "$(dirname "$0")"
55d17203 8
60668406 9docker_min_version='0.9.1'
68f0b9dc 10docker_rec_version='0.11.1'
60668406 11
8dea575c 12config_file=containers/"$config".yml
7e738616 13cidfile=cids/"$config".cid
1acce9e4 14cidbootstrap=cids/"$config"_boostrap.cid
5efded6a 15local_discourse=local_discourse
2d7d1501 16image=samsaffron/discourse:0.2.1
4807b1b8 17docker_path=`which docker.io || which docker`
7e738616 18
80c11be3
SS
19docker_ip=`/sbin/ifconfig | \
20 grep -B1 "inet addr" | \
21 awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
22 grep docker0 | \
23 awk -F: '{ print $3 }';`
24
25
5f803fb4 26usage () {
55d17203 27 echo "Usage: launcher COMMAND CONFIG [--skip-prereqs]"
7e738616 28 echo "Commands:"
1acce9e4
SS
29 echo " start: Start/initialize a container"
30 echo " stop: Stop a running container"
31 echo " restart: Restart a container"
32 echo " destroy: Stop and remove a container"
5f803fb4 33 echo " ssh: Start a bash shell in a running container"
1acce9e4 34 echo " logs: Docker logs for container"
7936ebaa 35 echo " mailtest: Test the mail settings in a container"
408a9c19 36 echo " bootstrap: Bootstrap a container for the config based on a template"
680dd4ea 37 echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
55d17203
RW
38 echo
39 echo "Options:"
40 echo " --skip-prereqs Don't check prerequisites"
7e738616
S
41 exit 1
42}
43
60668406
DP
44compare_version() {
45 declare -a ver_a
46 declare -a ver_b
47 IFS=. read -a ver_a <<< "$1"
48 IFS=. read -a ver_b <<< "$2"
49
50 while [[ -n $ver_a ]]; do
51 if (( ver_a > ver_b )); then
52 return 0
53 elif (( ver_b > ver_a )); then
54 return 1
55 else
56 unset ver_a[0]
57 ver_a=("${ver_a[@]}")
58 unset ver_b[0]
59 ver_b=("${ver_b[@]}")
60 fi
61 done
62 return 1 # They are equal
63}
64
a3e18d95
S
65prereqs() {
66
e741295a 67 # 1. docker daemon running?
4807b1b8 68 test=`$docker_path info >/dev/null`
e741295a
MB
69
70 if [[ $? -ne 0 ]] ; then
71 echo "Cannot connect to the docker daemon - verify it is running and you have access"
72 exit 1
73 fi
74
2d7d1501 75 # 2. running aufs
4807b1b8 76 test=`$docker_path info 2> /dev/null | grep 'Driver: aufs'`
a3e18d95 77 if [[ "$test" =~ "aufs" ]] ; then : ; else
2d7d1501
S
78 echo "Your Docker installation is not using aufs, in the past we have had issues with it"
79 echo "If you are unable to bootstrap your image (or stop it) please report the issue at:"
80 echo "https://meta.discourse.org/t/discourse-docker-installation-without-aufs/15639"
a3e18d95
S
81 fi
82
60668406
DP
83 # 3. running recommended docker version
84 test=($($docker_path --version)) # Get docker version string
85 test=${test[2]//,/} # Get version alone and strip comma if exists
a3e18d95 86
60668406
DP
87 # At least minimum version
88 if compare_version "${socker_min_version}" "${test}"; then
89 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
a3e18d95
S
90 exit 1
91 fi
92
60668406
DP
93 # Recommend best version
94 if compare_version "${docker_rec_version}" "${test}"; then
95 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
96 fi
97
e741295a 98 # 4. able to attach stderr / out / tty
4807b1b8 99 test=`$docker_path run -i --rm -a stdout -a stderr $image echo working`
a3e18d95
S
100 if [[ "$test" =~ "working" ]] ; then : ; else
101 echo "Your Docker installation is not working correctly"
102 echo
103 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
104 exit 1
105 fi
106}
107
55d17203
RW
108if [ "$opt" != "--skip-prereqs" ] ; then
109 prereqs
110fi
a3e18d95 111
88126eba 112get_ssh_pub_key() {
9d28af0e
MB
113 if tty -s ; then
114 if [[ ! -e ~/.ssh/id_rsa.pub && ! -e ~/.ssh/id_dsa.pub ]] ; then
8aca5cb7
JA
115 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
116 read -p "Generate a SSH key? (Y/n) " -n 1 -r
4c01e298
S
117 if [[ $REPLY =~ ^[Nn]$ ]] ; then
118 echo
119 echo WARNING: You may not be able to log in to your container.
88126eba 120 echo
88126eba
S
121 else
122 echo
4c01e298
S
123 echo Generating SSH key
124 mkdir -p ~/.ssh && ssh-keygen -f ~/.ssh/id_rsa -t rsa -N ''
88126eba
S
125 echo
126 fi
127 fi
128 fi
129
9d28af0e 130 ssh_pub_key="$(cat ~/.ssh/id_rsa.pub 2>/dev/null || cat ~/.ssh/id_dsa.pub)"
88126eba
S
131}
132
133
52388b87
SS
134install_docker() {
135
136 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
137 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
138 echo
139 echo "sudo apt-get update"
140 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
141 echo "sudo reboot"
142 echo
143
144 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
145 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
146 echo "sudo apt-get update"
147 echo "sudo apt-get install lxc-docker"
148
149 exit 1
150}
151
d90671f3 152set_volumes() {
4807b1b8 153 volumes=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
d90671f3
SS
154 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
155}
156
7f77c274
SS
157set_template_info() {
158
4807b1b8 159 templates=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
7f77c274
SS
160 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
161
162
163 arrTemplates=(${templates// / })
164 config_data=$(cat $config_file)
165
166 input="hack: true"
167
168
169 for template in "${arrTemplates[@]}"
170 do
171 [ ! -z $template ] && {
172 input="$input _FILE_SEPERATOR_ $(cat $template)"
173 }
174 done
175
176 # we always want our config file last so it takes priority
177 input="$input _FILE_SEPERATOR_ $config_data"
178
179 read -r -d '' env_ruby << 'RUBY'
180 require 'yaml'
181
182 input=STDIN.readlines.join
183 env = {}
184 input.split('_FILE_SEPERATOR_').each do |yml|
185 yml.strip!
186 begin
187 env.merge!(YAML.load(yml)['env'] || {})
188 rescue => e
189 puts yml
190 p e
191 end
192 end
4b563ee8 193 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
7f77c274
SS
194RUBY
195
4807b1b8 196 raw=`exec echo "$input" | $docker_path run --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
4b563ee8
SS
197
198 env=()
199 while read i; do
16f2d250
S
200 if [ -n "$i" ]; then
201 env[${#env[@]}]=$i
202 fi
4b563ee8
SS
203 done <<< "$raw"
204
205 echo "Calculated ENV: ${env[@]}"
7f77c274
SS
206}
207
52388b87
SS
208[ -z $docker_path ] && {
209 install_docker
210}
211
5f803fb4 212
c1005add 213[ $# -lt 2 ] && {
5f803fb4
SS
214 usage
215}
216
7e738616
S
217if [ ! -e $config_file ]
218 then
219 echo "Config file was not found, ensure $config_file exists"
220 exit 1
221fi
222
337a89aa 223
7936ebaa
MB
224run_mailtest(){
225 if [ ! -e $config_file ]; then
226 echo "Config does not exist: $config_file" >&2
227 exit 1
228 fi
229 exec scripts/mailtest $config_file
230}
231
337a89aa
S
232run_stop(){
233 if [ ! -e $cidfile ]
234 then
235 echo "No cid found"
236 exit 1
237 else
4807b1b8 238 $docker_path stop -t 10 `cat $cidfile`
337a89aa
S
239 fi
240}
241
242run_start(){
243
244 if [ ! -e $cidfile ]
245 then
246 echo "No cid found, creating a new container"
4807b1b8 247 ports=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
337a89aa
S
248 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
249
250 set_template_info
251 set_volumes
252
4807b1b8 253 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
337a89aa
S
254 if [ ! -z $existing ]
255 then
256 echo "Found an existing container by its name, recovering cidfile, please rerun"
257 echo $existing > $cidfile
258 exit 1
259 fi
260
4807b1b8 261 $docker_path run "${env[@]}" -h "`hostname`-$config" -e DOCKER_HOST_IP=$docker_ip --name $config -t --cidfile $cidfile $ports \
337a89aa
S
262 -d $volumes $local_discourse/$config /usr/bin/runsvdir -P /etc/service
263
264 exit 0
265 else
266 cid=`cat $cidfile`
267
268 if [ -z $cid ]
269 then
270 echo "Detected empty cid file, deleting, please re-run"
271 rm $cidfile
272 exit 1
273 fi
274
4807b1b8 275 found=`$docker_path ps -q -a --no-trunc | grep $cid`
337a89aa
S
276 if [ -z $found ]
277 then
278 echo "Invalid cid file, deleting, please re-run"
279 rm $cidfile
280 exit 1
281 fi
282
283 echo "cid found, ensuring container is started"
4807b1b8 284 $docker_path start `cat $cidfile`
337a89aa
S
285 exit 0
286 fi
287
288}
289
680dd4ea
S
290run_bootstrap(){
291 get_ssh_pub_key
88126eba 292
680dd4ea
S
293 # Is the image available?
294 # If not, pull it here so the user is aware what's happening.
4807b1b8 295 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
88126eba 296
680dd4ea 297 set_template_info
93149421 298
4807b1b8 299 base_image=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 300 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
93149421 301
4807b1b8 302 update_pups=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
680dd4ea 303 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
b9c7b50e 304
680dd4ea
S
305 if [[ ! X"" = X"$base_image" ]]; then
306 image=$base_image
307 fi
b9c7b50e 308
680dd4ea 309 set_volumes
b9c7b50e 310
680dd4ea 311 rm -f $cidbootstrap
d90671f3 312
680dd4ea
S
313 run_command="cd /pups &&"
314 if [[ ! "false" = $update_pups ]]; then
315 run_command="$run_command git pull &&"
316 fi
317 run_command="$run_command /pups/bin/pups --stdin"
2162f1d4 318
680dd4ea 319 echo $run_command
b9c7b50e 320
680dd4ea 321 env=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
c4498636 322
4807b1b8 323 (exec echo "$input" | $docker_path run "${env[@]}" -e DOCKER_HOST_IP=$docker_ip --cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
680dd4ea 324 /bin/bash -c "$run_command") \
4807b1b8 325 || ($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
88126eba 326
680dd4ea 327 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
9fb5f2d3 328
680dd4ea 329 sleep 5
2162f1d4 330
4807b1b8
MB
331 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
332 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
680dd4ea 333}
9fb5f2d3 334
680dd4ea
S
335case "$command" in
336 bootstrap)
680dd4ea 337 run_bootstrap
2dd2e330 338 echo "Successfully bootstrapped, to startup use ./launcher start $config"
4b3aebe1 339 exit 0
5f803fb4 340 ;;
1acce9e4 341
7936ebaa
MB
342 mailtest)
343 run_mailtest
344 exit 0
345 ;;
346
5f803fb4
SS
347 ssh)
348 if [ ! -e $cidfile ]
349 then
350 echo "No cid found"
351 exit 1
352 else
353 cid="`cat $cidfile`"
4807b1b8 354 address="`$docker_path port $cid 22`"
5f803fb4 355 split=(${address//:/ })
38c09f5e 356 exec ssh -o StrictHostKeyChecking=no root@${split[0]} -p ${split[1]}
5f803fb4
SS
357 fi
358 ;;
7e738616 359
5f803fb4 360 stop)
337a89aa
S
361 run_stop
362 exit 0
5f803fb4 363 ;;
7e738616 364
5f803fb4 365 logs)
7e738616 366
5f803fb4
SS
367 if [ ! -e $cidfile ]
368 then
369 echo "No cid found"
370 exit 1
371 else
4807b1b8 372 $docker_path logs `cat $cidfile`
5f803fb4
SS
373 exit 0
374 fi
375 ;;
7e738616 376
337a89aa
S
377 restart)
378 run_stop
379 run_start
380 exit 0
381 ;;
80c11be3 382
337a89aa
S
383 start)
384 run_start
385 exit 0
5f803fb4 386 ;;
7e738616 387
680dd4ea
S
388 rebuild)
389 if [ -e $cidfile ]
390 then
391 echo "Stopping old container"
4807b1b8 392 $docker_path stop -t 10 `cat $cidfile`
680dd4ea
S
393 fi
394
395 run_bootstrap
396
397 if [ -e $cidfile ]
398 then
4807b1b8 399 $docker_path rm `cat $cidfile` && rm $cidfile
680dd4ea
S
400 fi
401
402 run_start
403 exit 0
404 ;;
405
7e738616 406
5f803fb4
SS
407 destroy)
408 if [ -e $cidfile ]
409 then
410 echo "destroying container $cidfile"
4807b1b8
MB
411 $docker_path stop -t 10 `cat $cidfile`
412 $docker_path rm `cat $cidfile` && rm $cidfile
5f803fb4
SS
413 exit 0
414 else
415 echo "nothing to destroy cidfile does not exist"
416 exit 1
417 fi
418 ;;
419esac
7e738616 420
5f803fb4 421usage