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