Use array to pass in env, preserving spaces
[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
122 set_template_info
123
124 base_image=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
125 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
126
127 update_pups=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
128 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
129
130 if [[ ! X"" = X"$base_image" ]]; then
131 image=$base_image
132 fi
133
134 set_volumes
135
136 rm -f $cidbootstrap
137
138 run_command="cd /pups &&"
139 if [[ ! "false" = $update_pups ]]; then
140 run_command="$run_command git pull &&"
141 fi
142 run_command="$run_command /pups/bin/pups --stdin"
143
144 (exec echo "$input" | docker run "${env[@]}" -e DOCKER_HOST_IP=$docker_ip -cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
145 /bin/bash -c "$run_command") \
146 || (docker rm `cat $cidbootstrap` && rm $cidbootstrap)
147
148 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
149
150 sleep 5
151
152 docker commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
153 docker rm `cat $cidbootstrap` && rm $cidbootstrap
154
155 echo "Successfully bootstrapped, to startup use ./launcher start $config"
156 exit 0
157 ;;
158
159 ssh)
160 if [ ! -e $cidfile ]
161 then
162 echo "No cid found"
163 exit 1
164 else
165 cid="`cat $cidfile`"
166 address="`docker port $cid 22`"
167 split=(${address//:/ })
168 exec ssh root@${split[0]} -p ${split[1]}
169 fi
170 ;;
171
172 stop)
173 if [ ! -e $cidfile ]
174 then
175 echo "No cid found"
176 exit 1
177 else
178 docker stop -t 10 `cat $cidfile`
179 exit 0
180 fi
181 ;;
182
183 logs)
184
185 if [ ! -e $cidfile ]
186 then
187 echo "No cid found"
188 exit 1
189 else
190 docker logs `cat $cidfile`
191 exit 0
192 fi
193 ;;
194
195 start)
196
197 if [ ! -e $cidfile ]
198 then
199 echo "No cid found, creating a new container"
200 ports=`cat $config_file | docker run -rm -i -a stdout -a stdin $image ruby -e \
201 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
202
203 set_template_info
204 set_volumes
205
206 existing=`docker ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
207 if [ ! -z $existing ]
208 then
209 echo "Found an existing container by its name, recovering cidfile, please rerun"
210 echo $existing > $cidfile
211 exit 1
212 fi
213
214 docker run "${env[@]}" -e DOCKER_HOST_IP=$docker_ip -name $config -cidfile $cidfile $ports \
215 -d $volumes $local_discourse/$config /usr/bin/runsvdir -P /etc/service
216
217 exit 0
218 else
219 cid=`cat $cidfile`
220
221 if [ -z $cid ]
222 then
223 echo "Detected empty cid file, deleting, please re-run"
224 rm $cidfile
225 exit 1
226 fi
227
228 found=`docker ps -q -a -notrunc | grep $cid`
229 if [ -z $found ]
230 then
231 echo "Invalid cid file, deleting, please re-run"
232 rm $cidfile
233 exit 1
234 fi
235
236 echo "cid found, ensuring container is started"
237 docker start `cat $cidfile`
238 exit 0
239 fi
240 ;;
241
242
243 destroy)
244 if [ -e $cidfile ]
245 then
246 echo "destroying container $cidfile"
247 docker stop -t 10 `cat $cidfile`
248 docker rm `cat $cidfile` && rm $cidfile
249 exit 0
250 else
251 echo "nothing to destroy cidfile does not exist"
252 exit 1
253 fi
254 ;;
255 esac
256
257 usage