Merge branch '16809-s3-v4-signature'
authorTom Clegg <tom@tomclegg.ca>
Tue, 6 Oct 2020 17:56:07 +0000 (13:56 -0400)
committerTom Clegg <tom@tomclegg.ca>
Tue, 6 Oct 2020 17:56:07 +0000 (13:56 -0400)
closes #16809

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

129 files changed:
.licenseignore
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/controllers/trash_items_controller.rb
apps/workbench/app/models/container_request.rb
apps/workbench/app/models/user.rb
apps/workbench/app/views/work_units/_show_component.html.erb
build/run-library.sh
doc/_config.yml
doc/_includes/_install_ruby_and_bundler.liquid
doc/admin/collection-versioning.html.textile.liquid
doc/admin/federation.html.textile.liquid
doc/admin/upgrading.html.textile.liquid
doc/admin/user-management-cli.html.textile.liquid
doc/api/methods/links.html.textile.liquid
doc/api/tokens.html.textile.liquid
doc/architecture/Arvados_arch.odg
doc/architecture/federation.html.textile.liquid
doc/images/Arvados_arch.svg
doc/install/install-manual-prerequisites.html.textile.liquid
doc/sdk/cli/reference.html.textile.liquid
lib/cloud/cloudtest/tester.go
lib/config/config.default.yml
lib/config/export.go
lib/config/generated_config.go
lib/controller/federation/conn.go
lib/controller/federation/login_test.go
lib/controller/federation/user_test.go
lib/controller/localdb/login.go
lib/controller/localdb/login_testuser.go
lib/crunchrun/logging.go
lib/dispatchcloud/container/queue.go
lib/dispatchcloud/test/queue.go
lib/install/deps.go
lib/pam/pam-configs-arvados
sdk/R/DESCRIPTION
sdk/R/R/Arvados.R
sdk/R/R/ArvadosFile.R
sdk/R/R/Collection.R
sdk/R/R/CollectionTree.R
sdk/R/R/HttpParser.R
sdk/R/R/HttpRequest.R
sdk/R/R/RESTService.R
sdk/R/R/Subcollection.R
sdk/R/R/autoGenAPI.R
sdk/R/README.Rmd
sdk/R/tests/testthat/test-ArvadosFile.R
sdk/R/tests/testthat/test-Collection.R
sdk/R/tests/testthat/test-CollectionTree.R
sdk/R/tests/testthat/test-HttpParser.R
sdk/R/tests/testthat/test-HttpRequest.R
sdk/R/tests/testthat/test-RESTService.R
sdk/R/tests/testthat/test-Subcollection.R
sdk/cwl/arvados_cwl/__init__.py
sdk/cwl/arvados_cwl/arvcontainer.py
sdk/cwl/arvados_cwl/executor.py
sdk/cwl/arvados_cwl/runner.py
sdk/cwl/test_with_arvbox.sh
sdk/cwl/tests/test_submit.py
sdk/dev-jobs.dockerfile
sdk/go/arvados/config.go
sdk/go/arvados/fs_base.go
sdk/go/arvados/fs_collection.go
sdk/go/health/handler_test.go
sdk/go/httpserver/logger.go
sdk/go/keepclient/keepclient.go
sdk/go/keepclient/keepclient_test.go
sdk/go/keepclient/support.go
sdk/go/manifest/manifest.go
sdk/python/arvados/commands/run.py
sdk/python/tests/fed-migrate/fed-migrate.cwl
sdk/python/tests/fed-migrate/superuser-tok.cwl
services/api/app/controllers/arvados/v1/collections_controller.rb
services/api/app/controllers/arvados/v1/users_controller.rb
services/api/app/models/api_client.rb
services/api/app/models/api_client_authorization.rb
services/api/app/models/arvados_model.rb
services/api/app/models/database_seeds.rb
services/api/app/models/user.rb
services/api/app/views/user_notifier/account_is_setup.text.erb
services/api/config/arvados_config.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/links.yml
services/api/test/fixtures/logs.yml
services/api/test/functional/arvados/v1/collections_controller_test.rb
services/api/test/functional/arvados/v1/users_controller_test.rb
services/api/test/integration/remote_user_test.rb
services/api/test/unit/api_client_test.rb
services/api/test/unit/log_test.rb
services/api/test/unit/permission_test.rb
services/api/test/unit/user_notifier_test.rb
services/keep-web/cache.go
services/keep-web/s3.go
services/keep-web/s3_test.go
services/keepproxy/keepproxy.go
services/keepstore/volume.go
tools/arvbox/bin/arvbox
tools/arvbox/lib/arvbox/docker/Dockerfile.base
tools/arvbox/lib/arvbox/docker/Dockerfile.demo
tools/arvbox/lib/arvbox/docker/Dockerfile.dev
tools/arvbox/lib/arvbox/docker/api-setup.sh
tools/arvbox/lib/arvbox/docker/cluster-config.sh
tools/arvbox/lib/arvbox/docker/common.sh
tools/arvbox/lib/arvbox/docker/createusers.sh
tools/arvbox/lib/arvbox/docker/devenv.sh
tools/arvbox/lib/arvbox/docker/go-setup.sh
tools/arvbox/lib/arvbox/docker/keep-setup.sh
tools/arvbox/lib/arvbox/docker/runit/2
tools/arvbox/lib/arvbox/docker/runsu.sh
tools/arvbox/lib/arvbox/docker/service/api/run-service
tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service
tools/arvbox/lib/arvbox/docker/service/certificate/run
tools/arvbox/lib/arvbox/docker/service/controller/run
tools/arvbox/lib/arvbox/docker/service/crunch-dispatch-local/run-service
tools/arvbox/lib/arvbox/docker/service/gitolite/run-service
tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service
tools/arvbox/lib/arvbox/docker/service/nginx/run
tools/arvbox/lib/arvbox/docker/service/postgres/run
tools/arvbox/lib/arvbox/docker/service/postgres/run-service
tools/arvbox/lib/arvbox/docker/service/ready/run-service
tools/arvbox/lib/arvbox/docker/service/vm/run
tools/arvbox/lib/arvbox/docker/service/vm/run-service
tools/arvbox/lib/arvbox/docker/service/websockets/run
tools/arvbox/lib/arvbox/docker/service/workbench/run
tools/arvbox/lib/arvbox/docker/service/workbench/run-service
tools/arvbox/lib/arvbox/docker/service/workbench2/run-service
tools/arvbox/lib/arvbox/docker/waitforpostgres.sh

index 81f6b7181d2083ff2b84b3b5ec0e88168d58ca4b..490c8447c0b48b75d1e8ba6b8d95055a49b3e179 100644 (file)
@@ -82,3 +82,6 @@ sdk/java-v2/settings.gradle
 sdk/cwl/tests/wf/feddemo
 go.mod
 go.sum
+sdk/python/tests/fed-migrate/CWLFile
+sdk/python/tests/fed-migrate/*.cwl
+sdk/python/tests/fed-migrate/*.cwlex
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 12ef20aa664a337998c1fc5980cea350ece1e982..d8f7ae62c8591e6a218c659c64de861aafa05456 100644 (file)
@@ -95,12 +95,12 @@ class TrashItemsController < ApplicationController
         owner_uuids = @objects.collect(&:owner_uuid).uniq
         @owners = {}
         @not_trashed = {}
-        Group.filter([["uuid", "in", owner_uuids]]).with_count("none").include_trash(true).each do |grp|
-          @owners[grp.uuid] = grp
-        end
-        User.filter([["uuid", "in", owner_uuids]]).with_count("none").include_trash(true).each do |grp|
-          @owners[grp.uuid] = grp
-          @not_trashed[grp.uuid] = true
+        [Group, User].each do |owner_class|
+          owner_class.filter([["uuid", "in", owner_uuids]]).with_count("none")
+            .include_trash(true).fetch_multiple_pages(false)
+            .each do |owner|
+            @owners[owner.uuid] = owner
+          end
         end
         Group.filter([["uuid", "in", owner_uuids]]).with_count("none").select([:uuid]).each do |grp|
           @not_trashed[grp.uuid] = true
index 3c08d94989e0eba7231fb8db6b7318aa693e0bfe..48920c55e75bb17b286b16c78e4fcf7a0cf2e596 100644 (file)
@@ -15,6 +15,10 @@ class ContainerRequest < ArvadosBase
     true
   end
 
+  def self.copies_to_projects?
+    false
+  end
+
   def work_unit(label=nil, child_objects=nil)
     ContainerWorkUnit.new(self, label, self.uuid, child_objects=child_objects)
   end
index 34e8181515c887fbe9e09659d09ebee4ab40f24f..c4b273c6b81e81cbcccd0034ee1aff1bf5a07424 100644 (file)
@@ -110,6 +110,6 @@ class User < ArvadosBase
   end
 
   def self.creatable?
-    current_user and current_user.is_admin
+    current_user.andand.is_admin
   end
 end
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 df551455c12dc8890a326f38b2e86f4b93adb4db..bd150e6a9b36ae96ed57792f2c7f79c51d21fcae 100755 (executable)
@@ -210,7 +210,7 @@ package_go_so() {
         "$WORKSPACE/apache-2.0.txt=/usr/share/doc/$pkg/apache-2.0.txt"
     )
     if [[ -e "$WORKSPACE/$src_path/pam-configs-arvados" ]]; then
-        fpmargs+=("$WORKSPACE/$src_path/pam-configs-arvados=/usr/share/pam-configs/arvados-go")
+        fpmargs+=("$WORKSPACE/$src_path/pam-configs-arvados=/usr/share/doc/$pkg/pam-configs-arvados-go")
     fi
     if [[ -e "$WORKSPACE/$src_path/README" ]]; then
         fpmargs+=("$WORKSPACE/$src_path/README=/usr/share/doc/$pkg/README")
index 44f8112c14f95cca2270f02c0495bb55a152693a..97db92f18c84dbb3d023dd072f951b62173bde2a 100644 (file)
@@ -219,14 +219,14 @@ navbar:
       - install/install-keep-balance.html.textile.liquid
     - User interface:
       - install/setup-login.html.textile.liquid
+      - install/install-ws.html.textile.liquid
       - install/install-workbench-app.html.textile.liquid
       - install/install-workbench2-app.html.textile.liquid
       - install/install-composer.html.textile.liquid
     - Additional services:
-      - install/install-ws.html.textile.liquid
-      - install/install-arv-git-httpd.html.textile.liquid
       - install/install-shell-server.html.textile.liquid
       - install/install-webshell.html.textile.liquid
+      - install/install-arv-git-httpd.html.textile.liquid
     - Containers API:
       - install/install-jobs-image.html.textile.liquid
       - install/crunch2-cloud/install-compute-node.html.textile.liquid
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 f67f4ad9832ed8b81048557aa599c3c10519f241..29b0bcd506a81ea186d87fb96cf0a2553b744f3e 100644 (file)
@@ -32,7 +32,7 @@ There are 2 configuration settings in the @Collections@ section of @config.yml@
       PreserveVersionIfIdle: -1s
 </pre>
 
-Note that if you set @collection_versioning@ to @false@ after being enabled, old versions will still be accessible, but further changes will not be versioned.
+Note that if you set @CollectionVersioning@ to @false@ after being enabled, old versions will still be accessible, but further changes will not be versioned.
 
 h3. Using collection versioning
 
index 3726a6d96c798a11dad9a3359ca389fe42b247b6..eb4a451a891e4151b016f5d9d7edf6ae0d191c90 100644 (file)
@@ -38,13 +38,17 @@ Similar settings should be added to @clsr2@ & @clsr3@ hosts, so that all cluster
 
 The @ActivateUsers@ setting indicates whether users from a given cluster are automatically activated or they require manual activation.  User activation is covered in more detail in the "user activation section":{{site.baseurl}}/admin/activation.html.  In the current example, users from @clsr2@ would be automatically, activated, but users from @clsr3@ would require an admin to activate the account.
 
-h2(#LoginCluster). Federation user management
+h2(#LoginCluster). User management
 
 A federation of clusters can be configured to use a separate user database per cluster, or delegate a central cluster to manage the database.
 
-If clusters belong to separate organizations, each cluster will have its own user database for the members of that organization.  Through federation, a user from one organization can be granted access to the cluster of another organization.  The admin of the second cluster controls access on a individual basis by choosing to activate or deactivate accounts from other organizations (with the default policy the value of  @ActivateUsers@).
+h3. Peer federation
 
-On the other hand, if all clusters belong to the same organization, and users in that organization should have access to all the clusters, user management can be simplified by setting the @LoginCluster@ which manages the user database used by all other clusters in the federation.  To do this, choose one cluster in the federation which will be the 'login cluster'.  Set the the @Login.LoginCluster@ configuration value on all clusters in the federation to the cluster id of the login cluster.  After setting @LoginCluster@, restart arvados-api-server and arvados-controller.
+If clusters belong to separate organizations, each cluster will have its own user database for the members of that organization.  Through federation, a user from one organization can be granted access to the cluster of another organization.  The admin of the second cluster can control access on a individual basis by choosing to activate or deactivate accounts from other organizations.
+
+h3. Centralized (LoginCluster) federation
+
+If all clusters belong to the same organization, and users in that organization should have access to all the clusters, user management can be simplified by setting the @LoginCluster@ which manages the user database used by all other clusters in the federation.  To do this, choose one cluster in the federation which will be the 'login cluster'.  Set the the @Login.LoginCluster@ configuration value on all clusters in the federation to the cluster id of the login cluster.  After setting @LoginCluster@, restart arvados-api-server and arvados-controller.
 
 <pre>
 Clusters:
@@ -53,12 +57,33 @@ Clusters:
       LoginCluster: clsr1
 </pre>
 
-The @LoginCluster@ configuration redirects all user logins to the LoginCluster, and the LoginCluster will issue API tokens which are valid on any cluster in the federation.  Users are activated or deactivated across the entire federation based on their status on the master cluster.
+The @LoginCluster@ configuration redirects all user logins to the LoginCluster, and the LoginCluster will issue API tokens which will be accepted by the federation.  Users are activated or deactivated across the entire federation based on their status on the master cluster.
 
-Note: tokens issued by the master cluster need to be periodically re-validated when used on other clusters in the federation.  The period between revalidation attempts is configured with @Login.RemoteTokenRefresh@.  The default is 5 minutes.  A longer period reduces overhead from validating tokens, but means it will take longer for other clusters to notice when a token has been revoked or a user has changed status (being activated/deactivated, admin flag changed).
+Note: tokens issued by the master cluster need to be periodically re-validated when used on other clusters in the federation.  The period between revalidation attempts is configured with @Login.RemoteTokenRefresh@.  The default is 5 minutes.  A longer period reduces overhead from validating tokens, but means it may take longer for other clusters to notice when a token has been revoked or a user has changed status (being activated/deactivated, admin flag changed).
 
 To migrate users of existing clusters with separate user databases to use a single LoginCluster, use "arv-federation-migrate":merge-remote-account.html .
 
+h2. Groups
+
+In order for a user to see (and be able to share with) other users, the admin needs to create a "can_read" permission link from the user to either the "All users" group, or another group that grants visibility to a subset of users.
+
+In a peer federation, this means that for a user that has joined a second cluster, that user needs to be added to the "All users" group on the second cluster as well, to be able to share with other users.
+
+In a LoginCluster federation, all visibility of users to share with other users is set by the LoginCluster.  It is not necessary to add users to "All users" on the other clusters.
+
+h3. Trusted clients
+
+When a cluster is configured to use a LoginCluster, the login flow goes to the LoginCluster to log in and issue a token, then returns the user to the starting workbench.  In this case, you want to configure the LoginCluster to "trust" the workbench instances associated with the other clusters.
+
+<pre>
+Clusters:
+  clsr1:
+    Login:
+      TrustedClients:
+        "https://workbench.cluster2.com": {}
+        "https://workbench.cluster3.com": {}
+</pre>
+
 h2. Testing
 
 Following the above example, let's suppose @clsr1@ is our "home cluster", that is to say, we use our @clsr1@ user account as our federated identity and both @clsr2@ and @clsr3@ remote clusters are set up to allow users from @clsr1@ and to auto-activate them. The first thing to do would be to log into a remote workbench using the local user token. This can be done following these steps:
index 061b68fa5d27b766e7d45bd0c08750fed210f5dd..de700d5598083e28fe2a8c5a333c1bb2b143f7bb 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,18 @@ 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-28)
 
 "Upgrading from 2.0.0":#v2_0_0
 
+h3. LoginCluster conflicts with other Login providers
+
+A satellite cluster that delegates its user login to a central user database must only have `Login.LoginCluster` set, or it will return an error.  This is a change in behavior, previously it would return an error if another login provider was _not_ configured, even though the provider would never be used.
+
+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 +96,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 6892176604a91346fc64eea037820f0c1262e3e6..8cebf02cdc10d85df1387cc2a1a7d86c6fb1ce4c 100644 (file)
@@ -85,6 +85,52 @@ To get the token string, combine the values of @uuid@ and @api_token@ in the for
 ARVADOS_API_TOKEN=v2/zzzzz-gj3su-yyyyyyyyyyyyyyy/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 </pre>
 
+h3(#delete-token). Delete a token
+
+If you need to revoke a token, for example the token is leaked to an unauthorized party, you can delete the token at the command line.
+
+1. First, determine the token UUID.  If it is a "v2" format token (starts with "v2/") then the token UUID is middle section between the two slashes.   For example:
+
+<pre>
+v2/zzzzz-gj3su-yyyyyyyyyyyyyyy/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+</pre>
+
+the UUID is "zzzzz-gj3su-yyyyyyyyyyyyyyy" and you can skip to the next step.
+
+If you have a "bare" token (only the secret part) then, as an admin, you need to query the token to get the uuid:
+
+<pre>
+$ ARVADOS_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx arv api_client_authorization current
+{
+ "href":"/api_client_authorizations/x33hz-gj3su-fk8nbj4byptz6ma",
+ "kind":"arvados#apiClientAuthorization",
+ "etag":"77wktnitqeelbgb4riv84zi2q",
+ "uuid":"zzzzz-gj3su-yyyyyyyyyyyyyyy",
+ "owner_uuid":"zzzzz-tpzed-j8w1ymjsn4vf4v4",
+ "created_at":"2020-09-25T15:19:48.606984000Z",
+ "modified_by_client_uuid":null,
+ "modified_by_user_uuid":null,
+ "modified_at":null,
+ "user_id":3,
+ "api_client_id":1,
+ "api_token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "created_by_ip_address":null,
+ "default_owner_uuid":null,
+ "expires_at":null,
+ "last_used_at":null,
+ "last_used_by_ip_address":null,
+ "scopes":[
+  "all"
+ ]
+}
+</pre>
+
+2. Now use the token to delete itself:
+
+<pre>
+$ ARVADOS_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx arv api_client_authorization delete --uuid zzzzz-gj3su-yyyyyyyyyyyyyyy
+</pre>
+
 h2. Adding Permissions
 
 h3. VM login
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 1846d60b0ec5f87831e0a3912b746cc1c5c34cca..67e66eecec2bba6f7f234d06e328a0a5bc116691 100644 (file)
@@ -43,7 +43,7 @@ API clients may be marked as "trusted" by making an API call to create or update
 
 A authorization token which is not associated with a trusted client may only use the @current@ method to query its own api_client_authorization object.  The "untrusted" token is forbidden performing any other operations on API client authorizations, such as listing other authorizations or creating new authorizations.
 
-Authorization tokens which are not issued via the browser login flow (created directly via the API) will not have an associated api client.  This means authorization tokens created via the API are always "untrusted".
+Authorization tokens which are not issued via the browser login flow (created directly via the API) inherit the api client of the token used to create them.  They will always be "trusted" because untrusted API clients cannot create tokens.
 
 h2(#scopes). Scopes
 
index 8b363c171adb74d47d579682c53da9a090628e23..03b9f3d353868b61c5e6d0848ec7181e7b7a4858 100644 (file)
Binary files a/doc/architecture/Arvados_arch.odg and b/doc/architecture/Arvados_arch.odg differ
index 78aa4e16deff226b1dfa1d5f7739826c6cb0a823..7512828430fd821696d46fad2631b51d4edb9599 100644 (file)
@@ -47,9 +47,9 @@ In this example, the cluster @clsr1@ is configured to contact @api.cluster2.com@
 
 h2(#identity). Identity
 
-A federated user has a single identity across the cluster federation.  This identity is a user account on a specific "home cluster".  When arvados-controller contacts a remote cluster, the remote cluster verifies the user's identity (see below) and then creates a mirror of the user account with the same uuid of the user's home cluster.  On the remote cluster, permissions can then be granted to the federated user, and the federated user can create and own objects.
+The goal is for a federated user to have a single identity across the cluster federation.  This identity is a user account on a specific "home cluster".  When arvados-controller contacts a remote cluster, the remote cluster verifies the user's identity (see below) and then creates a mirror of the user account with the same uuid of the user's home cluster.  On the remote cluster, permissions can then be granted to the federated user, and the federated user can create and own objects.
 
-h3. Authenticating remote users with salted tokens
+h3. Peer federation: Authenticating remote users with salted tokens
 
 When making a request to the home cluster, authorization is established by looking up the API token in the @api_client_authorizations@ table to determine the user identity.  When making a request to a remote cluster, we need to provide an API token which can be used to establish the user's identity.  The remote cluster will connect back to the home cluster to determine if the token valid and the user it corresponds to.  However, we do not want to send along the same API token used for the original request.  If the remote cluster is malicious or compromised, sending along user's regular token would compromise the user account on the home cluster.  Instead, the controller sends a "salted token".  The salted token is restricted to only to fetching the user account and group membership.  The salted token consists of the uuid of the token in @api_client_authorizations@ and the SHA1 HMAC of the original token and the cluster id of remote cluster.  To verify the token, the remote cluster contacts the home cluster and provides the token uuid, the hash, and its cluster id.  The home cluster uses the uuid to look up the token re-computes the SHA1 HMAC of the original token and cluster id.  If that hash matches, then the token is valid.  To avoid having to re-validate the token on every request, it is cached for a short period.
 
@@ -59,6 +59,10 @@ The security properties of this scheme are:
 * Revoking a token on the home cluster also revokes it for remote clusters (after the cache period)
 * A salted token given to a malicious/compromised cluster cannot be used to gain access to the user account on another remote cluster
 
+h3. LoginCluster federation: Centralized user database
+
+In a LoginCluster federation, there is a central "home" called the LoginCluster, and one or more "satellite" clusters.  The satellite clusters delegate their user management to the LoginCluster.  Unlike the peer federation, satellite clusters implicitly trust the home cluster, so the "salted token" scheme is not used.  Users arriving at a satellite cluster are redirected to the home cluster for login, the user token is issued by the LoginCluster, and then the user is sent back to the satellite cluster.   Tokens issued by the LoginCluster are accepted by all clusters in the federation.  All requests for user records on a satellite cluster is forwarded to the LoginCluster.
+
 h2(#retrieval). Federated records
 
 !(full-width){{site.baseurl}}/images/arvados_federation.svg!
index 76804701a33a4cb416870ad5d5884435bf858066..24f1f5a1d515f06ac0123dda0ae00df84ca6b9d9 100644 (file)
   <font id="EmbeddedFont_1" horiz-adv-x="2048">
    <font-face font-family="Liberation Sans embedded" units-per-em="2048" font-weight="normal" font-style="normal" ascent="1852" descent="423"/>
    <missing-glyph horiz-adv-x="2048" d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"/>
-   <glyph unicode="y" horiz-adv-x="1059" d="M 604,1 C 579,-64 553,-123 527,-175 500,-227 471,-272 438,-309 405,-346 369,-374 329,-394 289,-413 243,-423 191,-423 168,-423 147,-423 128,-423 109,-423 88,-420 67,-414 L 67,-279 C 80,-282 94,-284 110,-284 126,-284 140,-284 151,-284 204,-284 253,-264 298,-225 343,-186 383,-124 417,-38 L 434,5 5,1082 197,1082 425,484 C 432,466 440,442 451,412 461,382 471,352 482,322 492,292 501,265 509,241 517,217 522,202 523,196 525,203 530,218 538,240 545,261 554,285 564,312 573,339 583,366 593,393 603,420 611,444 618,464 L 830,1082 1020,1082 604,1 Z"/>
-   <glyph unicode="x" horiz-adv-x="1033" d="M 801,0 L 510,444 217,0 23,0 408,556 41,1082 240,1082 510,661 778,1082 979,1082 612,558 1002,0 801,0 Z"/>
-   <glyph unicode="w" horiz-adv-x="1535" d="M 1174,0 L 965,0 792,698 C 787,716 781,738 776,765 770,792 764,818 759,843 752,872 746,903 740,934 734,904 728,874 721,845 716,820 710,793 704,766 697,739 691,715 686,694 L 508,0 300,0 -3,1082 175,1082 358,347 C 363,332 367,313 372,291 377,268 381,246 386,225 391,200 396,175 401,149 406,174 412,199 418,223 423,244 429,265 434,286 439,307 444,325 448,339 L 644,1082 837,1082 1026,339 C 1031,322 1036,302 1041,280 1046,258 1051,237 1056,218 1061,195 1067,172 1072,149 1077,174 1083,199 1088,223 1093,244 1098,265 1103,288 1108,310 1112,330 1117,347 L 1308,1082 1484,1082 1174,0 Z"/>
-   <glyph unicode="v" horiz-adv-x="1059" d="M 613,0 L 400,0 7,1082 199,1082 437,378 C 442,363 447,346 454,325 460,304 466,282 473,259 480,236 486,215 492,194 497,173 502,155 506,141 510,155 515,173 522,194 528,215 534,236 541,258 548,280 555,302 562,323 569,344 575,361 580,376 L 826,1082 1017,1082 613,0 Z"/>
-   <glyph unicode="u" horiz-adv-x="901" d="M 314,1082 L 314,396 C 314,343 318,299 326,264 333,229 346,200 363,179 380,157 403,142 432,133 460,124 495,119 537,119 580,119 618,127 653,142 687,157 716,178 741,207 765,235 784,270 797,312 810,353 817,401 817,455 L 817,1082 997,1082 997,228 C 997,205 997,181 998,156 998,131 998,107 999,85 1000,62 1000,43 1001,27 1002,11 1002,3 1003,3 L 833,3 C 832,6 832,15 831,30 830,44 830,61 829,79 828,98 827,117 826,136 825,156 825,172 825,185 L 822,185 C 805,154 786,125 765,100 744,75 720,53 693,36 666,18 634,4 599,-6 564,-15 523,-20 476,-20 416,-20 364,-13 321,2 278,17 242,39 214,70 186,101 166,140 153,188 140,236 133,294 133,361 L 133,1082 314,1082 Z"/>
-   <glyph unicode="t" horiz-adv-x="531" d="M 554,8 C 527,1 499,-5 471,-10 442,-14 409,-16 372,-16 228,-16 156,66 156,229 L 156,951 31,951 31,1082 163,1082 216,1324 336,1324 336,1082 536,1082 536,951 336,951 336,268 C 336,216 345,180 362,159 379,138 408,127 450,127 467,127 484,128 501,131 517,134 535,137 554,141 L 554,8 Z"/>
-   <glyph unicode="s" horiz-adv-x="927" d="M 950,299 C 950,248 940,203 921,164 901,124 872,91 835,64 798,37 752,16 698,2 643,-13 581,-20 511,-20 448,-20 392,-15 342,-6 291,4 247,20 209,41 171,62 139,91 114,126 88,161 69,203 57,254 L 216,285 C 231,227 263,185 311,158 359,131 426,117 511,117 550,117 585,120 618,125 650,130 678,140 701,153 724,166 743,183 756,205 769,226 775,253 775,285 775,318 767,345 752,366 737,387 715,404 688,418 661,432 628,444 589,455 550,465 507,476 460,489 417,500 374,513 331,527 288,541 250,560 216,583 181,606 153,634 132,668 111,702 100,745 100,796 100,895 135,970 206,1022 276,1073 378,1099 513,1099 632,1099 727,1078 798,1036 868,994 912,927 931,834 L 769,814 C 763,842 752,866 736,885 720,904 701,919 678,931 655,942 630,951 602,956 573,961 544,963 513,963 432,963 372,951 333,926 294,901 275,864 275,814 275,785 282,761 297,742 311,723 331,707 357,694 382,681 413,669 449,660 485,650 525,640 568,629 597,622 626,614 656,606 686,597 715,587 744,576 772,564 799,550 824,535 849,519 870,500 889,478 908,456 923,430 934,401 945,372 950,338 950,299 Z"/>
-   <glyph unicode="r" horiz-adv-x="556" d="M 142,0 L 142,830 C 142,853 142,876 142,900 141,923 141,946 140,968 139,990 139,1011 138,1030 137,1049 137,1067 136,1082 L 306,1082 C 307,1067 308,1049 309,1030 310,1010 311,990 312,969 313,948 313,929 314,910 314,891 314,874 314,861 L 318,861 C 331,902 344,938 359,969 373,999 390,1024 409,1044 428,1063 451,1078 478,1088 505,1097 537,1102 575,1102 590,1102 604,1101 617,1099 630,1096 641,1094 648,1092 L 648,927 C 636,930 622,933 606,935 590,936 572,937 552,937 511,937 476,928 447,909 418,890 394,865 376,832 357,799 344,759 335,714 326,668 322,618 322,564 L 322,0 142,0 Z"/>
-   <glyph unicode="p" horiz-adv-x="953" d="M 1053,546 C 1053,464 1046,388 1033,319 1020,250 998,190 967,140 936,90 895,51 844,23 793,-6 730,-20 655,-20 578,-20 510,-5 452,24 394,53 350,101 319,168 L 314,168 C 315,167 315,161 316,150 316,139 316,126 317,110 317,94 317,76 318,57 318,37 318,17 318,-2 L 318,-425 138,-425 138,864 C 138,891 138,916 138,940 137,964 137,986 136,1005 135,1025 135,1042 134,1056 133,1070 133,1077 132,1077 L 306,1077 C 307,1075 308,1068 309,1057 310,1045 311,1031 312,1014 313,998 314,980 315,961 316,943 316,925 316,908 L 320,908 C 337,943 356,972 377,997 398,1021 423,1041 450,1057 477,1072 508,1084 542,1091 575,1098 613,1101 655,1101 730,1101 793,1088 844,1061 895,1034 936,997 967,949 998,900 1020,842 1033,774 1046,705 1053,629 1053,546 Z M 864,542 C 864,609 860,668 852,720 844,772 830,816 811,852 791,888 765,915 732,934 699,953 658,962 609,962 569,962 531,956 496,945 461,934 430,912 404,880 377,848 356,804 341,748 326,691 318,618 318,528 318,451 324,387 337,334 350,281 368,238 393,205 417,172 447,149 483,135 519,120 560,113 607,113 657,113 699,123 732,142 765,161 791,189 811,226 830,263 844,308 852,361 860,414 864,474 864,542 Z"/>
-   <glyph unicode="o" horiz-adv-x="980" d="M 1053,542 C 1053,353 1011,212 928,119 845,26 724,-20 565,-20 490,-20 422,-9 363,14 304,37 254,71 213,118 172,165 140,223 119,294 97,364 86,447 86,542 86,915 248,1102 571,1102 655,1102 728,1090 789,1067 850,1044 900,1009 939,962 978,915 1006,857 1025,787 1044,717 1053,635 1053,542 Z M 864,542 C 864,626 858,695 845,750 832,805 813,848 788,881 763,914 732,937 696,950 660,963 619,969 574,969 528,969 487,962 450,949 413,935 381,912 355,879 329,846 309,802 296,747 282,692 275,624 275,542 275,458 282,389 297,334 312,279 332,235 358,202 383,169 414,146 449,133 484,120 522,113 563,113 609,113 651,120 688,133 725,146 757,168 783,201 809,234 829,278 843,333 857,388 864,458 864,542 Z"/>
-   <glyph unicode="n" horiz-adv-x="900" d="M 825,0 L 825,686 C 825,739 821,783 814,818 806,853 793,882 776,904 759,925 736,941 708,950 679,959 644,963 602,963 559,963 521,956 487,941 452,926 423,904 399,876 374,847 355,812 342,771 329,729 322,681 322,627 L 322,0 142,0 142,853 C 142,876 142,900 142,925 141,950 141,974 140,996 139,1019 139,1038 138,1054 137,1070 137,1078 136,1078 L 306,1078 C 307,1075 307,1066 308,1052 309,1037 310,1021 311,1002 312,984 312,965 313,945 314,926 314,910 314,897 L 317,897 C 334,928 353,957 374,982 395,1007 419,1029 446,1047 473,1064 505,1078 540,1088 575,1097 616,1102 663,1102 723,1102 775,1095 818,1080 861,1065 897,1043 925,1012 953,981 974,942 987,894 1000,845 1006,788 1006,721 L 1006,0 825,0 Z"/>
-   <glyph unicode="m" horiz-adv-x="1456" d="M 768,0 L 768,686 C 768,739 765,783 758,818 751,853 740,882 725,904 709,925 688,941 663,950 638,959 607,963 570,963 532,963 498,956 467,941 436,926 410,904 389,876 367,847 350,812 339,771 327,729 321,681 321,627 L 321,0 142,0 142,853 C 142,876 142,900 142,925 141,950 141,974 140,996 139,1019 139,1038 138,1054 137,1070 137,1078 136,1078 L 306,1078 C 307,1075 307,1066 308,1052 309,1037 310,1021 311,1002 312,984 312,965 313,945 314,926 314,910 314,897 L 317,897 C 333,928 350,957 369,982 388,1007 410,1029 435,1047 460,1064 488,1078 521,1088 553,1097 590,1102 633,1102 715,1102 780,1086 828,1053 875,1020 908,968 927,897 L 930,897 C 946,928 964,957 984,982 1004,1007 1027,1029 1054,1047 1081,1064 1111,1078 1144,1088 1177,1097 1215,1102 1258,1102 1313,1102 1360,1095 1400,1080 1439,1065 1472,1043 1497,1012 1522,981 1541,942 1553,894 1565,845 1571,788 1571,721 L 1571,0 1393,0 1393,686 C 1393,739 1390,783 1383,818 1376,853 1365,882 1350,904 1334,925 1313,941 1288,950 1263,959 1232,963 1195,963 1157,963 1123,956 1092,942 1061,927 1035,906 1014,878 992,850 975,815 964,773 952,731 946,682 946,627 L 946,0 768,0 Z"/>
+   <glyph unicode="y" horiz-adv-x="1033" d="M 191,-425 C 142,-425 100,-421 67,-414 L 67,-279 C 92,-283 120,-285 151,-285 263,-285 352,-203 417,-38 L 434,5 5,1082 197,1082 425,484 C 428,475 432,464 437,451 442,438 457,394 482,320 507,246 521,205 523,196 L 593,393 830,1082 1020,1082 604,0 C 559,-115 518,-201 479,-258 440,-314 398,-356 351,-384 304,-411 250,-425 191,-425 Z"/>
+   <glyph unicode="x" horiz-adv-x="1006" d="M 801,0 L 510,444 217,0 23,0 408,556 41,1082 240,1082 510,661 778,1082 979,1082 612,558 1002,0 801,0 Z"/>
+   <glyph unicode="w" horiz-adv-x="1509" d="M 1174,0 L 965,0 776,765 740,934 C 734,904 725,861 712,805 699,748 631,480 508,0 L 300,0 -3,1082 175,1082 358,347 C 363,331 377,265 401,149 L 418,223 644,1082 837,1082 1026,339 1072,149 1103,288 1308,1082 1484,1082 1174,0 Z"/>
+   <glyph unicode="v" horiz-adv-x="1033" d="M 613,0 L 400,0 7,1082 199,1082 437,378 C 446,351 469,272 506,141 L 541,258 580,376 826,1082 1017,1082 613,0 Z"/>
+   <glyph unicode="u" horiz-adv-x="874" d="M 314,1082 L 314,396 C 314,325 321,269 335,230 349,191 371,162 402,145 433,128 478,119 537,119 624,119 692,149 742,208 792,267 817,350 817,455 L 817,1082 997,1082 997,231 C 997,105 999,28 1003,0 L 833,0 C 832,3 832,12 831,27 830,42 830,59 829,78 828,97 826,132 825,185 L 822,185 C 781,110 733,58 679,27 624,-4 557,-20 476,-20 357,-20 271,10 216,69 161,128 133,225 133,361 L 133,1082 314,1082 Z"/>
+   <glyph unicode="t" horiz-adv-x="531" d="M 554,8 C 495,-8 434,-16 372,-16 228,-16 156,66 156,229 L 156,951 31,951 31,1082 163,1082 216,1324 336,1324 336,1082 536,1082 536,951 336,951 336,268 C 336,216 345,180 362,159 379,138 408,127 450,127 474,127 509,132 554,141 L 554,8 Z"/>
+   <glyph unicode="s" horiz-adv-x="901" d="M 950,299 C 950,197 912,118 835,63 758,8 650,-20 511,-20 376,-20 273,2 200,47 127,91 79,160 57,254 L 216,285 C 231,227 263,185 311,158 359,131 426,117 511,117 602,117 669,131 712,159 754,187 775,229 775,285 775,328 760,362 731,389 702,416 654,438 589,455 L 460,489 C 357,516 283,542 240,568 196,593 162,624 137,661 112,698 100,743 100,796 100,895 135,970 206,1022 276,1073 378,1099 513,1099 632,1099 727,1078 798,1036 868,994 912,927 931,834 L 769,814 C 759,862 732,899 689,925 645,950 586,963 513,963 432,963 372,951 333,926 294,901 275,864 275,814 275,783 283,758 299,738 315,718 339,701 370,687 401,673 467,654 568,629 663,605 732,583 774,563 816,542 849,520 874,495 898,470 917,442 930,410 943,377 950,340 950,299 Z"/>
+   <glyph unicode="r" horiz-adv-x="530" d="M 142,0 L 142,830 C 142,906 140,990 136,1082 L 306,1082 C 311,959 314,886 314,861 L 318,861 C 347,954 380,1017 417,1051 454,1085 507,1102 575,1102 599,1102 623,1099 648,1092 L 648,927 C 624,934 592,937 552,937 477,937 420,905 381,841 342,776 322,684 322,564 L 322,0 142,0 Z"/>
+   <glyph unicode="p" horiz-adv-x="953" d="M 1053,546 C 1053,169 920,-20 655,-20 488,-20 376,43 319,168 L 314,168 C 317,163 318,106 318,-2 L 318,-425 138,-425 138,861 C 138,972 136,1046 132,1082 L 306,1082 C 307,1079 308,1070 309,1054 310,1037 312,1012 314,978 315,944 316,921 316,908 L 320,908 C 352,975 394,1024 447,1055 500,1086 569,1101 655,1101 788,1101 888,1056 954,967 1020,878 1053,737 1053,546 Z M 864,542 C 864,693 844,800 803,865 762,930 698,962 609,962 538,962 482,947 442,917 401,887 371,840 350,777 329,713 318,630 318,528 318,386 341,281 386,214 431,147 505,113 607,113 696,113 762,146 803,212 844,277 864,387 864,542 Z"/>
+   <glyph unicode="o" horiz-adv-x="980" d="M 1053,542 C 1053,353 1011,212 928,119 845,26 724,-20 565,-20 407,-20 288,28 207,125 126,221 86,360 86,542 86,915 248,1102 571,1102 736,1102 858,1057 936,966 1014,875 1053,733 1053,542 Z M 864,542 C 864,691 842,800 798,868 753,935 679,969 574,969 469,969 393,935 346,866 299,797 275,689 275,542 275,399 298,292 345,221 391,149 464,113 563,113 671,113 748,148 795,217 841,286 864,395 864,542 Z"/>
+   <glyph unicode="n" horiz-adv-x="874" d="M 825,0 L 825,686 C 825,757 818,813 804,852 790,891 768,920 737,937 706,954 661,963 602,963 515,963 447,933 397,874 347,815 322,732 322,627 L 322,0 142,0 142,851 C 142,977 140,1054 136,1082 L 306,1082 C 307,1079 307,1070 308,1055 309,1040 310,1024 311,1005 312,986 313,950 314,897 L 317,897 C 358,972 406,1025 461,1056 515,1087 582,1102 663,1102 782,1102 869,1073 924,1014 979,955 1006,857 1006,721 L 1006,0 825,0 Z"/>
+   <glyph unicode="m" horiz-adv-x="1457" d="M 768,0 L 768,686 C 768,791 754,863 725,903 696,943 645,963 570,963 493,963 433,934 388,875 343,816 321,734 321,627 L 321,0 142,0 142,851 C 142,977 140,1054 136,1082 L 306,1082 C 307,1079 307,1070 308,1055 309,1040 310,1024 311,1005 312,986 313,950 314,897 L 317,897 C 356,974 400,1027 450,1057 500,1087 561,1102 633,1102 715,1102 780,1086 828,1053 875,1020 908,968 927,897 L 930,897 C 967,970 1013,1022 1066,1054 1119,1086 1183,1102 1258,1102 1367,1102 1447,1072 1497,1013 1546,954 1571,856 1571,721 L 1571,0 1393,0 1393,686 C 1393,791 1379,863 1350,903 1321,943 1270,963 1195,963 1116,963 1055,934 1012,876 968,817 946,734 946,627 L 946,0 768,0 Z"/>
    <glyph unicode="l" horiz-adv-x="187" d="M 138,0 L 138,1484 318,1484 318,0 138,0 Z"/>
-   <glyph unicode="k" horiz-adv-x="927" d="M 816,0 L 450,494 318,385 318,0 138,0 138,1484 318,1484 318,557 793,1082 1004,1082 565,617 1027,0 816,0 Z"/>
-   <glyph unicode="j" horiz-adv-x="372" d="M 137,1312 L 137,1484 317,1484 317,1312 137,1312 Z M 317,-132 C 317,-174 314,-212 307,-247 300,-283 287,-313 269,-339 251,-365 227,-386 196,-401 165,-416 125,-423 77,-423 54,-423 32,-423 11,-423 -11,-423 -31,-421 -50,-416 L -50,-277 C -41,-278 -31,-280 -19,-281 -7,-282 3,-283 12,-283 37,-283 58,-280 75,-273 91,-266 104,-256 113,-242 122,-227 129,-209 132,-187 135,-164 137,-138 137,-107 L 137,1082 317,1082 317,-132 Z"/>
+   <glyph unicode="k" horiz-adv-x="901" d="M 816,0 L 450,494 318,385 318,0 138,0 138,1484 318,1484 318,557 793,1082 1004,1082 565,617 1027,0 816,0 Z"/>
+   <glyph unicode="j" horiz-adv-x="372" d="M 137,1312 L 137,1484 317,1484 317,1312 137,1312 Z M 317,-134 C 317,-236 297,-310 257,-356 217,-402 157,-425 77,-425 26,-425 -17,-422 -50,-416 L -50,-277 12,-283 C 58,-283 90,-271 109,-247 128,-223 137,-176 137,-107 L 137,1082 317,1082 317,-134 Z"/>
    <glyph unicode="i" horiz-adv-x="187" d="M 137,1312 L 137,1484 317,1484 317,1312 137,1312 Z M 137,0 L 137,1082 317,1082 317,0 137,0 Z"/>
-   <glyph unicode="h" horiz-adv-x="874" d="M 317,897 C 337,934 359,965 382,991 405,1016 431,1037 459,1054 487,1071 518,1083 551,1091 584,1098 622,1102 663,1102 732,1102 789,1093 834,1074 878,1055 913,1029 939,996 964,962 982,922 992,875 1001,828 1006,777 1006,721 L 1006,0 825,0 825,686 C 825,732 822,772 817,807 811,842 800,871 784,894 768,917 745,934 716,946 687,957 649,963 602,963 559,963 521,955 487,940 452,925 423,903 399,875 374,847 355,813 342,773 329,733 322,688 322,638 L 322,0 142,0 142,1484 322,1484 322,1098 C 322,1076 322,1054 321,1032 320,1010 320,990 319,971 318,952 317,937 316,924 315,911 315,902 314,897 L 317,897 Z"/>
-   <glyph unicode="g" horiz-adv-x="954" d="M 548,-425 C 486,-425 431,-419 383,-406 335,-393 294,-375 260,-352 226,-328 198,-300 177,-267 156,-234 140,-198 131,-158 L 312,-132 C 324,-182 351,-220 392,-248 433,-274 486,-288 553,-288 594,-288 631,-282 664,-271 697,-260 726,-241 749,-217 772,-191 790,-159 803,-119 816,-79 822,-30 822,27 L 822,201 820,201 C 807,174 790,148 771,123 751,98 727,75 699,56 670,37 637,21 600,10 563,-2 520,-8 472,-8 403,-8 345,4 296,27 247,50 207,84 176,130 145,176 122,233 108,302 93,370 86,449 86,539 86,626 93,704 108,773 122,842 145,901 178,950 210,998 252,1035 304,1061 355,1086 418,1099 492,1099 569,1099 635,1082 692,1047 748,1012 791,962 822,897 L 824,897 C 824,914 825,933 826,953 827,974 828,994 829,1012 830,1031 831,1046 832,1060 833,1073 835,1080 836,1080 L 1007,1080 C 1006,1074 1006,1064 1005,1050 1004,1035 1004,1018 1003,998 1002,978 1002,956 1002,932 1001,907 1001,882 1001,856 L 1001,30 C 1001,-121 964,-234 890,-311 815,-387 701,-425 548,-425 Z M 822,541 C 822,616 814,681 798,735 781,788 760,832 733,866 706,900 676,925 642,941 607,957 572,965 536,965 490,965 451,957 418,941 385,925 357,900 336,866 314,831 298,787 288,734 277,680 272,616 272,541 272,463 277,398 288,345 298,292 314,249 335,216 356,183 383,160 416,146 449,132 488,125 533,125 569,125 604,133 639,148 673,163 704,188 731,221 758,254 780,297 797,350 814,403 822,466 822,541 Z"/>
-   <glyph unicode="f" horiz-adv-x="557" d="M 361,951 L 361,0 181,0 181,951 29,951 29,1082 181,1082 181,1204 C 181,1243 185,1280 192,1314 199,1347 213,1377 233,1402 252,1427 279,1446 313,1461 347,1475 391,1482 445,1482 466,1482 489,1481 512,1479 535,1477 555,1474 572,1470 L 572,1333 C 561,1335 548,1337 533,1339 518,1340 504,1341 492,1341 465,1341 444,1337 427,1330 410,1323 396,1312 387,1299 377,1285 370,1268 367,1248 363,1228 361,1205 361,1179 L 361,1082 572,1082 572,951 361,951 Z"/>
-   <glyph unicode="e" horiz-adv-x="980" d="M 276,503 C 276,446 282,394 294,347 305,299 323,258 348,224 372,189 403,163 441,144 479,125 525,115 578,115 656,115 719,131 766,162 813,193 844,233 861,281 L 1019,236 C 1008,206 992,176 972,146 951,115 924,88 890,64 856,39 814,19 763,4 712,-12 650,-20 578,-20 418,-20 296,28 213,123 129,218 87,360 87,548 87,649 100,735 125,806 150,876 185,933 229,977 273,1021 324,1053 383,1073 442,1092 504,1102 571,1102 662,1102 738,1087 799,1058 860,1029 909,988 946,937 983,885 1009,824 1025,754 1040,684 1048,608 1048,527 L 1048,503 276,503 Z M 862,641 C 852,755 823,838 775,891 727,943 658,969 568,969 538,969 507,964 474,955 441,945 410,928 382,903 354,878 330,845 311,803 292,760 281,706 278,641 L 862,641 Z"/>
-   <glyph unicode="d" horiz-adv-x="954" d="M 821,174 C 788,105 744,55 689,25 634,-5 565,-20 484,-20 347,-20 247,26 183,118 118,210 86,349 86,536 86,913 219,1102 484,1102 566,1102 634,1087 689,1057 744,1027 788,979 821,914 L 823,914 C 823,921 823,931 823,946 822,960 822,975 822,991 821,1006 821,1021 821,1035 821,1049 821,1059 821,1065 L 821,1484 1001,1484 1001,219 C 1001,193 1001,168 1002,143 1002,119 1002,97 1003,77 1004,57 1004,40 1005,26 1006,11 1006,4 1007,4 L 835,4 C 834,11 833,20 832,32 831,44 830,58 829,73 828,89 827,105 826,123 825,140 825,157 825,174 L 821,174 Z M 275,542 C 275,467 280,403 289,350 298,297 313,253 334,219 355,184 381,159 413,143 445,127 484,119 530,119 577,119 619,127 656,142 692,157 722,182 747,217 771,251 789,296 802,351 815,406 821,474 821,554 821,631 815,696 802,749 789,802 771,844 746,877 721,910 691,933 656,948 620,962 579,969 532,969 488,969 450,961 418,946 386,931 359,906 338,872 317,838 301,794 291,740 280,685 275,619 275,542 Z"/>
-   <glyph unicode="c" horiz-adv-x="875" d="M 275,546 C 275,484 280,427 289,375 298,323 313,278 334,241 355,203 384,174 419,153 454,132 497,122 548,122 612,122 666,139 709,173 752,206 778,258 788,328 L 970,328 C 964,283 951,239 931,197 911,155 884,118 850,86 815,54 773,28 724,9 675,-10 618,-20 553,-20 468,-20 396,-6 337,23 278,52 230,91 193,142 156,192 129,251 112,320 95,388 87,462 87,542 87,615 93,679 105,735 117,790 134,839 156,881 177,922 203,957 232,986 261,1014 293,1037 328,1054 362,1071 398,1083 436,1091 474,1098 512,1102 551,1102 612,1102 666,1094 713,1077 760,1060 801,1038 836,1009 870,980 898,945 919,906 940,867 955,824 964,779 L 779,765 C 770,825 746,873 708,908 670,943 616,961 546,961 495,961 452,953 418,936 383,919 355,893 334,859 313,824 298,781 289,729 280,677 275,616 275,546 Z"/>
-   <glyph unicode="b" horiz-adv-x="953" d="M 1053,546 C 1053,169 920,-20 655,-20 573,-20 505,-5 451,25 396,54 352,102 318,168 L 316,168 C 316,150 316,132 315,113 314,94 313,77 312,61 311,45 310,31 309,19 308,8 307,2 306,2 L 132,2 C 133,8 133,18 134,32 135,47 135,64 136,84 137,104 137,126 138,150 138,174 138,199 138,225 L 138,1484 318,1484 318,1061 C 318,1041 318,1022 318,1004 317,985 317,969 316,955 315,938 315,923 314,908 L 318,908 C 351,977 396,1027 451,1057 506,1087 574,1102 655,1102 792,1102 892,1056 957,964 1021,872 1053,733 1053,546 Z M 864,540 C 864,615 859,679 850,732 841,785 826,829 805,864 784,898 758,923 726,939 694,955 655,963 609,963 562,963 520,955 484,940 447,925 417,900 393,866 368,832 350,787 337,732 324,677 318,609 318,529 318,452 324,387 337,334 350,281 368,239 393,206 417,173 447,149 483,135 519,120 560,113 607,113 651,113 689,121 721,136 753,151 780,176 801,210 822,244 838,288 849,343 859,397 864,463 864,540 Z"/>
-   <glyph unicode="a" horiz-adv-x="1060" d="M 414,-20 C 305,-20 224,9 169,66 114,124 87,203 87,303 87,375 101,434 128,480 155,526 190,562 234,588 277,614 327,632 383,642 439,652 496,657 554,657 L 797,657 797,717 C 797,762 792,800 783,832 774,863 759,889 740,908 721,928 697,942 668,951 639,960 604,965 565,965 530,965 499,963 471,958 443,953 419,944 398,931 377,918 361,900 348,878 335,855 327,827 323,793 L 135,810 C 142,853 154,892 173,928 192,963 218,994 253,1020 287,1046 330,1066 382,1081 433,1095 496,1102 569,1102 705,1102 807,1071 876,1009 945,946 979,856 979,738 L 979,272 C 979,219 986,179 1000,152 1014,125 1041,111 1080,111 1090,111 1100,112 1110,113 1120,114 1130,116 1139,118 L 1139,6 C 1116,1 1094,-3 1072,-6 1049,-9 1025,-10 1000,-10 966,-10 937,-5 913,4 888,13 868,26 853,45 838,63 826,86 818,113 810,140 805,171 803,207 L 797,207 C 778,172 757,141 734,113 711,85 684,61 653,42 622,22 588,7 549,-4 510,-15 465,-20 414,-20 Z M 455,115 C 512,115 563,125 606,146 649,167 684,194 713,226 741,259 762,294 776,332 790,371 797,408 797,443 L 797,531 600,531 C 556,531 514,528 475,522 435,517 400,506 370,489 340,472 316,449 299,418 281,388 272,349 272,300 272,241 288,195 320,163 351,131 396,115 455,115 Z"/>
-   <glyph unicode="W" horiz-adv-x="1906" d="M 1511,0 L 1283,0 1039,895 C 1032,920 1024,950 1016,985 1007,1020 1000,1053 993,1084 985,1121 977,1158 969,1196 960,1157 952,1120 944,1083 937,1051 929,1018 921,984 913,950 905,920 898,895 L 652,0 424,0 9,1409 208,1409 461,514 C 472,472 483,430 494,389 504,348 513,311 520,278 529,239 537,203 544,168 554,214 564,259 575,304 580,323 584,342 589,363 594,384 599,404 604,424 609,444 614,463 619,482 624,500 628,517 632,532 L 877,1409 1060,1409 1305,532 C 1309,517 1314,500 1319,482 1324,463 1329,444 1334,425 1339,405 1343,385 1348,364 1353,343 1357,324 1362,305 1373,260 1383,215 1393,168 1394,168 1397,180 1402,203 1407,226 1414,254 1422,289 1430,324 1439,361 1449,402 1458,442 1468,479 1478,514 L 1727,1409 1926,1409 1511,0 Z"/>
-   <glyph unicode="S" horiz-adv-x="1139" d="M 1272,389 C 1272,330 1261,275 1238,225 1215,175 1179,132 1131,96 1083,59 1023,31 950,11 877,-10 790,-20 690,-20 515,-20 378,11 280,72 182,133 120,222 93,338 L 278,375 C 287,338 302,305 321,275 340,245 367,219 400,198 433,176 473,159 522,147 571,135 629,129 697,129 754,129 806,134 853,144 900,153 941,168 975,188 1009,208 1036,234 1055,266 1074,297 1083,335 1083,379 1083,425 1073,462 1052,491 1031,520 1001,543 963,562 925,581 880,596 827,609 774,622 716,635 652,650 613,659 573,668 534,679 494,689 456,701 420,716 383,730 349,747 317,766 285,785 257,809 234,836 211,863 192,894 179,930 166,965 159,1006 159,1053 159,1120 173,1177 200,1225 227,1272 264,1311 312,1342 360,1373 417,1395 482,1409 547,1423 618,1430 694,1430 781,1430 856,1423 918,1410 980,1396 1032,1375 1075,1348 1118,1321 1152,1287 1178,1247 1203,1206 1224,1159 1239,1106 L 1051,1073 C 1042,1107 1028,1137 1011,1164 993,1191 970,1213 941,1231 912,1249 878,1263 837,1272 796,1281 747,1286 692,1286 627,1286 572,1280 528,1269 483,1257 448,1241 421,1221 394,1201 374,1178 363,1151 351,1124 345,1094 345,1063 345,1021 356,987 377,960 398,933 426,910 462,892 498,874 540,859 587,847 634,835 685,823 738,811 781,801 825,791 868,781 911,770 952,758 991,744 1030,729 1067,712 1102,693 1136,674 1166,650 1191,622 1216,594 1236,561 1251,523 1265,485 1272,440 1272,389 Z"/>
-   <glyph unicode="P" horiz-adv-x="1086" d="M 1258,985 C 1258,924 1248,867 1228,814 1207,761 1177,715 1137,676 1096,637 1046,606 985,583 924,560 854,549 773,549 L 359,549 359,0 168,0 168,1409 761,1409 C 844,1409 917,1399 979,1379 1041,1358 1093,1330 1134,1293 1175,1256 1206,1211 1227,1159 1248,1106 1258,1048 1258,985 Z M 1066,983 C 1066,1072 1039,1140 984,1187 929,1233 847,1256 738,1256 L 359,1256 359,700 746,700 C 856,700 937,724 989,773 1040,822 1066,892 1066,983 Z"/>
-   <glyph unicode="L" horiz-adv-x="900" d="M 168,0 L 168,1409 359,1409 359,156 1071,156 1071,0 168,0 Z"/>
-   <glyph unicode="I" horiz-adv-x="186" d="M 189,0 L 189,1409 380,1409 380,0 189,0 Z"/>
+   <glyph unicode="h" horiz-adv-x="874" d="M 317,897 C 356,968 402,1020 457,1053 511,1086 580,1102 663,1102 780,1102 867,1073 923,1015 978,956 1006,858 1006,721 L 1006,0 825,0 825,686 C 825,762 818,819 804,856 790,893 767,920 735,937 703,954 659,963 602,963 517,963 450,934 399,875 348,816 322,737 322,638 L 322,0 142,0 142,1484 322,1484 322,1098 C 322,1057 321,1015 319,972 316,929 315,904 314,897 L 317,897 Z"/>
+   <glyph unicode="g" horiz-adv-x="927" d="M 548,-425 C 430,-425 336,-402 266,-356 196,-309 151,-243 131,-158 L 312,-132 C 324,-182 351,-220 392,-248 433,-274 486,-288 553,-288 732,-288 822,-183 822,27 L 822,201 820,201 C 786,132 739,80 680,45 621,10 551,-8 472,-8 339,-8 242,36 180,124 117,212 86,350 86,539 86,730 120,872 187,963 254,1054 355,1099 492,1099 569,1099 635,1082 692,1047 748,1012 791,962 822,897 L 824,897 C 824,917 825,952 828,1001 831,1050 833,1077 836,1082 L 1007,1082 C 1003,1046 1001,971 1001,858 L 1001,31 C 1001,-273 850,-425 548,-425 Z M 822,541 C 822,629 810,705 786,769 762,832 728,881 685,915 641,948 591,965 536,965 444,965 377,932 335,865 293,798 272,690 272,541 272,393 292,287 331,222 370,157 438,125 533,125 590,125 640,142 684,175 728,208 762,256 786,319 810,381 822,455 822,541 Z"/>
+   <glyph unicode="f" horiz-adv-x="557" d="M 361,951 L 361,0 181,0 181,951 29,951 29,1082 181,1082 181,1204 C 181,1303 203,1374 246,1417 289,1460 356,1482 445,1482 495,1482 537,1478 572,1470 L 572,1333 C 542,1338 515,1341 492,1341 446,1341 413,1329 392,1306 371,1283 361,1240 361,1179 L 361,1082 572,1082 572,951 361,951 Z"/>
+   <glyph unicode="e" horiz-adv-x="980" d="M 276,503 C 276,379 302,283 353,216 404,149 479,115 578,115 656,115 719,131 766,162 813,193 844,233 861,281 L 1019,236 C 954,65 807,-20 578,-20 418,-20 296,28 213,123 129,218 87,360 87,548 87,727 129,864 213,959 296,1054 416,1102 571,1102 889,1102 1048,910 1048,527 L 1048,503 276,503 Z M 862,641 C 852,755 823,838 775,891 727,943 658,969 568,969 481,969 412,940 361,882 310,823 282,743 278,641 L 862,641 Z"/>
+   <glyph unicode="d" horiz-adv-x="927" d="M 821,174 C 788,105 744,55 689,25 634,-5 565,-20 484,-20 347,-20 247,26 183,118 118,210 86,349 86,536 86,913 219,1102 484,1102 566,1102 634,1087 689,1057 744,1027 788,979 821,914 L 823,914 821,1035 821,1484 1001,1484 1001,223 C 1001,110 1003,36 1007,0 L 835,0 C 833,11 831,35 829,74 826,113 825,146 825,174 L 821,174 Z M 275,542 C 275,391 295,282 335,217 375,152 440,119 530,119 632,119 706,154 752,225 798,296 821,405 821,554 821,697 798,802 752,869 706,936 633,969 532,969 441,969 376,936 336,869 295,802 275,693 275,542 Z"/>
+   <glyph unicode="c" horiz-adv-x="901" d="M 275,546 C 275,402 298,295 343,226 388,157 457,122 548,122 612,122 666,139 709,174 752,209 778,262 788,334 L 970,322 C 956,218 912,135 837,73 762,11 668,-20 553,-20 402,-20 286,28 207,124 127,219 87,359 87,542 87,724 127,863 207,959 287,1054 402,1102 551,1102 662,1102 754,1073 827,1016 900,959 945,880 964,779 L 779,765 C 770,825 746,873 708,908 670,943 616,961 546,961 451,961 382,929 339,866 296,803 275,696 275,546 Z"/>
+   <glyph unicode="b" horiz-adv-x="953" d="M 1053,546 C 1053,169 920,-20 655,-20 573,-20 505,-5 451,25 396,54 352,102 318,168 L 316,168 C 316,147 315,116 312,74 309,31 307,7 306,0 L 132,0 C 136,36 138,110 138,223 L 138,1484 318,1484 318,1061 C 318,1018 317,967 314,908 L 318,908 C 351,977 396,1027 451,1057 506,1087 574,1102 655,1102 792,1102 892,1056 957,964 1021,872 1053,733 1053,546 Z M 864,540 C 864,691 844,800 804,865 764,930 699,963 609,963 508,963 434,928 388,859 341,790 318,680 318,529 318,387 341,282 386,215 431,147 505,113 607,113 698,113 763,147 804,214 844,281 864,389 864,540 Z"/>
+   <glyph unicode="a" horiz-adv-x="1060" d="M 414,-20 C 305,-20 224,9 169,66 114,123 87,202 87,302 87,414 124,500 198,560 271,620 390,652 554,656 L 797,660 797,719 C 797,807 778,870 741,908 704,946 645,965 565,965 484,965 426,951 389,924 352,897 330,853 323,793 L 135,810 C 166,1005 310,1102 569,1102 705,1102 807,1071 876,1009 945,946 979,856 979,738 L 979,272 C 979,219 986,179 1000,152 1014,125 1041,111 1080,111 1097,111 1117,113 1139,118 L 1139,6 C 1094,-5 1047,-10 1000,-10 933,-10 885,8 855,43 824,78 807,132 803,207 L 797,207 C 751,124 698,66 637,32 576,-3 501,-20 414,-20 Z M 455,115 C 521,115 580,130 631,160 682,190 723,231 753,284 782,336 797,390 797,445 L 797,534 600,530 C 515,529 451,520 408,504 364,488 330,463 307,430 284,397 272,353 272,299 272,240 288,195 320,163 351,131 396,115 455,115 Z"/>
+   <glyph unicode="W" horiz-adv-x="1932" d="M 1511,0 L 1283,0 1039,895 C 1023,951 1000,1051 969,1196 952,1119 937,1054 925,1002 913,950 822,616 652,0 L 424,0 9,1409 208,1409 461,514 C 491,402 519,287 544,168 560,241 579,321 600,408 621,495 713,828 877,1409 L 1060,1409 1305,532 C 1342,389 1372,267 1393,168 L 1402,203 C 1420,280 1435,342 1446,391 1457,439 1551,778 1727,1409 L 1926,1409 1511,0 Z"/>
+   <glyph unicode="U" horiz-adv-x="1192" d="M 731,-20 C 616,-20 515,1 429,43 343,85 276,146 229,226 182,306 158,401 158,512 L 158,1409 349,1409 349,528 C 349,399 382,302 447,235 512,168 607,135 730,135 857,135 955,170 1026,239 1096,308 1131,408 1131,541 L 1131,1409 1321,1409 1321,530 C 1321,416 1297,318 1249,235 1200,152 1132,89 1044,46 955,2 851,-20 731,-20 Z"/>
+   <glyph unicode="S" horiz-adv-x="1192" d="M 1272,389 C 1272,259 1221,158 1120,87 1018,16 875,-20 690,-20 347,-20 148,99 93,338 L 278,375 C 299,290 345,228 414,189 483,149 578,129 697,129 820,129 916,150 983,193 1050,235 1083,297 1083,379 1083,425 1073,462 1052,491 1031,520 1001,543 963,562 925,581 880,596 827,609 774,622 716,635 652,650 541,675 456,699 399,724 341,749 295,776 262,807 229,837 203,872 186,913 168,954 159,1000 159,1053 159,1174 205,1267 298,1332 390,1397 522,1430 694,1430 854,1430 976,1406 1061,1357 1146,1308 1205,1224 1239,1106 L 1051,1073 C 1030,1148 991,1202 933,1236 875,1269 795,1286 692,1286 579,1286 493,1267 434,1230 375,1193 345,1137 345,1063 345,1020 357,984 380,956 403,927 436,903 479,884 522,864 609,840 738,811 781,801 825,791 868,781 911,770 952,758 991,744 1030,729 1067,712 1102,693 1136,674 1166,650 1191,622 1216,594 1236,561 1251,523 1265,485 1272,440 1272,389 Z"/>
+   <glyph unicode="P" horiz-adv-x="1112" d="M 1258,985 C 1258,852 1215,746 1128,667 1041,588 922,549 773,549 L 359,549 359,0 168,0 168,1409 761,1409 C 919,1409 1041,1372 1128,1298 1215,1224 1258,1120 1258,985 Z M 1066,983 C 1066,1165 957,1256 738,1256 L 359,1256 359,700 746,700 C 959,700 1066,794 1066,983 Z"/>
+   <glyph unicode="L" horiz-adv-x="927" d="M 168,0 L 168,1409 359,1409 359,156 1071,156 1071,0 168,0 Z"/>
+   <glyph unicode="I" horiz-adv-x="213" d="M 189,0 L 189,1409 380,1409 380,0 189,0 Z"/>
+   <glyph unicode="H" horiz-adv-x="1165" d="M 1121,0 L 1121,653 359,653 359,0 168,0 168,1409 359,1409 359,813 1121,813 1121,1409 1312,1409 1312,0 1121,0 Z"/>
    <glyph unicode="F" horiz-adv-x="1006" d="M 359,1253 L 359,729 1145,729 1145,571 359,571 359,0 168,0 168,1409 1169,1409 1169,1253 359,1253 Z"/>
-   <glyph unicode="E" horiz-adv-x="1112" d="M 168,0 L 168,1409 1237,1409 1237,1253 359,1253 359,801 1177,801 1177,647 359,647 359,156 1278,156 1278,0 168,0 Z"/>
-   <glyph unicode="C" horiz-adv-x="1297" d="M 792,1274 C 712,1274 641,1261 580,1234 518,1207 466,1169 425,1120 383,1071 351,1011 330,942 309,873 298,796 298,711 298,626 310,549 333,479 356,408 389,348 432,297 475,246 527,207 590,179 652,151 722,137 800,137 855,137 905,144 950,159 995,173 1035,193 1072,219 1108,245 1140,276 1169,312 1198,347 1223,387 1245,430 L 1401,352 C 1376,299 1344,250 1307,205 1270,160 1226,120 1176,87 1125,54 1068,28 1005,9 941,-10 870,-20 791,-20 677,-20 577,-2 492,35 406,71 334,122 277,187 219,252 176,329 147,418 118,507 104,605 104,711 104,821 119,920 150,1009 180,1098 224,1173 283,1236 341,1298 413,1346 498,1380 583,1413 681,1430 790,1430 940,1430 1065,1401 1166,1342 1267,1283 1341,1196 1388,1081 L 1207,1021 C 1194,1054 1176,1086 1153,1117 1130,1147 1102,1174 1068,1197 1034,1220 994,1239 949,1253 903,1267 851,1274 792,1274 Z"/>
-   <glyph unicode="A" horiz-adv-x="1350" d="M 1167,0 L 1006,412 364,412 202,0 4,0 579,1409 796,1409 1362,0 1167,0 Z M 768,1026 C 757,1053 747,1080 738,1107 728,1134 719,1159 712,1182 705,1204 699,1223 694,1238 689,1253 686,1262 685,1265 684,1262 681,1252 676,1237 671,1222 665,1203 658,1180 650,1157 641,1132 632,1105 622,1078 612,1051 602,1024 L 422,561 949,561 768,1026 Z"/>
-   <glyph unicode="3" horiz-adv-x="980" d="M 1049,389 C 1049,324 1039,267 1018,216 997,165 966,123 926,88 885,53 835,26 776,8 716,-11 648,-20 571,-20 484,-20 410,-9 351,13 291,34 242,63 203,99 164,134 135,175 116,221 97,266 84,313 78,362 L 264,379 C 269,342 279,308 294,277 308,246 327,220 352,198 377,176 407,159 443,147 479,135 522,129 571,129 662,129 733,151 785,196 836,241 862,307 862,395 862,447 851,489 828,521 805,552 776,577 742,595 707,612 670,624 630,630 589,636 552,639 518,639 L 416,639 416,795 514,795 C 548,795 583,799 620,806 657,813 690,825 721,844 751,862 776,887 796,918 815,949 825,989 825,1038 825,1113 803,1173 759,1217 714,1260 648,1282 561,1282 482,1282 418,1262 369,1221 320,1180 291,1123 283,1049 L 102,1063 C 109,1125 126,1179 153,1225 180,1271 214,1309 255,1340 296,1370 342,1393 395,1408 448,1423 504,1430 563,1430 642,1430 709,1420 766,1401 823,1381 869,1354 905,1321 941,1287 968,1247 985,1202 1002,1157 1010,1108 1010,1057 1010,1016 1004,977 993,941 982,905 964,873 940,844 916,815 886,791 849,770 812,749 767,734 715,723 L 715,719 C 772,713 821,700 863,681 905,661 940,636 967,607 994,578 1015,544 1029,507 1042,470 1049,430 1049,389 Z"/>
-   <glyph unicode="0" horiz-adv-x="980" d="M 1059,705 C 1059,570 1046,456 1021,364 995,271 960,197 916,140 871,83 819,42 759,17 699,-8 635,-20 567,-20 498,-20 434,-8 375,17 316,42 264,82 221,139 177,196 143,270 118,363 93,455 80,569 80,705 80,847 93,965 118,1058 143,1151 177,1225 221,1280 265,1335 317,1374 377,1397 437,1419 502,1430 573,1430 640,1430 704,1419 763,1397 822,1374 873,1335 917,1280 961,1225 996,1151 1021,1058 1046,965 1059,847 1059,705 Z M 876,705 C 876,817 869,910 856,985 843,1059 823,1118 797,1163 771,1207 739,1238 702,1257 664,1275 621,1284 573,1284 522,1284 478,1275 439,1256 400,1237 368,1206 342,1162 315,1117 295,1058 282,984 269,909 262,816 262,705 262,597 269,506 283,432 296,358 316,299 343,254 369,209 401,176 439,157 477,137 520,127 569,127 616,127 659,137 697,157 735,176 767,209 794,254 820,299 840,358 855,432 869,506 876,597 876,705 Z"/>
-   <glyph unicode="." horiz-adv-x="186" d="M 187,0 L 187,219 382,219 382,0 187,0 Z"/>
-   <glyph unicode="-" horiz-adv-x="504" d="M 91,464 L 91,624 591,624 591,464 91,464 Z"/>
-   <glyph unicode="," horiz-adv-x="212" d="M 385,219 L 385,51 C 385,16 384,-16 381,-46 378,-74 373,-101 366,-127 359,-151 351,-175 342,-197 332,-219 320,-241 307,-262 L 184,-262 C 214,-219 237,-175 254,-131 270,-87 278,-43 278,0 L 190,0 190,219 385,219 Z"/>
+   <glyph unicode="E" horiz-adv-x="1138" d="M 168,0 L 168,1409 1237,1409 1237,1253 359,1253 359,801 1177,801 1177,647 359,647 359,156 1278,156 1278,0 168,0 Z"/>
+   <glyph unicode="C" horiz-adv-x="1324" d="M 792,1274 C 636,1274 515,1224 428,1124 341,1023 298,886 298,711 298,538 343,400 434,295 524,190 646,137 800,137 997,137 1146,235 1245,430 L 1401,352 C 1343,231 1262,138 1157,75 1052,12 930,-20 791,-20 649,-20 526,10 423,69 319,128 240,212 186,322 131,431 104,561 104,711 104,936 165,1112 286,1239 407,1366 575,1430 790,1430 940,1430 1065,1401 1166,1342 1267,1283 1341,1196 1388,1081 L 1207,1021 C 1174,1103 1122,1166 1050,1209 977,1252 891,1274 792,1274 Z"/>
+   <glyph unicode="A" horiz-adv-x="1377" d="M 1167,0 L 1006,412 364,412 202,0 4,0 579,1409 796,1409 1362,0 1167,0 Z M 685,1265 L 676,1237 C 659,1182 635,1111 602,1024 L 422,561 949,561 768,1026 C 749,1072 731,1124 712,1182 L 685,1265 Z"/>
+   <glyph unicode="3" horiz-adv-x="1006" d="M 1049,389 C 1049,259 1008,158 925,87 842,16 724,-20 571,-20 428,-20 315,12 230,77 145,141 94,236 78,362 L 264,379 C 288,212 390,129 571,129 662,129 733,151 785,196 836,241 862,307 862,395 862,472 833,532 774,575 715,618 629,639 518,639 L 416,639 416,795 514,795 C 613,795 689,817 744,860 798,903 825,962 825,1038 825,1113 803,1173 759,1217 714,1260 648,1282 561,1282 482,1282 418,1262 369,1221 320,1180 291,1123 283,1049 L 102,1063 C 115,1178 163,1268 246,1333 328,1398 434,1430 563,1430 704,1430 814,1397 893,1332 971,1266 1010,1174 1010,1057 1010,967 985,894 935,838 884,781 811,743 715,723 L 715,719 C 820,708 902,672 961,613 1020,554 1049,479 1049,389 Z"/>
+   <glyph unicode="0" horiz-adv-x="980" d="M 1059,705 C 1059,470 1018,290 935,166 852,42 729,-20 567,-20 405,-20 283,42 202,165 121,288 80,468 80,705 80,947 120,1128 199,1249 278,1370 402,1430 573,1430 739,1430 862,1369 941,1247 1020,1125 1059,944 1059,705 Z M 876,705 C 876,908 853,1056 806,1147 759,1238 681,1284 573,1284 462,1284 383,1239 335,1149 286,1059 262,911 262,705 262,505 287,359 336,266 385,173 462,127 569,127 675,127 753,174 802,269 851,364 876,509 876,705 Z"/>
+   <glyph unicode="." horiz-adv-x="213" d="M 187,0 L 187,219 382,219 382,0 187,0 Z"/>
+   <glyph unicode="-" horiz-adv-x="531" d="M 91,464 L 91,624 591,624 591,464 91,464 Z"/>
+   <glyph unicode="," horiz-adv-x="239" d="M 385,219 L 385,51 C 385,-20 379,-79 366,-126 353,-173 334,-219 307,-262 L 184,-262 C 247,-171 278,-84 278,0 L 190,0 190,219 385,219 Z"/>
+   <glyph unicode=")" horiz-adv-x="557" d="M 555,528 C 555,335 525,162 465,9 404,-144 311,-289 186,-424 L 12,-424 C 137,-284 229,-136 287,19 345,174 374,344 374,530 374,716 345,887 287,1042 228,1197 137,1345 12,1484 L 186,1484 C 312,1348 405,1203 465,1050 525,896 555,723 555,532 L 555,528 Z"/>
+   <glyph unicode="(" horiz-adv-x="583" d="M 127,532 C 127,725 157,898 218,1051 278,1204 371,1349 496,1484 L 670,1484 C 545,1345 454,1198 396,1042 337,886 308,715 308,530 308,345 337,175 395,20 452,-135 544,-283 670,-424 L 496,-424 C 370,-288 277,-143 217,11 157,164 127,337 127,528 L 127,532 Z"/>
    <glyph unicode=" " horiz-adv-x="556"/>
   </font>
  </defs>
    <font-face font-family="Liberation Sans embedded" units-per-em="2048" font-weight="bold" font-style="normal" ascent="1852" descent="423"/>
    <missing-glyph horiz-adv-x="2048" d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"/>
    <glyph unicode="x" horiz-adv-x="1139" d="M 819,0 L 567,392 313,0 14,0 410,559 33,1082 336,1082 567,728 797,1082 1102,1082 725,562 1124,0 819,0 Z"/>
-   <glyph unicode="w" horiz-adv-x="1615" d="M 436,255 L 645,1082 946,1082 1153,255 1337,1082 1597,1082 1313,0 1016,0 797,882 571,0 274,0 -6,1082 258,1082 436,255 Z"/>
-   <glyph unicode="v" horiz-adv-x="1139" d="M 565,227 L 836,1082 1130,1082 731,0 395,0 8,1082 305,1082 565,227 Z"/>
-   <glyph unicode="t" horiz-adv-x="636" d="M 420,-18 C 337,-18 274,5 229,50 184,95 162,163 162,254 L 162,892 25,892 25,1082 176,1082 264,1336 440,1336 440,1082 645,1082 645,892 440,892 440,330 C 440,277 450,239 470,214 490,189 521,176 563,176 580,176 596,177 610,180 624,183 640,186 657,190 L 657,16 C 622,5 586,-4 547,-10 508,-15 466,-18 420,-18 Z"/>
-   <glyph unicode="s" horiz-adv-x="980" d="M 1055,316 C 1055,264 1044,217 1023,176 1001,135 969,100 928,71 887,42 836,19 776,4 716,-12 648,-20 571,-20 502,-20 440,-15 385,-5 330,5 281,22 240,45 198,68 163,97 135,134 107,171 86,216 72,270 L 319,307 C 327,277 338,253 352,234 366,215 383,201 404,191 425,181 449,174 477,171 504,168 536,166 571,166 603,166 633,168 661,172 688,175 712,182 733,191 753,200 769,212 780,229 791,245 797,265 797,290 797,318 789,340 773,357 756,373 734,386 706,397 677,407 644,416 606,424 567,431 526,440 483,450 438,460 393,472 349,486 305,500 266,519 231,543 196,567 168,598 147,635 126,672 115,718 115,775 115,826 125,872 145,913 165,953 194,987 233,1016 272,1044 320,1066 377,1081 434,1096 499,1103 573,1103 632,1103 686,1098 737,1087 788,1076 833,1058 873,1035 913,1011 947,981 974,944 1001,907 1019,863 1030,811 L 781,785 C 776,811 768,833 756,850 744,867 729,880 712,890 694,900 673,907 650,911 627,914 601,916 573,916 506,916 456,908 423,891 390,874 373,845 373,805 373,780 380,761 394,746 407,731 427,719 452,710 477,700 506,692 541,685 575,678 612,669 653,659 703,648 752,636 801,622 849,607 892,588 930,563 967,538 998,505 1021,466 1044,427 1055,377 1055,316 Z"/>
-   <glyph unicode="r" horiz-adv-x="662" d="M 143,0 L 143,833 C 143,856 143,881 143,907 142,933 142,958 141,982 140,1006 139,1027 138,1046 137,1065 136,1075 135,1075 L 403,1075 C 404,1067 406,1054 407,1035 408,1016 410,995 411,972 412,950 414,927 415,905 416,883 416,865 416,851 L 420,851 C 434,890 448,926 462,957 476,988 493,1014 512,1036 531,1057 553,1074 580,1086 607,1097 640,1103 679,1103 696,1103 712,1102 729,1099 745,1096 757,1092 766,1088 L 766,853 C 748,857 730,861 712,864 693,867 671,868 646,868 576,868 522,840 483,783 444,726 424,642 424,531 L 424,0 143,0 Z"/>
-   <glyph unicode="p" horiz-adv-x="1059" d="M 1167,546 C 1167,464 1159,388 1143,319 1126,250 1101,190 1067,140 1033,90 990,51 938,23 885,-6 823,-20 752,-20 720,-20 688,-17 657,-10 625,-3 595,8 566,23 537,38 511,57 487,82 462,106 441,136 424,172 L 418,172 C 419,169 419,160 420,147 421,134 421,118 422,101 423,83 423,64 424,45 424,25 424,7 424,-10 L 424,-425 143,-425 143,833 C 143,888 142,938 141,981 139,1024 137,1058 135,1082 L 408,1082 C 409,1077 411,1068 413,1055 414,1042 416,1026 417,1009 418,992 418,974 419,955 420,936 420,920 420,906 L 424,906 C 458,977 505,1028 564,1059 623,1090 692,1105 770,1105 839,1105 898,1091 948,1063 998,1035 1039,996 1072,947 1104,898 1128,839 1144,771 1159,702 1167,627 1167,546 Z M 874,546 C 874,669 855,761 818,821 781,880 725,910 651,910 623,910 595,904 568,893 540,881 515,861 494,833 472,804 454,766 441,719 427,671 420,611 420,538 420,467 427,409 440,362 453,315 471,277 493,249 514,221 539,201 566,190 593,178 621,172 649,172 685,172 717,179 745,194 773,208 797,230 816,261 835,291 849,330 859,377 869,424 874,481 874,546 Z"/>
-   <glyph unicode="o" horiz-adv-x="1086" d="M 1171,542 C 1171,459 1160,384 1137,315 1114,246 1079,187 1033,138 987,88 930,49 861,22 792,-6 712,-20 621,-20 533,-20 455,-6 388,21 321,48 264,87 219,136 173,185 138,245 115,314 92,383 80,459 80,542 80,623 91,697 114,766 136,834 170,893 215,943 260,993 317,1032 386,1060 455,1088 535,1102 627,1102 724,1102 807,1088 876,1060 945,1032 1001,993 1045,944 1088,894 1120,835 1141,767 1161,698 1171,623 1171,542 Z M 877,542 C 877,671 856,764 814,822 772,880 711,909 631,909 548,909 485,880 441,821 397,762 375,669 375,542 375,477 381,422 393,375 404,328 421,290 442,260 463,230 489,208 519,194 549,179 582,172 618,172 659,172 696,179 729,194 761,208 788,230 810,260 832,290 849,328 860,375 871,422 877,477 877,542 Z"/>
-   <glyph unicode="n" horiz-adv-x="1006" d="M 844,0 L 844,607 C 844,649 841,688 834,723 827,758 816,788 801,813 786,838 766,857 741,871 716,885 686,892 651,892 617,892 586,885 559,870 531,855 507,833 487,806 467,778 452,745 441,707 430,668 424,626 424,580 L 424,0 143,0 143,845 C 143,868 143,892 143,917 142,942 142,966 141,988 140,1010 139,1031 138,1048 137,1066 136,1075 135,1075 L 403,1075 C 404,1067 406,1055 407,1038 408,1021 410,1002 411,981 412,961 414,940 415,919 416,899 416,881 416,867 L 420,867 C 458,950 506,1010 563,1047 620,1084 689,1103 768,1103 833,1103 889,1092 934,1071 979,1050 1015,1020 1044,983 1072,946 1092,902 1105,851 1118,800 1124,746 1124,687 L 1124,0 844,0 Z"/>
+   <glyph unicode="w" horiz-adv-x="1641" d="M 1313,0 L 1016,0 844,660 C 836,690 820,764 797,882 L 745,658 571,0 274,0 -6,1082 258,1082 436,255 450,329 475,446 645,1082 946,1082 1112,446 C 1121,411 1135,348 1153,255 L 1181,387 1337,1082 1597,1082 1313,0 Z"/>
+   <glyph unicode="v" horiz-adv-x="1139" d="M 731,0 L 395,0 8,1082 305,1082 494,477 C 504,444 528,360 565,227 572,254 585,302 606,371 627,440 703,677 836,1082 L 1130,1082 731,0 Z"/>
+   <glyph unicode="t" horiz-adv-x="662" d="M 420,-18 C 337,-18 274,5 229,50 184,95 162,163 162,254 L 162,892 25,892 25,1082 176,1082 264,1336 440,1336 440,1082 645,1082 645,892 440,892 440,330 C 440,277 450,239 470,214 490,189 521,176 563,176 585,176 616,181 657,190 L 657,16 C 588,-7 509,-18 420,-18 Z"/>
+   <glyph unicode="s" horiz-adv-x="1006" d="M 1055,316 C 1055,211 1012,129 927,70 841,10 722,-20 571,-20 422,-20 309,4 230,51 151,98 98,171 72,270 L 319,307 C 333,256 357,219 392,198 426,177 486,166 571,166 650,166 707,176 743,196 779,216 797,247 797,290 797,325 783,352 754,373 725,393 675,410 606,424 447,455 340,485 285,512 230,539 188,574 159,617 130,660 115,712 115,775 115,878 155,959 235,1017 314,1074 427,1103 573,1103 702,1103 805,1078 884,1028 962,978 1011,906 1030,811 L 781,785 C 773,829 753,862 722,884 691,905 641,916 573,916 506,916 456,908 423,891 390,874 373,845 373,805 373,774 386,749 412,731 437,712 480,697 541,685 626,668 701,650 767,632 832,613 885,591 925,566 964,541 996,508 1020,469 1043,429 1055,378 1055,316 Z"/>
+   <glyph unicode="r" horiz-adv-x="636" d="M 143,0 L 143,828 C 143,887 142,937 141,977 139,1016 137,1051 135,1082 L 403,1082 C 405,1070 408,1034 411,973 414,912 416,871 416,851 L 420,851 C 447,927 472,981 493,1012 514,1043 540,1066 569,1081 598,1096 635,1103 679,1103 715,1103 744,1098 766,1088 L 766,853 C 721,863 681,868 646,868 576,868 522,840 483,783 444,726 424,642 424,531 L 424,0 143,0 Z"/>
+   <glyph unicode="p" horiz-adv-x="1033" d="M 1167,546 C 1167,365 1131,226 1059,128 986,29 884,-20 752,-20 676,-20 610,-3 554,30 497,63 454,110 424,172 L 418,172 C 422,152 424,91 424,-10 L 424,-425 143,-425 143,833 C 143,935 140,1018 135,1082 L 408,1082 C 411,1070 414,1046 417,1011 419,976 420,941 420,906 L 424,906 C 487,1039 603,1105 770,1105 896,1105 994,1057 1063,960 1132,863 1167,725 1167,546 Z M 874,546 C 874,789 800,910 651,910 576,910 519,877 480,812 440,747 420,655 420,538 420,421 440,331 480,268 519,204 576,172 649,172 799,172 874,297 874,546 Z"/>
+   <glyph unicode="o" horiz-adv-x="1113" d="M 1171,542 C 1171,367 1122,229 1025,130 928,30 793,-20 621,-20 452,-20 320,30 224,130 128,230 80,367 80,542 80,716 128,853 224,953 320,1052 454,1102 627,1102 804,1102 939,1054 1032,958 1125,861 1171,723 1171,542 Z M 877,542 C 877,671 856,764 814,822 772,880 711,909 631,909 460,909 375,787 375,542 375,421 396,330 438,267 479,204 539,172 618,172 791,172 877,295 877,542 Z"/>
+   <glyph unicode="n" horiz-adv-x="1007" d="M 844,0 L 844,607 C 844,797 780,892 651,892 583,892 528,863 487,805 445,746 424,671 424,580 L 424,0 143,0 143,840 C 143,898 142,946 141,983 139,1020 137,1053 135,1082 L 403,1082 C 405,1069 408,1036 411,981 414,926 416,888 416,867 L 420,867 C 458,950 506,1010 563,1047 620,1084 689,1103 768,1103 883,1103 971,1068 1032,997 1093,926 1124,823 1124,687 L 1124,0 844,0 Z"/>
    <glyph unicode="l" horiz-adv-x="292" d="M 143,0 L 143,1484 424,1484 424,0 143,0 Z"/>
-   <glyph unicode="k" horiz-adv-x="1033" d="M 834,0 L 545,490 424,406 424,0 143,0 143,1484 424,1484 424,634 810,1082 1112,1082 732,660 1141,0 834,0 Z"/>
+   <glyph unicode="k" horiz-adv-x="1007" d="M 834,0 L 545,490 424,406 424,0 143,0 143,1484 424,1484 424,634 810,1082 1112,1082 732,660 1141,0 834,0 Z"/>
    <glyph unicode="i" horiz-adv-x="292" d="M 143,1277 L 143,1484 424,1484 424,1277 143,1277 Z M 143,0 L 143,1082 424,1082 424,0 143,0 Z"/>
-   <glyph unicode="g" horiz-adv-x="1060" d="M 596,-434 C 525,-434 462,-427 408,-413 353,-398 307,-378 269,-353 230,-327 200,-296 177,-261 154,-225 138,-186 129,-143 L 410,-110 C 420,-153 442,-187 475,-212 508,-237 551,-249 604,-249 637,-249 668,-244 696,-235 723,-226 747,-210 767,-188 786,-165 802,-136 813,-99 824,-62 829,-17 829,37 829,56 829,75 829,94 829,113 829,131 830,147 831,166 831,184 831,201 L 829,201 C 796,131 751,80 692,49 633,18 562,2 481,2 412,2 353,16 304,43 254,70 213,107 180,156 147,204 123,262 108,329 92,396 84,469 84,550 84,633 92,709 109,777 126,844 151,902 186,951 220,1000 263,1037 316,1064 368,1090 430,1103 502,1103 574,1103 639,1088 696,1057 753,1026 797,977 829,908 L 834,908 C 834,922 835,939 836,957 837,976 838,994 839,1011 840,1029 842,1044 844,1058 845,1071 847,1078 848,1078 L 1114,1078 C 1113,1054 1111,1020 1110,977 1109,934 1108,885 1108,829 L 1108,32 C 1108,-47 1097,-115 1074,-173 1051,-231 1018,-280 975,-318 931,-357 877,-386 814,-405 750,-424 677,-434 596,-434 Z M 831,556 C 831,624 824,681 811,726 798,771 780,808 759,835 738,862 713,882 686,893 658,904 630,910 602,910 566,910 534,903 507,889 479,875 455,853 436,824 417,795 402,757 392,712 382,667 377,613 377,550 377,433 396,345 433,286 470,227 526,197 600,197 628,197 656,203 684,214 711,225 736,244 758,272 780,299 798,336 811,382 824,428 831,486 831,556 Z"/>
-   <glyph unicode="f" horiz-adv-x="663" d="M 473,892 L 473,0 193,0 193,892 35,892 35,1082 193,1082 193,1195 C 193,1236 198,1275 208,1310 218,1345 235,1375 259,1401 283,1427 315,1447 356,1462 397,1477 447,1484 508,1484 540,1484 572,1482 603,1479 634,1476 661,1472 686,1468 L 686,1287 C 674,1290 661,1292 646,1294 631,1295 617,1296 604,1296 578,1296 557,1293 540,1288 523,1283 509,1275 500,1264 490,1253 483,1240 479,1224 475,1207 473,1188 473,1167 L 473,1082 686,1082 686,892 473,892 Z"/>
-   <glyph unicode="e" horiz-adv-x="980" d="M 586,-20 C 508,-20 438,-8 376,15 313,38 260,73 216,120 172,167 138,226 115,297 92,368 80,451 80,546 80,649 94,736 122,807 149,878 187,935 234,979 281,1022 335,1054 396,1073 457,1092 522,1102 590,1102 675,1102 748,1087 809,1057 869,1027 918,986 957,932 996,878 1024,814 1042,739 1060,664 1069,582 1069,491 L 1069,491 375,491 C 375,445 379,402 387,363 395,323 408,289 426,261 444,232 467,209 496,193 525,176 559,168 600,168 649,168 690,179 721,200 752,221 775,253 788,297 L 1053,274 C 1041,243 1024,211 1003,176 981,141 952,110 916,81 880,52 835,28 782,9 728,-10 663,-20 586,-20 Z M 586,925 C 557,925 531,920 506,911 481,901 459,886 441,865 422,844 407,816 396,783 385,750 378,710 377,663 L 797,663 C 792,750 771,816 734,860 697,903 648,925 586,925 Z"/>
-   <glyph unicode="c" horiz-adv-x="1007" d="M 594,-20 C 508,-20 433,-7 369,20 304,47 251,84 208,133 165,182 133,240 112,309 91,377 80,452 80,535 80,625 92,705 115,776 138,846 172,905 216,954 260,1002 314,1039 379,1064 443,1089 516,1102 598,1102 668,1102 730,1092 785,1073 839,1054 886,1028 925,995 964,963 996,924 1021,879 1045,834 1062,786 1071,734 L 788,734 C 780,787 760,830 728,861 696,893 651,909 592,909 517,909 462,878 427,816 392,754 375,664 375,546 375,297 449,172 596,172 649,172 694,188 730,221 766,253 788,302 797,366 L 1079,366 C 1072,315 1057,267 1034,220 1010,174 978,133 938,97 897,62 848,33 791,12 734,-9 668,-20 594,-20 Z"/>
-   <glyph unicode="a" horiz-adv-x="1112" d="M 393,-20 C 341,-20 295,-13 254,2 213,16 178,37 149,65 120,93 98,127 83,168 68,208 60,255 60,307 60,371 71,425 94,469 116,513 146,548 185,575 224,602 269,622 321,634 373,647 428,653 487,653 L 720,653 720,709 C 720,748 717,782 710,808 703,835 692,857 679,873 666,890 649,902 630,909 610,916 587,920 562,920 539,920 518,918 500,913 481,909 465,901 452,890 439,879 428,864 420,845 411,826 405,803 402,774 L 109,774 C 117,822 132,866 153,906 174,946 204,981 242,1010 279,1039 326,1062 381,1078 436,1094 500,1102 574,1102 641,1102 701,1094 754,1077 807,1060 851,1036 888,1003 925,970 953,929 972,881 991,833 1001,777 1001,714 L 1001,320 C 1001,295 1002,272 1005,252 1007,232 1011,215 1018,202 1024,188 1033,178 1045,171 1056,164 1071,160 1090,160 1111,160 1132,162 1152,166 L 1152,14 C 1135,10 1120,6 1107,3 1094,0 1080,-3 1067,-5 1054,-7 1040,-9 1025,-10 1010,-11 992,-12 972,-12 901,-12 849,5 816,40 782,75 762,126 755,193 L 749,193 C 712,126 664,73 606,36 547,-1 476,-20 393,-20 Z M 720,499 L 576,499 C 546,499 518,497 491,493 464,490 440,482 420,470 399,459 383,442 371,420 359,397 353,367 353,329 353,277 365,239 389,214 412,189 444,176 483,176 519,176 552,184 581,199 610,214 635,234 656,259 676,284 692,312 703,345 714,377 720,411 720,444 L 720,499 Z"/>
-   <glyph unicode="S" horiz-adv-x="1218" d="M 1286,406 C 1286,342 1274,284 1251,232 1228,179 1192,134 1143,97 1094,60 1031,31 955,11 878,-10 787,-20 682,-20 589,-20 506,-12 435,5 364,22 303,46 252,79 201,112 159,152 128,201 96,249 73,304 59,367 L 344,414 C 352,383 364,354 379,328 394,302 416,280 443,261 470,242 503,227 544,217 584,206 633,201 690,201 790,201 867,216 920,247 973,277 999,324 999,389 999,428 988,459 967,484 946,509 917,529 882,545 847,561 806,574 760,585 714,596 666,606 616,616 576,625 536,635 496,645 456,655 418,667 382,681 345,695 311,712 280,731 249,750 222,774 199,803 176,831 158,864 145,902 132,940 125,985 125,1036 125,1106 139,1166 167,1216 195,1266 234,1307 284,1339 333,1370 392,1393 461,1408 530,1423 605,1430 686,1430 778,1430 857,1423 923,1409 988,1394 1043,1372 1088,1343 1132,1314 1167,1277 1193,1233 1218,1188 1237,1136 1249,1077 L 963,1038 C 948,1099 919,1144 874,1175 829,1206 764,1221 680,1221 628,1221 585,1217 551,1208 516,1199 489,1186 469,1171 448,1156 434,1138 425,1118 416,1097 412,1076 412,1053 412,1018 420,990 437,968 454,945 477,927 507,912 537,897 573,884 615,874 656,863 702,853 752,842 796,833 840,823 883,813 926,802 968,790 1007,776 1046,762 1083,745 1117,725 1151,705 1181,681 1206,652 1231,623 1250,588 1265,548 1279,508 1286,461 1286,406 Z"/>
-   <glyph unicode="I" horiz-adv-x="292" d="M 137,0 L 137,1409 432,1409 432,0 137,0 Z"/>
-   <glyph unicode="E" horiz-adv-x="1139" d="M 137,0 L 137,1409 1245,1409 1245,1181 432,1181 432,827 1184,827 1184,599 432,599 432,228 1286,228 1286,0 137,0 Z"/>
-   <glyph unicode=")" horiz-adv-x="583" d="M 2,-425 C 55,-347 101,-270 139,-196 177,-120 208,-44 233,33 257,110 275,190 286,272 297,353 303,439 303,530 303,620 297,706 286,788 275,869 257,949 233,1026 208,1103 177,1180 139,1255 101,1330 55,1407 2,1484 L 283,1484 C 334,1410 379,1337 416,1264 453,1191 484,1116 509,1039 533,962 551,882 563,799 574,716 580,626 580,531 580,436 574,347 563,264 551,180 533,99 509,22 484,-55 453,-131 416,-204 379,-277 334,-351 283,-425 L 2,-425 Z"/>
-   <glyph unicode="(" horiz-adv-x="583" d="M 399,-425 C 348,-351 303,-277 266,-204 229,-131 198,-55 174,22 149,99 131,180 120,264 108,347 102,436 102,531 102,626 108,716 120,799 131,882 149,962 174,1039 198,1116 229,1191 266,1264 303,1337 348,1410 399,1484 L 680,1484 C 627,1407 581,1330 543,1255 505,1180 474,1103 450,1026 425,949 407,869 396,788 385,706 379,620 379,530 379,439 385,353 396,272 407,190 425,110 450,33 474,-44 505,-120 543,-196 581,-270 627,-347 680,-425 L 399,-425 Z"/>
+   <glyph unicode="g" horiz-adv-x="1033" d="M 596,-434 C 464,-434 358,-409 278,-359 197,-308 148,-236 129,-143 L 410,-110 C 420,-153 442,-187 475,-212 508,-237 551,-249 604,-249 682,-249 739,-225 775,-177 811,-129 829,-58 829,37 L 829,94 831,201 829,201 C 767,68 651,2 481,2 355,2 257,49 188,144 119,239 84,374 84,550 84,727 120,863 191,959 262,1055 366,1103 502,1103 659,1103 768,1038 829,908 L 834,908 C 834,931 836,963 839,1003 842,1043 845,1069 848,1082 L 1114,1082 C 1110,1010 1108,927 1108,832 L 1108,33 C 1108,-121 1064,-237 977,-316 890,-395 763,-434 596,-434 Z M 831,556 C 831,667 811,754 772,817 732,879 675,910 602,910 452,910 377,790 377,550 377,315 451,197 600,197 675,197 732,228 772,291 811,353 831,441 831,556 Z"/>
+   <glyph unicode="f" horiz-adv-x="663" d="M 473,892 L 473,0 193,0 193,892 35,892 35,1082 193,1082 193,1195 C 193,1293 219,1366 271,1413 323,1460 402,1484 508,1484 561,1484 620,1479 686,1468 L 686,1287 C 659,1293 631,1296 604,1296 556,1296 522,1287 503,1268 483,1249 473,1215 473,1167 L 473,1082 686,1082 686,892 473,892 Z"/>
+   <glyph unicode="e" horiz-adv-x="1007" d="M 586,-20 C 423,-20 298,28 211,125 124,221 80,361 80,546 80,725 124,862 213,958 302,1054 427,1102 590,1102 745,1102 864,1051 946,948 1028,845 1069,694 1069,495 L 1069,487 375,487 C 375,382 395,302 434,249 473,195 528,168 600,168 699,168 762,211 788,297 L 1053,274 C 976,78 821,-20 586,-20 Z M 586,925 C 520,925 469,902 434,856 398,810 379,746 377,663 L 797,663 C 792,750 771,816 734,860 697,903 648,925 586,925 Z"/>
+   <glyph unicode="c" horiz-adv-x="1007" d="M 594,-20 C 430,-20 303,29 214,127 125,224 80,360 80,535 80,714 125,853 215,953 305,1052 433,1102 598,1102 725,1102 831,1070 914,1006 997,942 1050,854 1071,741 L 788,727 C 780,782 760,827 728,860 696,893 651,909 592,909 447,909 375,788 375,546 375,297 449,172 596,172 649,172 694,189 730,223 766,256 788,306 797,373 L 1079,360 C 1069,286 1043,220 1000,162 957,104 900,59 830,28 760,-4 681,-20 594,-20 Z"/>
+   <glyph unicode="a" horiz-adv-x="1112" d="M 393,-20 C 288,-20 207,9 148,66 89,123 60,203 60,306 60,418 97,503 170,562 243,621 348,651 487,652 L 720,656 720,711 C 720,782 708,834 683,869 658,903 618,920 562,920 510,920 472,908 448,885 423,861 408,822 402,767 L 109,781 C 127,886 175,966 254,1021 332,1075 439,1102 574,1102 711,1102 816,1068 890,1001 964,934 1001,838 1001,714 L 1001,320 C 1001,259 1008,218 1022,195 1035,172 1058,160 1090,160 1111,160 1132,162 1152,166 L 1152,14 C 1135,10 1120,6 1107,3 1094,0 1080,-3 1067,-5 1054,-7 1040,-9 1025,-10 1010,-11 992,-12 972,-12 901,-12 849,5 816,40 782,75 762,126 755,193 L 749,193 C 670,51 552,-20 393,-20 Z M 720,501 L 576,499 C 511,496 464,489 437,478 410,466 389,448 375,424 360,400 353,368 353,328 353,277 365,239 389,214 412,189 444,176 483,176 527,176 567,188 604,212 640,236 668,269 689,312 710,354 720,399 720,446 L 720,501 Z"/>
+   <glyph unicode="S" horiz-adv-x="1244" d="M 1286,406 C 1286,268 1235,163 1133,90 1030,17 880,-20 682,-20 501,-20 360,12 257,76 154,140 88,237 59,367 L 344,414 C 363,339 401,285 457,252 513,218 591,201 690,201 896,201 999,264 999,389 999,429 987,462 964,488 940,514 907,536 864,553 821,570 738,591 616,616 511,641 437,661 396,676 355,691 317,708 284,729 251,749 222,773 199,802 176,831 158,864 145,903 132,942 125,986 125,1036 125,1163 173,1261 269,1329 364,1396 503,1430 686,1430 861,1430 992,1403 1080,1348 1167,1293 1224,1203 1249,1077 L 963,1038 C 948,1099 919,1144 874,1175 829,1206 764,1221 680,1221 501,1221 412,1165 412,1053 412,1016 422,986 441,963 460,940 488,920 525,904 562,887 638,867 752,842 887,813 984,787 1043,763 1101,738 1147,710 1181,678 1215,645 1241,607 1259,562 1277,517 1286,465 1286,406 Z"/>
+   <glyph unicode="I" horiz-adv-x="319" d="M 137,0 L 137,1409 432,1409 432,0 137,0 Z"/>
+   <glyph unicode="E" horiz-adv-x="1165" d="M 137,0 L 137,1409 1245,1409 1245,1181 432,1181 432,827 1184,827 1184,599 432,599 432,228 1286,228 1286,0 137,0 Z"/>
+   <glyph unicode=")" horiz-adv-x="583" d="M 2,-425 C 109,-269 186,-116 233,33 280,182 303,347 303,530 303,713 279,881 231,1032 183,1183 107,1333 2,1484 L 283,1484 C 388,1333 464,1182 511,1032 557,882 580,715 580,531 580,346 557,178 511,28 464,-122 388,-273 283,-425 L 2,-425 Z"/>
+   <glyph unicode="(" horiz-adv-x="610" d="M 399,-425 C 294,-274 219,-124 172,26 125,176 102,344 102,531 102,717 125,885 172,1035 219,1184 294,1334 399,1484 L 680,1484 C 575,1332 498,1181 451,1030 403,879 379,713 379,530 379,348 403,182 450,33 497,-117 574,-270 680,-425 L 399,-425 Z"/>
    <glyph unicode=" " horiz-adv-x="556"/>
   </font>
  </defs>
   <g ooo:slide="id1" ooo:id-list="id3 id4 id5 id6 id7 id8 id9 id10 id11 id12 id13 id14 id15 id16 id17 id18 id19 id20 id21 id22 id23 id24 id25 id26 id27 id28 id29 id30 id31 id32 id33 id34 id35 id36 id37 id38 id39 id40 id41 id42"/>
  </defs>
  <defs class="EmbeddedBulletChars">
-  <g id="bullet-char-template(57356)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-57356" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 580,1141 L 1163,571 580,0 -4,571 580,1141 Z"/>
   </g>
-  <g id="bullet-char-template(57354)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-57354" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 8,1128 L 1137,1128 1137,0 8,0 8,1128 Z"/>
   </g>
-  <g id="bullet-char-template(10146)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-10146" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 174,0 L 602,739 174,1481 1456,739 174,0 Z M 1358,739 L 309,1346 659,739 1358,739 Z"/>
   </g>
-  <g id="bullet-char-template(10132)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-10132" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 2015,739 L 1276,0 717,0 1260,543 174,543 174,936 1260,936 717,1481 1274,1481 2015,739 Z"/>
   </g>
-  <g id="bullet-char-template(10007)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-10007" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 0,-2 C -7,14 -16,27 -25,37 L 356,567 C 262,823 215,952 215,954 215,979 228,992 255,992 264,992 276,990 289,987 310,991 331,999 354,1012 L 381,999 492,748 772,1049 836,1024 860,1049 C 881,1039 901,1025 922,1006 886,937 835,863 770,784 769,783 710,716 594,584 L 774,223 C 774,196 753,168 711,139 L 727,119 C 717,90 699,76 672,76 641,76 570,178 457,381 L 164,-76 C 142,-110 111,-127 72,-127 30,-127 9,-110 8,-76 1,-67 -2,-52 -2,-32 -2,-23 -1,-13 0,-2 Z"/>
   </g>
-  <g id="bullet-char-template(10004)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-10004" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 285,-33 C 182,-33 111,30 74,156 52,228 41,333 41,471 41,549 55,616 82,672 116,743 169,778 240,778 293,778 328,747 346,684 L 369,508 C 377,444 397,411 428,410 L 1163,1116 C 1174,1127 1196,1133 1229,1133 1271,1133 1292,1118 1292,1087 L 1292,965 C 1292,929 1282,901 1262,881 L 442,47 C 390,-6 338,-33 285,-33 Z"/>
   </g>
-  <g id="bullet-char-template(9679)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-9679" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 813,0 C 632,0 489,54 383,161 276,268 223,411 223,592 223,773 276,916 383,1023 489,1130 632,1184 813,1184 992,1184 1136,1130 1245,1023 1353,916 1407,772 1407,592 1407,412 1353,268 1245,161 1136,54 992,0 813,0 Z"/>
   </g>
-  <g id="bullet-char-template(8226)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-8226" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 346,457 C 273,457 209,483 155,535 101,586 74,649 74,723 74,796 101,859 155,911 209,963 273,989 346,989 419,989 480,963 531,910 582,859 608,796 608,723 608,648 583,586 532,535 482,483 420,457 346,457 Z"/>
   </g>
-  <g id="bullet-char-template(8211)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-8211" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M -4,459 L 1135,459 1135,606 -4,606 -4,459 Z"/>
   </g>
-  <g id="bullet-char-template(61548)" transform="scale(0.00048828125,-0.00048828125)">
+  <g id="bullet-char-template-61548" transform="scale(0.00048828125,-0.00048828125)">
    <path d="M 173,740 C 173,903 231,1043 346,1159 462,1274 601,1332 765,1332 928,1332 1067,1274 1183,1159 1299,1043 1357,903 1357,740 1357,577 1299,437 1183,322 1067,206 928,148 765,148 601,148 462,206 346,322 231,437 173,577 173,740 Z"/>
   </g>
  </defs>
      <g class="Page">
       <g class="com.sun.star.drawing.LineShape">
        <g id="id3">
-        <rect class="BoundingBox" stroke="none" fill="none" x="16493" y="6587" width="2416" height="2289"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 16494,6588 L 18907,8874"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="19033" y="6333" width="4956" height="2162"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 19034,6334 L 23987,8493"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id4">
-        <rect class="BoundingBox" stroke="none" fill="none" x="13572" y="1506" width="2036" height="1909"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,1507 C 15165,1507 15605,1919 15605,2459 15605,2999 15165,3412 14589,3412 14013,3412 13573,2999 13573,2459 13573,1919 14013,1507 14589,1507 Z M 13573,1507 L 13573,1507 Z M 15606,3413 L 15606,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,1507 C 15165,1507 15605,1919 15605,2459 15605,2999 15165,3412 14589,3412 14013,3412 13573,2999 13573,2459 13573,1919 14013,1507 14589,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 13573,1507 L 13573,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 15606,3413 L 15606,3413 Z"/>
-        <path fill="rgb(91,127,166)" stroke="none" d="M 14258,2005 C 14311,2005 14352,2076 14352,2169 14352,2262 14311,2333 14258,2333 14205,2333 14165,2262 14165,2169 14165,2076 14205,2005 14258,2005 Z M 13573,1507 L 13573,1507 Z M 15606,3413 L 15606,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14258,2005 C 14311,2005 14352,2076 14352,2169 14352,2262 14311,2333 14258,2333 14205,2333 14165,2262 14165,2169 14165,2076 14205,2005 14258,2005 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 13573,1507 L 13573,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 15606,3413 L 15606,3413 Z"/>
-        <path fill="rgb(91,127,166)" stroke="none" d="M 14916,2005 C 14969,2005 15010,2076 15010,2169 15010,2262 14969,2333 14916,2333 14863,2333 14823,2262 14823,2169 14823,2076 14863,2005 14916,2005 Z M 13573,1507 L 13573,1507 Z M 15606,3413 L 15606,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14916,2005 C 14969,2005 15010,2076 15010,2169 15010,2262 14969,2333 14916,2333 14863,2333 14823,2262 14823,2169 14823,2076 14863,2005 14916,2005 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 13573,1507 L 13573,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 15606,3413 L 15606,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14031,2787 C 14389,3141 14789,3141 15147,2787"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 13573,1507 L 13573,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 15606,3413 L 15606,3413 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="23986" y="9889" width="3" height="7242"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 23987,9890 L 23987,17129"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id5">
-        <rect class="BoundingBox" stroke="none" fill="none" x="7349" y="1506" width="2036" height="1909"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 8366,1507 C 8942,1507 9382,1919 9382,2459 9382,2999 8942,3412 8366,3412 7790,3412 7350,2999 7350,2459 7350,1919 7790,1507 8366,1507 Z M 7350,1507 L 7350,1507 Z M 9383,3413 L 9383,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 8366,1507 C 8942,1507 9382,1919 9382,2459 9382,2999 8942,3412 8366,3412 7790,3412 7350,2999 7350,2459 7350,1919 7790,1507 8366,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7350,1507 L 7350,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 9383,3413 L 9383,3413 Z"/>
-        <path fill="rgb(91,127,166)" stroke="none" d="M 8035,2005 C 8088,2005 8129,2076 8129,2169 8129,2262 8088,2333 8035,2333 7982,2333 7942,2262 7942,2169 7942,2076 7982,2005 8035,2005 Z M 7350,1507 L 7350,1507 Z M 9383,3413 L 9383,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 8035,2005 C 8088,2005 8129,2076 8129,2169 8129,2262 8088,2333 8035,2333 7982,2333 7942,2262 7942,2169 7942,2076 7982,2005 8035,2005 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7350,1507 L 7350,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 9383,3413 L 9383,3413 Z"/>
-        <path fill="rgb(91,127,166)" stroke="none" d="M 8693,2005 C 8746,2005 8787,2076 8787,2169 8787,2262 8746,2333 8693,2333 8640,2333 8600,2262 8600,2169 8600,2076 8640,2005 8693,2005 Z M 7350,1507 L 7350,1507 Z M 9383,3413 L 9383,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 8693,2005 C 8746,2005 8787,2076 8787,2169 8787,2262 8746,2333 8693,2333 8640,2333 8600,2262 8600,2169 8600,2076 8640,2005 8693,2005 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7350,1507 L 7350,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 9383,3413 L 9383,3413 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7808,2787 C 8166,3141 8566,3141 8924,2787"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7350,1507 L 7350,1507 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 9383,3413 L 9383,3413 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="19414" y="10016" width="130" height="7115"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 19542,17129 L 19415,10017"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id6">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12682" y="5570" width="4194" height="1400"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14779,6968 L 12683,6968 12683,5571 16874,5571 16874,6968 14779,6968 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14779,6968 L 12683,6968 12683,5571 16874,5571 16874,6968 14779,6968 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="13528" y="6441"><tspan fill="rgb(0,0,0)" stroke="none">Workbench</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="8365" y="10270" width="3" height="2924"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 8366,10271 L 8366,13192"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id7">
-        <rect class="BoundingBox" stroke="none" fill="none" x="5824" y="8618" width="4194" height="1654"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 7921,10270 L 5825,10270 5825,8619 10016,8619 10016,10270 7921,10270 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7921,10270 L 5825,10270 5825,8619 10016,8619 10016,10270 7921,10270 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="6784" y="9339"><tspan fill="rgb(0,0,0)" stroke="none">keepproxy</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="6850" y="9894"><tspan fill="rgb(0,0,0)" stroke="none">keep-web</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="9635" y="15096" width="2924" height="1400"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 9636,15097 L 12557,16494"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id8">
-        <rect class="BoundingBox" stroke="none" fill="none" x="22080" y="8492" width="4194" height="1781"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 24177,10271 L 22081,10271 22081,8493 26272,8493 26272,10271 24177,10271 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 24177,10271 L 22081,10271 22081,8493 26272,8493 26272,10271 24177,10271 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="22856" y="9554"><tspan fill="rgb(0,0,0)" stroke="none">arv-git-httpd</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="4682" y="15604" width="1400" height="1527"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 6080,15605 L 4683,17129"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id9">
-        <rect class="BoundingBox" stroke="none" fill="none" x="17635" y="8492" width="4194" height="1781"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 19732,10271 L 17636,10271 17636,8493 21827,8493 21827,10271 19732,10271 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 19732,10271 L 17636,10271 17636,8493 21827,8493 21827,10271 19732,10271 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="19008" y="9554"><tspan fill="rgb(0,0,0)" stroke="none">arv-ws</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="14842" y="6333" width="3" height="2162"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 14843,6334 L 14843,8493"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id10">
-        <rect class="BoundingBox" stroke="none" fill="none" x="5825" y="15730" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 7604,18144 L 5826,18144 5826,15731 9382,15731 9382,18144 7604,18144 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7604,18144 L 5826,18144 5826,15731 9382,15731 9382,18144 7604,18144 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="13826" y="14588" width="3" height="1273"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 13827,14589 L 13827,15859"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id11">
-        <rect class="BoundingBox" stroke="none" fill="none" x="6079" y="16111" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 7858,18525 L 6080,18525 6080,16112 9636,16112 9636,18525 7858,18525 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 7858,18525 L 6080,18525 6080,16112 9636,16112 9636,18525 7858,18525 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="8492" y="6206" width="3051" height="2416"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 11541,6207 L 8493,8620"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id12">
-        <rect class="BoundingBox" stroke="none" fill="none" x="6460" y="16492" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 8239,18906 L 6461,18906 6461,16493 10017,16493 10017,18906 8239,18906 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 8239,18906 L 6461,18906 6461,16493 10017,16493 10017,18906 8239,18906 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="7149" y="17871"><tspan fill="rgb(0,0,0)" stroke="none">keepstore</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="17001" y="6206" width="2289" height="2289"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 17002,6207 L 19288,8493"/>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id13">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12556" y="15730" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14335,18144 L 12557,18144 12557,15731 16113,15731 16113,18144 14335,18144 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14335,18144 L 12557,18144 12557,15731 16113,15731 16113,18144 14335,18144 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="13572" y="1633" width="2035" height="1908"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,1634 C 15165,1634 15605,2046 15605,2586 15605,3126 15165,3539 14589,3539 14013,3539 13573,3126 13573,2586 13573,2046 14013,1634 14589,1634 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,1634 C 15165,1634 15605,2046 15605,2586 15605,3126 15165,3539 14589,3539 14013,3539 13573,3126 13573,2586 13573,2046 14013,1634 14589,1634 Z"/>
+        <path fill="rgb(91,127,166)" stroke="none" d="M 14258,2132 C 14311,2132 14352,2203 14352,2296 14352,2389 14311,2460 14258,2460 14205,2460 14165,2389 14165,2296 14165,2203 14205,2132 14258,2132 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14258,2132 C 14311,2132 14352,2203 14352,2296 14352,2389 14311,2460 14258,2460 14205,2460 14165,2389 14165,2296 14165,2203 14205,2132 14258,2132 Z"/>
+        <path fill="rgb(91,127,166)" stroke="none" d="M 14916,2132 C 14969,2132 15010,2203 15010,2296 15010,2389 14969,2460 14916,2460 14863,2460 14823,2389 14823,2296 14823,2203 14863,2132 14916,2132 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14916,2132 C 14969,2132 15010,2203 15010,2296 15010,2389 14969,2460 14916,2460 14863,2460 14823,2389 14823,2296 14823,2203 14863,2132 14916,2132 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14031,2914 C 14389,3268 14789,3268 15147,2914"/>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id14">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12810" y="16111" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,18525 L 12811,18525 12811,16112 16367,16112 16367,18525 14589,18525 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,18525 L 12811,18525 12811,16112 16367,16112 16367,18525 14589,18525 Z"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="5824" y="8618" width="4194" height="1654"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 7921,10270 L 5825,10270 5825,8619 10016,8619 10016,10270 7921,10270 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 7921,10270 L 5825,10270 5825,8619 10016,8619 10016,10270 7921,10270 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="6725" y="9339"><tspan fill="rgb(0,0,0)" stroke="none">keepproxy,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="6848" y="9894"><tspan fill="rgb(0,0,0)" stroke="none">keep-web</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id15">
-        <rect class="BoundingBox" stroke="none" fill="none" x="13191" y="16492" width="3559" height="2416"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14970,18906 L 13192,18906 13192,16493 16748,16493 16748,18906 14970,18906 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14970,18906 L 13192,18906 13192,16493 16748,16493 16748,18906 14970,18906 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="13671" y="17871"><tspan fill="rgb(0,0,0)" stroke="none">compute0...</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="22080" y="8491" width="4194" height="1654"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 24177,10143 L 22081,10143 22081,8492 26272,8492 26272,10143 24177,10143 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 24177,10143 L 22081,10143 22081,8492 26272,8492 26272,10143 24177,10143 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="22852" y="9489"><tspan fill="rgb(0,0,0)" stroke="none">arv-git-httpd</tspan></tspan></tspan></text>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id16">
-        <rect class="BoundingBox" stroke="none" fill="none" x="15477" y="10143" width="5972" height="5972"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 15478,10144 L 21447,16113"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="17254" y="8491" width="4194" height="1654"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 19351,10143 L 17255,10143 17255,8492 21446,8492 21446,10143 19351,10143 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 19351,10143 L 17255,10143 17255,8492 21446,8492 21446,10143 19351,10143 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="18620" y="9489"><tspan fill="rgb(0,0,0)" stroke="none">arv-ws</tspan></tspan></tspan></text>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id17">
-        <rect class="BoundingBox" stroke="none" fill="none" x="14588" y="6968" width="3" height="1527"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 14589,6969 L 14589,8493"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="5571" y="12936" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 7350,15350 L 5572,15350 5572,12937 9128,12937 9128,15350 7350,15350 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 7350,15350 L 5572,15350 5572,12937 9128,12937 9128,15350 7350,15350 Z"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id18">
-        <rect class="BoundingBox" stroke="none" fill="none" x="7984" y="10270" width="3" height="5464"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 7985,10271 L 7985,15732"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="5825" y="13317" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 7604,15731 L 5826,15731 5826,13318 9382,13318 9382,15731 7604,15731 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 7604,15731 L 5826,15731 5826,13318 9382,13318 9382,15731 7604,15731 Z"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id19">
-        <rect class="BoundingBox" stroke="none" fill="none" x="10016" y="17382" width="2543" height="3"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 10017,17383 L 12557,17383"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="6206" y="13698" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 7985,16112 L 6207,16112 6207,13699 9763,13699 9763,16112 7985,16112 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 7985,16112 L 6207,16112 6207,13699 9763,13699 9763,16112 7985,16112 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="6895" y="15077"><tspan fill="rgb(0,0,0)" stroke="none">keepstore</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id20">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12047" y="13064" width="5210" height="1781"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14652,14843 L 12048,14843 12048,13065 17255,13065 17255,14843 14652,14843 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14652,14843 L 12048,14843 12048,13065 17255,13065 17255,14843 14652,14843 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="12209" y="14126"><tspan fill="rgb(0,0,0)" stroke="none">crunch-dispatch-slurm</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="12556" y="15730" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14335,18144 L 12557,18144 12557,15731 16113,15731 16113,18144 14335,18144 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14335,18144 L 12557,18144 12557,15731 16113,15731 16113,18144 14335,18144 Z"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id21">
-        <rect class="BoundingBox" stroke="none" fill="none" x="14588" y="10143" width="3" height="2924"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 14589,10144 L 14589,13065"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="12810" y="16111" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,18525 L 12811,18525 12811,16112 16367,16112 16367,18525 14589,18525 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,18525 L 12811,18525 12811,16112 16367,16112 16367,18525 14589,18525 Z"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id22">
-        <rect class="BoundingBox" stroke="none" fill="none" x="14588" y="14842" width="3" height="892"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 14589,14843 L 14589,15732"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="13191" y="16492" width="3559" height="2416"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14970,18906 L 13192,18906 13192,16493 16748,16493 16748,18906 14970,18906 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14970,18906 L 13192,18906 13192,16493 16748,16493 16748,18906 14970,18906 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="13673" y="17871"><tspan fill="rgb(0,0,0)" stroke="none">compute0...</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.LineShape">
        <g id="id23">
+        <rect class="BoundingBox" stroke="none" fill="none" x="15858" y="10143" width="3178" height="6988"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 15859,10144 L 19034,17129"/>
+       </g>
+      </g>
+      <g class="com.sun.star.drawing.CustomShape">
+       <g id="id24">
+        <rect class="BoundingBox" stroke="none" fill="none" x="10778" y="12937" width="4067" height="1781"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 12811,14716 L 10779,14716 10779,12938 14843,12938 14843,14716 12811,14716 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 12811,14716 L 10779,14716 10779,12938 14843,12938 14843,14716 12811,14716 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="11215" y="13721"><tspan fill="rgb(0,0,0)" stroke="none">Cloud or HPC </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="11666" y="14276"><tspan fill="rgb(0,0,0)" stroke="none">dispatcher</tspan></tspan></tspan></text>
+       </g>
+      </g>
+      <g class="com.sun.star.drawing.LineShape">
+       <g id="id25">
+        <rect class="BoundingBox" stroke="none" fill="none" x="13826" y="10016" width="3" height="2924"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 13827,10017 L 13827,12938"/>
+       </g>
+      </g>
+      <g class="com.sun.star.drawing.LineShape">
+       <g id="id26">
         <rect class="BoundingBox" stroke="none" fill="none" x="1582" y="12123" width="24872" height="107"/>
         <path fill="none" stroke="rgb(0,0,0)" stroke-width="106" stroke-linejoin="round" d="M 1635,12176 L 1844,12176"/>
         <path fill="none" stroke="rgb(0,0,0)" stroke-width="106" stroke-linejoin="round" d="M 1978,12176 L 2187,12176"/>
         <path fill="none" stroke="rgb(0,0,0)" stroke-width="106" stroke-linejoin="round" d="M 26363,12176 L 26400,12176"/>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
-       <g id="id24">
-        <rect class="BoundingBox" stroke="none" fill="none" x="16366" y="9381" width="1273" height="3"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 16367,9382 L 17637,9382"/>
-       </g>
-      </g>
       <g class="com.sun.star.drawing.CustomShape">
-       <g id="id25">
-        <rect class="BoundingBox" stroke="none" fill="none" x="22462" y="12936" width="3306" height="2417"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 24114,12937 C 23213,12937 22463,13074 22463,13238 L 22463,15049 C 22463,15213 23213,15351 24114,15351 25015,15351 25766,15213 25766,15049 L 25766,13238 C 25766,13074 25015,12937 24114,12937 L 24114,12937 Z M 22463,12937 L 22463,12937 Z M 25766,15351 L 25766,15351 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 24114,12937 C 23213,12937 22463,13074 22463,13238 L 22463,15049 C 22463,15213 23213,15351 24114,15351 25015,15351 25766,15213 25766,15049 L 25766,13238 C 25766,13074 25015,12937 24114,12937 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 22463,12937 L 22463,12937 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 25766,15351 L 25766,15351 Z"/>
-        <path fill="rgb(165,195,226)" stroke="none" d="M 24114,12937 C 23213,12937 22463,13074 22463,13238 22463,13403 23213,13540 24114,13540 25015,13540 25766,13403 25766,13238 25766,13074 25015,12937 24114,12937 L 24114,12937 Z M 22463,12937 L 22463,12937 Z M 25766,15351 L 25766,15351 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 24114,12937 C 23213,12937 22463,13074 22463,13238 22463,13403 23213,13540 24114,13540 25015,13540 25766,13403 25766,13238 25766,13074 25015,12937 24114,12937 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 22463,12937 L 22463,12937 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 25766,15351 L 25766,15351 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="23162" y="14466"><tspan fill="rgb(0,0,0)" stroke="none">git repos</tspan></tspan></tspan></text>
-       </g>
-      </g>
-      <g class="com.sun.star.drawing.LineShape">
-       <g id="id26">
-        <rect class="BoundingBox" stroke="none" fill="none" x="23986" y="10270" width="3" height="2670"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 23987,10271 L 23987,12938"/>
-       </g>
-      </g>
-      <g class="com.sun.star.drawing.LineShape">
        <g id="id27">
-        <rect class="BoundingBox" stroke="none" fill="none" x="14588" y="4301" width="3" height="1273"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 14589,4302 L 14589,5572"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="22462" y="16874" width="3306" height="2544"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 24114,16875 C 23213,16875 22463,17019 22463,17192 L 22463,19098 C 22463,19271 23213,19416 24114,19416 25015,19416 25766,19271 25766,19098 L 25766,17192 C 25766,17019 25015,16875 24114,16875 L 24114,16875 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 24114,16875 C 23213,16875 22463,17019 22463,17192 L 22463,19098 C 22463,19271 23213,19416 24114,19416 25015,19416 25766,19271 25766,19098 L 25766,17192 C 25766,17019 25015,16875 24114,16875 Z"/>
+        <path fill="rgb(165,195,226)" stroke="none" d="M 24114,16875 C 23213,16875 22463,17019 22463,17192 22463,17365 23213,17510 24114,17510 25015,17510 25766,17365 25766,17192 25766,17019 25015,16875 24114,16875 L 24114,16875 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 24114,16875 C 23213,16875 22463,17019 22463,17192 22463,17365 23213,17510 24114,17510 25015,17510 25766,17365 25766,17192 25766,17019 25015,16875 24114,16875 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="23162" y="18476"><tspan fill="rgb(0,0,0)" stroke="none">git repos</tspan></tspan></tspan></text>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id28">
-        <rect class="BoundingBox" stroke="none" fill="none" x="9381" y="4809" width="3432" height="3686"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 12811,8493 L 9382,4810"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="13345" y="3666" width="2541" height="636"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="14243" y="4105"><tspan fill="rgb(0,0,0)" stroke="none">User</tspan></tspan></tspan></text>
        </g>
       </g>
-      <g class="com.sun.star.drawing.LineShape">
+      <g class="com.sun.star.drawing.CustomShape">
        <g id="id29">
-        <rect class="BoundingBox" stroke="none" fill="none" x="7984" y="4809" width="3" height="3813"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 7985,8620 L 7985,4810"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="5445" y="10524" width="2541" height="636"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="5502" y="10963"><tspan fill="rgb(0,0,0)" stroke="none">Storage access</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id30">
-        <rect class="BoundingBox" stroke="none" fill="none" x="7350" y="3666" width="2541" height="636"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="7956" y="4105"><tspan fill="rgb(0,0,0)" stroke="none">CLI user</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="1254" y="10524" width="2541" height="1398"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1783" y="10950"><tspan fill="rgb(0,0,0)" stroke="none">External </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1957" y="11344"><tspan fill="rgb(0,0,0)" stroke="none">facing </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1824" y="11738"><tspan fill="rgb(0,0,0)" stroke="none">services</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id31">
-        <rect class="BoundingBox" stroke="none" fill="none" x="13319" y="3539" width="2541" height="636"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="13831" y="3978"><tspan fill="rgb(0,0,0)" stroke="none">Web user</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="1122" y="12556" width="2812" height="1398"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1889" y="12982"><tspan fill="rgb(0,0,0)" stroke="none">Internal</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1756" y="13376"><tspan fill="rgb(0,0,0)" stroke="none">Services </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1106" y="13770"><tspan fill="rgb(0,0,0)" stroke="none">(private network)</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id32">
-        <rect class="BoundingBox" stroke="none" fill="none" x="5445" y="10651" width="2541" height="636"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="5502" y="11090"><tspan fill="rgb(0,0,0)" stroke="none">Storage access</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="18906" y="7349" width="1906" height="1144"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="19236" y="7845"><tspan fill="rgb(0,0,0)" stroke="none">Publish </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="19340" y="8239"><tspan fill="rgb(0,0,0)" stroke="none">events</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id33">
-        <rect class="BoundingBox" stroke="none" fill="none" x="1254" y="10524" width="2541" height="1398"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1783" y="10950"><tspan fill="rgb(0,0,0)" stroke="none">External </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1957" y="11344"><tspan fill="rgb(0,0,0)" stroke="none">facing </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1824" y="11738"><tspan fill="rgb(0,0,0)" stroke="none">services</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="10750" y="10271" width="2855" height="1525"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="10734" y="10760"><tspan fill="rgb(0,0,0)" stroke="none">Storage metadata,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11045" y="11154"><tspan fill="rgb(0,0,0)" stroke="none">Compute jobs,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11219" y="11548"><tspan fill="rgb(0,0,0)" stroke="none">Permissions</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id34">
-        <rect class="BoundingBox" stroke="none" fill="none" x="1123" y="12556" width="2811" height="1398"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1889" y="12982"><tspan fill="rgb(0,0,0)" stroke="none">Internal</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1756" y="13376"><tspan fill="rgb(0,0,0)" stroke="none">Services </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="700"><tspan class="TextPosition" x="1106" y="13770"><tspan fill="rgb(0,0,0)" stroke="none">(private network)</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="6587" y="16239" width="5462" height="636"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="6671" y="16678"><tspan fill="rgb(0,0,0)" stroke="none">Content-addressed object storage</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id35">
-        <rect class="BoundingBox" stroke="none" fill="none" x="17636" y="10525" width="3938" height="1017"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="17792" y="10957"><tspan fill="rgb(0,0,0)" stroke="none">Publish change events </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="18294" y="11351"><tspan fill="rgb(0,0,0)" stroke="none">over websockets</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="12811" y="19033" width="4065" height="636"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="13078" y="19472"><tspan fill="rgb(0,0,0)" stroke="none">Elastic compute nodes</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id36">
-        <rect class="BoundingBox" stroke="none" fill="none" x="11508" y="10271" width="2855" height="1525"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11492" y="10760"><tspan fill="rgb(0,0,0)" stroke="none">Storage metadata,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11801" y="11154"><tspan fill="rgb(0,0,0)" stroke="none">Compute jobs,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11977" y="11548"><tspan fill="rgb(0,0,0)" stroke="none">Permissions</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="1000" y="1127" width="5843" height="2033"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="635px" font-weight="400"><tspan class="TextPosition" x="1190" y="2008"><tspan fill="rgb(0,0,0)" stroke="none">An Arvados cluster </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="635px" font-weight="400"><tspan class="TextPosition" x="1595" y="2719"><tspan fill="rgb(0,0,0)" stroke="none">From 30000 feet</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id37">
-        <rect class="BoundingBox" stroke="none" fill="none" x="5444" y="19033" width="5462" height="636"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="5526" y="19472"><tspan fill="rgb(0,0,0)" stroke="none">Content-addressed object storage</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="17890" y="16874" width="3814" height="2544"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 19796,16875 C 18757,16875 17891,17019 17891,17192 L 17891,19098 C 17891,19271 18757,19416 19796,19416 20835,19416 21702,19271 21702,19098 L 21702,17192 C 21702,17019 20835,16875 19796,16875 L 19796,16875 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 19796,16875 C 18757,16875 17891,17019 17891,17192 L 17891,19098 C 17891,19271 18757,19416 19796,19416 20835,19416 21702,19271 21702,19098 L 21702,17192 C 21702,17019 20835,16875 19796,16875 Z"/>
+        <path fill="rgb(165,195,226)" stroke="none" d="M 19796,16875 C 18757,16875 17891,17019 17891,17192 17891,17365 18757,17510 19796,17510 20835,17510 21702,17365 21702,17192 21702,17019 20835,16875 19796,16875 L 19796,16875 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 19796,16875 C 18757,16875 17891,17019 17891,17192 17891,17365 18757,17510 19796,17510 20835,17510 21702,17365 21702,17192 21702,17019 20835,16875 19796,16875 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="18472" y="18476"><tspan fill="rgb(0,0,0)" stroke="none">Postgres db</tspan></tspan></tspan></text>
        </g>
       </g>
-      <g class="com.sun.star.drawing.CustomShape">
+      <g class="com.sun.star.drawing.LineShape">
        <g id="id38">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12811" y="19033" width="4065" height="636"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="13074" y="19472"><tspan fill="rgb(0,0,0)" stroke="none">Elastic compute nodes</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="10016" y="9381" width="2924" height="3"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 10017,9382 L 12938,9382"/>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id39">
-        <rect class="BoundingBox" stroke="none" fill="none" x="1000" y="1127" width="5843" height="2033"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="635px" font-weight="400"><tspan class="TextPosition" x="1190" y="2008"><tspan fill="rgb(0,0,0)" stroke="none">An Arvados cluster </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="635px" font-weight="400"><tspan class="TextPosition" x="1595" y="2719"><tspan fill="rgb(0,0,0)" stroke="none">From 30000 feet</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="12810" y="8491" width="3559" height="1654"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,10143 L 12811,10143 12811,8492 16367,8492 16367,10143 14589,10143 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,10143 L 12811,10143 12811,8492 16367,8492 16367,10143 14589,10143 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="14189" y="9489"><tspan fill="rgb(0,0,0)" stroke="none">API</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id40">
-        <rect class="BoundingBox" stroke="none" fill="none" x="19795" y="15985" width="3814" height="3306"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 21701,15986 C 20662,15986 19796,16173 19796,16398 L 19796,18876 C 19796,19101 20662,19289 21701,19289 22740,19289 23607,19101 23607,18876 L 23607,16398 C 23607,16173 22740,15986 21701,15986 L 21701,15986 Z M 19796,15986 L 19796,15986 Z M 23607,19289 L 23607,19289 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 21701,15986 C 20662,15986 19796,16173 19796,16398 L 19796,18876 C 19796,19101 20662,19289 21701,19289 22740,19289 23607,19101 23607,18876 L 23607,16398 C 23607,16173 22740,15986 21701,15986 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 19796,15986 L 19796,15986 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 23607,19289 L 23607,19289 Z"/>
-        <path fill="rgb(165,195,226)" stroke="none" d="M 21701,15986 C 20662,15986 19796,16173 19796,16398 19796,16624 20662,16811 21701,16811 22740,16811 23607,16624 23607,16398 23607,16173 22740,15986 21701,15986 L 21701,15986 Z M 19796,15986 L 19796,15986 Z M 23607,19289 L 23607,19289 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 21701,15986 C 20662,15986 19796,16173 19796,16398 19796,16624 20662,16811 21701,16811 22740,16811 23607,16624 23607,16398 23607,16173 22740,15986 21701,15986 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 19796,15986 L 19796,15986 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 23607,19289 L 23607,19289 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="20377" y="18015"><tspan fill="rgb(0,0,0)" stroke="none">Postgres db</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="9381" y="5062" width="10163" height="1400"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 14462,6460 L 9382,6460 9382,5063 19542,5063 19542,6460 14462,6460 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 14462,6460 L 9382,6460 9382,5063 19542,5063 19542,6460 14462,6460 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="12570" y="5656"><tspan fill="rgb(0,0,0)" stroke="none">Web Workbench,</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="12832" y="6211"><tspan fill="rgb(0,0,0)" stroke="none">CLI client tools</tspan></tspan></tspan></text>
        </g>
       </g>
       <g class="com.sun.star.drawing.LineShape">
        <g id="id41">
-        <rect class="BoundingBox" stroke="none" fill="none" x="10016" y="9381" width="2924" height="3"/>
-        <path fill="none" stroke="rgb(0,0,0)" d="M 10017,9382 L 12938,9382"/>
+        <rect class="BoundingBox" stroke="none" fill="none" x="15223" y="10143" width="3" height="5591"/>
+        <path fill="none" stroke="rgb(0,0,0)" d="M 15224,10144 L 15224,15732"/>
        </g>
       </g>
       <g class="com.sun.star.drawing.CustomShape">
        <g id="id42">
-        <rect class="BoundingBox" stroke="none" fill="none" x="12810" y="8491" width="3559" height="1654"/>
-        <path fill="rgb(114,159,207)" stroke="none" d="M 14589,10143 L 12811,10143 12811,8492 16367,8492 16367,10143 14589,10143 Z"/>
-        <path fill="none" stroke="rgb(52,101,164)" d="M 14589,10143 L 12811,10143 12811,8492 16367,8492 16367,10143 14589,10143 Z"/>
-        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="14189" y="9489"><tspan fill="rgb(0,0,0)" stroke="none">API</tspan></tspan></tspan></text>
+        <rect class="BoundingBox" stroke="none" fill="none" x="2269" y="17001" width="4576" height="2544"/>
+        <path fill="rgb(114,159,207)" stroke="none" d="M 4556,17002 C 3309,17002 2270,17146 2270,17319 L 2270,19225 C 2270,19398 3309,19543 4556,19543 5803,19543 6843,19398 6843,19225 L 6843,17319 C 6843,17146 5803,17002 4556,17002 L 4556,17002 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 4556,17002 C 3309,17002 2270,17146 2270,17319 L 2270,19225 C 2270,19398 3309,19543 4556,19543 5803,19543 6843,19398 6843,19225 L 6843,17319 C 6843,17146 5803,17002 4556,17002 Z"/>
+        <path fill="rgb(165,195,226)" stroke="none" d="M 4556,17002 C 3309,17002 2270,17146 2270,17319 2270,17492 3309,17637 4556,17637 5803,17637 6843,17492 6843,17319 6843,17146 5803,17002 4556,17002 L 4556,17002 Z"/>
+        <path fill="none" stroke="rgb(52,101,164)" d="M 4556,17002 C 3309,17002 2270,17146 2270,17319 2270,17492 3309,17637 4556,17637 5803,17637 6843,17492 6843,17319 6843,17146 5803,17002 4556,17002 Z"/>
+        <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="2681" y="18325"><tspan fill="rgb(0,0,0)" stroke="none">Storage backend</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="494px" font-weight="400"><tspan class="TextPosition" x="2844" y="18880"><tspan fill="rgb(0,0,0)" stroke="none">(filesystem, S3)</tspan></tspan></tspan></text>
        </g>
       </g>
      </g>
index 55095b1f20f05cb21e203a9ba6a39fa3f069a2dd..534309a7eb8dea2577b3d16c3bacf10795b8bd08 100644 (file)
@@ -11,6 +11,8 @@ SPDX-License-Identifier: CC-BY-SA-3.0
 
 Before attempting installation, you should begin by reviewing supported platforms, choosing backends for identity, storage, and scheduling, and decide how you will distribute Arvados services onto machines.  You should also choose an Arvados Cluster ID, choose your hostnames, and aquire TLS certificates.  It may be helpful to make notes as you go along using one of these worksheets:  "New cluster checklist for AWS":new_cluster_checklist_AWS.xlsx - "New cluster checklist for Azure":new_cluster_checklist_Azure.xlsx - "New cluster checklist for on premises Slurm":new_cluster_checklist_slurm.xlsx
 
+The installation guide describes how to set up a basic standalone Arvados instance.  Additional configuration for features including "federation,":{{site.baseurl}}/admin/federation.html "collection versioning,":{{site.baseurl}}/admin/collection-versioning.html "managed properties,":{{site.baseurl}}/admin/collection-managed-properties.html and "storage classes":{{site.baseurl}}/admin/collection-managed-properties.html are described in the "Admin guide.":{{site.baseurl}}/admin
+
 The Arvados storage subsystem is called "keep".  The compute subsystem is called "crunch".
 
 # "Supported GNU/Linux distributions":#supportedlinux
@@ -68,6 +70,7 @@ h2(#identity). Identity provider
 Choose which backend you will use to authenticate users.
 
 * Google login to authenticate users with a Google account.
+* OpenID Connect (OIDC) if you have Single-Sign-On (SSO) service that supports the OpenID Connect standard.
 * LDAP login to authenticate users by username/password using the LDAP protocol, supported by many services such as OpenLDAP and Active Directory.
 * PAM login to authenticate users by username/password according to the PAM configuration on the controller node.
 
index e1d25aaa23019020da809943b8309c1b10dc0d07..735ba5ca8719af5b39fb876bfde9e4b1a45f9ecb 100644 (file)
@@ -42,6 +42,8 @@ Get list of groups
 Delete a group
 @arv group delete --uuid 6dnxa-j7d0g-iw7i6n43d37jtog@
 
+Create an empty collection
+@arv collection create --collection '{"name": "test collection"}'@
 
 h3. Common commands
 
index 087aceffad73cc8a99857aca9b87f4f9bd1f65b2..9fd7c9e74941f8e12c47ae6bab60f5ea764fa422 100644 (file)
@@ -150,9 +150,8 @@ func (t *tester) Run() bool {
                        if time.Now().After(bootDeadline) {
                                t.Logger.Error("timed out")
                                return false
-                       } else {
-                               t.sleepSyncInterval()
                        }
+                       t.sleepSyncInterval()
                }
                t.Logger.WithField("Instance", t.testInstance.ID()).Info("new instance appeared")
                t.showLoginInfo()
index 15e7c7c06ce723114cafc86d8e4c6ec0c2b99dff..005d2738da5641bcadaea77b02fa351ce99298f1 100644 (file)
@@ -287,6 +287,20 @@ Clusters:
       # address is used.
       PreferDomainForUsername: ""
 
+      UserSetupMailText: |
+        <% if not @user.full_name.empty? -%>
+        <%= @user.full_name %>,
+        <% else -%>
+        Hi there,
+        <% end -%>
+
+        Your Arvados account has been set up.  You can log in at
+
+        <%= Rails.configuration.Services.Workbench1.ExternalURL %>
+
+        Thanks,
+        Your Arvados administrator.
+
     AuditLogs:
       # Time to keep audit logs, in seconds. (An audit log is a row added
       # to the "logs" table in the PostgreSQL database each time an
@@ -713,6 +727,17 @@ Clusters:
       # Default value zero means tokens don't have expiration.
       TokenLifetime: 0s
 
+      # When the token is returned to a client, the token itself may
+      # be restricted from manipulating other tokens based on whether
+      # the client is "trusted" or not.  The local Workbench1 and
+      # Workbench2 are trusted by default, but if this is a
+      # LoginCluster, you probably want to include the other Workbench
+      # instances in the federation in this list.
+      TrustedClients:
+        SAMPLE:
+          "https://workbench.federate1.example": {}
+          "https://workbench.federate2.example": {}
+
     Git:
       # Path to git or gitolite-shell executable. Each authenticated
       # request will execute this program with the single argument "http-backend"
index 6ab69d21fe13eaec3dff84a3ef74e8febc88ff1b..0735354b1b3a144da23a830d8c3eb2ebcd748f0b 100644 (file)
@@ -174,6 +174,7 @@ var whitelist = map[string]bool{
        "Login.Test.Enable":                            true,
        "Login.Test.Users":                             false,
        "Login.TokenLifetime":                          false,
+       "Login.TrustedClients":                         false,
        "Mail":                                         true,
        "Mail.EmailFrom":                               false,
        "Mail.IssueReporterEmailFrom":                  false,
@@ -214,6 +215,7 @@ var whitelist = map[string]bool{
        "Users.PreferDomainForUsername":                false,
        "Users.UserNotifierEmailFrom":                  false,
        "Users.UserProfileNotificationAddress":         false,
+       "Users.UserSetupMailText":                      false,
        "Volumes":                                      true,
        "Volumes.*":                                    true,
        "Volumes.*.*":                                  false,
index 7ed332151b8bbacaa81fa7352e8251058296b8c8..885bb4b8c5cf87e9552814c1799f69b1aa898746 100644 (file)
@@ -293,6 +293,20 @@ Clusters:
       # address is used.
       PreferDomainForUsername: ""
 
+      UserSetupMailText: |
+        <% if not @user.full_name.empty? -%>
+        <%= @user.full_name %>,
+        <% else -%>
+        Hi there,
+        <% end -%>
+
+        Your Arvados account has been set up.  You can log in at
+
+        <%= Rails.configuration.Services.Workbench1.ExternalURL %>
+
+        Thanks,
+        Your Arvados administrator.
+
     AuditLogs:
       # Time to keep audit logs, in seconds. (An audit log is a row added
       # to the "logs" table in the PostgreSQL database each time an
@@ -719,6 +733,17 @@ Clusters:
       # Default value zero means tokens don't have expiration.
       TokenLifetime: 0s
 
+      # When the token is returned to a client, the token itself may
+      # be restricted from manipulating other tokens based on whether
+      # the client is "trusted" or not.  The local Workbench1 and
+      # Workbench2 are trusted by default, but if this is a
+      # LoginCluster, you probably want to include the other Workbench
+      # instances in the federation in this list.
+      TrustedClients:
+        SAMPLE:
+          "https://workbench.federate1.example": {}
+          "https://workbench.federate2.example": {}
+
     Git:
       # Path to git or gitolite-shell executable. Each authenticated
       # request will execute this program with the single argument "http-backend"
index 61cac9bbabcd1d5128417fe0ab91041981afd207..f07c3b63167d577f722b085ff56de252a73f251f 100644 (file)
@@ -500,11 +500,24 @@ func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (
 }
 
 func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       resp, err := conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       if err != nil {
+               return resp, err
+       }
+       if options.UUID != resp.UUID {
+               return arvados.User{}, httpErrorf(http.StatusBadGateway, "Had requested %v but response was for %v", options.UUID, resp.UUID)
+       }
+       if options.UUID[:5] != conn.cluster.ClusterID {
+               err = conn.batchUpdateUsers(ctx, arvados.ListOptions{Select: options.Select}, []arvados.User{resp})
+               if err != nil {
+                       return arvados.User{}, err
+               }
+       }
+       return resp, nil
 }
 
 func (conn *Conn) UserGetCurrent(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGetCurrent(ctx, options)
+       return conn.local.UserGetCurrent(ctx, options)
 }
 
 func (conn *Conn) UserGetSystem(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
index ad91bcf8028d60960044a4c578a79320587a90ed..007f5df8b4726c7f24ebbcdf3b6ac0c46a202fbd 100644 (file)
@@ -43,8 +43,6 @@ func (s *LoginSuite) TestDeferToLoginCluster(c *check.C) {
 func (s *LoginSuite) TestLogout(c *check.C) {
        s.cluster.Services.Workbench1.ExternalURL = arvados.URL{Scheme: "https", Host: "workbench1.example.com"}
        s.cluster.Services.Workbench2.ExternalURL = arvados.URL{Scheme: "https", Host: "workbench2.example.com"}
-       s.cluster.Login.Google.Enable = true
-       s.cluster.Login.Google.ClientID = "zzzzzzzzzzzzzz"
        s.addHTTPRemote(c, "zhome", &arvadostest.APIStub{})
        s.cluster.Login.LoginCluster = "zhome"
        // s.fed is already set by SetUpTest, but we need to
index 09aa5086decd3eeb62c20874b64ad1308674668c..2812c1f41d5c6cd7aa3f02da5b6a06f051c6283a 100644 (file)
@@ -117,6 +117,60 @@ func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
        }
 }
 
+func (s *UserSuite) TestLoginClusterUserGet(c *check.C) {
+       s.cluster.ClusterID = "local"
+       s.cluster.Login.LoginCluster = "zzzzz"
+       s.fed = New(s.cluster)
+       s.addDirectRemote(c, "zzzzz", rpc.NewConn("zzzzz", &url.URL{Scheme: "https", Host: os.Getenv("ARVADOS_API_HOST")}, true, rpc.PassthroughTokenProvider))
+
+       opts := arvados.GetOptions{UUID: "zzzzz-tpzed-xurymjxw79nv3jz", Select: []string{"uuid", "email"}}
+
+       stub := &arvadostest.APIStub{Error: errors.New("local cluster failure")}
+       s.fed.local = stub
+       s.fed.UserGet(s.ctx, opts)
+
+       calls := stub.Calls(stub.UserBatchUpdate)
+       if c.Check(calls, check.HasLen, 1) {
+               c.Logf("... stub.UserUpdate called with options: %#v", calls[0].Options)
+               shouldUpdate := map[string]bool{
+                       "uuid":       false,
+                       "email":      true,
+                       "first_name": true,
+                       "last_name":  true,
+                       "is_admin":   true,
+                       "is_active":  true,
+                       "prefs":      true,
+                       // can't safely update locally
+                       "owner_uuid":   false,
+                       "identity_url": false,
+                       // virtual attrs
+                       "full_name":  false,
+                       "is_invited": false,
+               }
+               if opts.Select != nil {
+                       // Only the selected
+                       // fields (minus uuid)
+                       // should be updated.
+                       for k := range shouldUpdate {
+                               shouldUpdate[k] = false
+                       }
+                       for _, k := range opts.Select {
+                               if k != "uuid" {
+                                       shouldUpdate[k] = true
+                               }
+                       }
+               }
+               var uuid string
+               for uuid = range calls[0].Options.(arvados.UserBatchUpdateOptions).Updates {
+               }
+               for k, shouldFind := range shouldUpdate {
+                       _, found := calls[0].Options.(arvados.UserBatchUpdateOptions).Updates[uuid][k]
+                       c.Check(found, check.Equals, shouldFind, check.Commentf("offending attr: %s", k))
+               }
+       }
+
+}
+
 func (s *UserSuite) TestLoginClusterUserListBypassFederation(c *check.C) {
        s.cluster.ClusterID = "local"
        s.cluster.Login.LoginCluster = "zzzzz"
index 12674148426133fa97f1ef786b38cf6803b1c376..f4632751e30dc24944d04157e939d676ee33c53a 100644 (file)
@@ -34,10 +34,11 @@ func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) log
        wantPAM := cluster.Login.PAM.Enable
        wantLDAP := cluster.Login.LDAP.Enable
        wantTest := cluster.Login.Test.Enable
+       wantLoginCluster := cluster.Login.LoginCluster != "" && cluster.Login.LoginCluster != cluster.ClusterID
        switch {
-       case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantSSO, wantPAM, wantLDAP, wantTest):
+       case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantSSO, wantPAM, wantLDAP, wantTest, wantLoginCluster):
                return errorLoginController{
-                       error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.SSO, Login.PAM, Login.LDAP, and Login.Test must be enabled"),
+                       error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.SSO, Login.PAM, Login.LDAP, Login.Test, or Login.LoginCluster must be set"),
                }
        case wantGoogle:
                return &oidcLoginController{
@@ -69,6 +70,8 @@ func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) log
                return &ldapLoginController{Cluster: cluster, RailsProxy: railsProxy}
        case wantTest:
                return &testLoginController{Cluster: cluster, RailsProxy: railsProxy}
+       case wantLoginCluster:
+               return &federatedLoginController{Cluster: cluster}
        default:
                return errorLoginController{
                        error: errors.New("BUG: missing case in login controller setup switch"),
@@ -106,6 +109,20 @@ func (ctrl errorLoginController) UserAuthenticate(context.Context, arvados.UserA
        return arvados.APIClientAuthorization{}, ctrl.error
 }
 
+type federatedLoginController struct {
+       Cluster *arvados.Cluster
+}
+
+func (ctrl federatedLoginController) Login(context.Context, arvados.LoginOptions) (arvados.LoginResponse, error) {
+       return arvados.LoginResponse{}, httpserver.ErrorWithStatus(errors.New("Should have been redirected to login cluster"), http.StatusBadRequest)
+}
+func (ctrl federatedLoginController) Logout(_ context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
+       return noopLogout(ctrl.Cluster, opts)
+}
+func (ctrl federatedLoginController) UserAuthenticate(context.Context, arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
+       return arvados.APIClientAuthorization{}, httpserver.ErrorWithStatus(errors.New("username/password authentication is not available"), http.StatusBadRequest)
+}
+
 func noopLogout(cluster *arvados.Cluster, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
        target := opts.ReturnTo
        if target == "" {
@@ -124,7 +141,7 @@ func createAPIClientAuthorization(ctx context.Context, conn *rpc.Conn, rootToken
                // Send a fake ReturnTo value instead of the caller's
                // opts.ReturnTo. We won't follow the resulting
                // redirect target anyway.
-               ReturnTo: ",https://none.invalid",
+               ReturnTo: ",https://controller.api.client.invalid",
                AuthInfo: authinfo,
        })
        if err != nil {
index e9c6e82f6e2c8c6dac3255fce957ff28d199505f..5852273529e6434b2f54ce7fcb551a85eb360880 100644 (file)
@@ -82,7 +82,7 @@ const loginform = `
          redir += '?'
        }
         const respj = await resp.json()
-       document.location = redir + "api_token=" + respj.api_token
+       document.location = redir + "api_token=v2/" + respj.uuid + "/" + respj.api_token
       }
     </script>
   </head>
index d5de184e5c41bf8e9dc434fe226d8d5ed17fa1f9..febfb1404d32b4f59776a97c45692d7b5c5ab0a9 100644 (file)
@@ -368,9 +368,8 @@ func (arvlog *ArvLogWriter) rateLimit(line []byte, now time.Time) (bool, []byte)
                // instead of the log message that exceeded the limit.
                message += " A complete log is still being written to Keep, and will be available when the job finishes."
                return true, []byte(message)
-       } else {
-               return arvlog.logThrottleIsOpen, line
        }
+       return arvlog.logThrottleIsOpen, line
 }
 
 // load the rate limit discovery config parameters
index a1ff414b73ecbd3be22276b716a64af6eaa3f225..7a2727c1e9532271cb5e7df52f1a383e49f2584f 100644 (file)
@@ -145,11 +145,11 @@ func (cq *Queue) Forget(uuid string) {
 func (cq *Queue) Get(uuid string) (arvados.Container, bool) {
        cq.mtx.Lock()
        defer cq.mtx.Unlock()
-       if ctr, ok := cq.current[uuid]; !ok {
+       ctr, ok := cq.current[uuid]
+       if !ok {
                return arvados.Container{}, false
-       } else {
-               return ctr.Container, true
        }
+       return ctr.Container, true
 }
 
 // Entries returns all cache entries, keyed by container UUID.
index 8a8f686e168ff6372f0c19813d31cd2ced26509c..3598ec6da05baf23d3eaed302ec8db603f38e96c 100644 (file)
@@ -172,12 +172,11 @@ func (q *Queue) Notify(upd arvados.Container) bool {
                        if allowContainerUpdate[ctr.State][upd.State] {
                                q.Containers[i] = upd
                                return true
-                       } else {
-                               if q.Logger != nil {
-                                       q.Logger.WithField("ContainerUUID", ctr.UUID).Infof("test.Queue rejected update from %s to %s", ctr.State, upd.State)
-                               }
-                               return false
                        }
+                       if q.Logger != nil {
+                               q.Logger.WithField("ContainerUUID", ctr.UUID).Infof("test.Queue rejected update from %s to %s", ctr.State, upd.State)
+                       }
+                       return false
                }
        }
        q.Containers = append(q.Containers, upd)
index b16d5bfc272b3ba3d3ddcfb8ad817e89ba316f9d..15ff0607a9a927e9659ac581d786e393b51f6c44 100644 (file)
@@ -146,6 +146,11 @@ func (installCommand) RunCommand(prog string, args []string, stdin io.Reader, st
                        "python3-virtualenv",
                        "r-base",
                        "r-cran-testthat",
+                       "r-cran-devtools",
+                       "r-cran-knitr",
+                       "r-cran-markdown",
+                       "r-cran-roxygen2",
+                       "r-cran-xml",
                        "sudo",
                        "wget",
                        "xvfb",
index 37ed4b86ab9ca58a5fbd7a95632204069d39100d..3d695bf96b7d5caf01d2b12d1636b8aacc7ed048 100644 (file)
@@ -2,11 +2,10 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is packaged as /usr/share/pam-configs/arvados-go; see build/run-library.sh
-
-# 1. Run `pam-auth-update` and choose Arvados authentication
-# 2. In /etc/pam.d/common-auth, change "api.example" to your ARVADOS_API_HOST
-# 3. In /etc/pam.d/common-auth, change "shell.example" to this host's hostname
+# 1. Copy the contents of this file *minus all comment lines* to /usr/share/pam-configs/arvados-go
+# 2. Run `pam-auth-update` and choose Arvados authentication
+# 3. In /etc/pam.d/common-auth, change "api.example" to your ARVADOS_API_HOST
+# 4. In /etc/pam.d/common-auth, change "shell.example" to this host's hostname
 #    (as it appears in the Arvados virtual_machines list)
 
 Name: Arvados authentication
index 878a70901452b47e2710a52be85504179767ea38..75ac892b4ba6680a7af4c91e47f1e770fcd7020c 100644 (file)
@@ -1,9 +1,9 @@
 Package: ArvadosR
 Type: Package
 Title: Arvados R SDK
-Version: 0.0.5
-Authors@R: person("Fuad", "Muhic", role = c("aut", "cre"), email = "fmuhic@capeannenterprises.com")
-Maintainer: Ward Vandewege <wvandewege@veritasgenetics.com>
+Version: 0.0.6
+Authors@R: c(person("Fuad", "Muhic", role = c("aut", "ctr"), email = "fmuhic@capeannenterprises.com"),
+             person("Peter", "Amstutz", role = c("cre"), email = "peter.amstutz@curii.com"))
 Description: This is the Arvados R SDK
 URL: http://doc.arvados.org
 License: Apache-2.0
index 744cb3c296163906be8be5858e0713e8d43aa44e..528a60665043d90cba5c785c45fd20615538499c 100644 (file)
-#' users.get
-#' 
-#' users.get is a method defined in Arvados class.
-#' 
-#' @usage arv$users.get(uuid)
-#' @param uuid The UUID of the User in question.
-#' @return User object.
-#' @name users.get
-NULL
-
-#' users.create
-#' 
-#' users.create is a method defined in Arvados class.
-#' 
-#' @usage arv$users.create(user, ensure_unique_name = "false")
-#' @param user User object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return User object.
-#' @name users.create
-NULL
-
-#' users.update
-#' 
-#' users.update is a method defined in Arvados class.
-#' 
-#' @usage arv$users.update(user, uuid)
-#' @param user User object.
-#' @param uuid The UUID of the User in question.
-#' @return User object.
-#' @name users.update
-NULL
-
-#' users.delete
-#' 
-#' users.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$users.delete(uuid)
-#' @param uuid The UUID of the User in question.
-#' @return User object.
-#' @name users.delete
-NULL
-
-#' users.current
-#' 
-#' users.current is a method defined in Arvados class.
-#' 
-#' @usage arv$users.current(NULL)
-#' @return User object.
-#' @name users.current
-NULL
-
-#' users.system
-#' 
-#' users.system is a method defined in Arvados class.
-#' 
-#' @usage arv$users.system(NULL)
-#' @return User object.
-#' @name users.system
-NULL
-
-#' users.activate
-#' 
-#' users.activate is a method defined in Arvados class.
-#' 
-#' @usage arv$users.activate(uuid)
-#' @param uuid 
-#' @return User object.
-#' @name users.activate
-NULL
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
 
-#' users.setup
+#' api_clients.get
 #' 
-#' users.setup is a method defined in Arvados class.
+#' api_clients.get is a method defined in Arvados class.
 #' 
-#' @usage arv$users.setup(user = NULL, openid_prefix = NULL,
-#'     repo_name = NULL, vm_uuid = NULL, send_notification_email = "false")
-#' @param user 
-#' @param openid_prefix 
-#' @param repo_name 
-#' @param vm_uuid 
-#' @param send_notification_email 
-#' @return User object.
-#' @name users.setup
+#' @usage arv$api_clients.get(uuid)
+#' @param uuid The UUID of the ApiClient in question.
+#' @return ApiClient object.
+#' @name api_clients.get
 NULL
 
-#' users.unsetup
+#' api_clients.create
 #' 
-#' users.unsetup is a method defined in Arvados class.
+#' api_clients.create is a method defined in Arvados class.
 #' 
-#' @usage arv$users.unsetup(uuid)
-#' @param uuid 
-#' @return User object.
-#' @name users.unsetup
+#' @usage arv$api_clients.create(apiclient,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param apiClient ApiClient object.
+#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return ApiClient object.
+#' @name api_clients.create
 NULL
 
-#' users.update_uuid
+#' api_clients.update
 #' 
-#' users.update_uuid is a method defined in Arvados class.
+#' api_clients.update is a method defined in Arvados class.
 #' 
-#' @usage arv$users.update_uuid(uuid, new_uuid)
-#' @param uuid 
-#' @param new_uuid 
-#' @return User object.
-#' @name users.update_uuid
+#' @usage arv$api_clients.update(apiclient,
+#'     uuid)
+#' @param apiClient ApiClient object.
+#' @param uuid The UUID of the ApiClient in question.
+#' @return ApiClient object.
+#' @name api_clients.update
 NULL
 
-#' users.merge
+#' api_clients.delete
 #' 
-#' users.merge is a method defined in Arvados class.
+#' api_clients.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$users.merge(new_owner_uuid,
-#'     new_user_token, redirect_to_new_user = NULL)
-#' @param new_owner_uuid 
-#' @param new_user_token 
-#' @param redirect_to_new_user 
-#' @return User object.
-#' @name users.merge
+#' @usage arv$api_clients.delete(uuid)
+#' @param uuid The UUID of the ApiClient in question.
+#' @return ApiClient object.
+#' @name api_clients.delete
 NULL
 
-#' users.list
+#' api_clients.list
 #' 
-#' users.list is a method defined in Arvados class.
+#' api_clients.list is a method defined in Arvados class.
 #' 
-#' @usage arv$users.list(filters = NULL,
+#' @usage arv$api_clients.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -133,8 +63,10 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return UserList object.
-#' @name users.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return ApiClientList object.
+#' @name api_clients.list
 NULL
 
 #' api_client_authorizations.get
@@ -152,9 +84,10 @@ NULL
 #' api_client_authorizations.create is a method defined in Arvados class.
 #' 
 #' @usage arv$api_client_authorizations.create(apiclientauthorization,
-#'     ensure_unique_name = "false")
+#'     ensure_unique_name = "false", cluster_id = NULL)
 #' @param apiClientAuthorization ApiClientAuthorization object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
 #' @return ApiClientAuthorization object.
 #' @name api_client_authorizations.create
 NULL
@@ -209,7 +142,7 @@ NULL
 #' @usage arv$api_client_authorizations.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -218,111 +151,173 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
 #' @return ApiClientAuthorizationList object.
 #' @name api_client_authorizations.list
 NULL
 
-#' containers.get
+#' authorized_keys.get
 #' 
-#' containers.get is a method defined in Arvados class.
+#' authorized_keys.get is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.get(uuid)
-#' @param uuid The UUID of the Container in question.
-#' @return Container object.
-#' @name containers.get
+#' @usage arv$authorized_keys.get(uuid)
+#' @param uuid The UUID of the AuthorizedKey in question.
+#' @return AuthorizedKey object.
+#' @name authorized_keys.get
 NULL
 
-#' containers.create
+#' authorized_keys.create
 #' 
-#' containers.create is a method defined in Arvados class.
+#' authorized_keys.create is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.create(container,
-#'     ensure_unique_name = "false")
-#' @param container Container object.
+#' @usage arv$authorized_keys.create(authorizedkey,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param authorizedKey AuthorizedKey object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Container object.
-#' @name containers.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return AuthorizedKey object.
+#' @name authorized_keys.create
 NULL
 
-#' containers.update
+#' authorized_keys.update
 #' 
-#' containers.update is a method defined in Arvados class.
+#' authorized_keys.update is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.update(container,
+#' @usage arv$authorized_keys.update(authorizedkey,
 #'     uuid)
-#' @param container Container object.
-#' @param uuid The UUID of the Container in question.
-#' @return Container object.
-#' @name containers.update
+#' @param authorizedKey AuthorizedKey object.
+#' @param uuid The UUID of the AuthorizedKey in question.
+#' @return AuthorizedKey object.
+#' @name authorized_keys.update
 NULL
 
-#' containers.delete
+#' authorized_keys.delete
 #' 
-#' containers.delete is a method defined in Arvados class.
+#' authorized_keys.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.delete(uuid)
-#' @param uuid The UUID of the Container in question.
-#' @return Container object.
-#' @name containers.delete
+#' @usage arv$authorized_keys.delete(uuid)
+#' @param uuid The UUID of the AuthorizedKey in question.
+#' @return AuthorizedKey object.
+#' @name authorized_keys.delete
 NULL
 
-#' containers.auth
+#' authorized_keys.list
 #' 
-#' containers.auth is a method defined in Arvados class.
+#' authorized_keys.list is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.auth(uuid)
-#' @param uuid 
-#' @return Container object.
-#' @name containers.auth
+#' @usage arv$authorized_keys.list(filters = NULL,
+#'     where = NULL, order = NULL, select = NULL,
+#'     distinct = NULL, limit = "100", offset = "0",
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
+#' @param filters 
+#' @param where 
+#' @param order 
+#' @param select 
+#' @param distinct 
+#' @param limit 
+#' @param offset 
+#' @param count 
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return AuthorizedKeyList object.
+#' @name authorized_keys.list
 NULL
 
-#' containers.lock
+#' collections.get
 #' 
-#' containers.lock is a method defined in Arvados class.
+#' collections.get is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.lock(uuid)
-#' @param uuid 
-#' @return Container object.
-#' @name containers.lock
+#' @usage arv$collections.get(uuid)
+#' @param uuid The UUID of the Collection in question.
+#' @return Collection object.
+#' @name collections.get
 NULL
 
-#' containers.unlock
+#' collections.create
 #' 
-#' containers.unlock is a method defined in Arvados class.
+#' collections.create is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.unlock(uuid)
-#' @param uuid 
-#' @return Container object.
-#' @name containers.unlock
+#' @usage arv$collections.create(collection,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param collection Collection object.
+#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Collection object.
+#' @name collections.create
 NULL
 
-#' containers.secret_mounts
+#' collections.update
 #' 
-#' containers.secret_mounts is a method defined in Arvados class.
+#' collections.update is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.secret_mounts(uuid)
-#' @param uuid 
-#' @return Container object.
-#' @name containers.secret_mounts
+#' @usage arv$collections.update(collection,
+#'     uuid)
+#' @param collection Collection object.
+#' @param uuid The UUID of the Collection in question.
+#' @return Collection object.
+#' @name collections.update
 NULL
 
-#' containers.current
+#' collections.delete
 #' 
-#' containers.current is a method defined in Arvados class.
+#' collections.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.current(NULL)
-#' @return Container object.
-#' @name containers.current
+#' @usage arv$collections.delete(uuid)
+#' @param uuid The UUID of the Collection in question.
+#' @return Collection object.
+#' @name collections.delete
 NULL
 
-#' containers.list
+#' collections.provenance
 #' 
-#' containers.list is a method defined in Arvados class.
+#' collections.provenance is a method defined in Arvados class.
 #' 
-#' @usage arv$containers.list(filters = NULL,
+#' @usage arv$collections.provenance(uuid)
+#' @param uuid 
+#' @return Collection object.
+#' @name collections.provenance
+NULL
+
+#' collections.used_by
+#' 
+#' collections.used_by is a method defined in Arvados class.
+#' 
+#' @usage arv$collections.used_by(uuid)
+#' @param uuid 
+#' @return Collection object.
+#' @name collections.used_by
+NULL
+
+#' collections.trash
+#' 
+#' collections.trash is a method defined in Arvados class.
+#' 
+#' @usage arv$collections.trash(uuid)
+#' @param uuid 
+#' @return Collection object.
+#' @name collections.trash
+NULL
+
+#' collections.untrash
+#' 
+#' collections.untrash is a method defined in Arvados class.
+#' 
+#' @usage arv$collections.untrash(uuid)
+#' @param uuid 
+#' @return Collection object.
+#' @name collections.untrash
+NULL
+
+#' collections.list
+#' 
+#' collections.list is a method defined in Arvados class.
+#' 
+#' @usage arv$collections.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL,
+#'     include_trash = NULL, include_old_versions = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -331,62 +326,116 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return ContainerList object.
-#' @name containers.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @param include_trash Include collections whose is_trashed attribute is true.
+#' @param include_old_versions Include past collection versions.
+#' @return CollectionList object.
+#' @name collections.list
 NULL
 
-#' api_clients.get
+#' containers.get
 #' 
-#' api_clients.get is a method defined in Arvados class.
+#' containers.get is a method defined in Arvados class.
 #' 
-#' @usage arv$api_clients.get(uuid)
-#' @param uuid The UUID of the ApiClient in question.
-#' @return ApiClient object.
-#' @name api_clients.get
+#' @usage arv$containers.get(uuid)
+#' @param uuid The UUID of the Container in question.
+#' @return Container object.
+#' @name containers.get
 NULL
 
-#' api_clients.create
+#' containers.create
 #' 
-#' api_clients.create is a method defined in Arvados class.
+#' containers.create is a method defined in Arvados class.
 #' 
-#' @usage arv$api_clients.create(apiclient,
-#'     ensure_unique_name = "false")
-#' @param apiClient ApiClient object.
+#' @usage arv$containers.create(container,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param container Container object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return ApiClient object.
-#' @name api_clients.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Container object.
+#' @name containers.create
 NULL
 
-#' api_clients.update
+#' containers.update
 #' 
-#' api_clients.update is a method defined in Arvados class.
+#' containers.update is a method defined in Arvados class.
 #' 
-#' @usage arv$api_clients.update(apiclient,
+#' @usage arv$containers.update(container,
 #'     uuid)
-#' @param apiClient ApiClient object.
-#' @param uuid The UUID of the ApiClient in question.
-#' @return ApiClient object.
-#' @name api_clients.update
+#' @param container Container object.
+#' @param uuid The UUID of the Container in question.
+#' @return Container object.
+#' @name containers.update
 NULL
 
-#' api_clients.delete
+#' containers.delete
 #' 
-#' api_clients.delete is a method defined in Arvados class.
+#' containers.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$api_clients.delete(uuid)
-#' @param uuid The UUID of the ApiClient in question.
-#' @return ApiClient object.
-#' @name api_clients.delete
+#' @usage arv$containers.delete(uuid)
+#' @param uuid The UUID of the Container in question.
+#' @return Container object.
+#' @name containers.delete
 NULL
 
-#' api_clients.list
+#' containers.auth
 #' 
-#' api_clients.list is a method defined in Arvados class.
+#' containers.auth is a method defined in Arvados class.
 #' 
-#' @usage arv$api_clients.list(filters = NULL,
+#' @usage arv$containers.auth(uuid)
+#' @param uuid 
+#' @return Container object.
+#' @name containers.auth
+NULL
+
+#' containers.lock
+#' 
+#' containers.lock is a method defined in Arvados class.
+#' 
+#' @usage arv$containers.lock(uuid)
+#' @param uuid 
+#' @return Container object.
+#' @name containers.lock
+NULL
+
+#' containers.unlock
+#' 
+#' containers.unlock is a method defined in Arvados class.
+#' 
+#' @usage arv$containers.unlock(uuid)
+#' @param uuid 
+#' @return Container object.
+#' @name containers.unlock
+NULL
+
+#' containers.secret_mounts
+#' 
+#' containers.secret_mounts is a method defined in Arvados class.
+#' 
+#' @usage arv$containers.secret_mounts(uuid)
+#' @param uuid 
+#' @return Container object.
+#' @name containers.secret_mounts
+NULL
+
+#' containers.current
+#' 
+#' containers.current is a method defined in Arvados class.
+#' 
+#' @usage arv$containers.current(NULL)
+#' @return Container object.
+#' @name containers.current
+NULL
+
+#' containers.list
+#' 
+#' containers.list is a method defined in Arvados class.
+#' 
+#' @usage arv$containers.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -395,8 +444,10 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return ApiClientList object.
-#' @name api_clients.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return ContainerList object.
+#' @name containers.list
 NULL
 
 #' container_requests.get
@@ -414,9 +465,10 @@ NULL
 #' container_requests.create is a method defined in Arvados class.
 #' 
 #' @usage arv$container_requests.create(containerrequest,
-#'     ensure_unique_name = "false")
+#'     ensure_unique_name = "false", cluster_id = NULL)
 #' @param containerRequest ContainerRequest object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
 #' @return ContainerRequest object.
 #' @name container_requests.create
 NULL
@@ -450,7 +502,8 @@ NULL
 #' @usage arv$container_requests.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL,
+#'     include_trash = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -459,62 +512,96 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @param include_trash Include container requests whose owner project is trashed.
 #' @return ContainerRequestList object.
 #' @name container_requests.list
 NULL
 
-#' authorized_keys.get
+#' groups.get
 #' 
-#' authorized_keys.get is a method defined in Arvados class.
+#' groups.get is a method defined in Arvados class.
 #' 
-#' @usage arv$authorized_keys.get(uuid)
-#' @param uuid The UUID of the AuthorizedKey in question.
-#' @return AuthorizedKey object.
-#' @name authorized_keys.get
+#' @usage arv$groups.get(uuid)
+#' @param uuid The UUID of the Group in question.
+#' @return Group object.
+#' @name groups.get
 NULL
 
-#' authorized_keys.create
+#' groups.create
 #' 
-#' authorized_keys.create is a method defined in Arvados class.
+#' groups.create is a method defined in Arvados class.
 #' 
-#' @usage arv$authorized_keys.create(authorizedkey,
-#'     ensure_unique_name = "false")
-#' @param authorizedKey AuthorizedKey object.
+#' @usage arv$groups.create(group, ensure_unique_name = "false",
+#'     cluster_id = NULL, async = "false")
+#' @param group Group object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return AuthorizedKey object.
-#' @name authorized_keys.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @param async defer permissions update
+#' @return Group object.
+#' @name groups.create
 NULL
 
-#' authorized_keys.update
+#' groups.update
 #' 
-#' authorized_keys.update is a method defined in Arvados class.
+#' groups.update is a method defined in Arvados class.
 #' 
-#' @usage arv$authorized_keys.update(authorizedkey,
-#'     uuid)
-#' @param authorizedKey AuthorizedKey object.
-#' @param uuid The UUID of the AuthorizedKey in question.
-#' @return AuthorizedKey object.
-#' @name authorized_keys.update
+#' @usage arv$groups.update(group, uuid,
+#'     async = "false")
+#' @param group Group object.
+#' @param uuid The UUID of the Group in question.
+#' @param async defer permissions update
+#' @return Group object.
+#' @name groups.update
 NULL
 
-#' authorized_keys.delete
+#' groups.delete
 #' 
-#' authorized_keys.delete is a method defined in Arvados class.
+#' groups.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$authorized_keys.delete(uuid)
-#' @param uuid The UUID of the AuthorizedKey in question.
-#' @return AuthorizedKey object.
-#' @name authorized_keys.delete
+#' @usage arv$groups.delete(uuid)
+#' @param uuid The UUID of the Group in question.
+#' @return Group object.
+#' @name groups.delete
 NULL
 
-#' authorized_keys.list
+#' groups.contents
 #' 
-#' authorized_keys.list is a method defined in Arvados class.
+#' groups.contents is a method defined in Arvados class.
 #' 
-#' @usage arv$authorized_keys.list(filters = NULL,
+#' @usage arv$groups.contents(filters = NULL,
+#'     where = NULL, order = NULL, distinct = NULL,
+#'     limit = "100", offset = "0", count = "exact",
+#'     cluster_id = NULL, bypass_federation = NULL,
+#'     include_trash = NULL, uuid = NULL, recursive = NULL,
+#'     include = NULL)
+#' @param filters 
+#' @param where 
+#' @param order 
+#' @param distinct 
+#' @param limit 
+#' @param offset 
+#' @param count 
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @param include_trash Include items whose is_trashed attribute is true.
+#' @param uuid 
+#' @param recursive Include contents from child groups recursively.
+#' @param include Include objects referred to by listed field in "included" (only owner_uuid)
+#' @return Group object.
+#' @name groups.contents
+NULL
+
+#' groups.shared
+#' 
+#' groups.shared is a method defined in Arvados class.
+#' 
+#' @usage arv$groups.shared(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL,
+#'     include_trash = NULL, include = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -523,102 +610,120 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return AuthorizedKeyList object.
-#' @name authorized_keys.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @param include_trash Include items whose is_trashed attribute is true.
+#' @param include 
+#' @return Group object.
+#' @name groups.shared
 NULL
 
-#' collections.get
+#' groups.trash
 #' 
-#' collections.get is a method defined in Arvados class.
+#' groups.trash is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.get(uuid)
-#' @param uuid The UUID of the Collection in question.
-#' @return Collection object.
-#' @name collections.get
+#' @usage arv$groups.trash(uuid)
+#' @param uuid 
+#' @return Group object.
+#' @name groups.trash
 NULL
 
-#' collections.create
+#' groups.untrash
 #' 
-#' collections.create is a method defined in Arvados class.
+#' groups.untrash is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.create(collection,
-#'     ensure_unique_name = "false")
-#' @param collection Collection object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Collection object.
-#' @name collections.create
+#' @usage arv$groups.untrash(uuid)
+#' @param uuid 
+#' @return Group object.
+#' @name groups.untrash
 NULL
 
-#' collections.update
+#' groups.list
 #' 
-#' collections.update is a method defined in Arvados class.
+#' groups.list is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.update(collection,
-#'     uuid)
-#' @param collection Collection object.
-#' @param uuid The UUID of the Collection in question.
-#' @return Collection object.
-#' @name collections.update
+#' @usage arv$groups.list(filters = NULL,
+#'     where = NULL, order = NULL, select = NULL,
+#'     distinct = NULL, limit = "100", offset = "0",
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL,
+#'     include_trash = NULL)
+#' @param filters 
+#' @param where 
+#' @param order 
+#' @param select 
+#' @param distinct 
+#' @param limit 
+#' @param offset 
+#' @param count 
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @param include_trash Include items whose is_trashed attribute is true.
+#' @return GroupList object.
+#' @name groups.list
 NULL
 
-#' collections.delete
+#' keep_services.get
 #' 
-#' collections.delete is a method defined in Arvados class.
+#' keep_services.get is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.delete(uuid)
-#' @param uuid The UUID of the Collection in question.
-#' @return Collection object.
-#' @name collections.delete
+#' @usage arv$keep_services.get(uuid)
+#' @param uuid The UUID of the KeepService in question.
+#' @return KeepService object.
+#' @name keep_services.get
 NULL
 
-#' collections.provenance
+#' keep_services.create
 #' 
-#' collections.provenance is a method defined in Arvados class.
+#' keep_services.create is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.provenance(uuid)
-#' @param uuid 
-#' @return Collection object.
-#' @name collections.provenance
+#' @usage arv$keep_services.create(keepservice,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param keepService KeepService object.
+#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return KeepService object.
+#' @name keep_services.create
 NULL
 
-#' collections.used_by
+#' keep_services.update
 #' 
-#' collections.used_by is a method defined in Arvados class.
+#' keep_services.update is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.used_by(uuid)
-#' @param uuid 
-#' @return Collection object.
-#' @name collections.used_by
+#' @usage arv$keep_services.update(keepservice,
+#'     uuid)
+#' @param keepService KeepService object.
+#' @param uuid The UUID of the KeepService in question.
+#' @return KeepService object.
+#' @name keep_services.update
 NULL
 
-#' collections.trash
+#' keep_services.delete
 #' 
-#' collections.trash is a method defined in Arvados class.
+#' keep_services.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.trash(uuid)
-#' @param uuid 
-#' @return Collection object.
-#' @name collections.trash
+#' @usage arv$keep_services.delete(uuid)
+#' @param uuid The UUID of the KeepService in question.
+#' @return KeepService object.
+#' @name keep_services.delete
 NULL
 
-#' collections.untrash
+#' keep_services.accessible
 #' 
-#' collections.untrash is a method defined in Arvados class.
+#' keep_services.accessible is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.untrash(uuid)
-#' @param uuid 
-#' @return Collection object.
-#' @name collections.untrash
+#' @usage arv$keep_services.accessible(NULL)
+#' @return KeepService object.
+#' @name keep_services.accessible
 NULL
 
-#' collections.list
+#' keep_services.list
 #' 
-#' collections.list is a method defined in Arvados class.
+#' keep_services.list is a method defined in Arvados class.
 #' 
-#' @usage arv$collections.list(filters = NULL,
+#' @usage arv$keep_services.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact", include_trash = NULL)
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -627,61 +732,64 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @param include_trash Include collections whose is_trashed attribute is true.
-#' @return CollectionList object.
-#' @name collections.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return KeepServiceList object.
+#' @name keep_services.list
 NULL
 
-#' humans.get
+#' links.get
 #' 
-#' humans.get is a method defined in Arvados class.
+#' links.get is a method defined in Arvados class.
 #' 
-#' @usage arv$humans.get(uuid)
-#' @param uuid The UUID of the Human in question.
-#' @return Human object.
-#' @name humans.get
+#' @usage arv$links.get(uuid)
+#' @param uuid The UUID of the Link in question.
+#' @return Link object.
+#' @name links.get
 NULL
 
-#' humans.create
+#' links.create
 #' 
-#' humans.create is a method defined in Arvados class.
+#' links.create is a method defined in Arvados class.
 #' 
-#' @usage arv$humans.create(human, ensure_unique_name = "false")
-#' @param human Human object.
+#' @usage arv$links.create(link, ensure_unique_name = "false",
+#'     cluster_id = NULL)
+#' @param link Link object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Human object.
-#' @name humans.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Link object.
+#' @name links.create
 NULL
 
-#' humans.update
+#' links.update
 #' 
-#' humans.update is a method defined in Arvados class.
+#' links.update is a method defined in Arvados class.
 #' 
-#' @usage arv$humans.update(human, uuid)
-#' @param human Human object.
-#' @param uuid The UUID of the Human in question.
-#' @return Human object.
-#' @name humans.update
+#' @usage arv$links.update(link, uuid)
+#' @param link Link object.
+#' @param uuid The UUID of the Link in question.
+#' @return Link object.
+#' @name links.update
 NULL
 
-#' humans.delete
+#' links.delete
 #' 
-#' humans.delete is a method defined in Arvados class.
+#' links.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$humans.delete(uuid)
-#' @param uuid The UUID of the Human in question.
-#' @return Human object.
-#' @name humans.delete
+#' @usage arv$links.delete(uuid)
+#' @param uuid The UUID of the Link in question.
+#' @return Link object.
+#' @name links.delete
 NULL
 
-#' humans.list
+#' links.list
 #' 
-#' humans.list is a method defined in Arvados class.
+#' links.list is a method defined in Arvados class.
 #' 
-#' @usage arv$humans.list(filters = NULL,
+#' @usage arv$links.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -690,60 +798,74 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return HumanList object.
-#' @name humans.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return LinkList object.
+#' @name links.list
+NULL
+
+#' links.get_permissions
+#' 
+#' links.get_permissions is a method defined in Arvados class.
+#' 
+#' @usage arv$links.get_permissions(uuid)
+#' @param uuid 
+#' @return Link object.
+#' @name links.get_permissions
 NULL
 
-#' job_tasks.get
+#' logs.get
 #' 
-#' job_tasks.get is a method defined in Arvados class.
+#' logs.get is a method defined in Arvados class.
 #' 
-#' @usage arv$job_tasks.get(uuid)
-#' @param uuid The UUID of the JobTask in question.
-#' @return JobTask object.
-#' @name job_tasks.get
+#' @usage arv$logs.get(uuid)
+#' @param uuid The UUID of the Log in question.
+#' @return Log object.
+#' @name logs.get
 NULL
 
-#' job_tasks.create
+#' logs.create
 #' 
-#' job_tasks.create is a method defined in Arvados class.
+#' logs.create is a method defined in Arvados class.
 #' 
-#' @usage arv$job_tasks.create(jobtask, ensure_unique_name = "false")
-#' @param jobTask JobTask object.
+#' @usage arv$logs.create(log, ensure_unique_name = "false",
+#'     cluster_id = NULL)
+#' @param log Log object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return JobTask object.
-#' @name job_tasks.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Log object.
+#' @name logs.create
 NULL
 
-#' job_tasks.update
+#' logs.update
 #' 
-#' job_tasks.update is a method defined in Arvados class.
+#' logs.update is a method defined in Arvados class.
 #' 
-#' @usage arv$job_tasks.update(jobtask, uuid)
-#' @param jobTask JobTask object.
-#' @param uuid The UUID of the JobTask in question.
-#' @return JobTask object.
-#' @name job_tasks.update
+#' @usage arv$logs.update(log, uuid)
+#' @param log Log object.
+#' @param uuid The UUID of the Log in question.
+#' @return Log object.
+#' @name logs.update
 NULL
 
-#' job_tasks.delete
+#' logs.delete
 #' 
-#' job_tasks.delete is a method defined in Arvados class.
+#' logs.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$job_tasks.delete(uuid)
-#' @param uuid The UUID of the JobTask in question.
-#' @return JobTask object.
-#' @name job_tasks.delete
+#' @usage arv$logs.delete(uuid)
+#' @param uuid The UUID of the Log in question.
+#' @return Log object.
+#' @name logs.delete
 NULL
 
-#' job_tasks.list
+#' logs.list
 #' 
-#' job_tasks.list is a method defined in Arvados class.
+#' logs.list is a method defined in Arvados class.
 #' 
-#' @usage arv$job_tasks.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#' @usage arv$logs.list(filters = NULL, where = NULL,
+#'     order = NULL, select = NULL, distinct = NULL,
+#'     limit = "100", offset = "0", count = "exact",
+#'     cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -752,196 +874,145 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return JobTaskList object.
-#' @name job_tasks.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return LogList object.
+#' @name logs.list
 NULL
 
-#' jobs.get
+#' users.get
 #' 
-#' jobs.get is a method defined in Arvados class.
+#' users.get is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.get(uuid)
-#' @param uuid The UUID of the Job in question.
-#' @return Job object.
-#' @name jobs.get
+#' @usage arv$users.get(uuid)
+#' @param uuid The UUID of the User in question.
+#' @return User object.
+#' @name users.get
 NULL
 
-#' jobs.create
+#' users.create
 #' 
-#' jobs.create is a method defined in Arvados class.
+#' users.create is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.create(job, ensure_unique_name = "false",
-#'     find_or_create = "false", filters = NULL,
-#'     minimum_script_version = NULL, exclude_script_versions = NULL)
-#' @param job Job object.
+#' @usage arv$users.create(user, ensure_unique_name = "false",
+#'     cluster_id = NULL)
+#' @param user User object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @param find_or_create 
-#' @param filters 
-#' @param minimum_script_version 
-#' @param exclude_script_versions 
-#' @return Job object.
-#' @name jobs.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return User object.
+#' @name users.create
 NULL
 
-#' jobs.update
+#' users.update
 #' 
-#' jobs.update is a method defined in Arvados class.
+#' users.update is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.update(job, uuid)
-#' @param job Job object.
-#' @param uuid The UUID of the Job in question.
-#' @return Job object.
-#' @name jobs.update
+#' @usage arv$users.update(user, uuid, bypass_federation = NULL)
+#' @param user User object.
+#' @param uuid The UUID of the User in question.
+#' @param bypass_federation 
+#' @return User object.
+#' @name users.update
 NULL
 
-#' jobs.delete
+#' users.delete
 #' 
-#' jobs.delete is a method defined in Arvados class.
+#' users.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.delete(uuid)
-#' @param uuid The UUID of the Job in question.
-#' @return Job object.
-#' @name jobs.delete
+#' @usage arv$users.delete(uuid)
+#' @param uuid The UUID of the User in question.
+#' @return User object.
+#' @name users.delete
 NULL
 
-#' jobs.queue
+#' users.current
 #' 
-#' jobs.queue is a method defined in Arvados class.
+#' users.current is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.queue(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return Job object.
-#' @name jobs.queue
+#' @usage arv$users.current(NULL)
+#' @return User object.
+#' @name users.current
 NULL
 
-#' jobs.queue_size
+#' users.system
 #' 
-#' jobs.queue_size is a method defined in Arvados class.
+#' users.system is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.queue_size(NULL)
-#' @return Job object.
-#' @name jobs.queue_size
+#' @usage arv$users.system(NULL)
+#' @return User object.
+#' @name users.system
 NULL
 
-#' jobs.cancel
+#' users.activate
 #' 
-#' jobs.cancel is a method defined in Arvados class.
+#' users.activate is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.cancel(uuid)
+#' @usage arv$users.activate(uuid)
 #' @param uuid 
-#' @return Job object.
-#' @name jobs.cancel
+#' @return User object.
+#' @name users.activate
 NULL
 
-#' jobs.lock
+#' users.setup
 #' 
-#' jobs.lock is a method defined in Arvados class.
+#' users.setup is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.lock(uuid)
+#' @usage arv$users.setup(uuid = NULL, user = NULL,
+#'     repo_name = NULL, vm_uuid = NULL, send_notification_email = "false")
 #' @param uuid 
-#' @return Job object.
-#' @name jobs.lock
+#' @param user 
+#' @param repo_name 
+#' @param vm_uuid 
+#' @param send_notification_email 
+#' @return User object.
+#' @name users.setup
 NULL
 
-#' jobs.list
+#' users.unsetup
 #' 
-#' jobs.list is a method defined in Arvados class.
+#' users.unsetup is a method defined in Arvados class.
 #' 
-#' @usage arv$jobs.list(filters = NULL, where = NULL,
-#'     order = NULL, select = NULL, distinct = NULL,
-#'     limit = "100", offset = "0", count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return JobList object.
-#' @name jobs.list
+#' @usage arv$users.unsetup(uuid)
+#' @param uuid 
+#' @return User object.
+#' @name users.unsetup
 NULL
 
-#' keep_disks.get
+#' users.update_uuid
 #' 
-#' keep_disks.get is a method defined in Arvados class.
+#' users.update_uuid is a method defined in Arvados class.
 #' 
-#' @usage arv$keep_disks.get(uuid)
-#' @param uuid The UUID of the KeepDisk in question.
-#' @return KeepDisk object.
-#' @name keep_disks.get
+#' @usage arv$users.update_uuid(uuid, new_uuid)
+#' @param uuid 
+#' @param new_uuid 
+#' @return User object.
+#' @name users.update_uuid
 NULL
 
-#' keep_disks.create
+#' users.merge
 #' 
-#' keep_disks.create is a method defined in Arvados class.
+#' users.merge is a method defined in Arvados class.
 #' 
-#' @usage arv$keep_disks.create(keepdisk,
-#'     ensure_unique_name = "false")
-#' @param keepDisk KeepDisk object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return KeepDisk object.
-#' @name keep_disks.create
-NULL
-
-#' keep_disks.update
-#' 
-#' keep_disks.update is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_disks.update(keepdisk,
-#'     uuid)
-#' @param keepDisk KeepDisk object.
-#' @param uuid The UUID of the KeepDisk in question.
-#' @return KeepDisk object.
-#' @name keep_disks.update
-NULL
-
-#' keep_disks.delete
-#' 
-#' keep_disks.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_disks.delete(uuid)
-#' @param uuid The UUID of the KeepDisk in question.
-#' @return KeepDisk object.
-#' @name keep_disks.delete
-NULL
-
-#' keep_disks.ping
-#' 
-#' keep_disks.ping is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_disks.ping(uuid = NULL,
-#'     ping_secret, node_uuid = NULL, filesystem_uuid = NULL,
-#'     service_host = NULL, service_port, service_ssl_flag)
-#' @param uuid 
-#' @param ping_secret 
-#' @param node_uuid 
-#' @param filesystem_uuid 
-#' @param service_host 
-#' @param service_port 
-#' @param service_ssl_flag 
-#' @return KeepDisk object.
-#' @name keep_disks.ping
+#' @usage arv$users.merge(new_owner_uuid,
+#'     new_user_token = NULL, redirect_to_new_user = NULL,
+#'     old_user_uuid = NULL, new_user_uuid = NULL)
+#' @param new_owner_uuid 
+#' @param new_user_token 
+#' @param redirect_to_new_user 
+#' @param old_user_uuid 
+#' @param new_user_uuid 
+#' @return User object.
+#' @name users.merge
 NULL
 
-#' keep_disks.list
+#' users.list
 #' 
-#' keep_disks.list is a method defined in Arvados class.
+#' users.list is a method defined in Arvados class.
 #' 
-#' @usage arv$keep_disks.list(filters = NULL,
+#' @usage arv$users.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -950,74 +1021,74 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return KeepDiskList object.
-#' @name keep_disks.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return UserList object.
+#' @name users.list
 NULL
 
-#' nodes.get
+#' repositories.get
 #' 
-#' nodes.get is a method defined in Arvados class.
+#' repositories.get is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.get(uuid)
-#' @param uuid The UUID of the Node in question.
-#' @return Node object.
-#' @name nodes.get
+#' @usage arv$repositories.get(uuid)
+#' @param uuid The UUID of the Repository in question.
+#' @return Repository object.
+#' @name repositories.get
 NULL
 
-#' nodes.create
+#' repositories.create
 #' 
-#' nodes.create is a method defined in Arvados class.
+#' repositories.create is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.create(node, ensure_unique_name = "false",
-#'     assign_slot = NULL)
-#' @param node Node object.
+#' @usage arv$repositories.create(repository,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param repository Repository object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @param assign_slot assign slot and hostname
-#' @return Node object.
-#' @name nodes.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Repository object.
+#' @name repositories.create
 NULL
 
-#' nodes.update
+#' repositories.update
 #' 
-#' nodes.update is a method defined in Arvados class.
+#' repositories.update is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.update(node, uuid, assign_slot = NULL)
-#' @param node Node object.
-#' @param uuid The UUID of the Node in question.
-#' @param assign_slot assign slot and hostname
-#' @return Node object.
-#' @name nodes.update
+#' @usage arv$repositories.update(repository,
+#'     uuid)
+#' @param repository Repository object.
+#' @param uuid The UUID of the Repository in question.
+#' @return Repository object.
+#' @name repositories.update
 NULL
 
-#' nodes.delete
+#' repositories.delete
 #' 
-#' nodes.delete is a method defined in Arvados class.
+#' repositories.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.delete(uuid)
-#' @param uuid The UUID of the Node in question.
-#' @return Node object.
-#' @name nodes.delete
+#' @usage arv$repositories.delete(uuid)
+#' @param uuid The UUID of the Repository in question.
+#' @return Repository object.
+#' @name repositories.delete
 NULL
 
-#' nodes.ping
+#' repositories.get_all_permissions
 #' 
-#' nodes.ping is a method defined in Arvados class.
+#' repositories.get_all_permissions is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.ping(uuid, ping_secret)
-#' @param uuid 
-#' @param ping_secret 
-#' @return Node object.
-#' @name nodes.ping
+#' @usage arv$repositories.get_all_permissions(NULL)
+#' @return Repository object.
+#' @name repositories.get_all_permissions
 NULL
 
-#' nodes.list
+#' repositories.list
 #' 
-#' nodes.list is a method defined in Arvados class.
+#' repositories.list is a method defined in Arvados class.
 #' 
-#' @usage arv$nodes.list(filters = NULL,
+#' @usage arv$repositories.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -1026,143 +1097,84 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return NodeList object.
-#' @name nodes.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return RepositoryList object.
+#' @name repositories.list
 NULL
 
-#' links.get
+#' virtual_machines.get
 #' 
-#' links.get is a method defined in Arvados class.
+#' virtual_machines.get is a method defined in Arvados class.
 #' 
-#' @usage arv$links.get(uuid)
-#' @param uuid The UUID of the Link in question.
-#' @return Link object.
-#' @name links.get
+#' @usage arv$virtual_machines.get(uuid)
+#' @param uuid The UUID of the VirtualMachine in question.
+#' @return VirtualMachine object.
+#' @name virtual_machines.get
 NULL
 
-#' links.create
+#' virtual_machines.create
 #' 
-#' links.create is a method defined in Arvados class.
+#' virtual_machines.create is a method defined in Arvados class.
 #' 
-#' @usage arv$links.create(link, ensure_unique_name = "false")
-#' @param link Link object.
+#' @usage arv$virtual_machines.create(virtualmachine,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param virtualMachine VirtualMachine object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Link object.
-#' @name links.create
-NULL
-
-#' links.update
-#' 
-#' links.update is a method defined in Arvados class.
-#' 
-#' @usage arv$links.update(link, uuid)
-#' @param link Link object.
-#' @param uuid The UUID of the Link in question.
-#' @return Link object.
-#' @name links.update
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return VirtualMachine object.
+#' @name virtual_machines.create
 NULL
 
-#' links.delete
+#' virtual_machines.update
 #' 
-#' links.delete is a method defined in Arvados class.
+#' virtual_machines.update is a method defined in Arvados class.
 #' 
-#' @usage arv$links.delete(uuid)
-#' @param uuid The UUID of the Link in question.
-#' @return Link object.
-#' @name links.delete
+#' @usage arv$virtual_machines.update(virtualmachine,
+#'     uuid)
+#' @param virtualMachine VirtualMachine object.
+#' @param uuid The UUID of the VirtualMachine in question.
+#' @return VirtualMachine object.
+#' @name virtual_machines.update
 NULL
 
-#' links.list
+#' virtual_machines.delete
 #' 
-#' links.list is a method defined in Arvados class.
+#' virtual_machines.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$links.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return LinkList object.
-#' @name links.list
+#' @usage arv$virtual_machines.delete(uuid)
+#' @param uuid The UUID of the VirtualMachine in question.
+#' @return VirtualMachine object.
+#' @name virtual_machines.delete
 NULL
 
-#' links.get_permissions
+#' virtual_machines.logins
 #' 
-#' links.get_permissions is a method defined in Arvados class.
+#' virtual_machines.logins is a method defined in Arvados class.
 #' 
-#' @usage arv$links.get_permissions(uuid)
+#' @usage arv$virtual_machines.logins(uuid)
 #' @param uuid 
-#' @return Link object.
-#' @name links.get_permissions
-NULL
-
-#' keep_services.get
-#' 
-#' keep_services.get is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_services.get(uuid)
-#' @param uuid The UUID of the KeepService in question.
-#' @return KeepService object.
-#' @name keep_services.get
-NULL
-
-#' keep_services.create
-#' 
-#' keep_services.create is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_services.create(keepservice,
-#'     ensure_unique_name = "false")
-#' @param keepService KeepService object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return KeepService object.
-#' @name keep_services.create
-NULL
-
-#' keep_services.update
-#' 
-#' keep_services.update is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_services.update(keepservice,
-#'     uuid)
-#' @param keepService KeepService object.
-#' @param uuid The UUID of the KeepService in question.
-#' @return KeepService object.
-#' @name keep_services.update
-NULL
-
-#' keep_services.delete
-#' 
-#' keep_services.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$keep_services.delete(uuid)
-#' @param uuid The UUID of the KeepService in question.
-#' @return KeepService object.
-#' @name keep_services.delete
+#' @return VirtualMachine object.
+#' @name virtual_machines.logins
 NULL
 
-#' keep_services.accessible
+#' virtual_machines.get_all_logins
 #' 
-#' keep_services.accessible is a method defined in Arvados class.
+#' virtual_machines.get_all_logins is a method defined in Arvados class.
 #' 
-#' @usage arv$keep_services.accessible(NULL)
-#' @return KeepService object.
-#' @name keep_services.accessible
+#' @usage arv$virtual_machines.get_all_logins(NULL)
+#' @return VirtualMachine object.
+#' @name virtual_machines.get_all_logins
 NULL
 
-#' keep_services.list
+#' virtual_machines.list
 #' 
-#' keep_services.list is a method defined in Arvados class.
+#' virtual_machines.list is a method defined in Arvados class.
 #' 
-#' @usage arv$keep_services.list(filters = NULL,
+#' @usage arv$virtual_machines.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -1171,62 +1183,65 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return KeepServiceList object.
-#' @name keep_services.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return VirtualMachineList object.
+#' @name virtual_machines.list
 NULL
 
-#' pipeline_templates.get
+#' workflows.get
 #' 
-#' pipeline_templates.get is a method defined in Arvados class.
+#' workflows.get is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_templates.get(uuid)
-#' @param uuid The UUID of the PipelineTemplate in question.
-#' @return PipelineTemplate object.
-#' @name pipeline_templates.get
+#' @usage arv$workflows.get(uuid)
+#' @param uuid The UUID of the Workflow in question.
+#' @return Workflow object.
+#' @name workflows.get
 NULL
 
-#' pipeline_templates.create
+#' workflows.create
 #' 
-#' pipeline_templates.create is a method defined in Arvados class.
+#' workflows.create is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_templates.create(pipelinetemplate,
-#'     ensure_unique_name = "false")
-#' @param pipelineTemplate PipelineTemplate object.
+#' @usage arv$workflows.create(workflow,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param workflow Workflow object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return PipelineTemplate object.
-#' @name pipeline_templates.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return Workflow object.
+#' @name workflows.create
 NULL
 
-#' pipeline_templates.update
+#' workflows.update
 #' 
-#' pipeline_templates.update is a method defined in Arvados class.
+#' workflows.update is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_templates.update(pipelinetemplate,
+#' @usage arv$workflows.update(workflow,
 #'     uuid)
-#' @param pipelineTemplate PipelineTemplate object.
-#' @param uuid The UUID of the PipelineTemplate in question.
-#' @return PipelineTemplate object.
-#' @name pipeline_templates.update
+#' @param workflow Workflow object.
+#' @param uuid The UUID of the Workflow in question.
+#' @return Workflow object.
+#' @name workflows.update
 NULL
 
-#' pipeline_templates.delete
+#' workflows.delete
 #' 
-#' pipeline_templates.delete is a method defined in Arvados class.
+#' workflows.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_templates.delete(uuid)
-#' @param uuid The UUID of the PipelineTemplate in question.
-#' @return PipelineTemplate object.
-#' @name pipeline_templates.delete
+#' @usage arv$workflows.delete(uuid)
+#' @param uuid The UUID of the Workflow in question.
+#' @return Workflow object.
+#' @name workflows.delete
 NULL
 
-#' pipeline_templates.list
+#' workflows.list
 #' 
-#' pipeline_templates.list is a method defined in Arvados class.
+#' workflows.list is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_templates.list(filters = NULL,
+#' @usage arv$workflows.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -1235,209 +1250,83 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return PipelineTemplateList object.
-#' @name pipeline_templates.list
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return WorkflowList object.
+#' @name workflows.list
 NULL
 
-#' pipeline_instances.get
+#' user_agreements.get
 #' 
-#' pipeline_instances.get is a method defined in Arvados class.
+#' user_agreements.get is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_instances.get(uuid)
-#' @param uuid The UUID of the PipelineInstance in question.
-#' @return PipelineInstance object.
-#' @name pipeline_instances.get
+#' @usage arv$user_agreements.get(uuid)
+#' @param uuid The UUID of the UserAgreement in question.
+#' @return UserAgreement object.
+#' @name user_agreements.get
 NULL
 
-#' pipeline_instances.create
+#' user_agreements.create
 #' 
-#' pipeline_instances.create is a method defined in Arvados class.
+#' user_agreements.create is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_instances.create(pipelineinstance,
-#'     ensure_unique_name = "false")
-#' @param pipelineInstance PipelineInstance object.
+#' @usage arv$user_agreements.create(useragreement,
+#'     ensure_unique_name = "false", cluster_id = NULL)
+#' @param userAgreement UserAgreement object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return PipelineInstance object.
-#' @name pipeline_instances.create
+#' @param cluster_id Create object on a remote federated cluster instead of the current one.
+#' @return UserAgreement object.
+#' @name user_agreements.create
 NULL
 
-#' pipeline_instances.update
+#' user_agreements.update
 #' 
-#' pipeline_instances.update is a method defined in Arvados class.
+#' user_agreements.update is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_instances.update(pipelineinstance,
+#' @usage arv$user_agreements.update(useragreement,
 #'     uuid)
-#' @param pipelineInstance PipelineInstance object.
-#' @param uuid The UUID of the PipelineInstance in question.
-#' @return PipelineInstance object.
-#' @name pipeline_instances.update
+#' @param userAgreement UserAgreement object.
+#' @param uuid The UUID of the UserAgreement in question.
+#' @return UserAgreement object.
+#' @name user_agreements.update
 NULL
 
-#' pipeline_instances.delete
+#' user_agreements.delete
 #' 
-#' pipeline_instances.delete is a method defined in Arvados class.
+#' user_agreements.delete is a method defined in Arvados class.
 #' 
-#' @usage arv$pipeline_instances.delete(uuid)
-#' @param uuid The UUID of the PipelineInstance in question.
-#' @return PipelineInstance object.
-#' @name pipeline_instances.delete
-NULL
-
-#' pipeline_instances.cancel
-#' 
-#' pipeline_instances.cancel is a method defined in Arvados class.
-#' 
-#' @usage arv$pipeline_instances.cancel(uuid)
-#' @param uuid 
-#' @return PipelineInstance object.
-#' @name pipeline_instances.cancel
-NULL
-
-#' pipeline_instances.list
-#' 
-#' pipeline_instances.list is a method defined in Arvados class.
-#' 
-#' @usage arv$pipeline_instances.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return PipelineInstanceList object.
-#' @name pipeline_instances.list
-NULL
-
-#' repositories.get
-#' 
-#' repositories.get is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.get(uuid)
-#' @param uuid The UUID of the Repository in question.
-#' @return Repository object.
-#' @name repositories.get
-NULL
-
-#' repositories.create
-#' 
-#' repositories.create is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.create(repository,
-#'     ensure_unique_name = "false")
-#' @param repository Repository object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Repository object.
-#' @name repositories.create
-NULL
-
-#' repositories.update
-#' 
-#' repositories.update is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.update(repository,
-#'     uuid)
-#' @param repository Repository object.
-#' @param uuid The UUID of the Repository in question.
-#' @return Repository object.
-#' @name repositories.update
-NULL
-
-#' repositories.delete
-#' 
-#' repositories.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.delete(uuid)
-#' @param uuid The UUID of the Repository in question.
-#' @return Repository object.
-#' @name repositories.delete
-NULL
-
-#' repositories.get_all_permissions
-#' 
-#' repositories.get_all_permissions is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.get_all_permissions(NULL)
-#' @return Repository object.
-#' @name repositories.get_all_permissions
-NULL
-
-#' repositories.list
-#' 
-#' repositories.list is a method defined in Arvados class.
-#' 
-#' @usage arv$repositories.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return RepositoryList object.
-#' @name repositories.list
-NULL
-
-#' specimens.get
-#' 
-#' specimens.get is a method defined in Arvados class.
-#' 
-#' @usage arv$specimens.get(uuid)
-#' @param uuid The UUID of the Specimen in question.
-#' @return Specimen object.
-#' @name specimens.get
-NULL
-
-#' specimens.create
-#' 
-#' specimens.create is a method defined in Arvados class.
-#' 
-#' @usage arv$specimens.create(specimen,
-#'     ensure_unique_name = "false")
-#' @param specimen Specimen object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Specimen object.
-#' @name specimens.create
+#' @usage arv$user_agreements.delete(uuid)
+#' @param uuid The UUID of the UserAgreement in question.
+#' @return UserAgreement object.
+#' @name user_agreements.delete
 NULL
 
-#' specimens.update
+#' user_agreements.signatures
 #' 
-#' specimens.update is a method defined in Arvados class.
+#' user_agreements.signatures is a method defined in Arvados class.
 #' 
-#' @usage arv$specimens.update(specimen,
-#'     uuid)
-#' @param specimen Specimen object.
-#' @param uuid The UUID of the Specimen in question.
-#' @return Specimen object.
-#' @name specimens.update
+#' @usage arv$user_agreements.signatures(NULL)
+#' @return UserAgreement object.
+#' @name user_agreements.signatures
 NULL
 
-#' specimens.delete
+#' user_agreements.sign
 #' 
-#' specimens.delete is a method defined in Arvados class.
+#' user_agreements.sign is a method defined in Arvados class.
 #' 
-#' @usage arv$specimens.delete(uuid)
-#' @param uuid The UUID of the Specimen in question.
-#' @return Specimen object.
-#' @name specimens.delete
+#' @usage arv$user_agreements.sign(NULL)
+#' @return UserAgreement object.
+#' @name user_agreements.sign
 NULL
 
-#' specimens.list
+#' user_agreements.list
 #' 
-#' specimens.list is a method defined in Arvados class.
+#' user_agreements.list is a method defined in Arvados class.
 #' 
-#' @usage arv$specimens.list(filters = NULL,
+#' @usage arv$user_agreements.list(filters = NULL,
 #'     where = NULL, order = NULL, select = NULL,
 #'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#'     count = "exact", cluster_id = NULL, bypass_federation = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
@@ -1446,1774 +1335,312 @@ NULL
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return SpecimenList object.
-#' @name specimens.list
-NULL
-
-#' logs.get
-#' 
-#' logs.get is a method defined in Arvados class.
-#' 
-#' @usage arv$logs.get(uuid)
-#' @param uuid The UUID of the Log in question.
-#' @return Log object.
-#' @name logs.get
-NULL
-
-#' logs.create
-#' 
-#' logs.create is a method defined in Arvados class.
-#' 
-#' @usage arv$logs.create(log, ensure_unique_name = "false")
-#' @param log Log object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Log object.
-#' @name logs.create
-NULL
-
-#' logs.update
-#' 
-#' logs.update is a method defined in Arvados class.
-#' 
-#' @usage arv$logs.update(log, uuid)
-#' @param log Log object.
-#' @param uuid The UUID of the Log in question.
-#' @return Log object.
-#' @name logs.update
+#' @param cluster_id List objects on a remote federated cluster instead of the current one.
+#' @param bypass_federation bypass federation behavior, list items from local instance database only
+#' @return UserAgreementList object.
+#' @name user_agreements.list
 NULL
 
-#' logs.delete
+#' user_agreements.new
 #' 
-#' logs.delete is a method defined in Arvados class.
+#' user_agreements.new is a method defined in Arvados class.
 #' 
-#' @usage arv$logs.delete(uuid)
-#' @param uuid The UUID of the Log in question.
-#' @return Log object.
-#' @name logs.delete
+#' @usage arv$user_agreements.new(NULL)
+#' @return UserAgreement object.
+#' @name user_agreements.new
 NULL
 
-#' logs.list
+#' configs.get
 #' 
-#' logs.list is a method defined in Arvados class.
+#' configs.get is a method defined in Arvados class.
 #' 
-#' @usage arv$logs.list(filters = NULL, where = NULL,
-#'     order = NULL, select = NULL, distinct = NULL,
-#'     limit = "100", offset = "0", count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return LogList object.
-#' @name logs.list
+#' @usage arv$configs.get(NULL)
+#' @return  object.
+#' @name configs.get
 NULL
 
-#' traits.get
+#' project.get
 #' 
-#' traits.get is a method defined in Arvados class.
+#' projects.get is equivalent to groups.get method.
 #' 
-#' @usage arv$traits.get(uuid)
-#' @param uuid The UUID of the Trait in question.
-#' @return Trait object.
-#' @name traits.get
+#' @usage arv$projects.get(uuid)
+#' @param uuid The UUID of the Group in question.
+#' @return Group object.
+#' @name projects.get
 NULL
 
-#' traits.create
+#' project.create
 #' 
-#' traits.create is a method defined in Arvados class.
+#' projects.create wrapps groups.create method by setting group_class attribute to "project".
 #' 
-#' @usage arv$traits.create(trait, ensure_unique_name = "false")
-#' @param trait Trait object.
+#' @usage arv$projects.create(group, ensure_unique_name = "false")
+#' @param group Group object.
 #' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Trait object.
-#' @name traits.create
+#' @return Group object.
+#' @name projects.create
 NULL
 
-#' traits.update
+#' project.update
 #' 
-#' traits.update is a method defined in Arvados class.
+#' projects.update wrapps groups.update method by setting group_class attribute to "project".
 #' 
-#' @usage arv$traits.update(trait, uuid)
-#' @param trait Trait object.
-#' @param uuid The UUID of the Trait in question.
-#' @return Trait object.
-#' @name traits.update
+#' @usage arv$projects.update(group, uuid)
+#' @param group Group object.
+#' @param uuid The UUID of the Group in question.
+#' @return Group object.
+#' @name projects.update
 NULL
 
-#' traits.delete
+#' project.delete
 #' 
-#' traits.delete is a method defined in Arvados class.
+#' projects.delete is equivalent to groups.delete method.
 #' 
-#' @usage arv$traits.delete(uuid)
-#' @param uuid The UUID of the Trait in question.
-#' @return Trait object.
-#' @name traits.delete
+#' @usage arv$project.delete(uuid)
+#' @param uuid The UUID of the Group in question.
+#' @return Group object.
+#' @name projects.delete
 NULL
 
-#' traits.list
+#' project.list
 #' 
-#' traits.list is a method defined in Arvados class.
+#' projects.list wrapps groups.list method by setting group_class attribute to "project".
 #' 
-#' @usage arv$traits.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
+#' @usage arv$projects.list(filters = NULL,
+#'     where = NULL, order = NULL, distinct = NULL,
+#'     limit = "100", offset = "0", count = "exact",
+#'     include_trash = NULL, uuid = NULL, recursive = NULL)
 #' @param filters 
 #' @param where 
 #' @param order 
-#' @param select 
 #' @param distinct 
 #' @param limit 
 #' @param offset 
 #' @param count 
-#' @return TraitList object.
-#' @name traits.list
-NULL
-
-#' virtual_machines.get
-#' 
-#' virtual_machines.get is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.get(uuid)
-#' @param uuid The UUID of the VirtualMachine in question.
-#' @return VirtualMachine object.
-#' @name virtual_machines.get
-NULL
-
-#' virtual_machines.create
-#' 
-#' virtual_machines.create is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.create(virtualmachine,
-#'     ensure_unique_name = "false")
-#' @param virtualMachine VirtualMachine object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return VirtualMachine object.
-#' @name virtual_machines.create
-NULL
-
-#' virtual_machines.update
-#' 
-#' virtual_machines.update is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.update(virtualmachine,
-#'     uuid)
-#' @param virtualMachine VirtualMachine object.
-#' @param uuid The UUID of the VirtualMachine in question.
-#' @return VirtualMachine object.
-#' @name virtual_machines.update
+#' @param include_trash Include items whose is_trashed attribute is true.
+#' @param uuid 
+#' @param recursive Include contents from child groups recursively.
+#' @return Group object.
+#' @name projects.list
 NULL
 
-#' virtual_machines.delete
-#' 
-#' virtual_machines.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.delete(uuid)
-#' @param uuid The UUID of the VirtualMachine in question.
-#' @return VirtualMachine object.
-#' @name virtual_machines.delete
-NULL
-
-#' virtual_machines.logins
-#' 
-#' virtual_machines.logins is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.logins(uuid)
-#' @param uuid 
-#' @return VirtualMachine object.
-#' @name virtual_machines.logins
-NULL
-
-#' virtual_machines.get_all_logins
-#' 
-#' virtual_machines.get_all_logins is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.get_all_logins(NULL)
-#' @return VirtualMachine object.
-#' @name virtual_machines.get_all_logins
-NULL
-
-#' virtual_machines.list
-#' 
-#' virtual_machines.list is a method defined in Arvados class.
-#' 
-#' @usage arv$virtual_machines.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return VirtualMachineList object.
-#' @name virtual_machines.list
-NULL
-
-#' workflows.get
-#' 
-#' workflows.get is a method defined in Arvados class.
-#' 
-#' @usage arv$workflows.get(uuid)
-#' @param uuid The UUID of the Workflow in question.
-#' @return Workflow object.
-#' @name workflows.get
-NULL
-
-#' workflows.create
-#' 
-#' workflows.create is a method defined in Arvados class.
-#' 
-#' @usage arv$workflows.create(workflow,
-#'     ensure_unique_name = "false")
-#' @param workflow Workflow object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Workflow object.
-#' @name workflows.create
-NULL
-
-#' workflows.update
-#' 
-#' workflows.update is a method defined in Arvados class.
-#' 
-#' @usage arv$workflows.update(workflow,
-#'     uuid)
-#' @param workflow Workflow object.
-#' @param uuid The UUID of the Workflow in question.
-#' @return Workflow object.
-#' @name workflows.update
-NULL
-
-#' workflows.delete
-#' 
-#' workflows.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$workflows.delete(uuid)
-#' @param uuid The UUID of the Workflow in question.
-#' @return Workflow object.
-#' @name workflows.delete
-NULL
-
-#' workflows.list
-#' 
-#' workflows.list is a method defined in Arvados class.
-#' 
-#' @usage arv$workflows.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return WorkflowList object.
-#' @name workflows.list
-NULL
-
-#' groups.get
-#' 
-#' groups.get is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.get(uuid)
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name groups.get
-NULL
-
-#' groups.create
-#' 
-#' groups.create is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.create(group, ensure_unique_name = "false")
-#' @param group Group object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Group object.
-#' @name groups.create
-NULL
-
-#' groups.update
-#' 
-#' groups.update is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.update(group, uuid)
-#' @param group Group object.
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name groups.update
-NULL
-
-#' groups.delete
-#' 
-#' groups.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.delete(uuid)
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name groups.delete
-NULL
-
-#' groups.contents
-#' 
-#' groups.contents is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.contents(filters = NULL,
-#'     where = NULL, order = NULL, distinct = NULL,
-#'     limit = "100", offset = "0", count = "exact",
-#'     include_trash = NULL, uuid = NULL, recursive = NULL)
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @param include_trash Include items whose is_trashed attribute is true.
-#' @param uuid 
-#' @param recursive Include contents from child groups recursively.
-#' @return Group object.
-#' @name groups.contents
-NULL
-
-#' groups.trash
-#' 
-#' groups.trash is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.trash(uuid)
-#' @param uuid 
-#' @return Group object.
-#' @name groups.trash
-NULL
-
-#' groups.untrash
-#' 
-#' groups.untrash is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.untrash(uuid)
-#' @param uuid 
-#' @return Group object.
-#' @name groups.untrash
-NULL
-
-#' groups.list
-#' 
-#' groups.list is a method defined in Arvados class.
-#' 
-#' @usage arv$groups.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact", include_trash = NULL)
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @param include_trash Include items whose is_trashed attribute is true.
-#' @return GroupList object.
-#' @name groups.list
-NULL
-
-#' user_agreements.get
-#' 
-#' user_agreements.get is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.get(uuid)
-#' @param uuid The UUID of the UserAgreement in question.
-#' @return UserAgreement object.
-#' @name user_agreements.get
-NULL
-
-#' user_agreements.create
-#' 
-#' user_agreements.create is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.create(useragreement,
-#'     ensure_unique_name = "false")
-#' @param userAgreement UserAgreement object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return UserAgreement object.
-#' @name user_agreements.create
-NULL
-
-#' user_agreements.update
-#' 
-#' user_agreements.update is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.update(useragreement,
-#'     uuid)
-#' @param userAgreement UserAgreement object.
-#' @param uuid The UUID of the UserAgreement in question.
-#' @return UserAgreement object.
-#' @name user_agreements.update
-NULL
-
-#' user_agreements.delete
-#' 
-#' user_agreements.delete is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.delete(uuid)
-#' @param uuid The UUID of the UserAgreement in question.
-#' @return UserAgreement object.
-#' @name user_agreements.delete
-NULL
-
-#' user_agreements.signatures
-#' 
-#' user_agreements.signatures is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.signatures(NULL)
-#' @return UserAgreement object.
-#' @name user_agreements.signatures
-NULL
-
-#' user_agreements.sign
-#' 
-#' user_agreements.sign is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.sign(NULL)
-#' @return UserAgreement object.
-#' @name user_agreements.sign
-NULL
-
-#' user_agreements.list
-#' 
-#' user_agreements.list is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.list(filters = NULL,
-#'     where = NULL, order = NULL, select = NULL,
-#'     distinct = NULL, limit = "100", offset = "0",
-#'     count = "exact")
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param select 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @return UserAgreementList object.
-#' @name user_agreements.list
-NULL
-
-#' user_agreements.new
-#' 
-#' user_agreements.new is a method defined in Arvados class.
-#' 
-#' @usage arv$user_agreements.new(NULL)
-#' @return UserAgreement object.
-#' @name user_agreements.new
-NULL
-
-#' project.get
-#' 
-#' projects.get is equivalent to groups.get method.
-#' 
-#' @usage arv$projects.get(uuid)
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name projects.get
-NULL
-
-#' project.create
-#' 
-#' projects.create wrapps groups.create method by setting group_class attribute to "project".
-#' 
-#' @usage arv$projects.create(group, ensure_unique_name = "false")
-#' @param group Group object.
-#' @param ensure_unique_name Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.
-#' @return Group object.
-#' @name projects.create
-NULL
-
-#' project.update
-#' 
-#' projects.update wrapps groups.update method by setting group_class attribute to "project".
-#' 
-#' @usage arv$projects.update(group, uuid)
-#' @param group Group object.
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name projects.update
-NULL
-
-#' project.delete
-#' 
-#' projects.delete is equivalent to groups.delete method.
-#' 
-#' @usage arv$project.delete(uuid)
-#' @param uuid The UUID of the Group in question.
-#' @return Group object.
-#' @name projects.delete
-NULL
-
-#' project.list
-#' 
-#' projects.list wrapps groups.list method by setting group_class attribute to "project".
-#' 
-#' @usage arv$projects.list(filters = NULL,
-#'     where = NULL, order = NULL, distinct = NULL,
-#'     limit = "100", offset = "0", count = "exact",
-#'     include_trash = NULL, uuid = NULL, recursive = NULL)
-#' @param filters 
-#' @param where 
-#' @param order 
-#' @param distinct 
-#' @param limit 
-#' @param offset 
-#' @param count 
-#' @param include_trash Include items whose is_trashed attribute is true.
-#' @param uuid 
-#' @param recursive Include contents from child groups recursively.
-#' @return Group object.
-#' @name projects.list
-NULL
-
-#' Arvados
-#'
-#' Arvados class gives users ability to access Arvados REST API.
-#'
-#' @section Usage:
-#' \preformatted{arv = Arvados$new(authToken = NULL, hostName = NULL, numRetries = 0)}
-#'
-#' @section Arguments:
-#' \describe{
-#'     \item{authToken}{Authentification token. If not specified ARVADOS_API_TOKEN environment variable will be used.}
-#'     \item{hostName}{Host name. If not specified ARVADOS_API_HOST environment variable will be used.}
-#'     \item{numRetries}{Number which specifies how many times to retry failed service requests.}
-#' }
-#'
-#' @section Methods:
-#' \describe{
-#'     \item{}{\code{\link{api_client_authorizations.create}}}
-#'     \item{}{\code{\link{api_client_authorizations.create_system_auth}}}
-#'     \item{}{\code{\link{api_client_authorizations.current}}}
-#'     \item{}{\code{\link{api_client_authorizations.delete}}}
-#'     \item{}{\code{\link{api_client_authorizations.get}}}
-#'     \item{}{\code{\link{api_client_authorizations.list}}}
-#'     \item{}{\code{\link{api_client_authorizations.update}}}
-#'     \item{}{\code{\link{api_clients.create}}}
-#'     \item{}{\code{\link{api_clients.delete}}}
-#'     \item{}{\code{\link{api_clients.get}}}
-#'     \item{}{\code{\link{api_clients.list}}}
-#'     \item{}{\code{\link{api_clients.update}}}
-#'     \item{}{\code{\link{authorized_keys.create}}}
-#'     \item{}{\code{\link{authorized_keys.delete}}}
-#'     \item{}{\code{\link{authorized_keys.get}}}
-#'     \item{}{\code{\link{authorized_keys.list}}}
-#'     \item{}{\code{\link{authorized_keys.update}}}
-#'     \item{}{\code{\link{collections.create}}}
-#'     \item{}{\code{\link{collections.delete}}}
-#'     \item{}{\code{\link{collections.get}}}
-#'     \item{}{\code{\link{collections.list}}}
-#'     \item{}{\code{\link{collections.provenance}}}
-#'     \item{}{\code{\link{collections.trash}}}
-#'     \item{}{\code{\link{collections.untrash}}}
-#'     \item{}{\code{\link{collections.update}}}
-#'     \item{}{\code{\link{collections.used_by}}}
-#'     \item{}{\code{\link{container_requests.create}}}
-#'     \item{}{\code{\link{container_requests.delete}}}
-#'     \item{}{\code{\link{container_requests.get}}}
-#'     \item{}{\code{\link{container_requests.list}}}
-#'     \item{}{\code{\link{container_requests.update}}}
-#'     \item{}{\code{\link{containers.auth}}}
-#'     \item{}{\code{\link{containers.create}}}
-#'     \item{}{\code{\link{containers.current}}}
-#'     \item{}{\code{\link{containers.delete}}}
-#'     \item{}{\code{\link{containers.get}}}
-#'     \item{}{\code{\link{containers.list}}}
-#'     \item{}{\code{\link{containers.lock}}}
-#'     \item{}{\code{\link{containers.secret_mounts}}}
-#'     \item{}{\code{\link{containers.unlock}}}
-#'     \item{}{\code{\link{containers.update}}}
-#'     \item{}{\code{\link{groups.contents}}}
-#'     \item{}{\code{\link{groups.create}}}
-#'     \item{}{\code{\link{groups.delete}}}
-#'     \item{}{\code{\link{groups.get}}}
-#'     \item{}{\code{\link{groups.list}}}
-#'     \item{}{\code{\link{groups.trash}}}
-#'     \item{}{\code{\link{groups.untrash}}}
-#'     \item{}{\code{\link{groups.update}}}
-#'     \item{}{\code{\link{humans.create}}}
-#'     \item{}{\code{\link{humans.delete}}}
-#'     \item{}{\code{\link{humans.get}}}
-#'     \item{}{\code{\link{humans.list}}}
-#'     \item{}{\code{\link{humans.update}}}
-#'     \item{}{\code{\link{jobs.cancel}}}
-#'     \item{}{\code{\link{jobs.create}}}
-#'     \item{}{\code{\link{jobs.delete}}}
-#'     \item{}{\code{\link{jobs.get}}}
-#'     \item{}{\code{\link{jobs.list}}}
-#'     \item{}{\code{\link{jobs.lock}}}
-#'     \item{}{\code{\link{jobs.queue}}}
-#'     \item{}{\code{\link{jobs.queue_size}}}
-#'     \item{}{\code{\link{jobs.update}}}
-#'     \item{}{\code{\link{job_tasks.create}}}
-#'     \item{}{\code{\link{job_tasks.delete}}}
-#'     \item{}{\code{\link{job_tasks.get}}}
-#'     \item{}{\code{\link{job_tasks.list}}}
-#'     \item{}{\code{\link{job_tasks.update}}}
-#'     \item{}{\code{\link{keep_disks.create}}}
-#'     \item{}{\code{\link{keep_disks.delete}}}
-#'     \item{}{\code{\link{keep_disks.get}}}
-#'     \item{}{\code{\link{keep_disks.list}}}
-#'     \item{}{\code{\link{keep_disks.ping}}}
-#'     \item{}{\code{\link{keep_disks.update}}}
-#'     \item{}{\code{\link{keep_services.accessible}}}
-#'     \item{}{\code{\link{keep_services.create}}}
-#'     \item{}{\code{\link{keep_services.delete}}}
-#'     \item{}{\code{\link{keep_services.get}}}
-#'     \item{}{\code{\link{keep_services.list}}}
-#'     \item{}{\code{\link{keep_services.update}}}
-#'     \item{}{\code{\link{links.create}}}
-#'     \item{}{\code{\link{links.delete}}}
-#'     \item{}{\code{\link{links.get}}}
-#'     \item{}{\code{\link{links.get_permissions}}}
-#'     \item{}{\code{\link{links.list}}}
-#'     \item{}{\code{\link{links.update}}}
-#'     \item{}{\code{\link{logs.create}}}
-#'     \item{}{\code{\link{logs.delete}}}
-#'     \item{}{\code{\link{logs.get}}}
-#'     \item{}{\code{\link{logs.list}}}
-#'     \item{}{\code{\link{logs.update}}}
-#'     \item{}{\code{\link{nodes.create}}}
-#'     \item{}{\code{\link{nodes.delete}}}
-#'     \item{}{\code{\link{nodes.get}}}
-#'     \item{}{\code{\link{nodes.list}}}
-#'     \item{}{\code{\link{nodes.ping}}}
-#'     \item{}{\code{\link{nodes.update}}}
-#'     \item{}{\code{\link{pipeline_instances.cancel}}}
-#'     \item{}{\code{\link{pipeline_instances.create}}}
-#'     \item{}{\code{\link{pipeline_instances.delete}}}
-#'     \item{}{\code{\link{pipeline_instances.get}}}
-#'     \item{}{\code{\link{pipeline_instances.list}}}
-#'     \item{}{\code{\link{pipeline_instances.update}}}
-#'     \item{}{\code{\link{pipeline_templates.create}}}
-#'     \item{}{\code{\link{pipeline_templates.delete}}}
-#'     \item{}{\code{\link{pipeline_templates.get}}}
-#'     \item{}{\code{\link{pipeline_templates.list}}}
-#'     \item{}{\code{\link{pipeline_templates.update}}}
-#'     \item{}{\code{\link{projects.create}}}
-#'     \item{}{\code{\link{projects.delete}}}
-#'     \item{}{\code{\link{projects.get}}}
-#'     \item{}{\code{\link{projects.list}}}
-#'     \item{}{\code{\link{projects.update}}}
-#'     \item{}{\code{\link{repositories.create}}}
-#'     \item{}{\code{\link{repositories.delete}}}
-#'     \item{}{\code{\link{repositories.get}}}
-#'     \item{}{\code{\link{repositories.get_all_permissions}}}
-#'     \item{}{\code{\link{repositories.list}}}
-#'     \item{}{\code{\link{repositories.update}}}
-#'     \item{}{\code{\link{specimens.create}}}
-#'     \item{}{\code{\link{specimens.delete}}}
-#'     \item{}{\code{\link{specimens.get}}}
-#'     \item{}{\code{\link{specimens.list}}}
-#'     \item{}{\code{\link{specimens.update}}}
-#'     \item{}{\code{\link{traits.create}}}
-#'     \item{}{\code{\link{traits.delete}}}
-#'     \item{}{\code{\link{traits.get}}}
-#'     \item{}{\code{\link{traits.list}}}
-#'     \item{}{\code{\link{traits.update}}}
-#'     \item{}{\code{\link{user_agreements.create}}}
-#'     \item{}{\code{\link{user_agreements.delete}}}
-#'     \item{}{\code{\link{user_agreements.get}}}
-#'     \item{}{\code{\link{user_agreements.list}}}
-#'     \item{}{\code{\link{user_agreements.new}}}
-#'     \item{}{\code{\link{user_agreements.sign}}}
-#'     \item{}{\code{\link{user_agreements.signatures}}}
-#'     \item{}{\code{\link{user_agreements.update}}}
-#'     \item{}{\code{\link{users.activate}}}
-#'     \item{}{\code{\link{users.create}}}
-#'     \item{}{\code{\link{users.current}}}
-#'     \item{}{\code{\link{users.delete}}}
-#'     \item{}{\code{\link{users.get}}}
-#'     \item{}{\code{\link{users.list}}}
-#'     \item{}{\code{\link{users.merge}}}
-#'     \item{}{\code{\link{users.setup}}}
-#'     \item{}{\code{\link{users.system}}}
-#'     \item{}{\code{\link{users.unsetup}}}
-#'     \item{}{\code{\link{users.update}}}
-#'     \item{}{\code{\link{users.update_uuid}}}
-#'     \item{}{\code{\link{virtual_machines.create}}}
-#'     \item{}{\code{\link{virtual_machines.delete}}}
-#'     \item{}{\code{\link{virtual_machines.get}}}
-#'     \item{}{\code{\link{virtual_machines.get_all_logins}}}
-#'     \item{}{\code{\link{virtual_machines.list}}}
-#'     \item{}{\code{\link{virtual_machines.logins}}}
-#'     \item{}{\code{\link{virtual_machines.update}}}
-#'     \item{}{\code{\link{workflows.create}}}
-#'     \item{}{\code{\link{workflows.delete}}}
-#'     \item{}{\code{\link{workflows.get}}}
-#'     \item{}{\code{\link{workflows.list}}}
-#'     \item{}{\code{\link{workflows.update}}}
-#' }
-#'
-#' @name Arvados
-#' @examples
-#' \dontrun{
-#' arv <- Arvados$new("your Arvados token", "example.arvadosapi.com")
-#'
-#' collection <- arv$collections.get("uuid")
-#'
-#' collectionList <- arv$collections.list(list(list("name", "like", "Test%")))
-#' collectionList <- listAll(arv$collections.list, list(list("name", "like", "Test%")))
-#'
-#' deletedCollection <- arv$collections.delete("uuid")
-#'
-#' updatedCollection <- arv$collections.update(list(name = "New name", description = "New description"),
-#'                                             "uuid")
-#'
-#' createdCollection <- arv$collections.create(list(name = "Example",
-#'                                                  description = "This is a test collection"))
-#' }
-NULL
-
-#' @export
-Arvados <- R6::R6Class(
-
-       "Arvados",
-
-       public = list(
-
-               initialize = function(authToken = NULL, hostName = NULL, numRetries = 0)
-               {
-                       if(!is.null(hostName))
-                               Sys.setenv(ARVADOS_API_HOST = hostName)
-
-                       if(!is.null(authToken))
-                               Sys.setenv(ARVADOS_API_TOKEN = authToken)
-
-                       hostName <- Sys.getenv("ARVADOS_API_HOST")
-                       token    <- Sys.getenv("ARVADOS_API_TOKEN")
-
-                       if(hostName == "" | token == "")
-                               stop(paste("Please provide host name and authentification token",
-                                                  "or set ARVADOS_API_HOST and ARVADOS_API_TOKEN",
-                                                  "environment variables."))
-
-                       private$token <- token
-                       private$host  <- paste0("https://", hostName, "/arvados/v1/")
-                       private$numRetries <- numRetries
-                       private$REST <- RESTService$new(token, hostName,
-                                                       HttpRequest$new(), HttpParser$new(),
-                                                       numRetries)
-
-               },
-
-               projects.get = function(uuid)
-               {
-                       self$groups.get(uuid)
-               },
-
-               projects.create = function(group, ensure_unique_name = "false")
-               {
-                       group <- c("group_class" = "project", group)
-                       self$groups.create(group, ensure_unique_name)
-               },
-
-               projects.update = function(group, uuid)
-               {
-                       group <- c("group_class" = "project", group)
-                       self$groups.update(group, uuid)
-               },
-
-               projects.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact",
-                       include_trash = NULL)
-               {
-                       filters[[length(filters) + 1]] <- list("group_class", "=", "project")
-                       self$groups.list(filters, where, order, select, distinct,
-                                        limit, offset, count, include_trash)
-               },
-
-               projects.delete = function(uuid)
-               {
-                       self$groups.delete(uuid)
-               },
-
-               users.get = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.create = function(user, ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("users")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(user) > 0)
-                               body <- jsonlite::toJSON(list(user = user), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.update = function(user, uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(user) > 0)
-                               body <- jsonlite::toJSON(list(user = user), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.delete = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.current = function()
-               {
-                       endPoint <- stringr::str_interp("users/current")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.system = function()
-               {
-                       endPoint <- stringr::str_interp("users/system")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.activate = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}/activate")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.setup = function(user = NULL, openid_prefix = NULL,
-                       repo_name = NULL, vm_uuid = NULL, send_notification_email = "false")
-               {
-                       endPoint <- stringr::str_interp("users/setup")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(user = user, openid_prefix = openid_prefix,
-                                                         repo_name = repo_name, vm_uuid = vm_uuid,
-                                                         send_notification_email = send_notification_email)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.unsetup = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}/unsetup")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.update_uuid = function(uuid, new_uuid)
-               {
-                       endPoint <- stringr::str_interp("users/${uuid}/update_uuid")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(new_uuid = new_uuid)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.merge = function(new_owner_uuid, new_user_token,
-                       redirect_to_new_user = NULL)
-               {
-                       endPoint <- stringr::str_interp("users/merge")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(new_owner_uuid = new_owner_uuid,
-                                                         new_user_token = new_user_token, redirect_to_new_user = redirect_to_new_user)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               users.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
-               {
-                       endPoint <- stringr::str_interp("users")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.get = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.create = function(apiclientauthorization,
-                       ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(apiclientauthorization) > 0)
-                               body <- jsonlite::toJSON(list(apiclientauthorization = apiclientauthorization), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.update = function(apiclientauthorization, uuid)
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(apiclientauthorization) > 0)
-                               body <- jsonlite::toJSON(list(apiclientauthorization = apiclientauthorization), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.delete = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.create_system_auth = function(api_client_id = NULL, scopes = NULL)
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations/create_system_auth")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(api_client_id = api_client_id,
-                                                         scopes = scopes)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.current = function()
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations/current")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_client_authorizations.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
-               {
-                       endPoint <- stringr::str_interp("api_client_authorizations")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.get = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.create = function(container, ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("containers")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(container) > 0)
-                               body <- jsonlite::toJSON(list(container = container), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.update = function(container, uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(container) > 0)
-                               body <- jsonlite::toJSON(list(container = container), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.delete = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.auth = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}/auth")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.lock = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}/lock")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.unlock = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}/unlock")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.secret_mounts = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("containers/${uuid}/secret_mounts")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.current = function()
-               {
-                       endPoint <- stringr::str_interp("containers/current")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               containers.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
-               {
-                       endPoint <- stringr::str_interp("containers")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_clients.get = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("api_clients/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_clients.create = function(apiclient, ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("api_clients")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(apiclient) > 0)
-                               body <- jsonlite::toJSON(list(apiclient = apiclient), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_clients.update = function(apiclient, uuid)
-               {
-                       endPoint <- stringr::str_interp("api_clients/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(apiclient) > 0)
-                               body <- jsonlite::toJSON(list(apiclient = apiclient), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               api_clients.delete = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("api_clients/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+#' Arvados
+#'
+#' Arvados class gives users ability to access Arvados REST API.
+#'
+#' @section Usage:
+#' \preformatted{arv = Arvados$new(authToken = NULL, hostName = NULL, numRetries = 0)}
+#'
+#' @section Arguments:
+#' \describe{
+#'     \item{authToken}{Authentification token. If not specified ARVADOS_API_TOKEN environment variable will be used.}
+#'     \item{hostName}{Host name. If not specified ARVADOS_API_HOST environment variable will be used.}
+#'     \item{numRetries}{Number which specifies how many times to retry failed service requests.}
+#' }
+#'
+#' @section Methods:
+#' \describe{
+#'     \item{}{\code{\link{api_client_authorizations.create}}}
+#'     \item{}{\code{\link{api_client_authorizations.create_system_auth}}}
+#'     \item{}{\code{\link{api_client_authorizations.current}}}
+#'     \item{}{\code{\link{api_client_authorizations.delete}}}
+#'     \item{}{\code{\link{api_client_authorizations.get}}}
+#'     \item{}{\code{\link{api_client_authorizations.list}}}
+#'     \item{}{\code{\link{api_client_authorizations.update}}}
+#'     \item{}{\code{\link{api_clients.create}}}
+#'     \item{}{\code{\link{api_clients.delete}}}
+#'     \item{}{\code{\link{api_clients.get}}}
+#'     \item{}{\code{\link{api_clients.list}}}
+#'     \item{}{\code{\link{api_clients.update}}}
+#'     \item{}{\code{\link{authorized_keys.create}}}
+#'     \item{}{\code{\link{authorized_keys.delete}}}
+#'     \item{}{\code{\link{authorized_keys.get}}}
+#'     \item{}{\code{\link{authorized_keys.list}}}
+#'     \item{}{\code{\link{authorized_keys.update}}}
+#'     \item{}{\code{\link{collections.create}}}
+#'     \item{}{\code{\link{collections.delete}}}
+#'     \item{}{\code{\link{collections.get}}}
+#'     \item{}{\code{\link{collections.list}}}
+#'     \item{}{\code{\link{collections.provenance}}}
+#'     \item{}{\code{\link{collections.trash}}}
+#'     \item{}{\code{\link{collections.untrash}}}
+#'     \item{}{\code{\link{collections.update}}}
+#'     \item{}{\code{\link{collections.used_by}}}
+#'     \item{}{\code{\link{configs.get}}}
+#'     \item{}{\code{\link{container_requests.create}}}
+#'     \item{}{\code{\link{container_requests.delete}}}
+#'     \item{}{\code{\link{container_requests.get}}}
+#'     \item{}{\code{\link{container_requests.list}}}
+#'     \item{}{\code{\link{container_requests.update}}}
+#'     \item{}{\code{\link{containers.auth}}}
+#'     \item{}{\code{\link{containers.create}}}
+#'     \item{}{\code{\link{containers.current}}}
+#'     \item{}{\code{\link{containers.delete}}}
+#'     \item{}{\code{\link{containers.get}}}
+#'     \item{}{\code{\link{containers.list}}}
+#'     \item{}{\code{\link{containers.lock}}}
+#'     \item{}{\code{\link{containers.secret_mounts}}}
+#'     \item{}{\code{\link{containers.unlock}}}
+#'     \item{}{\code{\link{containers.update}}}
+#'     \item{}{\code{\link{groups.contents}}}
+#'     \item{}{\code{\link{groups.create}}}
+#'     \item{}{\code{\link{groups.delete}}}
+#'     \item{}{\code{\link{groups.get}}}
+#'     \item{}{\code{\link{groups.list}}}
+#'     \item{}{\code{\link{groups.shared}}}
+#'     \item{}{\code{\link{groups.trash}}}
+#'     \item{}{\code{\link{groups.untrash}}}
+#'     \item{}{\code{\link{groups.update}}}
+#'     \item{}{\code{\link{keep_services.accessible}}}
+#'     \item{}{\code{\link{keep_services.create}}}
+#'     \item{}{\code{\link{keep_services.delete}}}
+#'     \item{}{\code{\link{keep_services.get}}}
+#'     \item{}{\code{\link{keep_services.list}}}
+#'     \item{}{\code{\link{keep_services.update}}}
+#'     \item{}{\code{\link{links.create}}}
+#'     \item{}{\code{\link{links.delete}}}
+#'     \item{}{\code{\link{links.get}}}
+#'     \item{}{\code{\link{links.get_permissions}}}
+#'     \item{}{\code{\link{links.list}}}
+#'     \item{}{\code{\link{links.update}}}
+#'     \item{}{\code{\link{logs.create}}}
+#'     \item{}{\code{\link{logs.delete}}}
+#'     \item{}{\code{\link{logs.get}}}
+#'     \item{}{\code{\link{logs.list}}}
+#'     \item{}{\code{\link{logs.update}}}
+#'     \item{}{\code{\link{projects.create}}}
+#'     \item{}{\code{\link{projects.delete}}}
+#'     \item{}{\code{\link{projects.get}}}
+#'     \item{}{\code{\link{projects.list}}}
+#'     \item{}{\code{\link{projects.update}}}
+#'     \item{}{\code{\link{repositories.create}}}
+#'     \item{}{\code{\link{repositories.delete}}}
+#'     \item{}{\code{\link{repositories.get}}}
+#'     \item{}{\code{\link{repositories.get_all_permissions}}}
+#'     \item{}{\code{\link{repositories.list}}}
+#'     \item{}{\code{\link{repositories.update}}}
+#'     \item{}{\code{\link{user_agreements.create}}}
+#'     \item{}{\code{\link{user_agreements.delete}}}
+#'     \item{}{\code{\link{user_agreements.get}}}
+#'     \item{}{\code{\link{user_agreements.list}}}
+#'     \item{}{\code{\link{user_agreements.new}}}
+#'     \item{}{\code{\link{user_agreements.sign}}}
+#'     \item{}{\code{\link{user_agreements.signatures}}}
+#'     \item{}{\code{\link{user_agreements.update}}}
+#'     \item{}{\code{\link{users.activate}}}
+#'     \item{}{\code{\link{users.create}}}
+#'     \item{}{\code{\link{users.current}}}
+#'     \item{}{\code{\link{users.delete}}}
+#'     \item{}{\code{\link{users.get}}}
+#'     \item{}{\code{\link{users.list}}}
+#'     \item{}{\code{\link{users.merge}}}
+#'     \item{}{\code{\link{users.setup}}}
+#'     \item{}{\code{\link{users.system}}}
+#'     \item{}{\code{\link{users.unsetup}}}
+#'     \item{}{\code{\link{users.update}}}
+#'     \item{}{\code{\link{users.update_uuid}}}
+#'     \item{}{\code{\link{virtual_machines.create}}}
+#'     \item{}{\code{\link{virtual_machines.delete}}}
+#'     \item{}{\code{\link{virtual_machines.get}}}
+#'     \item{}{\code{\link{virtual_machines.get_all_logins}}}
+#'     \item{}{\code{\link{virtual_machines.list}}}
+#'     \item{}{\code{\link{virtual_machines.logins}}}
+#'     \item{}{\code{\link{virtual_machines.update}}}
+#'     \item{}{\code{\link{workflows.create}}}
+#'     \item{}{\code{\link{workflows.delete}}}
+#'     \item{}{\code{\link{workflows.get}}}
+#'     \item{}{\code{\link{workflows.list}}}
+#'     \item{}{\code{\link{workflows.update}}}
+#' }
+#'
+#' @name Arvados
+#' @examples
+#' \dontrun{
+#' arv <- Arvados$new("your Arvados token", "example.arvadosapi.com")
+#'
+#' collection <- arv$collections.get("uuid")
+#'
+#' collectionList <- arv$collections.list(list(list("name", "like", "Test%")))
+#' collectionList <- listAll(arv$collections.list, list(list("name", "like", "Test%")))
+#'
+#' deletedCollection <- arv$collections.delete("uuid")
+#'
+#' updatedCollection <- arv$collections.update(list(name = "New name", description = "New description"),
+#'                                             "uuid")
+#'
+#' createdCollection <- arv$collections.create(list(name = "Example",
+#'                                                  description = "This is a test collection"))
+#' }
+NULL
 
-               api_clients.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
-               {
-                       endPoint <- stringr::str_interp("api_clients")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+#' @export
+Arvados <- R6::R6Class(
 
-               container_requests.get = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("container_requests/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+       "Arvados",
 
-               container_requests.create = function(containerrequest,
-                       ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("container_requests")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(containerrequest) > 0)
-                               body <- jsonlite::toJSON(list(containerrequest = containerrequest), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+       public = list(
 
-               container_requests.update = function(containerrequest, uuid)
+               initialize = function(authToken = NULL, hostName = NULL, numRetries = 0)
                {
-                       endPoint <- stringr::str_interp("container_requests/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(containerrequest) > 0)
-                               body <- jsonlite::toJSON(list(containerrequest = containerrequest), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+                       if(!is.null(hostName))
+                               Sys.setenv(ARVADOS_API_HOST = hostName)
 
-               container_requests.delete = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("container_requests/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
+                       if(!is.null(authToken))
+                               Sys.setenv(ARVADOS_API_TOKEN = authToken)
+
+                       hostName <- Sys.getenv("ARVADOS_API_HOST")
+                       token    <- Sys.getenv("ARVADOS_API_TOKEN")
+
+                       if(hostName == "" | token == "")
+                               stop(paste("Please provide host name and authentification token",
+                                                  "or set ARVADOS_API_HOST and ARVADOS_API_TOKEN",
+                                                  "environment variables."))
+
+                       private$token <- token
+                       private$host  <- paste0("https://", hostName, "/arvados/v1/")
+                       private$numRetries <- numRetries
+                       private$REST <- RESTService$new(token, hostName,
+                                                       HttpRequest$new(), HttpParser$new(),
+                                                       numRetries)
 
-               container_requests.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
-               {
-                       endPoint <- stringr::str_interp("container_requests")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
                },
 
-               authorized_keys.get = function(uuid)
+               projects.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
+                       self$groups.get(uuid)
                },
 
-               authorized_keys.create = function(authorizedkey,
-                       ensure_unique_name = "false")
+               projects.create = function(group, ensure_unique_name = "false")
                {
-                       endPoint <- stringr::str_interp("authorized_keys")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(authorizedkey) > 0)
-                               body <- jsonlite::toJSON(list(authorizedkey = authorizedkey), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
+                       group <- c("group_class" = "project", group)
+                       self$groups.create(group, ensure_unique_name)
                },
 
-               authorized_keys.update = function(authorizedkey, uuid)
+               projects.update = function(group, uuid)
                {
-                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(authorizedkey) > 0)
-                               body <- jsonlite::toJSON(list(authorizedkey = authorizedkey), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
+                       group <- c("group_class" = "project", group)
+                       self$groups.update(group, uuid)
                },
 
-               authorized_keys.delete = function(uuid)
+               projects.list = function(filters = NULL, where = NULL,
+                       order = NULL, select = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       include_trash = NULL)
                {
-                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
+                       filters[[length(filters) + 1]] <- list("group_class", "=", "project")
+                       self$groups.list(filters, where, order, select, distinct,
+                                        limit, offset, count, include_trash)
                },
 
-               authorized_keys.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
-               {
-                       endPoint <- stringr::str_interp("authorized_keys")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
+               projects.delete = function(uuid)
+               {
+                       self$groups.delete(uuid)
                },
 
-               collections.get = function(uuid)
+               api_clients.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}")
+                       endPoint <- stringr::str_interp("api_clients/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3229,16 +1656,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.create = function(collection, ensure_unique_name = "false")
+               api_clients.create = function(apiclient,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("collections")
+                       endPoint <- stringr::str_interp("api_clients")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(collection) > 0)
-                               body <- jsonlite::toJSON(list(collection = collection), 
+                       if(length(apiclient) > 0)
+                               body <- jsonlite::toJSON(list(apiclient = apiclient), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3253,16 +1682,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.update = function(collection, uuid)
+               api_clients.update = function(apiclient, uuid)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}")
+                       endPoint <- stringr::str_interp("api_clients/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(collection) > 0)
-                               body <- jsonlite::toJSON(list(collection = collection), 
+                       if(length(apiclient) > 0)
+                               body <- jsonlite::toJSON(list(apiclient = apiclient), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3277,11 +1706,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.delete = function(uuid)
+               api_clients.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}")
+                       endPoint <- stringr::str_interp("api_clients/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3297,13 +1726,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.provenance = function(uuid)
+               api_clients.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}/provenance")
+                       endPoint <- stringr::str_interp("api_clients")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(filters = filters, where = where,
+                                                         order = order, select = select, distinct = distinct,
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -3317,11 +1752,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.used_by = function(uuid)
+               api_client_authorizations.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}/used_by")
+                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3337,15 +1772,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.trash = function(uuid)
+               api_client_authorizations.create = function(apiclientauthorization,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}/trash")
+                       endPoint <- stringr::str_interp("api_client_authorizations")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       body <- NULL
+                       if(length(apiclientauthorization) > 0)
+                               body <- jsonlite::toJSON(list(apiclientauthorization = apiclientauthorization), 
+                                                        auto_unbox = TRUE)
+                       else
+                               body <- NULL
                        
                        response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
@@ -3357,43 +1798,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               collections.untrash = function(uuid)
+               api_client_authorizations.update = function(apiclientauthorization, uuid)
                {
-                       endPoint <- stringr::str_interp("collections/${uuid}/untrash")
+                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               collections.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact", include_trash = NULL)
-               {
-                       endPoint <- stringr::str_interp("collections")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count,
-                                                         include_trash = include_trash)
-                       
-                       body <- NULL
+                       if(length(apiclientauthorization) > 0)
+                               body <- jsonlite::toJSON(list(apiclientauthorization = apiclientauthorization), 
+                                                        auto_unbox = TRUE)
+                       else
+                               body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("PUT", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -3403,17 +1822,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               humans.get = function(uuid)
+               api_client_authorizations.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("humans/${uuid}")
+                       endPoint <- stringr::str_interp("api_client_authorizations/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("DELETE", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -3423,19 +1842,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               humans.create = function(human, ensure_unique_name = "false")
+               api_client_authorizations.create_system_auth = function(api_client_id = NULL, scopes = NULL)
                {
-                       endPoint <- stringr::str_interp("humans")
+                       endPoint <- stringr::str_interp("api_client_authorizations/create_system_auth")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(api_client_id = api_client_id,
+                                                         scopes = scopes)
                        
-                       if(length(human) > 0)
-                               body <- jsonlite::toJSON(list(human = human), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
                        response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
@@ -3447,41 +1863,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               humans.update = function(human, uuid)
-               {
-                       endPoint <- stringr::str_interp("humans/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(human) > 0)
-                               body <- jsonlite::toJSON(list(human = human), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               humans.delete = function(uuid)
+               api_client_authorizations.current = function()
                {
-                       endPoint <- stringr::str_interp("humans/${uuid}")
+                       endPoint <- stringr::str_interp("api_client_authorizations/current")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -3491,17 +1883,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               humans.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               api_client_authorizations.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("humans")
+                       endPoint <- stringr::str_interp("api_client_authorizations")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -3515,11 +1909,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               job_tasks.get = function(uuid)
+               authorized_keys.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("job_tasks/${uuid}")
+                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3535,16 +1929,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               job_tasks.create = function(jobtask, ensure_unique_name = "false")
+               authorized_keys.create = function(authorizedkey,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("job_tasks")
+                       endPoint <- stringr::str_interp("authorized_keys")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(jobtask) > 0)
-                               body <- jsonlite::toJSON(list(jobtask = jobtask), 
+                       if(length(authorizedkey) > 0)
+                               body <- jsonlite::toJSON(list(authorizedkey = authorizedkey), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3559,16 +1955,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               job_tasks.update = function(jobtask, uuid)
+               authorized_keys.update = function(authorizedkey, uuid)
                {
-                       endPoint <- stringr::str_interp("job_tasks/${uuid}")
+                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(jobtask) > 0)
-                               body <- jsonlite::toJSON(list(jobtask = jobtask), 
+                       if(length(authorizedkey) > 0)
+                               body <- jsonlite::toJSON(list(authorizedkey = authorizedkey), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3583,11 +1979,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               job_tasks.delete = function(uuid)
+               authorized_keys.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("job_tasks/${uuid}")
+                       endPoint <- stringr::str_interp("authorized_keys/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3603,18 +1999,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               job_tasks.list = function(filters = NULL,
+               authorized_keys.list = function(filters = NULL,
                        where = NULL, order = NULL, select = NULL,
                        distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("job_tasks")
+                       endPoint <- stringr::str_interp("authorized_keys")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -3628,11 +2025,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.get = function(uuid)
+               collections.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/${uuid}")
+                       endPoint <- stringr::str_interp("collections/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3648,21 +2045,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.create = function(job, ensure_unique_name = "false",
-                       find_or_create = "false", filters = NULL,
-                       minimum_script_version = NULL, exclude_script_versions = NULL)
+               collections.create = function(collection,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("jobs")
+                       endPoint <- stringr::str_interp("collections")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(ensure_unique_name = ensure_unique_name,
-                                                         find_or_create = find_or_create, filters = filters,
-                                                         minimum_script_version = minimum_script_version,
-                                                         exclude_script_versions = exclude_script_versions)
+                                                         cluster_id = cluster_id)
                        
-                       if(length(job) > 0)
-                               body <- jsonlite::toJSON(list(job = job), 
+                       if(length(collection) > 0)
+                               body <- jsonlite::toJSON(list(collection = collection), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3677,16 +2071,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.update = function(job, uuid)
+               collections.update = function(collection, uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/${uuid}")
+                       endPoint <- stringr::str_interp("collections/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(job) > 0)
-                               body <- jsonlite::toJSON(list(job = job), 
+                       if(length(collection) > 0)
+                               body <- jsonlite::toJSON(list(collection = collection), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3701,11 +2095,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.delete = function(uuid)
+               collections.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/${uuid}")
+                       endPoint <- stringr::str_interp("collections/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3721,17 +2115,13 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.queue = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               collections.provenance = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/queue")
+                       endPoint <- stringr::str_interp("collections/${uuid}/provenance")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
@@ -3745,11 +2135,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.queue_size = function()
+               collections.used_by = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/queue_size")
+                       endPoint <- stringr::str_interp("collections/${uuid}/used_by")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3765,11 +2155,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.cancel = function(uuid)
+               collections.trash = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/${uuid}/cancel")
+                       endPoint <- stringr::str_interp("collections/${uuid}/trash")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3785,11 +2175,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.lock = function(uuid)
+               collections.untrash = function(uuid)
                {
-                       endPoint <- stringr::str_interp("jobs/${uuid}/lock")
+                       endPoint <- stringr::str_interp("collections/${uuid}/untrash")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3805,17 +2195,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               jobs.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               collections.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL,
+                       include_trash = NULL, include_old_versions = NULL)
                {
-                       endPoint <- stringr::str_interp("jobs")
+                       endPoint <- stringr::str_interp("collections")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation,
+                                                         include_trash = include_trash, include_old_versions = include_old_versions)
                        
                        body <- NULL
                        
@@ -3829,11 +2223,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_disks.get = function(uuid)
+               containers.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("keep_disks/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3849,16 +2243,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_disks.create = function(keepdisk, ensure_unique_name = "false")
+               containers.create = function(container, ensure_unique_name = "false",
+                       cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("keep_disks")
+                       endPoint <- stringr::str_interp("containers")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(keepdisk) > 0)
-                               body <- jsonlite::toJSON(list(keepdisk = keepdisk), 
+                       if(length(container) > 0)
+                               body <- jsonlite::toJSON(list(container = container), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3873,16 +2269,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_disks.update = function(keepdisk, uuid)
+               containers.update = function(container, uuid)
                {
-                       endPoint <- stringr::str_interp("keep_disks/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(keepdisk) > 0)
-                               body <- jsonlite::toJSON(list(keepdisk = keepdisk), 
+                       if(length(container) > 0)
+                               body <- jsonlite::toJSON(list(container = container), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -3897,11 +2293,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_disks.delete = function(uuid)
+               containers.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("keep_disks/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -3917,43 +2313,13 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_disks.ping = function(uuid = NULL, ping_secret,
-                       node_uuid = NULL, filesystem_uuid = NULL,
-                       service_host = NULL, service_port, service_ssl_flag)
-               {
-                       endPoint <- stringr::str_interp("keep_disks/ping")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(uuid = uuid, ping_secret = ping_secret,
-                                                         node_uuid = node_uuid, filesystem_uuid = filesystem_uuid,
-                                                         service_host = service_host, service_port = service_port,
-                                                         service_ssl_flag = service_ssl_flag)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               keep_disks.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+               containers.auth = function(uuid)
                {
-                       endPoint <- stringr::str_interp("keep_disks")
+                       endPoint <- stringr::str_interp("containers/${uuid}/auth")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
@@ -3967,42 +2333,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               nodes.get = function(uuid)
+               containers.lock = function(uuid)
                {
-                       endPoint <- stringr::str_interp("nodes/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}/lock")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               nodes.create = function(node, ensure_unique_name = "false",
-                       assign_slot = NULL)
-               {
-                       endPoint <- stringr::str_interp("nodes")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
-                                                         assign_slot = assign_slot)
-                       
-                       if(length(node) > 0)
-                               body <- jsonlite::toJSON(list(node = node), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
                        response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
@@ -4013,21 +2353,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               nodes.update = function(node, uuid, assign_slot = NULL)
+               containers.unlock = function(uuid)
                {
-                       endPoint <- stringr::str_interp("nodes/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}/unlock")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(assign_slot = assign_slot)
+                       queryArgs <- NULL
                        
-                       if(length(node) > 0)
-                               body <- jsonlite::toJSON(list(node = node), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
-                       response <- private$REST$http$exec("PUT", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4037,17 +2373,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               nodes.delete = function(uuid)
+               containers.secret_mounts = function(uuid)
                {
-                       endPoint <- stringr::str_interp("nodes/${uuid}")
+                       endPoint <- stringr::str_interp("containers/${uuid}/secret_mounts")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4057,17 +2393,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               nodes.ping = function(uuid, ping_secret)
+               containers.current = function()
                {
-                       endPoint <- stringr::str_interp("nodes/${uuid}/ping")
+                       endPoint <- stringr::str_interp("containers/current")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ping_secret = ping_secret)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("POST", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4077,17 +2413,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               nodes.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               containers.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("nodes")
+                       endPoint <- stringr::str_interp("containers")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -4101,11 +2439,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               links.get = function(uuid)
+               container_requests.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("links/${uuid}")
+                       endPoint <- stringr::str_interp("container_requests/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4121,16 +2459,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               links.create = function(link, ensure_unique_name = "false")
+               container_requests.create = function(containerrequest,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("links")
+                       endPoint <- stringr::str_interp("container_requests")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(link) > 0)
-                               body <- jsonlite::toJSON(list(link = link), 
+                       if(length(containerrequest) > 0)
+                               body <- jsonlite::toJSON(list(containerrequest = containerrequest), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4145,16 +2485,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               links.update = function(link, uuid)
+               container_requests.update = function(containerrequest, uuid)
                {
-                       endPoint <- stringr::str_interp("links/${uuid}")
+                       endPoint <- stringr::str_interp("container_requests/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(link) > 0)
-                               body <- jsonlite::toJSON(list(link = link), 
+                       if(length(containerrequest) > 0)
+                               body <- jsonlite::toJSON(list(containerrequest = containerrequest), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4169,11 +2509,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               links.delete = function(uuid)
+               container_requests.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("links/${uuid}")
+                       endPoint <- stringr::str_interp("container_requests/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4189,37 +2529,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               links.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               container_requests.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL,
+                       include_trash = NULL)
                {
-                       endPoint <- stringr::str_interp("links")
+                       endPoint <- stringr::str_interp("container_requests")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
-                       
-                       body <- NULL
-                       
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               links.get_permissions = function(uuid)
-               {
-                       endPoint <- stringr::str_interp("permissions/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation,
+                                                         include_trash = include_trash)
                        
                        body <- NULL
                        
@@ -4233,11 +2557,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.get = function(uuid)
+               groups.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("keep_services/${uuid}")
+                       endPoint <- stringr::str_interp("groups/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4253,17 +2577,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.create = function(keepservice,
-                       ensure_unique_name = "false")
+               groups.create = function(group, ensure_unique_name = "false",
+                       cluster_id = NULL, async = "false")
                {
-                       endPoint <- stringr::str_interp("keep_services")
+                       endPoint <- stringr::str_interp("groups")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id, async = async)
                        
-                       if(length(keepservice) > 0)
-                               body <- jsonlite::toJSON(list(keepservice = keepservice), 
+                       if(length(group) > 0)
+                               body <- jsonlite::toJSON(list(group = group), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4278,16 +2603,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.update = function(keepservice, uuid)
+               groups.update = function(group, uuid, async = "false")
                {
-                       endPoint <- stringr::str_interp("keep_services/${uuid}")
+                       endPoint <- stringr::str_interp("groups/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(async = async)
                        
-                       if(length(keepservice) > 0)
-                               body <- jsonlite::toJSON(list(keepservice = keepservice), 
+                       if(length(group) > 0)
+                               body <- jsonlite::toJSON(list(group = group), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4302,11 +2627,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.delete = function(uuid)
+               groups.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("keep_services/${uuid}")
+                       endPoint <- stringr::str_interp("groups/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4322,13 +2647,22 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.accessible = function()
+               groups.contents = function(filters = NULL,
+                       where = NULL, order = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       cluster_id = NULL, bypass_federation = NULL,
+                       include_trash = NULL, uuid = NULL, recursive = NULL,
+                       include = NULL)
                {
-                       endPoint <- stringr::str_interp("keep_services/accessible")
+                       endPoint <- stringr::str_interp("groups/contents")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(filters = filters, where = where,
+                                                         order = order, distinct = distinct, limit = limit,
+                                                         offset = offset, count = count, cluster_id = cluster_id,
+                                                         bypass_federation = bypass_federation, include_trash = include_trash,
+                                                         uuid = uuid, recursive = recursive, include = include)
                        
                        body <- NULL
                        
@@ -4342,18 +2676,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               keep_services.list = function(filters = NULL,
+               groups.shared = function(filters = NULL,
                        where = NULL, order = NULL, select = NULL,
                        distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL,
+                       include_trash = NULL, include = NULL)
                {
-                       endPoint <- stringr::str_interp("keep_services")
+                       endPoint <- stringr::str_interp("groups/shared")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation,
+                                                         include_trash = include_trash, include = include)
                        
                        body <- NULL
                        
@@ -4367,41 +2704,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_templates.get = function(uuid)
+               groups.trash = function(uuid)
                {
-                       endPoint <- stringr::str_interp("pipeline_templates/${uuid}")
+                       endPoint <- stringr::str_interp("groups/${uuid}/trash")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               pipeline_templates.create = function(pipelinetemplate,
-                       ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("pipeline_templates")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(pipelinetemplate) > 0)
-                               body <- jsonlite::toJSON(list(pipelinetemplate = pipelinetemplate), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
                        response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
@@ -4412,41 +2724,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_templates.update = function(pipelinetemplate, uuid)
-               {
-                       endPoint <- stringr::str_interp("pipeline_templates/${uuid}")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- NULL
-                       
-                       if(length(pipelinetemplate) > 0)
-                               body <- jsonlite::toJSON(list(pipelinetemplate = pipelinetemplate), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("PUT", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               pipeline_templates.delete = function(uuid)
+               groups.untrash = function(uuid)
                {
-                       endPoint <- stringr::str_interp("pipeline_templates/${uuid}")
+                       endPoint <- stringr::str_interp("groups/${uuid}/untrash")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4456,18 +2744,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_templates.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+               groups.list = function(filters = NULL, where = NULL,
+                       order = NULL, select = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       cluster_id = NULL, bypass_federation = NULL,
+                       include_trash = NULL)
                {
-                       endPoint <- stringr::str_interp("pipeline_templates")
+                       endPoint <- stringr::str_interp("groups")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation,
+                                                         include_trash = include_trash)
                        
                        body <- NULL
                        
@@ -4481,11 +2772,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.get = function(uuid)
+               keep_services.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("pipeline_instances/${uuid}")
+                       endPoint <- stringr::str_interp("keep_services/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4501,17 +2792,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.create = function(pipelineinstance,
-                       ensure_unique_name = "false")
+               keep_services.create = function(keepservice,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("pipeline_instances")
+                       endPoint <- stringr::str_interp("keep_services")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(pipelineinstance) > 0)
-                               body <- jsonlite::toJSON(list(pipelineinstance = pipelineinstance), 
+                       if(length(keepservice) > 0)
+                               body <- jsonlite::toJSON(list(keepservice = keepservice), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4526,16 +2818,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.update = function(pipelineinstance, uuid)
+               keep_services.update = function(keepservice, uuid)
                {
-                       endPoint <- stringr::str_interp("pipeline_instances/${uuid}")
+                       endPoint <- stringr::str_interp("keep_services/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(pipelineinstance) > 0)
-                               body <- jsonlite::toJSON(list(pipelineinstance = pipelineinstance), 
+                       if(length(keepservice) > 0)
+                               body <- jsonlite::toJSON(list(keepservice = keepservice), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4550,11 +2842,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.delete = function(uuid)
+               keep_services.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("pipeline_instances/${uuid}")
+                       endPoint <- stringr::str_interp("keep_services/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4570,17 +2862,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.cancel = function(uuid)
+               keep_services.accessible = function()
                {
-                       endPoint <- stringr::str_interp("pipeline_instances/${uuid}/cancel")
+                       endPoint <- stringr::str_interp("keep_services/accessible")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("POST", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4590,18 +2882,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               pipeline_instances.list = function(filters = NULL,
+               keep_services.list = function(filters = NULL,
                        where = NULL, order = NULL, select = NULL,
                        distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("pipeline_instances")
+                       endPoint <- stringr::str_interp("keep_services")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -4615,11 +2908,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.get = function(uuid)
+               links.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("repositories/${uuid}")
+                       endPoint <- stringr::str_interp("links/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4635,16 +2928,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.create = function(repository, ensure_unique_name = "false")
+               links.create = function(link, ensure_unique_name = "false",
+                       cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("repositories")
+                       endPoint <- stringr::str_interp("links")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(repository) > 0)
-                               body <- jsonlite::toJSON(list(repository = repository), 
+                       if(length(link) > 0)
+                               body <- jsonlite::toJSON(list(link = link), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4659,16 +2954,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.update = function(repository, uuid)
+               links.update = function(link, uuid)
                {
-                       endPoint <- stringr::str_interp("repositories/${uuid}")
+                       endPoint <- stringr::str_interp("links/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(repository) > 0)
-                               body <- jsonlite::toJSON(list(repository = repository), 
+                       if(length(link) > 0)
+                               body <- jsonlite::toJSON(list(link = link), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4683,11 +2978,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.delete = function(uuid)
+               links.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("repositories/${uuid}")
+                       endPoint <- stringr::str_interp("links/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4703,13 +2998,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.get_all_permissions = function()
+               links.list = function(filters = NULL, where = NULL,
+                       order = NULL, select = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("repositories/get_all_permissions")
+                       endPoint <- stringr::str_interp("links")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(filters = filters, where = where,
+                                                         order = order, select = select, distinct = distinct,
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -4723,18 +3024,13 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               repositories.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+               links.get_permissions = function(uuid)
                {
-                       endPoint <- stringr::str_interp("repositories")
+                       endPoint <- stringr::str_interp("permissions/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
@@ -4748,11 +3044,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               specimens.get = function(uuid)
+               logs.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("specimens/${uuid}")
+                       endPoint <- stringr::str_interp("logs/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4768,16 +3064,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               specimens.create = function(specimen, ensure_unique_name = "false")
+               logs.create = function(log, ensure_unique_name = "false",
+                       cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("specimens")
+                       endPoint <- stringr::str_interp("logs")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(specimen) > 0)
-                               body <- jsonlite::toJSON(list(specimen = specimen), 
+                       if(length(log) > 0)
+                               body <- jsonlite::toJSON(list(log = log), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4792,16 +3090,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               specimens.update = function(specimen, uuid)
+               logs.update = function(log, uuid)
                {
-                       endPoint <- stringr::str_interp("specimens/${uuid}")
+                       endPoint <- stringr::str_interp("logs/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(specimen) > 0)
-                               body <- jsonlite::toJSON(list(specimen = specimen), 
+                       if(length(log) > 0)
+                               body <- jsonlite::toJSON(list(log = log), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4816,11 +3114,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               specimens.delete = function(uuid)
+               logs.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("specimens/${uuid}")
+                       endPoint <- stringr::str_interp("logs/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4836,18 +3134,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               specimens.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+               logs.list = function(filters = NULL, where = NULL,
+                       order = NULL, select = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("specimens")
+                       endPoint <- stringr::str_interp("logs")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -4861,11 +3160,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               logs.get = function(uuid)
+               users.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("logs/${uuid}")
+                       endPoint <- stringr::str_interp("users/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -4881,16 +3180,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               logs.create = function(log, ensure_unique_name = "false")
+               users.create = function(user, ensure_unique_name = "false",
+                       cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("logs")
+                       endPoint <- stringr::str_interp("users")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(log) > 0)
-                               body <- jsonlite::toJSON(list(log = log), 
+                       if(length(user) > 0)
+                               body <- jsonlite::toJSON(list(user = user), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -4905,21 +3206,41 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               logs.update = function(log, uuid)
+               users.update = function(user, uuid, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("logs/${uuid}")
+                       endPoint <- stringr::str_interp("users/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(bypass_federation = bypass_federation)
                        
-                       if(length(log) > 0)
-                               body <- jsonlite::toJSON(list(log = log), 
+                       if(length(user) > 0)
+                               body <- jsonlite::toJSON(list(user = user), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
                        
-                       response <- private$REST$http$exec("PUT", url, headers, body,
+                       response <- private$REST$http$exec("PUT", url, headers, body,
+                                                          queryArgs, private$numRetries)
+                       resource <- private$REST$httpParser$parseJSONResponse(response)
+                       
+                       if(!is.null(resource$errors))
+                               stop(resource$errors)
+                       
+                       resource
+               },
+
+               users.delete = function(uuid)
+               {
+                       endPoint <- stringr::str_interp("users/${uuid}")
+                       url <- paste0(private$host, endPoint)
+                       headers <- list(Authorization = paste("Bearer", private$token), 
+                                       "Content-Type" = "application/json")
+                       queryArgs <- NULL
+                       
+                       body <- NULL
+                       
+                       response <- private$REST$http$exec("DELETE", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4929,17 +3250,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               logs.delete = function(uuid)
+               users.current = function()
                {
-                       endPoint <- stringr::str_interp("logs/${uuid}")
+                       endPoint <- stringr::str_interp("users/current")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4949,17 +3270,13 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               logs.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               users.system = function()
                {
-                       endPoint <- stringr::str_interp("logs")
+                       endPoint <- stringr::str_interp("users/system")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
@@ -4973,17 +3290,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               traits.get = function(uuid)
+               users.activate = function(uuid)
                {
-                       endPoint <- stringr::str_interp("traits/${uuid}")
+                       endPoint <- stringr::str_interp("users/${uuid}/activate")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -4993,19 +3310,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               traits.create = function(trait, ensure_unique_name = "false")
+               users.setup = function(uuid = NULL, user = NULL,
+                       repo_name = NULL, vm_uuid = NULL, send_notification_email = "false")
                {
-                       endPoint <- stringr::str_interp("traits")
+                       endPoint <- stringr::str_interp("users/setup")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(uuid = uuid, user = user,
+                                                         repo_name = repo_name, vm_uuid = vm_uuid,
+                                                         send_notification_email = send_notification_email)
                        
-                       if(length(trait) > 0)
-                               body <- jsonlite::toJSON(list(trait = trait), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
                        response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
@@ -5017,21 +3333,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               traits.update = function(trait, uuid)
+               users.unsetup = function(uuid)
                {
-                       endPoint <- stringr::str_interp("traits/${uuid}")
+                       endPoint <- stringr::str_interp("users/${uuid}/unsetup")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(trait) > 0)
-                               body <- jsonlite::toJSON(list(trait = trait), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
-                       response <- private$REST$http$exec("PUT", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5041,17 +3353,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               traits.delete = function(uuid)
+               users.update_uuid = function(uuid, new_uuid)
                {
-                       endPoint <- stringr::str_interp("traits/${uuid}")
+                       endPoint <- stringr::str_interp("users/${uuid}/update_uuid")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(new_uuid = new_uuid)
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5061,21 +3373,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               traits.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact")
+               users.merge = function(new_owner_uuid, new_user_token = NULL,
+                       redirect_to_new_user = NULL, old_user_uuid = NULL,
+                       new_user_uuid = NULL)
                {
-                       endPoint <- stringr::str_interp("traits")
+                       endPoint <- stringr::str_interp("users/merge")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- list(new_owner_uuid = new_owner_uuid,
+                                                         new_user_token = new_user_token, redirect_to_new_user = redirect_to_new_user,
+                                                         old_user_uuid = old_user_uuid, new_user_uuid = new_user_uuid)
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5085,13 +3397,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.get = function(uuid)
+               users.list = function(filters = NULL, where = NULL,
+                       order = NULL, select = NULL, distinct = NULL,
+                       limit = "100", offset = "0", count = "exact",
+                       cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
+                       endPoint <- stringr::str_interp("users")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(filters = filters, where = where,
+                                                         order = order, select = select, distinct = distinct,
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -5105,22 +3423,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.create = function(virtualmachine,
-                       ensure_unique_name = "false")
+               repositories.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("virtual_machines")
+                       endPoint <- stringr::str_interp("repositories/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- NULL
                        
-                       if(length(virtualmachine) > 0)
-                               body <- jsonlite::toJSON(list(virtualmachine = virtualmachine), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
-                       response <- private$REST$http$exec("POST", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5130,21 +3443,23 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.update = function(virtualmachine, uuid)
+               repositories.create = function(repository,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
+                       endPoint <- stringr::str_interp("repositories")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(virtualmachine) > 0)
-                               body <- jsonlite::toJSON(list(virtualmachine = virtualmachine), 
+                       if(length(repository) > 0)
+                               body <- jsonlite::toJSON(list(repository = repository), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
                        
-                       response <- private$REST$http$exec("PUT", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5154,17 +3469,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.delete = function(uuid)
+               repositories.update = function(repository, uuid)
                {
-                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
+                       endPoint <- stringr::str_interp("repositories/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       body <- NULL
+                       if(length(repository) > 0)
+                               body <- jsonlite::toJSON(list(repository = repository), 
+                                                        auto_unbox = TRUE)
+                       else
+                               body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("PUT", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5174,17 +3493,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.logins = function(uuid)
+               repositories.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("virtual_machines/${uuid}/logins")
+                       endPoint <- stringr::str_interp("repositories/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("DELETE", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5194,11 +3513,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.get_all_logins = function()
+               repositories.get_all_permissions = function()
                {
-                       endPoint <- stringr::str_interp("virtual_machines/get_all_logins")
+                       endPoint <- stringr::str_interp("repositories/get_all_permissions")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5214,18 +3533,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               virtual_machines.list = function(filters = NULL,
+               repositories.list = function(filters = NULL,
                        where = NULL, order = NULL, select = NULL,
                        distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("virtual_machines")
+                       endPoint <- stringr::str_interp("repositories")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -5239,11 +3559,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               workflows.get = function(uuid)
+               virtual_machines.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("workflows/${uuid}")
+                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5259,16 +3579,18 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               workflows.create = function(workflow, ensure_unique_name = "false")
+               virtual_machines.create = function(virtualmachine,
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("workflows")
+                       endPoint <- stringr::str_interp("virtual_machines")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       if(length(workflow) > 0)
-                               body <- jsonlite::toJSON(list(workflow = workflow), 
+                       if(length(virtualmachine) > 0)
+                               body <- jsonlite::toJSON(list(virtualmachine = virtualmachine), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -5283,16 +3605,16 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               workflows.update = function(workflow, uuid)
+               virtual_machines.update = function(virtualmachine, uuid)
                {
-                       endPoint <- stringr::str_interp("workflows/${uuid}")
+                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       if(length(workflow) > 0)
-                               body <- jsonlite::toJSON(list(workflow = workflow), 
+                       if(length(virtualmachine) > 0)
+                               body <- jsonlite::toJSON(list(virtualmachine = virtualmachine), 
                                                         auto_unbox = TRUE)
                        else
                                body <- NULL
@@ -5307,11 +3629,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               workflows.delete = function(uuid)
+               virtual_machines.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("workflows/${uuid}")
+                       endPoint <- stringr::str_interp("virtual_machines/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5327,18 +3649,13 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               workflows.list = function(filters = NULL,
-                       where = NULL, order = NULL, select = NULL,
-                       distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+               virtual_machines.logins = function(uuid)
                {
-                       endPoint <- stringr::str_interp("workflows")
+                       endPoint <- stringr::str_interp("virtual_machines/${uuid}/logins")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                       queryArgs <- NULL
                        
                        body <- NULL
                        
@@ -5352,11 +3669,11 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.get = function(uuid)
+               virtual_machines.get_all_logins = function()
                {
-                       endPoint <- stringr::str_interp("groups/${uuid}")
+                       endPoint <- stringr::str_interp("virtual_machines/get_all_logins")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5372,45 +3689,23 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.create = function(group, ensure_unique_name = "false")
-               {
-                       endPoint <- stringr::str_interp("groups")
-                       url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
-                                       "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
-                       
-                       if(length(group) > 0)
-                               body <- jsonlite::toJSON(list(group = group), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
-                       
-                       response <- private$REST$http$exec("POST", url, headers, body,
-                                                          queryArgs, private$numRetries)
-                       resource <- private$REST$httpParser$parseJSONResponse(response)
-                       
-                       if(!is.null(resource$errors))
-                               stop(resource$errors)
-                       
-                       resource
-               },
-
-               groups.update = function(group, uuid)
+               virtual_machines.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("groups/${uuid}")
+                       endPoint <- stringr::str_interp("virtual_machines")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- NULL
+                       queryArgs <- list(filters = filters, where = where,
+                                                         order = order, select = select, distinct = distinct,
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
-                       if(length(group) > 0)
-                               body <- jsonlite::toJSON(list(group = group), 
-                                                        auto_unbox = TRUE)
-                       else
-                               body <- NULL
+                       body <- NULL
                        
-                       response <- private$REST$http$exec("PUT", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5420,17 +3715,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.delete = function(uuid)
+               workflows.get = function(uuid)
                {
-                       endPoint <- stringr::str_interp("groups/${uuid}")
+                       endPoint <- stringr::str_interp("workflows/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("DELETE", url, headers, body,
+                       response <- private$REST$http$exec("GET", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5440,23 +3735,23 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.contents = function(filters = NULL,
-                       where = NULL, order = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact",
-                       include_trash = NULL, uuid = NULL, recursive = NULL)
+               workflows.create = function(workflow, ensure_unique_name = "false",
+                       cluster_id = NULL)
                {
-                       endPoint <- stringr::str_interp("groups/contents")
+                       endPoint <- stringr::str_interp("workflows")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(filters = filters, where = where,
-                                                         order = order, distinct = distinct, limit = limit,
-                                                         offset = offset, count = count, include_trash = include_trash,
-                                                         uuid = uuid, recursive = recursive)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
-                       body <- NULL
+                       if(length(workflow) > 0)
+                               body <- jsonlite::toJSON(list(workflow = workflow), 
+                                                        auto_unbox = TRUE)
+                       else
+                               body <- NULL
                        
-                       response <- private$REST$http$exec("GET", url, headers, body,
+                       response <- private$REST$http$exec("POST", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5466,17 +3761,21 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.trash = function(uuid)
+               workflows.update = function(workflow, uuid)
                {
-                       endPoint <- stringr::str_interp("groups/${uuid}/trash")
+                       endPoint <- stringr::str_interp("workflows/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
-                       body <- NULL
+                       if(length(workflow) > 0)
+                               body <- jsonlite::toJSON(list(workflow = workflow), 
+                                                        auto_unbox = TRUE)
+                       else
+                               body <- NULL
                        
-                       response <- private$REST$http$exec("POST", url, headers, body,
+                       response <- private$REST$http$exec("PUT", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5486,17 +3785,17 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.untrash = function(uuid)
+               workflows.delete = function(uuid)
                {
-                       endPoint <- stringr::str_interp("groups/${uuid}/untrash")
+                       endPoint <- stringr::str_interp("workflows/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
                        body <- NULL
                        
-                       response <- private$REST$http$exec("POST", url, headers, body,
+                       response <- private$REST$http$exec("DELETE", url, headers, body,
                                                           queryArgs, private$numRetries)
                        resource <- private$REST$httpParser$parseJSONResponse(response)
                        
@@ -5506,19 +3805,19 @@ Arvados <- R6::R6Class(
                        resource
                },
 
-               groups.list = function(filters = NULL, where = NULL,
-                       order = NULL, select = NULL, distinct = NULL,
-                       limit = "100", offset = "0", count = "exact",
-                       include_trash = NULL)
+               workflows.list = function(filters = NULL,
+                       where = NULL, order = NULL, select = NULL,
+                       distinct = NULL, limit = "100", offset = "0",
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
-                       endPoint <- stringr::str_interp("groups")
+                       endPoint <- stringr::str_interp("workflows")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
                                                          limit = limit, offset = offset, count = count,
-                                                         include_trash = include_trash)
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -5536,7 +3835,7 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5553,13 +3852,14 @@ Arvados <- R6::R6Class(
                },
 
                user_agreements.create = function(useragreement,
-                       ensure_unique_name = "false")
+                       ensure_unique_name = "false", cluster_id = NULL)
                {
                        endPoint <- stringr::str_interp("user_agreements")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
-                       queryArgs <- list(ensure_unique_name = ensure_unique_name)
+                       queryArgs <- list(ensure_unique_name = ensure_unique_name,
+                                                         cluster_id = cluster_id)
                        
                        if(length(useragreement) > 0)
                                body <- jsonlite::toJSON(list(useragreement = useragreement), 
@@ -5581,7 +3881,7 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5605,7 +3905,7 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/${uuid}")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5625,7 +3925,7 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/signatures")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5645,7 +3945,7 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/sign")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
@@ -5664,15 +3964,16 @@ Arvados <- R6::R6Class(
                user_agreements.list = function(filters = NULL,
                        where = NULL, order = NULL, select = NULL,
                        distinct = NULL, limit = "100", offset = "0",
-                       count = "exact")
+                       count = "exact", cluster_id = NULL, bypass_federation = NULL)
                {
                        endPoint <- stringr::str_interp("user_agreements")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- list(filters = filters, where = where,
                                                          order = order, select = select, distinct = distinct,
-                                                         limit = limit, offset = offset, count = count)
+                                                         limit = limit, offset = offset, count = count,
+                                                         cluster_id = cluster_id, bypass_federation = bypass_federation)
                        
                        body <- NULL
                        
@@ -5690,7 +3991,27 @@ Arvados <- R6::R6Class(
                {
                        endPoint <- stringr::str_interp("user_agreements/new")
                        url <- paste0(private$host, endPoint)
-                       headers <- list(Authorization = paste("OAuth2", private$token), 
+                       headers <- list(Authorization = paste("Bearer", private$token), 
+                                       "Content-Type" = "application/json")
+                       queryArgs <- NULL
+                       
+                       body <- NULL
+                       
+                       response <- private$REST$http$exec("GET", url, headers, body,
+                                                          queryArgs, private$numRetries)
+                       resource <- private$REST$httpParser$parseJSONResponse(response)
+                       
+                       if(!is.null(resource$errors))
+                               stop(resource$errors)
+                       
+                       resource
+               },
+
+               configs.get = function()
+               {
+                       endPoint <- stringr::str_interp("config")
+                       url <- paste0(private$host, endPoint)
+                       headers <- list(Authorization = paste("Bearer", private$token), 
                                        "Content-Type" = "application/json")
                        queryArgs <- NULL
                        
index 70bb4450eccca6efd453002dc7a0962c904fb0d0..fb1d3b335cba00df4db898de20b917334b7e4610 100644 (file)
@@ -2,8 +2,6 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-source("./R/util.R")
-
 #' ArvadosFile
 #'
 #' ArvadosFile class represents a file inside Arvados collection.
index 8869d7be67846b449200fe2c675936dd1c4133db..1440836547253bc96871c651e666ec8608af243a 100644 (file)
@@ -2,11 +2,6 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-source("./R/Subcollection.R")
-source("./R/ArvadosFile.R")
-source("./R/RESTService.R")
-source("./R/util.R")
-
 #' Collection
 #'
 #' Collection class provides interface for working with Arvados collections.
index 5f7a29455ae4a58aaae6792f6dd1eb26ae30ae4e..e01e7e8de9dc1f36ac462a0c3730c525926a1555 100644 (file)
@@ -2,10 +2,6 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-source("./R/Subcollection.R")
-source("./R/ArvadosFile.R")
-source("./R/util.R")
-
 CollectionTree <- R6::R6Class(
     "CollectionTree",
     public = list(
index cd492166a139bf56dccebf732f2533c443440cf7..60bf7828278859e14fefaacebbcb5d762f1dbe99 100644 (file)
@@ -31,14 +31,13 @@ HttpParser <- R6::R6Class(
         {
             text <- rawToChar(response$content)
             doc <- XML::xmlParse(text, asText=TRUE)
-            base <- paste(paste("/", strsplit(uri, "/")[[1]][-1:-3], sep="", collapse=""), "/", sep="")
+            base <- paste("/", strsplit(uri, "/")[[1]][4], "/", sep="")
             result <- unlist(
                 XML::xpathApply(doc, "//D:response/D:href", function(node) {
                     sub(base, "", URLdecode(XML::xmlValue(node)), fixed=TRUE)
                 })
             )
-            result <- result[result != ""]
-            result[-1]
+            result[result != ""]
         },
 
         getFileSizesFromResponse = function(response, uri)
index 07defca90f4c99e8be9f8a73f7412f398ab1a701..18b36f96898c2fa1be1d2e512a2fb158ac94294a 100644 (file)
@@ -2,8 +2,6 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-source("./R/util.R")
-
 HttpRequest <- R6::R6Class(
 
     "HttrRequest",
@@ -54,7 +52,7 @@ HttpRequest <- R6::R6Class(
             {
                 query <- paste0(names(query), "=", query, collapse = "&")
 
-                return(paste0("/?", query))
+                return(paste0("?", query))
             }
 
             return("")
index 78b2c35e32fa117190f033075e1ea5ee2a3805e3..9c65e72861f41513936e431afda50f6ab443f983 100644 (file)
@@ -36,16 +36,13 @@ RESTService <- R6::R6Class(
         {
             if(is.null(private$webDavHostName))
             {
-                discoveryDocumentURL <- paste0("https://", private$rawHostName,
-                                               "/discovery/v1/apis/arvados/v1/rest")
+                publicConfigURL <- paste0("https://", private$rawHostName,
+                                               "/arvados/v1/config")
 
-                headers <- list(Authorization = paste("OAuth2", self$token))
-
-                serverResponse <- self$http$exec("GET", discoveryDocumentURL, headers,
-                                                 retryTimes = self$numRetries)
+                serverResponse <- self$http$exec("GET", publicConfigURL, retryTimes = self$numRetries)
 
-                discoveryDocument <- self$httpParser$parseJSONResponse(serverResponse)
-                private$webDavHostName <- discoveryDocument$keepWebServiceUrl
+                configDocument <- self$httpParser$parseJSONResponse(serverResponse)
+                private$webDavHostName <- configDocument$Services$WebDAVDownload$ExternalURL
 
                 if(is.null(private$webDavHostName))
                     stop("Unable to find WebDAV server.")
@@ -118,7 +115,7 @@ RESTService <- R6::R6Class(
             collectionURL <- URLencode(paste0(self$getWebDavHostName(),
                                               "c=", uuid))
 
-            headers <- list("Authorization" = paste("OAuth2", self$token))
+            headers <- list("Authorization" = paste("Bearer", self$token))
 
             response <- self$http$exec("PROPFIND", collectionURL, headers,
                                        retryTimes = self$numRetries)
index 17a9ef3ee3ba6180546763da637a8824905d66dc..981bd687a2fbcb68f8eb0deafa7caed619dd3628 100644 (file)
@@ -2,8 +2,6 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-source("./R/util.R")
-
 #' Subcollection
 #'
 #' Subcollection class represents a folder inside Arvados collection.
index 1aef20b6cb90fe11d7440219bbe24d464af988c2..c86684f8b0a13ab62f53eddc23884a16e2504ffc 100644 (file)
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: Apache-2.0
 
 getAPIDocument <- function(){
-    url <- "https://4xphq.arvadosapi.com/discovery/v1/apis/arvados/v1/rest"
+    url <- "https://jutro.arvadosapi.com/discovery/v1/apis/arvados/v1/rest"
     serverResponse <- httr::RETRY("GET", url = url)
 
     httr::content(serverResponse, as = "parsed", type = "application/json")
@@ -17,6 +17,10 @@ generateAPI <- function()
     discoveryDocument <- getAPIDocument()
 
     methodResources <- discoveryDocument$resources
+
+    # Don't emit deprecated APIs
+    methodResources <- methodResources[!(names(methodResources) %in% c("jobs", "job_tasks", "pipeline_templates", "pipeline_instances",
+                           "keep_disks", "nodes", "humans", "traits", "specimens"))]
     resourceNames   <- names(methodResources)
 
     methodDoc <- genMethodsDoc(methodResources, resourceNames)
@@ -34,6 +38,10 @@ generateAPI <- function()
                       arvadosAPIFooter)
 
     fileConn <- file("./R/Arvados.R", "w")
+    writeLines(c(
+    "# Copyright (C) The Arvados Authors. All rights reserved.",
+    "#",
+    "# SPDX-License-Identifier: Apache-2.0", ""), fileConn)
     writeLines(unlist(arvadosClass), fileConn)
     close(fileConn)
     NULL
@@ -252,7 +260,7 @@ getRequestURL <- function(methodMetaData)
 
 getRequestHeaders <- function()
 {
-    c("headers <- list(Authorization = paste(\"OAuth2\", private$token), ",
+    c("headers <- list(Authorization = paste(\"Bearer\", private$token), ",
       "                \"Content-Type\" = \"application/json\")")
 }
 
index c1d6c7cf4f01eebaae55764630e8e1c68d6f1def..63bf55373d17a163522d1f2fdcf0ee4d640361d5 100644 (file)
@@ -14,7 +14,7 @@ knitr::opts_chunk$set(eval=FALSE)
 ```
 
 ```{r}
-install.packages("ArvadosR", repos=c("http://r.arvados.org", getOption("repos")["CRAN"]), dependencies=TRUE)
+install.packages("ArvadosR", repos=c("https://r.arvados.org", getOption("repos")["CRAN"]), dependencies=TRUE)
 ```
 
 Note: on Linux, you may have to install supporting packages.
index e3457c993f7c88cee4a963ca7006a90c6078f478..da7d52c67d63697bc81aefbcbe16e7713add3891 100644 (file)
@@ -23,7 +23,7 @@ test_that("get always returns NULL", {
     dog <- ArvadosFile$new("dog")
 
     responseIsNull <- is.null(dog$get("something"))
-    expect_that(responseIsNull, is_true())
+    expect_true(responseIsNull)
 })
 
 test_that("getFirst always returns NULL", {
@@ -31,7 +31,7 @@ test_that("getFirst always returns NULL", {
     dog <- ArvadosFile$new("dog")
 
     responseIsNull <- is.null(dog$getFirst())
-    expect_that(responseIsNull, is_true())
+    expect_true(responseIsNull)
 })
 
 test_that(paste("getSizeInBytes returns zero if arvadosFile",
@@ -266,8 +266,8 @@ test_that("move moves arvados file inside collection tree", {
     dogIsNullOnOldLocation <- is.null(collection$get("animal/dog"))
     dogExistsOnNewLocation <- !is.null(collection$get("dog"))
 
-    expect_that(dogIsNullOnOldLocation, is_true())
-    expect_that(dogExistsOnNewLocation, is_true())
+    expect_true(dogIsNullOnOldLocation)
+    expect_true(dogExistsOnNewLocation)
 })
 
 test_that(paste("copy raises exception if arvados file",
@@ -339,8 +339,8 @@ test_that("copy copies arvados file inside collection tree", {
     dogExistsOnOldLocation <- !is.null(collection$get("animal/dog"))
     dogExistsOnNewLocation <- !is.null(collection$get("dog"))
 
-    expect_that(dogExistsOnOldLocation, is_true())
-    expect_that(dogExistsOnNewLocation, is_true())
+    expect_true(dogExistsOnOldLocation)
+    expect_true(dogExistsOnNewLocation)
 })
 
 test_that("duplicate performs deep cloning of Arvados file", {
index 636359ae21a7b196d406ec2b16ee8839e0921f9e..20a2ecf05b120bb769d7f0b8d01c007099638516 100644 (file)
@@ -86,7 +86,7 @@ test_that(paste("add adds ArvadosFile or Subcollection",
     dog <- collection$get("animal/dog")
     dogExistsInCollection <- !is.null(dog) && dog$getName() == "dog"
 
-    expect_that(dogExistsInCollection, is_true())
+    expect_true(dogExistsInCollection)
     expect_that(fakeREST$createCallCount, equals(1))
 })
 
@@ -119,8 +119,8 @@ test_that(paste("create adds files specified by fileNames",
     dogExistsInCollection <- !is.null(dog) && dog$getName() == "dog"
     catExistsInCollection <- !is.null(cat) && cat$getName() == "cat"
 
-    expect_that(dogExistsInCollection, is_true())
-    expect_that(catExistsInCollection, is_true())
+    expect_true(dogExistsInCollection)
+    expect_true(catExistsInCollection)
     expect_that(fakeREST$createCallCount, equals(2))
 })
 
@@ -168,8 +168,8 @@ test_that(paste("remove removes files specified by paths",
     dogExistsInCollection <- !is.null(dog) && dog$getName() == "dog"
     catExistsInCollection <- !is.null(cat) && cat$getName() == "cat"
 
-    expect_that(dogExistsInCollection, is_false())
-    expect_that(catExistsInCollection, is_false())
+    expect_false(dogExistsInCollection)
+    expect_false(catExistsInCollection)
     expect_that(fakeREST$deleteCallCount, equals(2))
 })
 
@@ -188,8 +188,8 @@ test_that(paste("move moves content to a new location inside file tree",
     dogIsNullOnOldLocation <- is.null(collection$get("animal/dog"))
     dogExistsOnNewLocation <- !is.null(collection$get("dog"))
 
-    expect_that(dogIsNullOnOldLocation, is_true())
-    expect_that(dogExistsOnNewLocation, is_true())
+    expect_true(dogIsNullOnOldLocation)
+    expect_true(dogExistsOnNewLocation)
     expect_that(fakeREST$moveCallCount, equals(1))
 })
 
@@ -219,7 +219,7 @@ test_that("getFileListing returns sorted collection content received from REST s
     contentMatchExpected <- all(collection$getFileListing() ==
                                 c("animal", "animal/fish", "ball"))
 
-    expect_that(contentMatchExpected, is_true())
+    expect_true(contentMatchExpected)
     #2 calls because Collection$new calls getFileListing once
     expect_that(fakeREST$getCollectionContentCallCount, equals(2))
 
@@ -237,7 +237,7 @@ test_that("get returns arvados file or subcollection from internal tree structur
     fish <- collection$get("animal/fish")
     fishIsNotNull <- !is.null(fish)
 
-    expect_that(fishIsNotNull, is_true())
+    expect_true(fishIsNotNull)
     expect_that(fish$getName(), equals("fish"))
 })
 
@@ -256,8 +256,8 @@ test_that(paste("copy copies content to a new location inside file tree",
     dogExistsOnOldLocation <- !is.null(collection$get("animal/dog"))
     dogExistsOnNewLocation <- !is.null(collection$get("dog"))
 
-    expect_that(dogExistsOnOldLocation, is_true())
-    expect_that(dogExistsOnNewLocation, is_true())
+    expect_true(dogExistsOnOldLocation)
+    expect_true(dogExistsOnNewLocation)
     expect_that(fakeREST$copyCallCount, equals(1))
 })
 
index 1a3aefecd012325658ad408ee2a699682907dbaf..c4bf9a1da7ff639d62c1bbb135ea77f4326ed4d6 100644 (file)
@@ -34,16 +34,16 @@ test_that("constructor creates file tree from character array properly", {
                                          boat$getCollection()   == "myCollection"
 
     expect_that(root$getName(), equals(""))
-    expect_that(rootIsOfTypeSubcollection, is_true())
-    expect_that(rootHasNoParent, is_true())
-    expect_that(animalIsOfTypeSubcollection, is_true())
-    expect_that(animalsParentIsRoot, is_true())
-    expect_that(animalContainsDog, is_true())
-    expect_that(dogIsOfTypeArvadosFile, is_true())
-    expect_that(dogsParentIsAnimal, is_true())
-    expect_that(boatIsOfTypeArvadosFile, is_true())
-    expect_that(boatsParentIsRoot, is_true())
-    expect_that(allElementsBelongToSameCollection, is_true())
+    expect_true(rootIsOfTypeSubcollection)
+    expect_true(rootHasNoParent)
+    expect_true(animalIsOfTypeSubcollection)
+    expect_true(animalsParentIsRoot)
+    expect_true(animalContainsDog)
+    expect_true(dogIsOfTypeArvadosFile)
+    expect_true(dogsParentIsAnimal)
+    expect_true(boatIsOfTypeArvadosFile)
+    expect_true(boatsParentIsRoot)
+    expect_true(allElementsBelongToSameCollection)
 })
 
 test_that("getElement returns element from tree if element exists on specified path", {
@@ -72,7 +72,7 @@ test_that("getElement returns NULL from tree if element doesn't exists on specif
     fish <- collectionTree$getElement("animal/fish")
     fishIsNULL <- is.null(fish)
 
-    expect_that(fishIsNULL, is_true())
+    expect_true(fishIsNULL)
 })
 
 test_that("getElement trims ./ from start of relativePath", {
index 82c0fb0dd2fed88598e8fd14a8dd88a11d065b71..fb9f379b3623099b1171456b4f4a2b849713773b 100644 (file)
@@ -18,7 +18,7 @@ test_that("parseJSONResponse generates and returns JSON object from server respo
     result <- parser$parseJSONResponse(serverResponse)
     barExists <- !is.null(result$bar)
 
-    expect_that(barExists, is_true())
+    expect_true(barExists)
     expect_that(unlist(result$bar$foo), equals(10))
 })
 
@@ -40,7 +40,7 @@ test_that(paste("parseResponse generates and returns character vector",
 
 webDAVResponseSample =
     paste0("<?xml version=\"1.0\" encoding=\"UTF-8\"?><D:multistatus xmlns:",
-           "D=\"DAV:\"><D:response><D:href>/c=aaaaa-bbbbb-ccccccccccccccc</D",
+           "D=\"DAV:\"><D:response><D:href>/c=aaaaa-bbbbb-ccccccccccccccc/</D",
            ":href><D:propstat><D:prop><D:resourcetype><D:collection xmlns:D=",
            "\"DAV:\"/></D:resourcetype><D:getlastmodified>Fri, 11 Jan 2018 1",
            "1:11:11 GMT</D:getlastmodified><D:displayname></D:displayname><D",
@@ -75,7 +75,7 @@ test_that(paste("getFileNamesFromResponse returns file names belonging to specif
     expectedResult <- "myFile.exe"
     resultMatchExpected <- all.equal(result, expectedResult)
 
-    expect_that(resultMatchExpected, is_true())
+    expect_true(resultMatchExpected)
 })
 
 test_that(paste("getFileSizesFromResponse returns file sizes",
@@ -92,5 +92,5 @@ test_that(paste("getFileSizesFromResponse returns file sizes",
     result <- parser$getFileSizesFromResponse(serverResponse, url)
     resultMatchExpected <- result == expectedResult
 
-    expect_that(resultMatchExpected, is_true())
+    expect_true(resultMatchExpected)
 })
index f12463c805dda10e67325adb2a892d5223600932..c1b6f1039cfc28e0e7b4f62087f3919acaa7c0b3 100644 (file)
@@ -20,7 +20,7 @@ test_that("createQuery generates and encodes query portion of http", {
     queryParams$limit <- 20
     queryParams$offset <- 50
     expect_that(http$createQuery(queryParams),
-                equals(paste0("/?filters=%5B%5B%22color%22%2C%22%3D%22%2C%22red",
+                equals(paste0("?filters=%5B%5B%22color%22%2C%22%3D%22%2C%22red",
                               "%22%5D%5D&limit=20&offset=50")))
 })
 
@@ -59,8 +59,8 @@ test_that("exec calls httr functions correctly", {
     http <- HttpRequest$new()
     http$exec("GET", "url")
 
-    expect_that(add_headersCalled, is_true())
-    expect_that(retryCalled, is_true())
+    expect_true(add_headersCalled)
+    expect_true(retryCalled)
     expect_that(expectedConfig$options, equals(list(ssl_verifypeer = 0L)))
 })
 
@@ -101,8 +101,8 @@ test_that("getConnection calls curl functions correctly", {
     http <- HttpRequest$new()
     http$getConnection("location", list(), "r")
 
-    expect_that(new_handleCalled, is_true())
-    expect_that(handle_setheadersCalled, is_true())
-    expect_that(handle_setoptCalled, is_true())
-    expect_that(curlCalled, is_true())
+    expect_true(new_handleCalled)
+    expect_true(handle_setheadersCalled)
+    expect_true(handle_setoptCalled)
+    expect_true(curlCalled)
 })
index 64988e33db2c3c4614112d2eb993687d6e169199..8885ed3de2f5caa906b9d5223878b2fe5d52ccb3 100644 (file)
@@ -10,8 +10,8 @@ context("REST service")
 
 test_that("getWebDavHostName calls REST service properly", {
 
-    expectedURL <- "https://host/discovery/v1/apis/arvados/v1/rest"
-    serverResponse <- list(keepWebServiceUrl = "https://myWebDavServer.com")
+    expectedURL <- "https://host/arvados/v1/config"
+    serverResponse <- list(Services = list(WebDAVDownload = list(ExternalURL = "https://myWebDavServer.com")))
     httpRequest <- FakeHttpRequest$new(expectedURL, serverResponse)
 
     REST <- RESTService$new("token", "host",
@@ -19,14 +19,14 @@ test_that("getWebDavHostName calls REST service properly", {
 
     REST$getWebDavHostName()
 
-    expect_that(httpRequest$URLIsProperlyConfigured, is_true())
-    expect_that(httpRequest$requestHeaderContainsAuthorizationField, is_true())
+    expect_true(httpRequest$URLIsProperlyConfigured)
+    expect_false(httpRequest$requestHeaderContainsAuthorizationField)
     expect_that(httpRequest$numberOfGETRequests, equals(1))
 })
 
 test_that("getWebDavHostName returns webDAV host name properly", {
 
-    serverResponse <- list(keepWebServiceUrl = "https://myWebDavServer.com")
+    serverResponse <- list(Services = list(WebDAVDownload = list(ExternalURL = "https://myWebDavServer.com")))
     httpRequest <- FakeHttpRequest$new(expectedURL = NULL, serverResponse)
 
     REST <- RESTService$new("token", "host",
@@ -48,8 +48,8 @@ test_that("create calls REST service properly", {
 
     REST$create("file", uuid)
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
     expect_that(fakeHttp$numberOfPUTRequests, equals(1))
 })
 
@@ -81,8 +81,8 @@ test_that("delete calls REST service properly", {
 
     REST$delete("file", uuid)
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
     expect_that(fakeHttp$numberOfDELETERequests, equals(1))
 })
 
@@ -114,9 +114,9 @@ test_that("move calls REST service properly", {
 
     REST$move("file", "newDestination/file", uuid)
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
-    expect_that(fakeHttp$requestHeaderContainsDestinationField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
+    expect_true(fakeHttp$requestHeaderContainsDestinationField)
     expect_that(fakeHttp$numberOfMOVERequests, equals(1))
 })
 
@@ -148,9 +148,9 @@ test_that("copy calls REST service properly", {
 
     REST$copy("file", "newDestination/file", uuid)
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
-    expect_that(fakeHttp$requestHeaderContainsDestinationField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
+    expect_true(fakeHttp$requestHeaderContainsDestinationField)
     expect_that(fakeHttp$numberOfCOPYRequests, equals(1))
 })
 
@@ -187,8 +187,8 @@ test_that("getCollectionContent retreives correct content from WebDAV server", {
     returnedContentMatchExpected <- all.equal(returnResult,
                                               c("animal", "animal/dog", "ball"))
 
-    expect_that(returnedContentMatchExpected, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
+    expect_true(returnedContentMatchExpected)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
 })
 
 test_that("getCollectionContent raises exception if server returns empty response", {
@@ -266,9 +266,9 @@ test_that("getResourceSize calls REST service properly", {
     returnedContentMatchExpected <- all.equal(returnResult,
                                               c(6, 2, 931, 12003))
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
-    expect_that(returnedContentMatchExpected, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
+    expect_true(returnedContentMatchExpected)
 })
 
 test_that("getResourceSize raises exception if server returns empty response", {
@@ -330,9 +330,9 @@ test_that("read calls REST service properly", {
 
     returnResult <- REST$read("file", uuid, "text", 1024, 512)
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
-    expect_that(fakeHttp$requestHeaderContainsRangeField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
+    expect_true(fakeHttp$requestHeaderContainsRangeField)
     expect_that(returnResult, equals("file content"))
 })
 
@@ -390,10 +390,10 @@ test_that("write calls REST service properly", {
 
     REST$write("file", uuid, fileContent, "text/html")
 
-    expect_that(fakeHttp$URLIsProperlyConfigured, is_true())
-    expect_that(fakeHttp$requestBodyIsProvided, is_true())
-    expect_that(fakeHttp$requestHeaderContainsAuthorizationField, is_true())
-    expect_that(fakeHttp$requestHeaderContainsContentTypeField, is_true())
+    expect_true(fakeHttp$URLIsProperlyConfigured)
+    expect_true(fakeHttp$requestBodyIsProvided)
+    expect_true(fakeHttp$requestHeaderContainsAuthorizationField)
+    expect_true(fakeHttp$requestHeaderContainsContentTypeField)
 })
 
 test_that("write raises exception if server response code is not between 200 and 300", {
index a6e420962bce9777d56d69c4ded58c015986b288..a95247f77c7d457d9f368ef321a027a980652e85 100644 (file)
@@ -37,7 +37,7 @@ test_that(paste("getFileListing by default returns sorted path of all files",
     resultsMatch <- length(expectedResult) == length(result) &&
                     all(expectedResult == result)
 
-    expect_that(resultsMatch, is_true())
+    expect_true(resultsMatch)
 })
 
 test_that(paste("getFileListing returns sorted names of all direct children",
@@ -58,7 +58,7 @@ test_that(paste("getFileListing returns sorted names of all direct children",
     resultsMatch <- length(expectedResult) == length(result) &&
                     all(expectedResult == result)
 
-    expect_that(resultsMatch, is_true())
+    expect_true(resultsMatch)
 })
 
 test_that("add adds content to inside collection tree", {
@@ -73,8 +73,8 @@ test_that("add adds content to inside collection tree", {
     animalContainsFish <- animal$get("fish")$getName() == fish$getName()
     animalContainsDog  <- animal$get("dog")$getName()  == dog$getName()
 
-    expect_that(animalContainsFish, is_true())
-    expect_that(animalContainsDog, is_true())
+    expect_true(animalContainsFish)
+    expect_true(animalContainsDog)
 })
 
 test_that("add raises exception if content name is empty string", {
@@ -143,7 +143,7 @@ test_that("remove removes content from subcollection", {
 
     returnValueAfterRemovalIsNull <- is.null(animal$get("fish"))
 
-    expect_that(returnValueAfterRemovalIsNull, is_true())
+    expect_true(returnValueAfterRemovalIsNull)
 })
 
 test_that(paste("remove raises exception",
@@ -198,10 +198,10 @@ test_that(paste("get returns ArvadosFile or Subcollection",
     returnedFishIsSubcollection <- "Subcollection" %in% class(returnedFish)
     returnedDogIsArvadosFile    <- "ArvadosFile"   %in% class(returnedDog)
 
-    expect_that(returnedFishIsSubcollection, is_true())
+    expect_true(returnedFishIsSubcollection)
     expect_that(returnedFish$getName(), equals("fish"))
 
-    expect_that(returnedDogIsArvadosFile, is_true())
+    expect_true(returnedDogIsArvadosFile)
     expect_that(returnedDog$getName(), equals("dog"))
 })
 
@@ -215,7 +215,7 @@ test_that(paste("get returns NULL if file or folder",
 
     returnedDogIsNull <- is.null(animal$get("dog"))
 
-    expect_that(returnedDogIsNull, is_true())
+    expect_true(returnedDogIsNull)
 })
 
 test_that("getFirst returns first child in the subcollection", {
@@ -234,7 +234,7 @@ test_that("getFirst returns NULL if subcollection contains no children", {
 
     returnedElementIsNull <- is.null(animal$getFirst())
 
-    expect_that(returnedElementIsNull, is_true())
+    expect_true(returnedElementIsNull)
 })
 
 test_that(paste("setCollection by default sets collection",
@@ -261,7 +261,7 @@ test_that(paste("setCollection sets collection filed of subcollection only",
     fishCollectionIsNull <- is.null(fish$getCollection())
 
     expect_that(animal$getCollection(), equals("myCollection"))
-    expect_that(fishCollectionIsNull, is_true())
+    expect_true(fishCollectionIsNull)
 })
 
 test_that(paste("move raises exception if subcollection",
@@ -330,8 +330,8 @@ test_that("move moves subcollection inside collection tree", {
     fishIsNullOnOldLocation <- is.null(collection$get("animal/fish"))
     fishExistsOnNewLocation <- !is.null(collection$get("fish"))
 
-    expect_that(fishIsNullOnOldLocation, is_true())
-    expect_that(fishExistsOnNewLocation, is_true())
+    expect_true(fishIsNullOnOldLocation)
+    expect_true(fishExistsOnNewLocation)
 })
 
 test_that(paste("getSizeInBytes returns zero if subcollection",
@@ -425,8 +425,8 @@ test_that("copy copies subcollection inside collection tree", {
     fishExistsOnOldLocation <- !is.null(collection$get("animal/fish"))
     fishExistsOnNewLocation <- !is.null(collection$get("fish"))
 
-    expect_that(fishExistsOnOldLocation, is_true())
-    expect_that(fishExistsOnNewLocation, is_true())
+    expect_true(fishExistsOnOldLocation)
+    expect_true(fishExistsOnNewLocation)
 })
 
 test_that("duplicate performs deep cloning of Subcollection", {
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 b10f02d1401b9e31014eb30b32e18adfdcb394d2..f0645311651c244c7d4f18dc3710663d01c2c481 100644 (file)
@@ -446,7 +446,7 @@ def upload_docker(arvrunner, tool):
                     "Option 'dockerOutputDirectory' of DockerRequirement not supported.")
             arvados_cwl.arvdocker.arv_docker_get_image(arvrunner.api, docker_req, True, arvrunner.project_uuid)
         else:
-            arvados_cwl.arvdocker.arv_docker_get_image(arvrunner.api, {"dockerPull": "arvados/jobs"}, True, arvrunner.project_uuid)
+            arvados_cwl.arvdocker.arv_docker_get_image(arvrunner.api, {"dockerPull": "arvados/jobs:"+__version__}, True, arvrunner.project_uuid)
     elif isinstance(tool, cwltool.workflow.Workflow):
         for s in tool.steps:
             upload_docker(arvrunner, s.embedded_tool)
index 6de404f448e2c7c14911db1b45df7fe7ec0305f0..dc4a6263178afdff11cbdd296c56f5b846467c3f 100755 (executable)
@@ -129,7 +129,7 @@ fi
 
 export ARVADOS_API_HOST=localhost:8000
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=\$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=\$(cat /var/lib/arvados-arvbox/superuser_token)
 
 if test -n "$build" ; then
   /usr/src/arvados/build/build-dev-docker-jobs-image.sh
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 394e30a737e2aff13128df90d96decfc12428863..a8d601d5f6591d2f224cd9a7d0f941be8894b541 100644 (file)
@@ -49,12 +49,12 @@ func (sc *Config) GetCluster(clusterID string) (*Cluster, error) {
                        }
                }
        }
-       if cc, ok := sc.Clusters[clusterID]; !ok {
+       cc, ok := sc.Clusters[clusterID]
+       if !ok {
                return nil, fmt.Errorf("cluster %q is not configured", clusterID)
-       } else {
-               cc.ClusterID = clusterID
-               return &cc, nil
        }
+       cc.ClusterID = clusterID
+       return &cc, nil
 }
 
 type WebDAVCacheConfig struct {
@@ -183,6 +183,7 @@ type Cluster struct {
                LoginCluster       string
                RemoteTokenRefresh Duration
                TokenLifetime      Duration
+               TrustedClients     map[string]struct{}
        }
        Mail struct {
                MailchimpAPIKey                string
@@ -219,6 +220,7 @@ type Cluster struct {
                UserNotifierEmailFrom                 string
                UserProfileNotificationAddress        string
                PreferDomainForUsername               string
+               UserSetupMailText                     string
        }
        Volumes   map[string]Volume
        Workbench struct {
index 5e57fed3beab3281b1d498936edb4eed813398ec..aa75fee7c4d0f5bf47826d12300b51cdcf08a424 100644 (file)
@@ -598,9 +598,8 @@ func (fs *fileSystem) remove(name string, recursive bool) error {
 func (fs *fileSystem) Sync() error {
        if syncer, ok := fs.root.(syncer); ok {
                return syncer.Sync()
-       } else {
-               return ErrInvalidOperation
        }
+       return ErrInvalidOperation
 }
 
 func (fs *fileSystem) Flush(string, bool) error {
index 060b57b493cbf555d4d87d9b71db4f6171ff85b8..1de558a1bda4ab7c2def0c03d32998b0e18535ae 100644 (file)
@@ -109,16 +109,15 @@ func (fs *collectionFileSystem) newNode(name string, perm os.FileMode, modTime t
                                inodes: make(map[string]inode),
                        },
                }, nil
-       } else {
-               return &filenode{
-                       fs: fs,
-                       fileinfo: fileinfo{
-                               name:    name,
-                               mode:    perm & ^os.ModeDir,
-                               modTime: modTime,
-                       },
-               }, nil
        }
+       return &filenode{
+               fs: fs,
+               fileinfo: fileinfo{
+                       name:    name,
+                       mode:    perm & ^os.ModeDir,
+                       modTime: modTime,
+               },
+       }, nil
 }
 
 func (fs *collectionFileSystem) Child(name string, replace func(inode) (inode, error)) (inode, error) {
@@ -729,12 +728,11 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
                        // it fails, we'll try again next time.
                        close(done)
                        return nil
-               } else {
-                       // In sync mode, we proceed regardless of
-                       // whether another flush is in progress: It
-                       // can't finish before we do, because we hold
-                       // fn's lock until we finish our own writes.
                }
+               // In sync mode, we proceed regardless of
+               // whether another flush is in progress: It
+               // can't finish before we do, because we hold
+               // fn's lock until we finish our own writes.
                seg.flushing = done
                offsets = append(offsets, len(block))
                if len(refs) == 1 {
@@ -802,9 +800,8 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
        }()
        if sync {
                return <-errs
-       } else {
-               return nil
        }
+       return nil
 }
 
 type flushOpts struct {
index c9f6a0b675b17b6de869198008054793bae7f141..097e292d386bc540b1955d37ce1506afbef3e933 100644 (file)
@@ -81,9 +81,8 @@ func (s *Suite) TestPingOverride(c *check.C) {
                                ok = !ok
                                if ok {
                                        return nil
-                               } else {
-                                       return errors.New("good error")
                                }
+                               return errors.New("good error")
                        },
                },
        }
index 59981e3e55265be4eed1827d3570391533ac3a30..5336488df0508039e968d9434cae343f66b26c63 100644 (file)
@@ -64,9 +64,8 @@ func rewrapResponseWriter(w http.ResponseWriter, wrapped http.ResponseWriter) ht
                        http.ResponseWriter
                        http.Hijacker
                }{w, hijacker}
-       } else {
-               return w
        }
+       return w
 }
 
 func Logger(req *http.Request) logrus.FieldLogger {
index b18d7e046404c34b0f1486aadfb667a2fe1e01d7..e65baa3b3f48460329a49f95782b664b0bc150e0 100644 (file)
@@ -191,11 +191,11 @@ func (kc *KeepClient) PutB(buffer []byte) (string, int, error) {
 //
 // If the block hash and data size are known, PutHR is more efficient.
 func (kc *KeepClient) PutR(r io.Reader) (locator string, replicas int, err error) {
-       if buffer, err := ioutil.ReadAll(r); err != nil {
+       buffer, err := ioutil.ReadAll(r)
+       if err != nil {
                return "", 0, err
-       } else {
-               return kc.PutB(buffer)
        }
+       return kc.PutB(buffer)
 }
 
 func (kc *KeepClient) getOrHead(method string, locator string, header http.Header) (io.ReadCloser, int64, string, http.Header, error) {
@@ -290,10 +290,9 @@ func (kc *KeepClient) getOrHead(method string, locator string, header http.Heade
                                        Hash:   md5.New(),
                                        Check:  locator[0:32],
                                }, expectLength, url, resp.Header, nil
-                       } else {
-                               resp.Body.Close()
-                               return nil, expectLength, url, resp.Header, nil
                        }
+                       resp.Body.Close()
+                       return nil, expectLength, url, resp.Header, nil
                }
                serversToTry = retryList
        }
@@ -493,9 +492,8 @@ func (kc *KeepClient) getSortedRoots(locator string) []string {
 func (kc *KeepClient) cache() *BlockCache {
        if kc.BlockCache != nil {
                return kc.BlockCache
-       } else {
-               return DefaultBlockCache
        }
+       return DefaultBlockCache
 }
 
 func (kc *KeepClient) ClearBlockCache() {
@@ -576,9 +574,8 @@ var reqIDGen = httpserver.IDGenerator{Prefix: "req-"}
 func (kc *KeepClient) getRequestID() string {
        if kc.RequestID != "" {
                return kc.RequestID
-       } else {
-               return reqIDGen.Next()
        }
+       return reqIDGen.Next()
 }
 
 type Locator struct {
index 2604b02b17aaeb412b2519e4c09a69264fa8d340..8d595fbe14016e96645c39c2db4dae494c26b151 100644 (file)
@@ -139,9 +139,9 @@ func UploadToStubHelper(c *C, st http.Handler, f func(*KeepClient, string,
        kc, _ := MakeKeepClient(arv)
 
        reader, writer := io.Pipe()
-       upload_status := make(chan uploadStatus)
+       uploadStatusChan := make(chan uploadStatus)
 
-       f(kc, ks.url, reader, writer, upload_status)
+       f(kc, ks.url, reader, writer, uploadStatusChan)
 }
 
 func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
@@ -156,15 +156,15 @@ func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
                make(chan string)}
 
        UploadToStubHelper(c, st,
-               func(kc *KeepClient, url string, reader io.ReadCloser, writer io.WriteCloser, upload_status chan uploadStatus) {
+               func(kc *KeepClient, url string, reader io.ReadCloser, writer io.WriteCloser, uploadStatusChan chan uploadStatus) {
                        kc.StorageClasses = []string{"hot"}
-                       go kc.uploadToKeepServer(url, st.expectPath, reader, upload_status, int64(len("foo")), kc.getRequestID())
+                       go kc.uploadToKeepServer(url, st.expectPath, reader, uploadStatusChan, int64(len("foo")), kc.getRequestID())
 
                        writer.Write([]byte("foo"))
                        writer.Close()
 
                        <-st.handled
-                       status := <-upload_status
+                       status := <-uploadStatusChan
                        c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
                })
 }
@@ -179,12 +179,12 @@ func (s *StandaloneSuite) TestUploadToStubKeepServerBufferReader(c *C) {
                make(chan string)}
 
        UploadToStubHelper(c, st,
-               func(kc *KeepClient, url string, _ io.ReadCloser, _ io.WriteCloser, upload_status chan uploadStatus) {
-                       go kc.uploadToKeepServer(url, st.expectPath, bytes.NewBuffer([]byte("foo")), upload_status, 3, kc.getRequestID())
+               func(kc *KeepClient, url string, _ io.ReadCloser, _ io.WriteCloser, uploadStatusChan chan uploadStatus) {
+                       go kc.uploadToKeepServer(url, st.expectPath, bytes.NewBuffer([]byte("foo")), uploadStatusChan, 3, kc.getRequestID())
 
                        <-st.handled
 
-                       status := <-upload_status
+                       status := <-uploadStatusChan
                        c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
                })
 }
@@ -233,16 +233,16 @@ func (s *StandaloneSuite) TestFailedUploadToStubKeepServer(c *C) {
 
        UploadToStubHelper(c, st,
                func(kc *KeepClient, url string, reader io.ReadCloser,
-                       writer io.WriteCloser, upload_status chan uploadStatus) {
+                       writer io.WriteCloser, uploadStatusChan chan uploadStatus) {
 
-                       go kc.uploadToKeepServer(url, hash, reader, upload_status, 3, kc.getRequestID())
+                       go kc.uploadToKeepServer(url, hash, reader, uploadStatusChan, 3, kc.getRequestID())
 
                        writer.Write([]byte("foo"))
                        writer.Close()
 
                        <-st.handled
 
-                       status := <-upload_status
+                       status := <-uploadStatusChan
                        c.Check(status.url, Equals, fmt.Sprintf("%s/%s", url, hash))
                        c.Check(status.statusCode, Equals, 500)
                })
@@ -770,9 +770,9 @@ type BarHandler struct {
        handled chan string
 }
 
-func (this BarHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
+func (h BarHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
        resp.Write([]byte("bar"))
-       this.handled <- fmt.Sprintf("http://%s", req.Host)
+       h.handled <- fmt.Sprintf("http://%s", req.Host)
 }
 
 func (s *StandaloneSuite) TestChecksum(c *C) {
@@ -860,9 +860,9 @@ func (s *StandaloneSuite) TestGetWithFailures(c *C) {
        c.Check(n, Equals, int64(3))
        c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks1[0].url, hash))
 
-       read_content, err2 := ioutil.ReadAll(r)
+       readContent, err2 := ioutil.ReadAll(r)
        c.Check(err2, Equals, nil)
-       c.Check(read_content, DeepEquals, content)
+       c.Check(readContent, DeepEquals, content)
 }
 
 func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
@@ -892,9 +892,9 @@ func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
                c.Check(n, Equals, int64(len(content)))
                c.Check(url2, Matches, fmt.Sprintf("http://localhost:\\d+/%s", hash))
 
-               read_content, err2 := ioutil.ReadAll(r)
+               readContent, err2 := ioutil.ReadAll(r)
                c.Check(err2, Equals, nil)
-               c.Check(read_content, DeepEquals, content)
+               c.Check(readContent, DeepEquals, content)
        }
        {
                n, url2, err := kc.Ask(hash)
@@ -921,9 +921,9 @@ type StubProxyHandler struct {
        handled chan string
 }
 
-func (this StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
+func (h StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
        resp.Header().Set("X-Keep-Replicas-Stored", "2")
-       this.handled <- fmt.Sprintf("http://%s", req.Host)
+       h.handled <- fmt.Sprintf("http://%s", req.Host)
 }
 
 func (s *StandaloneSuite) TestPutProxy(c *C) {
index 7989e66c03728fbf383946c4fb7a21ed03199ac3..594379b4fabe6ed10383488e50be4d2b9e1a7de7 100644 (file)
@@ -48,22 +48,22 @@ type svcList struct {
 }
 
 type uploadStatus struct {
-       err             error
-       url             string
-       statusCode      int
-       replicas_stored int
-       response        string
+       err            error
+       url            string
+       statusCode     int
+       replicasStored int
+       response       string
 }
 
 func (this *KeepClient) uploadToKeepServer(host string, hash string, body io.Reader,
-       upload_status chan<- uploadStatus, expectedLength int64, reqid string) {
+       uploadStatusChan chan<- uploadStatus, expectedLength int64, reqid string) {
 
        var req *http.Request
        var err error
        var url = fmt.Sprintf("%s/%s", host, hash)
        if req, err = http.NewRequest("PUT", url, nil); err != nil {
                DebugPrintf("DEBUG: [%s] Error creating request PUT %v error: %v", reqid, url, err.Error())
-               upload_status <- uploadStatus{err, url, 0, 0, ""}
+               uploadStatusChan <- uploadStatus{err, url, 0, 0, ""}
                return
        }
 
@@ -87,7 +87,7 @@ func (this *KeepClient) uploadToKeepServer(host string, hash string, body io.Rea
        var resp *http.Response
        if resp, err = this.httpClient().Do(req); err != nil {
                DebugPrintf("DEBUG: [%s] Upload failed %v error: %v", reqid, url, err.Error())
-               upload_status <- uploadStatus{err, url, 0, 0, err.Error()}
+               uploadStatusChan <- uploadStatus{err, url, 0, 0, err.Error()}
                return
        }
 
@@ -103,16 +103,16 @@ func (this *KeepClient) uploadToKeepServer(host string, hash string, body io.Rea
        response := strings.TrimSpace(string(respbody))
        if err2 != nil && err2 != io.EOF {
                DebugPrintf("DEBUG: [%s] Upload %v error: %v response: %v", reqid, url, err2.Error(), response)
-               upload_status <- uploadStatus{err2, url, resp.StatusCode, rep, response}
+               uploadStatusChan <- uploadStatus{err2, url, resp.StatusCode, rep, response}
        } else if resp.StatusCode == http.StatusOK {
                DebugPrintf("DEBUG: [%s] Upload %v success", reqid, url)
-               upload_status <- uploadStatus{nil, url, resp.StatusCode, rep, response}
+               uploadStatusChan <- uploadStatus{nil, url, resp.StatusCode, rep, response}
        } else {
                if resp.StatusCode >= 300 && response == "" {
                        response = resp.Status
                }
                DebugPrintf("DEBUG: [%s] Upload %v error: %v response: %v", reqid, url, resp.StatusCode, response)
-               upload_status <- uploadStatus{errors.New(resp.Status), url, resp.StatusCode, rep, response}
+               uploadStatusChan <- uploadStatus{errors.New(resp.Status), url, resp.StatusCode, rep, response}
        }
 }
 
@@ -133,16 +133,16 @@ func (this *KeepClient) putReplicas(
        active := 0
 
        // Used to communicate status from the upload goroutines
-       upload_status := make(chan uploadStatus)
+       uploadStatusChan := make(chan uploadStatus)
        defer func() {
                // Wait for any abandoned uploads (e.g., we started
                // two uploads and the first replied with replicas=2)
                // to finish before closing the status channel.
                go func() {
                        for active > 0 {
-                               <-upload_status
+                               <-uploadStatusChan
                        }
-                       close(upload_status)
+                       close(uploadStatusChan)
                }()
        }()
 
@@ -169,7 +169,7 @@ func (this *KeepClient) putReplicas(
                                // Start some upload requests
                                if nextServer < len(sv) {
                                        DebugPrintf("DEBUG: [%s] Begin upload %s to %s", reqid, hash, sv[nextServer])
-                                       go this.uploadToKeepServer(sv[nextServer], hash, getReader(), upload_status, expectedLength, reqid)
+                                       go this.uploadToKeepServer(sv[nextServer], hash, getReader(), uploadStatusChan, expectedLength, reqid)
                                        nextServer += 1
                                        active += 1
                                } else {
@@ -189,13 +189,13 @@ func (this *KeepClient) putReplicas(
 
                        // Now wait for something to happen.
                        if active > 0 {
-                               status := <-upload_status
+                               status := <-uploadStatusChan
                                active -= 1
 
                                if status.statusCode == 200 {
                                        // good news!
-                                       replicasDone += status.replicas_stored
-                                       replicasTodo -= status.replicas_stored
+                                       replicasDone += status.replicasStored
+                                       replicasTodo -= status.replicasStored
                                        locator = status.response
                                        delete(lastError, status.url)
                                } else {
index ec9ae6ece0e68bb0b1f2428bc0418fb96b341656..7a705eb8c2f6ac9c6a7fe71687f209e6f67fdc1a 100644 (file)
@@ -48,7 +48,7 @@ type FileStreamSegment struct {
        Name   string
 }
 
-// Represents a single line from a manifest.
+// ManifestStream represents a single line from a manifest.
 type ManifestStream struct {
        StreamName         string
        Blocks             []string
@@ -152,32 +152,32 @@ func (s *ManifestStream) FileSegmentIterByName(filepath string) <-chan *FileSegm
        return ch
 }
 
-func firstBlock(offsets []uint64, range_start uint64) int {
-       // range_start/block_start is the inclusive lower bound
-       // range_end/block_end is the exclusive upper bound
+func firstBlock(offsets []uint64, rangeStart uint64) int {
+       // rangeStart/blockStart is the inclusive lower bound
+       // rangeEnd/blockEnd is the exclusive upper bound
 
        hi := len(offsets) - 1
        var lo int
        i := ((hi + lo) / 2)
-       block_start := offsets[i]
-       block_end := offsets[i+1]
+       blockStart := offsets[i]
+       blockEnd := offsets[i+1]
 
        // perform a binary search for the first block
-       // assumes that all of the blocks are contiguous, so range_start is guaranteed
+       // assumes that all of the blocks are contiguous, so rangeStart is guaranteed
        // to either fall into the range of a block or be outside the block range entirely
-       for !(range_start >= block_start && range_start < block_end) {
+       for !(rangeStart >= blockStart && rangeStart < blockEnd) {
                if lo == i {
                        // must be out of range, fail
                        return -1
                }
-               if range_start > block_start {
+               if rangeStart > blockStart {
                        lo = i
                } else {
                        hi = i
                }
                i = ((hi + lo) / 2)
-               block_start = offsets[i]
-               block_end = offsets[i+1]
+               blockStart = offsets[i]
+               blockEnd = offsets[i+1]
        }
        return i
 }
@@ -357,7 +357,7 @@ func (stream segmentedStream) normalizedText(name string) string {
        }
        sort.Strings(sortedfiles)
 
-       stream_tokens := []string{EscapeName(name)}
+       streamTokens := []string{EscapeName(name)}
 
        blocks := make(map[blockdigest.BlockDigest]int64)
        var streamoffset int64
@@ -367,50 +367,50 @@ func (stream segmentedStream) normalizedText(name string) string {
                for _, segment := range stream[streamfile] {
                        b, _ := ParseBlockLocator(segment.Locator)
                        if _, ok := blocks[b.Digest]; !ok {
-                               stream_tokens = append(stream_tokens, segment.Locator)
+                               streamTokens = append(streamTokens, segment.Locator)
                                blocks[b.Digest] = streamoffset
                                streamoffset += int64(b.Size)
                        }
                }
        }
 
-       if len(stream_tokens) == 1 {
-               stream_tokens = append(stream_tokens, "d41d8cd98f00b204e9800998ecf8427e+0")
+       if len(streamTokens) == 1 {
+               streamTokens = append(streamTokens, "d41d8cd98f00b204e9800998ecf8427e+0")
        }
 
        for _, streamfile := range sortedfiles {
                // Add in file segments
-               span_start := int64(-1)
-               span_end := int64(0)
+               spanStart := int64(-1)
+               spanEnd := int64(0)
                fout := EscapeName(streamfile)
                for _, segment := range stream[streamfile] {
                        // Collapse adjacent segments
                        b, _ := ParseBlockLocator(segment.Locator)
                        streamoffset = blocks[b.Digest] + int64(segment.Offset)
-                       if span_start == -1 {
-                               span_start = streamoffset
-                               span_end = streamoffset + int64(segment.Len)
+                       if spanStart == -1 {
+                               spanStart = streamoffset
+                               spanEnd = streamoffset + int64(segment.Len)
                        } else {
-                               if streamoffset == span_end {
-                                       span_end += int64(segment.Len)
+                               if streamoffset == spanEnd {
+                                       spanEnd += int64(segment.Len)
                                } else {
-                                       stream_tokens = append(stream_tokens, fmt.Sprintf("%d:%d:%s", span_start, span_end-span_start, fout))
-                                       span_start = streamoffset
-                                       span_end = streamoffset + int64(segment.Len)
+                                       streamTokens = append(streamTokens, fmt.Sprintf("%d:%d:%s", spanStart, spanEnd-spanStart, fout))
+                                       spanStart = streamoffset
+                                       spanEnd = streamoffset + int64(segment.Len)
                                }
                        }
                }
 
-               if span_start != -1 {
-                       stream_tokens = append(stream_tokens, fmt.Sprintf("%d:%d:%s", span_start, span_end-span_start, fout))
+               if spanStart != -1 {
+                       streamTokens = append(streamTokens, fmt.Sprintf("%d:%d:%s", spanStart, spanEnd-spanStart, fout))
                }
 
                if len(stream[streamfile]) == 0 {
-                       stream_tokens = append(stream_tokens, fmt.Sprintf("0:0:%s", fout))
+                       streamTokens = append(streamTokens, fmt.Sprintf("0:0:%s", fout))
                }
        }
 
-       return strings.Join(stream_tokens, " ") + "\n"
+       return strings.Join(streamTokens, " ") + "\n"
 }
 
 func (m segmentedManifest) manifestTextForPath(srcpath, relocate string) string {
@@ -429,12 +429,12 @@ func (m segmentedManifest) manifestTextForPath(srcpath, relocate string) string
                filesegs, okfile := stream[filename]
                if okfile {
                        newstream := make(segmentedStream)
-                       relocate_stream, relocate_filename := splitPath(relocate)
-                       if relocate_filename == "" {
-                               relocate_filename = filename
+                       relocateStream, relocateFilename := splitPath(relocate)
+                       if relocateFilename == "" {
+                               relocateFilename = filename
                        }
-                       newstream[relocate_filename] = filesegs
-                       return newstream.normalizedText(relocate_stream)
+                       newstream[relocateFilename] = filesegs
+                       return newstream.normalizedText(relocateStream)
                }
        }
 
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 19c2b58ef7ca4aee10af8413155042eb418d56b1..bb11f0a6e6b2fa66d4d34cbdb956f852627ad810 100644 (file)
@@ -293,7 +293,7 @@ $graph:
   - arguments:
       - arvbox
       - cat
-      - /var/lib/arvados/superuser_token
+      - /var/lib/arvados-arvbox/superuser_token
     class: CommandLineTool
     cwlVersion: v1.0
     id: '#superuser_tok'
@@ -476,10 +476,10 @@ $graph:
 
 
                           ARVADOS_VIRTUAL_MACHINE_UUID=\$($(inputs.arvbox_bin.path)
-                          cat /var/lib/arvados/vm-uuid)
+                          cat /var/lib/arvados-arvbox/vm-uuid)
 
                           ARVADOS_API_TOKEN=\$($(inputs.arvbox_bin.path) cat
-                          /var/lib/arvados/superuser_token)
+                          /var/lib/arvados-arvbox/superuser_token)
 
                           while ! curl --fail --insecure --silent -H
                           "Authorization: Bearer $ARVADOS_API_TOKEN"
index d2ce253a9304e402d31b251ff568cd365cf90f67..e2ad5db5d6c7a969b3cdfb12171d8124dba771a7 100755 (executable)
@@ -16,4 +16,4 @@ requirements:
     envDef:
       ARVBOX_CONTAINER: "$(inputs.container)"
   InlineJavascriptRequirement: {}
-arguments: [arvbox, cat, /var/lib/arvados/superuser_token]
+arguments: [arvbox, cat, /var/lib/arvados-arvbox/superuser_token]
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 cd23706d08140f2176fccb063ed5b4070202536a..76e8da0c72b306c7fc33612f5c345d866624c1fa 100644 (file)
@@ -135,7 +135,7 @@ class Arvados::V1::UsersController < ApplicationController
                               vm_uuid: params[:vm_uuid])
 
     # setup succeeded. send email to user
-    if params[:send_notification_email]
+    if params[:send_notification_email] && !Rails.configuration.Users.UserSetupMailText.empty?
       begin
         UserNotifier.account_is_setup(@object).deliver_now
       rescue => e
index c6c48a5b6b13c803d8d54d660a2d8fbd2a265740..015b61dc494c1c7b3cff629407cb0ebdc0ff656c 100644 (file)
@@ -21,13 +21,28 @@ class ApiClient < ArvadosModel
   protected
 
   def from_trusted_url
-    norm(self.url_prefix) == norm(Rails.configuration.Services.Workbench1.ExternalURL) ||
-      norm(self.url_prefix) == norm(Rails.configuration.Services.Workbench2.ExternalURL)
+    norm_url_prefix = norm(self.url_prefix)
+
+    [Rails.configuration.Services.Workbench1.ExternalURL,
+     Rails.configuration.Services.Workbench2.ExternalURL,
+     "https://controller.api.client.invalid"].each do |url|
+      if norm_url_prefix == norm(url)
+        return true
+      end
+    end
+
+    Rails.configuration.Login.TrustedClients.keys.each do |url|
+      if norm_url_prefix == norm(url)
+        return true
+      end
+    end
+
+    false
   end
 
   def norm url
     # normalize URL for comparison
-    url = URI(url)
+    url = URI(url.to_s)
     if url.scheme == "https"
       url.port == "443"
     end
index ab6fd8000c1f4a966be7e01450402719f7182d5a..518fe569377ab1b2c2b21880e4f3411aa340844a 100644 (file)
@@ -268,12 +268,14 @@ class ApiClientAuthorization < ArvadosModel
       end
 
       act_as_system_user do
-        if user.is_active && !remote_user['is_active']
+        if (user.is_active && !remote_user['is_active']) or (user.is_invited && !remote_user['is_invited'])
+          # Synchronize the user's "active/invited" state state.  This
+          # also saves the record.
           user.unsetup
+        else
+          user.save!
         end
 
-        user.save!
-
         # We will accept this token (and avoid reloading the user
         # record) for 'RemoteTokenRefresh' (default 5 minutes).
         # Possible todo:
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
index 778ad7d0bb1728c22ad45dcfecdc5264f1c65312..8ec90f7e53a38805eff5b9ebac846eb88a4d7117 100644 (file)
@@ -38,7 +38,8 @@ class User < ArvadosModel
   after_create :auto_setup_new_user, :if => Proc.new {
     Rails.configuration.Users.AutoSetupNewUsers and
     (uuid != system_user_uuid) and
-    (uuid != anonymous_user_uuid)
+    (uuid != anonymous_user_uuid) and
+    (uuid[0..4] == Rails.configuration.ClusterID)
   }
   after_create :send_admin_notifications
 
index 50d164bfa1e8493cef0b9d733062f6cfb4c8fbb6..352ee7754e1e6855c1b2ffc946dad5c24d0962fe 100644 (file)
@@ -2,17 +2,4 @@
 
 SPDX-License-Identifier: AGPL-3.0 %>
 
-<% if not @user.full_name.empty? -%>
-<%= @user.full_name %>,
-<% else -%>
-Hi there,
-<% end -%>
-
-Your Arvados shell account has been set up. Please visit the virtual machines page <% if Rails.configuration.Services.Workbench1.ExternalURL %>at
-
-  <%= Rails.configuration.Services.Workbench1.ExternalURL %><%= "/" if !Rails.configuration.Services.Workbench1.ExternalURL.to_s.end_with?("/") %>users/<%= @user.uuid%>/virtual_machines <% else %><% end %>
-
-for connection instructions.
-
-Thanks,
-The Arvados team.
+<%= ERB.new(Rails.configuration.Users.UserSetupMailText, 0, "-").result(binding) %>
index 4f831160e9351790143505cc16447e6d0507b0e3..69b20420abac9c0c52ccb5aefbccbbfc3110b194 100644 (file)
@@ -110,6 +110,7 @@ arvcfg.declare_config "Users.NewInactiveUserNotificationRecipients", Hash, :new_
 arvcfg.declare_config "Login.SSO.ProviderAppSecret", String, :sso_app_secret
 arvcfg.declare_config "Login.SSO.ProviderAppID", String, :sso_app_id
 arvcfg.declare_config "Login.LoginCluster", String
+arvcfg.declare_config "Login.TrustedClients", Hash
 arvcfg.declare_config "Login.RemoteTokenRefresh", ActiveSupport::Duration
 arvcfg.declare_config "Login.TokenLifetime", ActiveSupport::Duration
 arvcfg.declare_config "TLS.Insecure", Boolean, :sso_insecure
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 ee5dcd3421a9a0bbfd9e2a72be03fc9304fec21f..b7f1aaa1faff4fdf6897fb964567c75407daa9d3 100644 (file)
@@ -1125,3 +1125,17 @@ active_manages_viewing_group:
   name: can_manage
   head_uuid: zzzzz-j7d0g-futrprojviewgrp
   properties: {}
+
+public_favorites_permission_link:
+  uuid: zzzzz-o0j2j-testpublicfavor
+  owner_uuid: zzzzz-tpzed-000000000000000
+  created_at: 2014-01-24 20:42:26 -0800
+  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+  modified_by_user_uuid: zzzzz-tpzed-000000000000000
+  modified_at: 2014-01-24 20:42:26 -0800
+  updated_at: 2014-01-24 20:42:26 -0800
+  tail_uuid: zzzzz-j7d0g-anonymouspublic
+  link_class: permission
+  name: can_read
+  head_uuid: zzzzz-j7d0g-publicfavorites
+  properties: {}
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 ea5d5b1436bd256506cc1c23061dfd81eb8a763f..e0f7b8970dfd34f2a161a75336ef4a3bc964acd1 100644 (file)
@@ -609,6 +609,23 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
   test "setup user with send notification param true and verify email" do
     authorize_with :admin
 
+    Rails.configuration.Users.UserSetupMailText = %{
+<% if not @user.full_name.empty? -%>
+<%= @user.full_name %>,
+<% else -%>
+Hi there,
+<% end -%>
+
+Your Arvados shell account has been set up. Please visit the virtual machines page <% if Rails.configuration.Services.Workbench1.ExternalURL %>at
+
+<%= Rails.configuration.Services.Workbench1.ExternalURL %><%= "/" if !Rails.configuration.Services.Workbench1.ExternalURL.to_s.end_with?("/") %>users/<%= @user.uuid%>/virtual_machines <% else %><% end %>
+
+for connection instructions.
+
+Thanks,
+The Arvados team.
+}
+
     post :setup, params: {
       send_notification_email: 'true',
       user: {
index 8ad09894a16df4bc6281ba95db6c8b6b25be589c..9ad93c2ee6af4f3cb6a6a42f10e85468b90e8946 100644 (file)
@@ -84,6 +84,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       username: 'barney',
       is_admin: true,
       is_active: true,
+      is_invited: true,
     }
   end
 
@@ -153,6 +154,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
 
     # revoke original token
     @stub_content[:is_active] = false
+    @stub_content[:is_invited] = false
 
     # simulate cache expiry
     ApiClientAuthorization.where(
@@ -323,6 +325,91 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_equal 'barney', json_response['username']
   end
 
+  test 'get inactive user from Login cluster when AutoSetupNewUsers is set' do
+    Rails.configuration.Login.LoginCluster = 'zbbbb'
+    Rails.configuration.Users.AutoSetupNewUsers = true
+    @stub_content = {
+      uuid: 'zbbbb-tpzed-000000000000001',
+      email: 'foo@example.com',
+      username: 'barney',
+      is_admin: false,
+      is_active: false,
+      is_invited: false,
+    }
+    get '/arvados/v1/users/current',
+      params: {format: 'json'},
+      headers: auth(remote: 'zbbbb')
+    assert_response :success
+    assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
+    assert_equal false, json_response['is_admin']
+    assert_equal false, json_response['is_active']
+    assert_equal false, json_response['is_invited']
+    assert_equal 'foo@example.com', json_response['email']
+    assert_equal 'barney', json_response['username']
+  end
+
+    test 'get active user from Login cluster when AutoSetupNewUsers is set' do
+    Rails.configuration.Login.LoginCluster = 'zbbbb'
+    Rails.configuration.Users.AutoSetupNewUsers = true
+    @stub_content = {
+      uuid: 'zbbbb-tpzed-000000000000001',
+      email: 'foo@example.com',
+      username: 'barney',
+      is_admin: false,
+      is_active: true,
+      is_invited: true,
+    }
+    get '/arvados/v1/users/current',
+      params: {format: 'json'},
+      headers: auth(remote: 'zbbbb')
+    assert_response :success
+    assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
+    assert_equal false, json_response['is_admin']
+    assert_equal true, json_response['is_active']
+    assert_equal true, json_response['is_invited']
+    assert_equal 'foo@example.com', json_response['email']
+    assert_equal 'barney', json_response['username']
+
+    @stub_content = {
+      uuid: 'zbbbb-tpzed-000000000000001',
+      email: 'foo@example.com',
+      username: 'barney',
+      is_admin: false,
+      is_active: false,
+      is_invited: false,
+    }
+
+    # Use cached value.  User will still be active because we haven't
+    # re-queried the upstream cluster.
+    get '/arvados/v1/users/current',
+      params: {format: 'json'},
+      headers: auth(remote: 'zbbbb')
+    assert_response :success
+    assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
+    assert_equal false, json_response['is_admin']
+    assert_equal true, json_response['is_active']
+    assert_equal true, json_response['is_invited']
+    assert_equal 'foo@example.com', json_response['email']
+    assert_equal 'barney', json_response['username']
+
+    # Delete cached value.  User should be inactive now.
+    act_as_system_user do
+      ApiClientAuthorization.delete_all
+    end
+
+    get '/arvados/v1/users/current',
+      params: {format: 'json'},
+      headers: auth(remote: 'zbbbb')
+    assert_response :success
+    assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
+    assert_equal false, json_response['is_admin']
+    assert_equal false, json_response['is_active']
+    assert_equal false, json_response['is_invited']
+    assert_equal 'foo@example.com', json_response['email']
+    assert_equal 'barney', json_response['username']
+
+  end
+
   test 'pre-activate remote user' do
     @stub_content = {
       uuid: 'zbbbb-tpzed-000000000001234',
@@ -330,6 +417,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       username: 'barney',
       is_admin: true,
       is_active: true,
+      is_invited: true,
     }
 
     post '/arvados/v1/users',
@@ -364,6 +452,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       username: 'barney',
       is_admin: true,
       is_active: true,
+      is_invited: true,
     }
 
     get '/arvados/v1/users/current',
index 93e4c51abf0e9266a1883ab18bf5634ea45722b0..bf47cd175bcd5790930d55b67af74c1664d60926 100644 (file)
@@ -12,6 +12,8 @@ class ApiClientTest < ActiveSupport::TestCase
       Rails.configuration.Login.TokenLifetime = token_lifetime_enabled ? 8.hours : 0
       Rails.configuration.Services.Workbench1.ExternalURL = URI("http://wb1.example.com")
       Rails.configuration.Services.Workbench2.ExternalURL = URI("https://wb2.example.com:443")
+      Rails.configuration.Login.TrustedClients = ActiveSupport::OrderedOptions.new
+      Rails.configuration.Login.TrustedClients[:"https://wb3.example.com"] = ActiveSupport::OrderedOptions.new
 
       act_as_system_user do
         [["http://wb0.example.com", false],
@@ -19,6 +21,8 @@ class ApiClientTest < ActiveSupport::TestCase
         ["http://wb2.example.com", false],
         ["https://wb2.example.com", true],
         ["https://wb2.example.com/", true],
+        ["https://wb3.example.com/", true],
+        ["https://wb4.example.com/", false],
         ].each do |pfx, result|
           a = ApiClient.create(url_prefix: pfx, is_trusted: false)
           if token_lifetime_enabled
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 da6c7fdb88bc825c9918bb0dd92aa7c53a7b7aea..c288786c1323246c589af91aa53fc3d0aa37c557 100644 (file)
@@ -9,6 +9,24 @@ class UserNotifierTest < ActionMailer::TestCase
   # Send the email, then test that it got queued
   test "account is setup" do
     user = users :active
+
+    Rails.configuration.Users.UserSetupMailText = %{
+<% if not @user.full_name.empty? -%>
+<%= @user.full_name %>,
+<% else -%>
+Hi there,
+<% end -%>
+
+Your Arvados shell account has been set up. Please visit the virtual machines page <% if Rails.configuration.Services.Workbench1.ExternalURL %>at
+
+<%= Rails.configuration.Services.Workbench1.ExternalURL %><%= "/" if !Rails.configuration.Services.Workbench1.ExternalURL.to_s.end_with?("/") %>users/<%= @user.uuid%>/virtual_machines <% else %><% end %>
+
+for connection instructions.
+
+Thanks,
+The Arvados team.
+}
+
     email = UserNotifier.account_is_setup user
 
     assert_not_nil email
index 2ff2136ed7191a1d0229fbaced99f520b87212ce..eeb78ad9058d6c35e8b544cbef1a5c6500c90bcf 100644 (file)
@@ -144,14 +144,14 @@ var selectPDH = map[string]interface{}{
 func (c *cache) Update(client *arvados.Client, coll arvados.Collection, fs arvados.CollectionFileSystem) error {
        c.setupOnce.Do(c.setup)
 
-       if m, err := fs.MarshalManifest("."); err != nil || m == coll.ManifestText {
+       m, err := fs.MarshalManifest(".")
+       if err != nil || m == coll.ManifestText {
                return err
-       } else {
-               coll.ManifestText = m
        }
+       coll.ManifestText = m
        var updated arvados.Collection
        defer c.pdhs.Remove(coll.UUID)
-       err := client.RequestAndDecode(&updated, "PATCH", "arvados/v1/collections/"+coll.UUID, nil, map[string]interface{}{
+       err = client.RequestAndDecode(&updated, "PATCH", "arvados/v1/collections/"+coll.UUID, nil, map[string]interface{}{
                "collection": map[string]string{
                        "manifest_text": coll.ManifestText,
                },
@@ -224,13 +224,12 @@ func (c *cache) Get(arv *arvadosclient.ArvadosClient, targetID string, forceRelo
                                })
                        }
                        return collection, err
-               } else {
-                       // PDH changed, but now we know we have
-                       // permission -- and maybe we already have the
-                       // new PDH in the cache.
-                       if coll := c.lookupCollection(arv.ApiToken + "\000" + current.PortableDataHash); coll != nil {
-                               return coll, nil
-                       }
+               }
+               // PDH changed, but now we know we have
+               // permission -- and maybe we already have the
+               // new PDH in the cache.
+               if coll := c.lookupCollection(arv.ApiToken + "\000" + current.PortableDataHash); coll != nil {
+                       return coll, nil
                }
        }
 
index f3edf9894e243c1e99dc2cfd1c669a250e342843..49fb2456f5851662bec9573af6e06978d930d741 100644 (file)
@@ -503,6 +503,8 @@ func (h *handler) s3list(w http.ResponseWriter, r *http.Request, fs arvados.Cust
                // github.com/aws/aws-sdk-net never terminates its
                // paging loop).
                NextMarker string `xml:"NextMarker,omitempty"`
+               // ListObjectsV2 has a KeyCount response field.
+               KeyCount int
        }
        resp := listResp{
                ListResp: s3.ListResp{
@@ -599,6 +601,7 @@ func (h *handler) s3list(w http.ResponseWriter, r *http.Request, fs arvados.Cust
                }
                sort.Slice(resp.CommonPrefixes, func(i, j int) bool { return resp.CommonPrefixes[i].Prefix < resp.CommonPrefixes[j].Prefix })
        }
+       resp.KeyCount = len(resp.Contents)
        w.Header().Set("Content-Type", "application/xml")
        io.WriteString(w, xml.Header)
        if err := xml.NewEncoder(w).Encode(resp); err != nil {
index 51ac5ba98f2c72a49909dc11dd74d00691b46396..786e68afec4ca197980b56270e3f0bc66ab7494d 100644 (file)
@@ -477,6 +477,22 @@ func (s *IntegrationSuite) TestS3ListNoNextMarker(c *check.C) {
        }
 }
 
+// List response should include KeyCount field.
+func (s *IntegrationSuite) TestS3ListKeyCount(c *check.C) {
+       stage := s.s3setup(c)
+       defer stage.teardown(c)
+
+       req, err := http.NewRequest("GET", stage.collbucket.URL("/"), nil)
+       c.Assert(err, check.IsNil)
+       req.Header.Set("Authorization", "AWS "+arvadostest.ActiveTokenV2+":none")
+       req.URL.RawQuery = "prefix=&delimiter=/"
+       resp, err := http.DefaultClient.Do(req)
+       c.Assert(err, check.IsNil)
+       buf, err := ioutil.ReadAll(resp.Body)
+       c.Assert(err, check.IsNil)
+       c.Check(string(buf), check.Matches, `(?ms).*<KeyCount>2</KeyCount>.*`)
+}
+
 func (s *IntegrationSuite) TestS3CollectionList(c *check.C) {
        stage := s.s3setup(c)
        defer stage.teardown(c)
index 0191e5ba45391e4058b24e014ae4d2feab16d0e2..4e5014ef822d7551fc0e3db960b5c6d42f876f63 100644 (file)
@@ -167,7 +167,7 @@ func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
        return http.Serve(listener, httpserver.AddRequestIDs(httpserver.LogRequests(router)))
 }
 
-type ApiTokenCache struct {
+type APITokenCache struct {
        tokens     map[string]int64
        lock       sync.Mutex
        expireTime int64
@@ -175,7 +175,7 @@ type ApiTokenCache struct {
 
 // Cache the token and set an expire time.  If we already have an expire time
 // on the token, it is not updated.
-func (this *ApiTokenCache) RememberToken(token string) {
+func (this *APITokenCache) RememberToken(token string) {
        this.lock.Lock()
        defer this.lock.Unlock()
 
@@ -186,7 +186,7 @@ func (this *ApiTokenCache) RememberToken(token string) {
 }
 
 // Check if the cached token is known and still believed to be valid.
-func (this *ApiTokenCache) RecallToken(token string) bool {
+func (this *APITokenCache) RecallToken(token string) bool {
        this.lock.Lock()
        defer this.lock.Unlock()
 
@@ -211,7 +211,7 @@ func GetRemoteAddress(req *http.Request) string {
        return req.RemoteAddr
 }
 
-func CheckAuthorizationHeader(kc *keepclient.KeepClient, cache *ApiTokenCache, req *http.Request) (pass bool, tok string) {
+func CheckAuthorizationHeader(kc *keepclient.KeepClient, cache *APITokenCache, req *http.Request) (pass bool, tok string) {
        parts := strings.SplitN(req.Header.Get("Authorization"), " ", 2)
        if len(parts) < 2 || !(parts[0] == "OAuth2" || parts[0] == "Bearer") || len(parts[1]) == 0 {
                return false, ""
@@ -265,7 +265,7 @@ var defaultTransport = *(http.DefaultTransport.(*http.Transport))
 type proxyHandler struct {
        http.Handler
        *keepclient.KeepClient
-       *ApiTokenCache
+       *APITokenCache
        timeout   time.Duration
        transport *http.Transport
 }
@@ -289,7 +289,7 @@ func MakeRESTRouter(kc *keepclient.KeepClient, timeout time.Duration, mgmtToken
                KeepClient: kc,
                timeout:    timeout,
                transport:  &transport,
-               ApiTokenCache: &ApiTokenCache{
+               APITokenCache: &APITokenCache{
                        tokens:     make(map[string]int64),
                        expireTime: 300,
                },
@@ -349,9 +349,9 @@ func (h *proxyHandler) Options(resp http.ResponseWriter, req *http.Request) {
        SetCorsHeaders(resp)
 }
 
-var BadAuthorizationHeader = errors.New("Missing or invalid Authorization header")
-var ContentLengthMismatch = errors.New("Actual length != expected content length")
-var MethodNotSupported = errors.New("Method not supported")
+var errBadAuthorizationHeader = errors.New("Missing or invalid Authorization header")
+var errContentLengthMismatch = errors.New("Actual length != expected content length")
+var errMethodNotSupported = errors.New("Method not supported")
 
 var removeHint, _ = regexp.Compile("\\+K@[a-z0-9]{5}(\\+|$)")
 
@@ -379,8 +379,8 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) {
 
        var pass bool
        var tok string
-       if pass, tok = CheckAuthorizationHeader(kc, h.ApiTokenCache, req); !pass {
-               status, err = http.StatusForbidden, BadAuthorizationHeader
+       if pass, tok = CheckAuthorizationHeader(kc, h.APITokenCache, req); !pass {
+               status, err = http.StatusForbidden, errBadAuthorizationHeader
                return
        }
 
@@ -402,7 +402,7 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) {
                        defer reader.Close()
                }
        default:
-               status, err = http.StatusNotImplemented, MethodNotSupported
+               status, err = http.StatusNotImplemented, errMethodNotSupported
                return
        }
 
@@ -420,7 +420,7 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) {
                case "GET":
                        responseLength, err = io.Copy(resp, reader)
                        if err == nil && expectLength > -1 && responseLength != expectLength {
-                               err = ContentLengthMismatch
+                               err = errContentLengthMismatch
                        }
                }
        case keepclient.Error:
@@ -436,8 +436,8 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) {
        }
 }
 
-var LengthRequiredError = errors.New(http.StatusText(http.StatusLengthRequired))
-var LengthMismatchError = errors.New("Locator size hint does not match Content-Length header")
+var errLengthRequired = errors.New(http.StatusText(http.StatusLengthRequired))
+var errLengthMismatch = errors.New("Locator size hint does not match Content-Length header")
 
 func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
        if err := h.checkLoop(resp, req); err != nil {
@@ -474,7 +474,7 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
 
        _, err = fmt.Sscanf(req.Header.Get("Content-Length"), "%d", &expectLength)
        if err != nil || expectLength < 0 {
-               err = LengthRequiredError
+               err = errLengthRequired
                status = http.StatusLengthRequired
                return
        }
@@ -485,7 +485,7 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
                        status = http.StatusBadRequest
                        return
                } else if loc.Size > 0 && int64(loc.Size) != expectLength {
-                       err = LengthMismatchError
+                       err = errLengthMismatch
                        status = http.StatusBadRequest
                        return
                }
@@ -493,8 +493,8 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
 
        var pass bool
        var tok string
-       if pass, tok = CheckAuthorizationHeader(kc, h.ApiTokenCache, req); !pass {
-               err = BadAuthorizationHeader
+       if pass, tok = CheckAuthorizationHeader(kc, h.APITokenCache, req); !pass {
+               err = errBadAuthorizationHeader
                status = http.StatusForbidden
                return
        }
@@ -575,9 +575,9 @@ func (h *proxyHandler) Index(resp http.ResponseWriter, req *http.Request) {
        }()
 
        kc := h.makeKeepClient(req)
-       ok, token := CheckAuthorizationHeader(kc, h.ApiTokenCache, req)
+       ok, token := CheckAuthorizationHeader(kc, h.APITokenCache, req)
        if !ok {
-               status, err = http.StatusForbidden, BadAuthorizationHeader
+               status, err = http.StatusForbidden, errBadAuthorizationHeader
                return
        }
 
@@ -588,7 +588,7 @@ func (h *proxyHandler) Index(resp http.ResponseWriter, req *http.Request) {
 
        // Only GET method is supported
        if req.Method != "GET" {
-               status, err = http.StatusNotImplemented, MethodNotSupported
+               status, err = http.StatusNotImplemented, errMethodNotSupported
                return
        }
 
index 5a277b6007a7bdb7ff4ed2db04ddcb7b44606e5d..4d8a0aec7ac06ec4f38e815fe0d23447723e38fa 100644 (file)
@@ -353,9 +353,8 @@ func (vm *RRVolumeManager) Mounts() []*VolumeMount {
 func (vm *RRVolumeManager) Lookup(uuid string, needWrite bool) *VolumeMount {
        if mnt, ok := vm.mountMap[uuid]; ok && (!needWrite || !mnt.ReadOnly) {
                return mnt
-       } else {
-               return nil
        }
+       return nil
 }
 
 // AllReadable returns an array of all readable volumes
index 122e2bec7c5bb1790fe357f33ded44a369b0fc75..3040cb793c7cbf354a2e3394422df196635f0447 100755 (executable)
@@ -60,6 +60,8 @@ PIPCACHE="$ARVBOX_DATA/pip"
 NPMCACHE="$ARVBOX_DATA/npm"
 GOSTUFF="$ARVBOX_DATA/gopath"
 RLIBS="$ARVBOX_DATA/Rlibs"
+ARVADOS_CONTAINER_PATH="/var/lib/arvados-arvbox"
+GEM_HOME="/var/lib/arvados/lib/ruby/gems/2.5.0"
 
 getip() {
     docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
@@ -78,7 +80,7 @@ gethost() {
 }
 
 getclusterid() {
-    docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/api_uuid_prefix
+    docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
 }
 
 updateconf() {
@@ -96,7 +98,7 @@ EOF
 }
 
 listusers() {
-    docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml $(getclusterid) list
+    docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
 }
 
 wait_for_arvbox() {
@@ -129,9 +131,9 @@ docker_run_dev() {
            "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
            "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
            "--volume=$PG_DATA:/var/lib/postgresql:rw" \
-           "--volume=$VAR_DATA:/var/lib/arvados:rw" \
+           "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
            "--volume=$PASSENGER:/var/lib/passenger:rw" \
-           "--volume=$GEMS:/var/lib/gems:rw" \
+           "--volume=$GEMS:$GEM_HOME:rw" \
            "--volume=$PIPCACHE:/var/lib/pip:rw" \
            "--volume=$NPMCACHE:/var/lib/npm:rw" \
            "--volume=$GOSTUFF:/var/lib/gopath:rw" \
@@ -220,7 +222,7 @@ run() {
         fi
 
         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
-            docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
+            docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
         fi
 
         docker run \
@@ -264,11 +266,6 @@ run() {
                        $ARVBOX_CONTAINER \
                        /usr/local/lib/arvbox/runsu.sh \
                        /usr/local/lib/arvbox/waitforpostgres.sh
-
-                docker exec -ti \
-                       $ARVBOX_CONTAINER \
-                       /usr/local/lib/arvbox/runsu.sh \
-                       /var/lib/arvbox/service/api/run-service --only-setup
             fi
 
             interactive=""
@@ -281,12 +278,12 @@ run() {
                    -e COLUMNS=$(tput cols) \
                    -e TERM=$TERM \
                    -e WORKSPACE=/usr/src/arvados \
-                   -e GEM_HOME=/var/lib/gems \
-                   -e CONFIGSRC=/var/lib/arvados/run_tests \
+                   -e GEM_HOME=$GEM_HOME \
+                   -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
                    $ARVBOX_CONTAINER \
                    /usr/local/lib/arvbox/runsu.sh \
                    /usr/src/arvados/build/run-tests.sh \
-                   --temp /var/lib/arvados/test \
+                   --temp $ARVADOS_CONTAINER_PATH/test \
                    $interactive \
                    "$@"
         elif [[ "$CONFIG" = devenv ]] ; then
@@ -299,15 +296,15 @@ run() {
                     --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 \
+            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 "$@"
+                 /usr/local/lib/arvbox/devenv.sh "$@"
         elif [[ "$CONFIG" =~ dev$ ]] ; then
             docker_run_dev \
                    --detach \
@@ -366,6 +363,7 @@ stop() {
 }
 
 build() {
+    export DOCKER_BUILDKIT=1
     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
         exit 1
@@ -376,15 +374,25 @@ build() {
         FORCE=-f
     fi
     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
-    docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
-    docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
+
+    set +e
+    if which greadlink >/dev/null 2>/dev/null ; then
+        LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
+    else
+        LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
+    fi
+    set -e
+
     if test "$1" = localdemo -o "$1" = publicdemo ; then
-        docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
-        docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
+        BUILDTYPE=demo
     else
-        docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
-        docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
+        BUILDTYPE=dev
     fi
+
+    docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE --build-arg=arvados_version=$GITHEAD --build-arg=workdir=/tools/arvbox/lib/arvbox/docker -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$LOCAL_ARVADOS_ROOT"
+    docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
+    docker build $NO_CACHE -t arvados/arvbox-$BUILDTYPE:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" "$ARVBOX_DOCKER"
+    docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
 }
 
 check() {
@@ -424,7 +432,7 @@ case "$subcmd" in
                -e LINES=$(tput lines) \
                -e COLUMNS=$(tput cols) \
                -e TERM=$TERM \
-               -e GEM_HOME=/var/lib/gems \
+               -e GEM_HOME=$GEM_HOME \
                $ARVBOX_CONTAINER /bin/bash
         ;;
 
@@ -433,14 +441,14 @@ case "$subcmd" in
                -e LINES=$(tput lines) \
                -e COLUMNS=$(tput cols) \
                -e TERM=$TERM \
-               -e GEM_HOME=/var/lib/gems \
+               -e GEM_HOME=$GEM_HOME \
                -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 -
+        exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
         ;;
 
     stop)
@@ -587,24 +595,24 @@ case "$subcmd" in
         if test -n "$1" ; then
             CERT="$1"
         fi
-        docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/root-cert.pem > "$CERT"
+        docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/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 $ARVADOS_CONTAINER_PATH/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 $ARVADOS_CONTAINER_PATH/api_database_pw) exec pg_dump --host=localhost --username=arvados --clean arvados_development > $ARVADOS_CONTAINER_PATH/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 $ARVADOS_CONTAINER_PATH/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados --quiet --file=$ARVADOS_CONTAINER_PATH/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=$GEM_HOME /bin/bash - <<EOF
 sv stop api
 sv stop controller
 sv stop websockets
@@ -615,11 +623,11 @@ cd /usr/src/arvados/services/api
 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
 export RAILS_ENV=development
 bundle exec rake db:drop
-rm /var/lib/arvados/api_database_setup
-rm /var/lib/arvados/superuser_token
-rm /var/lib/arvados/keep0-uuid
-rm /var/lib/arvados/keep1-uuid
-rm /var/lib/arvados/keepproxy-uuid
+rm $ARVADOS_CONTAINER_PATH/api_database_setup
+rm $ARVADOS_CONTAINER_PATH/superuser_token
+rm $ARVADOS_CONTAINER_PATH/keep0-uuid
+rm $ARVADOS_CONTAINER_PATH/keep1-uuid
+rm $ARVADOS_CONTAINER_PATH/keepproxy-uuid
 sv start api
 sv start controller
 sv start websockets
@@ -630,13 +638,21 @@ 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
+if [[ -n "$2" ]] ; then
+          docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
+          docker exec $ARVBOX_CONTAINER sv restart controller
+       else
+           echo "Usage: adduser <username> <email> [password]"
+       fi
         ;;
 
     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
+       if [[ -n "$1" ]] ; then
+          docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
+          docker exec $ARVBOX_CONTAINER sv restart controller
+       else
+           echo "Usage: removeuser <username>"
+       fi
         ;;
 
     listusers)
@@ -673,7 +689,7 @@ EOF
         echo "sv <start|stop|restart> <service> "
         echo "                   change state of service inside arvbox"
         echo "clone <from> <to>  clone dev arvbox"
-        echo "adduser <username> <email>"
+        echo "adduser <username> <email> [password]"
         echo "                   add a user login"
         echo "removeuser <username>"
         echo "                   remove user login"
index eb52ca5a780e252873739c45a2e87fa667748024..115754cac7338cb01737ad8e8ee457682ec7406c 100644 (file)
+# syntax = docker/dockerfile:experimental
 # Copyright (C) The Arvados Authors. All rights reserved.
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-FROM debian:10
+ARG BUILDTYPE
+
+# We're using poor man's conditionals (see
+# https://www.docker.com/blog/advanced-dockerfiles-faster-builds-and-smaller-images-using-buildkit-and-multistage-builds/)
+# here to dtrt in the dev/test scenario and the demo scenario. In the dev/test
+# scenario, we use the docker context (i.e. the copy of Arvados checked out on
+# the host) to build arvados-server. In the demo scenario, we check out a new
+# tree, and use the $arvados_version commit (passed in via an argument).
 
+###########################################################################################################
+FROM debian:10-slim as dev
 ENV DEBIAN_FRONTEND noninteractive
 
+RUN echo "deb http://deb.debian.org/debian buster-backports main" > /etc/apt/sources.list.d/backports.list
+
 RUN apt-get update && \
     apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
-    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 \
-    fuse libfuse-dev \
-    pkg-config libattr1-dev \
-    libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
-    libjson-perl nginx gitolite3 lsof libreadline-dev \
-    apt-transport-https ca-certificates python3-yaml \
-    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 default-jdk-headless bsdmainutils net-tools \
-    ruby ruby-dev bundler shellinabox  && \
-    apt-get clean
+    golang -t buster-backports
+
+RUN apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
+    build-essential ca-certificates git libpam0g-dev
+
+ENV GOPATH /var/lib/gopath
+
+# the --mount option requires the experimental syntax enabled (enables
+# buildkit) on the first line of this file. This Dockerfile must also be built
+# with the DOCKER_BUILDKIT=1 environment variable set.
+RUN --mount=type=bind,target=/usr/src/arvados \
+    cd /usr/src/arvados && \
+    go mod download && \
+    cd cmd/arvados-server && \
+    go install
+
+###########################################################################################################
+FROM debian:10-slim as demo
+ENV DEBIAN_FRONTEND noninteractive
 
-ENV RUBYVERSION_MINOR 2.5
-ENV RUBYVERSION 2.5.1
+RUN echo "deb http://deb.debian.org/debian buster-backports main" > /etc/apt/sources.list.d/backports.list
 
-# Install Ruby from source
-# RUN cd /tmp && \
-#  curl -f http://cache.ruby-lang.org/pub/ruby/${RUBYVERSION_MINOR}/ruby-${RUBYVERSION}.tar.gz | tar -xzf - && \
-#  cd ruby-${RUBYVERSION} && \
-#  ./configure --disable-install-doc && \
-#  make && \
-#  make install && \
-#  cd /tmp && \
-#  rm -rf ruby-${RUBYVERSION}
+RUN apt-get update && \
+    apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
+    golang -t buster-backports
+
+RUN apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
+    build-essential ca-certificates git libpam0g-dev
 
-ENV GEM_HOME /var/lib/gems
-ENV PATH $PATH:/var/lib/gems/bin
+ENV GOPATH /var/lib/gopath
 
-ENV GOVERSION 1.15.2
+ARG arvados_version
+RUN echo arvados_version is git commit $arvados_version
 
-# Install golang binary
-RUN curl -f http://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz | \
-    tar -C /usr/local -xzf -
+RUN cd /usr/src && \
+    git clone --no-checkout https://git.arvados.org/arvados.git && \
+    git -C arvados checkout ${arvados_version} && \
+    cd /usr/src/arvados && \
+    go mod download && \
+    cd cmd/arvados-server && \
+    go install
 
-ENV PATH ${PATH}:/usr/local/go/bin
+###########################################################################################################
+FROM ${BUILDTYPE} as base
+
+###########################################################################################################
+FROM debian:10
+ENV DEBIAN_FRONTEND noninteractive
+
+# The arvbox-specific dependencies are
+#  gnupg2 runit python3-pip python3-setuptools python3-yaml shellinabox netcat less
+RUN apt-get update && \
+    apt-get -yq --no-install-recommends -o Acquire::Retries=6 install \
+    gnupg2 runit python3-pip python3-setuptools python3-yaml shellinabox netcat less && \
+    apt-get clean
+
+ENV GOPATH /var/lib/gopath
+RUN echo buildtype is $BUILDTYPE
+
+RUN mkdir -p $GOPATH/bin/
+COPY --from=base $GOPATH/bin/arvados-server $GOPATH/bin/arvados-server
+RUN $GOPATH/bin/arvados-server --version
+RUN $GOPATH/bin/arvados-server install -type test
+
+RUN /etc/init.d/postgresql start && \
+    su postgres -c 'dropuser arvados' && \
+    su postgres -c 'createuser -s arvbox' && \
+    /etc/init.d/postgresql stop
+
+ENV GEM_HOME /var/lib/arvados/lib/ruby/gems/2.5.0
+ENV PATH $PATH:$GEM_HOME/bin
 
 VOLUME /var/lib/docker
 VOLUME /var/log/nginx
 VOLUME /etc/ssl/private
 
-ADD 8D81803C0EBFCD88.asc /tmp/
+ARG workdir
+
+ADD $workdir/8D81803C0EBFCD88.asc /tmp/
 RUN apt-key add --no-tty /tmp/8D81803C0EBFCD88.asc && \
     rm -f /tmp/8D81803C0EBFCD88.asc
 
@@ -62,35 +108,6 @@ RUN mkdir -p /etc/apt/sources.list.d && \
     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
-
-ENV PJSVERSION=1.9.8
-# bitbucket is the origin, but downloads fail sometimes, so use our own mirror instead.
-#ENV PJSURL=https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-${PJSVERSION}-linux-x86_64.tar.bz2
-ENV PJSURL=http://cache.arvados.org/phantomjs-${PJSVERSION}-linux-x86_64.tar.bz2
-
-RUN set -e && \
- curl -L -f ${PJSURL} | tar -C /usr/local -xjf - && \
- ln -s ../phantomjs-${PJSVERSION}-linux-x86_64/bin/phantomjs /usr/local/bin
-
-ENV GDVERSION=v0.23.0
-ENV GDURL=https://github.com/mozilla/geckodriver/releases/download/$GDVERSION/geckodriver-$GDVERSION-linux64.tar.gz
-RUN set -e && curl -L -f ${GDURL} | tar -C /usr/local/bin -xzf - geckodriver
-
-ENV NODEVERSION v8.15.1
-
-# Install nodejs binary
-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
@@ -100,16 +117,21 @@ ENV LC_ALL en_US.UTF-8
 ARG arvados_version
 RUN echo arvados_version is git commit $arvados_version
 
-ADD fuse.conf /etc/
+COPY $workdir/fuse.conf /etc/
 
-ADD gitolite.rc \
-    keep-setup.sh common.sh createusers.sh \
-    logger runsu.sh waitforpostgres.sh \
-    yml_override.py api-setup.sh \
-    go-setup.sh devenv.sh cluster-config.sh edit_users.py \
+COPY $workdir/gitolite.rc \
+    $workdir/keep-setup.sh $workdir/common.sh $workdir/createusers.sh \
+    $workdir/logger $workdir/runsu.sh $workdir/waitforpostgres.sh \
+    $workdir/yml_override.py $workdir/api-setup.sh \
+    $workdir/go-setup.sh $workdir/devenv.sh $workdir/cluster-config.sh $workdir/edit_users.py \
     /usr/local/lib/arvbox/
 
-ADD runit /etc/runit
+COPY $workdir/runit /etc/runit
+
+# arvbox mounts a docker volume at $ARVADOS_CONTAINER_PATH, make sure that that
+# doesn't overlap with the directory where `arvados-server install -type test`
+# put everything (/var/lib/arvados)
+ENV ARVADOS_CONTAINER_PATH /var/lib/arvados-arvbox
 
 # Start the supervisor.
 ENV SVDIR /etc/service
index ed728204fa171976ef316abd4060e8156b0da2ad..777c71356cdf234baebecf552e5a22917dd13db9 100644 (file)
@@ -19,11 +19,14 @@ RUN cd /usr/src && \
     git -C workbench2 pull && \
     chown -R 1000:1000 /usr/src
 
+# avoid rebuilding arvados-server, it's already been built as part of the base image
+RUN install $GOPATH/bin/arvados-server /usr/local/bin
+
 ADD service/ /var/lib/arvbox/service
 RUN ln -sf /var/lib/arvbox/service /etc
-RUN mkdir -p /var/lib/arvados
-RUN echo "production" > /var/lib/arvados/api_rails_env
-RUN echo "production" > /var/lib/arvados/workbench_rails_env
+RUN mkdir -p $ARVADOS_CONTAINER_PATH
+RUN echo "production" > $ARVADOS_CONTAINER_PATH/api_rails_env
+RUN echo "production" > $ARVADOS_CONTAINER_PATH/workbench_rails_env
 
 RUN /usr/local/lib/arvbox/createusers.sh
 
index c7621e387dbdb51882e08669016a456810da6f24..e9c296a190453e43f3093d4f3aa392be01ee1783 100644 (file)
@@ -7,11 +7,11 @@ ARG arvados_version
 
 ADD service/ /var/lib/arvbox/service
 RUN ln -sf /var/lib/arvbox/service /etc
-RUN mkdir -p /var/lib/arvados
-RUN echo "development" > /var/lib/arvados/api_rails_env
-RUN echo "development" > /var/lib/arvados/workbench_rails_env
+RUN mkdir -p $ARVADOS_CONTAINER_PATH
+RUN echo "development" > $ARVADOS_CONTAINER_PATH/api_rails_env
+RUN echo "development" > $ARVADOS_CONTAINER_PATH/workbench_rails_env
 
 RUN mkdir /etc/test-service && \
     ln -sf /var/lib/arvbox/service/postgres /etc/test-service && \
     ln -sf /var/lib/arvbox/service/certificate /etc/test-service
-RUN mkdir /etc/devenv-service
\ No newline at end of file
+RUN mkdir /etc/devenv-service
index 6a261bf4c55e17b0423071394d03213013a40a08..f20278a69c46a90560dfd9a8888681be076c01c5 100755 (executable)
@@ -11,27 +11,27 @@ set -ex -o pipefail
 
 cd /usr/src/arvados/services/api
 
-if test -s /var/lib/arvados/api_rails_env ; then
-  export RAILS_ENV=$(cat /var/lib/arvados/api_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/api_rails_env ; then
+  export RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/api_rails_env)
 else
   export RAILS_ENV=development
 fi
 
 set -u
 
-flock /var/lib/arvados/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
+flock $ARVADOS_CONTAINER_PATH/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
 
 if test -a /usr/src/arvados/services/api/config/arvados_config.rb ; then
     rm -f config/application.yml config/database.yml
 else
-    uuid_prefix=$(cat /var/lib/arvados/api_uuid_prefix)
-    secret_token=$(cat /var/lib/arvados/api_secret_token)
-    blob_signing_key=$(cat /var/lib/arvados/blob_signing_key)
-    management_token=$(cat /var/lib/arvados/management_token)
-    database_pw=$(cat /var/lib/arvados/api_database_pw)
-    vm_uuid=$(cat /var/lib/arvados/vm-uuid)
+    uuid_prefix=$(cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix)
+    secret_token=$(cat $ARVADOS_CONTAINER_PATH/api_secret_token)
+    blob_signing_key=$(cat $ARVADOS_CONTAINER_PATH/blob_signing_key)
+    management_token=$(cat $ARVADOS_CONTAINER_PATH/management_token)
+    database_pw=$(cat $ARVADOS_CONTAINER_PATH/api_database_pw)
+    vm_uuid=$(cat $ARVADOS_CONTAINER_PATH/vm-uuid)
 
-cat >config/application.yml <<EOF
+    cat >config/application.yml <<EOF
 $RAILS_ENV:
   uuid_prefix: $uuid_prefix
   secret_token: $secret_token
@@ -51,18 +51,18 @@ $RAILS_ENV:
   ManagementToken: $management_token
 EOF
 
-(cd config && /usr/local/lib/arvbox/yml_override.py application.yml)
-sed "s/password:.*/password: $database_pw/" <config/database.yml.example >config/database.yml
+    (cd config && /usr/local/lib/arvbox/yml_override.py application.yml)
+    sed "s/password:.*/password: $database_pw/" <config/database.yml.example >config/database.yml
 fi
 
-if ! test -f /var/lib/arvados/api_database_setup ; then
+if ! test -f $ARVADOS_CONTAINER_PATH/api_database_setup ; then
    bundle exec rake db:setup
-   touch /var/lib/arvados/api_database_setup
+   touch $ARVADOS_CONTAINER_PATH/api_database_setup
 fi
 
-if ! test -s /var/lib/arvados/superuser_token ; then
+if ! test -s $ARVADOS_CONTAINER_PATH/superuser_token ; then
     superuser_tok=$(bundle exec ./script/create_superuser_token.rb)
-    echo "$superuser_tok" > /var/lib/arvados/superuser_token
+    echo "$superuser_tok" > $ARVADOS_CONTAINER_PATH/superuser_token
 fi
 
 rm -rf tmp
index bebf983b6bf07dc1af6748b4583fd8d17b43e86c..948eb00a559acfbb8f7ffaf48f8a79cbc9c8bfab 100755 (executable)
@@ -6,7 +6,9 @@
 exec 2>&1
 set -ex -o pipefail
 
-if [[ -s /etc/arvados/config.yml ]] && [[ /var/lib/arvados/cluster_config.yml.override -ot /etc/arvados/config.yml ]] ; then
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
+
+if [[ -s /etc/arvados/config.yml ]] && [[ $ARVADOS_CONTAINER_PATH/cluster_config.yml.override -ot /etc/arvados/config.yml ]] ; then
    exit
 fi
 
@@ -14,58 +16,58 @@ fi
 
 set -u
 
-if ! test -s /var/lib/arvados/api_uuid_prefix ; then
-  ruby -e 'puts "x#{rand(2**64).to_s(36)[0,4]}"' > /var/lib/arvados/api_uuid_prefix
+if ! test -s $ARVADOS_CONTAINER_PATH/api_uuid_prefix ; then
+  ruby -e 'puts "x#{rand(2**64).to_s(36)[0,4]}"' > $ARVADOS_CONTAINER_PATH/api_uuid_prefix
 fi
-uuid_prefix=$(cat /var/lib/arvados/api_uuid_prefix)
+uuid_prefix=$(cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix)
 
-if ! test -s /var/lib/arvados/api_secret_token ; then
-    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/api_secret_token
+if ! test -s $ARVADOS_CONTAINER_PATH/api_secret_token ; then
+    ruby -e 'puts rand(2**400).to_s(36)' > $ARVADOS_CONTAINER_PATH/api_secret_token
 fi
-secret_token=$(cat /var/lib/arvados/api_secret_token)
+secret_token=$(cat $ARVADOS_CONTAINER_PATH/api_secret_token)
 
-if ! test -s /var/lib/arvados/blob_signing_key ; then
-    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/blob_signing_key
+if ! test -s $ARVADOS_CONTAINER_PATH/blob_signing_key ; then
+    ruby -e 'puts rand(2**400).to_s(36)' > $ARVADOS_CONTAINER_PATH/blob_signing_key
 fi
-blob_signing_key=$(cat /var/lib/arvados/blob_signing_key)
+blob_signing_key=$(cat $ARVADOS_CONTAINER_PATH/blob_signing_key)
 
-if ! test -s /var/lib/arvados/management_token ; then
-    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/management_token
+if ! test -s $ARVADOS_CONTAINER_PATH/management_token ; then
+    ruby -e 'puts rand(2**400).to_s(36)' > $ARVADOS_CONTAINER_PATH/management_token
 fi
-management_token=$(cat /var/lib/arvados/management_token)
+management_token=$(cat $ARVADOS_CONTAINER_PATH/management_token)
 
-if ! test -s /var/lib/arvados/system_root_token ; then
-    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/system_root_token
+if ! test -s $ARVADOS_CONTAINER_PATH/system_root_token ; then
+    ruby -e 'puts rand(2**400).to_s(36)' > $ARVADOS_CONTAINER_PATH/system_root_token
 fi
-system_root_token=$(cat /var/lib/arvados/system_root_token)
+system_root_token=$(cat $ARVADOS_CONTAINER_PATH/system_root_token)
 
-if ! test -s /var/lib/arvados/vm-uuid ; then
-    echo $uuid_prefix-2x53u-$(ruby -e 'puts rand(2**400).to_s(36)[0,15]') > /var/lib/arvados/vm-uuid
+if ! test -s $ARVADOS_CONTAINER_PATH/vm-uuid ; then
+    echo $uuid_prefix-2x53u-$(ruby -e 'puts rand(2**400).to_s(36)[0,15]') > $ARVADOS_CONTAINER_PATH/vm-uuid
 fi
-vm_uuid=$(cat /var/lib/arvados/vm-uuid)
+vm_uuid=$(cat $ARVADOS_CONTAINER_PATH/vm-uuid)
 
-if ! test -f /var/lib/arvados/api_database_pw ; then
-    ruby -e 'puts rand(2**128).to_s(36)' > /var/lib/arvados/api_database_pw
+if ! test -f $ARVADOS_CONTAINER_PATH/api_database_pw ; then
+    ruby -e 'puts rand(2**128).to_s(36)' > $ARVADOS_CONTAINER_PATH/api_database_pw
 fi
-database_pw=$(cat /var/lib/arvados/api_database_pw)
+database_pw=$(cat $ARVADOS_CONTAINER_PATH/api_database_pw)
 
 if ! (psql postgres -c "\du" | grep "^ arvados ") >/dev/null ; then
     psql postgres -c "create user arvados with password '$database_pw'"
 fi
 psql postgres -c "ALTER USER arvados WITH SUPERUSER;"
 
-if ! test -s /var/lib/arvados/workbench_secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/workbench_secret_token
+if ! test -s $ARVADOS_CONTAINER_PATH/workbench_secret_token ; then
+  ruby -e 'puts rand(2**400).to_s(36)' > $ARVADOS_CONTAINER_PATH/workbench_secret_token
 fi
-workbench_secret_key_base=$(cat /var/lib/arvados/workbench_secret_token)
+workbench_secret_key_base=$(cat $ARVADOS_CONTAINER_PATH/workbench_secret_token)
 
-if test -s /var/lib/arvados/api_rails_env ; then
-  database_env=$(cat /var/lib/arvados/api_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/api_rails_env ; then
+  database_env=$(cat $ARVADOS_CONTAINER_PATH/api_rails_env)
 else
   database_env=development
 fi
 
-cat >/var/lib/arvados/cluster_config.yml <<EOF
+cat >$ARVADOS_CONTAINER_PATH/cluster_config.yml <<EOF
 Clusters:
   ${uuid_prefix}:
     SystemRootToken: $system_root_token
@@ -143,41 +145,44 @@ Clusters:
       ArvadosDocsite: http://$localip:${services[doc]}/
     Git:
       GitCommand: /usr/share/gitolite3/gitolite-shell
-      GitoliteHome: /var/lib/arvados/git
-      Repositories: /var/lib/arvados/git/repositories
+      GitoliteHome: $ARVADOS_CONTAINER_PATH/git
+      Repositories: $ARVADOS_CONTAINER_PATH/git/repositories
     Volumes:
       ${uuid_prefix}-nyw5e-000000000000000:
         Driver: Directory
         DriverParameters:
-          Root: /var/lib/arvados/keep0
+          Root: $ARVADOS_CONTAINER_PATH/keep0
         AccessViaHosts:
           "http://localhost:${services[keepstore0]}": {}
       ${uuid_prefix}-nyw5e-111111111111111:
         Driver: Directory
         DriverParameters:
-          Root: /var/lib/arvados/keep1
+          Root: $ARVADOS_CONTAINER_PATH/keep1
         AccessViaHosts:
           "http://localhost:${services[keepstore1]}": {}
 EOF
 
-/usr/local/lib/arvbox/yml_override.py /var/lib/arvados/cluster_config.yml
+/usr/local/lib/arvbox/yml_override.py $ARVADOS_CONTAINER_PATH/cluster_config.yml
 
-cp /var/lib/arvados/cluster_config.yml /etc/arvados/config.yml
+cp $ARVADOS_CONTAINER_PATH/cluster_config.yml /etc/arvados/config.yml
 
+# Do not abort if certain optional files don't exist (e.g. cluster_config.yml.override)
+set +e
 chmod og-rw \
-      /var/lib/arvados/cluster_config.yml.override \
-      /var/lib/arvados/cluster_config.yml \
+      $ARVADOS_CONTAINER_PATH/cluster_config.yml.override \
+      $ARVADOS_CONTAINER_PATH/cluster_config.yml \
       /etc/arvados/config.yml \
-      /var/lib/arvados/api_secret_token \
-      /var/lib/arvados/blob_signing_key \
-      /var/lib/arvados/management_token \
-      /var/lib/arvados/system_root_token \
-      /var/lib/arvados/api_database_pw \
-      /var/lib/arvados/workbench_secret_token \
-      /var/lib/arvados/superuser_token \
-
-mkdir -p /var/lib/arvados/run_tests
-cat >/var/lib/arvados/run_tests/config.yml <<EOF
+      $ARVADOS_CONTAINER_PATH/api_secret_token \
+      $ARVADOS_CONTAINER_PATH/blob_signing_key \
+      $ARVADOS_CONTAINER_PATH/management_token \
+      $ARVADOS_CONTAINER_PATH/system_root_token \
+      $ARVADOS_CONTAINER_PATH/api_database_pw \
+      $ARVADOS_CONTAINER_PATH/workbench_secret_token \
+      $ARVADOS_CONTAINER_PATH/superuser_token \
+set -e
+
+mkdir -p $ARVADOS_CONTAINER_PATH/run_tests
+cat >$ARVADOS_CONTAINER_PATH/run_tests/config.yml <<EOF
 Clusters:
   zzzzz:
     PostgreSQL:
index 185467cf7de8d7d5b599f714bb4771090e05abb0..48d3566405f982e210bc2af673a6f6df6fea962b 100644 (file)
@@ -3,12 +3,13 @@
 # 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_HOME=/var/lib/arvados/lib/ruby/gems/2.5.0
+export PATH=${PATH}:/usr/local/go/bin:$GEM_HOME/bin:/var/lib/arvados/bin
 export npm_config_cache=/var/lib/npm
 export npm_config_cache_min=Infinity
 export R_LIBS=/var/lib/Rlibs
 export HOME=$(getent passwd arvbox | cut -d: -f6)
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
 
 defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
 dockerip=$(/sbin/ip route | grep default | awk '{ print $3 }')
@@ -19,10 +20,10 @@ else
     localip=$containerip
 fi
 
-root_cert=/var/lib/arvados/root-cert.pem
-root_cert_key=/var/lib/arvados/root-cert.key
-server_cert=/var/lib/arvados/server-cert-${localip}.pem
-server_cert_key=/var/lib/arvados/server-cert-${localip}.key
+root_cert=$ARVADOS_CONTAINER_PATH/root-cert.pem
+root_cert_key=$ARVADOS_CONTAINER_PATH/root-cert.key
+server_cert=$ARVADOS_CONTAINER_PATH/server-cert-${localip}.pem
+server_cert_key=$ARVADOS_CONTAINER_PATH/server-cert-${localip}.key
 
 declare -A services
 services=(
@@ -62,22 +63,24 @@ run_bundler() {
         # 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 ' ')"
+        flock $GEM_HOME/gems.lock gem install bundler --no-document -v "$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1|tr -d ' ')"
         frozen=--frozen
     else
         frozen=""
     fi
-    # if ! test -x /var/lib/gems/bin/bundler ; then
+    # if ! test -x $GEM_HOME/bin/bundler ; then
     #  bundleversion=2.0.2
     #     bundlergem=$(ls -r $GEM_HOME/cache/bundler-${bundleversion}.gem 2>/dev/null | head -n1 || true)
     #     if test -n "$bundlergem" ; then
-    #         flock /var/lib/gems/gems.lock gem install --verbose --local --no-document $bundlergem
+    #         flock $GEM_HOME/gems.lock gem install --verbose --local --no-document $bundlergem
     #     else
-    #         flock /var/lib/gems/gems.lock gem install --verbose --no-document bundler --version ${bundleversion}
+    #         flock $GEM_HOME/gems.lock gem install --verbose --no-document bundler --version ${bundleversion}
     #     fi
     # fi
-    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 "$@"
+    # Make sure to put the gem binaries in the right place
+    flock /var/lib/arvados/lib/ruby/gems/2.5.0/gems.lock bundler config bin $GEM_HOME/bin
+    if ! flock $GEM_HOME/gems.lock bundler install --verbose --local --no-deployment $frozen "$@" ; then
+        flock $GEM_HOME/gems.lock bundler install --verbose --no-deployment $frozen "$@"
     fi
 }
 
index de1e7bba9606696d41fbc309f706a9a944888d49..7cf58e201d1e27ca2492d9ace8d9d241d1c4dc41 100755 (executable)
@@ -5,16 +5,19 @@
 
 set -e -o pipefail
 
+export GEM_HOME=/var/lib/arvados/lib/ruby/gems/2.5.0
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
+
 if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
     HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
 
-    mkdir -p /var/lib/arvados/git /var/lib/gems \
+    mkdir -p $ARVADOS_CONTAINER_PATH/git $GEM_HOME \
           /var/lib/passenger /var/lib/gopath \
           /var/lib/pip /var/lib/npm
 
     if test -z "$ARVBOX_HOME" ; then
-       ARVBOX_HOME=/var/lib/arvados
+        ARVBOX_HOME=$ARVADOS_CONTAINER_PATH
     fi
 
     groupadd --gid $HOSTGID --non-unique arvbox
@@ -25,27 +28,25 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
             --groups docker \
             --shell /bin/bash \
             arvbox
-    useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
+    useradd --home-dir $ARVADOS_CONTAINER_PATH/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker crunch
 
     if [[ "$1" != --no-chown ]] ; then
-       chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems \
+        chown arvbox:arvbox -R /usr/local $ARVADOS_CONTAINER_PATH $GEM_HOME \
               /var/lib/passenger /var/lib/postgresql \
               /var/lib/nginx /var/log/nginx /etc/ssl/private \
-              /var/lib/gopath /var/lib/pip /var/lib/npm
+              /var/lib/gopath /var/lib/pip /var/lib/npm \
+              /var/lib/arvados
     fi
 
-    mkdir -p /var/lib/gems/ruby
-    chown arvbox:arvbox -R /var/lib/gems/ruby
-
     mkdir -p /tmp/crunch0 /tmp/crunch1
     chown crunch:crunch -R /tmp/crunch0 /tmp/crunch1
 
     echo "arvbox    ALL=(crunch) NOPASSWD: ALL" >> /etc/sudoers
 
     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 PATH=/var/lib/arvados/bin:/usr/local/bin:/usr/bin:/bin
+export GEM_HOME=/var/lib/arvados/lib/ruby/gems/2.5.0
 export npm_config_cache=/var/lib/npm
 export npm_config_cache_min=Infinity
 export R_LIBS=/var/lib/Rlibs
index 4df5463f1f06101b5dd82ac61281df805fa15721..b5c57f39fc959cba2cc2a72c3b8a313ea95cbf20 100755 (executable)
@@ -3,7 +3,8 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh --no-chown
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
+flock $ARVADOS_CONTAINER_PATH/createusers.lock /usr/local/lib/arvbox/createusers.sh --no-chown
 
 if [[ -n "$*" ]] ; then
     exec su --preserve-environment arvbox -c "$*"
index 9bee9104482525c5f2f7856dd9c39735915ab5d4..21be0ccd6fc93649e587596913f2bf35388d508a 100644 (file)
@@ -8,10 +8,14 @@ mkdir -p $GOPATH
 
 cd /usr/src/arvados
 if [[ $UID = 0 ]] ; then
-    /usr/local/lib/arvbox/runsu.sh flock /var/lib/gopath/gopath.lock go mod download
+  /usr/local/lib/arvbox/runsu.sh flock /var/lib/gopath/gopath.lock go mod download
+  if [[ ! -f /usr/local/bin/arvados-server ]]; then
     /usr/local/lib/arvbox/runsu.sh flock /var/lib/gopath/gopath.lock go install git.arvados.org/arvados.git/cmd/arvados-server
+  fi
 else
-    flock /var/lib/gopath/gopath.lock go mod download
+  flock /var/lib/gopath/gopath.lock go mod download
+  if [[ ! -f /usr/local/bin/arvados-server ]]; then
     flock /var/lib/gopath/gopath.lock go install git.arvados.org/arvados.git/cmd/arvados-server
+  fi
 fi
 install $GOPATH/bin/arvados-server /usr/local/bin
index 3bc3899b0b8e7c070f6d71f23dd604ade36950ef..657a9a2600abd5f2ec4f6e6e06d184f00e517c1d 100755 (executable)
@@ -17,11 +17,11 @@ if test "$1" = "--only-deps" ; then
     exit
 fi
 
-mkdir -p /var/lib/arvados/$1
+mkdir -p $ARVADOS_CONTAINER_PATH/$1
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
 
 set +e
 read -rd $'\000' keepservice <<EOF
@@ -34,25 +34,25 @@ read -rd $'\000' keepservice <<EOF
 EOF
 set -e
 
-if test -s /var/lib/arvados/$1-uuid ; then
-    keep_uuid=$(cat /var/lib/arvados/$1-uuid)
+if test -s $ARVADOS_CONTAINER_PATH/$1-uuid ; then
+    keep_uuid=$(cat $ARVADOS_CONTAINER_PATH/$1-uuid)
     arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
 else
     UUID=$(arv --format=uuid keep_service create --keep-service "$keepservice")
-    echo $UUID > /var/lib/arvados/$1-uuid
+    echo $UUID > $ARVADOS_CONTAINER_PATH/$1-uuid
 fi
 
-management_token=$(cat /var/lib/arvados/management_token)
+management_token=$(cat $ARVADOS_CONTAINER_PATH/management_token)
 
 set +e
 sv hup /var/lib/arvbox/service/keepproxy
 
-cat >/var/lib/arvados/$1.yml <<EOF
+cat >$ARVADOS_CONTAINER_PATH/$1.yml <<EOF
 Listen: "localhost:$2"
-BlobSigningKeyFile: /var/lib/arvados/blob_signing_key
-SystemAuthTokenFile: /var/lib/arvados/superuser_token
+BlobSigningKeyFile: $ARVADOS_CONTAINER_PATH/blob_signing_key
+SystemAuthTokenFile: $ARVADOS_CONTAINER_PATH/superuser_token
 ManagementToken: $management_token
 MaxBuffers: 20
 EOF
 
-exec /usr/local/bin/keepstore -config=/var/lib/arvados/$1.yml
+exec /usr/local/bin/keepstore -config=$ARVADOS_CONTAINER_PATH/$1.yml
index 5812f3d8b0cea307b793016156b8fa73b3909224..eccf62553eaac49e61285a16113cd78492f6ebf3 100755 (executable)
@@ -3,7 +3,7 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-PATH=/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin
+PATH=/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin
 
 echo
 echo "Arvados-in-a-box starting"
index 88d832f0e837351ab79b5571163bd14a900e2429..674b15775564c5a4fcedffd01c50b8a9aa57b4b5 100755 (executable)
@@ -6,9 +6,11 @@
 HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
 HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
 
-flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
 
-export HOME=/var/lib/arvados
+flock $ARVADOS_CONTAINER_PATH/createusers.lock /usr/local/lib/arvbox/createusers.sh
+
+export HOME=$ARVADOS_CONTAINER_PATH
 
 chown arvbox /dev/stderr
 
index f052b5d636cf6095ce12b004d40ec87d4fd2812c..7df7b2820bf6a0b83bcb538ecb418e183e68afa8 100755 (executable)
@@ -10,8 +10,8 @@ set -ex -o pipefail
 
 cd /usr/src/arvados/services/api
 
-if test -s /var/lib/arvados/api_rails_env ; then
-  export RAILS_ENV=$(cat /var/lib/arvados/api_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/api_rails_env ; then
+  export RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/api_rails_env)
 else
   export RAILS_ENV=development
 fi
@@ -24,7 +24,7 @@ if test "$1" = "--only-deps" ; then
     exit
 fi
 
-flock /var/lib/arvados/api.lock /usr/local/lib/arvbox/api-setup.sh
+flock $ARVADOS_CONTAINER_PATH/api.lock /usr/local/lib/arvbox/api-setup.sh
 
 set +u
 if test "$1" = "--only-setup" ; then
index 5f71e5ab28a5d70a3e7ab5fa642f6b18d9c38a45..b369ff6228d0a90d9c1ef64968dde2b89d1ee7ff 100755 (executable)
@@ -18,7 +18,7 @@ fi
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export PATH="$PATH:/var/lib/arvados/git/bin"
+export PATH="$PATH:$ARVADOS_CONTAINER_PATH/git/bin"
 cd ~git
 
 exec /usr/local/bin/arv-git-httpd
index 6443b01793dd61aaa56e717aff71ec839a26c2c3..2536981a7aacd42dfca48694feb4155dc99f52b6 100755 (executable)
@@ -8,9 +8,9 @@ set -ex -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
-/usr/local/lib/arvbox/runsu.sh flock /var/lib/arvados/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
+/usr/local/lib/arvbox/runsu.sh flock $ARVADOS_CONTAINER_PATH/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
 
-uuid_prefix=$(cat /var/lib/arvados/api_uuid_prefix)
+uuid_prefix=$(cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix)
 
 if ! openssl verify -CAfile $root_cert $root_cert ; then
     # req           signing request sub-command
@@ -74,13 +74,13 @@ if ! openssl verify -CAfile $root_cert $server_cert ; then
            -extensions x509_ext \
            -config <(cat /etc/ssl/openssl.cnf \
                          <(printf "\n[x509_ext]\nkeyUsage=critical,digitalSignature,keyEncipherment\nsubjectAltName=DNS:localhost,$san")) \
-            -out /var/lib/arvados/server-cert-${localip}.csr \
+            -out $ARVADOS_CONTAINER_PATH/server-cert-${localip}.csr \
             -keyout $server_cert_key \
             -days 365
 
     openssl x509 \
            -req \
-           -in /var/lib/arvados/server-cert-${localip}.csr \
+           -in $ARVADOS_CONTAINER_PATH/server-cert-${localip}.csr \
            -CA $root_cert \
            -CAkey $root_cert_key \
            -out $server_cert \
index 588e9d2dad216faffa9e96686977507b3bfe2eb8..e495e222e171cd784e581bb42e5af37bb22b842f 100755 (executable)
@@ -15,6 +15,6 @@ if test "$1" = "--only-deps" ; then
     exit
 fi
 
-/usr/local/lib/arvbox/runsu.sh flock /var/lib/arvados/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
+/usr/local/lib/arvbox/runsu.sh flock $ARVADOS_CONTAINER_PATH/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
 
 exec /usr/local/bin/arvados-controller
index 6e80d30ab9570fb8a26fcaeb8eee1c1f8e2ff8a0..821afdce50b1fac246071dabc7e5fd507b201c84 100755 (executable)
@@ -25,6 +25,6 @@ chmod +x /usr/local/bin/crunch-run.sh
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
 
 exec /usr/local/bin/crunch-dispatch-local -crunch-run-command=/usr/local/bin/crunch-run.sh -poll-interval=1
index 6055efc4791e93978ac806f2f3111d7e15c758bb..e91386b6772a6e29184d53222c31c399e142f418 100755 (executable)
@@ -8,16 +8,16 @@ set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
-mkdir -p /var/lib/arvados/git
+mkdir -p $ARVADOS_CONTAINER_PATH/git
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
 
 export USER=git
 export USERNAME=git
 export LOGNAME=git
-export HOME=/var/lib/arvados/git
+export HOME=$ARVADOS_CONTAINER_PATH/git
 
 cd ~arvbox
 
@@ -33,7 +33,7 @@ if test -s ~arvbox/.ssh/known_hosts ; then
     ssh-keygen -f ".ssh/known_hosts" -R localhost
 fi
 
-if ! test -f /var/lib/arvados/gitolite-setup ; then
+if ! test -f $ARVADOS_CONTAINER_PATH/gitolite-setup ; then
     cd ~git
 
     # Do a no-op login to populate known_hosts
@@ -57,7 +57,7 @@ if ! test -f /var/lib/arvados/gitolite-setup ; then
     git config push.default simple
     git push
 
-    touch /var/lib/arvados/gitolite-setup
+    touch $ARVADOS_CONTAINER_PATH/gitolite-setup
 else
     # Do a no-op login to populate known_hosts
     # with the hostkey, so it won't try to ask
@@ -68,14 +68,14 @@ fi
 
 prefix=$(arv --format=uuid user current | cut -d- -f1)
 
-if ! test -s /var/lib/arvados/arvados-git-uuid ; then
+if ! test -s $ARVADOS_CONTAINER_PATH/arvados-git-uuid ; then
     repo_uuid=$(arv --format=uuid repository create --repository "{\"owner_uuid\":\"$prefix-tpzed-000000000000000\", \"name\":\"arvados\"}")
-    echo $repo_uuid > /var/lib/arvados/arvados-git-uuid
+    echo $repo_uuid > $ARVADOS_CONTAINER_PATH/arvados-git-uuid
 fi
 
-repo_uuid=$(cat /var/lib/arvados/arvados-git-uuid)
+repo_uuid=$(cat $ARVADOS_CONTAINER_PATH/arvados-git-uuid)
 
-if ! test -s /var/lib/arvados/arvados-git-link-uuid ; then
+if ! test -s $ARVADOS_CONTAINER_PATH/arvados-git-link-uuid ; then
     all_users_group_uuid="$prefix-j7d0g-fffffffffffffff"
 
     set +e
@@ -89,19 +89,19 @@ if ! test -s /var/lib/arvados/arvados-git-link-uuid ; then
 EOF
     set -e
     link_uuid=$(arv --format=uuid link create --link "$newlink")
-    echo $link_uuid > /var/lib/arvados/arvados-git-link-uuid
+    echo $link_uuid > $ARVADOS_CONTAINER_PATH/arvados-git-link-uuid
 fi
 
-if ! test -d /var/lib/arvados/git/repositories/$repo_uuid.git ; then
-    git clone --bare /usr/src/arvados /var/lib/arvados/git/repositories/$repo_uuid.git
+if ! test -d $ARVADOS_CONTAINER_PATH/git/repositories/$repo_uuid.git ; then
+    git clone --bare /usr/src/arvados $ARVADOS_CONTAINER_PATH/git/repositories/$repo_uuid.git
 else
-    git --git-dir=/var/lib/arvados/git/repositories/$repo_uuid.git fetch -f /usr/src/arvados master:master
+    git --git-dir=$ARVADOS_CONTAINER_PATH/git/repositories/$repo_uuid.git fetch -f /usr/src/arvados master:master
 fi
 
 cd /usr/src/arvados/services/api
 
-if test -s /var/lib/arvados/api_rails_env ; then
-  RAILS_ENV=$(cat /var/lib/arvados/api_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/api_rails_env ; then
+  RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/api_rails_env)
 else
   RAILS_ENV=development
 fi
@@ -110,8 +110,8 @@ git_user_key=$(cat ~git/.ssh/id_rsa.pub)
 
 cat > config/arvados-clients.yml <<EOF
 $RAILS_ENV:
-  gitolite_url: /var/lib/arvados/git/repositories/gitolite-admin.git
-  gitolite_tmp: /var/lib/arvados/git
+  gitolite_url: $ARVADOS_CONTAINER_PATH/git/repositories/gitolite-admin.git
+  gitolite_tmp: $ARVADOS_CONTAINER_PATH/git
   arvados_api_host: $localip:${services[controller-ssl]}
   arvados_api_token: "$ARVADOS_API_TOKEN"
   arvados_api_host_insecure: false
index d093fbc885ad84fb33e626ff1a7f6ae2ca2dcd32..cf5ccd724b885ee84233b03e0259ef9c5906e8cc 100755 (executable)
@@ -19,7 +19,7 @@ fi
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
 
 set +e
 read -rd $'\000' keepservice <<EOF
@@ -32,12 +32,12 @@ read -rd $'\000' keepservice <<EOF
 EOF
 set -e
 
-if test -s /var/lib/arvados/keepproxy-uuid ; then
-    keep_uuid=$(cat /var/lib/arvados/keepproxy-uuid)
+if test -s $ARVADOS_CONTAINER_PATH/keepproxy-uuid ; then
+    keep_uuid=$(cat $ARVADOS_CONTAINER_PATH/keepproxy-uuid)
     arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
 else
     UUID=$(arv --format=uuid keep_service create --keep-service "$keepservice")
-    echo $UUID > /var/lib/arvados/keepproxy-uuid
+    echo $UUID > $ARVADOS_CONTAINER_PATH/keepproxy-uuid
 fi
 
 exec /usr/local/bin/keepproxy
index cfb7788defc080986bb91fa0e5f1e9b871b27c5f..82db92137053f83f0282f24211e63824a7bb4a0c 100755 (executable)
@@ -21,9 +21,9 @@ fi
 
 openssl verify -CAfile $root_cert $server_cert
 
-cat <<EOF >/var/lib/arvados/nginx.conf
+cat <<EOF >$ARVADOS_CONTAINER_PATH/nginx.conf
 worker_processes auto;
-pid /var/lib/arvados/nginx.pid;
+pid $ARVADOS_CONTAINER_PATH/nginx.pid;
 
 error_log stderr;
 daemon off;
@@ -235,4 +235,4 @@ server {
 
 EOF
 
-exec nginx -c /var/lib/arvados/nginx.conf
+exec nginx -c $ARVADOS_CONTAINER_PATH/nginx.conf
index 3ef78ee45575676dc881059efd60cc57bd64cbd9..d8abc4d89d8b2037bdd240d0e3577b77e232bfc1 100755 (executable)
@@ -3,7 +3,8 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
+export ARVADOS_CONTAINER_PATH=/var/lib/arvados-arvbox
+flock $ARVADOS_CONTAINER_PATH/createusers.lock /usr/local/lib/arvbox/createusers.sh
 
 make-ssl-cert generate-default-snakeoil --force-overwrite
 
index f2377a0c2dd7a544cb0a5cf87318bada12b045e1..3569fd31264b2dfd849d653dcda065faa8bbf644 100755 (executable)
@@ -10,7 +10,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
-    sh -c "while ! (psql postgres -c'\du' | grep '^ arvbox ') >/dev/null ; do createuser -s arvbox ; sleep 1 ; done" &
 fi
 mkdir -p /var/run/postgresql/$PGVERSION-main.pg_stat_tmp
 
index 21cb7d48c64060d0edf08ca135e8d7f4fa92fd4e..b29dafed70b7696aeaee8657e4f4206c8a7b3d79 100755 (executable)
@@ -49,9 +49,9 @@ export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
 
 vm_ok=0
-if test -s /var/lib/arvados/vm-uuid -a -s /var/lib/arvados/superuser_token; then
-    vm_uuid=$(cat /var/lib/arvados/vm-uuid)
-    export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+if test -s $ARVADOS_CONTAINER_PATH/vm-uuid -a -s $ARVADOS_CONTAINER_PATH/superuser_token; then
+    vm_uuid=$(cat $ARVADOS_CONTAINER_PATH/vm-uuid)
+    export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
     if (which arv && arv virtual_machine get --uuid $vm_uuid) >/dev/null 2>/dev/null ; then
         vm_ok=1
     fi
@@ -63,7 +63,7 @@ fi
 
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
-        gemcount=$(ls /var/lib/gems/ruby/2.1.0/gems 2>/dev/null | wc -l)
+        gemcount=$(ls $GEM_HOME/gems 2>/dev/null | wc -l)
 
         gemlockcount=0
         for l in /usr/src/arvados/services/api/Gemfile.lock \
index ee210e35d8600d8cf90a01acf91f7624cb23c47c..4ea11aadcd85808dec396a87dfd575aacb07af56 100755 (executable)
@@ -16,8 +16,8 @@ cd /usr/src/arvados/services/login-sync
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-export ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
+export ARVADOS_VIRTUAL_MACHINE_UUID=$(cat $ARVADOS_CONTAINER_PATH/vm-uuid)
 
 while true ; do
       arvados-login-sync
index 932ba59818ba2fb604d4b11e744ffba37b622f78..5369af31d0c086cd986e2b9de877b5e196439d28 100755 (executable)
@@ -21,8 +21,8 @@ set -u
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-export ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
+export ARVADOS_VIRTUAL_MACHINE_UUID=$(cat $ARVADOS_CONTAINER_PATH/vm-uuid)
 
 set +e
 read -rd $'\000' vm <<EOF
index efa2e08a7a7f34c3a04ee4c213931ed37a4f65ab..f962c3e8f0004db016cec28240f7b5eb7285ed82 100755 (executable)
@@ -15,6 +15,6 @@ if test "$1" = "--only-deps" ; then
     exit
 fi
 
-/usr/local/lib/arvbox/runsu.sh flock /var/lib/arvados/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
+/usr/local/lib/arvbox/runsu.sh flock $ARVADOS_CONTAINER_PATH/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
 
 exec /usr/local/lib/arvbox/runsu.sh /usr/local/bin/arvados-ws
index e163493781f1a16531dc7bb355137aed941843fa..b8a28fa762379d6735b1185e60296cb463c73b35 100755 (executable)
@@ -15,8 +15,8 @@ rm -rf tmp
 mkdir tmp
 chown arvbox:arvbox tmp
 
-if test -s /var/lib/arvados/workbench_rails_env ; then
-  export RAILS_ENV=$(cat /var/lib/arvados/workbench_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/workbench_rails_env ; then
+  export RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/workbench_rails_env)
 else
   export RAILS_ENV=development
 fi
@@ -24,7 +24,7 @@ fi
 if test "$1" != "--only-deps" ; then
     openssl verify -CAfile $root_cert $server_cert
     exec bundle exec passenger start --port=${services[workbench]} \
-        --ssl --ssl-certificate=/var/lib/arvados/server-cert-${localip}.pem \
-        --ssl-certificate-key=/var/lib/arvados/server-cert-${localip}.key \
+        --ssl --ssl-certificate=$ARVADOS_CONTAINER_PATH/server-cert-${localip}.pem \
+        --ssl-certificate-key=$ARVADOS_CONTAINER_PATH/server-cert-${localip}.key \
          --user arvbox
 fi
index 06742cf82e204649336ff3d21ce676d0bb7a2dd4..51b9420eebf542ecf0596e6dea6b1801a4966a11 100755 (executable)
@@ -10,8 +10,8 @@ set -ex -o pipefail
 
 cd /usr/src/arvados/apps/workbench
 
-if test -s /var/lib/arvados/workbench_rails_env ; then
-  export RAILS_ENV=$(cat /var/lib/arvados/workbench_rails_env)
+if test -s $ARVADOS_CONTAINER_PATH/workbench_rails_env ; then
+  export RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/workbench_rails_env)
 else
   export RAILS_ENV=development
 fi
@@ -35,7 +35,7 @@ fi
 
 set -u
 
-secret_token=$(cat /var/lib/arvados/workbench_secret_token)
+secret_token=$(cat $ARVADOS_CONTAINER_PATH/workbench_secret_token)
 
 if test -a /usr/src/arvados/apps/workbench/config/arvados_config.rb ; then
     rm -f config/application.yml
index e3fbd22c4575c0e5b69ac8debceef81d8b2ee19b..8c3c49efd65dced676317333f0fa755280d9bde2 100755 (executable)
@@ -27,7 +27,7 @@ cat <<EOF > /usr/src/workbench2/public/config.json
 EOF
 
 export ARVADOS_API_HOST=$localip:${services[controller-ssl]}
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_API_TOKEN=$(cat $ARVADOS_CONTAINER_PATH/superuser_token)
 
 url_prefix="https://$localip:${services[workbench2-ssl]}/"
 
index 6bda618ab899e2a8ca1a429bf319f82263995c49..9b2eb69f9e97d53c3de952ac14b65f6fbf72ae08 100755 (executable)
@@ -9,6 +9,6 @@ while ! psql postgres -c\\du >/dev/null 2>/dev/null ; do
     sleep 1
 done
 
-while ! test -s /var/lib/arvados/server-cert-${localip}.pem ; do
+while ! test -s $ARVADOS_CONTAINER_PATH/server-cert-${localip}.pem ; do
     sleep 1
 done