16267: switch to `arvados-server install -type test` for installing
[arvados.git] / tools / arvbox / bin / arvbox
1 #!/bin/bash
2 # Copyright (C) The Arvados Authors. All rights reserved.
3 #
4 # SPDX-License-Identifier: AGPL-3.0
5
6 set -e
7
8 if ! test -d /sys/fs/cgroup ; then
9      echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
10      echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
11      echo "places (such as /cgroup) are not supported."
12      exit 1
13 fi
14
15 if ! which docker >/dev/null 2>/dev/null ; then
16   echo "Arvbox requires Docker.  To install, run the following command as root:"
17   echo "curl -sSL https://get.docker.com/ | sh"
18   exit 1
19 fi
20
21 if test -z "$ARVBOX_DOCKER" ; then
22     set +e
23     if which greadlink >/dev/null 2>/dev/null ; then
24         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
25     else
26         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
27     fi
28     set -e
29 fi
30
31 if test -z "$ARVBOX_CONTAINER" ; then
32     ARVBOX_CONTAINER=arvbox
33 fi
34
35 if test -z "$ARVBOX_BASE" ; then
36     ARVBOX_BASE="$HOME/.arvbox"
37 fi
38
39 if test -z "$ARVBOX_DATA" ; then
40     ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
41 fi
42
43 if test -z "$ARVADOS_ROOT" ; then
44     ARVADOS_ROOT="$ARVBOX_DATA/arvados"
45 fi
46
47 if test -z "$COMPOSER_ROOT" ; then
48     COMPOSER_ROOT="$ARVBOX_DATA/composer"
49 fi
50
51 if test -z "$WORKBENCH2_ROOT" ; then
52     WORKBENCH2_ROOT="$ARVBOX_DATA/workbench2"
53 fi
54
55 PG_DATA="$ARVBOX_DATA/postgres"
56 VAR_DATA="$ARVBOX_DATA/var"
57 PASSENGER="$ARVBOX_DATA/passenger"
58 GEMS="$ARVBOX_DATA/gems"
59 PIPCACHE="$ARVBOX_DATA/pip"
60 NPMCACHE="$ARVBOX_DATA/npm"
61 GOSTUFF="$ARVBOX_DATA/gopath"
62 RLIBS="$ARVBOX_DATA/Rlibs"
63 ARVADOS_CONTAINER_PATH="/var/lib/arvados-arvbox"
64 GEM_HOME="/var/lib/arvados/lib/ruby/gems/2.5.0"
65
66 getip() {
67     docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
68 }
69
70 gethost() {
71     set +e
72     OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
73     CODE=$?
74     set -e
75     if test "$CODE" = 0 ; then
76        echo $OVERRIDE
77     else
78         getip
79     fi
80 }
81
82 getclusterid() {
83     docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
84 }
85
86 updateconf() {
87     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
88         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
89         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
90     else
91         mkdir -p $HOME/.config/arvados
92         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
93 ARVADOS_API_HOST=$(gethost):8000
94 ARVADOS_API_TOKEN=
95 ARVADOS_API_HOST_INSECURE=true
96 EOF
97     fi
98 }
99
100 listusers() {
101     docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
102 }
103
104 wait_for_arvbox() {
105     FF=/tmp/arvbox-fifo-$$
106     mkfifo $FF
107     docker logs -f $ARVBOX_CONTAINER > $FF &
108     LOGPID=$!
109     while read line ; do
110         if [[ $line =~ "ok: down: ready:" ]] ; then
111             kill $LOGPID
112             set +e
113             wait $LOGPID 2>/dev/null
114             set -e
115         else
116             echo $line
117         fi
118     done < $FF
119     rm $FF
120     echo
121     if test -n "$localip" ; then
122         echo "export ARVADOS_API_HOST=$localip:8000"
123     else
124         echo "export ARVADOS_API_HOST=$(gethost):8000"
125     fi
126 }
127
128 docker_run_dev() {
129     docker run \
130            "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
131            "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
132            "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
133            "--volume=$PG_DATA:/var/lib/postgresql:rw" \
134            "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
135            "--volume=$PASSENGER:/var/lib/passenger:rw" \
136            "--volume=$GEMS:$GEM_HOME:rw" \
137            "--volume=$PIPCACHE:/var/lib/pip:rw" \
138            "--volume=$NPMCACHE:/var/lib/npm:rw" \
139            "--volume=$GOSTUFF:/var/lib/gopath:rw" \
140            "--volume=$RLIBS:/var/lib/Rlibs:rw" \
141            --label "org.arvados.arvbox_config=$CONFIG" \
142            "$@"
143 }
144
145 running_config() {
146     docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
147 }
148
149 run() {
150     CONFIG=$1
151     TAG=$2
152
153     shift
154
155     need_setup=1
156
157     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
158         if [[ $(running_config) != "$CONFIG" ]] ; then
159             echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
160             return 1
161         fi
162         if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
163             need_setup=0
164         else
165             echo "Container $ARVBOX_CONTAINER is already running"
166             return 0
167         fi
168     fi
169
170     if test $need_setup = 1 ; then
171         if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
172             echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
173             return 1
174         fi
175     fi
176
177     if test -n "$TAG"
178     then
179         if test $(echo $TAG | cut -c1-1) != '-' ; then
180             TAG=":$TAG"
181             shift
182         else
183             if [[ $TAG = '-' ]] ; then
184                 shift
185             fi
186             unset TAG
187         fi
188     fi
189
190     if [[ "$CONFIG" =~ ^public ]] ; then
191         if test -n "$ARVBOX_PUBLISH_IP" ; then
192             localip=$ARVBOX_PUBLISH_IP
193         else
194             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
195             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
196         fi
197         echo "Public arvbox will use address $localip"
198         iptemp=$(mktemp)
199         echo $localip > $iptemp
200         chmod og+r $iptemp
201         PUBLIC="--volume=$iptemp:/var/run/localip_override
202               --publish=443:443
203               --publish=3001:3001
204               --publish=8000:8000
205               --publish=8900:8900
206               --publish=9000:9000
207               --publish=9002:9002
208               --publish=25101:25101
209               --publish=8001:8001
210               --publish=8002:8002
211               --publish=4202:4202
212               --publish=45000-45020:45000-45020"
213     else
214         PUBLIC=""
215     fi
216
217     if [[ "$CONFIG" =~ demo$ ]] ; then
218         if test -d "$ARVBOX_DATA" ; then
219             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
220             echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
221             exit 1
222         fi
223
224         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
225             docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
226         fi
227
228         docker run \
229                --detach \
230                --name=$ARVBOX_CONTAINER \
231                --privileged \
232                --volumes-from $ARVBOX_CONTAINER-data \
233                --label "org.arvados.arvbox_config=$CONFIG" \
234                $PUBLIC \
235                arvados/arvbox-demo$TAG
236         updateconf
237         wait_for_arvbox
238     else
239         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
240
241         if ! test -d "$ARVADOS_ROOT" ; then
242             git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
243         fi
244         if ! test -d "$COMPOSER_ROOT" ; then
245             git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
246             git -C "$COMPOSER_ROOT" checkout arvados-fork
247             git -C "$COMPOSER_ROOT" pull
248         fi
249         if ! test -d "$WORKBENCH2_ROOT" ; then
250             git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
251         fi
252
253         if [[ "$CONFIG" = test ]] ; then
254
255             mkdir -p $VAR_DATA/test
256
257             if test "$need_setup" = 1 ; then
258                 docker_run_dev \
259                        --detach \
260                        --name=$ARVBOX_CONTAINER \
261                        --privileged \
262                        "--env=SVDIR=/etc/test-service" \
263                        arvados/arvbox-dev$TAG
264
265                 docker exec -ti \
266                        $ARVBOX_CONTAINER \
267                        /usr/local/lib/arvbox/runsu.sh \
268                        /usr/local/lib/arvbox/waitforpostgres.sh
269             fi
270
271             interactive=""
272             if [[ -z "$@" ]] ; then
273                 interactive=--interactive
274             fi
275
276             docker exec -ti \
277                    -e LINES=$(tput lines) \
278                    -e COLUMNS=$(tput cols) \
279                    -e TERM=$TERM \
280                    -e WORKSPACE=/usr/src/arvados \
281                    -e GEM_HOME=$GEM_HOME \
282                    -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
283                    $ARVBOX_CONTAINER \
284                    /usr/local/lib/arvbox/runsu.sh \
285                    /usr/src/arvados/build/run-tests.sh \
286                    --temp $ARVADOS_CONTAINER_PATH/test \
287                    $interactive \
288                    "$@"
289         elif [[ "$CONFIG" = devenv ]] ; then
290             if [[ $need_setup = 1 ]] ; then
291                     docker_run_dev \
292                     --detach \
293                     --name=${ARVBOX_CONTAINER} \
294                     "--env=SVDIR=/etc/devenv-service" \
295                         "--volume=$HOME:$HOME:rw" \
296                     --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
297                         arvados/arvbox-dev$TAG
298             fi
299             exec docker exec --interactive --tty \
300                  -e LINES=$(tput lines) \
301                  -e COLUMNS=$(tput cols) \
302                  -e TERM=$TERM \
303                  -e "ARVBOX_HOME=$HOME" \
304                  -e "DISPLAY=$DISPLAY" \
305                  --workdir=$PWD \
306                  ${ARVBOX_CONTAINER} \
307                  /usr/local/lib/arvbox/devenv.sh "$@"
308         elif [[ "$CONFIG" =~ dev$ ]] ; then
309             docker_run_dev \
310                    --detach \
311                    --name=$ARVBOX_CONTAINER \
312                    --privileged \
313                    $PUBLIC \
314                    arvados/arvbox-dev$TAG
315             updateconf
316             wait_for_arvbox
317             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
318             echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
319             if [[ "$(listusers)" =~ ^\{\} ]] ; then
320                 echo "No users defined, use 'arvbox adduser' to add user logins"
321             else
322                 echo "Use 'arvbox listusers' to see user logins"
323             fi
324         else
325             echo "Unknown configuration '$CONFIG'"
326         fi
327     fi
328 }
329
330 update() {
331     CONFIG=$1
332     TAG=$2
333
334     if test -n "$TAG"
335     then
336         if test $(echo $TAG | cut -c1-1) != '-' ; then
337             TAG=":$TAG"
338             shift
339         else
340             unset TAG
341         fi
342     fi
343
344     if echo "$CONFIG" | grep 'demo$' ; then
345         docker pull arvados/arvbox-demo$TAG
346     else
347         docker pull arvados/arvbox-dev$TAG
348     fi
349 }
350
351 stop() {
352     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
353         docker stop $ARVBOX_CONTAINER
354     fi
355
356     VOLUMES=--volumes=true
357     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
358         docker rm $VOLUMES $ARVBOX_CONTAINER
359     fi
360     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
361         docker rm $VOLUMES $ARVBOX_CONTAINER
362     fi
363 }
364
365 build() {
366     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
367         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
368         exit 1
369     fi
370     if docker --version |grep " 1\.[0-9]\." ; then
371         # Docker version prior 1.10 require -f flag
372         # -f flag removed in Docker 1.12
373         FORCE=-f
374     fi
375     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
376     docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
377     docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
378     if test "$1" = localdemo -o "$1" = publicdemo ; then
379         docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
380         docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
381     else
382         docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
383         docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
384     fi
385 }
386
387 check() {
388     case "$1" in
389         localdemo|publicdemo|dev|publicdev|test|devenv)
390             true
391             ;;
392         *)
393             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
394             exit 1
395         ;;
396     esac
397 }
398
399 subcmd="$1"
400 if test -n "$subcmd" ; then
401     shift
402 fi
403 case "$subcmd" in
404     build)
405         check $@
406         build $@
407         ;;
408
409     rebuild)
410         check $@
411         NO_CACHE=--no-cache build $@
412         ;;
413
414     start|run)
415         check $@
416         run $@
417         ;;
418
419     sh*)
420         exec docker exec --interactive --tty \
421                -e LINES=$(tput lines) \
422                -e COLUMNS=$(tput cols) \
423                -e TERM=$TERM \
424                -e GEM_HOME=$GEM_HOME \
425                $ARVBOX_CONTAINER /bin/bash
426         ;;
427
428     ash*)
429         exec docker exec --interactive --tty \
430                -e LINES=$(tput lines) \
431                -e COLUMNS=$(tput cols) \
432                -e TERM=$TERM \
433                -e GEM_HOME=$GEM_HOME \
434                -u arvbox \
435                -w /usr/src/arvados \
436                $ARVBOX_CONTAINER /bin/bash --login
437         ;;
438
439     pipe)
440         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
441         ;;
442
443     stop)
444         stop
445         ;;
446
447     restart)
448         check $@
449         stop
450         run $@
451         ;;
452
453     reboot)
454         check $@
455         stop
456         build $@
457         run $@
458         ;;
459
460     update)
461         check $@
462         stop
463         update $@
464         run $@
465         ;;
466
467     ip)
468         getip
469         ;;
470
471     host)
472         gethost
473         ;;
474
475     open)
476         exec xdg-open http://$(gethost)
477         ;;
478
479     status)
480         echo "Container: $ARVBOX_CONTAINER"
481         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
482             echo "Cluster id: $(getclusterid)"
483             echo "Status: running"
484             echo "Container IP: $(getip)"
485             echo "Published host: $(gethost)"
486         else
487             echo "Status: not running"
488         fi
489         if test -d "$ARVBOX_DATA" ; then
490             echo "Data: $ARVBOX_DATA"
491         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
492             echo "Data: $ARVBOX_CONTAINER-data"
493         else
494             echo "Data: none"
495         fi
496         ;;
497
498     reset|destroy)
499         stop
500         if test -d "$ARVBOX_DATA" ; then
501             if test "$subcmd" = destroy ; then
502                 if test "$1" != -f ; then
503                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
504                     echo "Use destroy -f if you really mean it."
505                     exit 1
506                 fi
507                 set -x
508                 chmod -R u+w "$ARVBOX_DATA"
509                 rm -rf "$ARVBOX_DATA"
510             else
511                 if test "$1" != -f ; then
512                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
513                     echo "Code and downloaded packages will be preserved."
514                     echo "Use reset -f if you really mean it."
515                     exit 1
516                 fi
517                 set -x
518                 rm -rf "$ARVBOX_DATA/postgres"
519                 rm -rf "$ARVBOX_DATA/var"
520             fi
521         else
522             if test "$1" != -f ; then
523                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
524                 exit 1
525             fi
526             set -x
527             docker rm "$ARVBOX_CONTAINER-data"
528         fi
529         ;;
530
531     log)
532         if test -n "$1" ; then
533             exec docker exec -ti -e LINES=$(tput lines) -e COLUMNS=$(tput cols) -e TERM=$TERM $ARVBOX_CONTAINER less --follow-name -R +GF "/etc/service/$1/log/main/current"
534         else
535             exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
536         fi
537         ;;
538
539     cat)
540         if test -n "$1" ; then
541             exec docker exec $ARVBOX_CONTAINER cat "$@"
542         else
543             echo "Usage: $0 $subcmd <files>"
544         fi
545         ;;
546
547     ls)
548         exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
549         ;;
550
551     sv)
552         if test -n "$1" -a -n "$2" ; then
553             exec docker exec $ARVBOX_CONTAINER sv "$@"
554         else
555             echo "Usage: $0 $subcmd <start|stop|restart> <service>"
556             echo "Available services:"
557             exec docker execa $ARVBOX_CONTAINER ls /etc/service
558         fi
559         ;;
560
561     clone)
562         if test -n "$2" ; then
563             mkdir -p "$ARVBOX_BASE/$2"
564             cp -a "$ARVBOX_BASE/$1/passenger" \
565                "$ARVBOX_BASE/$1/gems" \
566                "$ARVBOX_BASE/$1/pip" \
567                "$ARVBOX_BASE/$1/npm" \
568                "$ARVBOX_BASE/$1/gopath" \
569                "$ARVBOX_BASE/$1/Rlibs" \
570                "$ARVBOX_BASE/$1/arvados" \
571                "$ARVBOX_BASE/$1/composer" \
572                "$ARVBOX_BASE/$1/workbench2" \
573                "$ARVBOX_BASE/$2"
574             echo "Created new arvbox $2"
575             echo "export ARVBOX_CONTAINER=$2"
576         else
577             echo "clone <from> <to>   clone an arvbox"
578             echo "available arvboxes: $(ls $ARVBOX_BASE)"
579         fi
580         ;;
581
582     root-cert)
583         CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
584         if test -n "$1" ; then
585             CERT="$1"
586         fi
587         docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
588         echo "Certificate copied to $CERT"
589         ;;
590
591     psql)
592         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat $ARVADOS_CONTAINER_PATH/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados'
593         ;;
594
595     checkpoint)
596         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat $ARVADOS_CONTAINER_PATH/api_database_pw) exec pg_dump --host=localhost --username=arvados --clean arvados_development > $ARVADOS_CONTAINER_PATH/checkpoint.sql'
597         ;;
598
599     restore)
600         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat $ARVADOS_CONTAINER_PATH/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados --quiet --file=$ARVADOS_CONTAINER_PATH/checkpoint.sql'
601         ;;
602
603     hotreset)
604         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash - <<EOF
605 sv stop api
606 sv stop controller
607 sv stop websockets
608 sv stop keepstore0
609 sv stop keepstore1
610 sv stop keepproxy
611 cd /usr/src/arvados/services/api
612 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
613 export RAILS_ENV=development
614 bundle exec rake db:drop
615 rm $ARVADOS_CONTAINER_PATH/api_database_setup
616 rm $ARVADOS_CONTAINER_PATH/superuser_token
617 rm $ARVADOS_CONTAINER_PATH/keep0-uuid
618 rm $ARVADOS_CONTAINER_PATH/keep1-uuid
619 rm $ARVADOS_CONTAINER_PATH/keepproxy-uuid
620 sv start api
621 sv start controller
622 sv start websockets
623 sv restart keepstore0
624 sv restart keepstore1
625 sv restart keepproxy
626 EOF
627         ;;
628
629     adduser)
630         docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
631         docker exec $ARVBOX_CONTAINER sv restart controller
632         ;;
633
634     removeuser)
635         docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
636         docker exec $ARVBOX_CONTAINER sv restart controller
637         ;;
638
639     listusers)
640         listusers
641         ;;
642
643     *)
644         echo "Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html"
645         echo
646         echo "start|run <config> [tag]   start $ARVBOX_CONTAINER container"
647         echo "stop               stop arvbox container"
648         echo "restart <config>   stop, then run again"
649         echo "status             print some information about current arvbox"
650         echo "ip                 print arvbox docker container ip address"
651         echo "host               print arvbox published host"
652         echo "shell              enter shell as root"
653         echo "ashell             enter shell as 'arvbox'"
654         echo "psql               enter postgres console"
655         echo "open               open arvbox workbench in a web browser"
656         echo "root-cert          get copy of root certificate"
657         echo "update  <config>   stop, pull latest image, run"
658         echo "build   <config>   build arvbox Docker image"
659         echo "reboot  <config>   stop, build arvbox Docker image, run"
660         echo "rebuild <config>   build arvbox Docker image, no layer cache"
661         echo "checkpoint         create database backup"
662         echo "restore            restore checkpoint"
663         echo "hotreset           reset database and restart API without restarting container"
664         echo "reset              delete arvbox arvados data (be careful!)"
665         echo "destroy            delete all arvbox code and data (be careful!)"
666         echo "log <service>      tail log of specified service"
667         echo "ls <options>       list directories inside arvbox"
668         echo "cat <files>        get contents of files inside arvbox"
669         echo "pipe               run a bash script piped in from stdin"
670         echo "sv <start|stop|restart> <service> "
671         echo "                   change state of service inside arvbox"
672         echo "clone <from> <to>  clone dev arvbox"
673         echo "adduser <username> <email>"
674         echo "                   add a user login"
675         echo "removeuser <username>"
676         echo "                   remove user login"
677         echo "listusers          list user logins"
678         ;;
679 esac