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