Merge branch '13996-new-api-config' refs #13996
authorPeter Amstutz <pamstutz@veritasgenetics.com>
Thu, 18 Apr 2019 19:28:50 +0000 (15:28 -0400)
committerPeter Amstutz <pamstutz@veritasgenetics.com>
Thu, 18 Apr 2019 19:28:50 +0000 (15:28 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz@veritasgenetics.com>

14 files changed:
build/run-tests.sh
doc/_config.yml
doc/admin/controlling-container-reuse.html.textile.liquid [new file with mode: 0644]
doc/admin/logs-table-management.html.textile.liquid [new file with mode: 0644]
doc/api/methods/containers.html.textile.liquid
doc/install/arvbox.html.textile.liquid
doc/install/install-nodemanager.html.textile.liquid
lib/dispatchcloud/container/queue_test.go
services/api/app/models/container.rb
services/api/test/unit/container_test.rb
tools/arvbox/bin/arvbox
tools/arvbox/lib/arvbox/docker/Dockerfile.base
tools/arvbox/lib/arvbox/docker/createusers.sh
tools/arvbox/lib/arvbox/docker/devenv.sh

index a37a0f731e5a12c192c3a17094a9891ae920f9a6..dbf13940b2360997ab5885c8648b095a2b12ea33 100755 (executable)
@@ -394,7 +394,7 @@ start_services() {
         return 0
     fi
     . "$VENVDIR/bin/activate"
-    echo 'Starting API, keepproxy, keep-web, ws, arv-git-httpd, and nginx ssl proxy...'
+    echo 'Starting API, controller, keepproxy, keep-web, arv-git-httpd, ws, and nginx ssl proxy...'
     if [[ ! -d "$WORKSPACE/services/api/log" ]]; then
        mkdir -p "$WORKSPACE/services/api/log"
     fi
@@ -749,6 +749,7 @@ do_test_once() {
     title "test $1"
     timer_reset
 
+    result=
     if which deactivate >/dev/null; then deactivate; fi
     if ! . "$VENVDIR/bin/activate"
     then
@@ -821,6 +822,7 @@ do_install_once() {
     title "install $1"
     timer_reset
 
+    result=
     if which deactivate >/dev/null; then deactivate; fi
     if [[ "$1" != "env" ]] && ! . "$VENVDIR/bin/activate"; then
         result=1
index 57e5ec01bdf0e3a982f76df1c72d586812e8b7e8..c7f9bd19788448ef97af679ba917ed2cba530d27 100644 (file)
@@ -177,6 +177,8 @@ navbar:
     - Other:
       - admin/collection-versioning.html.textile.liquid
       - admin/federation.html.textile.liquid
+      - admin/controlling-container-reuse.html.textile.liquid
+      - admin/logs-table-management.html.textile.liquid
   installguide:
     - Overview:
       - install/index.html.textile.liquid
diff --git a/doc/admin/controlling-container-reuse.html.textile.liquid b/doc/admin/controlling-container-reuse.html.textile.liquid
new file mode 100644 (file)
index 0000000..76f57f3
--- /dev/null
@@ -0,0 +1,21 @@
+---
+layout: default
+navsection: admin
+title: Controlling container reuse
+...
+
+{% comment %}
+Copyright (C) The Arvados Authors. All rights reserved.
+
+SPDX-License-Identifier: CC-BY-SA-3.0
+{% endcomment %}
+
+This page describes how an admin can control container reuse using the @arv@ command. This can be utilized to avoid reusing a completed container without disabling reuse for the corresponding steps in affected workflows. For example, if a container exited successfully but produced bad output, it may not be feasible to update the workflow immediately. Meanwhile, changing the state of the container from @Complete@ to @Cancelled@ will prevent it from being used in subsequent workflows.
+
+If a container is in the @Complete@ state, the following @arv@ command will change its state to @Cancelled@, where @xxxxx-xxxxx-xxxxxxxxxxxxxxx@ is the @UUID@ of the container:
+
+<pre>arv container update -u xxxxx-xxxxx-xxxxxxxxxxxxxxx -c '{"state":"Cancelled"}'</pre>
+
+Use the following command to list all containers that exited with 0 and were then cancelled:
+
+<pre>arv container list --filters='[["state", "=", "Cancelled"], ["exit_code", "=", 0]]'</pre>See the "arv CLI tool overview":{{site.baseurl}}/sdk/cli/index.html for more details about using the @arv@ command.
diff --git a/doc/admin/logs-table-management.html.textile.liquid b/doc/admin/logs-table-management.html.textile.liquid
new file mode 100644 (file)
index 0000000..dedd960
--- /dev/null
@@ -0,0 +1,55 @@
+---
+layout: default
+navsection: admin
+title: "Logs table management"
+...
+
+{% comment %}
+Copyright (C) The Arvados Authors. All rights reserved.
+
+SPDX-License-Identifier: CC-BY-SA-3.0
+{% endcomment %}
+
+This page aims to provide insight about managing the ever growing API Server's logs table.
+
+h3. Logs table purpose & behavior
+
+This database table currently serves three purposes:
+* It's an audit log, permitting admins and users to look up the time and details of past changes to Arvados objects via @arvados.v1.logs.*@ endpoints.
+* It's a mechanism for passing cache-invalidation events, used by websocket servers, the Python SDK "events" library, and @arvados-cwl-runner@ to detect when an object has changed.
+* It's a staging area for stdout/stderr text coming from users' containers, permitting users to see what their containers are doing while they are still running (i.e., before those text files are written to Keep).
+
+As a result, this table grows indefinitely, even on sites where policy does not require an audit log; making backups, migrations, and upgrades unnecessarily slow and painful.
+
+h3. API Server configuration
+
+To solve the problem mentioned above, the API server offers the possibility to limit the amount of log information stored on the table:
+
+<pre>
+# Time to keep audit logs (a row in the log table added each time an
+# Arvados object is created, modified, or deleted) in the PostgreSQL
+# database. Currently, websocket event notifications rely on audit
+# logs, so this should not be set lower than 600 (10 minutes).
+max_audit_log_age: 1209600
+</pre>
+
+...and to prevent surprises and avoid bad database behavior (especially the first time the cleanup job runs on an existing cluster with a huge backlog) a maximum number of rows to delete in a single transaction.
+
+<pre>
+# Maximum number of log rows to delete in a single SQL transaction.
+#
+# If max_audit_log_delete_batch is 0, log entries will never be
+# deleted by Arvados. Cleanup can be done by an external process
+# without affecting any Arvados system processes, as long as very
+# recent (<5 minutes old) logs are not deleted.
+#
+# 100000 is a reasonable batch size for most sites.
+max_audit_log_delete_batch: 0
+</pre>
+
+This feature works when both settings are non-zero, periodically dispatching a background task that deletes all log rows older than @max_audit_log_age@.
+The events being cleaned up by this process don't include job/container stderr logs (they're handled by the existing @delete job/container logs@ rake tasks)
+
+h3. Additional consideration
+
+Depending on the local installation's audit requirements, the cluster admins should plan for an external backup procedure before enabling this feature, as this information is not replicated anywhere else.
index f0ce8e362f40ee0c533829b3c04adf7afa6ccf88..d59c66edc3cbf5f492dbb0c4befac668e209c980 100644 (file)
@@ -65,9 +65,11 @@ table(table table-bordered table-condensed).
 |Queued|Waiting for a dispatcher to lock it and try to run the container.|Locked, Cancelled|
 |Locked|A dispatcher has "taken" the container and is allocating resources for it. The container has not started yet.|Queued, Running, Cancelled|
 |Running|Resources have been allocated and the contained process has been started (or is about to start). Crunch-run _must_ set state to Running _before_ there is any possibility that user code will run in the container.|Complete, Cancelled|
-|Complete|Container was running, and the contained process/command has exited.|-|
+|Complete|Container was running, and the contained process/command has exited.|Cancelled|
 |Cancelled|The container did not run long enough to produce an exit code. This includes cases where the container didn't even start, cases where the container was interrupted/killed before it exited by itself (e.g., priority changed to 0), and cases where some problem prevented the system from capturing the contained process's exit status (exit code and output).|-|
 
+See "Controlling container reuse":{{site.baseurl}}/admin/controlling-container-reuse.html for details about changing state from @Complete@ to @Cancelled@
+
 h2(#mount_types). {% include 'mount_types' %}
 
 h2(#runtime_constraints). {% include 'container_runtime_constraints' %}
index 2d94d32ac5edbb844eaa9dca37c18d49aef7a689..64cc9c6f89edd737f72b77b66d47f0cb623d3fe7 100644 (file)
@@ -29,29 +29,32 @@ h2. Usage
 
 <pre>
 $ arvbox
-Arvados-in-a-box                      http://arvados.org
-
-start|run <config> [tag]  start arvbox container
-stop       stop arvbox container
-restart <config>  stop, then run again
-status     print some information about current arvbox
-ip         print arvbox docker container ip address
-host       print arvbox published host
-shell      enter arvbox shell
-open       open arvbox workbench in a web browser
-root-cert  get copy of root certificate
-update  <config> stop, pull latest image, run
-build   <config> build arvbox Docker image
-reboot  <config> stop, build arvbox Docker image, run
-rebuild <config> build arvbox Docker image, no layer cache
-reset      delete arvbox arvados data (be careful!)
-destroy    delete all arvbox code and data (be careful!)
-log <service> tail log of specified service
-ls <options>  list directories inside arvbox
-cat <files>   get contents of files inside arvbox
-pipe       run a bash script piped in from stdin
-sv <start|stop|restart> <service> change state of service inside arvbox
-clone <from> <to>   clone an arvbox
+Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html
+
+start|run <config> [tag]   start arvbox container
+stop               stop arvbox container
+restart <config>   stop, then run again
+status             print some information about current arvbox
+ip                 print arvbox docker container ip address
+host               print arvbox published host
+shell              enter shell as root
+ashell             enter shell as 'arvbox'
+psql               enter postgres console
+open               open arvbox workbench in a web browser
+root-cert          get copy of root certificate
+update  <config>   stop, pull latest image, run
+build   <config>   build arvbox Docker image
+reboot  <config>   stop, build arvbox Docker image, run
+rebuild <config>   build arvbox Docker image, no layer cache
+reset              delete arvbox arvados data (be careful!)
+destroy            delete all arvbox code and data (be careful!)
+log <service>      tail log of specified service
+ls <options>       list directories inside arvbox
+cat <files>        get contents of files inside arvbox
+pipe               run a bash script piped in from stdin
+sv <start|stop|restart> <service>
+                   change state of service inside arvbox
+clone <from> <to>  clone dev arvbox
 </pre>
 
 h2. Install root certificate
@@ -85,7 +88,11 @@ Demo configuration.  Boots a complete Arvados environment inside the container.
 
 h3. test
 
-Run the test suite.
+Starts postgres and initializes the API server, then runs the Arvados test suite.  Will pass command line arguments to test runner.  Supports test runner interactive mode.
+
+h3. devenv
+
+Starts a minimal container with no services and the host's $HOME bind mounted inside the container, then enters an interactive login shell.  Intended to make it convenient to use tools installed in arvbox that don't require services.
 
 h3. publicdev
 
index defec2589e82a3f32266f39e500c54401ee57683..770527da1fe4096af877a67363ee4d6e369a0a7d 100644 (file)
@@ -556,7 +556,7 @@ subscription_id = 00000000-0000-0000-0000-000000000000
 # https://azure.microsoft.com/en-us/documentation/articles/resource-group-authenticate-service-principal/
 # and updated for v2 of the Azure cli tool.
 #
-# az ad app create --display-name "Node Manager" --homepage "https://arvados.org" --identifier-uris "https://<Your_Application_Uri>" --password <Your_Password>
+# az ad app create --display-name "Node Manager" --homepage "https://arvados.org" --identifier-uris "https://<Your_Application_Uri>" --password <Your_Password> --end-date <Desired_credential_expiry_date>
 # az ad sp create "<Application_Id>"
 # az role assignment create --assignee "<Application_Id>" --role Owner --resource-group "<Your_Azure_Arvados_Resource_Group>"
 #
index 3c63fe51e6e89a116a40ea5c72917a5d4528ab41..daf7977ad50c5af0380ee44282bf81ff439e4d3b 100644 (file)
@@ -74,6 +74,7 @@ func (suite *IntegrationSuite) TestGetLockUnlockCancel(c *check.C) {
                        defer wg.Done()
                        err := cq.Unlock(uuid)
                        c.Check(err, check.NotNil)
+                       c.Check(err, check.ErrorMatches, ".*cannot unlock when Queued*.")
 
                        err = cq.Lock(uuid)
                        c.Check(err, check.IsNil)
@@ -101,9 +102,6 @@ func (suite *IntegrationSuite) TestGetLockUnlockCancel(c *check.C) {
                }()
        }
        wg.Wait()
-
-       err = cq.Cancel(arvadostest.CompletedContainerUUID)
-       c.Check(err, check.ErrorMatches, `.*State cannot change from Complete to Cancelled.*`)
 }
 
 func (suite *IntegrationSuite) TestCancelIfNoInstanceType(c *check.C) {
index 95691687e6d77c2d51c1287136ad3240869e81de..45cd13bbcddbc762f3d828a30454505082fce528 100644 (file)
@@ -89,7 +89,8 @@ class Container < ArvadosModel
     nil => [Queued],
     Queued => [Locked, Cancelled],
     Locked => [Queued, Running, Cancelled],
-    Running => [Complete, Cancelled]
+    Running => [Complete, Cancelled],
+    Complete => [Cancelled]
   }
 
   def self.limit_index_columns_read
@@ -497,7 +498,7 @@ class Container < ArvadosModel
       return false
     end
 
-    if self.state == Running &&
+    if self.state_was == Running &&
        !current_api_client_authorization.nil? &&
        (current_api_client_authorization.uuid == self.auth_uuid ||
         current_api_client_authorization.token == self.runtime_token)
@@ -505,6 +506,8 @@ class Container < ArvadosModel
       # change priority or log.
       permitted.push *final_attrs
       permitted = permitted - [:log, :priority]
+    elsif !current_user.andand.is_admin
+      raise PermissionDeniedError
     elsif self.locked_by_uuid && self.locked_by_uuid != current_api_client_authorization.andand.uuid
       # When locked, progress fields cannot be updated by the wrong
       # dispatcher, even though it has admin privileges.
index 11429affab1927fa8b7cec798f7a0510452a7856..88fd5feb6ad27c3c55dd5531c0a2566422239f41 100644 (file)
@@ -184,7 +184,7 @@ class ContainerTest < ActiveSupport::TestCase
     assert_equal c1.runtime_status, {}
 
     assert_equal Container::Queued, c1.state
-    assert_raises ActiveRecord::RecordInvalid do
+    assert_raises ArvadosModel::PermissionDeniedError do
       c1.update_attributes! runtime_status: {'error' => 'Oops!'}
     end
 
@@ -777,6 +777,51 @@ class ContainerTest < ActiveSupport::TestCase
     end
   end
 
+  [
+    [Container::Queued, {state: Container::Locked}],
+    [Container::Queued, {state: Container::Running}],
+    [Container::Queued, {state: Container::Complete}],
+    [Container::Queued, {state: Container::Cancelled}],
+    [Container::Queued, {priority: 123456789}],
+    [Container::Queued, {runtime_status: {'error' => 'oops'}}],
+    [Container::Queued, {cwd: '/'}],
+    [Container::Locked, {state: Container::Running}],
+    [Container::Locked, {state: Container::Queued}],
+    [Container::Locked, {priority: 123456789}],
+    [Container::Locked, {runtime_status: {'error' => 'oops'}}],
+    [Container::Locked, {cwd: '/'}],
+    [Container::Running, {state: Container::Complete}],
+    [Container::Running, {state: Container::Cancelled}],
+    [Container::Running, {priority: 123456789}],
+    [Container::Running, {runtime_status: {'error' => 'oops'}}],
+    [Container::Running, {cwd: '/'}],
+    [Container::Complete, {state: Container::Cancelled}],
+    [Container::Complete, {priority: 123456789}],
+    [Container::Complete, {runtime_status: {'error' => 'oops'}}],
+    [Container::Complete, {cwd: '/'}],
+    [Container::Cancelled, {cwd: '/'}],
+  ].each do |start_state, updates|
+    test "Container update #{updates.inspect} when #{start_state} forbidden for non-admin" do
+      set_user_from_auth :active
+      c, _ = minimal_new
+      if start_state != Container::Queued
+        set_user_from_auth :dispatch1
+        c.lock
+        if start_state != Container::Locked
+          c.update_attributes! state: Container::Running
+          if start_state != Container::Running
+            c.update_attributes! state: start_state
+          end
+        end
+      end
+      assert_equal c.state, start_state
+      set_user_from_auth :active
+      assert_raises(ArvadosModel::PermissionDeniedError) do
+        c.update_attributes! updates
+      end
+    end
+  end
+
   test "Container only set exit code on complete" do
     set_user_from_auth :active
     c, _ = minimal_new
@@ -899,7 +944,9 @@ class ContainerTest < ActiveSupport::TestCase
     c.update_attributes! state: Container::Running
 
     set_user_from_auth :running_to_be_deleted_container_auth
-    refute c.update_attributes(output: collections(:foo_file).portable_data_hash)
+    assert_raises(ArvadosModel::PermissionDeniedError) do
+      c.update_attributes(output: collections(:foo_file).portable_data_hash)
+    end
   end
 
   test "can set trashed output on running container" do
index 74933718c76ac8e0e499f62bf3ede740308ce073..878119634bbaf23fca3183ab37651e3274147e3e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # Copyright (C) The Arvados Authors. All rights reserved.
 #
 # SPDX-License-Identifier: AGPL-3.0
@@ -64,7 +64,7 @@ GOSTUFF="$ARVBOX_DATA/gopath"
 RLIBS="$ARVBOX_DATA/Rlibs"
 
 getip() {
-    docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
+    docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
 }
 
 gethost() {
@@ -103,8 +103,11 @@ wait_for_arvbox() {
     docker logs -f $ARVBOX_CONTAINER > $FF &
     LOGPID=$!
     while read line ; do
-        if echo $line | grep "ok: down: ready:" >/dev/null ; then
+        if [[ $line =~ "ok: down: ready:" ]] ; then
             kill $LOGPID
+           set +e
+           wait $LOGPID 2>/dev/null
+           set -e
        else
            echo $line
         fi
@@ -132,9 +135,14 @@ docker_run_dev() {
            "--volume=$NPMCACHE:/var/lib/npm:rw" \
            "--volume=$GOSTUFF:/var/lib/gopath:rw" \
            "--volume=$RLIBS:/var/lib/Rlibs:rw" \
+          --label "org.arvados.arvbox_config=$CONFIG" \
           "$@"
 }
 
+running_config() {
+    docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
+}
+
 run() {
     CONFIG=$1
     TAG=$2
@@ -144,18 +152,22 @@ run() {
     need_setup=1
 
     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
-        if test "$CONFIG" = test ; then
+       if [[ $(running_config) != "$CONFIG" ]] ; then
+           echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
+           return 1
+       fi
+        if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
             need_setup=0
         else
             echo "Container $ARVBOX_CONTAINER is already running"
-            exit 0
+            return 0
         fi
     fi
 
     if test $need_setup = 1 ; then
         if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
             echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
-            exit 1
+            return 1
         fi
     fi
 
@@ -165,11 +177,14 @@ run() {
            TAG=":$TAG"
             shift
         else
+           if [[ $TAG = '-' ]] ; then
+               shift
+           fi
             unset TAG
         fi
     fi
 
-    if echo "$CONFIG" | grep '^public' ; then
+    if [[ "$CONFIG" =~ ^public ]] ; then
         if test -n "$ARVBOX_PUBLISH_IP" ; then
             localip=$ARVBOX_PUBLISH_IP
         else
@@ -195,10 +210,10 @@ run() {
         PUBLIC=""
     fi
 
-    if echo "$CONFIG" | grep 'demo$' ; then
+    if [[ "$CONFIG" =~ demo$ ]] ; then
         if test -d "$ARVBOX_DATA" ; then
             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
-            echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
+            echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
             exit 1
         fi
 
@@ -211,6 +226,7 @@ run() {
                --name=$ARVBOX_CONTAINER \
                --privileged \
                --volumes-from $ARVBOX_CONTAINER-data \
+              --label "org.arvados.arvbox_config=$CONFIG" \
                $PUBLIC \
                arvados/arvbox-demo$TAG
         updateconf
@@ -218,7 +234,6 @@ run() {
     else
         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
 
-
         if ! test -d "$ARVADOS_ROOT" ; then
             git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
         fi
@@ -232,7 +247,7 @@ run() {
             git clone https://github.com/curoverse/arvados-workbench2.git "$WORKBENCH2_ROOT"
         fi
 
-        if test "$CONFIG" = test ; then
+        if [[ "$CONFIG" = test ]] ; then
 
             mkdir -p $VAR_DATA/test
 
@@ -261,14 +276,36 @@ run() {
             fi
 
             docker exec -ti \
+                   -e LINES=$(tput lines) \
+                   -e COLUMNS=$(tput cols) \
+                   -e TERM=$TERM \
+                   -e WORKSPACE=/usr/src/arvados \
+                   -e GEM_HOME=/var/lib/gems \
                    $ARVBOX_CONTAINER \
                    /usr/local/lib/arvbox/runsu.sh \
                    /usr/src/arvados/build/run-tests.sh \
                    --temp /var/lib/arvados/test \
-                   WORKSPACE=/usr/src/arvados \
-                   GEM_HOME=/var/lib/gems \
                    "$@"
-        elif echo "$CONFIG" | grep 'dev$' ; then
+        elif [[ "$CONFIG" = devenv ]] ; then
+           if [[ $need_setup = 1 ]] ; then
+               docker_run_dev \
+                    --detach \
+                   --name=${ARVBOX_CONTAINER} \
+                   "--env=SVDIR=/etc/devenv-service" \
+                   "--volume=$HOME:$HOME:rw" \
+                   --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
+                   arvados/arvbox-dev$TAG
+           fi
+           exec docker exec --interactive --tty \
+                -e LINES=$(tput lines) \
+                -e COLUMNS=$(tput cols) \
+                -e TERM=$TERM \
+                -e "ARVBOX_HOME=$HOME" \
+                -e "DISPLAY=$DISPLAY" \
+                --workdir=$PWD \
+                ${ARVBOX_CONTAINER} \
+                /usr/local/lib/arvbox/devenv.sh "$@"
+        elif [[ "$CONFIG" =~ dev$ ]] ; then
             docker_run_dev \
                    --detach \
                    --name=$ARVBOX_CONTAINER \
@@ -344,11 +381,11 @@ build() {
 
 check() {
     case "$1" in
-        localdemo|publicdemo|dev|publicdev|test)
+        localdemo|publicdemo|dev|publicdev|test|devenv)
             true
             ;;
         *)
-            echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
+            echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
             exit 1
         ;;
     esac
@@ -375,7 +412,7 @@ case "$subcmd" in
         ;;
 
     sh*)
-        exec docker exec -ti \
+        exec docker exec --interactive --tty \
               -e LINES=$(tput lines) \
               -e COLUMNS=$(tput cols) \
               -e TERM=$TERM \
@@ -383,6 +420,17 @@ case "$subcmd" in
               $ARVBOX_CONTAINER /bin/bash
         ;;
 
+    ash*)
+        exec docker exec --interactive --tty \
+              -e LINES=$(tput lines) \
+              -e COLUMNS=$(tput cols) \
+              -e TERM=$TERM \
+              -e GEM_HOME=/var/lib/gems \
+              -u arvbox \
+              -w /usr/src/arvados \
+              $ARVBOX_CONTAINER /bin/bash --login
+        ;;
+
     pipe)
         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash -
         ;;
@@ -524,63 +572,36 @@ case "$subcmd" in
        echo "Certificate copied to $CERT"
        ;;
 
-    devenv)
-       set -x
-       if docker ps -a --filter "status=exited" | grep -E "${ARVBOX_CONTAINER}-devenv$" -q ; then
-           docker start ${ARVBOX_CONTAINER}-devenv
-       elif ! (docker ps -a --filter "status=running" | grep -E "${ARVBOX_CONTAINER}-devenv$" -q) ; then
-           docker_run_dev \
-                 --detach \
-                --name=${ARVBOX_CONTAINER}-devenv \
-                "--env=SVDIR=/etc/devenv-service" \
-                "--volume=$HOME:$HOME:rw" \
-                --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
-                arvados/arvbox-dev$TAG
-       fi
-
-       exec docker exec --interactive --tty \
-            -e LINES=$(tput lines) \
-            -e COLUMNS=$(tput cols) \
-            -e TERM=$TERM \
-            -e "ARVBOX_HOME=$HOME" \
-            -e "DISPLAY=$DISPLAY" \
-            --workdir=$PWD \
-            ${ARVBOX_CONTAINER}-devenv \
-            /usr/local/lib/arvbox/devenv.sh "$@"
-       ;;
-
-    devenv-stop)
-       docker stop ${ARVBOX_CONTAINER}-devenv
-       ;;
-
-    devenv-reset)
-       docker stop ${ARVBOX_CONTAINER}-devenv
-       docker rm ${ARVBOX_CONTAINER}-devenv
+    psql)
+       exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados'
        ;;
 
     *)
-        echo "Arvados-in-a-box                      http://arvados.org"
+        echo "Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html"
         echo
-        echo "start|run <config> [tag]  start $ARVBOX_CONTAINER container"
-        echo "stop       stop arvbox container"
-        echo "restart <config>  stop, then run again"
-        echo "status     print some information about current arvbox"
-        echo "ip         print arvbox docker container ip address"
-        echo "host       print arvbox published host"
-        echo "shell      enter arvbox shell"
-        echo "open       open arvbox workbench in a web browser"
-        echo "root-cert  get copy of root certificate"
-        echo "update  <config> stop, pull latest image, run"
-        echo "build   <config> build arvbox Docker image"
-        echo "reboot  <config> stop, build arvbox Docker image, run"
-        echo "rebuild <config> build arvbox Docker image, no layer cache"
-        echo "reset      delete arvbox arvados data (be careful!)"
-        echo "destroy    delete all arvbox code and data (be careful!)"
-        echo "log <service> tail log of specified service"
-        echo "ls <options>  list directories inside arvbox"
-        echo "cat <files>   get contents of files inside arvbox"
-        echo "pipe       run a bash script piped in from stdin"
-        echo "sv <start|stop|restart> <service> change state of service inside arvbox"
-        echo "clone <from> <to>   clone an arvbox"
+        echo "start|run <config> [tag]   start $ARVBOX_CONTAINER container"
+        echo "stop               stop arvbox container"
+        echo "restart <config>   stop, then run again"
+        echo "status             print some information about current arvbox"
+        echo "ip                 print arvbox docker container ip address"
+        echo "host               print arvbox published host"
+        echo "shell              enter shell as root"
+        echo "ashell             enter shell as 'arvbox'"
+        echo "psql               enter postgres console"
+        echo "open               open arvbox workbench in a web browser"
+        echo "root-cert          get copy of root certificate"
+        echo "update  <config>   stop, pull latest image, run"
+        echo "build   <config>   build arvbox Docker image"
+        echo "reboot  <config>   stop, build arvbox Docker image, run"
+        echo "rebuild <config>   build arvbox Docker image, no layer cache"
+        echo "reset              delete arvbox arvados data (be careful!)"
+        echo "destroy            delete all arvbox code and data (be careful!)"
+        echo "log <service>      tail log of specified service"
+        echo "ls <options>       list directories inside arvbox"
+        echo "cat <files>        get contents of files inside arvbox"
+        echo "pipe               run a bash script piped in from stdin"
+        echo "sv <start|stop|restart> <service> "
+       echo "                   change state of service inside arvbox"
+        echo "clone <from> <to>  clone dev arvbox"
         ;;
 esac
index 741bd33c4998cab201e6e9e60f0c58a69a3414fd..65171de3d25e894c6fbfc86b862959b1cc22a606 100644 (file)
@@ -85,6 +85,14 @@ ENV NODEVERSION v8.15.1
 RUN curl -L -f https://nodejs.org/dist/${NODEVERSION}/node-${NODEVERSION}-linux-x64.tar.xz | tar -C /usr/local -xJf - && \
     ln -s ../node-${NODEVERSION}-linux-x64/bin/node ../node-${NODEVERSION}-linux-x64/bin/npm /usr/local/bin
 
+ENV GRADLEVERSION 5.3.1
+
+RUN cd /tmp && \
+    curl -L -O https://services.gradle.org/distributions/gradle-${GRADLEVERSION}-bin.zip && \
+    unzip gradle-${GRADLEVERSION}-bin.zip -d /usr/local && \
+    ln -s ../gradle-${GRADLEVERSION}/bin/gradle /usr/local/bin && \
+    rm gradle-${GRADLEVERSION}-bin.zip
+
 # Set UTF-8 locale
 RUN echo en_US.UTF-8 UTF-8 > /etc/locale.gen && locale-gen
 ENV LANG en_US.UTF-8
index e9721fd55d87c1e5a597f3a56b632310321bb8d1..c6270457d5af8f1e9b8bab9ac2de004014744d55 100755 (executable)
@@ -28,10 +28,12 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker crunch
 
-    chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems \
-          /var/lib/passenger /var/lib/postgresql \
-          /var/lib/nginx /var/log/nginx /etc/ssl/private \
-          /var/lib/gopath /var/lib/pip /var/lib/npm
+    if [[ "$1" != --no-chown ]] ; then
+       chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems \
+              /var/lib/passenger /var/lib/postgresql \
+              /var/lib/nginx /var/log/nginx /etc/ssl/private \
+              /var/lib/gopath /var/lib/pip /var/lib/npm
+    fi
 
     mkdir -p /var/lib/gems/ruby
     chown arvbox:arvbox -R /var/lib/gems/ruby
index 9ab3ac4c38cfd530e3a050c2040b73744c95f915..4df5463f1f06101b5dd82ac61281df805fa15721 100755 (executable)
@@ -3,7 +3,7 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
+flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh --no-chown
 
 if [[ -n "$*" ]] ; then
     exec su --preserve-environment arvbox -c "$*"