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