Add arvbox support for overriding settings in application.yml
[arvados.git] / bin / arvbox
1 #!/bin/sh
2
3 set -e
4
5 if ! test -d /sys/fs/cgroup ; then
6      echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
7      echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
8      echo "places (such as /cgroup) are not supported."
9      exit 1
10 fi
11
12 if ! which docker >/dev/null 2>/dev/null ; then
13   echo "Arvbox requires Docker.  To install, run the following command as root:"
14   echo "curl -sSL https://get.docker.com/ | sh"
15   exit 1
16 fi
17
18 if test -z "$ARVBOX_DOCKER" ; then
19     if which greadlink >/dev/null 2>/dev/null ; then
20         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
21     else
22         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
23     fi
24 fi
25
26 if test -z "$ARVBOX_CONTAINER" ; then
27     ARVBOX_CONTAINER=arvbox
28 fi
29
30 if test -z "$ARVBOX_BASE" ; then
31     ARVBOX_BASE="$HOME/.arvbox"
32 fi
33
34 if test -z "$ARVBOX_DATA" ; then
35     ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
36 fi
37
38 if test -z "$ARVADOS_ROOT" ; then
39     ARVADOS_ROOT="$ARVBOX_DATA/arvados"
40 fi
41
42 if test -z "$ARVADOS_DEV_ROOT" ; then
43     ARVADOS_DEV_ROOT="$ARVBOX_DATA/arvados-dev"
44 fi
45
46 if test -z "$SSO_ROOT" ; then
47     SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
48 fi
49
50 PG_DATA="$ARVBOX_DATA/postgres"
51 VAR_DATA="$ARVBOX_DATA/var"
52 PASSENGER="$ARVBOX_DATA/passenger"
53 GEMS="$ARVBOX_DATA/gems"
54
55 getip() {
56     docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
57 }
58
59 updateconf() {
60     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
61         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(getip):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
62         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
63     else
64         mkdir -p $HOME/.config/arvados
65         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
66 ARVADOS_API_HOST=$(getip):8000
67 ARVADOS_API_TOKEN=
68 ARVADOS_API_HOST_INSECURE=true
69 EOF
70     fi
71 }
72
73 wait_for_arvbox() {
74     FF=/tmp/arvbox-fifo-$$
75     mkfifo $FF
76     docker logs -f $ARVBOX_CONTAINER > $FF &
77     LOGPID=$!
78     while read line ; do
79         echo $line
80         if echo $line | grep "Workbench is running at" >/dev/null ; then
81             kill $LOGPID
82         fi
83     done < $FF
84     rm $FF
85     echo
86     if test -n "$localip" ; then
87         echo "export ARVADOS_API_HOST=$localip:8000"
88     else
89         echo "export ARVADOS_API_HOST=$(getip):8000"
90     fi
91 }
92
93 run() {
94     if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
95         echo "Container $ARVBOX_CONTAINER is already running, use stop, restart or reboot"
96         exit 0
97     fi
98
99     if echo "$1" | grep '^public' ; then
100         if test -n "$ARVBOX_PUBLISH_IP" ; then
101             localip=$ARVBOX_PUBLISH_IP
102         else
103             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
104             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
105         fi
106         iptemp=$(tempfile)
107         echo $localip > $iptemp
108         chmod og+r $iptemp
109         PUBLIC="--volume=$iptemp:/var/run/localip_override
110               --publish=80:80
111               --publish=8000:8000
112               --publish=8900:8900
113               --publish=9001:9001
114               --publish=9002:9002
115               --publish=25100:25100
116               --publish=25107:25107
117               --publish=25108:25108
118               --publish=8001:8001"
119     else
120         PUBLIC=""
121     fi
122
123     if echo "$1" | grep 'demo$' ; then
124         if test -d "$ARVBOX_DATA" ; then
125             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
126             echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
127             exit 1
128         fi
129
130         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
131             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
132         fi
133
134         docker run \
135                --detach \
136                --name=$ARVBOX_CONTAINER \
137                --privileged \
138                --volumes-from $ARVBOX_CONTAINER-data \
139                $PUBLIC \
140                arvados/arvbox-demo
141         updateconf
142         wait_for_arvbox
143     else
144         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS"
145
146         if ! test -d "$ARVADOS_ROOT" ; then
147             git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
148         fi
149         if ! test -d "$SSO_ROOT" ; then
150             git clone https://github.com/curoverse/sso-devise-omniauth-provider.git "$SSO_ROOT"
151         fi
152
153         if test "$1" = test ; then
154             shift
155
156             if ! test -d "$ARVADOS_DEV_ROOT" ; then
157                 git clone https://github.com/curoverse/arvados-dev.git "$ARVADOS_DEV_ROOT"
158             fi
159
160             mkdir -p $VAR_DATA/test
161
162             docker run \
163                    --detach \
164                    --name=$ARVBOX_CONTAINER \
165                    --privileged \
166                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
167                    "--volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw" \
168                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
169                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
170                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
171                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
172                    "--volume=$GEMS:/var/lib/gems:rw" \
173                    arvados/arvbox-dev \
174                    /usr/local/bin/runsvinit -svdir=/etc/test-service
175
176             docker exec -ti \
177                     $ARVBOX_CONTAINER \
178                     /usr/local/lib/arvbox/runsu.sh \
179                     /usr/local/lib/arvbox/waitforpostgres.sh
180
181             docker exec -ti \
182                    $ARVBOX_CONTAINER \
183                    /usr/local/lib/arvbox/runsu.sh \
184                    /usr/local/lib/arvbox/service/sso/run-service --only-setup
185
186             docker exec -ti \
187                    $ARVBOX_CONTAINER \
188                    /usr/local/lib/arvbox/runsu.sh \
189                    /usr/local/lib/arvbox/service/api/run-service --only-setup
190
191             docker exec -ti \
192                    $ARVBOX_CONTAINER \
193                    /usr/local/lib/arvbox/runsu.sh \
194                    /usr/src/arvados-dev/jenkins/run-tests.sh \
195                    --temp /var/lib/arvados/test \
196                    WORKSPACE=/usr/src/arvados \
197                    GEM_HOME=/var/lib/gems \
198                    "$@"
199         elif echo "$1" | grep 'dev$' ; then
200             docker run \
201                    --detach \
202                    --name=$ARVBOX_CONTAINER \
203                    --privileged \
204                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
205                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
206                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
207                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
208                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
209                    "--volume=$GEMS:/var/lib/gems:rw" \
210                    $PUBLIC \
211                    arvados/arvbox-dev
212             updateconf
213             wait_for_arvbox
214             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
215         else
216             echo "Unknown configuration '$1'"
217         fi
218     fi
219 }
220
221 stop() {
222     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
223         docker stop $ARVBOX_CONTAINER
224     fi
225
226     VOLUMES=--volumes=true
227     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
228         docker rm $VOLUMES $ARVBOX_CONTAINER
229     fi
230     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
231         docker rm $VOLUMES $ARVBOX_CONTAINER
232     fi
233 }
234
235 build() {
236     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
237         echo "Could not find Dockerfile ($ARVBOX_DOCKER/Dockerfile.base)"
238         exit 1
239     fi
240     docker build -t arvados/arvbox-base -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
241     if test "$1" = localdemo -o "$1" = publicdemo ; then
242         docker build -t arvados/arvbox-demo -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
243     else
244         docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
245     fi
246 }
247
248 check() {
249     case "$1" in
250         localdemo|publicdemo|dev|publicdev|test)
251             true
252             ;;
253         *)
254             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
255             exit 1
256         ;;
257     esac
258 }
259
260 subcmd="$1"
261 if test -n "$subcmd" ; then
262     shift
263 fi
264 case "$subcmd" in
265     build)
266         check $@
267         build $@
268         ;;
269
270     start|run)
271         check $@
272         run $@
273         ;;
274
275     sh*)
276         docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/gems /bin/bash
277         ;;
278
279     stop)
280         stop
281         ;;
282
283     restart)
284         check $@
285         stop
286         run $@
287         ;;
288
289     reboot)
290         check $@
291         stop
292         build $@
293         run $@
294         ;;
295
296     ip|open)
297         if test "$subcmd" = 'ip' ; then
298             echo $(getip)
299         else
300             xdg-open http://$(getip)
301         fi
302         ;;
303
304     status)
305         echo "Selected: $ARVBOX_CONTAINER"
306         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
307             echo "Status: running"
308             echo "IP: $(getip)"
309         else
310             echo "Status: not running"
311         fi
312         if test -d "$ARVBOX_DATA" ; then
313             echo "Data: $ARVBOX_DATA"
314         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
315             echo "Data: $ARVBOX_CONTAINER-data"
316         else
317             echo "Data: none"
318         fi
319         ;;
320
321     reset|destroy)
322         stop
323         if test -d "$ARVBOX_DATA" ; then
324             if test "$subcmd" = destroy ; then
325                 if test "$1" != -f ; then
326                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
327                     echo "Use destroy -f if you really mean it."
328                     exit 1
329                 fi
330                 set -x
331                 rm -rf "$ARVBOX_DATA"
332             else
333                 if test "$1" != -f ; then
334                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
335                     echo "Code and downloaded packages will be preserved."
336                     echo "Use reset -f if you really mean it."
337                     exit 1
338                 fi
339                 set -x
340                 rm -rf "$ARVBOX_DATA/postgres"
341                 rm -rf "$ARVBOX_DATA/var"
342             fi
343         else
344             if test "$1" != -f ; then
345                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
346                 exit 1
347             fi
348             set -x
349             docker rm "$ARVBOX_CONTAINER-data"
350         fi
351         ;;
352
353     log)
354         if test -n "$1" ; then
355             docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM less --follow-name +GF "/etc/service/$1/log/main/current"
356         else
357             docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
358         fi
359         ;;
360
361     svrestart)
362         if test -n "$1" ; then
363             docker exec -ti $ARVBOX_CONTAINER sv restart "$1"
364             docker exec -ti $ARVBOX_CONTAINER sv restart ready
365         else
366             echo "Usage: $0 $subcmd <service>"
367             echo "Available services:"
368             docker exec -ti $ARVBOX_CONTAINER ls /etc/service
369         fi
370         ;;
371
372     clone)
373         if test -n "$2" ; then
374             cp -r "$ARVBOX_BASE/$1" "$ARVBOX_BASE/$2"
375             echo "Created new arvbox $2"
376             echo "export ARVBOX_CONTAINER=$2"
377         else
378             echo "clone <from> <to>   clone an arvbox"
379             echo "available arvboxes: $(ls $ARVBOX_BASE)"
380         fi
381         ;;
382
383     *)
384         echo "Arvados-in-a-box"
385         echo
386         echo "$(basename $0) (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)"
387         echo
388         echo "build <config>      build arvbox Docker image"
389         echo "start|run <config>  start $ARVBOX_CONTAINER container"
390         echo "open       open arvbox workbench in a web browser"
391         echo "shell      enter arvbox shell"
392         echo "ip         print arvbox ip address"
393         echo "status     print some information about current arvbox"
394         echo "stop       stop arvbox container"
395         echo "restart <config>  stop, then run again"
396         echo "reboot  <config>  stop, build arvbox Docker image, run"
397         echo "reset      delete arvbox arvados data (be careful!)"
398         echo "destroy    delete all arvbox code and data (be careful!)"
399         echo "log       <service> tail log of specified service"
400         echo "svrestart <service> restart specified service inside arvbox"
401         echo "clone <from> <to>   clone an arvbox"
402         ;;
403 esac