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