FEATURE: hostname for instances so we can tell who is who
[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
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 install_docker() {
33
34 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
35 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
36 echo
37 echo "sudo apt-get update"
38 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
39 echo "sudo reboot"
40 echo
41
42 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
43 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
44 echo "sudo apt-get update"
45 echo "sudo apt-get install lxc-docker"
46
47 exit 1
48 }
49
50 set_volumes() {
51 volumes=`cat $config_file | docker run -rm -i -a stdout -a stdin $image ruby -e \
52 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
53 }
54
55 set_template_info() {
56
57 templates=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
58 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
59
60
61 arrTemplates=(${templates// / })
62 config_data=$(cat $config_file)
63
64 input="hack: true"
65
66
67 for template in "${arrTemplates[@]}"
68 do
69 [ ! -z $template ] && {
70 input="$input _FILE_SEPERATOR_ $(cat $template)"
71 }
72 done
73
74 # we always want our config file last so it takes priority
75 input="$input _FILE_SEPERATOR_ $config_data"
76
77 read -r -d '' env_ruby << 'RUBY'
78 require 'yaml'
79
80 input=STDIN.readlines.join
81 env = {}
82 input.split('_FILE_SEPERATOR_').each do |yml|
83 yml.strip!
84 begin
85 env.merge!(YAML.load(yml)['env'] || {})
86 rescue => e
87 puts yml
88 p e
89 end
90 end
91 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
92 RUBY
93
94 raw=`exec echo "$input" | docker run -rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
95
96 env=()
97 while read i; do
98 env[${#env[@]}]=$i
99 done <<< "$raw"
100
101 echo "Calculated ENV: ${env[@]}"
102 }
103
104 [ -z $docker_path ] && {
105 install_docker
106 }
107
108
109 [ $# -ne 2 ] && {
110 usage
111 }
112
113 if [ ! -e $config_file ]
114 then
115 echo "Config file was not found, ensure $config_file exists"
116 exit 1
117 fi
118
119 case "$command" in
120 bootstrap)
121 # Is the image available?
122 # If not, pull it here so the user is aware what's happening.
123 docker history $image >/dev/null 2>&1 || docker pull $image
124
125 set_template_info
126
127 base_image=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
128 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
129
130 update_pups=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
131 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
132
133 if [[ ! X"" = X"$base_image" ]]; then
134 image=$base_image
135 fi
136
137 set_volumes
138
139 rm -f $cidbootstrap
140
141 run_command="cd /pups &&"
142 if [[ ! "false" = $update_pups ]]; then
143 run_command="$run_command git pull &&"
144 fi
145 run_command="$run_command /pups/bin/pups --stdin"
146
147 (exec echo "$input" | docker run "${env[@]}" -e DOCKER_HOST_IP=$docker_ip -cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
148 /bin/bash -c "$run_command") \
149 || (docker rm `cat $cidbootstrap` && rm $cidbootstrap)
150
151 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
152
153 sleep 5
154
155 docker commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
156 docker rm `cat $cidbootstrap` && rm $cidbootstrap
157
158 echo "Successfully bootstrapped, to startup use ./launcher start $config"
159 exit 0
160 ;;
161
162 ssh)
163 if [ ! -e $cidfile ]
164 then
165 echo "No cid found"
166 exit 1
167 else
168 cid="`cat $cidfile`"
169 address="`docker port $cid 22`"
170 split=(${address//:/ })
171 exec ssh -o StrictHostKeyChecking=no root@${split[0]} -p ${split[1]}
172 fi
173 ;;
174
175 stop)
176 if [ ! -e $cidfile ]
177 then
178 echo "No cid found"
179 exit 1
180 else
181 docker stop -t 10 `cat $cidfile`
182 exit 0
183 fi
184 ;;
185
186 logs)
187
188 if [ ! -e $cidfile ]
189 then
190 echo "No cid found"
191 exit 1
192 else
193 docker logs `cat $cidfile`
194 exit 0
195 fi
196 ;;
197
198 start)
199
200 if [ ! -e $cidfile ]
201 then
202 echo "No cid found, creating a new container"
203 ports=`cat $config_file | docker run -rm -i -a stdout -a stdin $image ruby -e \
204 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
205
206 set_template_info
207 set_volumes
208
209 existing=`docker ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
210 if [ ! -z $existing ]
211 then
212 echo "Found an existing container by its name, recovering cidfile, please rerun"
213 echo $existing > $cidfile
214 exit 1
215 fi
216
217 docker run "${env[@]}" -h "`hostname`-$config" -e DOCKER_HOST_IP=$docker_ip -name $config -cidfile $cidfile $ports \
218 -d $volumes $local_discourse/$config /usr/bin/runsvdir -P /etc/service
219
220 exit 0
221 else
222 cid=`cat $cidfile`
223
224 if [ -z $cid ]
225 then
226 echo "Detected empty cid file, deleting, please re-run"
227 rm $cidfile
228 exit 1
229 fi
230
231 found=`docker ps -q -a -notrunc | grep $cid`
232 if [ -z $found ]
233 then
234 echo "Invalid cid file, deleting, please re-run"
235 rm $cidfile
236 exit 1
237 fi
238
239 echo "cid found, ensuring container is started"
240 docker start `cat $cidfile`
241 exit 0
242 fi
243 ;;
244
245
246 destroy)
247 if [ -e $cidfile ]
248 then
249 echo "destroying container $cidfile"
250 docker stop -t 10 `cat $cidfile`
251 docker rm `cat $cidfile` && rm $cidfile
252 exit 0
253 else
254 echo "nothing to destroy cidfile does not exist"
255 exit 1
256 fi
257 ;;
258 esac
259
260 usage