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