Merge branch '16850-s3-keycount'
authorTom Clegg <tom@tomclegg.ca>
Wed, 23 Sep 2020 14:33:52 +0000 (10:33 -0400)
committerTom Clegg <tom@tomclegg.ca>
Wed, 23 Sep 2020 14:33:52 +0000 (10:33 -0400)
fixes #16850

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

47 files changed:
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/controllers/projects_controller.rb
apps/workbench/app/views/work_units/_show_component.html.erb
build/run-tests.sh
doc/_includes/_install_ruby_and_bundler.liquid
doc/admin/upgrading.html.textile.liquid
doc/api/methods/links.html.textile.liquid
doc/user/tutorials/wgs-tutorial.html.textile.liquid
lib/cloud/cloudtest/tester.go
lib/cloud/ec2/ec2.go
lib/controller/federation/conn.go
lib/controller/localdb/login_oidc.go
lib/crunchrun/crunchrun_test.go
lib/dispatchcloud/dispatcher.go
lib/dispatchcloud/dispatcher_test.go
lib/dispatchcloud/sshexecutor/executor.go [moved from lib/dispatchcloud/ssh_executor/executor.go with 98% similarity]
lib/dispatchcloud/sshexecutor/executor_test.go [moved from lib/dispatchcloud/ssh_executor/executor_test.go with 99% similarity]
lib/dispatchcloud/worker/pool.go
lib/dispatchcloud/worker/worker.go
lib/dispatchcloud/worker/worker_test.go
sdk/cwl/arvados_cwl/__init__.py
sdk/cwl/arvados_cwl/arvcontainer.py
sdk/cwl/arvados_cwl/executor.py
sdk/cwl/tests/test_submit.py
sdk/dev-jobs.dockerfile
sdk/go/auth/salt.go
sdk/python/arvados/commands/run.py
services/api/app/controllers/arvados/v1/collections_controller.rb
services/api/app/models/arvados_model.rb
services/api/app/models/database_seeds.rb
services/api/db/migrate/20200914203202_public_favorites_project.rb [new file with mode: 0644]
services/api/db/structure.sql
services/api/lib/current_api_client.rb
services/api/test/fixtures/groups.yml
services/api/test/fixtures/logs.yml
services/api/test/functional/arvados/v1/collections_controller_test.rb
services/api/test/unit/log_test.rb
services/api/test/unit/permission_test.rb
services/crunch-dispatch-slurm/squeue.go
services/keepstore/pull_worker.go
services/keepstore/s3aws_volume.go
tools/arvbox/bin/arvbox
tools/arvbox/lib/arvbox/docker/Dockerfile.base
tools/arvbox/lib/arvbox/docker/common.sh
tools/arvbox/lib/arvbox/docker/createusers.sh
tools/arvbox/lib/arvbox/docker/service/postgres/run-service
tools/arvbox/lib/arvbox/docker/service/sdk/run-service

index 77ec68bdb06eeb5d9bf124206528e62c491c547e..cf4bfa8c5400b56543e6cfe7174091b489095b74 100644 (file)
@@ -927,7 +927,7 @@ class ApplicationController < ActionController::Base
   helper_method :my_starred_projects
   def my_starred_projects user
     return if defined?(@starred_projects) && @starred_projects
-    links = Link.filter([['owner_uuid', 'in', ["#{Rails.configuration.ClusterID}-j7d0g-fffffffffffffff", user.uuid]],
+    links = Link.filter([['owner_uuid', 'in', ["#{Rails.configuration.ClusterID}-j7d0g-publicfavorites", user.uuid]],
                          ['link_class', '=', 'star'],
                          ['head_uuid', 'is_a', 'arvados#group']]).with_count("none").select(%w(head_uuid))
     uuids = links.collect { |x| x.head_uuid }
index 66dc3dcea2d418b2bbd79e6907d37fac4cbc0fbb..e448e1b4530d78b1cfad3ec124ccc26fcd6e3583 100644 (file)
@@ -133,7 +133,7 @@ class ProjectsController < ApplicationController
   def remove_items
     @removed_uuids = []
     params[:item_uuids].collect { |uuid| ArvadosBase.find uuid }.each do |item|
-      if item.class == Collection or item.class == Group
+      if item.class == Collection or item.class == Group or item.class == Workflow or item.class == ContainerRequest
         # Use delete API on collections and projects/groups
         item.destroy
         @removed_uuids << item.uuid
index cac263d1ec56fd468ba050a94f24fc0fd0d8514d..4cce090a2235c7f7402971634360a2c9b4bde46d 100644 (file)
@@ -45,13 +45,13 @@ SPDX-License-Identifier: AGPL-3.0 %>
       <div class="panel-heading">
         <h4 class="panel-title">
           <a class="component-detail-panel" data-toggle="collapse" href="#errorDetail">
-            <span class="caret"></span> Error: <%= sanitize(wu.runtime_status[:error]) %>
+            <span class="caret"></span> Error: <%= h(wu.runtime_status[:error]) %>
           </a>
         </h4>
       </div>
       <div id="errorDetail" class="panel-body panel-collapse collapse">
         <% if wu.runtime_status[:errorDetail] %>
-          <pre><%= sanitize(wu.runtime_status[:errorDetail]) %></pre>
+          <pre><%= h(wu.runtime_status[:errorDetail]) %></pre>
         <% else %>
           No detailed information available.
         <% end %>
@@ -69,13 +69,13 @@ SPDX-License-Identifier: AGPL-3.0 %>
       <div class="panel-heading">
         <h4 class="panel-title">
           <a class="component-detail-panel" data-toggle="collapse" href="#warningDetail">
-            <span class="caret"></span> Warning: <%= sanitize(wu.runtime_status[:warning]) %>
+            <span class="caret"></span> Warning: <%= h(wu.runtime_status[:warning]) %>
           </a>
         </h4>
       </div>
       <div id="warningDetail" class="panel-body panel-collapse collapse">
         <% if wu.runtime_status[:warningDetail] %>
-          <pre><%= sanitize(wu.runtime_status[:warningDetail]) %></pre>
+          <pre><%= h(wu.runtime_status[:warningDetail]) %></pre>
         <% else %>
           No detailed information available.
         <% end %>
index 32d4a75d2b63bdd04811f78718a60a65de1c74c8..595f721080e99bfc689741a0144770f39236d2cc 100755 (executable)
@@ -88,7 +88,7 @@ lib/cloud/cloudtest
 lib/dispatchcloud
 lib/dispatchcloud/container
 lib/dispatchcloud/scheduler
-lib/dispatchcloud/ssh_executor
+lib/dispatchcloud/sshexecutor
 lib/dispatchcloud/worker
 lib/mount
 lib/pam
@@ -709,7 +709,7 @@ do_test() {
             stop_services
             check_arvados_config "$1"
             ;;
-        gofmt | doc | lib/cli | lib/cloud/azure | lib/cloud/ec2 | lib/cloud/cloudtest | lib/cmd | lib/dispatchcloud/ssh_executor | lib/dispatchcloud/worker)
+        gofmt | doc | lib/cli | lib/cloud/azure | lib/cloud/ec2 | lib/cloud/cloudtest | lib/cmd | lib/dispatchcloud/sshexecutor | lib/dispatchcloud/worker)
             check_arvados_config "$1"
             # don't care whether services are running
             ;;
index d14e555f89bcdbe35a93ecc7e859a98cea60587c..d1d33cbbe3e567a610768cbbe790560b2e953d7d 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) The Arvados Authors. All rights reserved.
 SPDX-License-Identifier: CC-BY-SA-3.0
 {% endcomment %}
 
-Minimum of Ruby 2.3 is required.  Ruby 2.5 is recommended.
+Ruby 2.5 or newer is required.
 
 * "Option 1: Install from packages":#packages
 * "Option 2: Install with RVM":#rvm
@@ -13,16 +13,18 @@ Minimum of Ruby 2.3 is required.  Ruby 2.5 is recommended.
 h2(#packages). Option 1: Install from packages
 
 {% include 'notebox_begin' %}
-Future versions of Arvados may require a newer version of Ruby than is packaged with your OS.  Using OS packages simplifies initial install, but may complicate upgrades that rely on a newer Ruby.  If this is a concern, we recommend using "RVM.":#rvm
+Future versions of Arvados may require a newer version of Ruby than is packaged with your OS.  Using OS packages simplifies initial install, but may complicate upgrades that rely on a newer Ruby.  If this is a concern, we recommend using "RVM":#rvm.
 {% include 'notebox_end' %}
 
 h3. Centos 7
 
-The Ruby version shipped with Centos 7 is too old.  Use "RVM.":#rvm
+The Ruby version shipped with Centos 7 is too old.  Use "RVM":#rvm to install Ruby 2.5 or later.
 
 h3. Debian and Ubuntu
 
-Debian 9 (stretch) and Ubuntu 16.04 (xenial) ship Ruby 2.3, which is sufficient to run Arvados.  Later releases have newer versions of Ruby that can also run Arvados.
+Debian 9 (stretch) and Ubuntu 16.04 (xenial) ship Ruby 2.3, which is not supported by Arvados.  Use "RVM":#rvm to install Ruby 2.5 or later.
+
+Debian 10 (buster) and Ubuntu 18.04 (bionic) and later ship with Ruby 2.5, which is supported by Arvados.
 
 <notextile>
 <pre><code># <span class="userinput">apt-get --no-install-recommends install ruby ruby-dev bundler</span></code></pre>
index 061b68fa5d27b766e7d45bd0c08750fed210f5dd..1eb2468c321c058298acc7316b23ca23d243f2f8 100644 (file)
@@ -16,6 +16,7 @@ h2. General process
 
 # Consult upgrade notes below to see if any manual configuration updates are necessary.
 # Wait for the cluster to be idle and stop Arvados services.
+# Make a backup of your database, as a precaution.
 # Install new packages using @apt-get upgrade@ or @yum upgrade@.
 # Wait for package installation scripts as they perform any necessary data migrations.
 # Restart Arvados services.
@@ -34,10 +35,14 @@ TODO: extract this information based on git commit messages and generate changel
 <div class="releasenotes">
 </notextile>
 
-h2(#master). development master (as of 2020-06-17)
+h2(#master). development master (as of 2020-09-22)
 
 "Upgrading from 2.0.0":#v2_0_0
 
+h3. Minimum supported Ruby version is now 2.5
+
+The minimum supported Ruby version is now 2.5.  If you are running Arvados on Debian 9 or Ubuntu 16.04, you may need to switch to using RVM or upgrade your OS.  See "Install Ruby and Bundler":../install/ruby.html for more information.
+
 h3. Removing libpam-arvados, replaced with libpam-arvados-go
 
 The Python-based PAM package has been replaced with a version written in Go. See "using PAM for authentication":{{site.baseurl}}/install/setup-login.html#pam for details.
@@ -87,6 +92,10 @@ for uuid in $(arv link list --filters '[["link_class", "=", "permission"], ["tai
 done
 </pre>
 
+h4. "Public favorites" moved to their own project
+
+As a side effect of new permission system constraints, "star" links (indicating shortcuts in Workbench) that were previously owned by "All users" (which is now a "role" and cannot own things) will be migrated to a new system project called "Public favorites" which is readable by the "Anonymous users" role.
+
 h2(#v2_0_0). v2.0.0 (2020-02-07)
 
 "Upgrading from 1.4":#v1_4_1
index 2e5de1856dc5f1dd4624c65d1b07369e6d769d24..c71105c74569a88b26c594b32482a696e1ab0165 100644 (file)
@@ -43,28 +43,30 @@ h3. star
 
 A **star** link is a shortcut to a project that is displayed in the user interface (Workbench) as "favorites".  Users can mark their own favorites (implemented by creating or deleting **star** links).
 
-An admin can also create **star** links owned by the "All Users" group, these will be displayed to all users that have permission to read the project that has been favorited.
+An admin can also create **star** links owned by the "Public favorites" project.  These are favorites will be displayed to all users that have permission to read the project that has been favorited.
 
 The schema for a star link is:
 
 table(table table-bordered table-condensed).
 |_. Field|_. Value|_. Description|
-|owner_uuid|user or group uuid|Either the user that owns the favorite, or the "All Users" group for public favorites.|
+|owner_uuid|user or group uuid|Either the user that owns the favorite, or the "Public favorites" group.|
+|tail_uuid|user or group uuid|Should be the same as owner_uuid|
 |head_uuid|project uuid|The project being favorited|
 |link_class|string of value "star"|Indicates this represents a link to a user favorite|
 
-h4. Creating a favorite
+h4. Creating a public favorite
 
-@owner_uuid@ is either an individual user, or the "All Users" group.  The @head_uuid@ is the project being favorited.
+@owner_uuid@ is either an individual user, or the "Public favorites" group.  The @head_uuid@ is the project being favorited.
 
 <pre>
-$ arv link create --link '{
-    "owner_uuid": "zzzzz-j7d0g-fffffffffffffff",
-    "head_uuid":  "zzzzz-j7d0g-theprojectuuid",
-    "link_class": "star"}'
+$ linkuuid=$(arv --format=uuid link create --link '{
+    "link_class": "star",
+    "owner_uuid": "zzzzz-j7d0g-publicfavorites",
+    "tail_uuid": "zzzzz-j7d0g-publicfavorites",
+    "head_uuid":  "zzzzz-j7d0g-theprojectuuid"}')
 </pre>
 
-h4. Deleting a favorite
+h4. Removing a favorite
 
 <pre>
 $ arv link delete --uuid zzzzz-o0j2j-thestarlinkuuid
@@ -77,7 +79,7 @@ To list all 'star' links that will be displayed for a user:
 <pre>
 $ arv link list --filters '[
   ["link_class", "=", "star"],
-  ["owner_uuid", "in", ["zzzzz-j7d0g-fffffffffffffff", "zzzzz-tpzed-currentuseruuid"]]]'
+  ["tail_uuid", "in", ["zzzzz-j7d0g-publicfavorites", "zzzzz-tpzed-currentuseruuid"]]]'
 </pre>
 
 h3. tag
index 2d60f7a3aba34572fda5a445a74a6793687d1a8a..cd4d1cc715e0f8dda3fdbe362ad096173c516f4e 100644 (file)
@@ -125,9 +125,11 @@ h3. 4b. Optional: Setting up to Run a Workflow Using Command Line and an Arvados
 
 Arvados provides a virtual machine which has all the necessary client-side libraries installed to submit to your Arvados cluster using the command line.  Webshell gives you access to an Arvados Virtual Machine (VM) from your browser with no additional setup.  You can access webshell through the Arvados Workbench.  It is the easiest way to try out submitting a workflow to Arvados via the command line.
 
-To get access to webshell on the Arvados Playground, you need to contact a Curii Arvados Playground Administrator to get access to an Arvados shell node by emailing "info@curii.com.":mailto:info@curii.com
+New users are playground are automatically given access to a shell account.
 
-Once you receive an email letting you know your access has been set up and you should be able to access the shell virtual machine.  You can follow the instructions here to access the machine using the browser (also known as using webshell):
+_Note_: the shell accounts are created on an interval and it may take up to two minutes from your initial log in before the shell account is created.
+
+You can follow the instructions here to access the machine using the browser (also known as using webshell):
 * "Accessing an Arvados VM with Webshell":{{ site.baseurl }}/user/getting_started/vm-login-with-webshell.html
 
 Arvados also allows you to ssh into the shell machine and other hosted VMs instead of using the webshell capabilities. However this tutorial does not cover that option in-depth.  If you like to explore it on your own, you can allow the instructions in the documentation here:
index 5288b5c76cd2b3f0d3cd87c78f76f6706889e8f7..087aceffad73cc8a99857aca9b87f4f9bd1f65b2 100644 (file)
@@ -12,7 +12,7 @@ import (
        "time"
 
        "git.arvados.org/arvados.git/lib/cloud"
-       "git.arvados.org/arvados.git/lib/dispatchcloud/ssh_executor"
+       "git.arvados.org/arvados.git/lib/dispatchcloud/sshexecutor"
        "git.arvados.org/arvados.git/lib/dispatchcloud/worker"
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "github.com/sirupsen/logrus"
@@ -48,7 +48,7 @@ type tester struct {
        is              cloud.InstanceSet
        testInstance    *worker.TagVerifier
        secret          string
-       executor        *ssh_executor.Executor
+       executor        *sshexecutor.Executor
        showedLoginInfo bool
 
        failed bool
@@ -308,7 +308,7 @@ func (t *tester) waitForBoot(deadline time.Time) bool {
 // current address.
 func (t *tester) updateExecutor() {
        if t.executor == nil {
-               t.executor = ssh_executor.New(t.testInstance)
+               t.executor = sshexecutor.New(t.testInstance)
                t.executor.SetTargetPort(t.SSHPort)
                t.executor.SetSigners(t.SSHKey)
        } else {
index c329c1f88a4c0b8a2b3c3b49142f3ce60d17e871..29062c491e3467dc31e5782f754d42023217fb2d 100644 (file)
@@ -308,9 +308,8 @@ func (inst *ec2Instance) Destroy() error {
 func (inst *ec2Instance) Address() string {
        if inst.instance.PrivateIpAddress != nil {
                return *inst.instance.PrivateIpAddress
-       } else {
-               return ""
        }
+       return ""
 }
 
 func (inst *ec2Instance) RemoteUser() string {
index 361c9613dd4e2dec8db1ba58b66a6b5c5fd34817..61cac9bbabcd1d5128417fe0ab91041981afd207 100644 (file)
@@ -203,9 +203,8 @@ func (conn *Conn) Login(ctx context.Context, options arvados.LoginOptions) (arva
                return arvados.LoginResponse{
                        RedirectLocation: target.String(),
                }, nil
-       } else {
-               return conn.local.Login(ctx, options)
        }
+       return conn.local.Login(ctx, options)
 }
 
 func (conn *Conn) Logout(ctx context.Context, options arvados.LogoutOptions) (arvados.LogoutResponse, error) {
index 9274d75d7c9fdc1973cbcad621b306599e571893..e0b01f13ebee8c4f01084d0dc4c8dca76804e696 100644 (file)
@@ -106,34 +106,33 @@ func (ctrl *oidcLoginController) Login(ctx context.Context, opts arvados.LoginOp
                                // one Google account.
                                oauth2.SetAuthURLParam("prompt", "select_account")),
                }, nil
-       } else {
-               // Callback after OIDC sign-in.
-               state := ctrl.parseOAuth2State(opts.State)
-               if !state.verify([]byte(ctrl.Cluster.SystemRootToken)) {
-                       return loginError(errors.New("invalid OAuth2 state"))
-               }
-               oauth2Token, err := ctrl.oauth2conf.Exchange(ctx, opts.Code)
-               if err != nil {
-                       return loginError(fmt.Errorf("error in OAuth2 exchange: %s", err))
-               }
-               rawIDToken, ok := oauth2Token.Extra("id_token").(string)
-               if !ok {
-                       return loginError(errors.New("error in OAuth2 exchange: no ID token in OAuth2 token"))
-               }
-               idToken, err := ctrl.verifier.Verify(ctx, rawIDToken)
-               if err != nil {
-                       return loginError(fmt.Errorf("error verifying ID token: %s", err))
-               }
-               authinfo, err := ctrl.getAuthInfo(ctx, oauth2Token, idToken)
-               if err != nil {
-                       return loginError(err)
-               }
-               ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{ctrl.Cluster.SystemRootToken}})
-               return ctrl.RailsProxy.UserSessionCreate(ctxRoot, rpc.UserSessionCreateOptions{
-                       ReturnTo: state.Remote + "," + state.ReturnTo,
-                       AuthInfo: *authinfo,
-               })
        }
+       // Callback after OIDC sign-in.
+       state := ctrl.parseOAuth2State(opts.State)
+       if !state.verify([]byte(ctrl.Cluster.SystemRootToken)) {
+               return loginError(errors.New("invalid OAuth2 state"))
+       }
+       oauth2Token, err := ctrl.oauth2conf.Exchange(ctx, opts.Code)
+       if err != nil {
+               return loginError(fmt.Errorf("error in OAuth2 exchange: %s", err))
+       }
+       rawIDToken, ok := oauth2Token.Extra("id_token").(string)
+       if !ok {
+               return loginError(errors.New("error in OAuth2 exchange: no ID token in OAuth2 token"))
+       }
+       idToken, err := ctrl.verifier.Verify(ctx, rawIDToken)
+       if err != nil {
+               return loginError(fmt.Errorf("error verifying ID token: %s", err))
+       }
+       authinfo, err := ctrl.getAuthInfo(ctx, oauth2Token, idToken)
+       if err != nil {
+               return loginError(err)
+       }
+       ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{ctrl.Cluster.SystemRootToken}})
+       return ctrl.RailsProxy.UserSessionCreate(ctxRoot, rpc.UserSessionCreateOptions{
+               ReturnTo: state.Remote + "," + state.ReturnTo,
+               AuthInfo: *authinfo,
+       })
 }
 
 func (ctrl *oidcLoginController) UserAuthenticate(ctx context.Context, opts arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
@@ -190,9 +189,8 @@ func (ctrl *oidcLoginController) getAuthInfo(ctx context.Context, token *oauth2.
                        // only the "fix config" advice to the user.
                        ctxlog.FromContext(ctx).WithError(err).WithField("email", ret.Email).Error("People API is not enabled")
                        return nil, errors.New("configuration error: Login.GoogleAlternateEmailAddresses is true, but Google People API is not enabled")
-               } else {
-                       return nil, fmt.Errorf("error getting profile info from People API: %s", err)
                }
+               return nil, fmt.Errorf("error getting profile info from People API: %s", err)
        }
 
        // The given/family names returned by the People API and
index e8c7660d1aee39424f88d2d6de0e2b3a213baa36..55cc6ee564be66ed2ecfc0e7713ad0c150a03e9e 100644 (file)
@@ -157,9 +157,8 @@ func (t *TestDockerClient) ContainerStart(ctx context.Context, container string,
        if container == "abcde" {
                // t.fn gets executed in ContainerWait
                return nil
-       } else {
-               return errors.New("Invalid container id")
        }
+       return errors.New("Invalid container id")
 }
 
 func (t *TestDockerClient) ContainerRemove(ctx context.Context, container string, options dockertypes.ContainerRemoveOptions) error {
@@ -196,9 +195,8 @@ func (t *TestDockerClient) ImageInspectWithRaw(ctx context.Context, image string
 
        if t.imageLoaded == image {
                return dockertypes.ImageInspect{}, nil, nil
-       } else {
-               return dockertypes.ImageInspect{}, nil, errors.New("")
        }
+       return dockertypes.ImageInspect{}, nil, errors.New("")
 }
 
 func (t *TestDockerClient) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (dockertypes.ImageLoadResponse, error) {
@@ -208,10 +206,9 @@ func (t *TestDockerClient) ImageLoad(ctx context.Context, input io.Reader, quiet
        _, err := io.Copy(ioutil.Discard, input)
        if err != nil {
                return dockertypes.ImageLoadResponse{}, err
-       } else {
-               t.imageLoaded = hwImageId
-               return dockertypes.ImageLoadResponse{Body: ioutil.NopCloser(input)}, nil
        }
+       t.imageLoaded = hwImageId
+       return dockertypes.ImageLoadResponse{Body: ioutil.NopCloser(input)}, nil
 }
 
 func (*TestDockerClient) ImageRemove(ctx context.Context, image string, options dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) {
@@ -260,9 +257,8 @@ func (client *ArvTestClient) Call(method, resourceType, uuid, action string, par
        case method == "GET" && resourceType == "containers" && action == "secret_mounts":
                if client.secretMounts != nil {
                        return json.Unmarshal(client.secretMounts, output)
-               } else {
-                       return json.Unmarshal([]byte(`{"secret_mounts":{}}`), output)
                }
+               return json.Unmarshal([]byte(`{"secret_mounts":{}}`), output)
        default:
                return fmt.Errorf("Not found")
        }
index 278bcb66579b7f37c280e0c2bf5c62ca3524694d..7614a143abded97b08757138bd4b152771eb3588 100644 (file)
@@ -17,7 +17,7 @@ import (
        "git.arvados.org/arvados.git/lib/cloud"
        "git.arvados.org/arvados.git/lib/dispatchcloud/container"
        "git.arvados.org/arvados.git/lib/dispatchcloud/scheduler"
-       "git.arvados.org/arvados.git/lib/dispatchcloud/ssh_executor"
+       "git.arvados.org/arvados.git/lib/dispatchcloud/sshexecutor"
        "git.arvados.org/arvados.git/lib/dispatchcloud/worker"
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "git.arvados.org/arvados.git/sdk/go/auth"
@@ -100,7 +100,7 @@ func (disp *dispatcher) Close() {
 
 // Make a worker.Executor for the given instance.
 func (disp *dispatcher) newExecutor(inst cloud.Instance) worker.Executor {
-       exr := ssh_executor.New(inst)
+       exr := sshexecutor.New(inst)
        exr.SetTargetPort(disp.Cluster.Containers.CloudVMs.SSHPort)
        exr.SetSigners(disp.sshKey)
        return exr
index 9f1eb098e01aa029ebe735f2f8a7a956bf56c236..d5d90bf3518b75fb548e810e2ad8a7cc2c9867ba 100644 (file)
@@ -227,6 +227,10 @@ func (s *DispatcherSuite) TestDispatchToStubDriver(c *check.C) {
        c.Check(resp.Body.String(), check.Matches, `(?ms).*time_from_shutdown_request_to_disappearance_seconds_sum [0-9.]*`)
        c.Check(resp.Body.String(), check.Matches, `(?ms).*time_from_queue_to_crunch_run_seconds_count [0-9]*`)
        c.Check(resp.Body.String(), check.Matches, `(?ms).*time_from_queue_to_crunch_run_seconds_sum [0-9e+.]*`)
+       c.Check(resp.Body.String(), check.Matches, `(?ms).*run_probe_duration_seconds_count{outcome="success"} [0-9]*`)
+       c.Check(resp.Body.String(), check.Matches, `(?ms).*run_probe_duration_seconds_sum{outcome="success"} [0-9e+.]*`)
+       c.Check(resp.Body.String(), check.Matches, `(?ms).*run_probe_duration_seconds_count{outcome="fail"} [0-9]*`)
+       c.Check(resp.Body.String(), check.Matches, `(?ms).*run_probe_duration_seconds_sum{outcome="fail"} [0-9e+.]*`)
 }
 
 func (s *DispatcherSuite) TestAPIPermissions(c *check.C) {
similarity index 98%
rename from lib/dispatchcloud/ssh_executor/executor.go
rename to lib/dispatchcloud/sshexecutor/executor.go
index 79b82e6c37a0248cc0db3d33105829ad23c76307..c37169921cf594ac035263ad4c53d4c176c13214 100644 (file)
@@ -2,9 +2,9 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-// Package ssh_executor provides an implementation of pool.Executor
+// Package sshexecutor provides an implementation of pool.Executor
 // using a long-lived multiplexed SSH session.
-package ssh_executor
+package sshexecutor
 
 import (
        "bytes"
similarity index 99%
rename from lib/dispatchcloud/ssh_executor/executor_test.go
rename to lib/dispatchcloud/sshexecutor/executor_test.go
index b7f3aadd8ab268a755aabcbc79543a76bc693d96..b4afeafa82dab3e671f48802646df185d8a64590 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-package ssh_executor
+package sshexecutor
 
 import (
        "bytes"
index c6eaeae2b618b11423512cc2be1cb5cfc454c20c..a25ed60150718f83829a003d6b0e8267a382a430 100644 (file)
@@ -86,9 +86,8 @@ const (
 func duration(conf arvados.Duration, def time.Duration) time.Duration {
        if conf > 0 {
                return time.Duration(conf)
-       } else {
-               return def
        }
+       return def
 }
 
 // NewPool creates a Pool of workers backed by instanceSet.
@@ -184,6 +183,7 @@ type Pool struct {
        mTimeToReadyForContainer  prometheus.Summary
        mTimeFromShutdownToGone   prometheus.Summary
        mTimeFromQueueToCrunchRun prometheus.Summary
+       mRunProbeDuration         *prometheus.SummaryVec
 }
 
 type createCall struct {
@@ -682,6 +682,14 @@ func (wp *Pool) registerMetrics(reg *prometheus.Registry) {
                Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.95: 0.005, 0.99: 0.001},
        })
        reg.MustRegister(wp.mTimeFromQueueToCrunchRun)
+       wp.mRunProbeDuration = prometheus.NewSummaryVec(prometheus.SummaryOpts{
+               Namespace:  "arvados",
+               Subsystem:  "dispatchcloud",
+               Name:       "instances_run_probe_duration_seconds",
+               Help:       "Number of seconds per runProbe call.",
+               Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.95: 0.005, 0.99: 0.001},
+       }, []string{"outcome"})
+       reg.MustRegister(wp.mRunProbeDuration)
 }
 
 func (wp *Pool) runMetrics() {
index 5b145d7c6599b75bb6e8b30f6c65e65d82186d84..9e89d7daafc01d05b770fb065f88049dea231a7e 100644 (file)
@@ -192,7 +192,7 @@ func (wkr *worker) startContainer(ctr arvados.Container) {
 }
 
 // ProbeAndUpdate conducts appropriate boot/running probes (if any)
-// for the worker's curent state. If a previous probe is still
+// for the worker's current state. If a previous probe is still
 // running, it does nothing.
 //
 // It should be called in a new goroutine.
@@ -376,6 +376,7 @@ func (wkr *worker) probeRunning() (running []string, reportsBroken, ok bool) {
        if u := wkr.instance.RemoteUser(); u != "root" {
                cmd = "sudo " + cmd
        }
+       before := time.Now()
        stdout, stderr, err := wkr.executor.Execute(nil, cmd, nil)
        if err != nil {
                wkr.logger.WithFields(logrus.Fields{
@@ -383,8 +384,10 @@ func (wkr *worker) probeRunning() (running []string, reportsBroken, ok bool) {
                        "stdout":  string(stdout),
                        "stderr":  string(stderr),
                }).WithError(err).Warn("probe failed")
+               wkr.wp.mRunProbeDuration.WithLabelValues("fail").Observe(time.Now().Sub(before).Seconds())
                return
        }
+       wkr.wp.mRunProbeDuration.WithLabelValues("success").Observe(time.Now().Sub(before).Seconds())
        ok = true
 
        staleRunLock := false
index a4c2a6370f3d5ce3803484b18ac811abec7e6bc1..cfb7a1bfb7a72b8924d5950deb7fc478f20873b0 100644 (file)
@@ -17,6 +17,7 @@ import (
        "git.arvados.org/arvados.git/lib/dispatchcloud/test"
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "git.arvados.org/arvados.git/sdk/go/ctxlog"
+       "github.com/prometheus/client_golang/prometheus"
        check "gopkg.in/check.v1"
 )
 
@@ -239,6 +240,7 @@ func (suite *WorkerSuite) TestProbeAndUpdate(c *check.C) {
                        runnerData:       trial.deployRunner,
                        runnerMD5:        md5.Sum(trial.deployRunner),
                }
+               wp.registerMetrics(prometheus.NewRegistry())
                if trial.deployRunner != nil {
                        svHash := md5.Sum(trial.deployRunner)
                        wp.runnerCmd = fmt.Sprintf("/var/run/arvados/crunch-run~%x", svHash)
index dcbe03a057b8cbd7d44643f3064563290e559b07..4bfe272789062018d47e33e1b46394a725f45e97 100644 (file)
@@ -192,6 +192,10 @@ def arg_parser():  # type: () -> argparse.ArgumentParser
                         action="store_false", default=True,
                         help=argparse.SUPPRESS)
 
+    parser.add_argument("--disable-color", dest="enable_color",
+                        action="store_false", default=True,
+                        help=argparse.SUPPRESS)
+
     parser.add_argument("--disable-js-validation",
                         action="store_true", default=False,
                         help=argparse.SUPPRESS)
index fb23c2ccf73df514923f4fd0041814c6e8751833..99d82f3398332d10e0ac0cbf95decb0d5870bd5a 100644 (file)
@@ -325,8 +325,8 @@ class ArvadosContainer(JobBase):
                 logger.info("%s reused container %s", self.arvrunner.label(self), response["container_uuid"])
             else:
                 logger.info("%s %s state is %s", self.arvrunner.label(self), response["uuid"], response["state"])
-        except Exception:
-            logger.exception("%s got an error", self.arvrunner.label(self))
+        except Exception as e:
+            logger.exception("%s error submitting container\n%s", self.arvrunner.label(self), e)
             logger.debug("Container request was %s", container_request)
             self.output_callback({}, "permanentFail")
 
@@ -475,6 +475,7 @@ class RunnerContainer(Runner):
                    "--api=containers",
                    "--no-log-timestamps",
                    "--disable-validate",
+                   "--disable-color",
                    "--eval-timeout=%s" % self.arvrunner.eval_timeout,
                    "--thread-count=%s" % self.arvrunner.thread_count,
                    "--enable-reuse" if self.enable_reuse else "--disable-reuse",
index 9ba798ec640f3d0caaecdaf114bafbdb36a1b4ad..68141586decdc7f656ca715e14bec1a6c436528a 100644 (file)
@@ -524,6 +524,8 @@ The 'jobs' API is no longer supported.
     def arv_executor(self, updated_tool, job_order, runtimeContext, logger=None):
         self.debug = runtimeContext.debug
 
+        logger.info("Using cluster %s (%s)", self.api.config()["ClusterID"], self.api.config()["Services"]["Controller"]["ExternalURL"])
+
         updated_tool.visit(self.check_features)
 
         self.project_uuid = runtimeContext.project_uuid
index 4da545bf36b91c6f96ba3ec8657e3d0a2a4db265..d2dd6e8162e686355b6b4d5b076c54fad11c6637 100644 (file)
@@ -302,7 +302,7 @@ def stubs(func):
             'secret_mounts': {},
             'state': 'Committed',
             'command': ['arvados-cwl-runner', '--local', '--api=containers',
-                        '--no-log-timestamps', '--disable-validate',
+                        '--no-log-timestamps', '--disable-validate', '--disable-color',
                         '--eval-timeout=20', '--thread-count=1',
                         '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
                         '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json'],
@@ -412,7 +412,7 @@ class TestSubmit(unittest.TestCase):
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = [
             'arvados-cwl-runner', '--local', '--api=containers',
-            '--no-log-timestamps', '--disable-validate',
+            '--no-log-timestamps', '--disable-validate', '--disable-color',
             '--eval-timeout=20', '--thread-count=1',
             '--disable-reuse', "--collection-cache-size=256",
             '--debug', '--on-error=continue',
@@ -436,7 +436,7 @@ class TestSubmit(unittest.TestCase):
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = [
             'arvados-cwl-runner', '--local', '--api=containers',
-            '--no-log-timestamps', '--disable-validate',
+            '--no-log-timestamps', '--disable-validate', '--disable-color',
             '--eval-timeout=20', '--thread-count=1',
             '--disable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
             '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
@@ -468,7 +468,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        '--debug', '--on-error=stop',
@@ -491,7 +491,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        "--output-name="+output_name, '--debug', '--on-error=continue',
@@ -513,7 +513,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256", "--debug",
                                        "--storage-classes=foo", '--on-error=continue',
@@ -576,7 +576,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256", '--debug',
                                        '--on-error=continue',
@@ -599,7 +599,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        '--debug', '--on-error=continue',
@@ -623,7 +623,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        "--output-tags="+output_tags, '--debug', '--on-error=continue',
@@ -700,7 +700,7 @@ class TestSubmit(unittest.TestCase):
             'name': 'expect_arvworkflow.cwl#main',
             'container_image': '999999999999999999999999999999d3+99',
             'command': ['arvados-cwl-runner', '--local', '--api=containers',
-                        '--no-log-timestamps', '--disable-validate',
+                        '--no-log-timestamps', '--disable-validate', '--disable-color',
                         '--eval-timeout=20', '--thread-count=1',
                         '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
                         '/var/lib/cwl/workflow/expect_arvworkflow.cwl#main', '/var/lib/cwl/cwl.input.json'],
@@ -795,7 +795,7 @@ class TestSubmit(unittest.TestCase):
             'name': 'a test workflow',
             'container_image': "999999999999999999999999999999d3+99",
             'command': ['arvados-cwl-runner', '--local', '--api=containers',
-                        '--no-log-timestamps', '--disable-validate',
+                        '--no-log-timestamps', '--disable-validate', '--disable-color',
                         '--eval-timeout=20', '--thread-count=1',
                         '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
                         '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json'],
@@ -859,7 +859,7 @@ class TestSubmit(unittest.TestCase):
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["owner_uuid"] = project_uuid
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        "--eval-timeout=20", "--thread-count=1",
                                        '--enable-reuse', "--collection-cache-size=256", '--debug',
                                        '--on-error=continue',
@@ -881,7 +881,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=60.0', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        '--debug', '--on-error=continue',
@@ -902,7 +902,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=1',
                                        '--enable-reuse', "--collection-cache-size=500",
                                        '--debug', '--on-error=continue',
@@ -924,7 +924,7 @@ class TestSubmit(unittest.TestCase):
 
         expect_container = copy.deepcopy(stubs.expect_container_spec)
         expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
-                                       '--no-log-timestamps', '--disable-validate',
+                                       '--no-log-timestamps', '--disable-validate', '--disable-color',
                                        '--eval-timeout=20', '--thread-count=20',
                                        '--enable-reuse', "--collection-cache-size=256",
                                        '--debug', '--on-error=continue',
@@ -994,7 +994,7 @@ class TestSubmit(unittest.TestCase):
             "arv": "http://arvados.org/cwl#",
         }
         expect_container['command'] = ['arvados-cwl-runner', '--local', '--api=containers',
-                        '--no-log-timestamps', '--disable-validate',
+                        '--no-log-timestamps', '--disable-validate', '--disable-color',
                         '--eval-timeout=20', '--thread-count=1',
                         '--enable-reuse', "--collection-cache-size=512", '--debug', '--on-error=continue',
                         '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
@@ -1059,6 +1059,7 @@ class TestSubmit(unittest.TestCase):
                 "--api=containers",
                 "--no-log-timestamps",
                 "--disable-validate",
+                "--disable-color",
                 "--eval-timeout=20",
                 '--thread-count=1',
                 "--enable-reuse",
index dd067e9778c790ee09dcb63c6c8665ac1addfd1d..f7719dbc4335048663e5195edaf791caa05dee8e 100644 (file)
 #  of the docker build root.)
 
 FROM debian:9
-MAINTAINER Ward Vandewege <ward@curoverse.com>
+MAINTAINER Peter Amstutz <peter.amstutz@curii.com>
 
 ENV DEBIAN_FRONTEND noninteractive
 
-ARG pythoncmd=python
-ARG pipcmd=pip
+ARG pythoncmd=python3
+ARG pipcmd=pip3
 
 RUN apt-get update -q && apt-get install -qy --no-install-recommends \
     git ${pythoncmd}-pip ${pythoncmd}-virtualenv ${pythoncmd}-dev libcurl4-gnutls-dev \
index 667a30f5ef669ac50c06e0756c4a30ecbde3e025..214021598641a057aafbfa15c0f74f5720878d00 100644 (file)
@@ -26,9 +26,8 @@ func SaltToken(token, remote string) (string, error) {
        if len(parts) < 3 || parts[0] != "v2" {
                if reObsoleteToken.MatchString(token) {
                        return "", ErrObsoleteToken
-               } else {
-                       return "", ErrTokenFormat
                }
+               return "", ErrTokenFormat
        }
        uuid := parts[1]
        secret := parts[2]
index a45775470a0ca49a731ba839803eb8b5f43be124..1e64eeb1dafd06105a5eef02e0737ddfab3ed597 100644 (file)
@@ -236,7 +236,7 @@ def uploadfiles(files, api, dry_run=False, num_retries=0,
             # empty collection
             pdh = collection.portable_data_hash()
             assert (pdh == config.EMPTY_BLOCK_LOCATOR), "Empty collection portable_data_hash did not have expected locator, was %s" % pdh
-            logger.info("Using empty collection %s", pdh)
+            logger.debug("Using empty collection %s", pdh)
 
     for c in files:
         c.keepref = "%s/%s" % (pdh, c.fn)
index 81b9ca9e5bec3d74c5b524cb351752845017b1e7..656bd37ae6e3cf7e53bae89eac6e1b6086257d33 100644 (file)
@@ -56,11 +56,19 @@ class Arvados::V1::CollectionsController < ApplicationController
   end
 
   def find_object_by_uuid
-    @include_old_versions = true
+    if params[:include_old_versions].nil?
+      @include_old_versions = true
+    else
+      @include_old_versions = params[:include_old_versions]
+    end
 
     if loc = Keep::Locator.parse(params[:id])
       loc.strip_hints!
 
+      opts = {}
+      opts.update({include_trash: true}) if params[:include_trash]
+      opts.update({include_old_versions: @include_old_versions})
+
       # It matters which Collection object we pick because we use it to get signed_manifest_text,
       # the value of which is affected by the value of trash_at.
       #
@@ -72,14 +80,13 @@ class Arvados::V1::CollectionsController < ApplicationController
       # it will select the Collection object with the longest
       # available lifetime.
 
-      if c = Collection.readable_by(*@read_users).where({ portable_data_hash: loc.to_s }).order("trash_at desc").limit(1).first
+      if c = Collection.readable_by(*@read_users, opts).where({ portable_data_hash: loc.to_s }).order("trash_at desc").limit(1).first
         @object = {
           uuid: c.portable_data_hash,
           portable_data_hash: c.portable_data_hash,
           manifest_text: c.signed_manifest_text,
         }
       end
-      true
     else
       super
     end
index 709b4b4d1c1304e456c494a4079ca2ea0cccc8fb..3966b7c3939edc31cdc4490b27285a565da0a84a 100644 (file)
@@ -627,7 +627,12 @@ class ArvadosModel < ApplicationRecord
   end
 
   def permission_to_destroy
-    permission_to_update
+    if [system_user_uuid, system_group_uuid, anonymous_group_uuid,
+        anonymous_user_uuid, public_project_uuid].include? uuid
+      false
+    else
+      permission_to_update
+    end
   end
 
   def maybe_update_modified_by_fields
index d7c5e04dfd1b82e571a92079e3563523ec065376..67bd3d10d78975cd942a32acc7bb49306d31e0cc 100644 (file)
@@ -7,15 +7,18 @@ require 'update_permissions'
 class DatabaseSeeds
   extend CurrentApiClient
   def self.install
-    system_user
-    system_group
-    all_users_group
-    anonymous_group
-    anonymous_group_read_permission
-    anonymous_user
-    system_root_token_api_client
-    empty_collection
-    refresh_permissions
+    batch_update_permissions do
+      system_user
+      system_group
+      all_users_group
+      anonymous_group
+      anonymous_group_read_permission
+      anonymous_user
+      system_root_token_api_client
+      public_project_group
+      public_project_read_permission
+      empty_collection
+    end
     refresh_trashed
   end
 end
diff --git a/services/api/db/migrate/20200914203202_public_favorites_project.rb b/services/api/db/migrate/20200914203202_public_favorites_project.rb
new file mode 100644 (file)
index 0000000..ef139aa
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+class PublicFavoritesProject < ActiveRecord::Migration[5.2]
+  include CurrentApiClient
+  def up
+    act_as_system_user do
+      public_project_group
+      public_project_read_permission
+      Link.where(link_class: "star",
+                 owner_uuid: system_user_uuid,
+                 tail_uuid: all_users_group_uuid).each do |ln|
+        ln.owner_uuid = public_project_uuid
+        ln.tail_uuid = public_project_uuid
+        ln.save!
+      end
+    end
+  end
+
+  def down
+  end
+end
index 83987d051859843a8df981cf539f8514daecc15b..a5740834c7a1c2646a83c59b6da9d40e3ef7684b 100644 (file)
@@ -3197,6 +3197,7 @@ INSERT INTO "schema_migrations" (version) VALUES
 ('20190809135453'),
 ('20190905151603'),
 ('20200501150153'),
-('20200602141328');
+('20200602141328'),
+('20200914203202');
 
 
index cfdae0bddec58455daf0d791b7a7731dd98e6e8b..dc40f158eeaef6fb4fb21cc7d3d8dad04c28f917 100644 (file)
@@ -9,6 +9,8 @@ $anonymous_user = nil
 $anonymous_group = nil
 $anonymous_group_read_permission = nil
 $empty_collection = nil
+$public_project_group = nil
+$public_project_group_read_permission = nil
 
 module CurrentApiClient
   def current_user
@@ -65,6 +67,12 @@ module CurrentApiClient
      'anonymouspublic'].join('-')
   end
 
+  def public_project_uuid
+    [Rails.configuration.ClusterID,
+     Group.uuid_prefix,
+     'publicfavorites'].join('-')
+  end
+
   def system_user
     $system_user = check_cache $system_user do
       real_current_user = Thread.current[:user]
@@ -189,6 +197,31 @@ module CurrentApiClient
     end
   end
 
+  def public_project_group
+    $public_project_group = check_cache $public_project_group do
+      act_as_system_user do
+        ActiveRecord::Base.transaction do
+          Group.where(uuid: public_project_uuid).
+            first_or_create!(group_class: "project",
+                             name: "Public favorites",
+                             description: "Public favorites")
+        end
+      end
+    end
+  end
+
+  def public_project_read_permission
+    $public_project_group_read_permission =
+        check_cache $public_project_group_read_permission do
+      act_as_system_user do
+        Link.where(tail_uuid: anonymous_group.uuid,
+                   head_uuid: public_project_group.uuid,
+                   link_class: "permission",
+                   name: "can_read").first_or_create!
+      end
+    end
+  end
+
   def system_root_token_api_client
     $system_root_token_api_client = check_cache $system_root_token_api_client do
       act_as_system_user do
index ee0d786bbe2f1537a9ef904df51eba7f221eea75..31a72f17208090a9b210996b4c34379e95116aa1 100644 (file)
@@ -56,6 +56,13 @@ system_group:
   description: System-owned Group
   group_class: role
 
+public_favorites_project:
+  uuid: zzzzz-j7d0g-publicfavorites
+  owner_uuid: zzzzz-tpzed-000000000000000
+  name: Public favorites
+  description: Public favorites
+  group_class: project
+
 empty_lonely_group:
   uuid: zzzzz-j7d0g-jtp06ulmvsezgyu
   owner_uuid: zzzzz-tpzed-000000000000000
index 0785c12a50884f37a021e0c60582b95bc7b00ae8..25f1efff62c8f71246749a3b3c189d297eb7ed82 100644 (file)
@@ -4,51 +4,56 @@
 
 noop: # nothing happened ...to the 'spectator' user
   id: 1
-  uuid: zzzzz-xxxxx-pshmckwoma9plh7
+  uuid: zzzzz-57u5n-pshmckwoma9plh7
   owner_uuid: zzzzz-tpzed-000000000000000
   object_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
   object_owner_uuid: zzzzz-tpzed-000000000000000
   event_at: <%= 1.minute.ago.to_s(:db) %>
+  created_at: <%= 1.minute.ago.to_s(:db) %>
 
 admin_changes_repository2: # admin changes repository2, which is owned by active user
   id: 2
-  uuid: zzzzz-xxxxx-pshmckwoma00002
+  uuid: zzzzz-57u5n-pshmckwoma00002
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
   object_uuid: zzzzz-2x53u-382brsig8rp3667 # repository foo
   object_owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
+  created_at: <%= 2.minute.ago.to_s(:db) %>
   event_at: <%= 2.minute.ago.to_s(:db) %>
   event_type: update
 
 admin_changes_specimen: # admin changes specimen owned_by_spectator
   id: 3
-  uuid: zzzzz-xxxxx-pshmckwoma00003
+  uuid: zzzzz-57u5n-pshmckwoma00003
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
   object_uuid: zzzzz-2x53u-3b0xxwzlbzxq5yr # specimen owned_by_spectator
   object_owner_uuid: zzzzz-tpzed-l1s2piq4t4mps8r # spectator user
+  created_at: <%= 3.minute.ago.to_s(:db) %>
   event_at: <%= 3.minute.ago.to_s(:db) %>
   event_type: update
 
 system_adds_foo_file: # foo collection added, readable by active through link
   id: 4
-  uuid: zzzzz-xxxxx-pshmckwoma00004
+  uuid: zzzzz-57u5n-pshmckwoma00004
   owner_uuid: zzzzz-tpzed-000000000000000 # system user
   object_uuid: zzzzz-4zz18-znfnqtbbv4spc3w # foo file
   object_owner_uuid: zzzzz-tpzed-000000000000000 # system user
+  created_at: <%= 4.minute.ago.to_s(:db) %>
   event_at: <%= 4.minute.ago.to_s(:db) %>
   event_type: create
 
 system_adds_baz: # baz collection added, readable by active and spectator through group 'all users' group membership
   id: 5
-  uuid: zzzzz-xxxxx-pshmckwoma00005
+  uuid: zzzzz-57u5n-pshmckwoma00005
   owner_uuid: zzzzz-tpzed-000000000000000 # system user
   object_uuid: zzzzz-4zz18-y9vne9npefyxh8g # baz file
   object_owner_uuid: zzzzz-tpzed-000000000000000 # system user
+  created_at: <%= 5.minute.ago.to_s(:db) %>
   event_at: <%= 5.minute.ago.to_s(:db) %>
   event_type: create
 
 log_owned_by_active:
   id: 6
-  uuid: zzzzz-xxxxx-pshmckwoma12345
+  uuid: zzzzz-57u5n-pshmckwoma12345
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   object_uuid: zzzzz-2x53u-382brsig8rp3667 # repository foo
   object_owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
index d8017881d5dd151029485066833ff7ab651eea0c..c025394bc1f33616684be72861862126642d95c4 100644 (file)
@@ -1388,6 +1388,16 @@ EOS
                   json_response['name']
   end
 
+  test 'can get old version collection by PDH' do
+    authorize_with :active
+    get :show, params: {
+      id: collections(:collection_owned_by_active_past_version_1).portable_data_hash,
+    }
+    assert_response :success
+    assert_equal collections(:collection_owned_by_active_past_version_1).portable_data_hash,
+                  json_response['portable_data_hash']
+  end
+
   test 'version and current_version_uuid are ignored at creation time' do
     permit_unsigned_manifests
     authorize_with :active
index 58f0cddb709064ad2f8af9df6c20aa20f0c77d6a..76d78f9eaa6cf14ebd83b8b7b138e3f94c69dff5 100644 (file)
@@ -319,6 +319,7 @@ class LogTest < ActiveSupport::TestCase
 
   def assert_no_logs_deleted
     logs_before = Log.unscoped.all.count
+    assert logs_before > 0
     yield
     assert_equal logs_before, Log.unscoped.all.count
   end
@@ -350,34 +351,34 @@ class LogTest < ActiveSupport::TestCase
   # but 3 minutes suits our test data better (and is test-worthy in
   # that it's expected to work correctly in production).
   test 'delete old audit logs with production settings' do
-    initial_log_count = Log.unscoped.all.count
+    initial_log_count = remaining_audit_logs.count
+    assert initial_log_count > 0
     AuditLogs.delete_old(max_age: 180, max_batch: 100000)
     assert_operator remaining_audit_logs.count, :<, initial_log_count
   end
 
   test 'delete all audit logs in multiple batches' do
+    assert remaining_audit_logs.count > 2
     AuditLogs.delete_old(max_age: 0.00001, max_batch: 2)
     assert_equal [], remaining_audit_logs.collect(&:uuid)
   end
 
   test 'delete old audit logs in thread' do
-    begin
-      Rails.configuration.AuditLogs.MaxAge = 20
-      Rails.configuration.AuditLogs.MaxDeleteBatch = 100000
-      Rails.cache.delete 'AuditLogs'
-      initial_log_count = Log.unscoped.all.count + 1
-      act_as_system_user do
-        Log.create!()
-        initial_log_count += 1
-      end
-      deadline = Time.now + 10
-      while remaining_audit_logs.count == initial_log_count
-        if Time.now > deadline
-          raise "timed out"
-        end
-        sleep 0.1
+    Rails.configuration.AuditLogs.MaxAge = 20
+    Rails.configuration.AuditLogs.MaxDeleteBatch = 100000
+    Rails.cache.delete 'AuditLogs'
+    initial_audit_log_count = remaining_audit_logs.count
+    assert initial_audit_log_count > 0
+    act_as_system_user do
+      Log.create!()
+    end
+    deadline = Time.now + 10
+    while remaining_audit_logs.count == initial_audit_log_count
+      if Time.now > deadline
+        raise "timed out"
       end
-      assert_operator remaining_audit_logs.count, :<, initial_log_count
+      sleep 0.1
     end
+    assert_operator remaining_audit_logs.count, :<, initial_audit_log_count
   end
 end
index 10664474c68bf219a4cfb521a0431e97a21c5fdc..123031b35feb90b0fc874b0461fff896ca531702 100644 (file)
@@ -579,4 +579,24 @@ class PermissionTest < ActiveSupport::TestCase
     assert users(:active).can?(write: prj.uuid)
     assert users(:active).can?(manage: prj.uuid)
   end
+
+  [system_user_uuid, anonymous_user_uuid].each do |u|
+    test "cannot delete system user #{u}" do
+      act_as_system_user do
+        assert_raises ArvadosModel::PermissionDeniedError do
+          User.find_by_uuid(u).destroy
+        end
+      end
+    end
+  end
+
+  [system_group_uuid, anonymous_group_uuid, public_project_uuid].each do |g|
+    test "cannot delete system group #{g}" do
+      act_as_system_user do
+        assert_raises ArvadosModel::PermissionDeniedError do
+          Group.find_by_uuid(g).destroy
+        end
+      end
+    end
+  end
 end
index 5aee7e087b2658945b2eebe1f2f309d67c351d16..eae21e62b6c0a72787890fcda9f4b1f29b3d92b5 100644 (file)
@@ -23,8 +23,8 @@ type slurmJob struct {
        hitNiceLimit bool
 }
 
-// Squeue implements asynchronous polling monitor of the SLURM queue using the
-// command 'squeue'.
+// SqueueChecker implements asynchronous polling monitor of the SLURM queue
+// using the command 'squeue'.
 type SqueueChecker struct {
        Logger         logger
        Period         time.Duration
@@ -102,13 +102,12 @@ func (sqc *SqueueChecker) reniceAll() {
        sort.Slice(jobs, func(i, j int) bool {
                if jobs[i].wantPriority != jobs[j].wantPriority {
                        return jobs[i].wantPriority > jobs[j].wantPriority
-               } else {
-                       // break ties with container uuid --
-                       // otherwise, the ordering would change from
-                       // one interval to the next, and we'd do many
-                       // pointless slurm queue rearrangements.
-                       return jobs[i].uuid > jobs[j].uuid
                }
+               // break ties with container uuid --
+               // otherwise, the ordering would change from
+               // one interval to the next, and we'd do many
+               // pointless slurm queue rearrangements.
+               return jobs[i].uuid > jobs[j].uuid
        })
        renice := wantNice(jobs, sqc.PrioritySpread)
        for i, job := range jobs {
index b4ccd98282a5de1966f9c32a9a0926c92f79bf81..670fa1a4140fc14229279d1ff920d76959679afd 100644 (file)
@@ -80,7 +80,7 @@ func (h *handler) pullItemAndProcess(pullRequest PullRequest) error {
        return writePulledBlock(h.volmgr, vol, readContent, pullRequest.Locator)
 }
 
-// Fetch the content for the given locator using keepclient.
+// GetContent fetches the content for the given locator using keepclient.
 var GetContent = func(signedLocator string, keepClient *keepclient.KeepClient) (io.ReadCloser, int64, string, error) {
        return keepClient.Get(signedLocator)
 }
@@ -88,8 +88,7 @@ var GetContent = func(signedLocator string, keepClient *keepclient.KeepClient) (
 var writePulledBlock = func(volmgr *RRVolumeManager, volume Volume, data []byte, locator string) error {
        if volume != nil {
                return volume.Put(context.Background(), locator, data)
-       } else {
-               _, err := PutBlock(context.Background(), volmgr, data, locator)
-               return err
        }
+       _, err := PutBlock(context.Background(), volmgr, data, locator)
+       return err
 }
index d07d23c3c219c630f61881bf75df1d233f0b67a6..8d999e7472ff14f03985e80a2b774632eebe7346 100644 (file)
@@ -33,7 +33,7 @@ import (
        "github.com/sirupsen/logrus"
 )
 
-// S3Volume implements Volume using an S3 bucket.
+// S3AWSVolume implements Volume using an S3 bucket.
 type S3AWSVolume struct {
        arvados.S3VolumeDriverParameters
        AuthToken      string    // populated automatically when IAMRole is used
@@ -69,10 +69,9 @@ func chooseS3VolumeDriver(cluster *arvados.Cluster, volume arvados.Volume, logge
        if v.UseAWSS3v2Driver {
                logger.Debugln("Using AWS S3 v2 driver")
                return newS3AWSVolume(cluster, volume, logger, metrics)
-       } else {
-               logger.Debugln("Using goamz S3 driver")
-               return newS3Volume(cluster, volume, logger, metrics)
        }
+       logger.Debugln("Using goamz S3 driver")
+       return newS3Volume(cluster, volume, logger, metrics)
 }
 
 const (
index 279d46c08b4ee98a652d78b88f949f1587453d8a..122e2bec7c5bb1790fe357f33ded44a369b0fc75 100755 (executable)
@@ -107,11 +107,11 @@ wait_for_arvbox() {
     while read line ; do
         if [[ $line =~ "ok: down: ready:" ]] ; then
             kill $LOGPID
-           set +e
-           wait $LOGPID 2>/dev/null
-           set -e
-       else
-           echo $line
+            set +e
+            wait $LOGPID 2>/dev/null
+            set -e
+        else
+            echo $line
         fi
     done < $FF
     rm $FF
@@ -125,7 +125,7 @@ wait_for_arvbox() {
 
 docker_run_dev() {
     docker run \
-          "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
+           "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
            "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
            "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
            "--volume=$PG_DATA:/var/lib/postgresql:rw" \
@@ -136,8 +136,8 @@ 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" \
-          "$@"
+           --label "org.arvados.arvbox_config=$CONFIG" \
+           "$@"
 }
 
 running_config() {
@@ -153,10 +153,10 @@ run() {
     need_setup=1
 
     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; 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 [[ $(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
@@ -175,12 +175,12 @@ run() {
     if test -n "$TAG"
     then
         if test $(echo $TAG | cut -c1-1) != '-' ; then
-           TAG=":$TAG"
+            TAG=":$TAG"
             shift
         else
-           if [[ $TAG = '-' ]] ; then
-               shift
-           fi
+            if [[ $TAG = '-' ]] ; then
+                shift
+            fi
             unset TAG
         fi
     fi
@@ -192,7 +192,7 @@ run() {
             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
         fi
-       echo "Public arvbox will use address $localip"
+        echo "Public arvbox will use address $localip"
         iptemp=$(mktemp)
         echo $localip > $iptemp
         chmod og+r $iptemp
@@ -207,7 +207,7 @@ run() {
               --publish=8001:8001
               --publish=8002:8002
               --publish=4202:4202
-             --publish=45000-45020:45000-45020"
+              --publish=45000-45020:45000-45020"
     else
         PUBLIC=""
     fi
@@ -228,7 +228,7 @@ run() {
                --name=$ARVBOX_CONTAINER \
                --privileged \
                --volumes-from $ARVBOX_CONTAINER-data \
-              --label "org.arvados.arvbox_config=$CONFIG" \
+               --label "org.arvados.arvbox_config=$CONFIG" \
                $PUBLIC \
                arvados/arvbox-demo$TAG
         updateconf
@@ -257,7 +257,7 @@ run() {
                        --detach \
                        --name=$ARVBOX_CONTAINER \
                        --privileged \
-                      "--env=SVDIR=/etc/test-service" \
+                       "--env=SVDIR=/etc/test-service" \
                        arvados/arvbox-dev$TAG
 
                 docker exec -ti \
@@ -271,10 +271,10 @@ run() {
                        /var/lib/arvbox/service/api/run-service --only-setup
             fi
 
-           interactive=""
-           if [[ -z "$@" ]] ; then
-               interactive=--interactive
-           fi
+            interactive=""
+            if [[ -z "$@" ]] ; then
+                interactive=--interactive
+            fi
 
             docker exec -ti \
                    -e LINES=$(tput lines) \
@@ -282,32 +282,32 @@ run() {
                    -e TERM=$TERM \
                    -e WORKSPACE=/usr/src/arvados \
                    -e GEM_HOME=/var/lib/gems \
-                  -e CONFIGSRC=/var/lib/arvados/run_tests \
+                   -e CONFIGSRC=/var/lib/arvados/run_tests \
                    $ARVBOX_CONTAINER \
                    /usr/local/lib/arvbox/runsu.sh \
                    /usr/src/arvados/build/run-tests.sh \
                    --temp /var/lib/arvados/test \
-                  $interactive \
+                   $interactive \
                    "$@"
         elif [[ "$CONFIG" = devenv ]] ; then
-           if [[ $need_setup = 1 ]] ; then
-               docker_run_dev \
+            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 "$@"
+                    --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 \
@@ -318,12 +318,12 @@ run() {
             updateconf
             wait_for_arvbox
             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
-           echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
-           if [[ "$(listusers)" =~ ^\{\} ]] ; then
-               echo "No users defined, use 'arvbox adduser' to add user logins"
-           else
-               echo "Use 'arvbox listusers' to see user logins"
-           fi
+            echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
+            if [[ "$(listusers)" =~ ^\{\} ]] ; then
+                echo "No users defined, use 'arvbox adduser' to add user logins"
+            else
+                echo "Use 'arvbox listusers' to see user logins"
+            fi
         else
             echo "Unknown configuration '$CONFIG'"
         fi
@@ -337,7 +337,7 @@ update() {
     if test -n "$TAG"
     then
         if test $(echo $TAG | cut -c1-1) != '-' ; then
-           TAG=":$TAG"
+            TAG=":$TAG"
             shift
         else
             unset TAG
@@ -345,9 +345,9 @@ update() {
     fi
 
     if echo "$CONFIG" | grep 'demo$' ; then
-       docker pull arvados/arvbox-demo$TAG
+        docker pull arvados/arvbox-demo$TAG
     else
-       docker pull arvados/arvbox-dev$TAG
+        docker pull arvados/arvbox-dev$TAG
     fi
 }
 
@@ -421,22 +421,22 @@ case "$subcmd" in
 
     sh*)
         exec docker exec --interactive --tty \
-              -e LINES=$(tput lines) \
-              -e COLUMNS=$(tput cols) \
-              -e TERM=$TERM \
-              -e GEM_HOME=/var/lib/gems \
-              $ARVBOX_CONTAINER /bin/bash
+               -e LINES=$(tput lines) \
+               -e COLUMNS=$(tput cols) \
+               -e TERM=$TERM \
+               -e GEM_HOME=/var/lib/gems \
+               $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
+               -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)
@@ -463,7 +463,7 @@ case "$subcmd" in
     update)
         check $@
         stop
-       update $@
+        update $@
         run $@
         ;;
 
@@ -482,7 +482,7 @@ case "$subcmd" in
     status)
         echo "Container: $ARVBOX_CONTAINER"
         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
-           echo "Cluster id: $(getclusterid)"
+            echo "Cluster id: $(getclusterid)"
             echo "Status: running"
             echo "Container IP: $(getip)"
             echo "Published host: $(gethost)"
@@ -563,17 +563,17 @@ case "$subcmd" in
 
     clone)
         if test -n "$2" ; then
-           mkdir -p "$ARVBOX_BASE/$2"
+            mkdir -p "$ARVBOX_BASE/$2"
             cp -a "$ARVBOX_BASE/$1/passenger" \
-              "$ARVBOX_BASE/$1/gems" \
-              "$ARVBOX_BASE/$1/pip" \
-              "$ARVBOX_BASE/$1/npm" \
-              "$ARVBOX_BASE/$1/gopath" \
-              "$ARVBOX_BASE/$1/Rlibs" \
-              "$ARVBOX_BASE/$1/arvados" \
-              "$ARVBOX_BASE/$1/composer" \
-              "$ARVBOX_BASE/$1/workbench2" \
-              "$ARVBOX_BASE/$2"
+               "$ARVBOX_BASE/$1/gems" \
+               "$ARVBOX_BASE/$1/pip" \
+               "$ARVBOX_BASE/$1/npm" \
+               "$ARVBOX_BASE/$1/gopath" \
+               "$ARVBOX_BASE/$1/Rlibs" \
+               "$ARVBOX_BASE/$1/arvados" \
+               "$ARVBOX_BASE/$1/composer" \
+               "$ARVBOX_BASE/$1/workbench2" \
+               "$ARVBOX_BASE/$2"
             echo "Created new arvbox $2"
             echo "export ARVBOX_CONTAINER=$2"
         else
@@ -583,28 +583,28 @@ case "$subcmd" in
         ;;
 
     root-cert)
-       CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
-       if test -n "$1" ; then
-           CERT="$1"
-       fi
-       docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/root-cert.pem > "$CERT"
-       echo "Certificate copied to $CERT"
-       ;;
+        CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
+        if test -n "$1" ; then
+            CERT="$1"
+        fi
+        docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/root-cert.pem > "$CERT"
+        echo "Certificate copied to $CERT"
+        ;;
 
     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'
-       ;;
+        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'
+        ;;
 
     checkpoint)
-       exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec pg_dump --host=localhost --username=arvados --clean arvados_development > /var/lib/arvados/checkpoint.sql'
-       ;;
+        exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec pg_dump --host=localhost --username=arvados --clean arvados_development > /var/lib/arvados/checkpoint.sql'
+        ;;
 
     restore)
-       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 --quiet --file=/var/lib/arvados/checkpoint.sql'
-       ;;
+        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 --quiet --file=/var/lib/arvados/checkpoint.sql'
+        ;;
 
     hotreset)
-       exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash - <<EOF
+        exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash - <<EOF
 sv stop api
 sv stop controller
 sv stop websockets
@@ -627,21 +627,21 @@ sv restart keepstore0
 sv restart keepstore1
 sv restart keepproxy
 EOF
-       ;;
+        ;;
 
     adduser)
-       docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) add $@
-       docker exec $ARVBOX_CONTAINER sv restart controller
-       ;;
+        docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) add $@
+        docker exec $ARVBOX_CONTAINER sv restart controller
+        ;;
 
     removeuser)
-       docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) remove $@
-       docker exec $ARVBOX_CONTAINER sv restart controller
-       ;;
+        docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) remove $@
+        docker exec $ARVBOX_CONTAINER sv restart controller
+        ;;
 
     listusers)
-       listusers
-       ;;
+        listusers
+        ;;
 
     *)
         echo "Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html"
@@ -661,9 +661,9 @@ EOF
         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 "checkpoint         create database backup"
-       echo "restore            restore checkpoint"
-       echo "hotreset           reset database and restart API without restarting container"
+        echo "checkpoint         create database backup"
+        echo "restore            restore checkpoint"
+        echo "hotreset           reset database and restart API without restarting container"
         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"
@@ -671,12 +671,12 @@ EOF
         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 "                   change state of service inside arvbox"
         echo "clone <from> <to>  clone dev arvbox"
-       echo "adduser <username> <email>"
-       echo "                   add a user login"
-       echo "removeuser <username>"
-       echo "                   remove user login"
-       echo "listusers          list user logins"
+        echo "adduser <username> <email>"
+        echo "                   add a user login"
+        echo "removeuser <username>"
+        echo "                   remove user login"
+        echo "listusers          list user logins"
         ;;
 esac
index 815db22b4ca5f9e983af413dff93e04d3608a949..eb52ca5a780e252873739c45a2e87fa667748024 100644 (file)
@@ -2,17 +2,17 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-FROM debian:9
+FROM debian:10
 
 ENV DEBIAN_FRONTEND noninteractive
 
 RUN apt-get update && \
     apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
-    postgresql-9.6 postgresql-contrib-9.6 git build-essential runit curl libpq-dev \
-    libcurl4-openssl-dev libssl1.0-dev zlib1g-dev libpcre3-dev libpam-dev \
+    postgresql postgresql-contrib git build-essential runit curl libpq-dev \
+    libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev libpam-dev \
     openssh-server netcat-traditional \
     graphviz bzip2 less sudo virtualenv \
-    libpython-dev fuse libfuse-dev \
+    fuse libfuse-dev \
     pkg-config libattr1-dev \
     libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
     libjson-perl nginx gitolite3 lsof libreadline-dev \
@@ -20,14 +20,12 @@ RUN apt-get update && \
     linkchecker python3-virtualenv python3-venv xvfb iceweasel \
     libgnutls28-dev python3-dev vim cadaver cython gnupg dirmngr \
     libsecret-1-dev r-base r-cran-testthat libxml2-dev pandoc \
-    python3-setuptools python3-pip openjdk-8-jdk bsdmainutils net-tools \
-    ruby2.3 ruby-dev bundler shellinabox  && \
-    apt-get remove -yq libpython-dev libpython-stdlib libpython2.7 libpython2.7-dev \
-    libpython2.7-minimal libpython2.7-stdlib python2.7-minimal python2.7 && \
+    python3-setuptools python3-pip default-jdk-headless bsdmainutils net-tools \
+    ruby ruby-dev bundler shellinabox  && \
     apt-get clean
 
-ENV RUBYVERSION_MINOR 2.3
-ENV RUBYVERSION 2.3.5
+ENV RUBYVERSION_MINOR 2.5
+ENV RUBYVERSION 2.5.1
 
 # Install Ruby from source
 # RUN cd /tmp && \
@@ -40,10 +38,9 @@ ENV RUBYVERSION 2.3.5
 #  rm -rf ruby-${RUBYVERSION}
 
 ENV GEM_HOME /var/lib/gems
-ENV GEM_PATH /var/lib/gems
 ENV PATH $PATH:/var/lib/gems/bin
 
-ENV GOVERSION 1.13.6
+ENV GOVERSION 1.15.2
 
 # Install golang binary
 RUN curl -f http://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz | \
@@ -60,9 +57,9 @@ RUN apt-key add --no-tty /tmp/8D81803C0EBFCD88.asc && \
     rm -f /tmp/8D81803C0EBFCD88.asc
 
 RUN mkdir -p /etc/apt/sources.list.d && \
-    echo deb https://download.docker.com/linux/debian/ stretch stable > /etc/apt/sources.list.d/docker.list && \
+    echo deb https://download.docker.com/linux/debian/ buster stable > /etc/apt/sources.list.d/docker.list && \
     apt-get update && \
-    apt-get -yq --no-install-recommends install docker-ce=17.06.0~ce-0~debian && \
+    apt-get -yq --no-install-recommends install docker-ce=5:19.03.13~3-0~debian-buster && \
     apt-get clean
 
 RUN rm -rf /var/lib/postgresql && mkdir -p /var/lib/postgresql
@@ -117,4 +114,4 @@ ADD runit /etc/runit
 # Start the supervisor.
 ENV SVDIR /etc/service
 STOPSIGNAL SIGINT
-CMD ["/sbin/runit"]
+CMD ["/etc/runit/2"]
index e81e8108e249fc7215c4ca19c4e25a4bb81efbd9..185467cf7de8d7d5b599f714bb4771090e05abb0 100644 (file)
@@ -2,10 +2,9 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-
+export DEBIAN_FRONTEND=noninteractive
 export PATH=${PATH}:/usr/local/go/bin:/var/lib/gems/bin
 export GEM_HOME=/var/lib/gems
-export GEM_PATH=/var/lib/gems
 export npm_config_cache=/var/lib/npm
 export npm_config_cache_min=Infinity
 export R_LIBS=/var/lib/Rlibs
@@ -60,6 +59,10 @@ fi
 
 run_bundler() {
     if test -f Gemfile.lock ; then
+        # The 'gem install bundler line below' is cf.
+        # https://bundler.io/blog/2019/05/14/solutions-for-cant-find-gem-bundler-with-executable-bundle.html,
+        # until we get bundler 2.7.10/3.0.0 or higher
+        gem install bundler --no-document -v "$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1|tr -d ' ')"
         frozen=--frozen
     else
         frozen=""
@@ -73,8 +76,8 @@ run_bundler() {
     #         flock /var/lib/gems/gems.lock gem install --verbose --no-document bundler --version ${bundleversion}
     #     fi
     # fi
-    if ! flock /var/lib/gems/gems.lock bundler install --verbose --path $GEM_HOME --local --no-deployment $frozen "$@" ; then
-        flock /var/lib/gems/gems.lock bundler install --verbose --path $GEM_HOME --no-deployment $frozen "$@"
+    if ! flock /var/lib/gems/gems.lock bundler install --verbose --local --no-deployment $frozen "$@" ; then
+        flock /var/lib/gems/gems.lock bundler install --verbose --no-deployment $frozen "$@"
     fi
 }
 
index 58fb413582e0a513c1819f66a36ccf47a3f36306..de1e7bba9606696d41fbc309f706a9a944888d49 100755 (executable)
@@ -46,7 +46,6 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     cat <<EOF > /etc/profile.d/paths.sh
 export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/go/bin:/var/lib/gems/bin:$(ls -d /usr/local/node-*)/bin
 export GEM_HOME=/var/lib/gems
-export GEM_PATH=/var/lib/gems
 export npm_config_cache=/var/lib/npm
 export npm_config_cache_min=Infinity
 export R_LIBS=/var/lib/Rlibs
index a0771aa6a04a9ba007b49c85e298f8f44c9cc7d6..f2377a0c2dd7a544cb0a5cf87318bada12b045e1 100755 (executable)
@@ -6,7 +6,7 @@
 exec 2>&1
 set -eux -o pipefail
 
-PGVERSION=9.6
+PGVERSION=11
 
 if ! test -d /var/lib/postgresql/$PGVERSION/main ; then
     /usr/lib/postgresql/$PGVERSION/bin/initdb --locale=en_US.UTF-8 -D /var/lib/postgresql/$PGVERSION/main
index 1ec225ca128c60c2587ebcd950a7661f1ce4aa12..d66bf315b12752338eed263aec2e3eff0218397e 100755 (executable)
@@ -20,20 +20,6 @@ ln -sf /usr/src/arvados/sdk/cli/binstubs/arv /usr/local/bin/arv
 
 export PYCMD=python3
 
-# Need to install the upstream version of pip because the python-pip package
-# shipped with Debian 9 is patched to change behavior in a way that breaks our
-# use case.
-# See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=876145
-# When a non-root user attempts to install system packages, it makes the
-# --ignore-installed flag the default (and there is no way to turn it off),
-# this has the effect of making it very hard to share dependencies shared among
-# multiple packages, because it will blindly install the latest version of each
-# dependency requested by each package, even if a compatible package version is
-# already installed.
-if ! pip3 install --no-index --find-links /var/lib/pip pip==9.0.3 ; then
-    pip3 install pip==9.0.3
-fi
-
 pip_install wheel
 
 cd /usr/src/arvados/sdk/python