15397: Merge branch 'main'
authorTom Clegg <tom@curii.com>
Fri, 3 May 2024 14:53:32 +0000 (10:53 -0400)
committerTom Clegg <tom@curii.com>
Fri, 3 May 2024 14:53:32 +0000 (10:53 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

269 files changed:
build/rails-package-scripts/README.md
build/rails-package-scripts/arvados-api-server.sh
build/rails-package-scripts/postinst.sh
build/rails-package-scripts/step2.sh
build/run-build-packages-one-target.sh
build/run-build-packages.sh
build/run-tests.sh
cmd/arvados-client/cmd.go
cmd/arvados-server/arvados-git-httpd.service [deleted file]
cmd/arvados-server/cmd.go
doc/_config.yml
doc/_includes/_mount_types.liquid
doc/_includes/_ssh_intro.liquid
doc/_includes/_tutorial_git_repo_expectations.liquid [deleted file]
doc/admin/config-urls.html.textile.liquid
doc/admin/inspect.html.textile.liquid
doc/admin/management-token.html.textile.liquid
doc/admin/metrics.html.textile.liquid
doc/admin/upgrading.html.textile.liquid
doc/admin/user-management-cli.html.textile.liquid
doc/admin/user-management.html.textile.liquid
doc/api/crunch-scripts.html.textile.liquid [deleted file]
doc/api/methods/humans.html.textile.liquid [deleted file]
doc/api/methods/job_tasks.html.textile.liquid [deleted file]
doc/api/methods/jobs.html.textile.liquid [deleted file]
doc/api/methods/keep_disks.html.textile.liquid [deleted file]
doc/api/methods/nodes.html.textile.liquid [deleted file]
doc/api/methods/pipeline_instances.html.textile.liquid [deleted file]
doc/api/methods/pipeline_templates.html.textile.liquid [deleted file]
doc/api/methods/repositories.html.textile.liquid [deleted file]
doc/api/methods/specimens.html.textile.liquid [deleted file]
doc/api/methods/traits.html.textile.liquid [deleted file]
doc/architecture/index.html.textile.liquid
doc/images/add-new-repository.png [deleted file]
doc/install/arvbox.html.textile.liquid
doc/install/install-arv-git-httpd.html.textile.liquid [deleted file]
doc/install/install-composer.html.textile.liquid [deleted file]
doc/install/install-jobs-image.html.textile.liquid [deleted file]
doc/install/install-manual-prerequisites.html.textile.liquid
doc/install/install-shell-server.html.textile.liquid
doc/sdk/cli/index.html.textile.liquid
doc/user/tutorials/add-new-repository.html.textile.liquid [deleted file]
doc/user/tutorials/git-arvados-guide.html.textile.liquid [deleted file]
lib/boot/nginx.go
lib/boot/supervisor.go
lib/config/config.default.yml
lib/config/deprecated.go
lib/config/deprecated_test.go
lib/config/export.go
lib/config/load.go
lib/controller/federation/conn.go
lib/controller/federation/generate.go
lib/controller/federation/generated.go
lib/controller/handler_test.go
lib/controller/integration_test.go
lib/controller/router/response.go
lib/controller/router/router.go
lib/controller/rpc/conn.go
lib/controller/rpc/conn_test.go
lib/crunchrun/crunchrun.go
lib/crunchrun/crunchrun_test.go
lib/crunchrun/git_mount.go [deleted file]
lib/crunchrun/git_mount_test.go [deleted file]
lib/crunchrun/logging_test.go
lib/install/deps.go
lib/install/init.go
lib/service/cmd.go
sdk/go/arvados/api.go
sdk/go/arvados/config.go
sdk/go/arvados/container.go
sdk/go/arvados/specimen.go [deleted file]
sdk/go/arvadosclient/pool.go
sdk/go/arvadostest/api.go
sdk/go/arvadostest/fixtures.go
sdk/go/health/aggregator_test.go
sdk/python/arvados-v1-discovery.json
sdk/python/arvados/commands/arv_copy.py
sdk/python/tests/nginx.conf
sdk/python/tests/run_test_server.py
sdk/python/tests/test_api.py
sdk/python/tests/test_events.py
sdk/python/tests/test_retry_job_helpers.py
services/api/app/assets/stylesheets/api_client_authorizations.css.scss [deleted file]
services/api/app/assets/stylesheets/api_clients.css.scss [deleted file]
services/api/app/assets/stylesheets/authorized_keys.css.scss [deleted file]
services/api/app/assets/stylesheets/collections.css.scss [deleted file]
services/api/app/assets/stylesheets/commit_ancestors.css.scss [deleted file]
services/api/app/assets/stylesheets/commits.css.scss [deleted file]
services/api/app/assets/stylesheets/groups.css.scss [deleted file]
services/api/app/assets/stylesheets/humans.css.scss [deleted file]
services/api/app/assets/stylesheets/job_tasks.css.scss [deleted file]
services/api/app/assets/stylesheets/jobs.css.scss [deleted file]
services/api/app/assets/stylesheets/keep_disks.css.scss [deleted file]
services/api/app/assets/stylesheets/links.css.scss [deleted file]
services/api/app/assets/stylesheets/logs.css.scss [deleted file]
services/api/app/assets/stylesheets/nodes.css [deleted file]
services/api/app/assets/stylesheets/nodes.css.scss [deleted file]
services/api/app/assets/stylesheets/pipeline_instances.css.scss [deleted file]
services/api/app/assets/stylesheets/pipeline_templates.css.scss [deleted file]
services/api/app/assets/stylesheets/repositories.css.scss [deleted file]
services/api/app/assets/stylesheets/specimens.css.scss [deleted file]
services/api/app/assets/stylesheets/traits.css.scss [deleted file]
services/api/app/assets/stylesheets/virtual_machines.css.scss [deleted file]
services/api/app/controllers/arvados/v1/collections_controller.rb
services/api/app/controllers/arvados/v1/groups_controller.rb
services/api/app/controllers/arvados/v1/humans_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/job_tasks_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/jobs_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/keep_disks_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/nodes_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/pipeline_instances_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/pipeline_templates_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/repositories_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/schema_controller.rb
services/api/app/controllers/arvados/v1/specimens_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/traits_controller.rb [deleted file]
services/api/app/controllers/arvados/v1/users_controller.rb
services/api/app/helpers/api_client_authorizations_helper.rb [deleted file]
services/api/app/helpers/api_clients_helper.rb [deleted file]
services/api/app/helpers/authorized_keys_helper.rb [deleted file]
services/api/app/helpers/collections_helper.rb [deleted file]
services/api/app/helpers/commits_helper.rb [deleted file]
services/api/app/helpers/groups_helper.rb [deleted file]
services/api/app/helpers/humans_helper.rb [deleted file]
services/api/app/helpers/job_tasks_helper.rb [deleted file]
services/api/app/helpers/jobs_helper.rb [deleted file]
services/api/app/helpers/keep_disks_helper.rb [deleted file]
services/api/app/helpers/links_helper.rb [deleted file]
services/api/app/helpers/logs_helper.rb [deleted file]
services/api/app/helpers/nodes_helper.rb [deleted file]
services/api/app/helpers/pipeline_instances_helper.rb [deleted file]
services/api/app/helpers/pipeline_templates_helper.rb [deleted file]
services/api/app/helpers/repositories_helper.rb [deleted file]
services/api/app/helpers/specimens_helper.rb [deleted file]
services/api/app/helpers/traits_helper.rb [deleted file]
services/api/app/helpers/virtual_machines_helper.rb [deleted file]
services/api/app/models/human.rb [deleted file]
services/api/app/models/job.rb [deleted file]
services/api/app/models/job_task.rb [deleted file]
services/api/app/models/keep_disk.rb [deleted file]
services/api/app/models/node.rb [deleted file]
services/api/app/models/pipeline_instance.rb [deleted file]
services/api/app/models/pipeline_template.rb [deleted file]
services/api/app/models/repository.rb [deleted file]
services/api/app/models/specimen.rb [deleted file]
services/api/app/models/trait.rb [deleted file]
services/api/app/models/user.rb
services/api/config/arvados_config.rb
services/api/config/routes.rb
services/api/lib/can_be_an_owner.rb
services/api/script/arvados-git-sync.rb [deleted file]
services/api/script/migrate-gitolite-to-uuid-storage.rb [deleted file]
services/api/test/fixtures/api_client_authorizations.yml
services/api/test/fixtures/collections.yml
services/api/test/fixtures/container_requests.yml
services/api/test/fixtures/containers.yml
services/api/test/fixtures/humans.yml [deleted file]
services/api/test/fixtures/job_tasks.yml [deleted file]
services/api/test/fixtures/jobs.yml [deleted file]
services/api/test/fixtures/keep_disks.yml [deleted file]
services/api/test/fixtures/links.yml
services/api/test/fixtures/logs.yml
services/api/test/fixtures/nodes.yml [deleted file]
services/api/test/fixtures/pipeline_instances.yml [deleted file]
services/api/test/fixtures/pipeline_templates.yml [deleted file]
services/api/test/fixtures/repositories.yml [deleted file]
services/api/test/fixtures/specimens.yml [deleted file]
services/api/test/fixtures/traits.yml [deleted file]
services/api/test/functional/application_controller_test.rb
services/api/test/functional/arvados/v1/collections_controller_test.rb
services/api/test/functional/arvados/v1/commits_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/groups_controller_test.rb
services/api/test/functional/arvados/v1/humans_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/job_reuse_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/job_tasks_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/jobs_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/keep_disks_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/nodes_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/pipeline_instances_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/pipeline_templates_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/repositories_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/schema_controller_test.rb
services/api/test/functional/arvados/v1/specimens_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/traits_controller_test.rb [deleted file]
services/api/test/functional/arvados/v1/users_controller_test.rb
services/api/test/functional/database_controller_test.rb
services/api/test/functional/sys_controller_test.rb
services/api/test/helpers/git_test_helper.rb [deleted file]
services/api/test/helpers/users_test_helper.rb
services/api/test/integration/api_client_authorizations_scopes_test.rb
services/api/test/integration/database_reset_test.rb
services/api/test/integration/groups_test.rb
services/api/test/integration/jobs_api_test.rb [deleted file]
services/api/test/integration/login_workflow_test.rb
services/api/test/integration/permissions_test.rb
services/api/test/integration/reader_tokens_test.rb
services/api/test/integration/serialized_encoding_test.rb
services/api/test/integration/user_sessions_test.rb
services/api/test/integration/users_test.rb
services/api/test/test.git.tar [deleted file]
services/api/test/unit/arvados_model_test.rb
services/api/test/unit/commit_ancestor_test.rb [deleted file]
services/api/test/unit/commit_test.rb [deleted file]
services/api/test/unit/container_test.rb
services/api/test/unit/group_test.rb
services/api/test/unit/helpers/api_client_authorizations_helper_test.rb [deleted file]
services/api/test/unit/helpers/api_clients_helper_test.rb [deleted file]
services/api/test/unit/helpers/authorized_keys_helper_test.rb [deleted file]
services/api/test/unit/helpers/collections_helper_test.rb [deleted file]
services/api/test/unit/helpers/commit_ancestors_helper_test.rb [deleted file]
services/api/test/unit/helpers/commits_helper_test.rb [deleted file]
services/api/test/unit/helpers/groups_helper_test.rb [deleted file]
services/api/test/unit/helpers/humans_helper_test.rb [deleted file]
services/api/test/unit/helpers/job_tasks_helper_test.rb [deleted file]
services/api/test/unit/helpers/jobs_helper_test.rb [deleted file]
services/api/test/unit/helpers/keep_disks_helper_test.rb [deleted file]
services/api/test/unit/helpers/links_helper_test.rb [deleted file]
services/api/test/unit/helpers/logs_helper_test.rb [deleted file]
services/api/test/unit/helpers/nodes_helper_test.rb [deleted file]
services/api/test/unit/helpers/pipeline_instances_helper_test.rb [deleted file]
services/api/test/unit/helpers/pipeline_templates_helper_test.rb [deleted file]
services/api/test/unit/helpers/repositories_helper_test.rb [deleted file]
services/api/test/unit/helpers/specimens_helper_test.rb [deleted file]
services/api/test/unit/helpers/traits_helper_test.rb [deleted file]
services/api/test/unit/helpers/virtual_machines_helper_test.rb [deleted file]
services/api/test/unit/human_test.rb [deleted file]
services/api/test/unit/job_task_test.rb [deleted file]
services/api/test/unit/job_test.rb [deleted file]
services/api/test/unit/link_test.rb
services/api/test/unit/log_test.rb
services/api/test/unit/owner_test.rb
services/api/test/unit/permission_test.rb
services/api/test/unit/pipeline_instance_test.rb [deleted file]
services/api/test/unit/pipeline_template_test.rb [deleted file]
services/api/test/unit/repository_test.rb [deleted file]
services/api/test/unit/specimen_test.rb [deleted file]
services/api/test/unit/trait_test.rb [deleted file]
services/api/test/unit/user_test.rb
services/fuse/tests/test_token_expiry.py
services/githttpd/auth_handler.go [deleted file]
services/githttpd/auth_handler_test.go [deleted file]
services/githttpd/cmd.go [deleted file]
services/githttpd/git_handler.go [deleted file]
services/githttpd/git_handler_test.go [deleted file]
services/githttpd/gitolite_test.go [deleted file]
services/githttpd/integration_test.go [deleted file]
services/githttpd/server_test.go [deleted file]
services/workbench2/cypress/e2e/search.cy.js
services/ws/event_source_test.go
services/ws/event_test.go
tools/arvbox/lib/arvbox/docker/Dockerfile.base
tools/arvbox/lib/arvbox/docker/Dockerfile.demo
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/gitolite.rc [deleted file]
tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/main/.gitstub [deleted file]
tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run [deleted symlink]
tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run [deleted symlink]
tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service [deleted file]
tools/arvbox/lib/arvbox/docker/service/gitolite/log/main/.gitstub [deleted file]
tools/arvbox/lib/arvbox/docker/service/gitolite/log/run [deleted symlink]
tools/arvbox/lib/arvbox/docker/service/gitolite/run [deleted symlink]
tools/arvbox/lib/arvbox/docker/service/gitolite/run-service [deleted file]
tools/arvbox/lib/arvbox/docker/service/nginx/run
tools/arvbox/lib/arvbox/docker/service/vm/run
tools/salt-install/config_examples/multi_host/aws/pillars/arvados.sls
tools/salt-install/config_examples/single_host/multiple_hostnames/pillars/arvados.sls
tools/salt-install/config_examples/single_host/single_hostname/pillars/arvados.sls

index 6ac2539f8e68e7c229cf7c1e4859674605c3c1d4..08772ce02fb3b747c8eafd31dcab45153cb950bc 100644 (file)
@@ -13,5 +13,4 @@ Since our build process is a tower of shell scripts, concatenating files seemed
 postinst.sh lets the early parts define a few hooks to control behavior:
 
 * After it installs the core configuration files (database.yml, application.yml, and production.rb) to /etc/arvados/server, it calls setup_extra_conffiles.  By default this is a noop function (in step2.sh).
-* Before it restarts nginx, it calls setup_before_nginx_restart.  By default this is a noop function (in step2.sh).  API server defines this to set up the internal git repository, if necessary.
 * $RAILSPKG_DATABASE_LOAD_TASK defines the Rake task to load the database.  API server uses db:structure:load.  Workbench doesn't set this, which causes the postinst to skip all database work.
index a0e356ce327cba01b876b1330c7430462c317542..493147d52138a80a0e7d5d3ff16ff30281d6ae07 100644 (file)
@@ -16,23 +16,3 @@ setup_extra_conffiles() {
   # can still be there, left over from a previous version of the API server package.
   rm -f $RELEASE_PATH/config/initializers/omniauth.rb
 }
-
-setup_before_nginx_restart() {
-  # initialize git_internal_dir
-  # usually /var/lib/arvados/internal.git (set in application.default.yml )
-  if [ "$APPLICATION_READY" = "1" ]; then
-      GIT_INTERNAL_DIR=$($COMMAND_PREFIX bin/rake config:dump 2>&1 | grep GitInternalDir | awk '{ print $2 }' |tr -d '"')
-      if [ ! -e "$GIT_INTERNAL_DIR" ]; then
-        run_and_report "Creating git_internal_dir '$GIT_INTERNAL_DIR'" \
-          mkdir -p "$GIT_INTERNAL_DIR"
-        run_and_report "Initializing git_internal_dir '$GIT_INTERNAL_DIR'" \
-          git init --quiet --bare $GIT_INTERNAL_DIR
-      else
-        echo "Initializing git_internal_dir $GIT_INTERNAL_DIR: directory exists, skipped."
-      fi
-      run_and_report "Making sure '$GIT_INTERNAL_DIR' has the right permission" \
-         chown -R "$WWW_OWNER:" "$GIT_INTERNAL_DIR"
-  else
-      echo "Initializing git_internal_dir... skipped."
-  fi
-}
index 95bb920d0bb212085c02ccba1cabc25619fec610..b5f78f988cda7f7097dc05c526fb58dadd170e7d 100644 (file)
@@ -248,8 +248,6 @@ configure_version() {
 
   chown -R "$WWW_OWNER:" $RELEASE_PATH/tmp
 
-  setup_before_nginx_restart
-
   if [ -n "$SERVICE_MANAGER" ]; then
       service_command "$SERVICE_MANAGER" restart "$WEB_SERVICE"
   fi
index 41c9cd71e366ff5d14973638ad48547bcc98ba3a..4af0e4a01b8c3edf855dd15c0d21c353d4658ee5 100644 (file)
@@ -26,9 +26,6 @@ SHARED_PATH=$INSTALL_PATH/shared
 if ! type setup_extra_conffiles >/dev/null 2>&1; then
     setup_extra_conffiles() { return; }
 fi
-if ! type setup_before_nginx_restart >/dev/null 2>&1; then
-    setup_before_nginx_restart() { return; }
-fi
 
 if [ -e /run/systemd/system ]; then
     USING_SYSTEMD=1
index b94f5be9199dc617ef518626dd934a62eb46ec05..b1801dd307a1ac34591e5ef2b0169bdba5a92ddb 100755 (executable)
@@ -230,7 +230,6 @@ if test -z "$packages" ; then
         arvados-dispatch-cloud
         arvados-dispatch-lsf
         arvados-docker-cleaner
-        arvados-git-httpd
         arvados-health
         arvados-server
         arvados-src
index ef1e430a5bd2704927fbce12551c4081c5b6abf1..588ebedb92c55d2d558f1478ad8a29731dd4fcc8 100755 (executable)
@@ -235,8 +235,6 @@ package_go_binary cmd/arvados-server arvados-dispatch-cloud "$FORMAT" "$ARCH" \
     "Arvados cluster cloud dispatch"
 package_go_binary cmd/arvados-server arvados-dispatch-lsf "$FORMAT" "$ARCH" \
     "Dispatch Arvados containers to an LSF cluster"
-package_go_binary cmd/arvados-server arvados-git-httpd "$FORMAT" "$ARCH" \
-    "Provide authenticated http access to Arvados-hosted git repositories"
 package_go_binary services/crunch-dispatch-local crunch-dispatch-local "$FORMAT" "$ARCH" \
     "Dispatch Crunch containers on the local system"
 package_go_binary cmd/arvados-server crunch-dispatch-slurm "$FORMAT" "$ARCH" \
index 2f1c40ec6fa1f96f5df2f7b7bbeea0132d78b401..3ab571ff7f812e5e3abd69fad0f1a51b6720e18f 100755 (executable)
@@ -40,7 +40,7 @@ services/api_test="TEST=test/functional/arvados/v1/collections_controller_test.r
                Restrict apiserver tests to the given file
 sdk/python_test="--test-suite tests.test_keep_locator"
                Restrict Python SDK tests to the given class
-services/githttpd_test="-check.vv"
+lib/dispatchcloud_test="-check.vv"
                Show all log messages, even when tests pass (also works
                with services/keepstore_test etc.)
 ARVADOS_DEBUG=1
@@ -87,7 +87,6 @@ lib/mount
 lib/pam
 lib/service
 services/api
-services/githttpd
 services/dockercleaner
 services/fuse
 services/fuse:py3
@@ -221,9 +220,6 @@ sanity_checks() {
     echo -n 'nginx: '
     PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
         || fatal "No nginx. Try: apt-get install nginx"
-    echo -n 'gitolite: '
-    which gitolite \
-        || fatal "No gitolite. Try: apt-get install gitolite3"
     echo -n 'npm: '
     npm --version \
         || fatal "No npm. Try: wget -O- https://nodejs.org/dist/v12.22.12/node-v12.22.12-linux-x64.tar.xz | sudo tar -C /usr/local -xJf - && sudo ln -s ../node-v12.22.12-linux-x64/bin/{node,npm} /usr/local/bin/"
@@ -395,7 +391,7 @@ start_services() {
         return 0
     fi
     . "$VENV3DIR/bin/activate"
-    echo 'Starting API, controller, keepproxy, keep-web, githttpd, ws, and nginx ssl proxy...'
+    echo 'Starting API, controller, keepproxy, keep-web, ws, and nginx ssl proxy...'
     if [[ ! -d "$WORKSPACE/services/api/log" ]]; then
         mkdir -p "$WORKSPACE/services/api/log"
     fi
@@ -423,9 +419,6 @@ start_services() {
         && python3 sdk/python/tests/run_test_server.py start_keep-web \
         && checkpidfile keep-web \
         && checkhealth WebDAV \
-        && python3 sdk/python/tests/run_test_server.py start_githttpd \
-        && checkpidfile githttpd \
-        && checkhealth GitHTTP \
         && python3 sdk/python/tests/run_test_server.py start_ws \
         && checkpidfile ws \
         && export ARVADOS_TEST_PROXY_SERVICES=1 \
@@ -446,7 +439,6 @@ stop_services() {
     . "$VENV3DIR/bin/activate" || return
     cd "$WORKSPACE" \
         && python3 sdk/python/tests/run_test_server.py stop_nginx \
-        && python3 sdk/python/tests/run_test_server.py stop_githttpd \
         && python3 sdk/python/tests/run_test_server.py stop_ws \
         && python3 sdk/python/tests/run_test_server.py stop_keep-web \
         && python3 sdk/python/tests/run_test_server.py stop_keep_proxy \
@@ -889,15 +881,6 @@ install_services/api() {
         ) || return 1
     fi
 
-    cd "$WORKSPACE/services/api" \
-        && rm -rf tmp/git \
-        && mkdir -p tmp/git \
-        && cd tmp/git \
-        && tar xf ../../test/test.git.tar \
-        && mkdir -p internal.git \
-        && git --git-dir internal.git init \
-            || return 1
-
     (
         set -ex
         cd "$WORKSPACE/services/api"
index 19d13437c898baad0fb2ceaea363c56ef7318d44..62630a6a01b0651d8701aa08f3f22469a75ad405 100644 (file)
@@ -37,19 +37,9 @@ var (
                "container":                cli.APICall,
                "container_request":        cli.APICall,
                "group":                    cli.APICall,
-               "human":                    cli.APICall,
-               "job":                      cli.APICall,
-               "job_task":                 cli.APICall,
-               "keep_disk":                cli.APICall,
                "keep_service":             cli.APICall,
                "link":                     cli.APICall,
                "log":                      cli.APICall,
-               "node":                     cli.APICall,
-               "pipeline_instance":        cli.APICall,
-               "pipeline_template":        cli.APICall,
-               "repository":               cli.APICall,
-               "specimen":                 cli.APICall,
-               "trait":                    cli.APICall,
                "user_agreement":           cli.APICall,
                "user":                     cli.APICall,
                "virtual_machine":          cli.APICall,
diff --git a/cmd/arvados-server/arvados-git-httpd.service b/cmd/arvados-server/arvados-git-httpd.service
deleted file mode 100644 (file)
index 517a75c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-[Unit]
-Description=Arvados git server
-Documentation=https://doc.arvados.org/
-After=network.target
-AssertPathExists=/etc/arvados/config.yml
-StartLimitIntervalSec=0
-
-[Service]
-Type=notify
-EnvironmentFile=-/etc/arvados/environment
-ExecStart=/usr/bin/arvados-git-httpd
-# Set a reasonable default for the open file limit
-LimitNOFILE=65536
-Restart=always
-RestartSec=1
-RestartPreventExitStatus=2
-
-[Install]
-WantedBy=multi-user.target
index c02b8fb57cf90cc318604d0d24063751c7da90d1..0f267a9b408f70afe2f370f172447fbf7128db2c 100644 (file)
@@ -30,7 +30,6 @@ import (
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "git.arvados.org/arvados.git/sdk/go/health"
        dispatchslurm "git.arvados.org/arvados.git/services/crunch-dispatch-slurm"
-       "git.arvados.org/arvados.git/services/githttpd"
        keepbalance "git.arvados.org/arvados.git/services/keep-balance"
        keepweb "git.arvados.org/arvados.git/services/keep-web"
        "git.arvados.org/arvados.git/services/keepproxy"
@@ -57,7 +56,6 @@ var (
                "dispatch-cloud":     dispatchcloud.Command,
                "dispatch-lsf":       lsf.DispatchCommand,
                "dispatch-slurm":     dispatchslurm.Command,
-               "git-httpd":          githttpd.Command,
                "health":             healthCommand,
                "install":            install.Command,
                "init":               install.InitCommand,
index 053922a24a4890ad4c26f21dd0f34036aaf5aa36..d64bc4b7dc5463880606737ea6ec18218f7ff16c 100644 (file)
@@ -141,7 +141,6 @@ navbar:
       - api/methods/pipeline_instances.html.textile.liquid
       - api/methods/pipeline_templates.html.textile.liquid
       - api/methods/nodes.html.textile.liquid
-      - api/methods/repositories.html.textile.liquid
       - api/methods/keep_disks.html.textile.liquid
     - Metadata for bioinformatics (legacy):
       - api/methods/humans.html.textile.liquid
@@ -243,13 +242,9 @@ navbar:
       - install/install-ws.html.textile.liquid
       - install/install-workbench2-app.html.textile.liquid
       - install/workbench.html.textile.liquid
-#      - install/install-composer.html.textile.liquid
     - Additional services:
       - install/install-shell-server.html.textile.liquid
       - install/install-webshell.html.textile.liquid
-      - install/install-arv-git-httpd.html.textile.liquid
-#    - Containers API (all):
-#      - install/install-jobs-image.html.textile.liquid
     - Containers API (cloud):
       - install/crunch2-cloud/install-compute-node.html.textile.liquid
       - install/crunch2-cloud/install-dispatch-cloud.html.textile.liquid
index 86e05be8663cc6053f72a6565bf5a0b628095b1a..f22f7d35514afd1822b02cd996e5ff417131b794 100644 (file)
@@ -24,15 +24,6 @@ At container startup, the target path will have the same directory structure as
  "kind":"collection",
  "uuid":"..."
 }</code></pre>|
-|Git tree|@git_tree@|@"uuid"@ must be the UUID of an Arvados-hosted git repository.
-@"commit"@ must be a full 40-character commit hash.
-@"path"@, if provided, must be "/".
-At container startup, the target path will have the source tree indicated by the given commit. The @.git@ metadata directory _will not_ be available.|<pre><code>{
- "kind":"git_tree",
- "uuid":"zzzzz-s0uqq-xxxxxxxxxxxxxxx",
- "commit":"f315c59f90934cccae6381e72bba59d27ba42099"
-}
-</code></pre>|
 |Temporary directory|@tmp@|@"capacity"@: capacity (in bytes) of the storage device.
 @"device_type"@ (optional, default "network"): one of @{"ram", "ssd", "disk", "network"}@ indicating the acceptable level of performance. (*note: not yet implemented as of v1.5*)
 At container startup, the target path will be empty. When the container finishes, the content will be discarded. This will be backed by a storage mechanism no slower than the specified type.|<pre><code>{
index 8cb09f135f23dbbc8b4dccecf4643f99f72e8136..4bf72c1b31f48fcd654ed13a49b28067d8eb31b7 100644 (file)
@@ -5,7 +5,7 @@ SPDX-License-Identifier: CC-BY-SA-3.0
 {% endcomment %}
 
 
-Arvados requires a public SSH key in order to securely log in to an Arvados VM instance, or to access an Arvados Git repository. The three sections below help you get started:
+Arvados requires a public SSH key in order to securely log in to an Arvados VM instance. The three sections below help you get started:
 
 # "Getting your SSH key":#gettingkey
 # "Adding your key to Arvados Workbench":#workbench
diff --git a/doc/_includes/_tutorial_git_repo_expectations.liquid b/doc/_includes/_tutorial_git_repo_expectations.liquid
deleted file mode 100644 (file)
index 8a172de..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin' %}
-This tutorial assumes that you have a working Arvados repository. If you do not have a repository created, you can follow the instructions in the "Adding a new repository":{{site.baseurl}}/user/tutorials/add-new-repository.html page. We will use the *$USER/tutorial* repository created in that page as the example.
-{% include 'notebox_end' %}
index 9158dd6b78e22d714ae2fdbe16443d1eb0f8362a..e2d1404332dd08f3b1898cc7d9301750933dd817 100644 (file)
@@ -31,7 +31,6 @@ table(table table-bordered table-condensed).
 |controller     |yes                    |yes|yes ^2,4^|InternalURLs used by reverse proxy and container shell connections|
 |arvados-dispatch-cloud|no              |yes|no ^3^|InternalURLs only used to expose Prometheus metrics|
 |arvados-dispatch-lsf|no                |yes|no ^3^|InternalURLs only used to expose Prometheus metrics|
-|git-http       |yes                    |yes|no ^2^|InternalURLs only used by reverse proxy (e.g. Nginx)|
 |git-ssh        |yes                    |no |no    ||
 |keepproxy      |yes                    |yes|no ^2^|InternalURLs only used by reverse proxy (e.g. Nginx)|
 |keepstore      |no                     |yes|yes   |All clients connect to InternalURLs|
index fff94cb55f63eee113884a0762ea50d4b3b3470d..601d26c5cb26973c7fa17fa9fec7973ccbeda911 100644 (file)
@@ -25,7 +25,6 @@ table(table table-bordered table-condensed table-hover){width:40em}.
 |arvados-controller|✓|
 |arvados-dispatch-cloud|✓|
 |arvados-dispatch-lsf|✓|
-|arvados-git-httpd||
 |arvados-ws|✓|
 |composer||
 |keepproxy|✓|
index a4939b740cba561025297a44e748511f2de7be0b..5650c5038d9a65999519212914c07c24103efa3c 100644 (file)
@@ -21,7 +21,6 @@ h2. API server and other services
 The following services also support monitoring.
 
 * API server
-* arvados-git-httpd
 * controller
 * keep-balance
 * keepproxy
index ed9fbbd7ae33f292697143af09363feb18cb5cc5..113536ff587b4d331ec5c0c8f6bc2164ab8e8594 100644 (file)
@@ -35,9 +35,7 @@ table(table table-bordered table-condensed table-hover).
 |arvados-controller|✓|
 |arvados-dispatch-cloud|✓|
 |arvados-dispatch-lsf|✓|
-|arvados-git-httpd||
 |arvados-ws|✓|
-|composer||
 |keepproxy|✓|
 |keepstore|✓|
 |keep-balance|✓|
index 64a113b6f8aba840814119be4486de02870984dc..320f188812c6c6a27727c9122a9eb4790d5ba466 100644 (file)
@@ -142,7 +142,7 @@ We have introduced a small exception to the previous behavior of "Arvados API to
 
 h3. Deprecated/legacy APIs slated for removal
 
-The legacy APIs "humans":../api/methods/humans.html, "specimens":../api/methods/specimens.html, "traits":../api/methods/traits.html, "jobs":../api/methods/jobs.html, "job_tasks":../api/methods/job_tasks.html, "pipeline_instances":../api/methods/pipeline_instances.html, "pipeline_templates":../api/methods/pipeline_templates.html, "nodes":../api/methods/nodes.html, "repositories":../api/methods/repositories.html, and "keep_disks":../api/methods/keep_disks.html are deprecated and will be removed in a future major version of Arvados.
+The legacy APIs "humans":https://doc.arvados.org/v2.7/api/methods/humans.html, "specimens":https://doc.arvados.org/v2.7/api/methods/specimens.html, "traits":https://doc.arvados.org/v2.7/api/methods/traits.html, "jobs":https://doc.arvados.org/v2.7/api/methods/jobs.html, "job_tasks":https://doc.arvados.org/v2.7/api/methods/job_tasks.html, "pipeline_instances":https://doc.arvados.org/v2.7/api/methods/pipeline_instances.html, "pipeline_templates":https://doc.arvados.org/v2.7/api/methods/pipeline_templates.html, "nodes":https://doc.arvados.org/v2.7/api/methods/nodes.html, "repositories":https://doc.arvados.org/v2.7/api/methods/repositories.html, and "keep_disks":https://doc.arvados.org/v2.7/api/methods/keep_disks.html are deprecated and will be removed in a future major version of Arvados.
 
 In addition, the @default_owner_uuid@, @api_client_id@, and @user_id@ fields of "api_client_authorizations":../api/methods/api_client_authorizations.html are deprecated and will be removed from @api_client_authorization@ responses in a future major version of Arvados.  This should not affect clients as  @default_owner_uuid@ was never implemented, and @api_client_id@ and @user_id@ returned internal ids that were not meaningful or usable with any other API call.
 
index c2d4743ddfdf5b58372ac9b31dfff9452eb2db26..dea705ddaa9d6710118e1dd98e13684dde5c5c83 100644 (file)
@@ -144,23 +144,3 @@ read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
 }
 EOF
 </pre>
-
-h3. Git repository
-
-Give @$user_uuid@ permission to commit to @$repo_uuid@ as @$repo_username@
-
-<pre>
-user_uuid=xxxxxxxchangeme
-repo_uuid=xxxxxxxchangeme
-repo_username=xxxxxxxchangeme
-
-read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
-{
-"tail_uuid":"$user_uuid",
-"head_uuid":"$repo_uuid",
-"link_class":"permission",
-"name":"can_write",
-"properties":{"username":"$repo_username"}
-}
-EOF
-</pre>
index 7d30ee88d1e70cbca7eb046e967e337abd154ac0..994081901ca86ebd9e5e65d9129eb4f14b956f52 100644 (file)
@@ -60,7 +60,6 @@ notextile. <div class="spaced-out">
 # A new user record is not set up, and not active.  An inactive user cannot create or update any object, but can read Arvados objects that the user account has permission to read (such as publicly available items readable by the "anonymous" user).
 # Using Workbench or the "command line":{{site.baseurl}}/admin/user-management-cli.html , the admin invokes @setup@ on the user.  The setup method adds the user to the "All users" group.
 - If "Users.AutoSetupNewUsers":config.html is true, this happens automatically during user creation, so in that case new users start at step (3).
-- If "Users.AutoSetupNewUsersWithRepository":config.html is true, a new git repo is created for the user.
 - If "Users.AutoSetupNewUsersWithVmUUID":config.html is set, the user is given login permission to the specified shell node
 # User is set up, but still not yet active.  The browser presents "user agreements":#user_agreements (if any) and then invokes the user @activate@ method on the user's behalf.
 # The user @activate@ method checks that all "user agreements":#user_agreements are signed.  If so, or there are no user agreements, the user is activated.
diff --git a/doc/api/crunch-scripts.html.textile.liquid b/doc/api/crunch-scripts.html.textile.liquid
deleted file mode 100644 (file)
index a0d244d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: Concepts
-title: Crunch scripts
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "container requests.":methods/container_requests.html
-{% include 'notebox_end' %}
-
-h2. Crunch scripts
-
-A crunch script is responsible for completing a single JobTask. In doing so, it will:
-
-* (optionally) read some input from Keep
-* (optionally) store some output in Keep
-* (optionally) create some new JobTasks and add them to the current Job
-* (optionally) update the current JobTask record with the "output" attribute set to a Keep locator or a fragment of a manifest
-* update the current JobTask record with the "success" attribute set to True
-
-A task's context is provided in environment variables.
-
-table(table table-bordered table-condensed).
-|Environment variable|Description|
-|@JOB_UUID@|UUID of the current "Job":methods/jobs.html|
-|@TASK_UUID@|UUID of the current "JobTask":methods/job_tasks.html|
-|@ARVADOS_API_HOST@|Hostname and port number of API server|
-|@ARVADOS_API_TOKEN@|Authentication token to use with API calls made by the current task|
-
-The crunch script typically uses the Python SDK (or another suitable client library / SDK) to connect to the Arvados service and retrieve the rest of the details about the current job and task.
-
-The Python SDK has some shortcuts for common operations.
-
-In general, a crunch script can access information about the current job and task like this:
-
-<pre>
-import arvados
-import os
-
-job = arvados.api().jobs().get(uuid=os.environ['JOB_UUID']).execute()
-$sys.stderr.write("script_parameters['foo'] == %s"
-                  % job['script_parameters']['foo'])
-
-task = arvados.api().job_tasks().get(uuid=os.environ['TASK_UUID']).execute()
-$sys.stderr.write("current task sequence number is %d"
-                  % task['sequence'])
-</pre>
diff --git a/doc/api/methods/humans.html.textile.liquid b/doc/api/methods/humans.html.textile.liquid
deleted file mode 100644 (file)
index 1c33821..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "humans"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and is slated to be removed entirely in a future major release of Arvados.  The recommended way to store metadata is with "'properties' field on collections and projects.":../properties.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/humans@
-
-Object type: @7a9it@
-
-Example UUID: @zzzzz-7a9it-0123456789abcde@
-
-h2. Resource
-
-A metadata record that may be used to represent a human subject.
-
-Each Human has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|properties|hash|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new Human.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|human|object||query||
-
-h3. delete
-
-Delete an existing Human.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Human in question.|path||
-
-h3. get
-
-Gets a Human's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Human in question.|path||
-
-h3. list
-
-List humans.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing Human.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Human in question.|path||
-|human|object||query||
diff --git a/doc/api/methods/job_tasks.html.textile.liquid b/doc/api/methods/job_tasks.html.textile.liquid
deleted file mode 100644 (file)
index 880fe56..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "job_tasks"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "container requests.":container_requests.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/job_tasks@
-
-Object type: @ot0gb@
-
-Example UUID: @zzzzz-ot0gb-0123456789abcde@
-
-h2. Resource
-
-Deprecated.
-
-A job task is a individually scheduled unit of work executed as part of an overall job.
-
-Each JobTask has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|sequence|integer|Execution sequence.
-A step cannot be run until all steps with lower sequence numbers have completed.
-Job steps with the same sequence number can be run in any order.||
-|parameters|hash|||
-|output|text|||
-|progress|float|||
-|success|boolean|Is null if the task has neither completed successfully nor failed permanently.||
-
-The following attributes should not be updated by anyone other than the job manager:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Notes|
-|qsequence|integer|Order of arrival|0-based|
-|job_uuid|string|||
-|created_by_job_task_uuid|string|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new JobTask.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|job_task|object||query||
-
-h3. delete
-
-Delete an existing JobTask.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the JobTask in question.|path||
-
-h3. get
-
-Gets a JobTask's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the JobTask in question.|path||
-
-h3. list
-
-List job_tasks.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing JobTask.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the JobTask in question.|path||
-|job_task|object||query||
diff --git a/doc/api/methods/jobs.html.textile.liquid b/doc/api/methods/jobs.html.textile.liquid
deleted file mode 100644 (file)
index 75d7368..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "jobs"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "container requests.":container_requests.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/jobs@
-
-Object type: @8i9sb@
-
-Example UUID: @zzzzz-8i9sb-0123456789abcde@
-
-h2. Resource
-
-A job describes a work order to be executed by the Arvados cluster.
-
-Each job has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Notes|
-|script|string|The filename of the job script.|This program will be invoked by Crunch for each job task. It is given as a path to an executable file, relative to the @/crunch_scripts@ directory in the Git tree specified by the _repository_ and _script_version_ attributes.|
-|script_parameters|hash|The input parameters for the job.|Conventionally, one of the parameters is called @"input"@. Typically, some parameter values are collection UUIDs. Ultimately, though, the significance of parameters is left entirely up to the script itself.|
-|repository|string|Git repository name or URL.|Source of the repository where the given script_version is to be found. This can be given as the name of a locally hosted repository, or as a publicly accessible URL starting with @git://@, @http://@, or @https://@.
-Examples:
-@yourusername/yourrepo@
-@https://github.com/arvados/arvados.git@|
-|script_version|string|Git commit|During a **create** transaction, this is the Git branch, tag, or hash supplied by the client. Before the job starts, Arvados updates it to the full 40-character SHA-1 hash of the commit used by the job.
-See "Specifying Git versions":#script_version below for more detail about acceptable ways to specify a commit.|
-|cancelled_by_client_uuid|string|API client ID|Is null if job has not been cancelled|
-|cancelled_by_user_uuid|string|Authenticated user ID|Is null if job has not been cancelled|
-|cancelled_at|datetime|When job was cancelled|Is null if job has not been cancelled|
-|started_at|datetime|When job started running|Is null if job has not [yet] started|
-|finished_at|datetime|When job finished running|Is null if job has not [yet] finished|
-|running|boolean|Whether the job is running||
-|success|boolean|Whether the job indicated successful completion|Is null if job has not finished|
-|is_locked_by_uuid|string|UUID of the user who has locked this job|Is null if job is not locked. The system user locks the job when starting the job, in order to prevent job attributes from being altered.|
-|node_uuids|array|List of UUID strings for node objects that have been assigned to this job||
-|log|string|Collection UUID|Is null if the job has not finished. After the job runs, the given collection contains a text file with log messages provided by the @arv-crunch-job@ task scheduler as well as the standard error streams provided by the task processes.|
-|tasks_summary|hash|Summary of task completion states.|Example: @{"done":0,"running":4,"todo":2,"failed":0}@|
-|output|string|Collection UUID|Is null if the job has not finished.|
-|nondeterministic|boolean|The job is expected to produce different results if run more than once.|If true, this job will not be considered as a candidate for automatic re-use when submitting subsequent identical jobs.|
-|submit_id|string|Unique ID provided by client when job was submitted|Optional. This can be used by a client to make the "jobs.create":{{site.baseurl}}/api/methods/jobs.html#create method idempotent.|
-|priority|string|||
-|arvados_sdk_version|string|Git commit hash that specifies the SDK version to use from the Arvados repository|This is set by searching the Arvados repository for a match for the arvados_sdk_version runtime constraint.|
-|docker_image_locator|string|Portable data hash of the collection that contains the Docker image to use|This is set by searching readable collections for a match for the docker_image runtime constraint.|
-|runtime_constraints|hash|Constraints that must be satisfied by the job/task scheduler in order to run the job.|See below.|
-|components|hash|Name and uuid pairs representing the child work units of this job. The uuids can be of different object types.|Example components hash: @{"name1": "zzzzz-8i9sb-xyz...", "name2": "zzzzz-d1hrv-xyz...",}@|
-
-h3(#script_version). Specifying Git versions
-
-The script_version attribute and arvados_sdk_version runtime constraint are typically given as a branch, tag, or commit hash, but there are many more ways to specify a Git commit. The "specifying revisions" section of the "gitrevisions manual page":http://git-scm.com/docs/gitrevisions.html has a definitive list. Arvados accepts Git versions in any format listed there that names a single commit (not a tree, a blob, or a range of commits). However, some kinds of names can be expected to resolve differently in Arvados than they do in your local repository. For example, <code>HEAD@{1}</code> refers to the local reflog, and @origin/main@ typically refers to a remote branch: neither is likely to work as desired if given as a Git version.
-
-h3. Runtime constraints
-
-table(table table-bordered table-condensed).
-|_. Key|_. Type|_. Description|_. Implemented|
-|arvados_sdk_version|string|The Git version of the SDKs to use from the Arvados git repository.  See "Specifying Git versions":#script_version for more detail about acceptable ways to specify a commit.  If you use this, you must also specify a @docker_image@ constraint (see below).  In order to install the Python SDK successfully, Crunch must be able to find and run virtualenv inside the container.|&#10003;|
-|docker_image|string|The Docker image that this Job needs to run.  If specified, Crunch will create a Docker container from this image, and run the Job's script inside that.  The Keep mount and work directories will be available as volumes inside this container.  The image must be uploaded to Arvados using @arv keep docker@.  You may specify the image in any format that Docker accepts, such as @arvados/jobs@, @debian:latest@, or the Docker image id.  Alternatively, you may specify the portable data hash of the image Collection.|&#10003;|
-|min_nodes|integer||&#10003;|
-|max_nodes|integer|||
-|min_cores_per_node|integer|Require that each node assigned to this Job have the specified number of CPU cores|&#10003;|
-|min_ram_mb_per_node|integer|Require that each node assigned to this Job have the specified amount of real memory (in MiB)|&#10003;|
-|min_scratch_mb_per_node|integer|Require that each node assigned to this Job have the specified amount of scratch storage available (in MiB)|&#10003;|
-|max_tasks_per_node|integer|Maximum simultaneous tasks on a single node|&#10003;|
-|keep_cache_mb_per_task|integer|Size of file data buffer for per-task Keep directory ($TASK_KEEPMOUNT), in MiB.  Default is 256 MiB.  Increase this to reduce cache thrashing in situtations such as accessing multiple large (64+ MiB) files at the same time, or accessing different parts of a large file at the same time.|&#10003;|
-|min_ram_per_task|integer|Minimum real memory (KiB) per task||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. cancel
-
-Cancel a job that is queued or running.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string||path||
-
-h3(#create). create
-
-Create a new Job.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|job|object|Job resource|request body||
-|minimum_script_version |string     |Git branch, tag, or commit hash specifying the minimum acceptable script version (earliest ancestor) to consider when deciding whether to re-use a past job.[1]|query|@"c3e86c9"@|
-|exclude_script_versions|array of strings|Git commit branches, tags, or hashes to exclude when deciding whether to re-use a past job.|query|@["8f03c71","8f03c71"]@
-@["badtag1","badtag2"]@|
-|filters|array of arrays|Conditions to find Jobs to reuse.|query||
-|find_or_create         |boolean    |Before creating, look for an existing job that has identical script, script_version, and script_parameters to those in the present job, has nondeterministic=false, and did not fail (it could be queued, running, or completed). If such a job exists, respond with the existing job instead of submitting a new one.|query|@false@|
-
-When a job is submitted to the queue using the **create** method, the @script_version@ attribute is updated to a full 40-character Git commit hash based on the current content of the specified repository. If @script_version@ cannot be resolved, the job submission is rejected.
-
-fn1. See the "note about specifying Git commits":#script_version for more detail.
-
-h4. Specialized filters
-
-Special filter operations are available for specific Job columns.
-
-* @script_version@ @in git@ @REFSPEC@, @arvados_sdk_version@ @in git@ @REFSPEC@<br>Resolve @REFSPEC@ to a list of Git commits, and match jobs with a @script_version@ or @arvados_sdk_version@ in that list.  When creating a job and filtering @script_version@, the search will find commits between @REFSPEC@ and the submitted job's @script_version@; all other searches will find commits between @REFSPEC@ and HEAD.  This list may include parallel branches if there is more than one path between @REFSPEC@ and the end commit in the graph.  Use @not in@ or @not in git@ filters (below) to blacklist specific commits.
-
-* @script_version@ @not in git@ @REFSPEC@, @arvados_sdk_version@ @not in git@ @REFSPEC@<br>Resolve @REFSPEC@ to a list of Git commits, and match jobs with a @script_version@ or @arvados_sdk_version@ not in that list.
-
-* @docker_image_locator@ @in docker@ @SEARCH@<br>@SEARCH@ can be a Docker image hash, a repository name, or a repository name and tag separated by a colon (@:@).  The server will find collections that contain a Docker image that match that search criteria, then match jobs with a @docker_image_locator@ in that list.
-
-* @docker_image_locator@ @not in docker@ @SEARCH@<br>Negate the @in docker@ filter.
-
-h4. Reusing jobs
-
-Because Arvados records the exact version of the script, input parameters, and runtime environment that was used to run the job, if the script is deterministic (meaning that the same code version is guaranteed to produce the same outputs from the same inputs) then it is possible to re-use the results of past jobs, and avoid re-running the computation to save time.  Arvados uses the following algorithm to determine if a past job can be re-used:
-
-notextile. <div class="spaced-out">
-
-# If @find_or_create@ is false or omitted, create a new job and skip the rest of these steps.
-# If @filters@ are specified, find jobs that match those filters. If any filters are given, there must be at least one filter on the @repository@ attribute and one on the @script@ attribute: otherwise an error is returned.
-# If @filters@ are not specified, find jobs with the same @repository@ and @script@, with a @script_version@ between @minimum_script_version@ and @script_version@ inclusively (excluding @excluded_script_versions@), and a @docker_image_locator@ with the latest Collection that matches the submitted job's @docker_image@ constraint.  If the submitted job includes an @arvados_sdk_version@ constraint, jobs must have an @arvados_sdk_version@ between that refspec and HEAD to be found. *This form is deprecated: use filters instead.*
-# If the found jobs include a completed job, and all found completed jobs have consistent output, return one of them.  Which specific job is returned is undefined.
-# If the found jobs only include incomplete jobs, return one of them.  Which specific job is returned is undefined.
-# If no job has been returned so far, create and return a new job.
-
-</div>
-
-h4. Examples
-
-Run the script "crunch_scripts/hash.py" in the repository "you" using the "main" commit.  Arvados should re-use a previous job if the script_version of the previous job is the same as the current "main" commit. This works irrespective of whether the previous job was submitted using the name "main", a different branch name or tag indicating the same commit, a SHA-1 commit hash, etc.
-
-<notextile><pre>
-{
-  "job": {
-    "script": "hash.py",
-    "repository": "<b>you</b>/<b>you</b>",
-    "script_version": "main",
-    "script_parameters": {
-      "input": "c1bad4b39ca5a924e481008009d94e32+210"
-    }
-  },
-  "find_or_create": true
-}
-</pre></notextile>
-
-Run using exactly the version "d00220fb38d4b85ca8fc28a8151702a2b9d1dec5". Arvados should re-use a previous job if the "script_version" of that job is also "d00220fb38d4b85ca8fc28a8151702a2b9d1dec5".
-
-<notextile><pre>
-{
-  "job": {
-    "script": "hash.py",
-    "repository": "<b>you</b>/<b>you</b>",
-    "script_version": "d00220fb38d4b85ca8fc28a8151702a2b9d1dec5",
-    "script_parameters": {
-      "input": "c1bad4b39ca5a924e481008009d94e32+210"
-    }
-  },
-  "find_or_create": true
-}
-</pre></notextile>
-
-Arvados should re-use a previous job if the "script_version" of the previous job is between "earlier_version_tag" and the "main" commit (inclusive), but not the commit indicated by "blacklisted_version_tag". If there are no previous jobs matching these criteria, run the job using the "main" commit.
-
-<notextile><pre>
-{
-  "job": {
-    "script": "hash.py",
-    "repository": "<b>you</b>/<b>you</b>",
-    "script_version": "main",
-    "script_parameters": {
-      "input": "c1bad4b39ca5a924e481008009d94e32+210"
-    }
-  },
-  "minimum_script_version": "earlier_version_tag",
-  "exclude_script_versions": ["blacklisted_version_tag"],
-  "find_or_create": true
-}
-</pre></notextile>
-
-The same behavior, using filters:
-
-<notextile><pre>
-{
-  "job": {
-    "script": "hash.py",
-    "repository": "<b>you</b>/<b>you</b>",
-    "script_version": "main",
-    "script_parameters": {
-      "input": "c1bad4b39ca5a924e481008009d94e32+210"
-    }
-  },
-  "filters": [["script", "=", "hash.py"],
-              ["repository", "=", "<b>you</b>/<b>you</b>"],
-              ["script_version", "in git", "earlier_version_tag"],
-              ["script_version", "not in git", "blacklisted_version_tag"]],
-  "find_or_create": true
-}
-</pre></notextile>
-
-Run the script "crunch_scripts/monte-carlo.py" in the repository "you/you" using the current "main" commit. Because it is marked as "nondeterministic", this job will not be considered as a suitable candidate for future job submissions that use the "find_or_create" feature.
-
-<notextile><pre>
-{
-  "job": {
-    "script": "monte-carlo.py",
-    "repository": "<b>you</b>/<b>you</b>",
-    "script_version": "main",
-    "nondeterministic": true,
-    "script_parameters": {
-      "input": "c1bad4b39ca5a924e481008009d94e32+210"
-    }
-  }
-}
-</pre></notextile>
-
-h3. delete
-
-Delete an existing Job.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Job in question.|path||
-
-h3. get
-
-Gets a Job's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Job in question.|path||
-
-h3. list
-
-List jobs.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-See the create method documentation for more information about Job-specific filters.
-
-h3. log_tail_follow
-
-log_tail_follow jobs
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string||path||
-|buffer_size|integer (default 8192)||query||
-
-h3. queue
-
-Get the current job queue.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|order|string||query||
-|filters|array||query||
-
-This method is equivalent to the "list method":#list, except that the results are restricted to queued jobs (i.e., jobs that have not yet been started or cancelled) and order defaults to queue priority.
-
-h3. update
-
-Update attributes of an existing Job.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Job in question.|path||
-|job|object||query||
diff --git a/doc/api/methods/keep_disks.html.textile.liquid b/doc/api/methods/keep_disks.html.textile.liquid
deleted file mode 100644 (file)
index 9a82a3e..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "keep_disks"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "keep services.":keep_services.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/keep_disks@
-
-Object type: @penuu@
-
-Example UUID: @zzzzz-penuu-0123456789abcde@
-
-h2. Resource
-
-Obsoleted by "keep_services":{{site.baseurl}}/api/methods/keep_services.html
-
-Each KeepDisk has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|ping_secret|string|||
-|node_uuid|string|||
-|filesystem_uuid|string|||
-|bytes_total|integer|||
-|bytes_free|integer|||
-|is_readable|boolean|||
-|is_writable|boolean|||
-|last_read_at|datetime|||
-|last_write_at|datetime|||
-|last_ping_at|datetime|||
-|keep_service_uuid|string|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new KeepDisk.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|keep_disk|object||query||
-
-h3. delete
-
-Delete an existing KeepDisk.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the KeepDisk in question.|path||
-
-h3. get
-
-Gets a KeepDisk's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the KeepDisk in question.|path||
-
-h3. list
-
-List keep_disks.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. ping
-
-ping keep_disks
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|ping_secret|string||query||
-{background:#ccffcc}.|service_port|string||query||
-{background:#ccffcc}.|service_ssl_flag|string||query||
-|filesystem_uuid|string||query||
-|node_uuid|string||query||
-|service_host|string||query||
-|uuid|string||query||
-
-h3. update
-
-Update attributes of an existing KeepDisk.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the KeepDisk in question.|path||
-|keep_disk|object||query||
diff --git a/doc/api/methods/nodes.html.textile.liquid b/doc/api/methods/nodes.html.textile.liquid
deleted file mode 100644 (file)
index b29527c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "nodes"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "cloud dispatcher API.":../dispatch.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/nodes@
-
-Object type: @7ekkf@
-
-Example UUID: @zzzzz-7ekkf-0123456789abcde@
-
-h2. Resource
-
-Node resources list compute nodes on which Crunch may schedule work.
-
-Each Node has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|slot_number|integer|||
-|hostname|string|||
-|domain|string|||
-|ip_address|string|||
-|job_uuid|string|The UUID of the job that this node is assigned to work on.  If you do not have permission to read the job, this will be null.||
-|first_ping_at|datetime|||
-|last_ping_at|datetime|||
-|info|hash|Sensitive information about the node (only visible to admin) such as 'ping_secret' and 'ec2_instance_id'. May be used in queries using "subproperty filters":{{site.baseurl}}/api/methods.html#subpropertyfilters||
-|properties|hash|Public information about the node, such as 'total_cpu_cores', 'total_ram_mb', and 'total_scratch_mb'.  May be used in queries using "subproperty filters":{{site.baseurl}}/api/methods.html#subpropertyfilters||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new Node.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|node|object||query||
-
-h3. delete
-
-Delete an existing Node.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Node in question.|path||
-
-h3. get
-
-Gets a Node's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Node in question.|path||
-
-h3. list
-
-List nodes.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. ping
-
-Process a ping from a compute node.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|ping_secret|string||query||
-{background:#ccffcc}.|uuid|string||path||
-
-h3. update
-
-Update attributes of an existing Node.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Node in question.|path||
-|node|object||query||
-
-To remove a node's job assignment, update the node object's @job_uuid@ to null.
diff --git a/doc/api/methods/pipeline_instances.html.textile.liquid b/doc/api/methods/pipeline_instances.html.textile.liquid
deleted file mode 100644 (file)
index e19dfba..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "pipeline_instances"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "container requests.":container_requests.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_instances@
-
-Object type: @d1hrv@
-
-Example UUID: @zzzzz-d1hrv-0123456789abcde@
-
-h2. Resource
-
-Deprecated.  A pipeline instance is a collection of jobs managed by @arvados-run-pipeline-instance@.
-
-Each PipelineInstance has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|pipeline_template_uuid|string|The "pipeline template":pipeline_templates.html that this instance was created from.||
-|name|string|||
-|components|hash|||
-|success|boolean|||
-|active|boolean|||
-|properties|Hash|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new PipelineInstance.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|pipeline_instance|object||query||
-
-h3. delete
-
-Delete an existing PipelineInstance.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineInstance in question.|path||
-
-h3. get
-
-Gets a PipelineInstance's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineInstance in question.|path||
-
-h3. list
-
-List pipeline_instances.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing PipelineInstance.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineInstance in question.|path||
-|pipeline_instance|object||query||
diff --git a/doc/api/methods/pipeline_templates.html.textile.liquid b/doc/api/methods/pipeline_templates.html.textile.liquid
deleted file mode 100644 (file)
index ddbe8ad..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "pipeline_templates"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "registered workflows.":workflows.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_templates@
-
-Object type: @p5p6p@
-
-Example UUID: @zzzzz-p5p6p-0123456789abcde@
-
-h2. Resource
-
-Deprecated.  A pipeline template is a collection of jobs that can be instantiated as a pipeline_instance.
-
-Each PipelineTemplate has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|name|string|||
-|components|hash|||
-
-The pipeline template consists of "name" and "components".
-
-table(table table-bordered table-condensed).
-|_. Attribute    |_. Type |_. Accepted values                           |_. Required|_. Description|
-|name            |string  |any                                          |yes        |The human-readable name of the pipeline template.|
-|components      |object  |JSON object containing job submission objects|yes        |The component jobs that make up the pipeline, with the component name as the key. |
-
-h3. Components
-
-The components field of the pipeline template is a JSON object which describes the individual steps that make up the pipeline.  Each component is an Arvados job submission.  "Parameters for job submissions are described on the job method page.":{{site.baseurl}}/api/methods/jobs.html#create  In addition, a component can have the following parameters:
-
-table(table table-bordered table-condensed).
-|_. Attribute    |_. Type          |_. Accepted values |_. Required|_. Description|
-|output_name     |string or boolean|string or false    |no         |If a string is provided, use this name for the output collection of this component.  If the value is false, do not create a permanent output collection (an temporary intermediate collection will still be created).  If not provided, a default name will be assigned to the output.|
-
-h3. Script parameters
-
-When used in a pipeline, each parameter in the 'script_parameters' attribute of a component job can specify that the input parameter must be supplied by the user, or the input parameter should be linked to the output of another component.  To do this, the value of the parameter should be JSON object containing one of the following attributes:
-
-table(table table-bordered table-condensed).
-|_. Attribute    |_. Type |_. Accepted values                               |_. Description|
-|default         |any     |any                                              |The default value for this parameter.|
-|required        |boolean |true or false                                    |Specifies whether the parameter is required to have a value or not.|
-|dataclass       |string  |One of 'Collection', 'File' [1], 'number', or 'text' |Data type of this parameter.|
-|search_for      |string  |any string                                       |Substring to use as a default search string when choosing inputs.|
-|output_of       |string  |the name of another component in the pipeline    |Specifies that the value of this parameter should be set to the 'output' attribute of the job that corresponds to the specified component.|
-|title           |string  |any string                                       |User friendly title to display when choosing parameter values|
-|description     |string  |any string                                       |Extended text description for describing expected/valid values for the script parameter|
-|link_name       |string  |any string                                       |User friendly name to display for the parameter value instead of the actual parameter value|
-
-The 'output_of' parameter is especially important, as this is how components are actually linked together to form a pipeline.  Component jobs that depend on the output of other components do not run until the parent job completes and has produced output.  If the parent job fails, the entire pipeline fails.
-
-fn1. The 'File' type refers to a specific file within a Keep collection in the form 'collection_hash/filename', for example '887cd41e9c613463eab2f0d885c6dd96+83/bob.txt'.
-
-The 'search_for' parameter is meaningful only when input dataclass of type Collection or File is used. If a value is provided, this will be preloaded into the input data chooser dialog in Workbench. For example, if your input dataclass is a File and you are interested in a certain filename extention, you can preconfigure it in this attribute.
-
-h3. Examples
-
-This is a pipeline named "Filter MD5 hash values" with two components, "do_hash" and "filter".  The "input" script parameter of the "do_hash" component is required to be filled in by the user, and the expected data type is "Collection".  This also specifies that the "input" script parameter of the "filter" component is the output of "do_hash", so "filter" will not run until "do_hash" completes successfully.  When the pipeline runs, past jobs that meet the criteria described above may be substituted for either or both components to avoid redundant computation.
-
-<notextile><pre>
-{
-  "name": "Filter MD5 hash values",
-  "components": {
-    "do_hash": {
-      "script": "hash.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": {
-        "input": {
-          "required": true,
-          "dataclass": "Collection",
-          "search_for": ".fastq.gz",
-          "title":"Please select a fastq file"
-        }
-      },
-    },
-    "filter": {
-      "script": "0-filter.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": {
-        "input": {
-          "output_of": "do_hash"
-        }
-      },
-    }
-  }
-}
-</pre></notextile>
-
-This pipeline consists of three components.  The components "thing1" and "thing2" both depend on "cat_in_the_hat".  Once the "cat_in_the_hat" job is complete, both "thing1" and "thing2" can run in parallel, because they do not depend on each other.
-
-<notextile><pre>
-{
-  "name": "Wreck the house",
-  "components": {
-    "cat_in_the_hat": {
-      "script": "cat.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": { }
-    },
-    "thing1": {
-      "script": "thing1.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": {
-        "input": {
-          "output_of": "cat_in_the_hat"
-        }
-      },
-    },
-    "thing2": {
-      "script": "thing2.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": {
-        "input": {
-          "output_of": "cat_in_the_hat"
-        }
-      },
-    },
-  }
-}
-</pre></notextile>
-
-This pipeline consists of three components.  The component "cleanup" depends on "thing1" and "thing2".  Both "thing1" and "thing2" are started immediately and can run in parallel, because they do not depend on each other, but "cleanup" cannot begin until both "thing1" and "thing2" have completed.
-
-<notextile><pre>
-{
-  "name": "Clean the house",
-  "components": {
-    "thing1": {
-      "script": "thing1.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": { }
-    },
-    "thing2": {
-      "script": "thing2.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": { }
-    },
-    "cleanup": {
-      "script": "cleanup.py",
-      "repository": "<b>you</b>/<b>you</b>",
-      "script_version": "main",
-      "script_parameters": {
-        "mess1": {
-          "output_of": "thing1"
-        },
-        "mess2": {
-          "output_of": "thing2"
-        }
-      }
-    }
-  }
-}
-</pre></notextile>
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new PipelineTemplate.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|pipeline_template|object||query||
-
-h3. delete
-
-Delete an existing PipelineTemplate.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineTemplate in question.|path||
-
-h3. get
-
-Gets a PipelineTemplate's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineTemplate in question.|path||
-
-h3. list
-
-List pipeline_templates.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing PipelineTemplate.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the PipelineTemplate in question.|path||
-|pipeline_template|object||query||
diff --git a/doc/api/methods/repositories.html.textile.liquid b/doc/api/methods/repositories.html.textile.liquid
deleted file mode 100644 (file)
index b2b2cab..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "repositories"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and slated to be removed entirely in a future major release of Arvados.  It is replaced by "collection versioning.":collections.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/repositories@
-
-Object type: @s0uqq@
-
-Example UUID: @zzzzz-s0uqq-0123456789abcde@
-
-h2. Resource
-
-The repositories resource lists git repositories managed by Arvados.
-
-Each Repository has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|name|string|The name of the repository on disk.  Repository names must begin with a letter and contain only alphanumerics.  Unless the repository is owned by the system user, the name must begin with the owner's username, then be separated from the base repository name with @/@.  You may not create a repository that is owned by a user without a username.|@username/project1@|
-|clone_urls|array|URLs from which the repository can be cloned. Read-only.|@["git@git.zzzzz.arvadosapi.com:foo/bar.git",
- "https://git.zzzzz.arvadosapi.com/foo/bar.git"]@|
-|fetch_url|string|URL suggested as a fetch-url in git config. Deprecated. Read-only.||
-|push_url|string|URL suggested as a push-url in git config. Deprecated. Read-only.||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new Repository.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|repository|object||query||
-
-h3. delete
-
-Delete an existing Repository.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Repository in question.|path||
-
-h3. get
-
-Gets a Repository's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Repository in question.|path||
-
-h3. get_all_permissions
-
-get_all_permissions repositories
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-
-h3. list
-
-List repositories.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing Repository.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Repository in question.|path||
-|repository|object||query||
diff --git a/doc/api/methods/specimens.html.textile.liquid b/doc/api/methods/specimens.html.textile.liquid
deleted file mode 100644 (file)
index 3820eeb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "specimens"
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and is slated to be removed entirely in a future major release of Arvados.  The recommended way to store metadata is with "'properties' field on collections and projects.":../properties.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/specimens@
-
-Object type: @j58dm@
-
-Example UUID: @zzzzz-j58dm-0123456789abcde@
-
-h2. Resource
-
-A metadata record that may be used to represent a biological specimen.
-
-Each Specimen has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|material|string|||
-|properties|hash|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new Specimen.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|specimen|object||query||
-
-h3. delete
-
-Delete an existing Specimen.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Specimen in question.|path||
-
-h3. get
-
-Gets a Specimen's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Specimen in question.|path||
-
-h3. list
-
-List specimens.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing Specimen.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Specimen in question.|path||
-|specimen|object||query||
diff --git a/doc/api/methods/traits.html.textile.liquid b/doc/api/methods/traits.html.textile.liquid
deleted file mode 100644 (file)
index 4e356b9..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
----
-layout: default
-navsection: api
-navmenu: API Methods
-title: "traits"
-
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This is a legacy API.  This endpoint is deprecated, disabled by default in new installations, and is slated to be removed entirely in a future major release of Arvados.  The recommended way to store metadata is with "'properties' field on collections and projects.":../properties.html
-{% include 'notebox_end' %}
-
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/traits@
-
-Object type: @q1cn2@
-
-Example UUID: @zzzzz-q1cn2-0123456789abcde@
-
-h2. Resource
-
-A metadata record that may be used to represent a genotype or phenotype trait.
-
-Each Trait has, in addition to the "Common resource fields":{{site.baseurl}}/api/resources.html:
-
-table(table table-bordered table-condensed).
-|_. Attribute|_. Type|_. Description|_. Example|
-|name|string|||
-|properties|hash|||
-
-h2. Methods
-
-See "Common resource methods":{{site.baseurl}}/api/methods.html for more information about @create@, @delete@, @get@, @list@, and @update@.
-
-Required arguments are displayed in %{background:#ccffcc}green%.
-
-h3. create
-
-Create a new Trait.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-|trait|object||query||
-
-h3. delete
-
-Delete an existing Trait.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Trait in question.|path||
-
-h3. get
-
-Gets a Trait's metadata by UUID.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Trait in question.|path||
-
-h3. list
-
-List traits.
-
-See "common resource list method.":{{site.baseurl}}/api/methods.html#index
-
-h3. update
-
-Update attributes of an existing Trait.
-
-Arguments:
-
-table(table table-bordered table-condensed).
-|_. Argument |_. Type |_. Description |_. Location |_. Example |
-{background:#ccffcc}.|uuid|string|The UUID of the Trait in question.|path||
-|trait|object||query||
index f5405c16e17cb84a7f082c2daa563aede25f5569..230a9be8f5244045640a1e433a8348fbe40e4bc9 100644 (file)
@@ -19,7 +19,6 @@ Located in @arvados/services@.
 table(table table-bordered table-condensed).
 |_. Component|_. Description|
 |api|The API server is the core of Arvados.  It is backed by a Postgres database and manages information such as metadata for storage, a record of submitted compute jobs, users, groups, and associated permissions.|
-|arvados-git-httpd|Provides a git+http interface to Arvados-managed git repositories, with permissions and authentication based on an Arvados API token.|
 |arvados-dispatch-cloud|Provide elastic computing by creating and destroying cloud based virtual machines on compute demand.|
 |crunch-dispatch-local|Get compute requests submitted to the API server and execute them locally.|
 |crunch-dispatch-slurm|Get compute requests submitted to the API server and submit them to slurm.|
diff --git a/doc/images/add-new-repository.png b/doc/images/add-new-repository.png
deleted file mode 100644 (file)
index d62a986..0000000
Binary files a/doc/images/add-new-repository.png and /dev/null differ
index 20e1c48eeea5d98ae067484ab6c1877bf67df7df..7265e2d5ccad5308195537a95e8eb675fa19ba9c 100644 (file)
@@ -28,7 +28,7 @@ $ <span class="userinput">./arvbox start localdemo</span>
 
 Arvados-in-a-box starting
 
-Waiting for workbench2 websockets workbench webshell keep-web controller keepproxy api keepstore1 arv-git-httpd keepstore0 sdk vm ...
+Waiting for workbench2 websockets workbench webshell keep-web controller keepproxy api keepstore1 keepstore0 sdk vm ...
 
 ...
 
diff --git a/doc/install/install-arv-git-httpd.html.textile.liquid b/doc/install/install-arv-git-httpd.html.textile.liquid
deleted file mode 100644 (file)
index 476c890..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
----
-layout: default
-navsection: installguide
-title: Install the Git server
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-# "Introduction":#introduction
-# "Install dependencies":#dependencies
-# "Create "git" user and storage directory":#create
-# "Install gitolite":#gitolite
-# "Configure gitolite":#config-gitolite
-# "Configure git synchronization":#sync
-# "Update config.yml":#update-config
-# "Update nginx configuration":#update-nginx
-# "Install arvados-git-httpd package":#install-packages
-# "Restart the API server and controller":#restart-api
-# "Confirm working installation":#confirm-working
-
-h2(#introduction). Introduction
-
-Arvados support for git repository management enables using Arvados permissions to control access to git repositories.  Users can create their own private and public git repositories and share them with others.
-
-The git hosting setup involves three components.
-* The "arvados-git-sync.rb" script polls the API server for the current list of repositories, creates bare repositories, and updates the local permission cache used by gitolite.
-* Gitolite provides SSH access.  Users authenticate by SSH keys.
-* arvados-git-http provides HTTPS access.  Users authenticate by Arvados tokens.
-
-Git services must be installed on the same host as the Arvados Rails API server.
-
-h2(#dependencies). Install dependencies
-
-h3. Alma/CentOS/Red Hat/Rocky
-
-<notextile>
-<pre><code># <span class="userinput">dnf install git perl-Data-Dumper openssh-server</span>
-</code></pre>
-</notextile>
-
-h3. Debian and Ubuntu
-
-<notextile>
-<pre><code># <span class="userinput">apt-get --no-install-recommends install git openssh-server</span>
-</code></pre>
-</notextile>
-
-h2(#create). Create "git" user and storage directory
-
-Gitolite and some additional scripts will be installed in @/var/lib/arvados/git@, which means hosted repository data will be stored in @/var/lib/arvados/git/repositories@. If you choose to install gitolite in a different location, make sure to update the @git_repositories_dir@ entry in your API server's @application.yml@ file accordingly: for example, if you install gitolite at @/data/gitolite@ then your @git_repositories_dir@ will be @/data/gitolite/repositories@.
-
-A new UNIX account called "git" will own the files. This makes git URLs look familiar to users (<code>git@[...]:username/reponame.git</code>).
-
-On Debian- or Red Hat-based systems:
-
-<notextile>
-<pre><code>gitserver:~$ <span class="userinput">sudo mkdir -p /var/lib/arvados/git</span>
-gitserver:~$ <span class="userinput">sudo useradd --comment git --home-dir /var/lib/arvados/git git</span>
-gitserver:~$ <span class="userinput">sudo chown -R git:git ~git</span>
-</code></pre>
-</notextile>
-
-The git user needs its own SSH key. (It must be able to run <code>ssh git@localhost</code> from scripts.)
-
-<notextile>
-<pre><code>gitserver:~$ <span class="userinput">sudo -u git -i bash</span>
-git@gitserver:~$ <span class="userinput">ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa</span>
-git@gitserver:~$ <span class="userinput">cp .ssh/id_rsa.pub .ssh/authorized_keys</span>
-git@gitserver:~$ <span class="userinput">ssh -o stricthostkeychecking=no localhost cat .ssh/id_rsa.pub</span>
-Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7aBIDAAgMQN16Pg6eHmvc+D+6TljwCGr4YGUBphSdVb25UyBCeAEgzqRiqy0IjQR2BLtSirXr+1SJAcQfBgI/jwR7FG+YIzJ4ND9JFEfcpq20FvWnMMQ6XD3y3xrZ1/h/RdBNwy4QCqjiXuxDpDB7VNP9/oeAzoATPZGhqjPfNS+RRVEQpC6BzZdsR+S838E53URguBOf9yrPwdHvosZn7VC0akeWQerHqaBIpSfDMtaM4+9s1Gdsz0iP85rtj/6U/K/XOuv2CZsuVZZ52nu3soHnEX2nx2IaXMS3L8Z+lfOXB2T6EaJgXF7Z9ME5K1tx9TSNTRcYCiKztXLNLSbp git@gitserver
-git@gitserver:~$ <span class="userinput">rm .ssh/authorized_keys</span>
-</code></pre>
-</notextile>
-
-h2(#gitolite). Install gitolite
-
-Check "https://github.com/sitaramc/gitolite/tags":https://github.com/sitaramc/gitolite/tags for the latest stable version. This guide was tested with @v3.6.11@. _Versions below 3.0 are missing some features needed by Arvados, and should not be used._
-
-Download and install the version you selected.
-
-<notextile>
-<pre><code>$ <span class="userinput">sudo -u git -i bash</span>
-git@gitserver:~$ <span class="userinput">echo 'PATH=$HOME/bin:$PATH' &gt;.profile</span>
-git@gitserver:~$ <span class="userinput">. .profile</span>
-git@gitserver:~$ <span class="userinput">git clone --branch <b>v3.6.11</b> https://github.com/sitaramc/gitolite</span>
-...
-Note: checking out '5d24ae666bfd2fa9093d67c840eb8d686992083f'.
-...
-git@gitserver:~$ <span class="userinput">mkdir bin</span>
-git@gitserver:~$ <span class="userinput">gitolite/install -ln ~git/bin</span>
-git@gitserver:~$ <span class="userinput">bin/gitolite setup -pk .ssh/id_rsa.pub</span>
-Initialized empty Git repository in /var/lib/arvados/git/repositories/gitolite-admin.git/
-Initialized empty Git repository in /var/lib/arvados/git/repositories/testing.git/
-WARNING: /var/lib/arvados/git/.ssh/authorized_keys missing; creating a new one
-    (this is normal on a brand new install)
-</code></pre>
-</notextile>
-
-_If this didn't go well, more detail about installing gitolite, and information about how it works, can be found on the "gitolite home page":http://gitolite.com/._
-
-Clone the gitolite-admin repository. The arvados-git-sync.rb script works by editing the files in this working directory and pushing them to gitolite. Here we make sure "git push" won't produce any errors or warnings.
-
-<notextile>
-<pre><code>git@gitserver:~$ <span class="userinput">git clone git@localhost:gitolite-admin</span>
-Cloning into 'gitolite-admin'...
-remote: Counting objects: 6, done.
-remote: Compressing objects: 100% (4/4), done.
-remote: Total 6 (delta 0), reused 0 (delta 0)
-Receiving objects: 100% (6/6), done.
-Checking connectivity... done.
-git@gitserver:~$ <span class="userinput">cd gitolite-admin</span>
-git@gitserver:~/gitolite-admin$ <span class="userinput">git config user.email arvados</span>
-git@gitserver:~/gitolite-admin$ <span class="userinput">git config user.name arvados</span>
-git@gitserver:~/gitolite-admin$ <span class="userinput">git config push.default simple</span>
-git@gitserver:~/gitolite-admin$ <span class="userinput">git push</span>
-Everything up-to-date
-</code></pre>
-</notextile>
-
-h2(#config-gitolite). Configure gitolite
-
-Configure gitolite to look up a repository name like @username/reponame.git@ and find the appropriate bare repository storage directory.
-
-Add the following lines to the top of @~git/.gitolite.rc@:
-
-<notextile>
-<pre><code><span class="userinput">my $repo_aliases;
-my $aliases_src = "$ENV{HOME}/.gitolite/arvadosaliases.pl";
-if ($ENV{HOME} && (-e $aliases_src)) {
-    $repo_aliases = do $aliases_src;
-}
-$repo_aliases ||= {};
-</span></code></pre>
-</notextile>
-
-Add the following lines inside the section that begins @%RC = (@:
-
-<notextile>
-<pre><code><span class="userinput">    REPO_ALIASES => $repo_aliases,
-</span></code></pre>
-</notextile>
-
-Inside that section, adjust the 'UMASK' setting to @022@, to ensure the API server has permission to read repositories:
-
-<notextile>
-<pre><code>    UMASK => <span class="userinput">022</span>,
-</code></pre>
-</notextile>
-
-Uncomment the 'Alias' line in the section that begins @ENABLE => [@:
-
-<notextile>
-<pre><code><span class="userinput">            # access a repo by another (possibly legacy) name
-            'Alias',
-</span></code></pre>
-</notextile>
-
-h2(#sync). Configure git synchronization
-
-Create a configuration file @/var/www/arvados-api/current/config/arvados-clients.yml@ using the following template, filling in the appropriate values for your system.
-* For @arvados_api_token@, use @SystemRootToken@
-* For @gitolite_arvados_git_user_key@, provide the public key you generated above, i.e., the contents of @~git/.ssh/id_rsa.pub@.
-
-<notextile>
-<pre><code>production:
-  gitolite_url: /var/lib/arvados/git/repositories/gitolite-admin.git
-  gitolite_tmp: /var/lib/arvados/git
-  arvados_api_host: <span class="userinput">ClusterID.example.com</span>
-  arvados_api_token: "<span class="userinput">zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz</span>"
-  arvados_api_host_insecure: <span class="userinput">false</span>
-  gitolite_arvados_git_user_key: "<span class="userinput">ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7aBIDAAgMQN16Pg6eHmvc+D+6TljwCGr4YGUBphSdVb25UyBCeAEgzqRiqy0IjQR2BLtSirXr+1SJAcQfBgI/jwR7FG+YIzJ4ND9JFEfcpq20FvWnMMQ6XD3y3xrZ1/h/RdBNwy4QCqjiXuxDpDB7VNP9/oeAzoATPZGhqjPfNS+RRVEQpC6BzZdsR+S838E53URguBOf9yrPwdHvosZn7VC0akeWQerHqaBIpSfDMtaM4+9s1Gdsz0iP85rtj/6U/K/XOuv2CZsuVZZ52nu3soHnEX2nx2IaXMS3L8Z+lfOXB2T6EaJgXF7Z9ME5K1tx9TSNTRcYCiKztXLNLSbp git@gitserver</span>"
-</code></pre>
-</notextile>
-
-<pre>
-$ sudo chown git:git /var/www/arvados-api/current/config/arvados-clients.yml
-$ sudo chmod og-rwx /var/www/arvados-api/current/config/arvados-clients.yml
-</pre>
-
-h3. Test configuration
-
-notextile. <pre><code>$ <span class="userinput">sudo -u git -i bash -c 'cd /var/www/arvados-api/current && bin/bundle exec script/arvados-git-sync.rb production'</span></code></pre>
-
-h3. Enable the synchronization script
-
-The API server package includes a script that retrieves the current set of repository names and permissions from the API, writes them to @arvadosaliases.pl@ in a format usable by gitolite, and triggers gitolite hooks which create new empty repositories if needed. This script should run every 2 to 5 minutes.
-
-Create @/etc/cron.d/arvados-git-sync@ with the following content:
-
-<notextile>
-<pre><code><span class="userinput">*/5 * * * * git cd /var/www/arvados-api/current && bin/bundle exec script/arvados-git-sync.rb production</span>
-</code></pre>
-</notextile>
-
-h2(#update-config). Update config.yml
-
-Edit the cluster config at @config.yml@ .
-
-<notextile>
-<pre><code>    Services:
-      GitSSH:
-        ExternalURL: "<span class="userinput">ssh://git@git.ClusterID.example.com</span>"
-      GitHTTP:
-        ExternalURL: <span class="userinput">https://git.ClusterID.example.com/</span>
-        InternalURLs:
-         "http://localhost:9001": {}
-    Git:
-      GitCommand: <span class="userinput">/var/lib/arvados/git/gitolite/src/gitolite-shell</span>
-      GitoliteHome: <span class="userinput">/var/lib/arvados/git</span>
-      Repositories: <span class="userinput">/var/lib/arvados/git/repositories</span>
-</code></pre>
-</notextile>
-
-h2(#update-nginx). Update nginx configuration
-
-Use a text editor to create a new file @/etc/nginx/conf.d/arvados-git.conf@ with the following configuration.  Options that need attention are marked in <span class="userinput">red</span>.
-
-<notextile>
-<pre><code>upstream arvados-git-httpd {
-  server                  127.0.0.1:<span class="userinput">9001</span>;
-}
-server {
-  listen                  443 ssl;
-  server_name             git.<span class="userinput">ClusterID.example.com</span>;
-  proxy_connect_timeout   90s;
-  proxy_read_timeout      300s;
-
-  ssl_certificate         <span class="userinput">/YOUR/PATH/TO/cert.pem</span>;
-  ssl_certificate_key     <span class="userinput">/YOUR/PATH/TO/cert.key</span>;
-
-  # The server needs to accept potentially large refpacks from push clients.
-  client_max_body_size 128m;
-
-  location  / {
-    proxy_pass            http://arvados-git-httpd;
-  }
-}
-</code></pre>
-</notextile>
-
-h2(#install-packages). Install the arvados-git-httpd package
-
-The arvados-git-httpd package provides HTTP access, using Arvados authentication tokens instead of passwords. It must be installed on the system where your git repositories are stored.
-
-h3. Alma/CentOS/Red Hat/Rocky
-
-<notextile>
-<pre><code># <span class="userinput">dnf install arvados-git-httpd</span>
-</code></pre>
-</notextile>
-
-h3. Debian and Ubuntu
-
-<notextile>
-<pre><code># <span class="userinput">apt-get --no-install-recommends install arvados-git-httpd</span>
-</code></pre>
-</notextile>
-
-h2(#restart-api). Restart the API server and controller
-
-After adding Workbench to the Services section, make sure the cluster config file is up to date on the API server host, and restart the API server and controller processes to ensure the changes are applied.
-
-<notextile>
-<pre><code># <span class="userinput">systemctl restart nginx arvados-controller</span>
-</code></pre>
-</notextile>
-
-h2(#confirm-working). Confirm working installation
-
-Create 'testrepo' in the Arvados database.
-
-<notextile>
-<pre><code>~$ <span class="userinput">arv --format=uuid repository create --repository '{"name":"myusername/testrepo"}'</span>
-</code></pre></notextile>
-
-The arvados-git-sync cron job will notice the new repository record and create a repository on disk.  Because it is on a timer (default 5 minutes) you may have to wait a minute or two for it to show up.
-
-h3. SSH
-
-Before you do this, go to Workbench and choose *SSH Keys* from the menu, and upload your public key.  Arvados uses the public key to identify you when you access the git repo.
-
-<notextile>
-<pre><code>~$ <span class="userinput">git clone git@git.ClusterID.example.com:username/testrepo.git</span>
-</code></pre>
-</notextile>
-
-h3. HTTP
-
-Set up git credential helpers as described in "install shell server":install-shell-server.html#config-git for the git command to use your API token instead of prompting you for a username and password.
-
-<notextile>
-<pre><code>~$ <span class="userinput">git clone https://git.ClusterID.example.com/username/testrepo.git</span>
-</code></pre>
-</notextile>
diff --git a/doc/install/install-composer.html.textile.liquid b/doc/install/install-composer.html.textile.liquid
deleted file mode 100644 (file)
index 58ba5d0..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
----
-layout: default
-navsection: installguide
-title: Install Composer
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-Arvados Composer is a web-based javascript application for building Common Workflow Languge (CWL) Workflows.
-
-# "Install dependencies":#dependencies
-# "Update config.yml":#update-config
-# "Update Nginx configuration":#update-nginx
-# "Install arvados-composer":#install-packages
-# "Restart the API server and controller":#restart-api
-# "Confirm working installation":#confirm-working
-
-h2(#dependencies). Install dependencies
-
-In addition to Arvados core services, Composer requires "Arvados hosted git repositories":install-arv-git-httpd.html which are used for storing workflow files.
-
-h2(#configure). Update config.yml
-
-Edit @config.yml@ and set @Services.Composer.ExternalURL@ to the location from which it is served:
-
-<notextile>
-<pre><code>    Services:
-      Composer:
-        ExternalURL: <span class="userinput">https://workbench.CusterID.example.com/composer</span></code></pre>
-</notextile>
-
-h2(#update-nginx). Update nginx configuration
-
-Composer may be served from the same host as Workbench.  Composer communicates directly with the Arvados API server.  It does not require its own backend and should be served as a static file.
-
-Add the following @location@ sections to @/etc/nginx/conf.d/arvados-workbench.conf@ .
-
-<notextile>
-<pre><code>server {
-  [...]
-
-  location /composer {
-    root   /var/www/arvados-composer;
-    index  index.html;
-  }
-
-  location /composer/composer.yml {
-    return 200 '{ "API_HOST": "<span class="userinput">ClusterID.example.com</span>" }';
-  }
-}
-</code></pre>
-</notextile>
-
-{% assign arvados_component = 'arvados-composer' %}
-
-{% include 'install_packages' %}
-
-{% include 'restart_api' %}
-
-h2(#confirm-working). Confirm working installation
-
-Visit @https://workbench.ClusterID.example.com/composer@ in a browser.  You should be able to log in using the login method you configured previously.
diff --git a/doc/install/install-jobs-image.html.textile.liquid b/doc/install/install-jobs-image.html.textile.liquid
deleted file mode 100644 (file)
index efd8c96..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
----
-layout: default
-navsection: installguide
-title: Install arvados/jobs image
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-h2. Create a project for Docker images
-
-Here we create a default project for the standard Arvados Docker images, and give all users read access to it. The project is owned by the system user.
-
-<notextile>
-<pre><code>~$ <span class="userinput">uuid_prefix=$(arv --format=uuid user current | cut -d- -f1)</span>
-~$ <span class="userinput">project_uuid=$(arv --format=uuid group create --group '{"owner_uuid":"'$uuid_prefix'-tpzed-000000000000000", "group_class":"project", "name":"Arvados Standard Docker Images"}')</span>
-~$ <span class="userinput">echo "Arvados project uuid is '$project_uuid'"</span>
-~$ <span class="userinput">read -rd $'\000' newlink &lt;&lt;EOF; arv link create --link "$newlink"</span>
-<span class="userinput">{
- "tail_uuid":"${uuid_prefix}-j7d0g-fffffffffffffff",
- "head_uuid":"$project_uuid",
- "link_class":"permission",
- "name":"can_read"
-}
-EOF</span>
-</code></pre></notextile>
-
-h2. Import the arvados/jobs docker image
-
-In order to start workflows from workbench, there needs to be Docker image @arvados/jobs@ tagged with the version of Arvados you are installing. The following command downloads the latest arvados/jobs image from Docker Hub, loads it into Keep.  In this example @$project_uuid@ should be the UUID of the "Arvados Standard Docker Images" project.
-
-<notextile>
-<pre><code>~$ <span class="userinput">arv-keepdocker --pull arvados/jobs latest --project-uuid $project_uuid</span>
-</code></pre></notextile>
-
-If the image needs to be downloaded from Docker Hub, the command can take a few minutes to complete, depending on available network bandwidth.
index 8819b0210f94609fc883eb2c55be05ce5a98c575..ba179f82ddc9bd92a870acba0e1176396f4aab7c 100644 (file)
@@ -47,7 +47,6 @@ table(table table-bordered table-condensed).
 |\3=. *Additional services*|
 |"Websockets server":install-ws.html |Event distribution server.|Required to view streaming container logs in Workbench.|
 |"Shell server":install-shell-server.html |Grant Arvados users access to Unix shell accounts on dedicated shell nodes.|Optional.|
-|"Git server":install-arv-git-httpd.html |Arvados-hosted git repositories, with Arvados-token based authentication.|Optional|
 |\3=. *Crunch (running containers)*|
 |"arvados-dispatch-cloud":crunch2-cloud/install-dispatch-cloud.html |Run analysis workflows on cloud by allocating and freeing cloud VM instances on demand.|Optional|
 |"crunch-dispatch-slurm":crunch2-slurm/install-dispatch.html |Run analysis workflows distributed across a Slurm cluster.|Optional|
@@ -96,7 +95,7 @@ For a production installation, this is a reasonable starting point:
 <div class="offset1">
 table(table table-bordered table-condensed).
 |_. Function|_. Number of nodes|_. Recommended specs|
-|PostgreSQL database, Arvados API server, Arvados controller, Git, Websockets, Container dispatcher|1|16+ GiB RAM, 4+ cores, fast disk for database|
+|PostgreSQL database, Arvados API server, Arvados controller, Websockets, Container dispatcher|1|16+ GiB RAM, 4+ cores, fast disk for database|
 |Workbench, Keepproxy, Keep-web, Keep-balance|1|8 GiB RAM, 2+ cores|
 |Keepstore servers ^1^|2+|4 GiB RAM|
 |Compute worker nodes ^1^|0+ |Depends on workload; scaled dynamically in the cloud|
@@ -138,7 +137,6 @@ It is possible to use custom DNS names for the Arvados services.
 table(table table-bordered table-condensed).
 |_. Function|_. DNS name|
 |Arvados API|@ClusterID.example.com@|
-|Arvados Git server|git.@ClusterID.example.com@|
 |Arvados Webshell|webshell.@ClusterID.example.com@|
 |Arvados Websockets endpoint|ws.@ClusterID.example.com@|
 |Arvados Workbench|workbench.@ClusterID.example.com@|
index f864f37563ba42b83cb8e7c54fbfcae2c425b3e6..9520c08397dfb650cfebbc2941756129e0cd580b 100644 (file)
@@ -12,7 +12,6 @@ SPDX-License-Identifier: CC-BY-SA-3.0
 # "Introduction":#introduction
 # "Install Dependencies and SDKs":#dependencies
 # "Install git and curl":#install-packages
-# "Update Git Config":#config-git
 # "Create record for VM":#vm-record
 # "Install arvados-login-sync":#arvados-login-sync
 # "Confirm working installation":#confirm-working
@@ -44,17 +43,6 @@ h2(#dependencies). Install Dependencies and SDKs
 
 {% include 'install_packages' %}
 
-h2(#config-git). Update Git Config
-
-Configure git to use the ARVADOS_API_TOKEN environment variable to authenticate to arvados-git-httpd. We use the @--system@ flag so it takes effect for all current and future user accounts. It does not affect git's behavior when connecting to other git servers.
-
-<notextile>
-<pre>
-<code># <span class="userinput">git config --system 'credential.https://git.<b>ClusterID.example.com</b>/.username' none</span></code>
-<code># <span class="userinput">git config --system 'credential.https://git.<b>ClusterID.example.com</b>/.helper' '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'</span></code>
-</pre>
-</notextile>
-
 h2(#vm-record). Create record for VM
 
 As an admin, create an Arvados virtual_machine object representing this shell server. This will return a uuid.
index ea10c830bc44006363d6270e91cb9bf951b40c38..827f1d08768fae86085cae8b44c35d620ffa0fff 100644 (file)
@@ -31,12 +31,12 @@ Available flags:
 Use 'arv subcommand|resource --help' to get more information about a particular
 command or resource.
 
-Available subcommands: copy, create, edit, keep, pipeline, run, tag, ws
+Available subcommands: copy, create, edit, keep, run, tag, ws
 
-Available resources: api_client_authorization, api_client, authorized_key,
-collection, user_agreement, group, job_task, link, log, keep_disk,
-pipeline_instance, node, repository, specimen, pipeline_template, user,
-virtual_machine, trait, human, job, keep_service
+Available resources: api_client_authorization, api_client,
+authorized_key, collection, container, container_request,
+user_agreement, group, keep_service, link, log, user, virtual_machine,
+workflow
 
 Additional options:
   -e, --version       Print version and exit
diff --git a/doc/user/tutorials/add-new-repository.html.textile.liquid b/doc/user/tutorials/add-new-repository.html.textile.liquid
deleted file mode 100644 (file)
index 6046e7d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
----
-layout: default
-navsection: userguide
-title: Adding a new Arvados git repository
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-Arvados supports managing git repositories. You can access these repositories using your Arvados credentials and share them with other Arvados users.
-
-{% include 'tutorial_expectations' %}
-
-h2. Setting up Git
-
-Before you start using Git and arvados repositories, you should do some basic configuration (you only need to do this the first time):
-
-<notextile>
-<pre><code>~$ <span class="userinput">git config --global user.name "Your Name"</span>
-~$ <span class="userinput">git config --global user.email $USER@example.com</span></code></pre>
-</notextile>
-
-h2. Add "tutorial" repository
-
-On the Arvados Workbench, click on the dropdown menu icon <i class="fa fa-lg fa-user"></i> (Account Management) in the upper right corner of the top navigation menu to access the user settings menu, and click on the menu item *Repositories*.
-
-In the *Repositories* page, you will see the <span class="btn btn-sm btn-primary">+ NEW REPOSITORY</span> button.
-
-!{width: 100%;}{{ site.baseurl }}/images/repositories-panel.png!
-
-Click the <span class="btn btn-sm btn-primary">+ NEW REPOSITORY</span> button to open the popup to add a new Arvados repository. You will see a text box where you can enter the name of the repository. Enter *tutorial* in this text box and click on *Create*.
-
-{% include 'notebox_begin' %}
-The name you enter here must begin with a letter and can only contain alphanumeric characters.
-{% include 'notebox_end' %}
-
-!{width: 100%;}{{ site.baseurl }}/images/add-new-repository.png!
-
-This will create a new repository with the name @$USER/tutorial@. It can be accessed using the URL <notextile><code>https://git.{{ site.arvados_api_host }}/$USER/tutorial.git</code></notextile> or <notextile><code>git@git.{{ site.arvados_api_host }}:$USER/tutorial.git</code></notextile>
-
-Back in the *Repositories* page, you should see the @$USER/tutorial@ repository listed in the name column with these URLs.
-
-!{display: block;margin-left: 25px;margin-right: auto;}{{ site.baseurl }}/images/added-new-repository.png!
-
-You are now ready to use this *tutorial* repository to run your crunch scripts.
diff --git a/doc/user/tutorials/git-arvados-guide.html.textile.liquid b/doc/user/tutorials/git-arvados-guide.html.textile.liquid
deleted file mode 100644 (file)
index a4ac2a5..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
----
-layout: default
-navsection: userguide
-title: Working with an Arvados git repository
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-This tutorial describes how to work with an Arvados-managed git repository. Working with an Arvados git repository is very similar to working with other public git repositories.
-
-{% include 'tutorial_expectations' %}
-
-{% include 'tutorial_git_repo_expectations' %}
-
-h2. Cloning a git repository
-
-Before you start using Git, you should do some basic configuration (you only need to do this the first time):
-
-<notextile>
-<pre><code>~$ <span class="userinput">git config --global user.name "Your Name"</span>
-~$ <span class="userinput">git config --global user.email $USER@example.com</span></code></pre>
-</notextile>
-
-On the Arvados Workbench, click on the dropdown menu icon <i class="fa fa-lg fa-user"></i> in the upper right corner of the top navigation menu to access the Account Management menu, and click on the menu item *Repositories*. In the *Repositories* page, you should see the @$USER/tutorial@ repository listed in the *name* column.  Next to *name* is the column *URL*. Copy the *URL* value associated with your repository.  This should look like <notextile><code>https://git.{{ site.arvados_api_host }}/$USER/tutorial.git</code></notextile>. Alternatively, you can use <notextile><code>git@git.{{ site.arvados_api_host }}:$USER/tutorial.git</code></notextile>
-
-Next, on the Arvados virtual machine, clone your Git repository:
-
-<notextile>
-<pre><code>~$ <span class="userinput">cd $HOME</span> # (or wherever you want to install)
-~$ <span class="userinput">git clone https://git.{{ site.arvados_api_host }}/$USER/tutorial.git</span>
-Cloning into 'tutorial'...</code></pre>
-</notextile>
-
-This will create a Git repository in the directory called @tutorial@ in your home directory. Say yes when prompted to continue with connection.
-Ignore any warning that you are cloning an empty repository.
-
-*Note:* If you are prompted for username and password when you try to git clone using this command, you may first need to update your git configuration. Execute the following commands to update your git configuration.
-
-<notextile>
-<pre>
-<code>~$ <span class="userinput">git config 'credential.https://git.{{ site.arvados_api_host }}/.username' none</span></code>
-<code>~$ <span class="userinput">git config 'credential.https://git.{{ site.arvados_api_host }}/.helper' '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'</span></code>
-</pre>
-</notextile>
-
-h2. Creating a git branch in an Arvados repository
-
-Create a git branch named *tutorial_branch* in the *tutorial* Arvados git repository.
-
-<notextile>
-<pre><code>~$ <span class="userinput">cd tutorial</span>
-~/tutorial$ <span class="userinput">git checkout -b tutorial_branch</span>
-</code></pre>
-</notextile>
-
-h2. Adding scripts to an Arvados repository
-
-A git repository is a good place to store the CWL workflows that you run on Arvados.
-
-First, create a simple CWL CommandLineTool:
-
-notextile. <pre>~/tutorials$ <code class="userinput">nano hello.cwl</code></pre>
-
-<notextile> {% code tutorial_hello_cwl as yaml %} </notextile>
-
-Next, add the file to the git repository.  This tells @git@ that the file should be included on the next commit.
-
-notextile. <pre><code>~/tutorial$ <span class="userinput">git add hello.cwl</span></code></pre>
-
-Next, commit your changes.  All staged changes are recorded into the local git repository:
-
-<notextile>
-<pre><code>~/tutorial$ <span class="userinput">git commit -m "my first script"</span>
-</code></pre>
-</notextile>
-
-Finally, upload your changes to the remote repository:
-
-<notextile>
-<pre><code>~/tutorial/crunch_scripts$ <span class="userinput">git push origin tutorial_branch</span>
-</code></pre>
-</notextile>
-
-The same steps can be used to add any of your custom bash, R, or python scripts to an Arvados repository.
index 9f1091eac39177f15855de7b7e8ccf2b0ac443f3..338a6b5bcc494b1fdfbcd50c3263fed119ceb916 100644 (file)
@@ -74,7 +74,6 @@ func (runNginx) Run(ctx context.Context, fail func(error), super *Supervisor) er
                {"KEEPWEB", super.cluster.Services.WebDAV},
                {"KEEPWEBDL", super.cluster.Services.WebDAVDownload},
                {"KEEPPROXY", super.cluster.Services.Keepproxy},
-               {"GIT", super.cluster.Services.GitHTTP},
                {"HEALTH", super.cluster.Services.Health},
                {"WORKBENCH1", super.cluster.Services.Workbench1},
                {"WORKBENCH2", super.cluster.Services.Workbench2},
@@ -135,7 +134,7 @@ func (runNginx) Run(ctx context.Context, fail func(error), super *Supervisor) er
                }
        }
 
-       configs := "error_log stderr info; "
+       configs := "error_log stderr warn; "
        configs += "pid " + filepath.Join(super.wwwtempdir, "nginx.pid") + "; "
        configs += "user www-data; "
 
index ac269b933abd226551441e977e4ce0f3daea896a..67649e75de55132692767184e05cbb932b5f97e1 100644 (file)
@@ -366,7 +366,6 @@ func (super *Supervisor) runCluster() error {
                runNginx{},
                railsDatabase{},
                runServiceCommand{name: "controller", svc: super.cluster.Services.Controller, depends: []supervisedTask{railsDatabase{}}},
-               runServiceCommand{name: "git-httpd", svc: super.cluster.Services.GitHTTP},
                runServiceCommand{name: "health", svc: super.cluster.Services.Health},
                runServiceCommand{name: "keepproxy", svc: super.cluster.Services.Keepproxy, depends: []supervisedTask{runPassenger{src: "services/api"}}},
                runServiceCommand{name: "keepstore", svc: super.cluster.Services.Keepstore},
@@ -821,7 +820,6 @@ func (super *Supervisor) autofillConfig() error {
        for _, svc := range []*arvados.Service{
                &super.cluster.Services.Controller,
                &super.cluster.Services.DispatchCloud,
-               &super.cluster.Services.GitHTTP,
                &super.cluster.Services.Health,
                &super.cluster.Services.Keepproxy,
                &super.cluster.Services.Keepstore,
@@ -839,7 +837,6 @@ func (super *Supervisor) autofillConfig() error {
                        }
                        host := net.JoinHostPort(defaultExtHost, port)
                        if svc == &super.cluster.Services.Controller ||
-                               svc == &super.cluster.Services.GitHTTP ||
                                svc == &super.cluster.Services.Health ||
                                svc == &super.cluster.Services.Keepproxy ||
                                svc == &super.cluster.Services.WebDAV ||
index 14e839a6cd3515a45e0943d13b06ebadc5022d36..b045553b23bd5997c8934422b00ba75b51152dad 100644 (file)
@@ -74,12 +74,6 @@ Clusters:
       Keepbalance:
         InternalURLs: {SAMPLE: {ListenURL: ""}}
         ExternalURL: ""
-      GitHTTP:
-        InternalURLs: {SAMPLE: {ListenURL: ""}}
-        ExternalURL: ""
-      GitSSH:
-        InternalURLs: {SAMPLE: {ListenURL: ""}}
-        ExternalURL: ""
       DispatchCloud:
         InternalURLs: {SAMPLE: {ListenURL: ""}}
         ExternalURL: ""
@@ -340,7 +334,6 @@ Clusters:
       # AutoSetupUsernameBlacklist is a list of usernames to be blacklisted for auto setup.
       AutoSetupNewUsers: false
       AutoSetupNewUsersWithVmUUID: ""
-      AutoSetupNewUsersWithRepository: false
       AutoSetupUsernameBlacklist:
         arvados: {}
         git: {}
@@ -1058,24 +1051,6 @@ Clusters:
       # production use.
       TrustPrivateNetworks: false
 
-    Git:
-      # Path to git or gitolite-shell executable. Each authenticated
-      # request will execute this program with the single argument "http-backend"
-      GitCommand: /usr/bin/git
-
-      # Path to Gitolite's home directory. If a non-empty path is given,
-      # the CGI environment will be set up to support the use of
-      # gitolite-shell as a GitCommand: for example, if GitoliteHome is
-      # "/gh", then the CGI environment will have GITOLITE_HTTP_HOME=/gh,
-      # PATH=$PATH:/gh/bin, and GL_BYPASS_ACCESS_CHECKS=1.
-      GitoliteHome: ""
-
-      # Git repositories must be readable by api server, or you won't be
-      # able to submit crunch jobs. To pass the test suites, put a clone
-      # of the arvados tree in {git_repositories_dir}/arvados.git or
-      # {git_repositories_dir}/arvados/.git
-      Repositories: /var/lib/arvados/git/repositories
-
     TLS:
       # Use "file:///var/lib/acme/live/example.com/cert" and
       # ".../privkey" to load externally managed certificates.
@@ -1335,47 +1310,6 @@ Clusters:
         SbatchArgumentsList: []
         SbatchEnvironmentVariables:
           SAMPLE: ""
-        Managed:
-          # Path to dns server configuration directory
-          # (e.g. /etc/unbound.d/conf.d). If false, do not write any config
-          # files or touch restart.txt (see below).
-          DNSServerConfDir: ""
-
-          # Template file for the dns server host snippets. See
-          # unbound.template in this directory for an example. If false, do
-          # not write any config files.
-          DNSServerConfTemplate: ""
-
-          # String to write to {dns_server_conf_dir}/restart.txt (with a
-          # trailing newline) after updating local data. If false, do not
-          # open or write the restart.txt file.
-          DNSServerReloadCommand: ""
-
-          # Command to run after each DNS update. Template variables will be
-          # substituted; see the "unbound" example below. If false, do not run
-          # a command.
-          DNSServerUpdateCommand: ""
-
-          ComputeNodeDomain: ""
-          ComputeNodeNameservers:
-            "192.168.1.1": {}
-            SAMPLE: {}
-
-          # Hostname to assign to a compute node when it sends a "ping" and the
-          # hostname in its Node record is nil.
-          # During bootstrapping, the "ping" script is expected to notice the
-          # hostname given in the ping response, and update its unix hostname
-          # accordingly.
-          # If false, leave the hostname alone (this is appropriate if your compute
-          # nodes' hostnames are already assigned by some other mechanism).
-          #
-          # One way or another, the hostnames of your node records should agree
-          # with your DNS records and your /etc/slurm-llnl/slurm.conf files.
-          #
-          # Example for compute0000, compute0001, ....:
-          # assign_node_hostname: compute%<slot_number>04d
-          # (See http://ruby-doc.org/core-2.2.2/Kernel.html#method-i-format for more.)
-          AssignNodeHostname: "compute%<slot_number>d"
 
       LSF:
         # Arguments to bsub when submitting Arvados containers as LSF jobs.
@@ -1443,12 +1377,6 @@ Clusters:
         # 'false' -- disable the Jobs API despite presence of existing records.
         Enable: 'auto'
 
-        # Git repositories must be readable by api server, or you won't be
-        # able to submit crunch jobs. To pass the test suites, put a clone
-        # of the arvados tree in {git_repositories_dir}/arvados.git or
-        # {git_repositories_dir}/arvados/.git
-        GitInternalDir: /var/lib/arvados/internal.git
-
       CloudVMs:
         # Enable the cloud scheduler.
         Enable: false
index d518b3414ad193795179f7e9776bccc26fedc129..0db3de7fc99d987cce1cf43dd5a982c590653272 100644 (file)
@@ -510,56 +510,6 @@ func (ldr *Loader) loadOldKeepWebConfig(cfg *arvados.Config) error {
        return nil
 }
 
-const defaultGitHttpdConfigPath = "/etc/arvados/git-httpd/git-httpd.yml"
-
-type oldGitHttpdConfig struct {
-       Client          *arvados.Client
-       Listen          *string
-       GitCommand      *string
-       GitoliteHome    *string
-       RepoRoot        *string
-       ManagementToken *string
-}
-
-func (ldr *Loader) loadOldGitHttpdConfig(cfg *arvados.Config) error {
-       if ldr.GitHttpdPath == "" {
-               return nil
-       }
-       var oc oldGitHttpdConfig
-       err := ldr.loadOldConfigHelper("arvados-git-httpd", ldr.GitHttpdPath, &oc)
-       if os.IsNotExist(err) && ldr.GitHttpdPath == defaultGitHttpdConfigPath {
-               return nil
-       } else if err != nil {
-               return err
-       }
-
-       cluster, err := cfg.GetCluster("")
-       if err != nil {
-               return err
-       }
-
-       loadOldClientConfig(cluster, oc.Client)
-
-       if oc.Listen != nil {
-               cluster.Services.GitHTTP.InternalURLs[arvados.URL{Host: *oc.Listen}] = arvados.ServiceInstance{}
-       }
-       if oc.ManagementToken != nil {
-               cluster.ManagementToken = *oc.ManagementToken
-       }
-       if oc.GitCommand != nil {
-               cluster.Git.GitCommand = *oc.GitCommand
-       }
-       if oc.GitoliteHome != nil {
-               cluster.Git.GitoliteHome = *oc.GitoliteHome
-       }
-       if oc.RepoRoot != nil {
-               cluster.Git.Repositories = *oc.RepoRoot
-       }
-
-       cfg.Clusters[cluster.ClusterID] = *cluster
-       return nil
-}
-
 const defaultKeepBalanceConfigPath = "/etc/arvados/keep-balance/keep-balance.yml"
 
 type oldKeepBalanceConfig struct {
index e06a1f231d96887467759087c14f8fb74b4b3e87..f73a92be5c44c4425aef83a7a8ae76fdba081d92 100644 (file)
@@ -283,52 +283,6 @@ func fmtKeepproxyConfig(param string, debugLog bool) string {
 `, debugLog, param)
 }
 
-func (s *LoadSuite) TestLegacyArvGitHttpdConfig(c *check.C) {
-       content := []byte(`
-{
-       "Client": {
-               "Scheme": "",
-               "APIHost": "example.com",
-               "AuthToken": "abcdefg",
-       },
-       "Listen": ":9000",
-       "GitCommand": "/test/git",
-       "GitoliteHome": "/test/gitolite",
-       "RepoRoot": "/test/reporoot",
-       "ManagementToken": "xyzzy"
-}
-`)
-       f := "-legacy-git-httpd-config"
-       cluster, err := testLoadLegacyConfig(content, f, c)
-
-       c.Assert(err, check.IsNil)
-       c.Assert(cluster, check.NotNil)
-       c.Check(cluster.Services.Controller.ExternalURL, check.Equals, arvados.URL{Scheme: "https", Host: "example.com", Path: "/"})
-       c.Check(cluster.SystemRootToken, check.Equals, "abcdefg")
-       c.Check(cluster.ManagementToken, check.Equals, "xyzzy")
-       c.Check(cluster.Git.GitCommand, check.Equals, "/test/git")
-       c.Check(cluster.Git.GitoliteHome, check.Equals, "/test/gitolite")
-       c.Check(cluster.Git.Repositories, check.Equals, "/test/reporoot")
-       c.Check(cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: ":9000"}], check.Equals, arvados.ServiceInstance{})
-}
-
-// Tests fix for https://dev.arvados.org/issues/15642
-func (s *LoadSuite) TestLegacyArvGitHttpdConfigDoesntDisableMissingItems(c *check.C) {
-       content := []byte(`
-{
-       "Client": {
-               "Scheme": "",
-               "APIHost": "example.com",
-               "AuthToken": "abcdefg",
-       }
-}
-`)
-       cluster, err := testLoadLegacyConfig(content, "-legacy-git-httpd-config", c)
-       c.Assert(err, check.IsNil)
-       // The resulting ManagementToken should be the one set up on the test server.
-       c.Check(cluster.ManagementToken, check.Equals, TestServerManagementToken)
-}
-
 func (s *LoadSuite) TestLegacyKeepBalanceConfig(c *check.C) {
        f := "-legacy-keepbalance-config"
        content := []byte(fmtKeepBalanceConfig(""))
index f511ebbcb16b1a238f0a5b77fdc85c2de6518367..3c1e6bc00822315967f49320289ba31be09b9fc3 100644 (file)
@@ -59,108 +59,106 @@ func ExportJSON(w io.Writer, cluster *arvados.Cluster) error {
 // exists.
 var whitelist = map[string]bool{
        // | sort -t'"' -k2,2
-       "API":                                      true,
-       "API.AsyncPermissionsUpdateInterval":       false,
-       "API.DisabledAPIs":                         false,
-       "API.FreezeProjectRequiresDescription":     true,
-       "API.FreezeProjectRequiresProperties":      true,
-       "API.FreezeProjectRequiresProperties.*":    true,
-       "API.KeepServiceRequestTimeout":            false,
-       "API.LockBeforeUpdate":                     false,
-       "API.LogCreateRequestFraction":             false,
-       "API.MaxConcurrentRailsRequests":           false,
-       "API.MaxConcurrentRequests":                false,
-       "API.MaxGatewayTunnels":                    false,
-       "API.MaxIndexDatabaseRead":                 false,
-       "API.MaxItemsPerResponse":                  true,
-       "API.MaxKeepBlobBuffers":                   false,
-       "API.MaxQueuedRequests":                    false,
-       "API.MaxQueueTimeForLockRequests":          false,
-       "API.MaxRequestAmplification":              false,
-       "API.MaxRequestSize":                       true,
-       "API.MaxTokenLifetime":                     false,
-       "API.RequestTimeout":                       true,
-       "API.SendTimeout":                          true,
-       "API.UnfreezeProjectRequiresAdmin":         true,
-       "API.VocabularyPath":                       false,
-       "API.WebsocketClientEventQueue":            false,
-       "API.WebsocketServerEventQueue":            false,
-       "AuditLogs":                                false,
-       "AuditLogs.MaxAge":                         false,
-       "AuditLogs.MaxDeleteBatch":                 false,
-       "AuditLogs.UnloggedAttributes":             false,
-       "ClusterID":                                true,
-       "Collections":                              true,
-       "Collections.BalanceCollectionBatch":       false,
-       "Collections.BalanceCollectionBuffers":     false,
-       "Collections.BalancePeriod":                false,
-       "Collections.BalancePullLimit":             false,
-       "Collections.BalanceTimeout":               false,
-       "Collections.BalanceTrashLimit":            false,
-       "Collections.BalanceUpdateLimit":           false,
-       "Collections.BlobDeleteConcurrency":        false,
-       "Collections.BlobMissingReport":            false,
-       "Collections.BlobReplicateConcurrency":     false,
-       "Collections.BlobSigning":                  true,
-       "Collections.BlobSigningKey":               false,
-       "Collections.BlobSigningTTL":               true,
-       "Collections.BlobTrash":                    false,
-       "Collections.BlobTrashCheckInterval":       false,
-       "Collections.BlobTrashConcurrency":         false,
-       "Collections.BlobTrashLifetime":            false,
-       "Collections.CollectionVersioning":         true,
-       "Collections.DefaultReplication":           true,
-       "Collections.DefaultTrashLifetime":         true,
-       "Collections.ForwardSlashNameSubstitution": true,
-       "Collections.KeepproxyPermission":          false,
-       "Collections.ManagedProperties":            true,
-       "Collections.ManagedProperties.*":          true,
-       "Collections.ManagedProperties.*.*":        true,
-       "Collections.PreserveVersionIfIdle":        true,
-       "Collections.S3FolderObjects":              true,
-       "Collections.TrashSweepInterval":           false,
-       "Collections.TrustAllContent":              true,
-       "Collections.WebDAVCache":                  false,
-       "Collections.WebDAVLogEvents":              false,
-       "Collections.WebDAVOutputBuffer":           false,
-       "Collections.WebDAVPermission":             false,
-       "Containers":                               true,
-       "Containers.AlwaysUsePreemptibleInstances": true,
-       "Containers.CloudVMs":                      false,
-       "Containers.CrunchRunArgumentsList":        false,
-       "Containers.CrunchRunCommand":              false,
-       "Containers.DefaultKeepCacheRAM":           true,
-       "Containers.DispatchPrivateKey":            false,
-       "Containers.JobsAPI":                       true,
-       "Containers.JobsAPI.Enable":                true,
-       "Containers.JobsAPI.GitInternalDir":        false,
-       "Containers.LocalKeepBlobBuffersPerVCPU":   false,
-       "Containers.LocalKeepLogsToContainerLog":   false,
-       "Containers.Logging":                       false,
-       "Containers.LogReuseDecisions":             false,
-       "Containers.LSF":                           false,
-       "Containers.MaxDispatchAttempts":           false,
-       "Containers.MaximumPriceFactor":            true,
-       "Containers.MaxRetryAttempts":              true,
-       "Containers.MinRetryPeriod":                true,
-       "Containers.PreemptiblePriceFactor":        false,
-       "Containers.ReserveExtraRAM":               true,
-       "Containers.RuntimeEngine":                 true,
-       "Containers.ShellAccess":                   true,
-       "Containers.ShellAccess.Admin":             true,
-       "Containers.ShellAccess.User":              true,
-       "Containers.SLURM":                         false,
-       "Containers.StaleLockTimeout":              false,
-       "Containers.SupportedDockerImageFormats":   true,
-       "Containers.SupportedDockerImageFormats.*": true,
-       "Git":                                  false,
-       "InstanceTypes":                        true,
-       "InstanceTypes.*":                      true,
-       "InstanceTypes.*.*":                    true,
-       "InstanceTypes.*.*.*":                  true,
-       "Login":                                true,
-       "Login.Google":                         true,
-       "Login.Google.AlternateEmailAddresses": false,
+       "API":                                                 true,
+       "API.AsyncPermissionsUpdateInterval":                  false,
+       "API.DisabledAPIs":                                    false,
+       "API.FreezeProjectRequiresDescription":                true,
+       "API.FreezeProjectRequiresProperties":                 true,
+       "API.FreezeProjectRequiresProperties.*":               true,
+       "API.KeepServiceRequestTimeout":                       false,
+       "API.LockBeforeUpdate":                                false,
+       "API.LogCreateRequestFraction":                        false,
+       "API.MaxConcurrentRailsRequests":                      false,
+       "API.MaxConcurrentRequests":                           false,
+       "API.MaxGatewayTunnels":                               false,
+       "API.MaxIndexDatabaseRead":                            false,
+       "API.MaxItemsPerResponse":                             true,
+       "API.MaxKeepBlobBuffers":                              false,
+       "API.MaxQueuedRequests":                               false,
+       "API.MaxQueueTimeForLockRequests":                     false,
+       "API.MaxRequestAmplification":                         false,
+       "API.MaxRequestSize":                                  true,
+       "API.MaxTokenLifetime":                                false,
+       "API.RequestTimeout":                                  true,
+       "API.SendTimeout":                                     true,
+       "API.UnfreezeProjectRequiresAdmin":                    true,
+       "API.VocabularyPath":                                  false,
+       "API.WebsocketClientEventQueue":                       false,
+       "API.WebsocketServerEventQueue":                       false,
+       "AuditLogs":                                           false,
+       "AuditLogs.MaxAge":                                    false,
+       "AuditLogs.MaxDeleteBatch":                            false,
+       "AuditLogs.UnloggedAttributes":                        false,
+       "ClusterID":                                           true,
+       "Collections":                                         true,
+       "Collections.BalanceCollectionBatch":                  false,
+       "Collections.BalanceCollectionBuffers":                false,
+       "Collections.BalancePeriod":                           false,
+       "Collections.BalancePullLimit":                        false,
+       "Collections.BalanceTimeout":                          false,
+       "Collections.BalanceTrashLimit":                       false,
+       "Collections.BalanceUpdateLimit":                      false,
+       "Collections.BlobDeleteConcurrency":                   false,
+       "Collections.BlobMissingReport":                       false,
+       "Collections.BlobReplicateConcurrency":                false,
+       "Collections.BlobSigning":                             true,
+       "Collections.BlobSigningKey":                          false,
+       "Collections.BlobSigningTTL":                          true,
+       "Collections.BlobTrash":                               false,
+       "Collections.BlobTrashCheckInterval":                  false,
+       "Collections.BlobTrashConcurrency":                    false,
+       "Collections.BlobTrashLifetime":                       false,
+       "Collections.CollectionVersioning":                    true,
+       "Collections.DefaultReplication":                      true,
+       "Collections.DefaultTrashLifetime":                    true,
+       "Collections.ForwardSlashNameSubstitution":            true,
+       "Collections.KeepproxyPermission":                     false,
+       "Collections.ManagedProperties":                       true,
+       "Collections.ManagedProperties.*":                     true,
+       "Collections.ManagedProperties.*.*":                   true,
+       "Collections.PreserveVersionIfIdle":                   true,
+       "Collections.S3FolderObjects":                         true,
+       "Collections.TrashSweepInterval":                      false,
+       "Collections.TrustAllContent":                         true,
+       "Collections.WebDAVCache":                             false,
+       "Collections.WebDAVLogEvents":                         false,
+       "Collections.WebDAVOutputBuffer":                      false,
+       "Collections.WebDAVPermission":                        false,
+       "Containers":                                          true,
+       "Containers.AlwaysUsePreemptibleInstances":            true,
+       "Containers.CloudVMs":                                 false,
+       "Containers.CrunchRunArgumentsList":                   false,
+       "Containers.CrunchRunCommand":                         false,
+       "Containers.DefaultKeepCacheRAM":                      true,
+       "Containers.DispatchPrivateKey":                       false,
+       "Containers.JobsAPI":                                  true,
+       "Containers.JobsAPI.Enable":                           true,
+       "Containers.LocalKeepBlobBuffersPerVCPU":              false,
+       "Containers.LocalKeepLogsToContainerLog":              false,
+       "Containers.Logging":                                  false,
+       "Containers.LogReuseDecisions":                        false,
+       "Containers.LSF":                                      false,
+       "Containers.MaxDispatchAttempts":                      false,
+       "Containers.MaximumPriceFactor":                       true,
+       "Containers.MaxRetryAttempts":                         true,
+       "Containers.MinRetryPeriod":                           true,
+       "Containers.PreemptiblePriceFactor":                   false,
+       "Containers.ReserveExtraRAM":                          true,
+       "Containers.RuntimeEngine":                            true,
+       "Containers.ShellAccess":                              true,
+       "Containers.ShellAccess.Admin":                        true,
+       "Containers.ShellAccess.User":                         true,
+       "Containers.SLURM":                                    false,
+       "Containers.StaleLockTimeout":                         false,
+       "Containers.SupportedDockerImageFormats":              true,
+       "Containers.SupportedDockerImageFormats.*":            true,
+       "InstanceTypes":                                       true,
+       "InstanceTypes.*":                                     true,
+       "InstanceTypes.*.*":                                   true,
+       "InstanceTypes.*.*.*":                                 true,
+       "Login":                                               true,
+       "Login.Google":                                        true,
+       "Login.Google.AlternateEmailAddresses":                false,
        "Login.Google.AuthenticationRequestParameters":        false,
        "Login.Google.ClientID":                               false,
        "Login.Google.ClientSecret":                           false,
@@ -243,7 +241,6 @@ var whitelist = map[string]bool{
        "Users.AutoAdminFirstUser":                            false,
        "Users.AutoAdminUserWithEmail":                        false,
        "Users.AutoSetupNewUsers":                             false,
-       "Users.AutoSetupNewUsersWithRepository":               false,
        "Users.AutoSetupNewUsersWithVmUUID":                   false,
        "Users.AutoSetupUsernameBlacklist":                    false,
        "Users.CanCreateRoleGroups":                           true,
index d504f7796c323f12598a0af4429e289390e22e52..00c8e286832f0f0c3a593c41cf08e919a054ad32 100644 (file)
@@ -48,7 +48,6 @@ type Loader struct {
        CrunchDispatchSlurmPath string
        WebsocketPath           string
        KeepproxyPath           string
-       GitHttpdPath            string
        KeepBalancePath         string
 
        configdata []byte
@@ -88,7 +87,6 @@ func (ldr *Loader) SetupFlags(flagset *flag.FlagSet) {
                flagset.StringVar(&ldr.CrunchDispatchSlurmPath, "legacy-crunch-dispatch-slurm-config", defaultCrunchDispatchSlurmConfigPath, "Legacy crunch-dispatch-slurm configuration `file`")
                flagset.StringVar(&ldr.WebsocketPath, "legacy-ws-config", defaultWebsocketConfigPath, "Legacy arvados-ws configuration `file`")
                flagset.StringVar(&ldr.KeepproxyPath, "legacy-keepproxy-config", defaultKeepproxyConfigPath, "Legacy keepproxy configuration `file`")
-               flagset.StringVar(&ldr.GitHttpdPath, "legacy-git-httpd-config", defaultGitHttpdConfigPath, "Legacy arvados-git-httpd configuration `file`")
                flagset.StringVar(&ldr.KeepBalancePath, "legacy-keepbalance-config", defaultKeepBalanceConfigPath, "Legacy keep-balance configuration `file`")
                flagset.BoolVar(&ldr.SkipLegacy, "skip-legacy", false, "Don't load legacy config files")
        }
@@ -168,9 +166,6 @@ func (ldr *Loader) MungeLegacyConfigArgs(lgr logrus.FieldLogger, args []string,
        if legacyConfigArg != "-legacy-keepproxy-config" {
                ldr.KeepproxyPath = ""
        }
-       if legacyConfigArg != "-legacy-git-httpd-config" {
-               ldr.GitHttpdPath = ""
-       }
        if legacyConfigArg != "-legacy-keepbalance-config" {
                ldr.KeepBalancePath = ""
        }
@@ -296,7 +291,6 @@ func (ldr *Loader) Load() (*arvados.Config, error) {
                        ldr.loadOldCrunchDispatchSlurmConfig,
                        ldr.loadOldWebsocketConfig,
                        ldr.loadOldKeepproxyConfig,
-                       ldr.loadOldGitHttpdConfig,
                        ldr.loadOldKeepBalanceConfig,
                )
        }
index 949cc56dd24cc34b71a8f7ef8ea7ac1d15df6e29..c2cbfec008fc19d7c3615a1f73be512307629226 100644 (file)
@@ -605,26 +605,6 @@ func (conn *Conn) LogDelete(ctx context.Context, options arvados.DeleteOptions)
        return conn.chooseBackend(options.UUID).LogDelete(ctx, options)
 }
 
-func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
-       return conn.generated_SpecimenList(ctx, options)
-}
-
-func (conn *Conn) SpecimenCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Specimen, error) {
-       return conn.chooseBackend(options.ClusterID).SpecimenCreate(ctx, options)
-}
-
-func (conn *Conn) SpecimenUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Specimen, error) {
-       return conn.chooseBackend(options.UUID).SpecimenUpdate(ctx, options)
-}
-
-func (conn *Conn) SpecimenGet(ctx context.Context, options arvados.GetOptions) (arvados.Specimen, error) {
-       return conn.chooseBackend(options.UUID).SpecimenGet(ctx, options)
-}
-
-func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Specimen, error) {
-       return conn.chooseBackend(options.UUID).SpecimenDelete(ctx, options)
-}
-
 func (conn *Conn) SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error) {
        return conn.local.SysTrashSweep(ctx, options)
 }
index 2dc2918f79ec8330dcfbe316af1ec728c3e27f07..079d908f0dba40eb0a64750f2bcb46c22cb3c84f 100644 (file)
@@ -53,7 +53,7 @@ func main() {
                defer out.Close()
                out.Write(regexp.MustCompile(`(?ms)^.*package .*?import.*?\n\)\n`).Find(buf))
                io.WriteString(out, "//\n// -- this file is auto-generated -- do not edit -- edit list.go and run \"go generate\" instead --\n//\n\n")
-               for _, t := range []string{"AuthorizedKey", "Container", "ContainerRequest", "Group", "Specimen", "User", "Link", "Log", "APIClientAuthorization"} {
+               for _, t := range []string{"AuthorizedKey", "Container", "ContainerRequest", "Group", "User", "Link", "Log", "APIClientAuthorization"} {
                        _, err := out.Write(bytes.ReplaceAll(orig, []byte("Collection"), []byte(t)))
                        if err != nil {
                                panic(err)
index 8c8666fea122787d91bf71305421d121e00ae7f9..95f2f650fce0e28b81eba21069f95f5afe6dc682 100755 (executable)
@@ -181,47 +181,6 @@ func (conn *Conn) generated_GroupList(ctx context.Context, options arvados.ListO
        return merged, err
 }
 
-func (conn *Conn) generated_SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
-       var mtx sync.Mutex
-       var merged arvados.SpecimenList
-       var needSort atomic.Value
-       needSort.Store(false)
-       err := conn.splitListRequest(ctx, options, func(ctx context.Context, _ string, backend arvados.API, options arvados.ListOptions) ([]string, error) {
-               options.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor
-               cl, err := backend.SpecimenList(ctx, options)
-               if err != nil {
-                       return nil, err
-               }
-               mtx.Lock()
-               defer mtx.Unlock()
-               if len(merged.Items) == 0 {
-                       merged = cl
-               } else if len(cl.Items) > 0 {
-                       merged.Items = append(merged.Items, cl.Items...)
-                       needSort.Store(true)
-               }
-               uuids := make([]string, 0, len(cl.Items))
-               for _, item := range cl.Items {
-                       uuids = append(uuids, item.UUID)
-               }
-               return uuids, nil
-       })
-       if needSort.Load().(bool) {
-               // Apply the default/implied order, "modified_at desc"
-               sort.Slice(merged.Items, func(i, j int) bool {
-                       mi, mj := merged.Items[i].ModifiedAt, merged.Items[j].ModifiedAt
-                       return mj.Before(mi)
-               })
-       }
-       if merged.Items == nil {
-               // Return empty results as [], not null
-               // (https://github.com/golang/go/issues/27589 might be
-               // a better solution in the future)
-               merged.Items = []arvados.Specimen{}
-       }
-       return merged, err
-}
-
 func (conn *Conn) generated_UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) {
        var mtx sync.Mutex
        var merged arvados.UserList
index eef0443b9a931afa1d5a0160a6cce8e67cc9c419..7d5e693f5b67a45019773adb98c09ebe31befd80 100644 (file)
@@ -568,8 +568,10 @@ func (s *HandlerSuite) CheckObjectType(c *check.C, url string, token string, ski
        req.Header.Set("Authorization", "Bearer "+token)
        resp := httptest.NewRecorder()
        s.handler.ServeHTTP(resp, req)
-       c.Assert(resp.Code, check.Equals, http.StatusOK,
-               check.Commentf("Wasn't able to get data from the controller at %q: %q", url, resp.Body.String()))
+       if !c.Check(resp.Code, check.Equals, http.StatusOK,
+               check.Commentf("Wasn't able to get data from the controller at %q: %q", url, resp.Body.String())) {
+               return
+       }
        err = json.Unmarshal(resp.Body.Bytes(), &proxied)
        c.Check(err, check.Equals, nil)
 
@@ -581,9 +583,11 @@ func (s *HandlerSuite) CheckObjectType(c *check.C, url string, token string, ski
        }
        resp2, err := client.Get(s.cluster.Services.RailsAPI.ExternalURL.String() + url + "/?api_token=" + token)
        c.Check(err, check.Equals, nil)
-       c.Assert(resp2.StatusCode, check.Equals, http.StatusOK,
-               check.Commentf("Wasn't able to get data from the RailsAPI at %q", url))
        defer resp2.Body.Close()
+       if !c.Check(resp2.StatusCode, check.Equals, http.StatusOK,
+               check.Commentf("Wasn't able to get data from the RailsAPI at %q", url)) {
+               return
+       }
        db, err := ioutil.ReadAll(resp2.Body)
        c.Check(err, check.Equals, nil)
        err = json.Unmarshal(db, &direct)
@@ -647,9 +651,7 @@ func (s *HandlerSuite) TestGetObjects(c *check.C) {
                "groups/" + arvadostest.AProjectUUID:                           nil,
                "keep_services/" + ksUUID:                                      nil,
                "links/" + arvadostest.ActiveUserCanReadAllUsersLinkUUID:       nil,
-               "logs/" + arvadostest.CrunchstatForRunningJobLogUUID:           nil,
-               "nodes/" + arvadostest.IdleNodeUUID:                            nil,
-               "repositories/" + arvadostest.ArvadosRepoUUID:                  nil,
+               "logs/" + arvadostest.CrunchstatForRunningContainerLogUUID:     nil,
                "users/" + arvadostest.ActiveUserUUID:                          {"href": true},
                "virtual_machines/" + arvadostest.TestVMUUID:                   nil,
                "workflows/" + arvadostest.WorkflowWithDefinitionYAMLUUID:      nil,
index 45f35a6d2e937b5285fe49308329f9752ed7163b..6b603f178ecb77bffe9f9999f99282e31c6fb66c 100644 (file)
@@ -604,8 +604,6 @@ func (s *IntegrationSuite) TestRequestIDHeader(c *check.C) {
 
        coll, err := conn1.CollectionCreate(userctx1, arvados.CreateOptions{})
        c.Check(err, check.IsNil)
-       specimen, err := conn1.SpecimenCreate(userctx1, arvados.CreateOptions{})
-       c.Check(err, check.IsNil)
 
        tests := []struct {
                path            string
@@ -618,8 +616,6 @@ func (s *IntegrationSuite) TestRequestIDHeader(c *check.C) {
                {"/arvados/v1/nonexistant", true, true},
                {"/arvados/v1/collections/" + coll.UUID, false, false},
                {"/arvados/v1/collections/" + coll.UUID, true, false},
-               {"/arvados/v1/specimens/" + specimen.UUID, false, false},
-               {"/arvados/v1/specimens/" + specimen.UUID, true, false},
                // new code path (lib/controller/router etc) - single-cluster request
                {"/arvados/v1/collections/z1111-4zz18-0123456789abcde", false, true},
                {"/arvados/v1/collections/z1111-4zz18-0123456789abcde", true, true},
@@ -627,8 +623,8 @@ func (s *IntegrationSuite) TestRequestIDHeader(c *check.C) {
                {"/arvados/v1/collections/z2222-4zz18-0123456789abcde", false, true},
                {"/arvados/v1/collections/z2222-4zz18-0123456789abcde", true, true},
                // old code path (proxyRailsAPI) - single-cluster request
-               {"/arvados/v1/specimens/z1111-j58dm-0123456789abcde", false, true},
-               {"/arvados/v1/specimens/z1111-j58dm-0123456789abcde", true, true},
+               {"/arvados/v1/containers/z1111-dz642-0123456789abcde", false, true},
+               {"/arvados/v1/containers/z1111-dz642-0123456789abcde", true, true},
                // old code path (setupProxyRemoteCluster) - federated request
                {"/arvados/v1/workflows/z2222-7fd4e-0123456789abcde", false, true},
                {"/arvados/v1/workflows/z2222-7fd4e-0123456789abcde", true, true},
@@ -830,7 +826,6 @@ func (s *IntegrationSuite) TestFederatedApiClientAuthHandling(c *check.C) {
 // Test for bug #18076
 func (s *IntegrationSuite) TestStaleCachedUserRecord(c *check.C) {
        rootctx1, _, _ := s.super.RootClients("z1111")
-       _, rootclnt3, _ := s.super.RootClients("z3333")
        conn1 := s.super.Conn("z1111")
        conn3 := s.super.Conn("z3333")
 
@@ -842,92 +837,69 @@ func (s *IntegrationSuite) TestStaleCachedUserRecord(c *check.C) {
                        check.Commentf("incorrect LoginCluster config on cluster %q", cls))
        }
 
-       for testCaseNr, testCase := range []struct {
-               name           string
-               withRepository bool
-       }{
-               {"User without local repository", false},
-               {"User with local repository", true},
-       } {
-               c.Log(c.TestName() + " " + testCase.name)
-               // Create some users, request them on the federated cluster so they're cached.
-               var users []arvados.User
-               for userNr := 0; userNr < 2; userNr++ {
-                       _, _, _, user := s.super.UserClients("z1111",
-                               rootctx1,
-                               c,
-                               conn1,
-                               fmt.Sprintf("user%d%d@example.com", testCaseNr, userNr),
-                               true)
-                       c.Assert(user.Username, check.Not(check.Equals), "")
-                       users = append(users, user)
-
-                       lst, err := conn3.UserList(rootctx1, arvados.ListOptions{Limit: -1})
-                       c.Assert(err, check.Equals, nil)
-                       userFound := false
-                       for _, fedUser := range lst.Items {
-                               if fedUser.UUID == user.UUID {
-                                       c.Assert(fedUser.Username, check.Equals, user.Username)
-                                       userFound = true
-                                       break
-                               }
-                       }
-                       c.Assert(userFound, check.Equals, true)
-
-                       if testCase.withRepository {
-                               var repo interface{}
-                               err = rootclnt3.RequestAndDecode(
-                                       &repo, "POST", "arvados/v1/repositories", nil,
-                                       map[string]interface{}{
-                                               "repository": map[string]string{
-                                                       "name":       fmt.Sprintf("%s/test", user.Username),
-                                                       "owner_uuid": user.UUID,
-                                               },
-                                       },
-                               )
-                               c.Assert(err, check.IsNil)
-                       }
-               }
-
-               // Swap the usernames
-               _, err := conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
-                       UUID: users[0].UUID,
-                       Attrs: map[string]interface{}{
-                               "username": "",
-                       },
-               })
-               c.Assert(err, check.Equals, nil)
-               _, err = conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
-                       UUID: users[1].UUID,
-                       Attrs: map[string]interface{}{
-                               "username": users[0].Username,
-                       },
-               })
-               c.Assert(err, check.Equals, nil)
-               _, err = conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
-                       UUID: users[0].UUID,
-                       Attrs: map[string]interface{}{
-                               "username": users[1].Username,
-                       },
-               })
-               c.Assert(err, check.Equals, nil)
+       // Create some users, request them on the federated cluster so they're cached.
+       var users []arvados.User
+       for userNr := 0; userNr < 2; userNr++ {
+               _, _, _, user := s.super.UserClients("z1111",
+                       rootctx1,
+                       c,
+                       conn1,
+                       fmt.Sprintf("user0%d@example.com", userNr),
+                       true)
+               c.Assert(user.Username, check.Not(check.Equals), "")
+               users = append(users, user)
 
-               // Re-request the list on the federated cluster & check for updates
                lst, err := conn3.UserList(rootctx1, arvados.ListOptions{Limit: -1})
                c.Assert(err, check.Equals, nil)
-               var user0Found, user1Found bool
-               for _, user := range lst.Items {
-                       if user.UUID == users[0].UUID {
-                               user0Found = true
-                               c.Assert(user.Username, check.Equals, users[1].Username)
-                       } else if user.UUID == users[1].UUID {
-                               user1Found = true
-                               c.Assert(user.Username, check.Equals, users[0].Username)
+               userFound := false
+               for _, fedUser := range lst.Items {
+                       if fedUser.UUID == user.UUID {
+                               c.Assert(fedUser.Username, check.Equals, user.Username)
+                               userFound = true
+                               break
                        }
                }
-               c.Assert(user0Found, check.Equals, true)
-               c.Assert(user1Found, check.Equals, true)
+               c.Assert(userFound, check.Equals, true)
+       }
+
+       // Swap the usernames
+       _, err := conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
+               UUID: users[0].UUID,
+               Attrs: map[string]interface{}{
+                       "username": "",
+               },
+       })
+       c.Assert(err, check.Equals, nil)
+       _, err = conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
+               UUID: users[1].UUID,
+               Attrs: map[string]interface{}{
+                       "username": users[0].Username,
+               },
+       })
+       c.Assert(err, check.Equals, nil)
+       _, err = conn1.UserUpdate(rootctx1, arvados.UpdateOptions{
+               UUID: users[0].UUID,
+               Attrs: map[string]interface{}{
+                       "username": users[1].Username,
+               },
+       })
+       c.Assert(err, check.Equals, nil)
+
+       // Re-request the list on the federated cluster & check for updates
+       lst, err := conn3.UserList(rootctx1, arvados.ListOptions{Limit: -1})
+       c.Assert(err, check.Equals, nil)
+       var user0Found, user1Found bool
+       for _, user := range lst.Items {
+               if user.UUID == users[0].UUID {
+                       user0Found = true
+                       c.Assert(user.Username, check.Equals, users[1].Username)
+               } else if user.UUID == users[1].UUID {
+                       user1Found = true
+                       c.Assert(user.Username, check.Equals, users[0].Username)
+               }
        }
+       c.Assert(user0Found, check.Equals, true)
+       c.Assert(user1Found, check.Equals, true)
 }
 
 // Test for bug #16263
index 42b34355935db015e72d7de3e8b7a6398ffc0680..97b84df73544f59ac873790041950bdafb156a11 100644 (file)
@@ -143,11 +143,6 @@ var infixMap = map[string]interface{}{
        "xvhdp": arvados.ContainerRequest{},
        "dz642": arvados.Container{},
        "j7d0g": arvados.Group{},
-       "8i9sb": arvados.Job{},
-       "d1hrv": arvados.PipelineInstance{},
-       "p5p6p": arvados.PipelineTemplate{},
-       "j58dm": arvados.Specimen{},
-       "q1cn2": arvados.Trait{},
        "7fd4e": arvados.Workflow{},
 }
 
index 054bcffaf7ecf33b12965bb8e0d0be2d9590e1e0..39c7d871d8e4116694242698f63fcc7ee24e68a3 100644 (file)
@@ -472,41 +472,6 @@ func (rtr *router) addRoutes() {
                                return rtr.backend.LogDelete(ctx, *opts.(*arvados.DeleteOptions))
                        },
                },
-               {
-                       arvados.EndpointSpecimenCreate,
-                       func() interface{} { return &arvados.CreateOptions{} },
-                       func(ctx context.Context, opts interface{}) (interface{}, error) {
-                               return rtr.backend.SpecimenCreate(ctx, *opts.(*arvados.CreateOptions))
-                       },
-               },
-               {
-                       arvados.EndpointSpecimenUpdate,
-                       func() interface{} { return &arvados.UpdateOptions{} },
-                       func(ctx context.Context, opts interface{}) (interface{}, error) {
-                               return rtr.backend.SpecimenUpdate(ctx, *opts.(*arvados.UpdateOptions))
-                       },
-               },
-               {
-                       arvados.EndpointSpecimenGet,
-                       func() interface{} { return &arvados.GetOptions{} },
-                       func(ctx context.Context, opts interface{}) (interface{}, error) {
-                               return rtr.backend.SpecimenGet(ctx, *opts.(*arvados.GetOptions))
-                       },
-               },
-               {
-                       arvados.EndpointSpecimenList,
-                       func() interface{} { return &arvados.ListOptions{Limit: -1} },
-                       func(ctx context.Context, opts interface{}) (interface{}, error) {
-                               return rtr.backend.SpecimenList(ctx, *opts.(*arvados.ListOptions))
-                       },
-               },
-               {
-                       arvados.EndpointSpecimenDelete,
-                       func() interface{} { return &arvados.DeleteOptions{} },
-                       func(ctx context.Context, opts interface{}) (interface{}, error) {
-                               return rtr.backend.SpecimenDelete(ctx, *opts.(*arvados.DeleteOptions))
-                       },
-               },
                {
                        arvados.EndpointAPIClientAuthorizationCreate,
                        func() interface{} { return &arvados.CreateOptions{} },
index c6be679a256cb2e860d5ce179646e3378219d1c6..3125ae29be67ac57966088b6d0951c387c0c6b4e 100644 (file)
@@ -682,41 +682,6 @@ func (conn *Conn) LogDelete(ctx context.Context, options arvados.DeleteOptions)
        return resp, err
 }
 
-func (conn *Conn) SpecimenCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Specimen, error) {
-       ep := arvados.EndpointSpecimenCreate
-       var resp arvados.Specimen
-       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-       return resp, err
-}
-
-func (conn *Conn) SpecimenUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Specimen, error) {
-       ep := arvados.EndpointSpecimenUpdate
-       var resp arvados.Specimen
-       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-       return resp, err
-}
-
-func (conn *Conn) SpecimenGet(ctx context.Context, options arvados.GetOptions) (arvados.Specimen, error) {
-       ep := arvados.EndpointSpecimenGet
-       var resp arvados.Specimen
-       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-       return resp, err
-}
-
-func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
-       ep := arvados.EndpointSpecimenList
-       var resp arvados.SpecimenList
-       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-       return resp, err
-}
-
-func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Specimen, error) {
-       ep := arvados.EndpointSpecimenDelete
-       var resp arvados.Specimen
-       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-       return resp, err
-}
-
 func (conn *Conn) SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error) {
        ep := arvados.EndpointSysTrashSweep
        var resp struct{}
index 0d1200fe12096843c8696a809d7220b4490acff9..ed26e041173e31a1ccbd0493426106d46dfcf40a 100644 (file)
@@ -100,23 +100,24 @@ func (s *RPCSuite) TestCollectionCreate(c *check.C) {
        c.Check(coll.UUID, check.HasLen, 27)
 }
 
-func (s *RPCSuite) TestSpecimenCRUD(c *check.C) {
+func (s *RPCSuite) TestGroupCRUD(c *check.C) {
        s.setupConn(c, os.Getenv("ARVADOS_TEST_API_HOST"))
-       sp, err := s.conn.SpecimenCreate(s.ctx, arvados.CreateOptions{Attrs: map[string]interface{}{
-               "owner_uuid": arvadostest.ActiveUserUUID,
-               "properties": map[string]string{"foo": "bar"},
+       sp, err := s.conn.GroupCreate(s.ctx, arvados.CreateOptions{Attrs: map[string]interface{}{
+               "group_class": "project",
+               "owner_uuid":  arvadostest.ActiveUserUUID,
+               "properties":  map[string]string{"foo": "bar"},
        }})
        c.Check(err, check.IsNil)
        c.Check(sp.UUID, check.HasLen, 27)
        c.Check(sp.Properties, check.HasLen, 1)
        c.Check(sp.Properties["foo"], check.Equals, "bar")
 
-       spGet, err := s.conn.SpecimenGet(s.ctx, arvados.GetOptions{UUID: sp.UUID})
+       spGet, err := s.conn.GroupGet(s.ctx, arvados.GetOptions{UUID: sp.UUID})
        c.Check(err, check.IsNil)
        c.Check(spGet.UUID, check.Equals, sp.UUID)
        c.Check(spGet.Properties["foo"], check.Equals, "bar")
 
-       spList, err := s.conn.SpecimenList(s.ctx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
+       spList, err := s.conn.GroupList(s.ctx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
        c.Check(err, check.IsNil)
        c.Check(spList.ItemsAvailable, check.Equals, 1)
        c.Assert(spList.Items, check.HasLen, 1)
@@ -124,12 +125,12 @@ func (s *RPCSuite) TestSpecimenCRUD(c *check.C) {
        c.Check(spList.Items[0].Properties["foo"], check.Equals, "bar")
 
        anonCtx := context.WithValue(context.Background(), contextKeyTestTokens, []string{arvadostest.AnonymousToken})
-       spList, err = s.conn.SpecimenList(anonCtx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
+       spList, err = s.conn.GroupList(anonCtx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
        c.Check(err, check.IsNil)
        c.Check(spList.ItemsAvailable, check.Equals, 0)
        c.Check(spList.Items, check.HasLen, 0)
 
-       spDel, err := s.conn.SpecimenDelete(s.ctx, arvados.DeleteOptions{UUID: sp.UUID})
+       spDel, err := s.conn.GroupDelete(s.ctx, arvados.DeleteOptions{UUID: sp.UUID})
        c.Check(err, check.IsNil)
        c.Check(spDel.UUID, check.Equals, sp.UUID)
 }
index a3f1d3532010611d40bcecf8488d4fbb985ff2bd..f8941162ec089515fd8ad2708f32e72162bc771e 100644 (file)
@@ -626,17 +626,6 @@ func (runner *ContainerRunner) SetupMounts() (map[string]bindmount, error) {
                                // OutputPath is a staging directory.
                                bindmounts[bind] = bindmount{HostPath: tmpfn, ReadOnly: true}
                        }
-
-               case mnt.Kind == "git_tree":
-                       tmpdir, err := runner.MkTempDir(runner.parentTemp, "git_tree")
-                       if err != nil {
-                               return nil, fmt.Errorf("creating temp dir: %v", err)
-                       }
-                       err = gitMount(mnt).extractTree(runner.containerClient, tmpdir, token)
-                       if err != nil {
-                               return nil, err
-                       }
-                       bindmounts[bind] = bindmount{HostPath: tmpdir, ReadOnly: true}
                }
        }
 
@@ -852,51 +841,36 @@ func (runner *ContainerRunner) LogHostInfo() (err error) {
 
 // LogContainerRecord gets and saves the raw JSON container record from the API server
 func (runner *ContainerRunner) LogContainerRecord() error {
-       logged, err := runner.logAPIResponse("container", "containers", map[string]interface{}{"filters": [][]string{{"uuid", "=", runner.Container.UUID}}}, nil)
+       logged, err := runner.logAPIResponse("container", "containers", map[string]interface{}{"filters": [][]string{{"uuid", "=", runner.Container.UUID}}})
        if !logged && err == nil {
                err = fmt.Errorf("error: no container record found for %s", runner.Container.UUID)
        }
        return err
 }
 
-// LogNodeRecord logs the current host's InstanceType config entry (or
-// the arvados#node record, if running via crunch-dispatch-slurm).
+// LogNodeRecord logs the current host's InstanceType config entry, if
+// running via arvados-dispatch-cloud.
 func (runner *ContainerRunner) LogNodeRecord() error {
-       if it := os.Getenv("InstanceType"); it != "" {
-               // Dispatched via arvados-dispatch-cloud. Save
-               // InstanceType config fragment received from
-               // dispatcher on stdin.
-               w, err := runner.LogCollection.OpenFile("node.json", os.O_CREATE|os.O_WRONLY, 0666)
-               if err != nil {
-                       return err
-               }
-               defer w.Close()
-               _, err = io.WriteString(w, it)
-               if err != nil {
-                       return err
-               }
-               return w.Close()
+       it := os.Getenv("InstanceType")
+       if it == "" {
+               // Not dispatched by arvados-dispatch-cloud.
+               return nil
        }
-       // Dispatched via crunch-dispatch-slurm. Look up
-       // apiserver's node record corresponding to
-       // $SLURMD_NODENAME.
-       hostname := os.Getenv("SLURMD_NODENAME")
-       if hostname == "" {
-               hostname, _ = os.Hostname()
+       // Save InstanceType config fragment received from dispatcher
+       // on stdin.
+       w, err := runner.LogCollection.OpenFile("node.json", os.O_CREATE|os.O_WRONLY, 0666)
+       if err != nil {
+               return err
        }
-       _, err := runner.logAPIResponse("node", "nodes", map[string]interface{}{"filters": [][]string{{"hostname", "=", hostname}}}, func(resp interface{}) {
-               // The "info" field has admin-only info when
-               // obtained with a privileged token, and
-               // should not be logged.
-               node, ok := resp.(map[string]interface{})
-               if ok {
-                       delete(node, "info")
-               }
-       })
-       return err
+       defer w.Close()
+       _, err = io.WriteString(w, it)
+       if err != nil {
+               return err
+       }
+       return w.Close()
 }
 
-func (runner *ContainerRunner) logAPIResponse(label, path string, params map[string]interface{}, munge func(interface{})) (logged bool, err error) {
+func (runner *ContainerRunner) logAPIResponse(label, path string, params map[string]interface{}) (logged bool, err error) {
        writer, err := runner.LogCollection.OpenFile(label+".json", os.O_CREATE|os.O_WRONLY, 0666)
        if err != nil {
                return false, err
@@ -926,9 +900,6 @@ func (runner *ContainerRunner) logAPIResponse(label, path string, params map[str
        } else if len(items) < 1 {
                return false, nil
        }
-       if munge != nil {
-               munge(items[0])
-       }
        // Re-encode it using indentation to improve readability
        enc := json.NewEncoder(w)
        enc.SetIndent("", "    ")
index 276dd366617e71a17bd7acb907a30941459ce7a5..5cb982e1bbf9e5de77df1903f278878212a4d443 100644 (file)
@@ -12,6 +12,7 @@ import (
        "errors"
        "fmt"
        "io"
+       "io/fs"
        "io/ioutil"
        "log"
        "math/rand"
@@ -39,8 +40,6 @@ import (
        "git.arvados.org/arvados.git/sdk/go/manifest"
 
        . "gopkg.in/check.v1"
-       git_client "gopkg.in/src-d/go-git.v4/plumbing/transport/client"
-       git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
 )
 
 // Gocheck boilerplate
@@ -113,6 +112,7 @@ func (s *TestSuite) SetUpTest(c *C) {
        err = ioutil.WriteFile(s.keepmount+"/by_id/"+fakeInputCollectionPDH+"/input.json", []byte(`{"input":true}`), 0644)
        c.Assert(err, IsNil)
        s.runner.ArvMountPoint = s.keepmount
+       os.Setenv("InstanceType", `{"ProviderType":"a1.2xlarge","Price":1.2}`)
 }
 
 type ArvTestClient struct {
@@ -129,8 +129,8 @@ type ArvTestClient struct {
 
 type KeepTestClient struct {
        Called         bool
-       Content        []byte
        StorageClasses []string
+       blocks         sync.Map
 }
 
 type stubExecutor struct {
@@ -358,18 +358,30 @@ func (client *KeepTestClient) LocalLocator(locator string) (string, error) {
 }
 
 func (client *KeepTestClient) BlockWrite(_ context.Context, opts arvados.BlockWriteOptions) (arvados.BlockWriteResponse, error) {
-       client.Content = opts.Data
+       locator := fmt.Sprintf("%x+%d", md5.Sum(opts.Data), len(opts.Data))
+       client.blocks.Store(locator, append([]byte(nil), opts.Data...))
        return arvados.BlockWriteResponse{
-               Locator: fmt.Sprintf("%x+%d", md5.Sum(opts.Data), len(opts.Data)),
+               Locator: locator,
        }, nil
 }
 
-func (client *KeepTestClient) ReadAt(string, []byte, int) (int, error) {
-       return 0, errors.New("not implemented")
+func (client *KeepTestClient) ReadAt(locator string, dst []byte, offset int) (int, error) {
+       loaded, ok := client.blocks.Load(locator)
+       if !ok {
+               return 0, os.ErrNotExist
+       }
+       data := loaded.([]byte)
+       if offset >= len(data) {
+               return 0, io.EOF
+       }
+       return copy(dst, data[offset:]), nil
 }
 
 func (client *KeepTestClient) Close() {
-       client.Content = nil
+       client.blocks.Range(func(locator, value interface{}) bool {
+               client.blocks.Delete(locator)
+               return true
+       })
 }
 
 func (client *KeepTestClient) SetStorageClasses(sc []string) {
@@ -591,7 +603,7 @@ func (ErrorReader) Seek(int64, int) (int64, error) {
        return 0, errors.New("ErrorReader")
 }
 
-func (KeepReadErrorTestClient) ManifestFileReader(m manifest.Manifest, filename string) (arvados.File, error) {
+func (*KeepReadErrorTestClient) ManifestFileReader(m manifest.Manifest, filename string) (arvados.File, error) {
        return ErrorReader{}, nil
 }
 
@@ -1003,9 +1015,8 @@ func (s *TestSuite) TestCrunchstat(c *C) {
 }
 
 func (s *TestSuite) TestNodeInfoLog(c *C) {
-       os.Setenv("SLURMD_NODENAME", "compute2")
        s.fullRunHelper(c, `{
-               "command": ["sleep", "1"],
+               "command": ["true"],
                "container_image": "`+arvadostest.DockerImage112PDH+`",
                "cwd": ".",
                "environment": {},
@@ -1015,18 +1026,17 @@ func (s *TestSuite) TestNodeInfoLog(c *C) {
                "runtime_constraints": {},
                "state": "Locked"
        }`, nil, func() int {
-               time.Sleep(time.Second)
                return 0
        })
 
        c.Check(s.api.CalledWith("container.exit_code", 0), NotNil)
        c.Check(s.api.CalledWith("container.state", "Complete"), NotNil)
 
-       c.Assert(s.api.Logs["node"], NotNil)
-       json := s.api.Logs["node"].String()
-       c.Check(json, Matches, `(?ms).*"uuid": *"zzzzz-7ekkf-2z3mc76g2q73aio".*`)
-       c.Check(json, Matches, `(?ms).*"total_cpu_cores": *16.*`)
-       c.Check(json, Not(Matches), `(?ms).*"info":.*`)
+       buf, err := fs.ReadFile(arvados.FS(s.runner.LogCollection), "/node.json")
+       c.Assert(err, IsNil)
+       json := string(buf)
+       c.Check(json, Matches, `(?ms).*"ProviderType": *"a1\.2xlarge".*`)
+       c.Check(json, Matches, `(?ms).*"Price": *1\.2.*`)
 
        c.Assert(s.api.Logs["node-info"], NotNil)
        json = s.api.Logs["node-info"].String()
@@ -1740,54 +1750,6 @@ func (s *TestSuite) TestSetupMounts(c *C) {
                cr.CleanupDirs()
                checkEmpty()
        }
-
-       // git_tree mounts
-       {
-               i = 0
-               cr.ArvMountPoint = ""
-               git_client.InstallProtocol("https", git_http.NewClient(arvados.InsecureHTTPClient))
-               cr.token = arvadostest.ActiveToken
-               cr.Container.Mounts = make(map[string]arvados.Mount)
-               cr.Container.Mounts = map[string]arvados.Mount{
-                       "/tip": {
-                               Kind:   "git_tree",
-                               UUID:   arvadostest.Repository2UUID,
-                               Commit: "fd3531f42995344f36c30b79f55f27b502f3d344",
-                               Path:   "/",
-                       },
-                       "/non-tip": {
-                               Kind:   "git_tree",
-                               UUID:   arvadostest.Repository2UUID,
-                               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                               Path:   "/",
-                       },
-               }
-               cr.Container.OutputPath = "/tmp"
-
-               bindmounts, err := cr.SetupMounts()
-               c.Check(err, IsNil)
-
-               for path, mount := range bindmounts {
-                       c.Check(mount.ReadOnly, Equals, !cr.Container.Mounts[path].Writable, Commentf("%s %#v", path, mount))
-               }
-
-               data, err := ioutil.ReadFile(bindmounts["/tip"].HostPath + "/dir1/dir2/file with mode 0644")
-               c.Check(err, IsNil)
-               c.Check(string(data), Equals, "\000\001\002\003")
-               _, err = ioutil.ReadFile(bindmounts["/tip"].HostPath + "/file only on testbranch")
-               c.Check(err, FitsTypeOf, &os.PathError{})
-               c.Check(os.IsNotExist(err), Equals, true)
-
-               data, err = ioutil.ReadFile(bindmounts["/non-tip"].HostPath + "/dir1/dir2/file with mode 0644")
-               c.Check(err, IsNil)
-               c.Check(string(data), Equals, "\000\001\002\003")
-               data, err = ioutil.ReadFile(bindmounts["/non-tip"].HostPath + "/file only on testbranch")
-               c.Check(err, IsNil)
-               c.Check(string(data), Equals, "testfile\n")
-
-               cr.CleanupDirs()
-               checkEmpty()
-       }
 }
 
 func (s *TestSuite) TestStdout(c *C) {
@@ -2386,7 +2348,6 @@ func (s *TestSuite) TestCalculateCost(c *C) {
        // hasn't found any data), cost is calculated based on
        // InstanceType env var
        os.Setenv("InstanceType", `{"Price":1.2}`)
-       defer os.Unsetenv("InstanceType")
        cost = cr.calculateCost(now)
        c.Check(cost, Equals, 1.2)
 
@@ -2432,7 +2393,6 @@ func (s *TestSuite) TestSIGUSR2CostUpdate(c *C) {
        c.Assert(err, IsNil)
 
        os.Setenv("InstanceType", `{"Price":2.2}`)
-       defer os.Unsetenv("InstanceType")
        defer func(s string) { lockdir = s }(lockdir)
        lockdir = c.MkDir()
 
diff --git a/lib/crunchrun/git_mount.go b/lib/crunchrun/git_mount.go
deleted file mode 100644 (file)
index 561ea18..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package crunchrun
-
-import (
-       "fmt"
-       "net/url"
-       "os"
-       "path/filepath"
-       "regexp"
-
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "gopkg.in/src-d/go-billy.v4/osfs"
-       git "gopkg.in/src-d/go-git.v4"
-       git_config "gopkg.in/src-d/go-git.v4/config"
-       git_plumbing "gopkg.in/src-d/go-git.v4/plumbing"
-       git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
-       "gopkg.in/src-d/go-git.v4/storage/memory"
-)
-
-type gitMount arvados.Mount
-
-var (
-       sha1re     = regexp.MustCompile(`^[0-9a-f]{40}$`)
-       repoUUIDre = regexp.MustCompile(`^[0-9a-z]{5}-s0uqq-[0-9a-z]{15}$`)
-)
-
-func (gm gitMount) validate() error {
-       if gm.Path != "" && gm.Path != "/" {
-               return fmt.Errorf("cannot mount git_tree with path %q -- only \"/\" is supported", gm.Path)
-       }
-       if !sha1re.MatchString(gm.Commit) {
-               return fmt.Errorf("cannot mount git_tree with commit %q -- must be a 40-char SHA1", gm.Commit)
-       }
-       if gm.RepositoryName != "" || gm.GitURL != "" {
-               return fmt.Errorf("cannot mount git_tree -- repository_name and git_url must be empty")
-       }
-       if !repoUUIDre.MatchString(gm.UUID) {
-               return fmt.Errorf("cannot mount git_tree with uuid %q -- must be a repository UUID", gm.UUID)
-       }
-       if gm.Writable {
-               return fmt.Errorf("writable git_tree mount is not supported")
-       }
-       return nil
-}
-
-// ExtractTree extracts the specified tree into dir, which is an
-// existing empty local directory.
-func (gm gitMount) extractTree(ac *arvados.Client, dir string, token string) error {
-       err := gm.validate()
-       if err != nil {
-               return err
-       }
-       dd, err := ac.DiscoveryDocument()
-       if err != nil {
-               return fmt.Errorf("error getting discovery document: %w", err)
-       }
-       u, err := url.Parse(dd.GitURL)
-       if err != nil {
-               return fmt.Errorf("parse gitUrl %q: %s", dd.GitURL, err)
-       }
-       u, err = u.Parse("/" + gm.UUID + ".git")
-       if err != nil {
-               return fmt.Errorf("build git url from %q, %q: %s", dd.GitURL, gm.UUID, err)
-       }
-       store := memory.NewStorage()
-       repo, err := git.Init(store, osfs.New(dir))
-       if err != nil {
-               return fmt.Errorf("init repo: %s", err)
-       }
-       _, err = repo.CreateRemote(&git_config.RemoteConfig{
-               Name: "origin",
-               URLs: []string{u.String()},
-       })
-       if err != nil {
-               return fmt.Errorf("create remote %q: %s", u.String(), err)
-       }
-       err = repo.Fetch(&git.FetchOptions{
-               RemoteName: "origin",
-               Auth: &git_http.BasicAuth{
-                       Username: "none",
-                       Password: token,
-               },
-       })
-       if err != nil {
-               return fmt.Errorf("git fetch %q: %s", u.String(), err)
-       }
-       wt, err := repo.Worktree()
-       if err != nil {
-               return fmt.Errorf("worktree failed: %s", err)
-       }
-       err = wt.Checkout(&git.CheckoutOptions{
-               Hash: git_plumbing.NewHash(gm.Commit),
-       })
-       if err != nil {
-               return fmt.Errorf("checkout failed: %s", err)
-       }
-       err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
-               if err != nil {
-                       return err
-               }
-               // copy user rx bits to group and other, in case
-               // prevailing umask is more restrictive than 022
-               mode := info.Mode()
-               mode = mode | ((mode >> 3) & 050) | ((mode >> 6) & 5)
-               return os.Chmod(path, mode)
-       })
-       if err != nil {
-               return fmt.Errorf("chmod -R %q: %s", dir, err)
-       }
-       return nil
-}
diff --git a/lib/crunchrun/git_mount_test.go b/lib/crunchrun/git_mount_test.go
deleted file mode 100644 (file)
index ac98dcc..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package crunchrun
-
-import (
-       "io/ioutil"
-       "os"
-       "path/filepath"
-
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadostest"
-       check "gopkg.in/check.v1"
-       git_client "gopkg.in/src-d/go-git.v4/plumbing/transport/client"
-       git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
-)
-
-type GitMountSuite struct {
-       tmpdir string
-}
-
-var _ = check.Suite(&GitMountSuite{})
-
-func (s *GitMountSuite) SetUpTest(c *check.C) {
-       var err error
-       s.tmpdir, err = ioutil.TempDir("", "")
-       c.Assert(err, check.IsNil)
-       git_client.InstallProtocol("https", git_http.NewClient(arvados.InsecureHTTPClient))
-}
-
-func (s *GitMountSuite) TearDownTest(c *check.C) {
-       err := os.RemoveAll(s.tmpdir)
-       c.Check(err, check.IsNil)
-}
-
-// Commit fd3531f is crunch-run-tree-test
-func (s *GitMountSuite) TestExtractTree(c *check.C) {
-       gm := gitMount{
-               Path:   "/",
-               UUID:   arvadostest.Repository2UUID,
-               Commit: "fd3531f42995344f36c30b79f55f27b502f3d344",
-       }
-       ac := arvados.NewClientFromEnv()
-       err := gm.extractTree(ac, s.tmpdir, arvadostest.ActiveToken)
-       c.Check(err, check.IsNil)
-
-       fnm := filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0644")
-       data, err := ioutil.ReadFile(fnm)
-       c.Check(err, check.IsNil)
-       c.Check(data, check.DeepEquals, []byte{0, 1, 2, 3})
-       fi, err := os.Stat(fnm)
-       c.Check(err, check.IsNil)
-       if err == nil {
-               c.Check(fi.Mode(), check.Equals, os.FileMode(0644))
-       }
-
-       fnm = filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0755")
-       data, err = ioutil.ReadFile(fnm)
-       c.Check(err, check.IsNil)
-       c.Check(string(data), check.DeepEquals, "#!/bin/sh\nexec echo OK\n")
-       fi, err = os.Stat(fnm)
-       c.Check(err, check.IsNil)
-       if err == nil {
-               c.Check(fi.Mode(), check.Equals, os.FileMode(0755))
-       }
-
-       // Ensure there's no extra stuff like a ".git" dir
-       s.checkTmpdirContents(c, []string{"dir1"})
-
-       // Ensure tmpdir is world-readable and world-executable so the
-       // UID inside the container can use it.
-       fi, err = os.Stat(s.tmpdir)
-       c.Check(err, check.IsNil)
-       c.Check(fi.Mode()&os.ModePerm, check.Equals, os.FileMode(0755))
-}
-
-// Commit 5ebfab0 is not the tip of any branch or tag, but is
-// reachable in branch "crunch-run-non-tip-test".
-func (s *GitMountSuite) TestExtractNonTipCommit(c *check.C) {
-       gm := gitMount{
-               UUID:   arvadostest.Repository2UUID,
-               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-       }
-       err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
-       c.Check(err, check.IsNil)
-
-       fnm := filepath.Join(s.tmpdir, "file only on testbranch")
-       data, err := ioutil.ReadFile(fnm)
-       c.Check(err, check.IsNil)
-       c.Check(string(data), check.DeepEquals, "testfile\n")
-}
-
-func (s *GitMountSuite) TestNonexistentRepository(c *check.C) {
-       gm := gitMount{
-               Path:   "/",
-               UUID:   "zzzzz-s0uqq-nonexistentrepo",
-               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-       }
-       err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
-       c.Check(err, check.NotNil)
-       c.Check(err, check.ErrorMatches, ".*repository not found.*")
-
-       s.checkTmpdirContents(c, []string{})
-}
-
-func (s *GitMountSuite) TestNonexistentCommit(c *check.C) {
-       gm := gitMount{
-               Path:   "/",
-               UUID:   arvadostest.Repository2UUID,
-               Commit: "bb66b6bb6b6bbb6b6b6b66b6b6b6b6b6b6b6b66b",
-       }
-       err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
-       c.Check(err, check.NotNil)
-       c.Check(err, check.ErrorMatches, ".*object not found.*")
-
-       s.checkTmpdirContents(c, []string{})
-}
-
-func (s *GitMountSuite) TestGitUrlDiscoveryFails(c *check.C) {
-       delete(discoveryMap, "gitUrl")
-       gm := gitMount{
-               Path:   "/",
-               UUID:   arvadostest.Repository2UUID,
-               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-       }
-       err := gm.extractTree(&arvados.Client{}, s.tmpdir, arvadostest.ActiveToken)
-       c.Check(err, check.ErrorMatches, ".*error getting discovery doc.*")
-}
-
-func (s *GitMountSuite) TestInvalid(c *check.C) {
-       for _, trial := range []struct {
-               gm      gitMount
-               matcher string
-       }{
-               {
-                       gm: gitMount{
-                               Path:   "/",
-                               UUID:   arvadostest.Repository2UUID,
-                               Commit: "abc123",
-                       },
-                       matcher: ".*SHA1.*",
-               },
-               {
-                       gm: gitMount{
-                               Path:           "/",
-                               UUID:           arvadostest.Repository2UUID,
-                               RepositoryName: arvadostest.Repository2Name,
-                               Commit:         "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                       },
-                       matcher: ".*repository_name.*",
-               },
-               {
-                       gm: gitMount{
-                               Path:   "/",
-                               GitURL: "https://localhost:0/" + arvadostest.Repository2Name + ".git",
-                               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                       },
-                       matcher: ".*git_url.*",
-               },
-               {
-                       gm: gitMount{
-                               Path:   "/dir1/",
-                               UUID:   arvadostest.Repository2UUID,
-                               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                       },
-                       matcher: ".*path.*",
-               },
-               {
-                       gm: gitMount{
-                               Path:   "/",
-                               Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                       },
-                       matcher: ".*UUID.*",
-               },
-               {
-                       gm: gitMount{
-                               Path:     "/",
-                               UUID:     arvadostest.Repository2UUID,
-                               Commit:   "5ebfab0522851df01fec11ec55a6d0f4877b542e",
-                               Writable: true,
-                       },
-                       matcher: ".*writable.*",
-               },
-       } {
-               err := trial.gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
-               c.Check(err, check.NotNil)
-               s.checkTmpdirContents(c, []string{})
-
-               err = trial.gm.validate()
-               c.Check(err, check.ErrorMatches, trial.matcher)
-       }
-}
-
-func (s *GitMountSuite) checkTmpdirContents(c *check.C, expect []string) {
-       f, err := os.Open(s.tmpdir)
-       c.Check(err, check.IsNil)
-       names, err := f.Readdirnames(-1)
-       c.Check(err, check.IsNil)
-       c.Check(names, check.DeepEquals, expect)
-}
index 42f165fd756b8027e7a9df880ac910db9fa0b2b5..ee3320c7c34b0ac0b2fa012ad8b8a5276ccdf176 100644 (file)
@@ -67,7 +67,7 @@ func (s *LoggingTestSuite) TestWriteLogs(c *C) {
 
        c.Check(api.Content[0]["log"].(arvadosclient.Dict)["event_type"], Equals, "crunch-run")
        c.Check(api.Content[0]["log"].(arvadosclient.Dict)["properties"].(map[string]string)["text"], Equals, logtext)
-       c.Check(string(kc.Content), Equals, logtext)
+       s.checkWroteBlock(c, kc, "74561df9ae65ee9f35d5661d42454264+83", logtext)
 }
 
 func (s *LoggingTestSuite) TestWriteLogsLarge(c *C) {
@@ -224,7 +224,14 @@ func (s *LoggingTestSuite) testWriteLogsWithRateLimit(c *C, throttleParam string
        c.Check(api.Content[0]["log"].(arvadosclient.Dict)["event_type"], Equals, "crunch-run")
        stderrLog := api.Content[0]["log"].(arvadosclient.Dict)["properties"].(map[string]string)["text"]
        c.Check(true, Equals, strings.Contains(stderrLog, expected))
-       c.Check(string(kc.Content), Equals, logtext)
+       s.checkWroteBlock(c, kc, "74561df9ae65ee9f35d5661d42454264+83", logtext)
+}
+
+func (s *LoggingTestSuite) checkWroteBlock(c *C, kc *KeepTestClient, locator, expect string) {
+       buf := make([]byte, len([]byte(expect))+1)
+       n, err := kc.ReadAt(locator, buf, 0)
+       c.Check(err, IsNil)
+       c.Check(string(buf[:n]), Equals, expect)
 }
 
 type filterSuite struct{}
index 146c645ecaac74dc9435ae5578ebb3de4e2f7b91..b27a14a5010d561961ca1719a58c98b25d298ab8 100644 (file)
@@ -901,7 +901,6 @@ func prodpkgs(osv osversion) []string {
                "curl",
                "fuse",
                "git",
-               "gitolite3",
                "graphviz",
                "haveged",
                "libcurl3-gnutls",
index d9b74f6a0630600680f8bc3516f97376e72924b7..12ffdd7af39b80d5dfc525d379cc6690ca0e683d 100644 (file)
@@ -230,10 +230,6 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read
       Keepbalance:
         InternalURLs:
           "http://0.0.0.0:9019/": {}
-      GitHTTP:
-        InternalURLs:
-          "http://0.0.0.0:9005/": {}
-        ExternalURL: {{printf "%q" ( print "https://" .Domain ":4445/" ) }}
       DispatchCloud:
         InternalURLs:
           "http://0.0.0.0:9006/": {}
index 82e95fe0b4c38b8ab0e7cfa49ab6c17da386da00..9ed0acfb8f7151e805c7269dceacb696f425c07b 100644 (file)
@@ -80,9 +80,9 @@ func (c *command) RunCommand(prog string, args []string, stdin io.Reader, stdout
        loader := config.NewLoader(stdin, log)
        loader.SetupFlags(flags)
 
-       // prog is [keepstore, keep-web, git-httpd, ...]  but the
+       // prog is [keepstore, keep-web, ...]  but the
        // legacy config flags are [-legacy-keepstore-config,
-       // -legacy-keepweb-config, -legacy-git-httpd-config, ...]
+       // -legacy-keepweb-config, ...]
        legacyFlag := "-legacy-" + strings.Replace(prog, "keep-", "keep", 1) + "-config"
        args = loader.MungeLegacyConfigArgs(log, args, legacyFlag)
 
index c3d0ea8aef676b3d3c57ce0bfbbcbe129b7689ac..dd1a6c4c3278c3a5306536314d171f2326fb26ba 100644 (file)
@@ -42,11 +42,6 @@ var (
        EndpointCollectionDelete                = APIEndpoint{"DELETE", "arvados/v1/collections/{uuid}", ""}
        EndpointCollectionTrash                 = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/trash", ""}
        EndpointCollectionUntrash               = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/untrash", ""}
-       EndpointSpecimenCreate                  = APIEndpoint{"POST", "arvados/v1/specimens", "specimen"}
-       EndpointSpecimenUpdate                  = APIEndpoint{"PATCH", "arvados/v1/specimens/{uuid}", "specimen"}
-       EndpointSpecimenGet                     = APIEndpoint{"GET", "arvados/v1/specimens/{uuid}", ""}
-       EndpointSpecimenList                    = APIEndpoint{"GET", "arvados/v1/specimens", ""}
-       EndpointSpecimenDelete                  = APIEndpoint{"DELETE", "arvados/v1/specimens/{uuid}", ""}
        EndpointContainerCreate                 = APIEndpoint{"POST", "arvados/v1/containers", "container"}
        EndpointContainerUpdate                 = APIEndpoint{"PATCH", "arvados/v1/containers/{uuid}", "container"}
        EndpointContainerPriorityUpdate         = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/update_priority", "container"}
@@ -332,11 +327,6 @@ type API interface {
        LogGet(ctx context.Context, options GetOptions) (Log, error)
        LogList(ctx context.Context, options ListOptions) (LogList, error)
        LogDelete(ctx context.Context, options DeleteOptions) (Log, error)
-       SpecimenCreate(ctx context.Context, options CreateOptions) (Specimen, error)
-       SpecimenUpdate(ctx context.Context, options UpdateOptions) (Specimen, error)
-       SpecimenGet(ctx context.Context, options GetOptions) (Specimen, error)
-       SpecimenList(ctx context.Context, options ListOptions) (SpecimenList, error)
-       SpecimenDelete(ctx context.Context, options DeleteOptions) (Specimen, error)
        SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error)
        UserCreate(ctx context.Context, options CreateOptions) (User, error)
        UserUpdate(ctx context.Context, options UpdateOptions) (User, error)
index 116051b09e3717f0d24c86aa967ae9452eb7877e..6725611fd0dbd8bd8905c68f1cf3e91e585c7fe0 100644 (file)
@@ -161,11 +161,6 @@ type Cluster struct {
                WebDAVLogEvents     bool
                WebDAVOutputBuffer  ByteSize
        }
-       Git struct {
-               GitCommand   string
-               GitoliteHome string
-               Repositories string
-       }
        Login struct {
                LDAP struct {
                        Enable             bool
@@ -248,7 +243,6 @@ type Cluster struct {
                AutoAdminFirstUser                    bool
                AutoAdminUserWithEmail                string
                AutoSetupNewUsers                     bool
-               AutoSetupNewUsersWithRepository       bool
                AutoSetupNewUsersWithVmUUID           string
                AutoSetupUsernameBlacklist            StringSet
                EmailSubjectPrefix                    string
@@ -356,8 +350,6 @@ type Services struct {
        DispatchCloud  Service
        DispatchLSF    Service
        DispatchSLURM  Service
-       GitHTTP        Service
-       GitSSH         Service
        Health         Service
        Keepbalance    Service
        Keepproxy      Service
@@ -511,8 +503,7 @@ type ContainersConfig struct {
        LocalKeepLogsToContainerLog   string
 
        JobsAPI struct {
-               Enable         string
-               GitInternalDir string
+               Enable string
        }
        Logging struct {
                MaxAge                       Duration
@@ -535,15 +526,6 @@ type ContainersConfig struct {
                PrioritySpread             int64
                SbatchArgumentsList        []string
                SbatchEnvironmentVariables map[string]string
-               Managed                    struct {
-                       DNSServerConfDir       string
-                       DNSServerConfTemplate  string
-                       DNSServerReloadCommand string
-                       DNSServerUpdateCommand string
-                       ComputeNodeDomain      string
-                       ComputeNodeNameservers StringSet
-                       AssignNodeHostname     string
-               }
        }
        LSF struct {
                BsubSudoUser       string
@@ -670,7 +652,6 @@ const (
        ServiceNameDispatchCloud ServiceName = "arvados-dispatch-cloud"
        ServiceNameDispatchLSF   ServiceName = "arvados-dispatch-lsf"
        ServiceNameDispatchSLURM ServiceName = "crunch-dispatch-slurm"
-       ServiceNameGitHTTP       ServiceName = "arvados-git-httpd"
        ServiceNameHealth        ServiceName = "arvados-health"
        ServiceNameKeepbalance   ServiceName = "keep-balance"
        ServiceNameKeepproxy     ServiceName = "keepproxy"
@@ -690,7 +671,6 @@ func (svcs Services) Map() map[ServiceName]Service {
                ServiceNameDispatchCloud: svcs.DispatchCloud,
                ServiceNameDispatchLSF:   svcs.DispatchLSF,
                ServiceNameDispatchSLURM: svcs.DispatchSLURM,
-               ServiceNameGitHTTP:       svcs.GitHTTP,
                ServiceNameHealth:        svcs.Health,
                ServiceNameKeepbalance:   svcs.Keepbalance,
                ServiceNameKeepproxy:     svcs.Keepproxy,
index aefad9b5e513547a0957836a2c6a648ac4e5b957..70038a18f79a82dca29b3dc937f2edfcc2fbb12a 100644 (file)
@@ -96,9 +96,6 @@ type Mount struct {
        Content           interface{} `json:"content"`
        ExcludeFromOutput bool        `json:"exclude_from_output"`
        Capacity          int64       `json:"capacity"`
-       Commit            string      `json:"commit"`          // only if kind=="git_tree"
-       RepositoryName    string      `json:"repository_name"` // only if kind=="git_tree"
-       GitURL            string      `json:"git_url"`         // only if kind=="git_tree"
 }
 
 type CUDARuntimeConstraints struct {
diff --git a/sdk/go/arvados/specimen.go b/sdk/go/arvados/specimen.go
deleted file mode 100644 (file)
index b561fb2..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package arvados
-
-import "time"
-
-type Specimen struct {
-       UUID                 string                 `json:"uuid"`
-       OwnerUUID            string                 `json:"owner_uuid"`
-       CreatedAt            time.Time              `json:"created_at"`
-       ModifiedAt           time.Time              `json:"modified_at"`
-       ModifiedByClientUUID string                 `json:"modified_by_client_uuid"`
-       ModifiedByUserUUID   string                 `json:"modified_by_user_uuid"`
-       Properties           map[string]interface{} `json:"properties"`
-}
-
-type SpecimenList struct {
-       Items          []Specimen `json:"items"`
-       ItemsAvailable int        `json:"items_available"`
-       Offset         int        `json:"offset"`
-       Limit          int        `json:"limit"`
-}
index bb7867aef7e35d283c5e47adb68873492bda609c..4272f0f759ff59403edba05fe553fab95dc2e54e 100644 (file)
@@ -13,8 +13,8 @@ import (
 // A ClientPool is a pool of ArvadosClients. This is useful for
 // applications that make API calls using a dynamic set of tokens,
 // like web services that pass through their own clients'
-// credentials. See arvados-git-httpd for an example, and sync.Pool
-// for more information about garbage collection.
+// credentials. See sync.Pool for more information about garbage
+// collection.
 type ClientPool struct {
        // Initialize new clients by copying this one.
        Prototype *ArvadosClient
index e1827b5d1f7995e3c3e01baa52ef016f349dcd95..658874c6d71480f4afdda12c8b3a9db8ad6e55f3 100644 (file)
@@ -264,26 +264,6 @@ func (as *APIStub) LogDelete(ctx context.Context, options arvados.DeleteOptions)
        as.appendCall(ctx, as.LogDelete, options)
        return arvados.Log{}, as.Error
 }
-func (as *APIStub) SpecimenCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Specimen, error) {
-       as.appendCall(ctx, as.SpecimenCreate, options)
-       return arvados.Specimen{}, as.Error
-}
-func (as *APIStub) SpecimenUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Specimen, error) {
-       as.appendCall(ctx, as.SpecimenUpdate, options)
-       return arvados.Specimen{}, as.Error
-}
-func (as *APIStub) SpecimenGet(ctx context.Context, options arvados.GetOptions) (arvados.Specimen, error) {
-       as.appendCall(ctx, as.SpecimenGet, options)
-       return arvados.Specimen{}, as.Error
-}
-func (as *APIStub) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
-       as.appendCall(ctx, as.SpecimenList, options)
-       return arvados.SpecimenList{}, as.Error
-}
-func (as *APIStub) SpecimenDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Specimen, error) {
-       as.appendCall(ctx, as.SpecimenDelete, options)
-       return arvados.Specimen{}, as.Error
-}
 func (as *APIStub) SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error) {
        as.appendCall(ctx, as.SysTrashSweep, options)
        return struct{}{}, as.Error
index 3b8a618fea099255434033751a156ab62d9a02d8..c70af45b5923ffa32f3852189b86a84b39144003 100644 (file)
@@ -101,7 +101,7 @@ const (
 
        AdminAuthorizedKeysUUID = "zzzzz-fngyi-12nc9ov4osp8nae"
 
-       CrunchstatForRunningJobLogUUID = "zzzzz-57u5n-tmymyrojrbtnxh1"
+       CrunchstatForRunningContainerLogUUID = "zzzzz-57u5n-containerlog006"
 
        IdleNodeUUID = "zzzzz-7ekkf-2z3mc76g2q73aio"
 
index f76f7b8ea80a45ba9d908e485d2dcae8b9eca300..d9f3faf034ffb0bb4cdc29481ed72186f46ddc20 100644 (file)
@@ -372,7 +372,6 @@ func (s *AggregatorSuite) setAllServiceURLs(listen string) {
                &svcs.DispatchCloud,
                &svcs.DispatchLSF,
                &svcs.DispatchSLURM,
-               &svcs.GitHTTP,
                &svcs.Keepbalance,
                &svcs.Keepproxy,
                &svcs.Keepstore,
index 6e3fcdc00cf4054df52f150b01b0e708118aa166..ef187f666300e95c5f1a03a28e8d3aea18905c8c 100644 (file)
         }
       }
     },
-    "humans": {
+    "keep_services": {
       "methods": {
         "get": {
-          "id": "arvados.humans.get",
-          "path": "humans/{uuid}",
+          "id": "arvados.keep_services.get",
+          "path": "keep_services/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a Human's metadata by UUID.",
+          "description": "Gets a KeepService's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Human in question.",
+              "description": "The UUID of the KeepService in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.humans.list",
-          "path": "humans",
+          "id": "arvados.keep_services.list",
+          "path": "keep_services",
           "httpMethod": "GET",
-          "description": "List Humans.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Humans. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#humanList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List KeepServices.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepServices. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepServiceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "HumanList"
+            "$ref": "KeepServiceList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.humans.create",
-          "path": "humans",
+          "id": "arvados.keep_services.create",
+          "path": "keep_services",
           "httpMethod": "POST",
-          "description": "Create a new Human.",
+          "description": "Create a new KeepService.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "human": {
-                "$ref": "Human"
+              "keep_service": {
+                "$ref": "KeepService"
               }
             }
           },
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.humans.update",
-          "path": "humans/{uuid}",
+          "id": "arvados.keep_services.update",
+          "path": "keep_services/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing Human.",
+          "description": "Update attributes of an existing KeepService.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Human in question.",
+              "description": "The UUID of the KeepService in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "human": {
-                "$ref": "Human"
+              "keep_service": {
+                "$ref": "KeepService"
               }
             }
           },
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.humans.delete",
-          "path": "humans/{uuid}",
+          "id": "arvados.keep_services.delete",
+          "path": "keep_services/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing Human.",
+          "description": "Delete an existing KeepService.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Human in question.",
+              "description": "The UUID of the KeepService in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "accessible": {
+          "id": "arvados.keep_services.accessible",
+          "path": "keep_services/accessible",
+          "httpMethod": "GET",
+          "description": "accessible keep_services",
+          "parameters": {},
+          "response": {
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "list": {
-          "id": "arvados.humans.list",
-          "path": "humans",
+          "id": "arvados.keep_services.list",
+          "path": "keep_services",
           "httpMethod": "GET",
-          "description": "List Humans.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Humans. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#humanList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List KeepServices.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepServices. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepServiceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "HumanList"
+            "$ref": "KeepServiceList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "show": {
-          "id": "arvados.humans.show",
-          "path": "humans/{uuid}",
+          "id": "arvados.keep_services.show",
+          "path": "keep_services/{uuid}",
           "httpMethod": "GET",
-          "description": "show humans",
+          "description": "show keep_services",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.humans.destroy",
-          "path": "humans/{uuid}",
+          "id": "arvados.keep_services.destroy",
+          "path": "keep_services/{uuid}",
           "httpMethod": "DELETE",
-          "description": "destroy humans",
+          "description": "destroy keep_services",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Human"
+            "$ref": "KeepService"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "jobs": {
+    "links": {
       "methods": {
         "get": {
-          "id": "arvados.jobs.get",
-          "path": "jobs/{uuid}",
+          "id": "arvados.links.get",
+          "path": "links/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a Job's metadata by UUID.",
+          "description": "Gets a Link's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Job in question.",
+              "description": "The UUID of the Link in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.jobs.list",
-          "path": "jobs",
+          "id": "arvados.links.list",
+          "path": "links",
           "httpMethod": "GET",
-          "description": "List Jobs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Jobs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#jobList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Links.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Links. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#linkList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "JobList"
+            "$ref": "LinkList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.jobs.create",
-          "path": "jobs",
+          "id": "arvados.links.create",
+          "path": "links",
           "httpMethod": "POST",
-          "description": "Create a new Job.",
+          "description": "Create a new Link.",
           "parameters": {
             "select": {
               "type": "array",
               "description": "Create object on a remote federated cluster instead of the current one.",
               "location": "query",
               "required": false
-            },
-            "find_or_create": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "minimum_script_version": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "exclude_script_versions": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
             }
           },
           "request": {
             "required": true,
             "properties": {
-              "job": {
-                "$ref": "Job"
+              "link": {
+                "$ref": "Link"
               }
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.jobs.update",
-          "path": "jobs/{uuid}",
+          "id": "arvados.links.update",
+          "path": "links/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing Job.",
+          "description": "Update attributes of an existing Link.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Job in question.",
+              "description": "The UUID of the Link in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "job": {
-                "$ref": "Job"
+              "link": {
+                "$ref": "Link"
               }
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.jobs.delete",
-          "path": "jobs/{uuid}",
+          "id": "arvados.links.delete",
+          "path": "links/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing Job.",
+          "description": "Delete an existing Link.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Job in question.",
+              "description": "The UUID of the Link in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
-        "queue": {
-          "id": "arvados.jobs.queue",
-          "path": "jobs/queue",
+        "list": {
+          "id": "arvados.links.list",
+          "path": "links",
           "httpMethod": "GET",
-          "description": "queue jobs",
+          "description": "List Links.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Links. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#linkList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "LinkList"
           },
           "scopes": [
-            "https://api.arvados.org/auth/arvados"
+            "https://api.arvados.org/auth/arvados",
+            "https://api.arvados.org/auth/arvados.readonly"
           ]
         },
-        "queue_size": {
-          "id": "arvados.jobs.queue_size",
-          "path": "jobs/queue_size",
+        "show": {
+          "id": "arvados.links.show",
+          "path": "links/{uuid}",
           "httpMethod": "GET",
-          "description": "queue_size jobs",
-          "parameters": {},
-          "response": {
-            "$ref": "Job"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "cancel": {
-          "id": "arvados.jobs.cancel",
-          "path": "jobs/{uuid}/cancel",
-          "httpMethod": "POST",
-          "description": "cancel jobs",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Job"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "lock": {
-          "id": "arvados.jobs.lock",
-          "path": "jobs/{uuid}/lock",
-          "httpMethod": "POST",
-          "description": "lock jobs",
+          "description": "show links",
           "parameters": {
             "uuid": {
               "type": "string",
               "description": "",
               "required": true,
               "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Job"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.jobs.list",
-          "path": "jobs",
-          "httpMethod": "GET",
-          "description": "List Jobs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Jobs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#jobList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
             },
             "select": {
               "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
+              "description": "Attributes of the object to return in the response.",
               "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
               "location": "query"
             }
           },
           "response": {
-            "$ref": "JobList"
+            "$ref": "Link"
           },
           "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
+            "https://api.arvados.org/auth/arvados"
           ]
         },
-        "show": {
-          "id": "arvados.jobs.show",
-          "path": "jobs/{uuid}",
-          "httpMethod": "GET",
-          "description": "show jobs",
+        "destroy": {
+          "id": "arvados.links.destroy",
+          "path": "links/{uuid}",
+          "httpMethod": "DELETE",
+          "description": "destroy links",
           "parameters": {
             "uuid": {
               "type": "string",
               "description": "",
               "required": true,
               "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
-        "destroy": {
-          "id": "arvados.jobs.destroy",
-          "path": "jobs/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy jobs",
+        "get_permissions": {
+          "id": "arvados.links.get_permissions",
+          "path": "permissions/{uuid}",
+          "httpMethod": "GET",
+          "description": "get_permissions links",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Job"
+            "$ref": "Link"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "job_tasks": {
+    "logs": {
       "methods": {
         "get": {
-          "id": "arvados.job_tasks.get",
-          "path": "job_tasks/{uuid}",
+          "id": "arvados.logs.get",
+          "path": "logs/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a JobTask's metadata by UUID.",
+          "description": "Gets a Log's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the JobTask in question.",
+              "description": "The UUID of the Log in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.job_tasks.list",
-          "path": "job_tasks",
+          "id": "arvados.logs.list",
+          "path": "logs",
           "httpMethod": "GET",
-          "description": "List JobTasks.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching JobTasks. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#jobTaskList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Logs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Logs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#logList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "JobTaskList"
+            "$ref": "LogList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.job_tasks.create",
-          "path": "job_tasks",
+          "id": "arvados.logs.create",
+          "path": "logs",
           "httpMethod": "POST",
-          "description": "Create a new JobTask.",
+          "description": "Create a new Log.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "job_task": {
-                "$ref": "JobTask"
+              "log": {
+                "$ref": "Log"
               }
             }
           },
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.job_tasks.update",
-          "path": "job_tasks/{uuid}",
+          "id": "arvados.logs.update",
+          "path": "logs/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing JobTask.",
+          "description": "Update attributes of an existing Log.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the JobTask in question.",
+              "description": "The UUID of the Log in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "job_task": {
-                "$ref": "JobTask"
-              }
+              "log": {
+                "$ref": "Log"
+              }
             }
           },
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.job_tasks.delete",
-          "path": "job_tasks/{uuid}",
+          "id": "arvados.logs.delete",
+          "path": "logs/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing JobTask.",
+          "description": "Delete an existing Log.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the JobTask in question.",
+              "description": "The UUID of the Log in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "list": {
-          "id": "arvados.job_tasks.list",
-          "path": "job_tasks",
+          "id": "arvados.logs.list",
+          "path": "logs",
           "httpMethod": "GET",
-          "description": "List JobTasks.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching JobTasks. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#jobTaskList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Logs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Logs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#logList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "JobTaskList"
+            "$ref": "LogList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "show": {
-          "id": "arvados.job_tasks.show",
-          "path": "job_tasks/{uuid}",
+          "id": "arvados.logs.show",
+          "path": "logs/{uuid}",
           "httpMethod": "GET",
-          "description": "show job_tasks",
+          "description": "show logs",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.job_tasks.destroy",
-          "path": "job_tasks/{uuid}",
+          "id": "arvados.logs.destroy",
+          "path": "logs/{uuid}",
           "httpMethod": "DELETE",
-          "description": "destroy job_tasks",
+          "description": "destroy logs",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "JobTask"
+            "$ref": "Log"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "keep_disks": {
+    "users": {
       "methods": {
         "get": {
-          "id": "arvados.keep_disks.get",
-          "path": "keep_disks/{uuid}",
+          "id": "arvados.users.get",
+          "path": "users/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a KeepDisk's metadata by UUID.",
+          "description": "Gets a User's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepDisk in question.",
+              "description": "The UUID of the User in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.keep_disks.list",
-          "path": "keep_disks",
+          "id": "arvados.users.list",
+          "path": "users",
           "httpMethod": "GET",
-          "description": "List KeepDisks.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepDisks. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepDiskList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Users.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Users. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "KeepDiskList"
+            "$ref": "UserList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.keep_disks.create",
-          "path": "keep_disks",
+          "id": "arvados.users.create",
+          "path": "users",
           "httpMethod": "POST",
-          "description": "Create a new KeepDisk.",
+          "description": "Create a new User.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "keep_disk": {
-                "$ref": "KeepDisk"
+              "user": {
+                "$ref": "User"
               }
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.keep_disks.update",
-          "path": "keep_disks/{uuid}",
+          "id": "arvados.users.update",
+          "path": "users/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing KeepDisk.",
+          "description": "Update attributes of an existing User.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepDisk in question.",
+              "description": "The UUID of the User in question.",
               "required": true,
               "location": "path"
             },
               "description": "Attributes of the updated object to return in the response.",
               "required": false,
               "location": "query"
+            },
+            "bypass_federation": {
+              "type": "boolean",
+              "required": false,
+              "default": "false",
+              "description": "",
+              "location": "query"
             }
           },
           "request": {
             "required": true,
             "properties": {
-              "keep_disk": {
-                "$ref": "KeepDisk"
+              "user": {
+                "$ref": "User"
               }
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.keep_disks.delete",
-          "path": "keep_disks/{uuid}",
+          "id": "arvados.users.delete",
+          "path": "users/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing KeepDisk.",
+          "description": "Delete an existing User.",
+          "parameters": {
+            "uuid": {
+              "type": "string",
+              "description": "The UUID of the User in question.",
+              "required": true,
+              "location": "path"
+            }
+          },
+          "response": {
+            "$ref": "User"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "current": {
+          "id": "arvados.users.current",
+          "path": "users/current",
+          "httpMethod": "GET",
+          "description": "current users",
+          "parameters": {},
+          "response": {
+            "$ref": "User"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "system": {
+          "id": "arvados.users.system",
+          "path": "users/system",
+          "httpMethod": "GET",
+          "description": "system users",
+          "parameters": {},
+          "response": {
+            "$ref": "User"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "activate": {
+          "id": "arvados.users.activate",
+          "path": "users/{uuid}/activate",
+          "httpMethod": "POST",
+          "description": "activate users",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepDisk in question.",
+              "description": "",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
-        "ping": {
-          "id": "arvados.keep_disks.ping",
-          "path": "keep_disks/ping",
+        "setup": {
+          "id": "arvados.users.setup",
+          "path": "users/setup",
           "httpMethod": "POST",
-          "description": "ping keep_disks",
+          "description": "setup users",
           "parameters": {
             "uuid": {
+              "type": "string",
+              "required": false,
+              "description": "",
+              "location": "query"
+            },
+            "user": {
+              "type": "object",
               "required": false,
+              "description": "",
+              "location": "query"
+            },
+            "repo_name": {
               "type": "string",
+              "required": false,
               "description": "",
               "location": "query"
             },
-            "ping_secret": {
-              "required": true,
+            "vm_uuid": {
               "type": "string",
+              "required": false,
               "description": "",
               "location": "query"
             },
-            "node_uuid": {
+            "send_notification_email": {
+              "type": "boolean",
               "required": false,
+              "default": "false",
+              "description": "",
+              "location": "query"
+            }
+          },
+          "response": {
+            "$ref": "User"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "unsetup": {
+          "id": "arvados.users.unsetup",
+          "path": "users/{uuid}/unsetup",
+          "httpMethod": "POST",
+          "description": "unsetup users",
+          "parameters": {
+            "uuid": {
+              "type": "string",
+              "description": "",
+              "required": true,
+              "location": "path"
+            }
+          },
+          "response": {
+            "$ref": "User"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "merge": {
+          "id": "arvados.users.merge",
+          "path": "users/merge",
+          "httpMethod": "POST",
+          "description": "merge users",
+          "parameters": {
+            "new_owner_uuid": {
               "type": "string",
+              "required": true,
               "description": "",
               "location": "query"
             },
-            "filesystem_uuid": {
-              "required": false,
+            "new_user_token": {
               "type": "string",
+              "required": false,
               "description": "",
               "location": "query"
             },
-            "service_host": {
+            "redirect_to_new_user": {
+              "type": "boolean",
               "required": false,
-              "type": "string",
+              "default": "false",
               "description": "",
               "location": "query"
             },
-            "service_port": {
-              "required": true,
+            "old_user_uuid": {
               "type": "string",
+              "required": false,
               "description": "",
               "location": "query"
             },
-            "service_ssl_flag": {
-              "required": true,
+            "new_user_uuid": {
               "type": "string",
+              "required": false,
               "description": "",
               "location": "query"
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "list": {
-          "id": "arvados.keep_disks.list",
-          "path": "keep_disks",
+          "id": "arvados.users.list",
+          "path": "users",
           "httpMethod": "GET",
-          "description": "List KeepDisks.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepDisks. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepDiskList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Users.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Users. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "KeepDiskList"
+            "$ref": "UserList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "show": {
-          "id": "arvados.keep_disks.show",
-          "path": "keep_disks/{uuid}",
+          "id": "arvados.users.show",
+          "path": "users/{uuid}",
           "httpMethod": "GET",
-          "description": "show keep_disks",
+          "description": "show users",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.keep_disks.destroy",
-          "path": "keep_disks/{uuid}",
+          "id": "arvados.users.destroy",
+          "path": "users/{uuid}",
           "httpMethod": "DELETE",
-          "description": "destroy keep_disks",
+          "description": "destroy users",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "KeepDisk"
+            "$ref": "User"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "keep_services": {
+    "user_agreements": {
       "methods": {
         "get": {
-          "id": "arvados.keep_services.get",
-          "path": "keep_services/{uuid}",
+          "id": "arvados.user_agreements.get",
+          "path": "user_agreements/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a KeepService's metadata by UUID.",
+          "description": "Gets a UserAgreement's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepService in question.",
+              "description": "The UUID of the UserAgreement in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.keep_services.list",
-          "path": "keep_services",
+          "id": "arvados.user_agreements.list",
+          "path": "user_agreements",
           "httpMethod": "GET",
-          "description": "List KeepServices.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepServices. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepServiceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List UserAgreements.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching UserAgreements. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userAgreementList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "KeepServiceList"
+            "$ref": "UserAgreementList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.keep_services.create",
-          "path": "keep_services",
+          "id": "arvados.user_agreements.create",
+          "path": "user_agreements",
           "httpMethod": "POST",
-          "description": "Create a new KeepService.",
+          "description": "Create a new UserAgreement.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "keep_service": {
-                "$ref": "KeepService"
+              "user_agreement": {
+                "$ref": "UserAgreement"
               }
             }
           },
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.keep_services.update",
-          "path": "keep_services/{uuid}",
+          "id": "arvados.user_agreements.update",
+          "path": "user_agreements/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing KeepService.",
+          "description": "Update attributes of an existing UserAgreement.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepService in question.",
+              "description": "The UUID of the UserAgreement in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "keep_service": {
-                "$ref": "KeepService"
+              "user_agreement": {
+                "$ref": "UserAgreement"
               }
             }
           },
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.keep_services.delete",
-          "path": "keep_services/{uuid}",
+          "id": "arvados.user_agreements.delete",
+          "path": "user_agreements/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing KeepService.",
+          "description": "Delete an existing UserAgreement.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the KeepService in question.",
+              "description": "The UUID of the UserAgreement in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
-        "accessible": {
-          "id": "arvados.keep_services.accessible",
-          "path": "keep_services/accessible",
+        "signatures": {
+          "id": "arvados.user_agreements.signatures",
+          "path": "user_agreements/signatures",
           "httpMethod": "GET",
-          "description": "accessible keep_services",
+          "description": "signatures user_agreements",
           "parameters": {},
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
-        "list": {
-          "id": "arvados.keep_services.list",
-          "path": "keep_services",
+        "sign": {
+          "id": "arvados.user_agreements.sign",
+          "path": "user_agreements/sign",
+          "httpMethod": "POST",
+          "description": "sign user_agreements",
+          "parameters": {},
+          "response": {
+            "$ref": "UserAgreement"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "list": {
+          "id": "arvados.user_agreements.list",
+          "path": "user_agreements",
           "httpMethod": "GET",
-          "description": "List KeepServices.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching KeepServices. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#keepServiceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List UserAgreements.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching UserAgreements. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userAgreementList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "KeepServiceList"
+            "$ref": "UserAgreementList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
             "https://api.arvados.org/auth/arvados.readonly"
           ]
         },
+        "new": {
+          "id": "arvados.user_agreements.new",
+          "path": "user_agreements/new",
+          "httpMethod": "GET",
+          "description": "new user_agreements",
+          "parameters": {},
+          "response": {
+            "$ref": "UserAgreement"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
         "show": {
-          "id": "arvados.keep_services.show",
-          "path": "keep_services/{uuid}",
+          "id": "arvados.user_agreements.show",
+          "path": "user_agreements/{uuid}",
           "httpMethod": "GET",
-          "description": "show keep_services",
+          "description": "show user_agreements",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.keep_services.destroy",
-          "path": "keep_services/{uuid}",
+          "id": "arvados.user_agreements.destroy",
+          "path": "user_agreements/{uuid}",
           "httpMethod": "DELETE",
-          "description": "destroy keep_services",
+          "description": "destroy user_agreements",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "KeepService"
+            "$ref": "UserAgreement"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "links": {
+    "virtual_machines": {
       "methods": {
         "get": {
-          "id": "arvados.links.get",
-          "path": "links/{uuid}",
+          "id": "arvados.virtual_machines.get",
+          "path": "virtual_machines/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a Link's metadata by UUID.",
+          "description": "Gets a VirtualMachine's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Link in question.",
+              "description": "The UUID of the VirtualMachine in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.links.list",
-          "path": "links",
+          "id": "arvados.virtual_machines.list",
+          "path": "virtual_machines",
           "httpMethod": "GET",
-          "description": "List Links.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Links. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#linkList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List VirtualMachines.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching VirtualMachines. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#virtualMachineList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "LinkList"
+            "$ref": "VirtualMachineList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.links.create",
-          "path": "links",
+          "id": "arvados.virtual_machines.create",
+          "path": "virtual_machines",
           "httpMethod": "POST",
-          "description": "Create a new Link.",
+          "description": "Create a new VirtualMachine.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "link": {
-                "$ref": "Link"
+              "virtual_machine": {
+                "$ref": "VirtualMachine"
               }
             }
           },
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.links.update",
-          "path": "links/{uuid}",
+          "id": "arvados.virtual_machines.update",
+          "path": "virtual_machines/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing Link.",
+          "description": "Update attributes of an existing VirtualMachine.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Link in question.",
+              "description": "The UUID of the VirtualMachine in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "link": {
-                "$ref": "Link"
+              "virtual_machine": {
+                "$ref": "VirtualMachine"
               }
             }
           },
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.links.delete",
-          "path": "links/{uuid}",
+          "id": "arvados.virtual_machines.delete",
+          "path": "virtual_machines/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing Link.",
+          "description": "Delete an existing VirtualMachine.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Link in question.",
+              "description": "The UUID of the VirtualMachine in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "logins": {
+          "id": "arvados.virtual_machines.logins",
+          "path": "virtual_machines/{uuid}/logins",
+          "httpMethod": "GET",
+          "description": "logins virtual_machines",
+          "parameters": {
+            "uuid": {
+              "type": "string",
+              "description": "",
+              "required": true,
+              "location": "path"
+            }
+          },
+          "response": {
+            "$ref": "VirtualMachine"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
+        },
+        "get_all_logins": {
+          "id": "arvados.virtual_machines.get_all_logins",
+          "path": "virtual_machines/get_all_logins",
+          "httpMethod": "GET",
+          "description": "get_all_logins virtual_machines",
+          "parameters": {},
+          "response": {
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "list": {
-          "id": "arvados.links.list",
-          "path": "links",
+          "id": "arvados.virtual_machines.list",
+          "path": "virtual_machines",
           "httpMethod": "GET",
-          "description": "List Links.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Links. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#linkList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List VirtualMachines.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching VirtualMachines. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#virtualMachineList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "LinkList"
+            "$ref": "VirtualMachineList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "show": {
-          "id": "arvados.links.show",
-          "path": "links/{uuid}",
+          "id": "arvados.virtual_machines.show",
+          "path": "virtual_machines/{uuid}",
           "httpMethod": "GET",
-          "description": "show links",
+          "description": "show virtual_machines",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.links.destroy",
-          "path": "links/{uuid}",
+          "id": "arvados.virtual_machines.destroy",
+          "path": "virtual_machines/{uuid}",
           "httpMethod": "DELETE",
-          "description": "destroy links",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Link"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "get_permissions": {
-          "id": "arvados.links.get_permissions",
-          "path": "permissions/{uuid}",
-          "httpMethod": "GET",
-          "description": "get_permissions links",
+          "description": "destroy virtual_machines",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Link"
+            "$ref": "VirtualMachine"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
         }
       }
     },
-    "logs": {
+    "workflows": {
       "methods": {
         "get": {
-          "id": "arvados.logs.get",
-          "path": "logs/{uuid}",
+          "id": "arvados.workflows.get",
+          "path": "workflows/{uuid}",
           "httpMethod": "GET",
-          "description": "Gets a Log's metadata by UUID.",
+          "description": "Gets a Workflow's metadata by UUID.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Log in question.",
+              "description": "The UUID of the Workflow in question.",
               "required": true,
               "location": "path"
             }
             "uuid"
           ],
           "response": {
-            "$ref": "Log"
+            "$ref": "Workflow"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "index": {
-          "id": "arvados.logs.list",
-          "path": "logs",
+          "id": "arvados.workflows.list",
+          "path": "workflows",
           "httpMethod": "GET",
-          "description": "List Logs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Logs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#logList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Workflows.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Workflows. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#workflowList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "LogList"
+            "$ref": "WorkflowList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "create": {
-          "id": "arvados.logs.create",
-          "path": "logs",
+          "id": "arvados.workflows.create",
+          "path": "workflows",
           "httpMethod": "POST",
-          "description": "Create a new Log.",
+          "description": "Create a new Workflow.",
           "parameters": {
             "select": {
               "type": "array",
           "request": {
             "required": true,
             "properties": {
-              "log": {
-                "$ref": "Log"
+              "workflow": {
+                "$ref": "Workflow"
               }
             }
           },
           "response": {
-            "$ref": "Log"
+            "$ref": "Workflow"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "update": {
-          "id": "arvados.logs.update",
-          "path": "logs/{uuid}",
+          "id": "arvados.workflows.update",
+          "path": "workflows/{uuid}",
           "httpMethod": "PUT",
-          "description": "Update attributes of an existing Log.",
+          "description": "Update attributes of an existing Workflow.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Log in question.",
+              "description": "The UUID of the Workflow in question.",
               "required": true,
               "location": "path"
             },
           "request": {
             "required": true,
             "properties": {
-              "log": {
-                "$ref": "Log"
+              "workflow": {
+                "$ref": "Workflow"
               }
             }
           },
           "response": {
-            "$ref": "Log"
+            "$ref": "Workflow"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "delete": {
-          "id": "arvados.logs.delete",
-          "path": "logs/{uuid}",
+          "id": "arvados.workflows.delete",
+          "path": "workflows/{uuid}",
           "httpMethod": "DELETE",
-          "description": "Delete an existing Log.",
+          "description": "Delete an existing Workflow.",
           "parameters": {
             "uuid": {
               "type": "string",
-              "description": "The UUID of the Log in question.",
+              "description": "The UUID of the Workflow in question.",
               "required": true,
               "location": "path"
             }
           },
           "response": {
-            "$ref": "Log"
+            "$ref": "Workflow"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "list": {
-          "id": "arvados.logs.list",
-          "path": "logs",
+          "id": "arvados.workflows.list",
+          "path": "workflows",
           "httpMethod": "GET",
-          "description": "List Logs.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Logs. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#logList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
+          "description": "List Workflows.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Workflows. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#workflowList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
           "parameters": {
             "filters": {
               "type": "array",
             }
           },
           "response": {
-            "$ref": "LogList"
+            "$ref": "WorkflowList"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados",
           ]
         },
         "show": {
-          "id": "arvados.logs.show",
-          "path": "logs/{uuid}",
+          "id": "arvados.workflows.show",
+          "path": "workflows/{uuid}",
           "httpMethod": "GET",
-          "description": "show logs",
+          "description": "show workflows",
           "parameters": {
             "uuid": {
               "type": "string",
             }
           },
           "response": {
-            "$ref": "Log"
+            "$ref": "Workflow"
           },
           "scopes": [
             "https://api.arvados.org/auth/arvados"
           ]
         },
         "destroy": {
-          "id": "arvados.logs.destroy",
-          "path": "logs/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy logs",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Log"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "nodes": {
-      "methods": {
-        "get": {
-          "id": "arvados.nodes.get",
-          "path": "nodes/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a Node's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Node in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.nodes.list",
-          "path": "nodes",
-          "httpMethod": "GET",
-          "description": "List Nodes.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Nodes. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#nodeList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "NodeList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.nodes.create",
-          "path": "nodes",
-          "httpMethod": "POST",
-          "description": "Create a new Node.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "assign_slot": {
-              "required": false,
-              "type": "boolean",
-              "description": "assign slot and hostname",
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "node": {
-                "$ref": "Node"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.nodes.update",
-          "path": "nodes/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing Node.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Node in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "assign_slot": {
-              "required": false,
-              "type": "boolean",
-              "description": "assign slot and hostname",
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "node": {
-                "$ref": "Node"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.nodes.delete",
-          "path": "nodes/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing Node.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Node in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "ping": {
-          "id": "arvados.nodes.ping",
-          "path": "nodes/{uuid}/ping",
-          "httpMethod": "POST",
-          "description": "ping nodes",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "ping_secret": {
-              "required": true,
-              "type": "string",
-              "description": "",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.nodes.list",
-          "path": "nodes",
-          "httpMethod": "GET",
-          "description": "List Nodes.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Nodes. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#nodeList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "NodeList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.nodes.show",
-          "path": "nodes/{uuid}",
-          "httpMethod": "GET",
-          "description": "show nodes",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.nodes.destroy",
-          "path": "nodes/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy nodes",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Node"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "pipeline_instances": {
-      "methods": {
-        "get": {
-          "id": "arvados.pipeline_instances.get",
-          "path": "pipeline_instances/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a PipelineInstance's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineInstance in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.pipeline_instances.list",
-          "path": "pipeline_instances",
-          "httpMethod": "GET",
-          "description": "List PipelineInstances.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching PipelineInstances. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#pipelineInstanceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstanceList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.pipeline_instances.create",
-          "path": "pipeline_instances",
-          "httpMethod": "POST",
-          "description": "Create a new PipelineInstance.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "pipeline_instance": {
-                "$ref": "PipelineInstance"
-              }
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.pipeline_instances.update",
-          "path": "pipeline_instances/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing PipelineInstance.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineInstance in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "pipeline_instance": {
-                "$ref": "PipelineInstance"
-              }
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.pipeline_instances.delete",
-          "path": "pipeline_instances/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing PipelineInstance.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineInstance in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "cancel": {
-          "id": "arvados.pipeline_instances.cancel",
-          "path": "pipeline_instances/{uuid}/cancel",
-          "httpMethod": "POST",
-          "description": "cancel pipeline_instances",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.pipeline_instances.list",
-          "path": "pipeline_instances",
-          "httpMethod": "GET",
-          "description": "List PipelineInstances.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching PipelineInstances. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#pipelineInstanceList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstanceList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.pipeline_instances.show",
-          "path": "pipeline_instances/{uuid}",
-          "httpMethod": "GET",
-          "description": "show pipeline_instances",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.pipeline_instances.destroy",
-          "path": "pipeline_instances/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy pipeline_instances",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "PipelineInstance"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "pipeline_templates": {
-      "methods": {
-        "get": {
-          "id": "arvados.pipeline_templates.get",
-          "path": "pipeline_templates/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a PipelineTemplate's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineTemplate in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.pipeline_templates.list",
-          "path": "pipeline_templates",
-          "httpMethod": "GET",
-          "description": "List PipelineTemplates.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching PipelineTemplates. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#pipelineTemplateList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplateList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.pipeline_templates.create",
-          "path": "pipeline_templates",
-          "httpMethod": "POST",
-          "description": "Create a new PipelineTemplate.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "pipeline_template": {
-                "$ref": "PipelineTemplate"
-              }
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.pipeline_templates.update",
-          "path": "pipeline_templates/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing PipelineTemplate.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineTemplate in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "pipeline_template": {
-                "$ref": "PipelineTemplate"
-              }
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.pipeline_templates.delete",
-          "path": "pipeline_templates/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing PipelineTemplate.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the PipelineTemplate in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.pipeline_templates.list",
-          "path": "pipeline_templates",
-          "httpMethod": "GET",
-          "description": "List PipelineTemplates.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching PipelineTemplates. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#pipelineTemplateList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplateList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.pipeline_templates.show",
-          "path": "pipeline_templates/{uuid}",
-          "httpMethod": "GET",
-          "description": "show pipeline_templates",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.pipeline_templates.destroy",
-          "path": "pipeline_templates/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy pipeline_templates",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "PipelineTemplate"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "repositories": {
-      "methods": {
-        "get": {
-          "id": "arvados.repositories.get",
-          "path": "repositories/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a Repository's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Repository in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.repositories.list",
-          "path": "repositories",
-          "httpMethod": "GET",
-          "description": "List Repositories.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Repositories. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#repositoryList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "RepositoryList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.repositories.create",
-          "path": "repositories",
-          "httpMethod": "POST",
-          "description": "Create a new Repository.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "repository": {
-                "$ref": "Repository"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.repositories.update",
-          "path": "repositories/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing Repository.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Repository in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "repository": {
-                "$ref": "Repository"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.repositories.delete",
-          "path": "repositories/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing Repository.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Repository in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "get_all_permissions": {
-          "id": "arvados.repositories.get_all_permissions",
-          "path": "repositories/get_all_permissions",
-          "httpMethod": "GET",
-          "description": "get_all_permissions repositories",
-          "parameters": {},
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.repositories.list",
-          "path": "repositories",
-          "httpMethod": "GET",
-          "description": "List Repositories.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Repositories. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#repositoryList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "RepositoryList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.repositories.show",
-          "path": "repositories/{uuid}",
-          "httpMethod": "GET",
-          "description": "show repositories",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.repositories.destroy",
-          "path": "repositories/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy repositories",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Repository"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "specimens": {
-      "methods": {
-        "get": {
-          "id": "arvados.specimens.get",
-          "path": "specimens/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a Specimen's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Specimen in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.specimens.list",
-          "path": "specimens",
-          "httpMethod": "GET",
-          "description": "List Specimens.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Specimens. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#specimenList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "SpecimenList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.specimens.create",
-          "path": "specimens",
-          "httpMethod": "POST",
-          "description": "Create a new Specimen.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "specimen": {
-                "$ref": "Specimen"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.specimens.update",
-          "path": "specimens/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing Specimen.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Specimen in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "specimen": {
-                "$ref": "Specimen"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.specimens.delete",
-          "path": "specimens/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing Specimen.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Specimen in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.specimens.list",
-          "path": "specimens",
-          "httpMethod": "GET",
-          "description": "List Specimens.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Specimens. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#specimenList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "SpecimenList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.specimens.show",
-          "path": "specimens/{uuid}",
-          "httpMethod": "GET",
-          "description": "show specimens",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.specimens.destroy",
-          "path": "specimens/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy specimens",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Specimen"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "traits": {
-      "methods": {
-        "get": {
-          "id": "arvados.traits.get",
-          "path": "traits/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a Trait's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Trait in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.traits.list",
-          "path": "traits",
-          "httpMethod": "GET",
-          "description": "List Traits.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Traits. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#traitList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "TraitList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.traits.create",
-          "path": "traits",
-          "httpMethod": "POST",
-          "description": "Create a new Trait.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "trait": {
-                "$ref": "Trait"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.traits.update",
-          "path": "traits/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing Trait.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Trait in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "trait": {
-                "$ref": "Trait"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.traits.delete",
-          "path": "traits/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing Trait.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Trait in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.traits.list",
-          "path": "traits",
-          "httpMethod": "GET",
-          "description": "List Traits.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Traits. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#traitList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "TraitList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.traits.show",
-          "path": "traits/{uuid}",
-          "httpMethod": "GET",
-          "description": "show traits",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.traits.destroy",
-          "path": "traits/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy traits",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Trait"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "users": {
-      "methods": {
-        "get": {
-          "id": "arvados.users.get",
-          "path": "users/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a User's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the User in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.users.list",
-          "path": "users",
-          "httpMethod": "GET",
-          "description": "List Users.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Users. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "UserList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.users.create",
-          "path": "users",
-          "httpMethod": "POST",
-          "description": "Create a new User.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "user": {
-                "$ref": "User"
-              }
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.users.update",
-          "path": "users/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing User.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the User in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "user": {
-                "$ref": "User"
-              }
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.users.delete",
-          "path": "users/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing User.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the User in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "current": {
-          "id": "arvados.users.current",
-          "path": "users/current",
-          "httpMethod": "GET",
-          "description": "current users",
-          "parameters": {},
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "system": {
-          "id": "arvados.users.system",
-          "path": "users/system",
-          "httpMethod": "GET",
-          "description": "system users",
-          "parameters": {},
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "activate": {
-          "id": "arvados.users.activate",
-          "path": "users/{uuid}/activate",
-          "httpMethod": "POST",
-          "description": "activate users",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "setup": {
-          "id": "arvados.users.setup",
-          "path": "users/setup",
-          "httpMethod": "POST",
-          "description": "setup users",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "user": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "repo_name": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "vm_uuid": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "send_notification_email": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "unsetup": {
-          "id": "arvados.users.unsetup",
-          "path": "users/{uuid}/unsetup",
-          "httpMethod": "POST",
-          "description": "unsetup users",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "merge": {
-          "id": "arvados.users.merge",
-          "path": "users/merge",
-          "httpMethod": "POST",
-          "description": "merge users",
-          "parameters": {
-            "new_owner_uuid": {
-              "type": "string",
-              "required": true,
-              "description": "",
-              "location": "query"
-            },
-            "new_user_token": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "redirect_to_new_user": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "old_user_uuid": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "new_user_uuid": {
-              "type": "string",
-              "required": false,
-              "description": "",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.users.list",
-          "path": "users",
-          "httpMethod": "GET",
-          "description": "List Users.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Users. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "UserList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.users.show",
-          "path": "users/{uuid}",
-          "httpMethod": "GET",
-          "description": "show users",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.users.destroy",
-          "path": "users/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy users",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "User"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "user_agreements": {
-      "methods": {
-        "get": {
-          "id": "arvados.user_agreements.get",
-          "path": "user_agreements/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a UserAgreement's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the UserAgreement in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.user_agreements.list",
-          "path": "user_agreements",
-          "httpMethod": "GET",
-          "description": "List UserAgreements.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching UserAgreements. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userAgreementList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "UserAgreementList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.user_agreements.create",
-          "path": "user_agreements",
-          "httpMethod": "POST",
-          "description": "Create a new UserAgreement.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "user_agreement": {
-                "$ref": "UserAgreement"
-              }
-            }
-          },
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.user_agreements.update",
-          "path": "user_agreements/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing UserAgreement.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the UserAgreement in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "user_agreement": {
-                "$ref": "UserAgreement"
-              }
-            }
-          },
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.user_agreements.delete",
-          "path": "user_agreements/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing UserAgreement.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the UserAgreement in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "signatures": {
-          "id": "arvados.user_agreements.signatures",
-          "path": "user_agreements/signatures",
-          "httpMethod": "GET",
-          "description": "signatures user_agreements",
-          "parameters": {},
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "sign": {
-          "id": "arvados.user_agreements.sign",
-          "path": "user_agreements/sign",
-          "httpMethod": "POST",
-          "description": "sign user_agreements",
-          "parameters": {},
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.user_agreements.list",
-          "path": "user_agreements",
-          "httpMethod": "GET",
-          "description": "List UserAgreements.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching UserAgreements. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#userAgreementList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "UserAgreementList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "new": {
-          "id": "arvados.user_agreements.new",
-          "path": "user_agreements/new",
-          "httpMethod": "GET",
-          "description": "new user_agreements",
-          "parameters": {},
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "show": {
-          "id": "arvados.user_agreements.show",
-          "path": "user_agreements/{uuid}",
-          "httpMethod": "GET",
-          "description": "show user_agreements",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.user_agreements.destroy",
-          "path": "user_agreements/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy user_agreements",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "UserAgreement"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "virtual_machines": {
-      "methods": {
-        "get": {
-          "id": "arvados.virtual_machines.get",
-          "path": "virtual_machines/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a VirtualMachine's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the VirtualMachine in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.virtual_machines.list",
-          "path": "virtual_machines",
-          "httpMethod": "GET",
-          "description": "List VirtualMachines.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching VirtualMachines. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#virtualMachineList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachineList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.virtual_machines.create",
-          "path": "virtual_machines",
-          "httpMethod": "POST",
-          "description": "Create a new VirtualMachine.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "virtual_machine": {
-                "$ref": "VirtualMachine"
-              }
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.virtual_machines.update",
-          "path": "virtual_machines/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing VirtualMachine.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the VirtualMachine in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "virtual_machine": {
-                "$ref": "VirtualMachine"
-              }
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.virtual_machines.delete",
-          "path": "virtual_machines/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing VirtualMachine.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the VirtualMachine in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "logins": {
-          "id": "arvados.virtual_machines.logins",
-          "path": "virtual_machines/{uuid}/logins",
-          "httpMethod": "GET",
-          "description": "logins virtual_machines",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "get_all_logins": {
-          "id": "arvados.virtual_machines.get_all_logins",
-          "path": "virtual_machines/get_all_logins",
-          "httpMethod": "GET",
-          "description": "get_all_logins virtual_machines",
-          "parameters": {},
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.virtual_machines.list",
-          "path": "virtual_machines",
-          "httpMethod": "GET",
-          "description": "List VirtualMachines.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching VirtualMachines. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#virtualMachineList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachineList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.virtual_machines.show",
-          "path": "virtual_machines/{uuid}",
-          "httpMethod": "GET",
-          "description": "show virtual_machines",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.virtual_machines.destroy",
-          "path": "virtual_machines/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy virtual_machines",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "VirtualMachine"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "workflows": {
-      "methods": {
-        "get": {
-          "id": "arvados.workflows.get",
-          "path": "workflows/{uuid}",
-          "httpMethod": "GET",
-          "description": "Gets a Workflow's metadata by UUID.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Workflow in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "parameterOrder": [
-            "uuid"
-          ],
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "index": {
-          "id": "arvados.workflows.list",
-          "path": "workflows",
-          "httpMethod": "GET",
-          "description": "List Workflows.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Workflows. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#workflowList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "WorkflowList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "create": {
-          "id": "arvados.workflows.create",
-          "path": "workflows",
-          "httpMethod": "POST",
-          "description": "Create a new Workflow.",
-          "parameters": {
-            "select": {
-              "type": "array",
-              "description": "Attributes of the new object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "ensure_unique_name": {
-              "type": "boolean",
-              "description": "Adjust name to ensure uniqueness instead of returning an error on (owner_uuid, name) collision.",
-              "location": "query",
-              "required": false,
-              "default": "false"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "Create object on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "workflow": {
-                "$ref": "Workflow"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "update": {
-          "id": "arvados.workflows.update",
-          "path": "workflows/{uuid}",
-          "httpMethod": "PUT",
-          "description": "Update attributes of an existing Workflow.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Workflow in question.",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the updated object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "request": {
-            "required": true,
-            "properties": {
-              "workflow": {
-                "$ref": "Workflow"
-              }
-            }
-          },
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "delete": {
-          "id": "arvados.workflows.delete",
-          "path": "workflows/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "Delete an existing Workflow.",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "The UUID of the Workflow in question.",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "list": {
-          "id": "arvados.workflows.list",
-          "path": "workflows",
-          "httpMethod": "GET",
-          "description": "List Workflows.\n\n                   The <code>list</code> method returns a\n                   <a href=\"/api/resources.html\">resource list</a> of\n                   matching Workflows. For example:\n\n                   <pre>\n                   {\n                    \"kind\":\"arvados#workflowList\",\n                    \"etag\":\"\",\n                    \"self_link\":\"\",\n                    \"next_page_token\":\"\",\n                    \"next_link\":\"\",\n                    \"items\":[\n                       ...\n                    ],\n                    \"items_available\":745,\n                    \"_profile\":{\n                     \"request_time\":0.157236317\n                    }\n                    </pre>",
-          "parameters": {
-            "filters": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "where": {
-              "type": "object",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "order": {
-              "type": "array",
-              "required": false,
-              "description": "",
-              "location": "query"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of each object to return in the response.",
-              "required": false,
-              "location": "query"
-            },
-            "distinct": {
-              "type": "boolean",
-              "required": false,
-              "default": "false",
-              "description": "",
-              "location": "query"
-            },
-            "limit": {
-              "type": "integer",
-              "required": false,
-              "default": "100",
-              "description": "",
-              "location": "query"
-            },
-            "offset": {
-              "type": "integer",
-              "required": false,
-              "default": "0",
-              "description": "",
-              "location": "query"
-            },
-            "count": {
-              "type": "string",
-              "required": false,
-              "default": "exact",
-              "description": "",
-              "location": "query"
-            },
-            "cluster_id": {
-              "type": "string",
-              "description": "List objects on a remote federated cluster instead of the current one.",
-              "location": "query",
-              "required": false
-            },
-            "bypass_federation": {
-              "type": "boolean",
-              "required": false,
-              "description": "bypass federation behavior, list items from local instance database only",
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "WorkflowList"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        },
-        "show": {
-          "id": "arvados.workflows.show",
-          "path": "workflows/{uuid}",
-          "httpMethod": "GET",
-          "description": "show workflows",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            },
-            "select": {
-              "type": "array",
-              "description": "Attributes of the object to return in the response.",
-              "required": false,
-              "location": "query"
-            }
-          },
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        },
-        "destroy": {
-          "id": "arvados.workflows.destroy",
-          "path": "workflows/{uuid}",
-          "httpMethod": "DELETE",
-          "description": "destroy workflows",
-          "parameters": {
-            "uuid": {
-              "type": "string",
-              "description": "",
-              "required": true,
-              "location": "path"
-            }
-          },
-          "response": {
-            "$ref": "Workflow"
-          },
-          "scopes": [
-            "https://api.arvados.org/auth/arvados"
-          ]
-        }
-      }
-    },
-    "configs": {
-      "methods": {
-        "get": {
-          "id": "arvados.configs.get",
-          "path": "config",
-          "httpMethod": "GET",
-          "description": "Get public config",
-          "parameters": {},
-          "parameterOrder": [],
-          "response": {},
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        }
-      }
-    },
-    "vocabularies": {
-      "methods": {
-        "get": {
-          "id": "arvados.vocabularies.get",
-          "path": "vocabulary",
-          "httpMethod": "GET",
-          "description": "Get vocabulary definition",
-          "parameters": {},
-          "parameterOrder": [],
-          "response": {},
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        }
-      }
-    },
-    "sys": {
-      "methods": {
-        "get": {
-          "id": "arvados.sys.trash_sweep",
-          "path": "sys/trash_sweep",
-          "httpMethod": "POST",
-          "description": "apply scheduled trash and delete operations",
-          "parameters": {},
-          "parameterOrder": [],
-          "response": {},
-          "scopes": [
-            "https://api.arvados.org/auth/arvados",
-            "https://api.arvados.org/auth/arvados.readonly"
-          ]
-        }
-      }
-    }
-  },
-  "revision": "20231117",
-  "schemas": {
-    "ApiClientList": {
-      "id": "ApiClientList",
-      "description": "ApiClient list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#apiClientList.",
-          "default": "arvados#apiClientList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of ApiClients.",
-          "items": {
-            "$ref": "ApiClient"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of ApiClients."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of ApiClients."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "ApiClient": {
-      "id": "ApiClient",
-      "description": "ApiClient",
-      "type": "object",
-      "uuidPrefix": "ozdt8",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "name": {
-          "type": "string"
-        },
-        "url_prefix": {
-          "type": "string"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "is_trusted": {
-          "type": "boolean"
-        }
-      }
-    },
-    "ApiClientAuthorizationList": {
-      "id": "ApiClientAuthorizationList",
-      "description": "ApiClientAuthorization list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#apiClientAuthorizationList.",
-          "default": "arvados#apiClientAuthorizationList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of ApiClientAuthorizations.",
-          "items": {
-            "$ref": "ApiClientAuthorization"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of ApiClientAuthorizations."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of ApiClientAuthorizations."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "ApiClientAuthorization": {
-      "id": "ApiClientAuthorization",
-      "description": "ApiClientAuthorization",
-      "type": "object",
-      "uuidPrefix": "gj3su",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "api_token": {
-          "type": "string"
-        },
-        "api_client_id": {
-          "type": "integer"
-        },
-        "user_id": {
-          "type": "integer"
-        },
-        "created_by_ip_address": {
-          "type": "string"
-        },
-        "last_used_by_ip_address": {
-          "type": "string"
-        },
-        "last_used_at": {
-          "type": "datetime"
-        },
-        "expires_at": {
-          "type": "datetime"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "default_owner_uuid": {
-          "type": "string"
-        },
-        "scopes": {
-          "type": "Array"
-        }
-      }
-    },
-    "AuthorizedKeyList": {
-      "id": "AuthorizedKeyList",
-      "description": "AuthorizedKey list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#authorizedKeyList.",
-          "default": "arvados#authorizedKeyList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of AuthorizedKeys.",
-          "items": {
-            "$ref": "AuthorizedKey"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of AuthorizedKeys."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of AuthorizedKeys."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "AuthorizedKey": {
-      "id": "AuthorizedKey",
-      "description": "AuthorizedKey",
-      "type": "object",
-      "uuidPrefix": "fngyi",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "name": {
-          "type": "string"
-        },
-        "key_type": {
-          "type": "string"
-        },
-        "authorized_user_uuid": {
-          "type": "string"
-        },
-        "public_key": {
-          "type": "text"
-        },
-        "expires_at": {
-          "type": "datetime"
-        },
-        "created_at": {
-          "type": "datetime"
-        }
-      }
-    },
-    "CollectionList": {
-      "id": "CollectionList",
-      "description": "Collection list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#collectionList.",
-          "default": "arvados#collectionList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of Collections.",
-          "items": {
-            "$ref": "Collection"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of Collections."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of Collections."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "Collection": {
-      "id": "Collection",
-      "description": "Collection",
-      "type": "object",
-      "uuidPrefix": "4zz18",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "portable_data_hash": {
-          "type": "string"
-        },
-        "replication_desired": {
-          "type": "integer"
-        },
-        "replication_confirmed_at": {
-          "type": "datetime"
-        },
-        "replication_confirmed": {
-          "type": "integer"
-        },
-        "manifest_text": {
-          "type": "text"
-        },
-        "name": {
-          "type": "string"
-        },
-        "description": {
-          "type": "string"
-        },
-        "properties": {
-          "type": "Hash"
-        },
-        "delete_at": {
-          "type": "datetime"
-        },
-        "trash_at": {
-          "type": "datetime"
-        },
-        "is_trashed": {
-          "type": "boolean"
-        },
-        "storage_classes_desired": {
-          "type": "Array"
-        },
-        "storage_classes_confirmed": {
-          "type": "Array"
-        },
-        "storage_classes_confirmed_at": {
-          "type": "datetime"
-        },
-        "current_version_uuid": {
-          "type": "string"
-        },
-        "version": {
-          "type": "integer"
-        },
-        "preserve_version": {
-          "type": "boolean"
-        },
-        "file_count": {
-          "type": "integer"
-        },
-        "file_size_total": {
-          "type": "integer"
-        }
-      }
-    },
-    "ContainerList": {
-      "id": "ContainerList",
-      "description": "Container list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#containerList.",
-          "default": "arvados#containerList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of Containers.",
-          "items": {
-            "$ref": "Container"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of Containers."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of Containers."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "Container": {
-      "id": "Container",
-      "description": "Container",
-      "type": "object",
-      "uuidPrefix": "dz642",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "state": {
-          "type": "string"
-        },
-        "started_at": {
-          "type": "datetime"
-        },
-        "finished_at": {
-          "type": "datetime"
-        },
-        "log": {
-          "type": "string"
-        },
-        "environment": {
-          "type": "Hash"
-        },
-        "cwd": {
-          "type": "string"
-        },
-        "command": {
-          "type": "Array"
-        },
-        "output_path": {
-          "type": "string"
-        },
-        "mounts": {
-          "type": "Hash"
-        },
-        "runtime_constraints": {
-          "type": "Hash"
-        },
-        "output": {
-          "type": "string"
-        },
-        "container_image": {
-          "type": "string"
-        },
-        "progress": {
-          "type": "float"
-        },
-        "priority": {
-          "type": "integer"
-        },
-        "exit_code": {
-          "type": "integer"
-        },
-        "auth_uuid": {
-          "type": "string"
-        },
-        "locked_by_uuid": {
-          "type": "string"
-        },
-        "scheduling_parameters": {
-          "type": "Hash"
-        },
-        "runtime_status": {
-          "type": "Hash"
-        },
-        "runtime_user_uuid": {
-          "type": "text"
-        },
-        "runtime_auth_scopes": {
-          "type": "Array"
-        },
-        "lock_count": {
-          "type": "integer"
-        },
-        "gateway_address": {
-          "type": "string"
-        },
-        "interactive_session_started": {
-          "type": "boolean"
-        },
-        "output_storage_classes": {
-          "type": "Array"
-        },
-        "output_properties": {
-          "type": "Hash"
-        },
-        "cost": {
-          "type": "float"
-        },
-        "subrequests_cost": {
-          "type": "float"
-        },
-        "output_glob": {
-          "type": "Array"
-        }
-      }
-    },
-    "ContainerRequestList": {
-      "id": "ContainerRequestList",
-      "description": "ContainerRequest list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#containerRequestList.",
-          "default": "arvados#containerRequestList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of ContainerRequests.",
-          "items": {
-            "$ref": "ContainerRequest"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of ContainerRequests."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of ContainerRequests."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "ContainerRequest": {
-      "id": "ContainerRequest",
-      "description": "ContainerRequest",
-      "type": "object",
-      "uuidPrefix": "xvhdp",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "name": {
-          "type": "string"
-        },
-        "description": {
-          "type": "text"
-        },
-        "properties": {
-          "type": "Hash"
-        },
-        "state": {
-          "type": "string"
-        },
-        "requesting_container_uuid": {
-          "type": "string"
-        },
-        "container_uuid": {
-          "type": "string"
-        },
-        "container_count_max": {
-          "type": "integer"
-        },
-        "mounts": {
-          "type": "Hash"
-        },
-        "runtime_constraints": {
-          "type": "Hash"
-        },
-        "container_image": {
-          "type": "string"
-        },
-        "environment": {
-          "type": "Hash"
-        },
-        "cwd": {
-          "type": "string"
-        },
-        "command": {
-          "type": "Array"
-        },
-        "output_path": {
-          "type": "string"
-        },
-        "priority": {
-          "type": "integer"
-        },
-        "expires_at": {
-          "type": "datetime"
-        },
-        "filters": {
-          "type": "text"
-        },
-        "container_count": {
-          "type": "integer"
-        },
-        "use_existing": {
-          "type": "boolean"
-        },
-        "scheduling_parameters": {
-          "type": "Hash"
-        },
-        "output_uuid": {
-          "type": "string"
-        },
-        "log_uuid": {
-          "type": "string"
-        },
-        "output_name": {
-          "type": "string"
-        },
-        "output_ttl": {
-          "type": "integer"
-        },
-        "output_storage_classes": {
-          "type": "Array"
-        },
-        "output_properties": {
-          "type": "Hash"
-        },
-        "cumulative_cost": {
-          "type": "float"
-        },
-        "output_glob": {
-          "type": "Array"
-        }
-      }
-    },
-    "GroupList": {
-      "id": "GroupList",
-      "description": "Group list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#groupList.",
-          "default": "arvados#groupList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of Groups.",
-          "items": {
-            "$ref": "Group"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of Groups."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of Groups."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "Group": {
-      "id": "Group",
-      "description": "Group",
-      "type": "object",
-      "uuidPrefix": "j7d0g",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "created_at": {
-          "type": "datetime"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "name": {
-          "type": "string"
-        },
-        "description": {
-          "type": "string"
-        },
-        "group_class": {
-          "type": "string"
-        },
-        "trash_at": {
-          "type": "datetime"
-        },
-        "is_trashed": {
-          "type": "boolean"
-        },
-        "delete_at": {
-          "type": "datetime"
-        },
-        "properties": {
-          "type": "Hash"
-        },
-        "frozen_by_uuid": {
-          "type": "string"
+          "id": "arvados.workflows.destroy",
+          "path": "workflows/{uuid}",
+          "httpMethod": "DELETE",
+          "description": "destroy workflows",
+          "parameters": {
+            "uuid": {
+              "type": "string",
+              "description": "",
+              "required": true,
+              "location": "path"
+            }
+          },
+          "response": {
+            "$ref": "Workflow"
+          },
+          "scopes": [
+            "https://api.arvados.org/auth/arvados"
+          ]
         }
       }
     },
-    "HumanList": {
-      "id": "HumanList",
-      "description": "Human list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#humanList.",
-          "default": "arvados#humanList"
-        },
-        "etag": {
-          "type": "string",
-          "description": "List version."
-        },
-        "items": {
-          "type": "array",
-          "description": "The list of Humans.",
-          "items": {
-            "$ref": "Human"
-          }
-        },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of Humans."
-        },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of Humans."
-        },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
+    "configs": {
+      "methods": {
+        "get": {
+          "id": "arvados.configs.get",
+          "path": "config",
+          "httpMethod": "GET",
+          "description": "Get public config",
+          "parameters": {},
+          "parameterOrder": [],
+          "response": {},
+          "scopes": [
+            "https://api.arvados.org/auth/arvados",
+            "https://api.arvados.org/auth/arvados.readonly"
+          ]
         }
       }
     },
-    "Human": {
-      "id": "Human",
-      "description": "Human",
-      "type": "object",
-      "uuidPrefix": "7a9it",
-      "properties": {
-        "uuid": {
-          "type": "string"
-        },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
-        },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "properties": {
-          "type": "Hash"
-        },
-        "created_at": {
-          "type": "datetime"
+    "vocabularies": {
+      "methods": {
+        "get": {
+          "id": "arvados.vocabularies.get",
+          "path": "vocabulary",
+          "httpMethod": "GET",
+          "description": "Get vocabulary definition",
+          "parameters": {},
+          "parameterOrder": [],
+          "response": {},
+          "scopes": [
+            "https://api.arvados.org/auth/arvados",
+            "https://api.arvados.org/auth/arvados.readonly"
+          ]
         }
       }
     },
-    "JobList": {
-      "id": "JobList",
-      "description": "Job list",
+    "sys": {
+      "methods": {
+        "get": {
+          "id": "arvados.sys.trash_sweep",
+          "path": "sys/trash_sweep",
+          "httpMethod": "POST",
+          "description": "apply scheduled trash and delete operations",
+          "parameters": {},
+          "parameterOrder": [],
+          "response": {},
+          "scopes": [
+            "https://api.arvados.org/auth/arvados",
+            "https://api.arvados.org/auth/arvados.readonly"
+          ]
+        }
+      }
+    }
+  },
+  "revision": "20231117",
+  "schemas": {
+    "ApiClientList": {
+      "id": "ApiClientList",
+      "description": "ApiClient list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#jobList.",
-          "default": "arvados#jobList"
+          "description": "Object type. Always arvados#apiClientList.",
+          "default": "arvados#apiClientList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Jobs.",
+          "description": "The list of ApiClients.",
           "items": {
-            "$ref": "Job"
+            "$ref": "ApiClient"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Jobs."
+          "description": "A link to the next page of ApiClients."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Jobs."
+          "description": "The page token for the next page of ApiClients."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Job": {
-      "id": "Job",
-      "description": "Job",
+    "ApiClient": {
+      "id": "ApiClient",
+      "description": "ApiClient",
       "type": "object",
-      "uuidPrefix": "8i9sb",
+      "uuidPrefix": "ozdt8",
       "properties": {
         "uuid": {
           "type": "string"
         "modified_at": {
           "type": "datetime"
         },
-        "submit_id": {
-          "type": "string"
-        },
-        "script": {
-          "type": "string"
-        },
-        "script_version": {
-          "type": "string"
-        },
-        "script_parameters": {
-          "type": "Hash"
-        },
-        "cancelled_by_client_uuid": {
-          "type": "string"
-        },
-        "cancelled_by_user_uuid": {
+        "name": {
           "type": "string"
         },
-        "cancelled_at": {
-          "type": "datetime"
-        },
-        "started_at": {
-          "type": "datetime"
-        },
-        "finished_at": {
-          "type": "datetime"
-        },
-        "running": {
-          "type": "boolean"
-        },
-        "success": {
-          "type": "boolean"
-        },
-        "output": {
+        "url_prefix": {
           "type": "string"
         },
         "created_at": {
           "type": "datetime"
         },
-        "is_locked_by_uuid": {
-          "type": "string"
-        },
-        "log": {
-          "type": "string"
-        },
-        "tasks_summary": {
-          "type": "Hash"
-        },
-        "runtime_constraints": {
-          "type": "Hash"
-        },
-        "nondeterministic": {
+        "is_trusted": {
           "type": "boolean"
-        },
-        "repository": {
-          "type": "string"
-        },
-        "supplied_script_version": {
-          "type": "string"
-        },
-        "docker_image_locator": {
-          "type": "string"
-        },
-        "priority": {
-          "type": "integer"
-        },
-        "description": {
-          "type": "string"
-        },
-        "state": {
-          "type": "string"
-        },
-        "arvados_sdk_version": {
-          "type": "string"
-        },
-        "components": {
-          "type": "Hash"
         }
       }
     },
-    "JobTaskList": {
-      "id": "JobTaskList",
-      "description": "JobTask list",
+    "ApiClientAuthorizationList": {
+      "id": "ApiClientAuthorizationList",
+      "description": "ApiClientAuthorization list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#jobTaskList.",
-          "default": "arvados#jobTaskList"
+          "description": "Object type. Always arvados#apiClientAuthorizationList.",
+          "default": "arvados#apiClientAuthorizationList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of JobTasks.",
+          "description": "The list of ApiClientAuthorizations.",
           "items": {
-            "$ref": "JobTask"
+            "$ref": "ApiClientAuthorization"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of JobTasks."
+          "description": "A link to the next page of ApiClientAuthorizations."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of JobTasks."
+          "description": "The page token for the next page of ApiClientAuthorizations."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "JobTask": {
-      "id": "JobTask",
-      "description": "JobTask",
+    "ApiClientAuthorization": {
+      "id": "ApiClientAuthorization",
+      "description": "ApiClientAuthorization",
       "type": "object",
-      "uuidPrefix": "ot0gb",
+      "uuidPrefix": "gj3su",
       "properties": {
         "uuid": {
           "type": "string"
           "type": "string",
           "description": "Object version."
         },
-        "owner_uuid": {
-          "type": "string"
-        },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
-        "modified_at": {
-          "type": "datetime"
-        },
-        "job_uuid": {
+        "api_token": {
           "type": "string"
         },
-        "sequence": {
+        "api_client_id": {
           "type": "integer"
         },
-        "parameters": {
-          "type": "Hash"
-        },
-        "output": {
-          "type": "text"
-        },
-        "progress": {
-          "type": "float"
-        },
-        "success": {
-          "type": "boolean"
+        "user_id": {
+          "type": "integer"
         },
-        "created_at": {
-          "type": "datetime"
+        "created_by_ip_address": {
+          "type": "string"
         },
-        "created_by_job_task_uuid": {
+        "last_used_by_ip_address": {
           "type": "string"
         },
-        "qsequence": {
-          "type": "integer"
+        "last_used_at": {
+          "type": "datetime"
         },
-        "started_at": {
+        "expires_at": {
           "type": "datetime"
         },
-        "finished_at": {
+        "created_at": {
           "type": "datetime"
+        },
+        "default_owner_uuid": {
+          "type": "string"
+        },
+        "scopes": {
+          "type": "Array"
         }
       }
     },
-    "KeepDiskList": {
-      "id": "KeepDiskList",
-      "description": "KeepDisk list",
+    "AuthorizedKeyList": {
+      "id": "AuthorizedKeyList",
+      "description": "AuthorizedKey list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#keepDiskList.",
-          "default": "arvados#keepDiskList"
+          "description": "Object type. Always arvados#authorizedKeyList.",
+          "default": "arvados#authorizedKeyList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of KeepDisks.",
+          "description": "The list of AuthorizedKeys.",
           "items": {
-            "$ref": "KeepDisk"
+            "$ref": "AuthorizedKey"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of KeepDisks."
+          "description": "A link to the next page of AuthorizedKeys."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of KeepDisks."
+          "description": "The page token for the next page of AuthorizedKeys."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "KeepDisk": {
-      "id": "KeepDisk",
-      "description": "KeepDisk",
+    "AuthorizedKey": {
+      "id": "AuthorizedKey",
+      "description": "AuthorizedKey",
       "type": "object",
-      "uuidPrefix": "penuu",
+      "uuidPrefix": "fngyi",
       "properties": {
         "uuid": {
           "type": "string"
         "modified_at": {
           "type": "datetime"
         },
-        "node_uuid": {
+        "name": {
           "type": "string"
         },
-        "filesystem_uuid": {
+        "key_type": {
           "type": "string"
         },
-        "bytes_total": {
-          "type": "integer"
-        },
-        "bytes_free": {
-          "type": "integer"
-        },
-        "is_readable": {
-          "type": "boolean"
-        },
-        "is_writable": {
-          "type": "boolean"
-        },
-        "last_read_at": {
-          "type": "datetime"
+        "authorized_user_uuid": {
+          "type": "string"
         },
-        "last_write_at": {
-          "type": "datetime"
+        "public_key": {
+          "type": "text"
         },
-        "last_ping_at": {
+        "expires_at": {
           "type": "datetime"
         },
         "created_at": {
           "type": "datetime"
-        },
-        "keep_service_uuid": {
-          "type": "string"
         }
       }
     },
-    "KeepServiceList": {
-      "id": "KeepServiceList",
-      "description": "KeepService list",
+    "CollectionList": {
+      "id": "CollectionList",
+      "description": "Collection list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#keepServiceList.",
-          "default": "arvados#keepServiceList"
+          "description": "Object type. Always arvados#collectionList.",
+          "default": "arvados#collectionList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of KeepServices.",
+          "description": "The list of Collections.",
           "items": {
-            "$ref": "KeepService"
+            "$ref": "Collection"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of KeepServices."
+          "description": "A link to the next page of Collections."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of KeepServices."
+          "description": "The page token for the next page of Collections."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "KeepService": {
-      "id": "KeepService",
-      "description": "KeepService",
+    "Collection": {
+      "id": "Collection",
+      "description": "Collection",
       "type": "object",
-      "uuidPrefix": "bi6l4",
+      "uuidPrefix": "4zz18",
       "properties": {
         "uuid": {
           "type": "string"
         "owner_uuid": {
           "type": "string"
         },
+        "created_at": {
+          "type": "datetime"
+        },
         "modified_by_client_uuid": {
           "type": "string"
         },
         "modified_at": {
           "type": "datetime"
         },
-        "service_host": {
+        "portable_data_hash": {
           "type": "string"
         },
-        "service_port": {
+        "replication_desired": {
           "type": "integer"
         },
-        "service_ssl_flag": {
-          "type": "boolean"
+        "replication_confirmed_at": {
+          "type": "datetime"
         },
-        "service_type": {
+        "replication_confirmed": {
+          "type": "integer"
+        },
+        "manifest_text": {
+          "type": "text"
+        },
+        "name": {
           "type": "string"
         },
-        "created_at": {
+        "description": {
+          "type": "string"
+        },
+        "properties": {
+          "type": "Hash"
+        },
+        "delete_at": {
           "type": "datetime"
         },
-        "read_only": {
+        "trash_at": {
+          "type": "datetime"
+        },
+        "is_trashed": {
           "type": "boolean"
+        },
+        "storage_classes_desired": {
+          "type": "Array"
+        },
+        "storage_classes_confirmed": {
+          "type": "Array"
+        },
+        "storage_classes_confirmed_at": {
+          "type": "datetime"
+        },
+        "current_version_uuid": {
+          "type": "string"
+        },
+        "version": {
+          "type": "integer"
+        },
+        "preserve_version": {
+          "type": "boolean"
+        },
+        "file_count": {
+          "type": "integer"
+        },
+        "file_size_total": {
+          "type": "integer"
         }
       }
     },
-    "LinkList": {
-      "id": "LinkList",
-      "description": "Link list",
+    "ContainerList": {
+      "id": "ContainerList",
+      "description": "Container list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#linkList.",
-          "default": "arvados#linkList"
+          "description": "Object type. Always arvados#containerList.",
+          "default": "arvados#containerList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Links.",
+          "description": "The list of Containers.",
           "items": {
-            "$ref": "Link"
+            "$ref": "Container"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Links."
+          "description": "A link to the next page of Containers."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Links."
+          "description": "The page token for the next page of Containers."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Link": {
-      "id": "Link",
-      "description": "Link",
+    "Container": {
+      "id": "Container",
+      "description": "Container",
       "type": "object",
-      "uuidPrefix": "o0j2j",
+      "uuidPrefix": "dz642",
       "properties": {
         "uuid": {
           "type": "string"
         "created_at": {
           "type": "datetime"
         },
+        "modified_at": {
+          "type": "datetime"
+        },
         "modified_by_client_uuid": {
           "type": "string"
         },
         "modified_by_user_uuid": {
           "type": "string"
         },
-        "modified_at": {
+        "state": {
+          "type": "string"
+        },
+        "started_at": {
           "type": "datetime"
         },
-        "tail_uuid": {
-          "type": "string"
+        "finished_at": {
+          "type": "datetime"
         },
-        "link_class": {
+        "log": {
           "type": "string"
         },
-        "name": {
-          "type": "string"
+        "environment": {
+          "type": "Hash"
         },
-        "head_uuid": {
+        "cwd": {
           "type": "string"
         },
-        "properties": {
-          "type": "Hash"
-        }
-      }
-    },
-    "LogList": {
-      "id": "LogList",
-      "description": "Log list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#logList.",
-          "default": "arvados#logList"
+        "command": {
+          "type": "Array"
         },
-        "etag": {
-          "type": "string",
-          "description": "List version."
+        "output_path": {
+          "type": "string"
         },
-        "items": {
-          "type": "array",
-          "description": "The list of Logs.",
-          "items": {
-            "$ref": "Log"
-          }
+        "mounts": {
+          "type": "Hash"
         },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of Logs."
+        "runtime_constraints": {
+          "type": "Hash"
         },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of Logs."
+        "output": {
+          "type": "string"
         },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "Log": {
-      "id": "Log",
-      "description": "Log",
-      "type": "object",
-      "uuidPrefix": "57u5n",
-      "properties": {
-        "uuid": {
+        "container_image": {
           "type": "string"
         },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
+        "progress": {
+          "type": "float"
         },
-        "id": {
+        "priority": {
           "type": "integer"
         },
-        "owner_uuid": {
-          "type": "string"
+        "exit_code": {
+          "type": "integer"
         },
-        "modified_by_client_uuid": {
+        "auth_uuid": {
           "type": "string"
         },
-        "modified_by_user_uuid": {
+        "locked_by_uuid": {
           "type": "string"
         },
-        "object_uuid": {
-          "type": "string"
+        "scheduling_parameters": {
+          "type": "Hash"
         },
-        "event_at": {
-          "type": "datetime"
+        "runtime_status": {
+          "type": "Hash"
         },
-        "event_type": {
+        "runtime_user_uuid": {
+          "type": "text"
+        },
+        "runtime_auth_scopes": {
+          "type": "Array"
+        },
+        "lock_count": {
+          "type": "integer"
+        },
+        "gateway_address": {
           "type": "string"
         },
-        "summary": {
-          "type": "text"
+        "interactive_session_started": {
+          "type": "boolean"
+        },
+        "output_storage_classes": {
+          "type": "Array"
         },
-        "properties": {
+        "output_properties": {
           "type": "Hash"
         },
-        "created_at": {
-          "type": "datetime"
+        "cost": {
+          "type": "float"
         },
-        "modified_at": {
-          "type": "datetime"
+        "subrequests_cost": {
+          "type": "float"
         },
-        "object_owner_uuid": {
-          "type": "string"
+        "output_glob": {
+          "type": "Array"
         }
       }
     },
-    "NodeList": {
-      "id": "NodeList",
-      "description": "Node list",
+    "ContainerRequestList": {
+      "id": "ContainerRequestList",
+      "description": "ContainerRequest list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#nodeList.",
-          "default": "arvados#nodeList"
+          "description": "Object type. Always arvados#containerRequestList.",
+          "default": "arvados#containerRequestList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Nodes.",
+          "description": "The list of ContainerRequests.",
           "items": {
-            "$ref": "Node"
+            "$ref": "ContainerRequest"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Nodes."
+          "description": "A link to the next page of ContainerRequests."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Nodes."
+          "description": "The page token for the next page of ContainerRequests."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Node": {
-      "id": "Node",
-      "description": "Node",
+    "ContainerRequest": {
+      "id": "ContainerRequest",
+      "description": "ContainerRequest",
       "type": "object",
-      "uuidPrefix": "7ekkf",
+      "uuidPrefix": "xvhdp",
       "properties": {
         "uuid": {
           "type": "string"
         "created_at": {
           "type": "datetime"
         },
-        "modified_by_client_uuid": {
-          "type": "string"
-        },
-        "modified_by_user_uuid": {
-          "type": "string"
-        },
         "modified_at": {
           "type": "datetime"
         },
-        "slot_number": {
-          "type": "integer"
-        },
-        "hostname": {
+        "modified_by_client_uuid": {
           "type": "string"
         },
-        "domain": {
+        "modified_by_user_uuid": {
           "type": "string"
         },
-        "ip_address": {
+        "name": {
           "type": "string"
         },
-        "last_ping_at": {
-          "type": "datetime"
+        "description": {
+          "type": "text"
         },
         "properties": {
           "type": "Hash"
         },
-        "job_uuid": {
+        "state": {
           "type": "string"
-        }
-      }
-    },
-    "PipelineInstanceList": {
-      "id": "PipelineInstanceList",
-      "description": "PipelineInstance list",
-      "type": "object",
-      "properties": {
-        "kind": {
-          "type": "string",
-          "description": "Object type. Always arvados#pipelineInstanceList.",
-          "default": "arvados#pipelineInstanceList"
         },
-        "etag": {
-          "type": "string",
-          "description": "List version."
+        "requesting_container_uuid": {
+          "type": "string"
         },
-        "items": {
-          "type": "array",
-          "description": "The list of PipelineInstances.",
-          "items": {
-            "$ref": "PipelineInstance"
-          }
+        "container_uuid": {
+          "type": "string"
         },
-        "next_link": {
-          "type": "string",
-          "description": "A link to the next page of PipelineInstances."
+        "container_count_max": {
+          "type": "integer"
         },
-        "next_page_token": {
-          "type": "string",
-          "description": "The page token for the next page of PipelineInstances."
+        "mounts": {
+          "type": "Hash"
         },
-        "selfLink": {
-          "type": "string",
-          "description": "A link back to this list."
-        }
-      }
-    },
-    "PipelineInstance": {
-      "id": "PipelineInstance",
-      "description": "PipelineInstance",
-      "type": "object",
-      "uuidPrefix": "d1hrv",
-      "properties": {
-        "uuid": {
+        "runtime_constraints": {
+          "type": "Hash"
+        },
+        "container_image": {
           "type": "string"
         },
-        "etag": {
-          "type": "string",
-          "description": "Object version."
+        "environment": {
+          "type": "Hash"
         },
-        "owner_uuid": {
+        "cwd": {
           "type": "string"
         },
-        "created_at": {
-          "type": "datetime"
+        "command": {
+          "type": "Array"
         },
-        "modified_by_client_uuid": {
+        "output_path": {
           "type": "string"
         },
-        "modified_by_user_uuid": {
-          "type": "string"
+        "priority": {
+          "type": "integer"
         },
-        "modified_at": {
+        "expires_at": {
           "type": "datetime"
         },
-        "pipeline_template_uuid": {
-          "type": "string"
+        "filters": {
+          "type": "text"
         },
-        "name": {
-          "type": "string"
+        "container_count": {
+          "type": "integer"
         },
-        "components": {
-          "type": "Hash"
+        "use_existing": {
+          "type": "boolean"
         },
-        "properties": {
+        "scheduling_parameters": {
           "type": "Hash"
         },
-        "state": {
+        "output_uuid": {
           "type": "string"
         },
-        "components_summary": {
-          "type": "Hash"
+        "log_uuid": {
+          "type": "string"
         },
-        "started_at": {
-          "type": "datetime"
+        "output_name": {
+          "type": "string"
         },
-        "finished_at": {
-          "type": "datetime"
+        "output_ttl": {
+          "type": "integer"
         },
-        "description": {
-          "type": "string"
+        "output_storage_classes": {
+          "type": "Array"
+        },
+        "output_properties": {
+          "type": "Hash"
+        },
+        "cumulative_cost": {
+          "type": "float"
+        },
+        "output_glob": {
+          "type": "Array"
         }
       }
     },
-    "PipelineTemplateList": {
-      "id": "PipelineTemplateList",
-      "description": "PipelineTemplate list",
+    "GroupList": {
+      "id": "GroupList",
+      "description": "Group list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#pipelineTemplateList.",
-          "default": "arvados#pipelineTemplateList"
+          "description": "Object type. Always arvados#groupList.",
+          "default": "arvados#groupList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of PipelineTemplates.",
+          "description": "The list of Groups.",
           "items": {
-            "$ref": "PipelineTemplate"
+            "$ref": "Group"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of PipelineTemplates."
+          "description": "A link to the next page of Groups."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of PipelineTemplates."
+          "description": "The page token for the next page of Groups."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "PipelineTemplate": {
-      "id": "PipelineTemplate",
-      "description": "PipelineTemplate",
+    "Group": {
+      "id": "Group",
+      "description": "Group",
       "type": "object",
-      "uuidPrefix": "p5p6p",
+      "uuidPrefix": "j7d0g",
       "properties": {
         "uuid": {
           "type": "string"
         "name": {
           "type": "string"
         },
-        "components": {
+        "description": {
+          "type": "string"
+        },
+        "group_class": {
+          "type": "string"
+        },
+        "trash_at": {
+          "type": "datetime"
+        },
+        "is_trashed": {
+          "type": "boolean"
+        },
+        "delete_at": {
+          "type": "datetime"
+        },
+        "properties": {
           "type": "Hash"
         },
-        "description": {
+        "frozen_by_uuid": {
           "type": "string"
         }
       }
     },
-    "RepositoryList": {
-      "id": "RepositoryList",
-      "description": "Repository list",
+    "KeepServiceList": {
+      "id": "KeepServiceList",
+      "description": "KeepService list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#repositoryList.",
-          "default": "arvados#repositoryList"
+          "description": "Object type. Always arvados#keepServiceList.",
+          "default": "arvados#keepServiceList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Repositories.",
+          "description": "The list of KeepServices.",
           "items": {
-            "$ref": "Repository"
+            "$ref": "KeepService"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Repositories."
+          "description": "A link to the next page of KeepServices."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Repositories."
+          "description": "The page token for the next page of KeepServices."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Repository": {
-      "id": "Repository",
-      "description": "Repository",
+    "KeepService": {
+      "id": "KeepService",
+      "description": "KeepService",
       "type": "object",
-      "uuidPrefix": "s0uqq",
+      "uuidPrefix": "bi6l4",
       "properties": {
         "uuid": {
           "type": "string"
         "modified_at": {
           "type": "datetime"
         },
-        "name": {
+        "service_host": {
+          "type": "string"
+        },
+        "service_port": {
+          "type": "integer"
+        },
+        "service_ssl_flag": {
+          "type": "boolean"
+        },
+        "service_type": {
           "type": "string"
         },
         "created_at": {
           "type": "datetime"
+        },
+        "read_only": {
+          "type": "boolean"
         }
       }
     },
-    "SpecimenList": {
-      "id": "SpecimenList",
-      "description": "Specimen list",
+    "LinkList": {
+      "id": "LinkList",
+      "description": "Link list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#specimenList.",
-          "default": "arvados#specimenList"
+          "description": "Object type. Always arvados#linkList.",
+          "default": "arvados#linkList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Specimens.",
+          "description": "The list of Links.",
           "items": {
-            "$ref": "Specimen"
+            "$ref": "Link"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Specimens."
+          "description": "A link to the next page of Links."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Specimens."
+          "description": "The page token for the next page of Links."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Specimen": {
-      "id": "Specimen",
-      "description": "Specimen",
+    "Link": {
+      "id": "Link",
+      "description": "Link",
       "type": "object",
-      "uuidPrefix": "j58dm",
+      "uuidPrefix": "o0j2j",
       "properties": {
         "uuid": {
           "type": "string"
         "modified_at": {
           "type": "datetime"
         },
-        "material": {
+        "tail_uuid": {
+          "type": "string"
+        },
+        "link_class": {
+          "type": "string"
+        },
+        "name": {
+          "type": "string"
+        },
+        "head_uuid": {
           "type": "string"
         },
         "properties": {
         }
       }
     },
-    "TraitList": {
-      "id": "TraitList",
-      "description": "Trait list",
+    "LogList": {
+      "id": "LogList",
+      "description": "Log list",
       "type": "object",
       "properties": {
         "kind": {
           "type": "string",
-          "description": "Object type. Always arvados#traitList.",
-          "default": "arvados#traitList"
+          "description": "Object type. Always arvados#logList.",
+          "default": "arvados#logList"
         },
         "etag": {
           "type": "string",
         },
         "items": {
           "type": "array",
-          "description": "The list of Traits.",
+          "description": "The list of Logs.",
           "items": {
-            "$ref": "Trait"
+            "$ref": "Log"
           }
         },
         "next_link": {
           "type": "string",
-          "description": "A link to the next page of Traits."
+          "description": "A link to the next page of Logs."
         },
         "next_page_token": {
           "type": "string",
-          "description": "The page token for the next page of Traits."
+          "description": "The page token for the next page of Logs."
         },
         "selfLink": {
           "type": "string",
         }
       }
     },
-    "Trait": {
-      "id": "Trait",
-      "description": "Trait",
+    "Log": {
+      "id": "Log",
+      "description": "Log",
       "type": "object",
-      "uuidPrefix": "q1cn2",
+      "uuidPrefix": "57u5n",
       "properties": {
         "uuid": {
           "type": "string"
           "type": "string",
           "description": "Object version."
         },
+        "id": {
+          "type": "integer"
+        },
         "owner_uuid": {
           "type": "string"
         },
         "modified_by_user_uuid": {
           "type": "string"
         },
-        "modified_at": {
+        "object_uuid": {
+          "type": "string"
+        },
+        "event_at": {
           "type": "datetime"
         },
-        "name": {
+        "event_type": {
           "type": "string"
         },
+        "summary": {
+          "type": "text"
+        },
         "properties": {
           "type": "Hash"
         },
         "created_at": {
           "type": "datetime"
+        },
+        "modified_at": {
+          "type": "datetime"
+        },
+        "object_owner_uuid": {
+          "type": "string"
         }
       }
     },
index bf66037a1b1c47f3b3be55c130f6df615410eb5a..eccf488efb4dca5bfadb5613336d55035238c7fa 100755 (executable)
@@ -729,58 +729,6 @@ def copy_collection(obj_uuid, src, dst, args):
     c['manifest_text'] = dst_manifest.getvalue()
     return create_collection_from(c, src, dst, args)
 
-def select_git_url(api, repo_name, retries, allow_insecure_http, allow_insecure_http_opt):
-    r = api.repositories().list(
-        filters=[['name', '=', repo_name]]).execute(num_retries=retries)
-    if r['items_available'] != 1:
-        raise Exception('cannot identify repo {}; {} repos found'
-                        .format(repo_name, r['items_available']))
-
-    https_url = [c for c in r['items'][0]["clone_urls"] if c.startswith("https:")]
-    http_url = [c for c in r['items'][0]["clone_urls"] if c.startswith("http:")]
-    other_url = [c for c in r['items'][0]["clone_urls"] if not c.startswith("http")]
-
-    priority = https_url + other_url + http_url
-
-    for url in priority:
-        if url.startswith("http"):
-            u = urllib.parse.urlsplit(url)
-            baseurl = urllib.parse.urlunsplit((u.scheme, u.netloc, "", "", ""))
-            git_config = ["-c", "credential.%s/.username=none" % baseurl,
-                          "-c", "credential.%s/.helper=!cred(){ cat >/dev/null; if [ \"$1\" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred" % baseurl]
-        else:
-            git_config = []
-
-        try:
-            logger.debug("trying %s", url)
-            subprocess.run(
-                ['git', *git_config, 'ls-remote', url],
-                check=True,
-                env={
-                    'ARVADOS_API_TOKEN': api.api_token,
-                    'GIT_ASKPASS': '/bin/false',
-                    'HOME': os.environ['HOME'],
-                },
-                stdout=subprocess.DEVNULL,
-            )
-        except subprocess.CalledProcessError:
-            pass
-        else:
-            git_url = url
-            break
-    else:
-        raise Exception('Cannot access git repository, tried {}'
-                        .format(priority))
-
-    if git_url.startswith("http:"):
-        if allow_insecure_http:
-            logger.warning("Using insecure git url %s but will allow this because %s", git_url, allow_insecure_http_opt)
-        else:
-            raise Exception("Refusing to use insecure git url %s, use %s if you really want this." % (git_url, allow_insecure_http_opt))
-
-    return (git_url, git_config)
-
-
 def copy_docker_image(docker_image, docker_image_tag, src, dst, args):
     """Copy the docker image identified by docker_image and
     docker_image_tag from src to dst. Create appropriate
index 446b95ca42c61400640a67ed632c492b64f8238a..a382d643ef39b1b688f8a803cde763b02477dc9e 100644 (file)
@@ -46,22 +46,6 @@ http {
       proxy_http_version 1.1;
     }
   }
-  upstream arv-git-http {
-    server {{UPSTREAMHOST}}:{{GITPORT}};
-  }
-  server {
-    listen {{LISTENHOST}}:{{GITSSLPORT}} ssl;
-    server_name arv-git-http git.*;
-    ssl_certificate "{{SSLCERT}}";
-    ssl_certificate_key "{{SSLKEY}}";
-    location  / {
-      proxy_pass http://arv-git-http;
-      proxy_set_header Host $http_host;
-      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-      proxy_set_header X-Forwarded-Proto https;
-      proxy_redirect off;
-    }
-  }
   upstream keepproxy {
     server {{UPSTREAMHOST}}:{{KEEPPROXYPORT}};
   }
index 787837b72334cbd58f52981d9b1d45ee216bdffb..b17f569b4d8f002d1af45f44843c1fbb608d95c0 100644 (file)
@@ -328,13 +328,6 @@ def run(leave_running_atexit=False):
     if not os.path.exists('tmp/logs'):
         os.makedirs('tmp/logs')
 
-    # Install the git repository fixtures.
-    gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
-    gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
-    if not os.path.isdir(gitdir):
-        os.makedirs(gitdir)
-    subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
-
     # Customizing the passenger config template is the only documented
     # way to override the default passenger_stat_throttle_rate (10 s).
     # In the testing environment, we want restart.txt to take effect
@@ -524,8 +517,6 @@ def run_keep(num_servers=2, **kwargs):
 
     for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
         api.keep_services().delete(uuid=d['uuid']).execute()
-    for d in api.keep_disks().list().execute()['items']:
-        api.keep_disks().delete(uuid=d['uuid']).execute()
 
     for d in range(0, num_servers):
         port = _start_keep(d, **kwargs)
@@ -536,9 +527,6 @@ def run_keep(num_servers=2, **kwargs):
             'service_type': 'disk',
             'service_ssl_flag': False,
         }}).execute()
-        api.keep_disks().create(body={
-            'keep_disk': {'keep_service_uuid': svc['uuid'] }
-        }).execute()
 
     # If keepproxy and/or keep-web is running, send SIGHUP to make
     # them discover the new keepstore services.
@@ -599,27 +587,6 @@ def stop_keep_proxy():
         return
     kill_server_pid(_pidfile('keepproxy'))
 
-def run_arv_git_httpd():
-    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
-        return
-    stop_arv_git_httpd()
-
-    gitport = internal_port_from_config("GitHTTP")
-    env = os.environ.copy()
-    env.pop('ARVADOS_API_TOKEN', None)
-    logf = open(_logfilename('githttpd'), WRITE_MODE)
-    agh = subprocess.Popen(['arvados-server', 'git-httpd'],
-        env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
-    _detachedSubprocesses.append(agh)
-    with open(_pidfile('githttpd'), 'w') as f:
-        f.write(str(agh.pid))
-    _wait_until_port_listens(gitport)
-
-def stop_arv_git_httpd():
-    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
-        return
-    kill_server_pid(_pidfile('githttpd'))
-
 def run_keep_web():
     if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
         return
@@ -656,8 +623,6 @@ def run_nginx():
     nginxconf['KEEPWEBSSLPORT'] = external_port_from_config("WebDAV")
     nginxconf['KEEPPROXYPORT'] = internal_port_from_config("Keepproxy")
     nginxconf['KEEPPROXYSSLPORT'] = external_port_from_config("Keepproxy")
-    nginxconf['GITPORT'] = internal_port_from_config("GitHTTP")
-    nginxconf['GITSSLPORT'] = external_port_from_config("GitHTTP")
     nginxconf['HEALTHPORT'] = internal_port_from_config("Health")
     nginxconf['HEALTHSSLPORT'] = external_port_from_config("Health")
     nginxconf['WSPORT'] = internal_port_from_config("Websocket")
@@ -685,7 +650,7 @@ def run_nginx():
 
     nginx = subprocess.Popen(
         ['nginx',
-         '-g', 'error_log stderr info; pid '+_pidfile('nginx')+';',
+         '-g', 'error_log stderr notice; pid '+_pidfile('nginx')+';',
          '-c', conffile],
         env=env, stdin=open('/dev/null'), stdout=sys.stderr)
     _detachedSubprocesses.append(nginx)
@@ -700,8 +665,6 @@ def setup_config():
     workbench1_external_port = find_available_port()
     workbench2_port = find_available_port()
     workbench2_external_port = find_available_port()
-    git_httpd_port = find_available_port()
-    git_httpd_external_port = find_available_port()
     health_httpd_port = find_available_port()
     health_httpd_external_port = find_available_port()
     keepproxy_port = find_available_port()
@@ -755,12 +718,6 @@ def setup_config():
                 "http://%s:%s"%(localhost, workbench2_port): {},
             },
         },
-        "GitHTTP": {
-            "ExternalURL": "https://%s:%s" % (localhost, git_httpd_external_port),
-            "InternalURLs": {
-                "http://%s:%s"%(localhost, git_httpd_port): {}
-            },
-        },
         "Health": {
             "ExternalURL": "https://%s:%s" % (localhost, health_httpd_external_port),
             "InternalURLs": {
@@ -833,13 +790,7 @@ def setup_config():
                     "ForwardSlashNameSubstitution": "/",
                     "TrashSweepInterval": "-1s",
                 },
-                "Git": {
-                    "Repositories": os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git', 'test'),
-                },
                 "Containers": {
-                    "JobsAPI": {
-                        "GitInternalDir": os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'internal.git'),
-                    },
                     "LocalKeepBlobBuffersPerVCPU": 0,
                     "Logging": {
                         "SweepInterval": 0, # disable, otherwise test cases can't acquire dblock
@@ -971,7 +922,6 @@ if __name__ == "__main__":
         'start_keep', 'stop_keep',
         'start_keep_proxy', 'stop_keep_proxy',
         'start_keep-web', 'stop_keep-web',
-        'start_githttpd', 'stop_githttpd',
         'start_nginx', 'stop_nginx', 'setup_config',
     ]
     parser = argparse.ArgumentParser()
@@ -1019,10 +969,6 @@ if __name__ == "__main__":
         run_keep_proxy()
     elif args.action == 'stop_keep_proxy':
         stop_keep_proxy()
-    elif args.action == 'start_githttpd':
-        run_arv_git_httpd()
-    elif args.action == 'stop_githttpd':
-        stop_arv_git_httpd()
     elif args.action == 'start_keep-web':
         run_keep_web()
     elif args.action == 'stop_keep-web':
index a4e943f6f235ec568d5f02ad8399c484fd89201d..7d7cc9ba596c1d224302bd540583bcbd3aab1c99 100644 (file)
@@ -67,8 +67,8 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
         self.assertIsNot(*clients)
 
     def test_empty_list(self):
-        answer = arvados.api('v1').humans().list(
-            filters=[['uuid', '=', None]]).execute()
+        answer = arvados.api('v1').collections().list(
+            filters=[['uuid', '=', 'abcdef']]).execute()
         self.assertEqual(answer['items_available'], len(answer['items']))
 
     def test_nonempty_list(self):
@@ -78,11 +78,11 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
 
     def test_timestamp_inequality_filter(self):
         api = arvados.api('v1')
-        new_item = api.specimens().create(body={}).execute()
+        new_item = api.collections().create(body={}).execute()
         for operator, should_include in [
                 ['<', False], ['>', False],
                 ['<=', True], ['>=', True], ['=', True]]:
-            response = api.specimens().list(filters=[
+            response = api.collections().list(filters=[
                 ['created_at', operator, new_item['created_at']],
                 # Also filter by uuid to ensure (if it matches) it's on page 0
                 ['uuid', '=', new_item['uuid']]]).execute()
@@ -97,13 +97,13 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
 
     def test_exceptions_include_errors(self):
         mock_responses = {
-            'arvados.humans.get': self.api_error_response(
+            'arvados.collections.get': self.api_error_response(
                 422, "Bad UUID format", "Bad output format"),
             }
         req_builder = apiclient_http.RequestMockBuilder(mock_responses)
         api = arvados.api('v1', requestBuilder=req_builder)
         with self.assertRaises(apiclient_errors.HttpError) as err_ctx:
-            api.humans().get(uuid='xyz-xyz-abcdef').execute()
+            api.collections().get(uuid='xyz-xyz-abcdef').execute()
         err_s = str(err_ctx.exception)
         for msg in ["Bad UUID format", "Bad output format"]:
             self.assertIn(msg, err_s)
@@ -123,14 +123,14 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
 
     def test_exceptions_without_errors_have_basic_info(self):
         mock_responses = {
-            'arvados.humans.delete': (
+            'arvados.collections.delete': (
                 fake_httplib2_response(500, **self.ERROR_HEADERS),
                 b"")
             }
         req_builder = apiclient_http.RequestMockBuilder(mock_responses)
         api = arvados.api('v1', requestBuilder=req_builder)
         with self.assertRaises(apiclient_errors.HttpError) as err_ctx:
-            api.humans().delete(uuid='xyz-xyz-abcdef').execute()
+            api.collections().delete(uuid='xyz-xyz-abcdef').execute()
         self.assertIn("500", str(err_ctx.exception))
 
     def test_request_too_large(self):
@@ -203,7 +203,7 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
 
     def test_ordered_json_model(self):
         mock_responses = {
-            'arvados.humans.get': (
+            'arvados.collections.get': (
                 None,
                 json.dumps(collections.OrderedDict(
                     (c, int(c, 16)) for c in string.hexdigits
@@ -213,7 +213,7 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
         req_builder = apiclient_http.RequestMockBuilder(mock_responses)
         api = arvados.api('v1',
                           requestBuilder=req_builder, model=OrderedJsonModel())
-        result = api.humans().get(uuid='test').execute()
+        result = api.collections().get(uuid='test').execute()
         self.assertEqual(string.hexdigits, ''.join(list(result.keys())))
 
     def test_api_is_threadsafe(self):
index a3a3267be7c4bde65a7dcd74cbbaf5b998a200cc..c5f33100153df3f8e824b127d35198a05834c39c 100644 (file)
@@ -97,9 +97,9 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
         # Create ancestor before subscribing.
         # When listening with start_time in the past, this should also be retrieved.
         # However, when start_time is omitted in subscribe, this should not be fetched.
-        ancestor = arvados.api('v1').humans().create(body={}).execute()
+        ancestor = arvados.api('v1').collections().create(body={}).execute()
 
-        filters = [['object_uuid', 'is_a', 'arvados#human']]
+        filters = [['object_uuid', 'is_a', 'arvados#collection']]
         if start_time:
             filters.append(['created_at', '>=', start_time])
 
@@ -118,11 +118,11 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
             while not self.ws._skip_old_events:
                 self.assertLess(time.time(), deadline)
                 time.sleep(0.1)
-        human = arvados.api('v1').humans().create(body={}).execute()
+        collection = arvados.api('v1').collections().create(body={}).execute()
 
         want_uuids = []
         if expected > 0:
-            want_uuids.append(human['uuid'])
+            want_uuids.append(collection['uuid'])
         if expected > 1:
             want_uuids.append(ancestor['uuid'])
         log_object_uuids = []
@@ -228,7 +228,7 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
         streamHandler = logging.StreamHandler(logstream)
         rootLogger.addHandler(streamHandler)
 
-        filters = [['object_uuid', 'is_a', 'arvados#human']]
+        filters = [['object_uuid', 'is_a', 'arvados#collection']]
         filters.append(['created_at', '>=', self.localiso(self.TIME_PAST)])
         self.ws = arvados.events.subscribe(
             arvados.api('v1'), filters,
@@ -239,10 +239,10 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
         self.assertEqual(200, events.get(True, 5)['status'])
 
         # create obj
-        human = arvados.api('v1').humans().create(body={}).execute()
+        collection = arvados.api('v1').collections().create(body={}).execute()
 
         # expect an event
-        self.assertIn(human['uuid'], events.get(True, 5)['object_uuid'])
+        self.assertIn(collection['uuid'], events.get(True, 5)['object_uuid'])
         with self.assertRaises(queue.Empty):
             self.assertEqual(events.get(True, 2), None)
 
@@ -253,7 +253,7 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
             self.ws.close()
 
         # create one more obj
-        human2 = arvados.api('v1').humans().create(body={}).execute()
+        collection2 = arvados.api('v1').collections().create(body={}).execute()
 
         # (un)expect the object creation event
         if close_unexpected:
@@ -264,8 +264,8 @@ class WebsocketTest(run_test_server.TestCaseWithServers):
                     log_object_uuids.append(event['object_uuid'])
             with self.assertRaises(queue.Empty):
                 self.assertEqual(events.get(True, 2), None)
-            self.assertNotIn(human['uuid'], log_object_uuids)
-            self.assertIn(human2['uuid'], log_object_uuids)
+            self.assertNotIn(collection['uuid'], log_object_uuids)
+            self.assertIn(collection2['uuid'], log_object_uuids)
         else:
             with self.assertRaises(queue.Empty):
                 self.assertEqual(events.get(True, 2), None)
index 979ab57246b0f457a0dad857c59c176531747298..a5a6bb22c143df64cea4cc36e94c62d91d7edeac 100644 (file)
@@ -56,22 +56,3 @@ class ApiClientRetryTestMixin(object):
     def test_no_retry_after_immediate_success(self):
         with tutil.mock_api_responses(self.api_client, '{}', [200, 400]):
             self.run_method()
-
-
-class CurrentJobTestCase(ApiClientRetryTestMixin, unittest.TestCase):
-
-    DEFAULT_EXCEPTION = arvados.errors.ApiError
-
-    def setUp(self):
-        super(CurrentJobTestCase, self).setUp()
-        os.environ['JOB_UUID'] = 'zzzzz-zzzzz-zzzzzzzzzzzzzzz'
-        os.environ['JOB_WORK'] = '.'
-
-    def tearDown(self):
-        del os.environ['JOB_UUID']
-        del os.environ['JOB_WORK']
-        arvados._current_job = None
-        super(CurrentJobTestCase, self).tearDown()
-
-    def run_method(self):
-        arvados.current_job()
diff --git a/services/api/app/assets/stylesheets/api_client_authorizations.css.scss b/services/api/app/assets/stylesheets/api_client_authorizations.css.scss
deleted file mode 100644 (file)
index ec87eb2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the ApiClientAuthorizations controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/api_clients.css.scss b/services/api/app/assets/stylesheets/api_clients.css.scss
deleted file mode 100644 (file)
index 61d7e53..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the ApiClients controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/authorized_keys.css.scss b/services/api/app/assets/stylesheets/authorized_keys.css.scss
deleted file mode 100644 (file)
index 9eeaa89..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the AuthorizedKeys controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/collections.css.scss b/services/api/app/assets/stylesheets/collections.css.scss
deleted file mode 100644 (file)
index 7510f17..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Collections controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/commit_ancestors.css.scss b/services/api/app/assets/stylesheets/commit_ancestors.css.scss
deleted file mode 100644 (file)
index 5004f86..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the commit_ancestors controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/commits.css.scss b/services/api/app/assets/stylesheets/commits.css.scss
deleted file mode 100644 (file)
index 6b4df4d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the commits controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/groups.css.scss b/services/api/app/assets/stylesheets/groups.css.scss
deleted file mode 100644 (file)
index 905e72a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Groups controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/humans.css.scss b/services/api/app/assets/stylesheets/humans.css.scss
deleted file mode 100644 (file)
index 29668c2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Humans controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/job_tasks.css.scss b/services/api/app/assets/stylesheets/job_tasks.css.scss
deleted file mode 100644 (file)
index 0d4d260..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the JobTasks controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/jobs.css.scss b/services/api/app/assets/stylesheets/jobs.css.scss
deleted file mode 100644 (file)
index 53b6ca7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Jobs controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/keep_disks.css.scss b/services/api/app/assets/stylesheets/keep_disks.css.scss
deleted file mode 100644 (file)
index 1996f11..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the KeepDisks controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/links.css.scss b/services/api/app/assets/stylesheets/links.css.scss
deleted file mode 100644 (file)
index c2e90ad..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the links controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/logs.css.scss b/services/api/app/assets/stylesheets/logs.css.scss
deleted file mode 100644 (file)
index c8b22f9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Logs controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/nodes.css b/services/api/app/assets/stylesheets/nodes.css
deleted file mode 100644 (file)
index d1ce011..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 */
-
-/*
-  Place all the styles related to the matching controller here.
-  They will automatically be included in application.css.
-*/
-.node-status {
-    /* unknown status - might be bad */
-    background: #ff8888;
-}
-.node-status-running .node-status {
-    background: #88ff88;
-}
-.node-status-missing .node-status {
-    background: #ff8888;
-}
-.node-status-terminated .node-status {
-    background: #ffffff;
-}
-
-.node-slurm-state {
-    /* unknown status - might be bad */
-    background: #ff8888;
-}
-.node-status-missing .node-slurm-state {
-    background: #ffffff;
-}
-.node-status-terminated .node-slurm-state {
-    background: #ffffff;
-}
-.node-status-running .node-slurm-state-alloc {
-    background: #88ff88;
-}
-.node-status-running .node-slurm-state-idle {
-    background: #ffbbbb;
-}
-.node-status-running .node-slurm-state-down {
-    background: #ff8888;
-}
diff --git a/services/api/app/assets/stylesheets/nodes.css.scss b/services/api/app/assets/stylesheets/nodes.css.scss
deleted file mode 100644 (file)
index a7b0861..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Nodes controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/pipeline_instances.css.scss b/services/api/app/assets/stylesheets/pipeline_instances.css.scss
deleted file mode 100644 (file)
index 7292a9a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the PipelineInstances controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/pipeline_templates.css.scss b/services/api/app/assets/stylesheets/pipeline_templates.css.scss
deleted file mode 100644 (file)
index 40c0cef..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the PipelineTemplates controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/repositories.css.scss b/services/api/app/assets/stylesheets/repositories.css.scss
deleted file mode 100644 (file)
index 1dd9a16..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Repositories controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/specimens.css.scss b/services/api/app/assets/stylesheets/specimens.css.scss
deleted file mode 100644 (file)
index 60d630c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Specimens controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/traits.css.scss b/services/api/app/assets/stylesheets/traits.css.scss
deleted file mode 100644 (file)
index 7d2f713..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the Traits controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/services/api/app/assets/stylesheets/virtual_machines.css.scss b/services/api/app/assets/stylesheets/virtual_machines.css.scss
deleted file mode 100644 (file)
index 4a94d45..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-// Place all the styles related to the VirtualMachines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
index ad1771a87eac936c697ae6e0ef5ba1985d599fcc..155a8e88268f11c37a0d36970c699a3622751a1c 100644 (file)
@@ -172,17 +172,7 @@ class Arvados::V1::CollectionsController < ApplicationController
       end
 
       if direction == :search_up
-        # Search upstream for jobs where this locator is the output of some job
-        if !Rails.configuration.API.DisabledAPIs["jobs.list"]
-          Job.readable_by(*@read_users).where(output: loc.to_s).each do |job|
-            search_edges(visited, job.uuid, :search_up)
-          end
-
-          Job.readable_by(*@read_users).where(log: loc.to_s).each do |job|
-            search_edges(visited, job.uuid, :search_up)
-          end
-        end
-
+        # Search upstream for jobs where this locator is the output of some container
         Container.readable_by(*@read_users).where(output: loc.to_s).pluck(:uuid).each do |c_uuid|
           search_edges(visited, c_uuid, :search_up)
         end
@@ -196,17 +186,7 @@ class Arvados::V1::CollectionsController < ApplicationController
           return
         end
 
-        # Search downstream for jobs where this locator is in script_parameters
-        if !Rails.configuration.API.DisabledAPIs["jobs.list"]
-          Job.readable_by(*@read_users).where(["jobs.script_parameters like ?", "%#{loc.to_s}%"]).each do |job|
-            search_edges(visited, job.uuid, :search_down)
-          end
-
-          Job.readable_by(*@read_users).where(["jobs.docker_image_locator = ?", "#{loc.to_s}"]).each do |job|
-            search_edges(visited, job.uuid, :search_down)
-          end
-        end
-
+        # Search downstream for jobs where this locator is in mounts
         Container.readable_by(*@read_users).where([Container.full_text_trgm + " like ?", "%#{loc.to_s}%"]).select("output, log, uuid").each do |c|
           if c.output != loc.to_s && c.log != loc.to_s
             search_edges(visited, c.uuid, :search_down)
@@ -216,21 +196,7 @@ class Arvados::V1::CollectionsController < ApplicationController
     else
       # uuid is a regular Arvados UUID
       rsc = ArvadosModel::resource_class_for_uuid uuid
-      if rsc == Job
-        Job.readable_by(*@read_users).where(uuid: uuid).each do |job|
-          visited[uuid] = job.as_api_response
-          if direction == :search_up
-            # Follow upstream collections referenced in the script parameters
-            find_collections(visited, job) do |hash, col_uuid|
-              search_edges(visited, hash, :search_up) if hash
-              search_edges(visited, col_uuid, :search_up) if col_uuid
-            end
-          elsif direction == :search_down
-            # Follow downstream job output
-            search_edges(visited, job.output, direction)
-          end
-        end
-      elsif rsc == Container
+      if rsc == Container
         c = Container.readable_by(*@read_users).where(uuid: uuid).limit(1).first
         if c
           visited[uuid] = c.as_api_response
@@ -266,16 +232,6 @@ class Arvados::V1::CollectionsController < ApplicationController
           if direction == :search_up
             visited[c.uuid] = c.as_api_response
 
-            if !Rails.configuration.API.DisabledAPIs["jobs.list"]
-              Job.readable_by(*@read_users).where(output: c.portable_data_hash).each do |job|
-                search_edges(visited, job.uuid, :search_up)
-              end
-
-              Job.readable_by(*@read_users).where(log: c.portable_data_hash).each do |job|
-                search_edges(visited, job.uuid, :search_up)
-              end
-            end
-
             ContainerRequest.readable_by(*@read_users).where(output_uuid: uuid).pluck(:uuid).each do |cr_uuid|
               search_edges(visited, cr_uuid, :search_up)
             end
index c362cf32d7e271c35891f10a33cf2f970503c09d..be73d39dd1b43ba2032d22afdf8837cd17e750bb 100644 (file)
@@ -218,10 +218,7 @@ class Arvados::V1::GroupsController < ApplicationController
 
     request_filters = @filters
 
-    klasses = [Group,
-     Job, PipelineInstance, PipelineTemplate, ContainerRequest, Workflow,
-     Collection,
-     Human, Specimen, Trait]
+    klasses = [Group, ContainerRequest, Workflow, Collection]
 
     table_names = Hash[klasses.collect { |k| [k, k.table_name] }]
 
diff --git a/services/api/app/controllers/arvados/v1/humans_controller.rb b/services/api/app/controllers/arvados/v1/humans_controller.rb
deleted file mode 100644 (file)
index 88eee30..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::HumansController < ApplicationController
-end
diff --git a/services/api/app/controllers/arvados/v1/job_tasks_controller.rb b/services/api/app/controllers/arvados/v1/job_tasks_controller.rb
deleted file mode 100644 (file)
index b960d2e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::JobTasksController < ApplicationController
-  accept_attribute_as_json :parameters, Hash
-
-  def create
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/jobs_controller.rb b/services/api/app/controllers/arvados/v1/jobs_controller.rb
deleted file mode 100644 (file)
index 2d6b052..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::JobsController < ApplicationController
-  accept_attribute_as_json :components, Hash
-  accept_attribute_as_json :script_parameters, Hash
-  accept_attribute_as_json :runtime_constraints, Hash
-  accept_attribute_as_json :tasks_summary, Hash
-  skip_before_action :find_object_by_uuid, :only => [:queue, :queue_size]
-  skip_before_action :render_404_if_no_object, :only => [:queue, :queue_size]
-
-  include DbCurrentTime
-
-  def create
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-
-  def cancel
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-
-  def lock
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-
-  def queue
-    @objects = []
-    index
-  end
-
-  def queue_size
-    render :json => {:queue_size => 0}
-  end
-
-  def self._create_requires_parameters
-    (super rescue {}).
-      merge({
-              find_or_create: {
-                type: 'boolean', required: false, default: false,
-              },
-              filters: {
-                type: 'array', required: false,
-              },
-              minimum_script_version: {
-                type: 'string', required: false,
-              },
-              exclude_script_versions: {
-                type: 'array', required: false,
-              },
-            })
-  end
-
-  def self._queue_requires_parameters
-    self._index_requires_parameters
-  end
-
-  protected
-
-  def load_filters_param
-    begin
-      super
-      attrs = resource_attrs rescue {}
-      @filters = Job.load_job_specific_filters attrs, @filters, @read_users
-    rescue ArgumentError => error
-      send_error(error.message)
-      false
-    else
-      true
-    end
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
deleted file mode 100644 (file)
index b8aa096..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::KeepDisksController < ApplicationController
-  skip_before_action :require_auth_scope, only: :ping
-  skip_before_action :render_404_if_no_object, only: :ping
-
-  def self._ping_requires_parameters
-    {
-      uuid: {required: false},
-      ping_secret: {required: true},
-      node_uuid: {required: false},
-      filesystem_uuid: {required: false},
-      service_host: {required: false},
-      service_port: {required: true},
-      service_ssl_flag: {required: true}
-    }
-  end
-
-  def ping
-    params[:service_host] ||= request.env['REMOTE_ADDR']
-    if !params[:uuid] && current_user.andand.is_admin
-      # Create a new KeepDisk and ping it.
-      @object = KeepDisk.new(filesystem_uuid: params[:filesystem_uuid])
-      @object.save!
-
-      # In the first ping from this new filesystem_uuid, we can't
-      # expect the keep node to know the ping_secret so we made sure
-      # we got an admin token. Here we add ping_secret to params so
-      # the ping call below is properly authenticated.
-      params[:ping_secret] = @object.ping_secret
-    end
-    act_as_system_user do
-      if !@object.andand.ping(params)
-        return render_not_found "object not found"
-      end
-      # Render the :superuser view (i.e., include the ping_secret) even
-      # if !current_user.is_admin. This is safe because @object.ping's
-      # success implies the ping_secret was already known by the client.
-      send_json @object.as_api_response(:superuser)
-    end
-  end
-
-  def find_objects_for_index
-    # all users can list all keep disks
-    @objects = model_class.where('1=1')
-    super
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/nodes_controller.rb b/services/api/app/controllers/arvados/v1/nodes_controller.rb
deleted file mode 100644 (file)
index 2510fd4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::NodesController < ApplicationController
-  skip_before_action :require_auth_scope, :only => :ping
-  skip_before_action :find_object_by_uuid, :only => :ping
-  skip_before_action :render_404_if_no_object, :only => :ping
-
-  include DbCurrentTime
-
-  def self._ping_requires_parameters
-    { ping_secret: {required: true} }
-  end
-
-  def self._create_requires_parameters
-    super.merge(
-      { assign_slot: {required: false, type: 'boolean', description: 'assign slot and hostname'} })
-  end
-
-  def self._update_requires_parameters
-    super.merge(
-      { assign_slot: {required: false, type: 'boolean', description: 'assign slot and hostname'} })
-  end
-
-  def create
-    @object = model_class.new(resource_attrs)
-    @object.assign_slot if params[:assign_slot]
-    @object.save!
-    show
-  end
-
-  def update
-    if resource_attrs[:job_uuid].is_a? String
-      @object.job_readable = readable_job_uuids([resource_attrs[:job_uuid]]).any?
-    end
-    attrs_to_update = resource_attrs.reject { |k,v|
-      [:kind, :etag, :href].index k
-    }
-    @object.update!(attrs_to_update)
-    @object.assign_slot if params[:assign_slot]
-    @object.save!
-    show
-  end
-
-  def ping
-    act_as_system_user do
-      @object = Node.where(uuid: (params[:id] || params[:uuid])).first
-      if !@object
-        return render_not_found
-      end
-      ping_data = {
-        ip: params[:local_ipv4] || request.remote_ip,
-        ec2_instance_id: params[:instance_id]
-      }
-      [:ping_secret, :total_cpu_cores, :total_ram_mb, :total_scratch_mb]
-        .each do |key|
-        ping_data[key] = params[key] if params[key]
-      end
-      @object.ping(ping_data)
-      if @object.info['ping_secret'] == params[:ping_secret]
-        send_json @object.as_api_response(:superuser)
-      else
-        raise "Invalid ping_secret after ping"
-      end
-    end
-  end
-
-  def find_objects_for_index
-    if !current_user.andand.is_admin && current_user.andand.is_active
-      # active non-admin users can list nodes that are (or were
-      # recently) working
-      @objects = model_class.where('last_ping_at >= ?', db_current_time - 1.hours)
-    end
-    super
-    if @select.nil? or @select.include? 'job_uuid'
-      job_uuids = @objects.map { |n| n[:job_uuid] }.compact
-      assoc_jobs = readable_job_uuids(job_uuids)
-      @objects.each do |node|
-        node.job_readable = assoc_jobs.include?(node[:job_uuid])
-      end
-    end
-  end
-
-  protected
-
-  def readable_job_uuids(uuids)
-    Job.readable_by(*@read_users).select(:uuid).where(uuid: uuids).map(&:uuid)
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/pipeline_instances_controller.rb b/services/api/app/controllers/arvados/v1/pipeline_instances_controller.rb
deleted file mode 100644 (file)
index 166f710..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::PipelineInstancesController < ApplicationController
-  accept_attribute_as_json :components, Hash
-  accept_attribute_as_json :properties, Hash
-  accept_attribute_as_json :components_summary, Hash
-
-  def create
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-
-  def cancel
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/pipeline_templates_controller.rb b/services/api/app/controllers/arvados/v1/pipeline_templates_controller.rb
deleted file mode 100644 (file)
index 4a5e724..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::PipelineTemplatesController < ApplicationController
-  accept_attribute_as_json :components, Hash
-
-  def create
-    return send_error("Unsupported legacy jobs API",
-                      status: 400)
-  end
-end
diff --git a/services/api/app/controllers/arvados/v1/repositories_controller.rb b/services/api/app/controllers/arvados/v1/repositories_controller.rb
deleted file mode 100644 (file)
index 9dff622..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::RepositoriesController < ApplicationController
-  skip_before_action :find_object_by_uuid, :only => :get_all_permissions
-  skip_before_action :render_404_if_no_object, :only => :get_all_permissions
-  before_action :admin_required, :only => :get_all_permissions
-
-  def get_all_permissions
-    # user_aks is a map of {user_uuid => array of public keys}
-    user_aks = {}
-    # admins is an array of user_uuids
-    admins = []
-    User.
-      where('users.is_active = ? or users.uuid = ?', true, anonymous_user_uuid).
-      eager_load(:authorized_keys).find_each do |u|
-      user_aks[u.uuid] = u.authorized_keys.collect do |ak|
-        {
-          public_key: ak.public_key,
-          authorized_key_uuid: ak.uuid
-        }
-      end
-      admins << u.uuid if u.is_admin
-    end
-    all_group_permissions = User.all_group_permissions
-    @repo_info = {}
-    Repository.eager_load(:permissions).find_each do |repo|
-      @repo_info[repo.uuid] = {
-        uuid: repo.uuid,
-        name: repo.name,
-        push_url: repo.push_url,
-        fetch_url: repo.fetch_url,
-        user_permissions: {},
-      }
-      # evidence is an array of {name: 'can_xxx', user_uuid: 'x-y-z'},
-      # one entry for each piece of evidence we find in the permission
-      # database that establishes that a user can access this
-      # repository. Multiple entries can be added for a given user,
-      # possibly with different access levels; these will be compacted
-      # below.
-      evidence = []
-      repo.permissions.each do |perm|
-        if ArvadosModel::resource_class_for_uuid(perm.tail_uuid) == Group
-          # A group has permission. Each user who has access to this
-          # group also has access to the repository. Access level is
-          # min(group-to-repo permission, user-to-group permission).
-          user_aks.each do |user_uuid, _|
-            perm_mask = all_group_permissions[user_uuid].andand[perm.tail_uuid]
-            if not perm_mask
-              next
-            elsif perm_mask[:manage] and perm.name == 'can_manage'
-              evidence << {name: 'can_manage', user_uuid: user_uuid}
-            elsif perm_mask[:write] and ['can_manage', 'can_write'].index perm.name
-              evidence << {name: 'can_write', user_uuid: user_uuid}
-            elsif perm_mask[:read]
-              evidence << {name: 'can_read', user_uuid: user_uuid}
-            end
-          end
-        elsif user_aks.has_key?(perm.tail_uuid)
-          # A user has permission; the user exists; and either the
-          # user is active, or it's the special case of the anonymous
-          # user which is never "active" but is allowed to read
-          # content from public repositories.
-          evidence << {name: perm.name, user_uuid: perm.tail_uuid}
-        end
-      end
-      # Owner of the repository, and all admins, can do everything.
-      ([repo.owner_uuid] | admins).each do |user_uuid|
-        # Except: no permissions for inactive users, even if they own
-        # repositories.
-        next unless user_aks.has_key?(user_uuid)
-        evidence << {name: 'can_manage', user_uuid: user_uuid}
-      end
-      # Distill all the evidence about permissions on this repository
-      # into one hash per user, of the form {'can_xxx' => true, ...}.
-      # The hash is nil for a user who has no permissions at all on
-      # this particular repository.
-      evidence.each do |perm|
-        user_uuid = perm[:user_uuid]
-        user_perms = (@repo_info[repo.uuid][:user_permissions][user_uuid] ||= {})
-        user_perms[perm[:name]] = true
-      end
-    end
-    # Revisit each {'can_xxx' => true, ...} hash for some final
-    # cleanup to make life easier for the requestor.
-    #
-    # Add a 'gitolite_permissions' key alongside the 'can_xxx' keys,
-    # for the convenience of the gitolite config file generator.
-    #
-    # Add all lesser permissions when a greater permission is
-    # present. If the requestor only wants to know who can write, it
-    # only has to test for 'can_write' in the response.
-    @repo_info.values.each do |repo|
-      repo[:user_permissions].each do |user_uuid, user_perms|
-        if user_perms['can_manage']
-          user_perms['gitolite_permissions'] = 'RW+'
-          user_perms['can_write'] = true
-          user_perms['can_read'] = true
-        elsif user_perms['can_write']
-          user_perms['gitolite_permissions'] = 'RW+'
-          user_perms['can_read'] = true
-        elsif user_perms['can_read']
-          user_perms['gitolite_permissions'] = 'R'
-        end
-      end
-    end
-    # The response looks like
-    #   {"kind":"...",
-    #    "repositories":[r1,r2,r3,...],
-    #    "user_keys":usermap}
-    # where each of r1,r2,r3 looks like
-    #   {"uuid":"repo-uuid-1",
-    #    "name":"username/reponame",
-    #    "push_url":"...",
-    #    "user_permissions":{"user-uuid-a":{"can_read":true,"gitolite_permissions":"R"}}}
-    # and usermap looks like
-    #   {"user-uuid-a":[{"public_key":"ssh-rsa g...","authorized_key_uuid":"ak-uuid-g"},...],
-    #    "user-uuid-b":[{"public_key":"ssh-rsa h...","authorized_key_uuid":"ak-uuid-h"},...],...}
-    send_json(kind: 'arvados#RepositoryPermissionSnapshot',
-              repositories: @repo_info.values,
-              user_keys: user_aks)
-  end
-end
index 74aa4078cbea66a6da3138cfd4a46f9ece81e350..ca803fd3863c200affa9c4ad6674648730959545 100644 (file)
@@ -72,7 +72,6 @@ class Arvados::V1::SchemaController < ApplicationController
       workbenchUrl: Rails.configuration.Services.Workbench1.ExternalURL.to_s,
       workbench2Url: Rails.configuration.Services.Workbench2.ExternalURL.to_s,
       keepWebServiceUrl: Rails.configuration.Services.WebDAV.ExternalURL.to_s,
-      gitUrl: Rails.configuration.Services.GitHTTP.ExternalURL.to_s,
       parameters: {
         alt: {
           type: "string",
@@ -484,6 +483,7 @@ class Arvados::V1::SchemaController < ApplicationController
 
     Rails.configuration.API.DisabledAPIs.each do |method, _|
       ctrl, action = method.to_s.split('.', 2)
+      next if ctrl.in?(['job_tasks', 'jobs', 'keep_disks', 'nodes', 'pipeline_instances', 'pipeline_templates', 'repositories'])
       discovery[:resources][ctrl][:methods].delete(action.to_sym)
     end
     discovery
diff --git a/services/api/app/controllers/arvados/v1/specimens_controller.rb b/services/api/app/controllers/arvados/v1/specimens_controller.rb
deleted file mode 100644 (file)
index b1e50a7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::SpecimensController < ApplicationController
-end
diff --git a/services/api/app/controllers/arvados/v1/traits_controller.rb b/services/api/app/controllers/arvados/v1/traits_controller.rb
deleted file mode 100644 (file)
index 7aaed5c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Arvados::V1::TraitsController < ApplicationController
-end
index 031dd2e4f92ba7c1764756027cef95db0afa5714..418295d26a6f25cfac66ad18cead7e31cbbc7b61 100644 (file)
@@ -123,8 +123,7 @@ class Arvados::V1::UsersController < ApplicationController
       full_repo_name = "#{@object.username}/#{params[:repo_name]}"
     end
 
-    @response = @object.setup(repo_name: full_repo_name,
-                              vm_uuid: params[:vm_uuid],
+    @response = @object.setup(vm_uuid: params[:vm_uuid],
                               send_notification_email: params[:send_notification_email])
 
     send_json kind: "arvados#HashList", items: @response.as_api_response(nil)
diff --git a/services/api/app/helpers/api_client_authorizations_helper.rb b/services/api/app/helpers/api_client_authorizations_helper.rb
deleted file mode 100644 (file)
index e1066ba..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module ApiClientAuthorizationsHelper
-end
diff --git a/services/api/app/helpers/api_clients_helper.rb b/services/api/app/helpers/api_clients_helper.rb
deleted file mode 100644 (file)
index 9604777..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module ApiClientsHelper
-end
diff --git a/services/api/app/helpers/authorized_keys_helper.rb b/services/api/app/helpers/authorized_keys_helper.rb
deleted file mode 100644 (file)
index 665fff7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module AuthorizedKeysHelper
-end
diff --git a/services/api/app/helpers/collections_helper.rb b/services/api/app/helpers/collections_helper.rb
deleted file mode 100644 (file)
index ca44f47..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module CollectionsHelper
-end
diff --git a/services/api/app/helpers/commits_helper.rb b/services/api/app/helpers/commits_helper.rb
deleted file mode 100644 (file)
index fdb83a0..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module CommitsHelper
-  extend CurrentApiClient
-
-  class GitError < RequestError
-    def http_status
-      422
-    end
-  end
-
-  def self.git_check_ref_format(e)
-    if !e or e.empty? or e[0] == '-' or e[0] == '$'
-      # definitely not valid
-      false
-    else
-      `git check-ref-format --allow-onelevel #{e.shellescape}`
-      $?.success?
-    end
-  end
-
-  # Return an array of commits (each a 40-char sha1) satisfying the
-  # given criteria.
-  #
-  # Return [] if the revisions given in minimum/maximum are invalid or
-  # don't exist in the given repository.
-  #
-  # Raise ArgumentError if the given repository is invalid, does not
-  # exist, or cannot be read for any reason. (Any transient error that
-  # prevents commit ranges from resolving must raise rather than
-  # returning an empty array.)
-  #
-  # repository can be the name of a locally hosted repository or a git
-  # URL (see git-fetch(1)). Currently http, https, and git schemes are
-  # supported.
-  def self.find_commit_range repository, minimum, maximum, exclude
-    if minimum and minimum.empty?
-      minimum = nil
-    end
-
-    if minimum and !git_check_ref_format(minimum)
-      Rails.logger.warn "find_commit_range called with invalid minimum revision: '#{minimum}'"
-      return []
-    end
-
-    if maximum and !git_check_ref_format(maximum)
-      Rails.logger.warn "find_commit_range called with invalid maximum revision: '#{maximum}'"
-      return []
-    end
-
-    if !maximum
-      maximum = "HEAD"
-    end
-
-    gitdir, is_remote = git_dir_for repository
-    fetch_remote_repository gitdir, repository if is_remote
-    ENV['GIT_DIR'] = gitdir
-
-    commits = []
-
-    # Get the commit hash for the upper bound
-    max_hash = nil
-    git_max_hash_cmd = "git rev-list --max-count=1 #{maximum.shellescape} --"
-    IO.foreach("|#{git_max_hash_cmd}") do |line|
-      max_hash = line.strip
-    end
-
-    # If not found, nothing else to do
-    if !max_hash
-      Rails.logger.warn "no refs found looking for max_hash: `GIT_DIR=#{gitdir} #{git_max_hash_cmd}` returned no output"
-      return []
-    end
-
-    # If string is invalid, nothing else to do
-    if !git_check_ref_format(max_hash)
-      Rails.logger.warn "ref returned by `GIT_DIR=#{gitdir} #{git_max_hash_cmd}` was invalid for max_hash: #{max_hash}"
-      return []
-    end
-
-    resolved_exclude = nil
-    if exclude
-      resolved_exclude = []
-      exclude.each do |e|
-        if git_check_ref_format(e)
-          IO.foreach("|git rev-list --max-count=1 #{e.shellescape} --") do |line|
-            resolved_exclude.push(line.strip)
-          end
-        else
-          Rails.logger.warn "find_commit_range called with invalid exclude invalid characters: '#{exclude}'"
-          return []
-        end
-      end
-    end
-
-    if minimum
-      # Get the commit hash for the lower bound
-      min_hash = nil
-      git_min_hash_cmd = "git rev-list --max-count=1 #{minimum.shellescape} --"
-      IO.foreach("|#{git_min_hash_cmd}") do |line|
-        min_hash = line.strip
-      end
-
-      # If not found, nothing else to do
-      if !min_hash
-        Rails.logger.warn "no refs found looking for min_hash: `GIT_DIR=#{gitdir} #{git_min_hash_cmd}` returned no output"
-        return []
-      end
-
-      # If string is invalid, nothing else to do
-      if !git_check_ref_format(min_hash)
-        Rails.logger.warn "ref returned by `GIT_DIR=#{gitdir} #{git_min_hash_cmd}` was invalid for min_hash: #{min_hash}"
-        return []
-      end
-
-      # Now find all commits between them
-      IO.foreach("|git rev-list #{min_hash.shellescape}..#{max_hash.shellescape} --") do |line|
-        hash = line.strip
-        commits.push(hash) if !resolved_exclude or !resolved_exclude.include? hash
-      end
-
-      commits.push(min_hash) if !resolved_exclude or !resolved_exclude.include? min_hash
-    else
-      commits.push(max_hash) if !resolved_exclude or !resolved_exclude.include? max_hash
-    end
-
-    commits
-  end
-
-  # Given a repository (url, or name of hosted repo) and commit sha1,
-  # copy the commit into the internal git repo (if necessary), and tag
-  # it with the given tag (typically a job UUID).
-  #
-  # The repo can be a remote url, but in this case sha1 must already
-  # be present in our local cache for that repo: e.g., sha1 was just
-  # returned by find_commit_range.
-  def self.tag_in_internal_repository repo_name, sha1, tag
-    unless git_check_ref_format tag
-      raise ArgumentError.new "invalid tag #{tag}"
-    end
-    unless /^[0-9a-f]{40}$/ =~ sha1
-      raise ArgumentError.new "invalid sha1 #{sha1}"
-    end
-    src_gitdir, _ = git_dir_for repo_name
-    unless src_gitdir
-      raise ArgumentError.new "no local repository for #{repo_name}"
-    end
-    dst_gitdir = Rails.configuration.Containers.JobsAPI.GitInternalDir
-
-    begin
-      commit_in_dst = must_git(dst_gitdir, "log -n1 --format=%H #{sha1.shellescape}^{commit}").strip
-    rescue GitError
-      commit_in_dst = false
-    end
-
-    tag_cmd = "tag --force #{tag.shellescape} #{sha1.shellescape}^{commit}"
-    if commit_in_dst == sha1
-      must_git(dst_gitdir, tag_cmd)
-    else
-      # git-fetch is faster than pack-objects|unpack-objects, but
-      # git-fetch can't fetch by sha1. So we first try to fetch a
-      # branch that has the desired commit, and if that fails (there
-      # is no such branch, or the branch we choose changes under us in
-      # race), we fall back to pack|unpack.
-      begin
-        branches = must_git(src_gitdir,
-                            "branch --contains #{sha1.shellescape}")
-        m = branches.match(/^. (\w+)\n/)
-        if !m
-          raise GitError.new "commit is not on any branch"
-        end
-        branch = m[1]
-        must_git(dst_gitdir,
-                 "fetch file://#{src_gitdir.shellescape} #{branch.shellescape}")
-        # Even if all of the above steps succeeded, we might still not
-        # have the right commit due to a race, in which case tag_cmd
-        # will fail, and we'll need to fall back to pack|unpack. So
-        # don't be tempted to condense this tag_cmd and the one in the
-        # rescue block into a single attempt.
-        must_git(dst_gitdir, tag_cmd)
-      rescue GitError
-        must_pipe("echo #{sha1.shellescape}",
-                  "git --git-dir #{src_gitdir.shellescape} pack-objects -q --revs --stdout",
-                  "git --git-dir #{dst_gitdir.shellescape} unpack-objects -q")
-        must_git(dst_gitdir, tag_cmd)
-      end
-    end
-  end
-
-  protected
-
-  def self.remote_url? repo_name
-    /^(https?|git):\/\// =~ repo_name
-  end
-
-  # Return [local_git_dir, is_remote]. If is_remote, caller must use
-  # fetch_remote_repository to ensure content is up-to-date.
-  #
-  # Raises an exception if the latest content could not be fetched for
-  # any reason.
-  def self.git_dir_for repo_name
-    if remote_url? repo_name
-      return [cache_dir_for(repo_name), true]
-    end
-    repos = Repository.readable_by(current_user).where(name: repo_name)
-    if repos.count == 0
-      raise ArgumentError.new "Repository not found: '#{repo_name}'"
-    elsif repos.count > 1
-      Rails.logger.error "Multiple repositories with name=='#{repo_name}'!"
-      raise ArgumentError.new "Name conflict"
-    else
-      return [repos.first.server_path, false]
-    end
-  end
-
-  def self.cache_dir_for git_url
-    File.join(cache_dir_base, Digest::SHA1.hexdigest(git_url) + ".git").to_s
-  end
-
-  def self.cache_dir_base
-    Rails.root.join 'tmp', 'git-cache'
-  end
-
-  def self.fetch_remote_repository gitdir, git_url
-    # Caller decides which protocols are worth using. This is just a
-    # safety check to ensure we never use urls like "--flag" or wander
-    # into git's hardlink features by using bare "/path/foo" instead
-    # of "file:///path/foo".
-    unless /^[a-z]+:\/\// =~ git_url
-      raise ArgumentError.new "invalid git url #{git_url}"
-    end
-    begin
-      must_git gitdir, "branch"
-    rescue GitError => e
-      raise unless /Not a git repository/i =~ e.to_s
-      # OK, this just means we need to create a blank cache repository
-      # before fetching.
-      FileUtils.mkdir_p gitdir
-      must_git gitdir, "init"
-    end
-    must_git(gitdir,
-             "fetch --no-progress --tags --prune --force --update-head-ok #{git_url.shellescape} 'refs/heads/*:refs/heads/*'")
-  end
-
-  def self.must_git gitdir, *cmds
-    # Clear token in case a git helper tries to use it as a password.
-    orig_token = ENV['ARVADOS_API_TOKEN']
-    ENV['ARVADOS_API_TOKEN'] = ''
-    last_output = ''
-    begin
-      git = "git --git-dir #{gitdir.shellescape}"
-      cmds.each do |cmd|
-        last_output = must_pipe git+" "+cmd
-      end
-    ensure
-      ENV['ARVADOS_API_TOKEN'] = orig_token
-    end
-    return last_output
-  end
-
-  def self.must_pipe *cmds
-    cmd = cmds.join(" 2>&1 |") + " 2>&1"
-    out = IO.read("| </dev/null #{cmd}")
-    if not $?.success?
-      raise GitError.new "#{cmd}: #{$?}: #{out}"
-    end
-    return out
-  end
-end
diff --git a/services/api/app/helpers/groups_helper.rb b/services/api/app/helpers/groups_helper.rb
deleted file mode 100644 (file)
index 5464d96..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module GroupsHelper
-end
diff --git a/services/api/app/helpers/humans_helper.rb b/services/api/app/helpers/humans_helper.rb
deleted file mode 100644 (file)
index e9b4c96..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module HumansHelper
-end
diff --git a/services/api/app/helpers/job_tasks_helper.rb b/services/api/app/helpers/job_tasks_helper.rb
deleted file mode 100644 (file)
index ae78d75..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module JobTasksHelper
-end
diff --git a/services/api/app/helpers/jobs_helper.rb b/services/api/app/helpers/jobs_helper.rb
deleted file mode 100644 (file)
index ba3f715..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module JobsHelper
-end
diff --git a/services/api/app/helpers/keep_disks_helper.rb b/services/api/app/helpers/keep_disks_helper.rb
deleted file mode 100644 (file)
index 19386c9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module KeepDisksHelper
-end
diff --git a/services/api/app/helpers/links_helper.rb b/services/api/app/helpers/links_helper.rb
deleted file mode 100644 (file)
index 422a42d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module LinksHelper
-end
diff --git a/services/api/app/helpers/logs_helper.rb b/services/api/app/helpers/logs_helper.rb
deleted file mode 100644 (file)
index 9b767d3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module LogsHelper
-end
diff --git a/services/api/app/helpers/nodes_helper.rb b/services/api/app/helpers/nodes_helper.rb
deleted file mode 100644 (file)
index cd1ecc9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module NodesHelper
-end
diff --git a/services/api/app/helpers/pipeline_instances_helper.rb b/services/api/app/helpers/pipeline_instances_helper.rb
deleted file mode 100644 (file)
index 79c2e09..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module PipelineInstancesHelper
-end
diff --git a/services/api/app/helpers/pipeline_templates_helper.rb b/services/api/app/helpers/pipeline_templates_helper.rb
deleted file mode 100644 (file)
index 135b525..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module PipelineTemplatesHelper
-end
diff --git a/services/api/app/helpers/repositories_helper.rb b/services/api/app/helpers/repositories_helper.rb
deleted file mode 100644 (file)
index 04ef0f1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module RepositoriesHelper
-end
diff --git a/services/api/app/helpers/specimens_helper.rb b/services/api/app/helpers/specimens_helper.rb
deleted file mode 100644 (file)
index 5c7e98a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module SpecimensHelper
-end
diff --git a/services/api/app/helpers/traits_helper.rb b/services/api/app/helpers/traits_helper.rb
deleted file mode 100644 (file)
index 35ae11d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module TraitsHelper
-end
diff --git a/services/api/app/helpers/virtual_machines_helper.rb b/services/api/app/helpers/virtual_machines_helper.rb
deleted file mode 100644 (file)
index 7d2b08f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-module VirtualMachinesHelper
-end
diff --git a/services/api/app/models/human.rb b/services/api/app/models/human.rb
deleted file mode 100644 (file)
index 6897282..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Human < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :properties, Hash
-
-  api_accessible :user, extend: :common do |t|
-    t.add :properties
-  end
-end
diff --git a/services/api/app/models/job.rb b/services/api/app/models/job.rb
deleted file mode 100644 (file)
index 029a313..0000000
+++ /dev/null
@@ -1,564 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-#
-#
-# Legacy jobs API aka crunch v1
-#
-# This is superceded by containers / container_requests (aka crunch v2)
-#
-# Arvados installations since the end of 2017 should have never
-# used jobs, and are unaffected by this change.
-#
-# So that older Arvados sites don't lose access to legacy records, the
-# API has been converted to read-only.  Creating and updating jobs
-# (and related types job_task, pipeline_template and
-# pipeline_instance) is disabled and much of the business logic
-# related has been removed, along with the crunch-dispatch.rb and
-# various other code specific to the jobs API.
-#
-# If you need to resurrect any of this code, here is the last commit
-# on master before the branch removing jobs API support:
-#
-# Wed Aug 7 14:49:38 2019 -0400 07d92519438a592d531f2c7558cd51788da262ca
-
-require 'log_reuse_info'
-require 'safe_json'
-
-class Job < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  extend CurrentApiClient
-  extend LogReuseInfo
-  serialize :components, Hash
-  serialize :script_parameters, Hash
-  serialize :runtime_constraints, Hash
-  serialize :tasks_summary, Hash
-  before_create :ensure_unique_submit_id
-  before_validation :set_priority
-  before_validation :update_state_from_old_state_attrs
-  before_validation :update_script_parameters_digest
-  validate :ensure_script_version_is_commit
-  validate :find_docker_image_locator
-  validate :find_arvados_sdk_version
-  validate :validate_status
-  validate :validate_state_change
-  validate :ensure_no_collection_uuids_in_script_params
-  before_save :tag_version_in_internal_repository
-  before_save :update_timestamps_when_state_changes
-  before_create :create_disabled
-  before_update :update_disabled
-
-  has_many(:nodes, foreign_key: 'job_uuid', primary_key: 'uuid')
-
-  class SubmitIdReused < RequestError
-  end
-
-  api_accessible :user, extend: :common do |t|
-    t.add :submit_id
-    t.add :priority
-    t.add :script
-    t.add :script_parameters
-    t.add :script_version
-    t.add :cancelled_at
-    t.add :cancelled_by_client_uuid
-    t.add :cancelled_by_user_uuid
-    t.add :started_at
-    t.add :finished_at
-    t.add :output
-    t.add :success
-    t.add :running
-    t.add :state
-    t.add :is_locked_by_uuid
-    t.add :log
-    t.add :runtime_constraints
-    t.add :tasks_summary
-    t.add :nondeterministic
-    t.add :repository
-    t.add :supplied_script_version
-    t.add :arvados_sdk_version
-    t.add :docker_image_locator
-    t.add :queue_position
-    t.add :node_uuids
-    t.add :description
-    t.add :components
-  end
-
-  # Supported states for a job
-  States = [
-            (Queued = 'Queued'),
-            (Running = 'Running'),
-            (Cancelled = 'Cancelled'),
-            (Failed = 'Failed'),
-            (Complete = 'Complete'),
-           ]
-
-  after_initialize do
-    @need_crunch_dispatch_trigger = false
-  end
-
-  def self.limit_index_columns_read
-    ["components"]
-  end
-
-  def self.protected_attributes
-    [:arvados_sdk_version, :docker_image_locator]
-  end
-
-  def assert_finished
-    update(finished_at: finished_at || db_current_time,
-                      success: success.nil? ? false : success,
-                      running: false)
-  end
-
-  def node_uuids
-    nodes.map(&:uuid)
-  end
-
-  def self.queue
-    self.where('state = ?', Queued).order('priority desc, created_at')
-  end
-
-  def queue_position
-    # We used to report this accurately, but the implementation made queue
-    # API requests O(n**2) for the size of the queue.  See #8800.
-    # We've soft-disabled it because it's not clear we even want this
-    # functionality: now that we have Node Manager with support for multiple
-    # node sizes, "queue position" tells you very little about when a job will
-    # run.
-    state == Queued ? 0 : nil
-  end
-
-  def self.running
-    self.where('running = ?', true).
-      order('priority desc, created_at')
-  end
-
-  def lock locked_by_uuid
-    with_lock do
-      unless self.state == Queued and self.is_locked_by_uuid.nil?
-        raise AlreadyLockedError
-      end
-      self.state = Running
-      self.is_locked_by_uuid = locked_by_uuid
-      self.save!
-    end
-  end
-
-  def update_script_parameters_digest
-    self.script_parameters_digest = self.class.sorted_hash_digest(script_parameters)
-  end
-
-  def self.searchable_columns operator
-    super - ["script_parameters_digest"]
-  end
-
-  def self.full_text_searchable_columns
-    super - ["script_parameters_digest"]
-  end
-
-  def self.load_job_specific_filters attrs, orig_filters, read_users
-    # Convert Job-specific @filters entries into general SQL filters.
-    script_info = {"repository" => nil, "script" => nil}
-    git_filters = Hash.new do |hash, key|
-      hash[key] = {"max_version" => "HEAD", "exclude_versions" => []}
-    end
-    filters = []
-    orig_filters.each do |attr, operator, operand|
-      if (script_info.has_key? attr) and (operator == "=")
-        if script_info[attr].nil?
-          script_info[attr] = operand
-        elsif script_info[attr] != operand
-          raise ArgumentError.new("incompatible #{attr} filters")
-        end
-      end
-      case operator
-      when "in git"
-        git_filters[attr]["min_version"] = operand
-      when "not in git"
-        git_filters[attr]["exclude_versions"] += Array.wrap(operand)
-      when "in docker", "not in docker"
-        image_hashes = Array.wrap(operand).flat_map do |search_term|
-          image_search, image_tag = search_term.split(':', 2)
-          Collection.
-            find_all_for_docker_image(image_search, image_tag, read_users, filter_compatible_format: false).
-            map(&:portable_data_hash)
-        end
-        filters << [attr, operator.sub(/ docker$/, ""), image_hashes]
-      else
-        filters << [attr, operator, operand]
-      end
-    end
-
-    # Build a real script_version filter from any "not? in git" filters.
-    git_filters.each_pair do |attr, filter|
-      case attr
-      when "script_version"
-        script_info.each_pair do |key, value|
-          if value.nil?
-            raise ArgumentError.new("script_version filter needs #{key} filter")
-          end
-        end
-        filter["repository"] = script_info["repository"]
-        if attrs[:script_version]
-          filter["max_version"] = attrs[:script_version]
-        else
-          # Using HEAD, set earlier by the hash default, is fine.
-        end
-      when "arvados_sdk_version"
-        filter["repository"] = "arvados"
-      else
-        raise ArgumentError.new("unknown attribute for git filter: #{attr}")
-      end
-      revisions = CommitsHelper::find_commit_range(filter["repository"],
-                                           filter["min_version"],
-                                           filter["max_version"],
-                                           filter["exclude_versions"])
-      if revisions.empty?
-        raise ArgumentError.
-          new("error searching #{filter['repository']} from " +
-              "'#{filter['min_version']}' to '#{filter['max_version']}', " +
-              "excluding #{filter['exclude_versions']}")
-      end
-      filters.append([attr, "in", revisions])
-    end
-
-    filters
-  end
-
-  def self.default_git_filters(attr_name, repo_name, refspec)
-    # Add a filter to @filters for `attr_name` = the latest commit available
-    # in `repo_name` at `refspec`.  No filter is added if refspec can't be
-    # resolved.
-    commits = CommitsHelper::find_commit_range(repo_name, nil, refspec, nil)
-    if commit_hash = commits.first
-      [[attr_name, "=", commit_hash]]
-    else
-      []
-    end
-  end
-
-  def cancel(cascade: false, need_transaction: true)
-    raise "No longer supported"
-  end
-
-  protected
-
-  def self.sorted_hash_digest h
-    Digest::MD5.hexdigest(Oj.dump(deep_sort_hash(h)))
-  end
-
-  def foreign_key_attributes
-    super + %w(output log)
-  end
-
-  def skip_uuid_read_permission_check
-    super + %w(cancelled_by_client_uuid)
-  end
-
-  def skip_uuid_existence_check
-    super + %w(output log)
-  end
-
-  def set_priority
-    if self.priority.nil?
-      self.priority = 0
-    end
-    true
-  end
-
-  def ensure_script_version_is_commit
-    if state == Running
-      # Apparently client has already decided to go for it. This is
-      # needed to run a local job using a local working directory
-      # instead of a commit-ish.
-      return true
-    end
-    if new_record? or repository_changed? or script_version_changed?
-      sha1 = CommitsHelper::find_commit_range(repository,
-                                      nil, script_version, nil).first
-      if not sha1
-        errors.add :script_version, "#{script_version} does not resolve to a commit"
-        return false
-      end
-      if supplied_script_version.nil? or supplied_script_version.empty?
-        self.supplied_script_version = script_version
-      end
-      self.script_version = sha1
-    end
-    true
-  end
-
-  def tag_version_in_internal_repository
-    if state == Running
-      # No point now. See ensure_script_version_is_commit.
-      true
-    elsif errors.any?
-      # Won't be saved, and script_version might not even be valid.
-      true
-    elsif new_record? or repository_changed? or script_version_changed?
-      uuid_was = uuid
-      begin
-        assign_uuid
-        CommitsHelper::tag_in_internal_repository repository, script_version, uuid
-      rescue
-        self.uuid = uuid_was
-        raise
-      end
-    end
-  end
-
-  def ensure_unique_submit_id
-    if !submit_id.nil?
-      if Job.where('submit_id=?',self.submit_id).first
-        raise SubmitIdReused.new
-      end
-    end
-    true
-  end
-
-  def resolve_runtime_constraint(key, attr_sym)
-    if ((runtime_constraints.is_a? Hash) and
-        (search = runtime_constraints[key]))
-      ok, result = yield search
-    else
-      ok, result = true, nil
-    end
-    if ok
-      send("#{attr_sym}=".to_sym, result)
-    else
-      errors.add(attr_sym, result)
-    end
-    ok
-  end
-
-  def find_arvados_sdk_version
-    resolve_runtime_constraint("arvados_sdk_version",
-                               :arvados_sdk_version) do |git_search|
-      commits = CommitsHelper::find_commit_range("arvados",
-                                         nil, git_search, nil)
-      if commits.empty?
-        [false, "#{git_search} does not resolve to a commit"]
-      elsif not runtime_constraints["docker_image"]
-        [false, "cannot be specified without a Docker image constraint"]
-      else
-        [true, commits.first]
-      end
-    end
-  end
-
-  def find_docker_image_locator
-    if runtime_constraints.is_a? Hash and Rails.configuration.Containers.JobsAPI.DefaultDockerImage != ""
-      runtime_constraints['docker_image'] ||=
-        Rails.configuration.Containers.JobsAPI.DefaultDockerImage
-    end
-
-    resolve_runtime_constraint("docker_image",
-                               :docker_image_locator) do |image_search|
-      image_tag = runtime_constraints['docker_image_tag']
-      if coll = Collection.for_latest_docker_image(image_search, image_tag)
-        [true, coll.portable_data_hash]
-      else
-        [false, "not found for #{image_search}"]
-      end
-    end
-  end
-
-  def permission_to_update
-    if is_locked_by_uuid_was and !(current_user and
-                                   (current_user.uuid == is_locked_by_uuid_was or
-                                    current_user.uuid == system_user.uuid))
-      if script_changed? or
-          script_parameters_changed? or
-          script_version_changed? or
-          (!cancelled_at_was.nil? and
-           (cancelled_by_client_uuid_changed? or
-            cancelled_by_user_uuid_changed? or
-            cancelled_at_changed?)) or
-          started_at_changed? or
-          finished_at_changed? or
-          running_changed? or
-          success_changed? or
-          output_changed? or
-          log_changed? or
-          tasks_summary_changed? or
-          (state_changed? && state != Cancelled) or
-          components_changed?
-        logger.warn "User #{current_user.uuid if current_user} tried to change protected job attributes on locked #{self.class.to_s} #{uuid_was}"
-        return false
-      end
-    end
-    if !is_locked_by_uuid_changed?
-      super
-    else
-      if !current_user
-        logger.warn "Anonymous user tried to change lock on #{self.class.to_s} #{uuid_was}"
-        false
-      elsif is_locked_by_uuid_was and is_locked_by_uuid_was != current_user.uuid
-        logger.warn "User #{current_user.uuid} tried to steal lock on #{self.class.to_s} #{uuid_was} from #{is_locked_by_uuid_was}"
-        false
-      elsif !is_locked_by_uuid.nil? and is_locked_by_uuid != current_user.uuid
-        logger.warn "User #{current_user.uuid} tried to lock #{self.class.to_s} #{uuid_was} with uuid #{is_locked_by_uuid}"
-        false
-      else
-        super
-      end
-    end
-  end
-
-  def update_modified_by_fields
-    if self.cancelled_at_changed?
-      # Ensure cancelled_at cannot be set to arbitrary non-now times,
-      # or changed once it is set.
-      if self.cancelled_at and not self.cancelled_at_was
-        self.cancelled_at = db_current_time
-        self.cancelled_by_user_uuid = current_user.uuid
-        self.cancelled_by_client_uuid = current_api_client.andand.uuid
-        @need_crunch_dispatch_trigger = true
-      else
-        self.cancelled_at = self.cancelled_at_was
-        self.cancelled_by_user_uuid = self.cancelled_by_user_uuid_was
-        self.cancelled_by_client_uuid = self.cancelled_by_client_uuid_was
-      end
-    end
-    super
-  end
-
-  def update_timestamps_when_state_changes
-    return if not (state_changed? or new_record?)
-
-    case state
-    when Running
-      self.started_at ||= db_current_time
-    when Failed, Complete
-      self.finished_at ||= db_current_time
-    when Cancelled
-      self.cancelled_at ||= db_current_time
-    end
-
-    # TODO: Remove the following case block when old "success" and
-    # "running" attrs go away. Until then, this ensures we still
-    # expose correct success/running flags to older clients, even if
-    # some new clients are writing only the new state attribute.
-    case state
-    when Queued
-      self.running = false
-      self.success = nil
-    when Running
-      self.running = true
-      self.success = nil
-    when Cancelled, Failed
-      self.running = false
-      self.success = false
-    when Complete
-      self.running = false
-      self.success = true
-    end
-    self.running ||= false # Default to false instead of nil.
-
-    @need_crunch_dispatch_trigger = true
-
-    true
-  end
-
-  def update_state_from_old_state_attrs
-    # If a client has touched the legacy state attrs, update the
-    # "state" attr to agree with the updated values of the legacy
-    # attrs.
-    #
-    # TODO: Remove this method when old "success" and "running" attrs
-    # go away.
-    if cancelled_at_changed? or
-        success_changed? or
-        running_changed? or
-        state.nil?
-      if cancelled_at
-        self.state = Cancelled
-      elsif success == false
-        self.state = Failed
-      elsif success == true
-        self.state = Complete
-      elsif running == true
-        self.state = Running
-      else
-        self.state = Queued
-      end
-    end
-    true
-  end
-
-  def validate_status
-    if self.state.in?(States)
-      true
-    else
-      errors.add :state, "#{state.inspect} must be one of: #{States.inspect}"
-      false
-    end
-  end
-
-  def validate_state_change
-    ok = true
-    if self.state_changed?
-      ok = case self.state_was
-           when nil
-             # state isn't set yet
-             true
-           when Queued
-             # Permit going from queued to any state
-             true
-           when Running
-             # From running, may only transition to a finished state
-             [Complete, Failed, Cancelled].include? self.state
-           when Complete, Failed, Cancelled
-             # Once in a finished state, don't permit any more state changes
-             false
-           else
-             # Any other state transition is also invalid
-             false
-           end
-      if not ok
-        errors.add :state, "invalid change from #{self.state_was} to #{self.state}"
-      end
-    end
-    ok
-  end
-
-  def ensure_no_collection_uuids_in_script_params
-    # Fail validation if any script_parameters field includes a string containing a
-    # collection uuid pattern.
-    if self.script_parameters_changed?
-      if recursive_hash_search(self.script_parameters, Collection.uuid_regex)
-        self.errors.add :script_parameters, "must use portable_data_hash instead of collection uuid"
-        return false
-      end
-    end
-    true
-  end
-
-  # recursive_hash_search searches recursively through hashes and
-  # arrays in 'thing' for string fields matching regular expression
-  # 'pattern'.  Returns true if pattern is found, false otherwise.
-  def recursive_hash_search thing, pattern
-    if thing.is_a? Hash
-      thing.each do |k, v|
-        return true if recursive_hash_search v, pattern
-      end
-    elsif thing.is_a? Array
-      thing.each do |k|
-        return true if recursive_hash_search k, pattern
-      end
-    elsif thing.is_a? String
-      return true if thing.match pattern
-    end
-    false
-  end
-
-  def create_disabled
-    raise "Disabled"
-  end
-
-  def update_disabled
-    raise "Disabled"
-  end
-end
diff --git a/services/api/app/models/job_task.rb b/services/api/app/models/job_task.rb
deleted file mode 100644 (file)
index b181e76..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class JobTask < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :parameters, Hash
-  before_create :set_default_qsequence
-  after_update :delete_created_job_tasks_if_failed
-  before_create :create_disabled
-  before_update :update_disabled
-
-  api_accessible :user, extend: :common do |t|
-    t.add :job_uuid
-    t.add :created_by_job_task_uuid
-    t.add :sequence
-    t.add :qsequence
-    t.add :parameters
-    t.add :output
-    t.add :progress
-    t.add :success
-    t.add :started_at
-    t.add :finished_at
-  end
-
-  protected
-
-  def delete_created_job_tasks_if_failed
-    if self.success == false and self.success != self.success_was
-      JobTask.delete_all ['created_by_job_task_uuid = ?', self.uuid]
-    end
-  end
-
-  def set_default_qsequence
-    self.qsequence ||= self.class.connection.
-      select_value("SELECT nextval('job_tasks_qsequence_seq')")
-  end
-
-  def create_disabled
-    raise "Disabled"
-  end
-
-  def update_disabled
-    raise "Disabled"
-  end
-end
diff --git a/services/api/app/models/keep_disk.rb b/services/api/app/models/keep_disk.rb
deleted file mode 100644 (file)
index 589936f..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class KeepDisk < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  before_validation :ensure_ping_secret
-
-  api_accessible :user, extend: :common do |t|
-    t.add :node_uuid
-    t.add :filesystem_uuid
-    t.add :bytes_total
-    t.add :bytes_free
-    t.add :is_readable
-    t.add :is_writable
-    t.add :last_read_at
-    t.add :last_write_at
-    t.add :last_ping_at
-    t.add :service_host
-    t.add :service_port
-    t.add :service_ssl_flag
-    t.add :keep_service_uuid
-  end
-  api_accessible :superuser, :extend => :user do |t|
-    t.add :ping_secret
-  end
-
-  def foreign_key_attributes
-    super.reject { |a| a == "filesystem_uuid" }
-  end
-
-  def ping(o)
-    raise "must have :service_host and :ping_secret" unless o[:service_host] and o[:ping_secret]
-
-    if o[:ping_secret] != self.ping_secret
-      logger.info "Ping: secret mismatch: received \"#{o[:ping_secret]}\" != \"#{self.ping_secret}\""
-      return nil
-    end
-
-    @bypass_arvados_authorization = true
-    self.update!(o.select { |k,v|
-                             [:bytes_total,
-                              :bytes_free,
-                              :is_readable,
-                              :is_writable,
-                              :last_read_at,
-                              :last_write_at
-                             ].collect(&:to_s).index k
-                           }.merge(last_ping_at: db_current_time))
-  end
-
-  def service_host
-    KeepService.find_by_uuid(self.keep_service_uuid).andand.service_host
-  end
-
-  def service_port
-    KeepService.find_by_uuid(self.keep_service_uuid).andand.service_port
-  end
-
-  def service_ssl_flag
-    KeepService.find_by_uuid(self.keep_service_uuid).andand.service_ssl_flag
-  end
-
-  protected
-
-  def ensure_ping_secret
-    self.ping_secret ||= rand(2**256).to_s(36)
-  end
-
-  def permission_to_update
-    @bypass_arvados_authorization or super
-  end
-
-  def permission_to_create
-    current_user and current_user.is_admin
-  end
-end
diff --git a/services/api/app/models/node.rb b/services/api/app/models/node.rb
deleted file mode 100644 (file)
index f384ba5..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'tempfile'
-
-class Node < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-
-  # Posgresql JSONB columns should NOT be declared as serialized, Rails 5
-  # already know how to properly treat them.
-  attribute :properties, :jsonbHash, default: {}
-  attribute :info, :jsonbHash, default: {}
-
-  before_validation :ensure_ping_secret
-  after_update :dns_server_update
-
-  # Only a controller can figure out whether or not the current API tokens
-  # have access to the associated Job.  They're expected to set
-  # job_readable=true if the Job UUID can be included in the API response.
-  belongs_to :job,
-             foreign_key: 'job_uuid',
-             primary_key: 'uuid',
-             optional: true
-  attr_accessor :job_readable
-
-  UNUSED_NODE_IP = '127.40.4.0'
-  MAX_VMS = 3
-
-  api_accessible :user, :extend => :common do |t|
-    t.add :hostname
-    t.add :domain
-    t.add :ip_address
-    t.add :last_ping_at
-    t.add :slot_number
-    t.add :status
-    t.add :api_job_uuid, as: :job_uuid
-    t.add :crunch_worker_state
-    t.add :properties
-  end
-  api_accessible :superuser, :extend => :user do |t|
-    t.add :first_ping_at
-    t.add :info
-    t.add lambda { |x| Rails.configuration.Containers.SLURM.Managed.ComputeNodeNameservers.keys }, :as => :nameservers
-  end
-
-  after_initialize do
-    @bypass_arvados_authorization = false
-  end
-
-  def domain
-    super || Rails.configuration.Containers.SLURM.Managed.ComputeNodeDomain
-  end
-
-  def api_job_uuid
-    job_readable ? job_uuid : nil
-  end
-
-  def crunch_worker_state
-    return 'down' if slot_number.nil?
-    case self.info.andand['slurm_state']
-    when 'alloc', 'comp', 'mix', 'drng'
-      'busy'
-    when 'idle'
-      'idle'
-    else
-      'down'
-    end
-  end
-
-  def status
-    if !self.last_ping_at
-      if db_current_time - self.created_at > 5.minutes
-        'startup-fail'
-      else
-        'pending'
-      end
-    elsif db_current_time - self.last_ping_at > 1.hours
-      'missing'
-    else
-      'running'
-    end
-  end
-
-  def ping(o)
-    raise "must have :ip and :ping_secret" unless o[:ip] and o[:ping_secret]
-
-    if o[:ping_secret] != self.info['ping_secret']
-      logger.info "Ping: secret mismatch: received \"#{o[:ping_secret]}\" != \"#{self.info['ping_secret']}\""
-      raise ArvadosModel::UnauthorizedError.new("Incorrect ping_secret")
-    end
-
-    current_time = db_current_time
-    self.last_ping_at = current_time
-
-    @bypass_arvados_authorization = true
-
-    # Record IP address
-    if self.ip_address.nil?
-      logger.info "#{self.uuid} ip_address= #{o[:ip]}"
-      self.ip_address = o[:ip]
-      self.first_ping_at = current_time
-    end
-
-    # Record instance ID if not already known
-    if o[:ec2_instance_id]
-      if !self.info['ec2_instance_id']
-        self.info['ec2_instance_id'] = o[:ec2_instance_id]
-      elsif self.info['ec2_instance_id'] != o[:ec2_instance_id]
-        logger.debug "Multiple nodes have credentials for #{self.uuid}"
-        raise "#{self.uuid} is already running at #{self.info['ec2_instance_id']} so rejecting ping from #{o[:ec2_instance_id]}"
-      end
-    end
-
-    assign_slot
-
-    # Record other basic stats
-    ['total_cpu_cores', 'total_ram_mb', 'total_scratch_mb'].each do |key|
-      if value = (o[key] or o[key.to_sym])
-        self.properties[key] = value.to_i
-      else
-        self.properties.delete(key)
-      end
-    end
-
-    save!
-  end
-
-  def assign_slot
-    return if self.slot_number.andand > 0
-    while true
-      self.slot_number = self.class.available_slot_number
-      if self.slot_number.nil?
-        raise "No available node slots"
-      end
-      begin
-        save!
-        return assign_hostname
-      rescue ActiveRecord::RecordNotUnique
-        # try again
-      end
-    end
-  end
-
-  protected
-
-  def assign_hostname
-    if self.hostname.nil? and Rails.configuration.Containers.SLURM.Managed.AssignNodeHostname
-      self.hostname = self.class.hostname_for_slot(self.slot_number)
-    end
-  end
-
-  def self.available_slot_number
-    # Join the sequence 1..max with the nodes table. Return the first
-    # (i.e., smallest) value that doesn't match the slot_number of any
-    # existing node.
-    connection.exec_query('SELECT n FROM generate_series(1, $1) AS slot(n)
-                          LEFT JOIN nodes ON n=slot_number
-                          WHERE slot_number IS NULL
-                          LIMIT 1',
-                          # query label:
-                          'Node.available_slot_number',
-                          # bind vars:
-                          [MAX_VMS],
-                         ).rows.first.andand.first
-  end
-
-  def ensure_ping_secret
-    self.info['ping_secret'] ||= rand(2**256).to_s(36)
-  end
-
-  def dns_server_update
-    if saved_change_to_ip_address? && ip_address
-      Node.where('id != ? and ip_address = ?',
-                 id, ip_address).each do |stale_node|
-        # One or more(!) stale node records have the same IP address
-        # as the new node. Clear the ip_address field on the stale
-        # nodes. Otherwise, we (via SLURM) might inadvertently connect
-        # to the new node using the old node's hostname.
-        stale_node.update!(ip_address: nil)
-      end
-    end
-    if hostname_before_last_save && saved_change_to_hostname?
-      self.class.dns_server_update(hostname_before_last_save, UNUSED_NODE_IP)
-    end
-    if hostname && (saved_change_to_hostname? || saved_change_to_ip_address?)
-      self.class.dns_server_update(hostname, ip_address || UNUSED_NODE_IP)
-    end
-  end
-
-  def self.dns_server_update hostname, ip_address
-    ok = true
-
-    ptr_domain = ip_address.
-      split('.').reverse.join('.').concat('.in-addr.arpa')
-
-    template_vars = {
-      hostname: hostname,
-      uuid_prefix: Rails.configuration.ClusterID,
-      ip_address: ip_address,
-      ptr_domain: ptr_domain,
-    }
-
-    if (!Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir.to_s.empty? and
-        !Rails.configuration.Containers.SLURM.Managed.DNSServerConfTemplate.to_s.empty?)
-      tmpfile = nil
-      begin
-        begin
-          template = IO.read(Rails.configuration.Containers.SLURM.Managed.DNSServerConfTemplate)
-        rescue IOError, SystemCallError => e
-          logger.error "Reading #{Rails.configuration.Containers.SLURM.Managed.DNSServerConfTemplate}: #{e.message}"
-          raise
-        end
-
-        hostfile = File.join Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir, "#{hostname}.conf"
-        Tempfile.open(["#{hostname}-", ".conf.tmp"],
-                                 Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir) do |f|
-          tmpfile = f.path
-          f.puts template % template_vars
-        end
-        File.rename tmpfile, hostfile
-      rescue IOError, SystemCallError => e
-        logger.error "Writing #{hostfile}: #{e.message}"
-        ok = false
-      ensure
-        if tmpfile and File.file? tmpfile
-          # Cleanup remaining temporary file.
-          File.unlink tmpfile
-        end
-      end
-    end
-
-    if !Rails.configuration.Containers.SLURM.Managed.DNSServerUpdateCommand.empty?
-      cmd = Rails.configuration.Containers.SLURM.Managed.DNSServerUpdateCommand % template_vars
-      if not system cmd
-        logger.error "dns_server_update_command #{cmd.inspect} failed: #{$?}"
-        ok = false
-      end
-    end
-
-    if (!Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir.to_s.empty? and
-        !Rails.configuration.Containers.SLURM.Managed.DNSServerReloadCommand.to_s.empty?)
-      restartfile = File.join(Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir, 'restart.txt')
-      begin
-        File.open(restartfile, 'w') do |f|
-          # Typically, this is used to trigger a dns server restart
-          f.puts Rails.configuration.Containers.SLURM.Managed.DNSServerReloadCommand
-        end
-      rescue IOError, SystemCallError => e
-        logger.error "Unable to write #{restartfile}: #{e.message}"
-        ok = false
-      end
-    end
-
-    ok
-  end
-
-  def self.hostname_for_slot(slot_number)
-    config = Rails.configuration.Containers.SLURM.Managed.AssignNodeHostname
-
-    return nil if !config
-
-    sprintf(config, {:slot_number => slot_number})
-  end
-
-  # At startup, make sure all DNS entries exist.  Otherwise, slurmctld
-  # will refuse to start.
-  if (!Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir.to_s.empty? and
-      !Rails.configuration.Containers.SLURM.Managed.DNSServerConfTemplate.to_s.empty? and
-      !Rails.configuration.Containers.SLURM.Managed.AssignNodeHostname.empty?)
-
-    (0..MAX_VMS-1).each do |slot_number|
-      hostname = hostname_for_slot(slot_number)
-      hostfile = File.join Rails.configuration.Containers.SLURM.Managed.DNSServerConfDir, "#{hostname}.conf"
-      if !File.exist? hostfile
-        n = Node.where(:slot_number => slot_number).first
-        if n.nil? or n.ip_address.nil?
-          dns_server_update(hostname, UNUSED_NODE_IP)
-        else
-          dns_server_update(hostname, n.ip_address)
-        end
-      end
-    end
-  end
-
-  def permission_to_update
-    @bypass_arvados_authorization or super
-  end
-
-  def permission_to_create
-    current_user and current_user.is_admin
-  end
-end
diff --git a/services/api/app/models/pipeline_instance.rb b/services/api/app/models/pipeline_instance.rb
deleted file mode 100644 (file)
index 0b0af8b..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class PipelineInstance < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :components, Hash
-  serialize :properties, Hash
-  serialize :components_summary, Hash
-  belongs_to :pipeline_template,
-             foreign_key: 'pipeline_template_uuid',
-             primary_key: 'uuid',
-             optional: true
-
-  before_validation :bootstrap_components
-  before_validation :update_state
-  before_validation :verify_status
-  before_validation :update_timestamps_when_state_changes
-  before_create :set_state_before_save
-  before_save :set_state_before_save
-  before_create :create_disabled
-  before_update :update_disabled
-
-  api_accessible :user, extend: :common do |t|
-    t.add :pipeline_template_uuid
-    t.add :name
-    t.add :components
-    t.add :properties
-    t.add :state
-    t.add :components_summary
-    t.add :description
-    t.add :started_at
-    t.add :finished_at
-  end
-
-  # Supported states for a pipeline instance
-  States =
-    [
-     (New = 'New'),
-     (Ready = 'Ready'),
-     (RunningOnServer = 'RunningOnServer'),
-     (RunningOnClient = 'RunningOnClient'),
-     (Paused = 'Paused'),
-     (Failed = 'Failed'),
-     (Complete = 'Complete'),
-    ]
-
-  def self.limit_index_columns_read
-    ["components"]
-  end
-
-  # if all components have input, the pipeline is Ready
-  def components_look_ready?
-    if !self.components || self.components.empty?
-      return false
-    end
-
-    all_components_have_input = true
-    self.components.each do |name, component|
-      component['script_parameters'].andand.each do |parametername, parameter|
-        parameter = { 'value' => parameter } unless parameter.is_a? Hash
-        if parameter['value'].nil? and parameter['required']
-          if parameter['output_of']
-            next
-          end
-          all_components_have_input = false
-          break
-        end
-      end
-    end
-    return all_components_have_input
-  end
-
-  def progress_table
-    begin
-      # v0 pipeline format
-      nrow = -1
-      components['steps'].collect do |step|
-        nrow += 1
-        row = [nrow, step['name']]
-        if step['complete'] and step['complete'] != 0
-          if step['output_data_locator']
-            row << 1.0
-          else
-            row << 0.0
-          end
-        else
-          row << 0.0
-          if step['failed']
-            self.state = Failed
-          end
-        end
-        row << (step['warehousejob']['id'] rescue nil)
-        row << (step['warehousejob']['revision'] rescue nil)
-        row << step['output_data_locator']
-        row << (Time.parse(step['warehousejob']['finishtime']) rescue nil)
-        row
-      end
-    rescue
-      []
-    end
-  end
-
-  def progress_ratio
-    t = progress_table
-    return 0 if t.size < 1
-    t.collect { |r| r[2] }.inject(0.0) { |sum,a| sum += a } / t.size
-  end
-
-  def self.queue
-    self.where("state = 'RunningOnServer'")
-  end
-
-  def cancel(cascade: false, need_transaction: true)
-    raise "No longer supported"
-  end
-
-  protected
-  def bootstrap_components
-    if pipeline_template and (!components or components.empty?)
-      self.components = pipeline_template.components.deep_dup
-    end
-  end
-
-  def update_state
-    if components and progress_ratio == 1.0
-      self.state = Complete
-    end
-  end
-
-  def verify_status
-    changed_attributes = self.changed
-
-    if new_record? or 'components'.in? changed_attributes
-      self.state ||= New
-      if (self.state == New) and self.components_look_ready?
-        self.state = Ready
-      end
-    end
-
-    if !self.state.in?(States)
-      errors.add :state, "'#{state.inspect} must be one of: [#{States.join ', '}]"
-      throw(:abort)
-    end
-  end
-
-  def set_state_before_save
-    if self.components_look_ready? && (!self.state || self.state == New)
-      self.state = Ready
-    end
-  end
-
-  def update_timestamps_when_state_changes
-    return if not (state_changed? or new_record?)
-
-    case state
-    when RunningOnServer, RunningOnClient
-      self.started_at ||= db_current_time
-    when Failed, Complete
-      current_time = db_current_time
-      self.started_at ||= current_time
-      self.finished_at ||= current_time
-    end
-  end
-
-
-  def create_disabled
-    raise "Disabled"
-  end
-
-  def update_disabled
-    raise "Disabled"
-  end
-end
diff --git a/services/api/app/models/pipeline_template.rb b/services/api/app/models/pipeline_template.rb
deleted file mode 100644 (file)
index 7c69469..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class PipelineTemplate < ArvadosModel
-  before_create :create_disabled
-  before_update :update_disabled
-
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :components, Hash
-
-  api_accessible :user, extend: :common do |t|
-    t.add :name
-    t.add :components
-    t.add :description
-  end
-
-  def self.limit_index_columns_read
-    ["components"]
-  end
-
-  def create_disabled
-    raise "Disabled"
-  end
-
-  def update_disabled
-    raise "Disabled"
-  end
-end
diff --git a/services/api/app/models/repository.rb b/services/api/app/models/repository.rb
deleted file mode 100644 (file)
index 46f2de6..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Repository < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-
-  # Order is important here.  We must validate the owner before we can
-  # validate the name.
-  validate :valid_owner
-  validate :name_format, :if => Proc.new { |r| r.errors[:owner_uuid].empty? }
-  validates(:name, uniqueness: true, allow_nil: false)
-
-  api_accessible :user, extend: :common do |t|
-    t.add :name
-    t.add :fetch_url
-    t.add :push_url
-    t.add :clone_urls
-  end
-
-  def self.attributes_required_columns
-    super.merge("clone_urls" => ["name"],
-                "fetch_url" => ["name"],
-                "push_url" => ["name"])
-  end
-
-  # Deprecated. Use clone_urls instead.
-  def push_url
-    ssh_clone_url
-  end
-
-  # Deprecated. Use clone_urls instead.
-  def fetch_url
-    ssh_clone_url
-  end
-
-  def clone_urls
-    [ssh_clone_url, https_clone_url].compact
-  end
-
-  def server_path
-    # Find where the repository is stored on the API server's filesystem,
-    # and return that path, or nil if not found.
-    # This method is only for the API server's internal use, and should not
-    # be exposed through the public API.  Following our current gitolite
-    # setup, it searches for repositories stored by UUID, then name; and it
-    # prefers bare repositories over checkouts.
-    [["%s.git"], ["%s", ".git"]].each do |repo_base, *join_args|
-      [:uuid, :name].each do |path_attr|
-        git_dir = File.join(Rails.configuration.Git.Repositories,
-                            repo_base % send(path_attr), *join_args)
-        return git_dir if File.exist?(git_dir)
-      end
-    end
-    nil
-  end
-
-  protected
-
-  def permission_to_update
-    if not super
-      false
-    elsif current_user.is_admin
-      true
-    elsif name_changed?
-      current_user.uuid == owner_uuid
-    else
-      true
-    end
-  end
-
-  def owner
-    User.find_by_uuid(owner_uuid)
-  end
-
-  def valid_owner
-    if owner.nil? or (owner.username.nil? and (owner.uuid != system_user_uuid))
-      errors.add(:owner_uuid, "must refer to a user with a username")
-      false
-    end
-  end
-
-  def name_format
-    if owner.uuid == system_user_uuid
-      prefix_match = ""
-      errmsg_start = "must be"
-    else
-      prefix_match = Regexp.escape(owner.username + "/")
-      errmsg_start = "must be the owner's username, then '/', then"
-    end
-    if not (/^#{prefix_match}[A-Za-z][A-Za-z0-9]*$/.match(name))
-      errors.add(:name,
-                 "#{errmsg_start} a letter followed by alphanumerics, expected pattern '#{prefix_match}[A-Za-z][A-Za-z0-9]*' but was '#{name}'")
-      false
-    end
-  end
-
-  def ssh_clone_url
-    _clone_url Rails.configuration.Services.GitSSH.andand.ExternalURL, 'ssh://git@git.%s.arvadosapi.com'
-  end
-
-  def https_clone_url
-    _clone_url Rails.configuration.Services.GitHTTP.andand.ExternalURL, 'https://git.%s.arvadosapi.com/'
-  end
-
-  def _clone_url config_var, default_base_fmt
-    if not config_var
-      return ""
-    end
-    prefix = new_record? ? Rails.configuration.ClusterID : uuid[0,5]
-    if prefix == Rails.configuration.ClusterID and config_var != URI("")
-      base = config_var
-    else
-      base = URI(default_base_fmt % prefix)
-    end
-    if base.path == ""
-      base.path = "/"
-    end
-    if base.scheme == "ssh"
-      '%s@%s:%s.git' % [base.user, base.host, name]
-    else
-      '%s%s.git' % [base, name]
-    end
-  end
-end
diff --git a/services/api/app/models/specimen.rb b/services/api/app/models/specimen.rb
deleted file mode 100644 (file)
index 32d5ed5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Specimen < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :properties, Hash
-
-  api_accessible :user, extend: :common do |t|
-    t.add :material
-    t.add :properties
-  end
-
-  def properties
-    @properties ||= Hash.new
-    super
-  end
-end
diff --git a/services/api/app/models/trait.rb b/services/api/app/models/trait.rb
deleted file mode 100644 (file)
index 2d3556b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-class Trait < ArvadosModel
-  include HasUuid
-  include KindAndEtag
-  include CommonApiTemplate
-  serialize :properties, Hash
-
-  api_accessible :user, extend: :common do |t|
-    t.add :name
-    t.add :properties
-  end
-end
index 5a95fb0b88e41efc593495bc50efeb5bd13b51b9..c104ac6fda4f432714a8ff33d8bebc0b651c55f3 100644 (file)
@@ -25,9 +25,6 @@ class User < ArvadosModel
   before_update :prevent_privilege_escalation
   before_update :prevent_inactive_admin
   before_update :prevent_nonadmin_system_root
-  before_update :verify_repositories_empty, :if => Proc.new {
-    username.nil? and username_changed?
-  }
   after_update :setup_on_activate
 
   before_create :check_auto_admin
@@ -49,16 +46,10 @@ class User < ArvadosModel
   before_update :before_ownership_change
   after_update :after_ownership_change
   after_update :send_profile_created_notification
-  after_update :sync_repository_names, :if => Proc.new {
-    (uuid != system_user_uuid) and
-    saved_change_to_username? and
-    (not username_before_last_save.nil?)
-  }
   before_destroy :clear_permissions
   after_destroy :remove_self_from_permissions
 
   has_many :authorized_keys, foreign_key: 'authorized_user_uuid', primary_key: 'uuid'
-  has_many :repositories, foreign_key: 'owner_uuid', primary_key: 'uuid'
 
   default_scope { where('redirect_to_user_uuid is null') }
 
@@ -261,7 +252,7 @@ SELECT target_uuid, perm_level
   end
 
   # create links
-  def setup(repo_name: nil, vm_uuid: nil, send_notification_email: nil)
+  def setup(vm_uuid: nil, send_notification_email: nil)
     newly_invited = Link.where(tail_uuid: self.uuid,
                               head_uuid: all_users_group_uuid,
                               link_class: 'permission').empty?
@@ -271,12 +262,6 @@ SELECT target_uuid, perm_level
     # direction which makes this user visible to other users.
     group_perms = add_to_all_users_group
 
-    # Add git repo
-    repo_perm = if (!repo_name.nil? || Rails.configuration.Users.AutoSetupNewUsersWithRepository) and !username.nil?
-                  repo_name ||= "#{username}/#{username}"
-                  create_user_repo_link repo_name
-                end
-
     # Add virtual machine
     if vm_uuid.nil? and !Rails.configuration.Users.AutoSetupNewUsersWithVmUUID.empty?
       vm_uuid = Rails.configuration.Users.AutoSetupNewUsersWithVmUUID
@@ -301,10 +286,10 @@ SELECT target_uuid, perm_level
 
     forget_cached_group_perms
 
-    return [repo_perm, vm_login_perm, *group_perms, self].compact
+    return [vm_login_perm, *group_perms, self].compact
   end
 
-  # delete user signatures, login, repo, and vm perms, and mark as inactive
+  # delete user signatures, login, and vm perms, and mark as inactive
   def unsetup
     if self.uuid == system_user_uuid
       raise "System root user cannot be deactivated"
@@ -483,30 +468,13 @@ SELECT target_uuid, perm_level
         klass.where(column => uuid).update_all(column => new_user.uuid)
       end
 
-      # Need to update repository names to new username
-      if username
-        old_repo_name_re = /^#{Regexp.escape(username)}\//
-        Repository.where(:owner_uuid => uuid).each do |repo|
-          repo.owner_uuid = new_user.uuid
-          repo_name_sub = "#{new_user.username}/"
-          name = repo.name.sub(old_repo_name_re, repo_name_sub)
-          while (conflict = Repository.where(:name => name).first) != nil
-            repo_name_sub += "migrated"
-            name = repo.name.sub(old_repo_name_re, repo_name_sub)
-          end
-          repo.name = name
-          repo.save!
-        end
-      end
-
       # References to the merged user's "home project" are updated to
       # point to new_owner_uuid.
       ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |klass|
         next if [ApiClientAuthorization,
                  AuthorizedKey,
                  Link,
-                 Log,
-                 Repository].include?(klass)
+                 Log].include?(klass)
         next if !klass.columns.collect(&:name).include?('owner_uuid')
         klass.where(owner_uuid: uuid).update_all(owner_uuid: new_owner_uuid)
       end
@@ -889,24 +857,8 @@ SELECT target_uuid, perm_level
     merged
   end
 
-  def create_user_repo_link(repo_name)
-    # repo_name is optional
-    if not repo_name
-      logger.warn ("Repository name not given for #{self.uuid}.")
-      return
-    end
-
-    repo = Repository.where(owner_uuid: uuid, name: repo_name).first_or_create!
-    logger.info { "repo uuid: " + repo[:uuid] }
-    repo_perm = Link.where(tail_uuid: uuid, head_uuid: repo.uuid,
-                           link_class: "permission",
-                           name: "can_manage").first_or_create!
-    logger.info { "repo permission: " + repo_perm[:uuid] }
-    return repo_perm
-  end
-
   # create login permission for the given vm_uuid, if it does not already exist
-  def create_vm_login_permission_link(vm_uuid, repo_name)
+  def create_vm_login_permission_link(vm_uuid, username)
     # vm uuid is optional
     return if vm_uuid == ""
 
@@ -924,11 +876,11 @@ SELECT target_uuid, perm_level
 
     login_perm = Link.
       where(login_attrs).
-      select { |link| link.properties["username"] == repo_name }.
+      select { |link| link.properties["username"] == username }.
       first
 
     login_perm ||= Link.
-      create(login_attrs.merge(properties: {"username" => repo_name}))
+      create(login_attrs.merge(properties: {"username" => username}))
 
     logger.info { "login permission: " + login_perm[:uuid] }
     login_perm
@@ -1001,22 +953,6 @@ SELECT target_uuid, perm_level
     end
   end
 
-  def verify_repositories_empty
-    unless repositories.first.nil?
-      errors.add(:username, "can't be unset when the user owns repositories")
-      throw(:abort)
-    end
-  end
-
-  def sync_repository_names
-    old_name_re = /^#{Regexp.escape(username_before_last_save)}\//
-    name_sub = "#{username}/"
-    repositories.find_each do |repo|
-      repo.name = repo.name.sub(old_name_re, name_sub)
-      repo.save!
-    end
-  end
-
   def identity_url_nil_if_empty
     if identity_url == ""
       self.identity_url = nil
index f8b9ff8ecdd650ceb0a556565fd600001087168d..f514fee641b4e5617b825655a669f701208ab2f5 100644 (file)
@@ -84,7 +84,6 @@ arvcfg = ConfigLoader.new
 arvcfg.declare_config "ClusterID", NonemptyString, :uuid_prefix
 arvcfg.declare_config "ManagementToken", String, :ManagementToken
 arvcfg.declare_config "SystemRootToken", String
-arvcfg.declare_config "Git.Repositories", String, :git_repositories_dir
 arvcfg.declare_config "API.DisabledAPIs", Hash, :disable_api_methods, ->(cfg, k, v) { arrayToHash cfg, "API.DisabledAPIs", v }
 arvcfg.declare_config "API.MaxRequestSize", Integer, :max_request_size
 arvcfg.declare_config "API.MaxIndexDatabaseRead", Integer, :max_index_database_read
@@ -94,7 +93,6 @@ arvcfg.declare_config "API.RequestTimeout", ActiveSupport::Duration
 arvcfg.declare_config "API.AsyncPermissionsUpdateInterval", ActiveSupport::Duration, :async_permissions_update_interval
 arvcfg.declare_config "Users.AutoSetupNewUsers", Boolean, :auto_setup_new_users
 arvcfg.declare_config "Users.AutoSetupNewUsersWithVmUUID", String, :auto_setup_new_users_with_vm_uuid
-arvcfg.declare_config "Users.AutoSetupNewUsersWithRepository", Boolean, :auto_setup_new_users_with_repository
 arvcfg.declare_config "Users.AutoSetupUsernameBlacklist", Hash, :auto_setup_name_blacklist, ->(cfg, k, v) { arrayToHash cfg, "Users.AutoSetupUsernameBlacklist", v }
 arvcfg.declare_config "Users.NewUsersAreActive", Boolean, :new_users_are_active
 arvcfg.declare_config "Users.AutoAdminUserWithEmail", String, :auto_admin_user
@@ -142,23 +140,12 @@ arvcfg.declare_config "Containers.Logging.LogPartialLineThrottlePeriod", ActiveS
 arvcfg.declare_config "Containers.Logging.LogUpdatePeriod", ActiveSupport::Duration, :crunch_log_update_period
 arvcfg.declare_config "Containers.Logging.LogUpdateSize", Integer, :crunch_log_update_size
 arvcfg.declare_config "Containers.Logging.MaxAge", ActiveSupport::Duration, :clean_container_log_rows_after
-arvcfg.declare_config "Containers.SLURM.Managed.DNSServerConfDir", Pathname, :dns_server_conf_dir
-arvcfg.declare_config "Containers.SLURM.Managed.DNSServerConfTemplate", Pathname, :dns_server_conf_template
-arvcfg.declare_config "Containers.SLURM.Managed.DNSServerReloadCommand", String, :dns_server_reload_command
-arvcfg.declare_config "Containers.SLURM.Managed.DNSServerUpdateCommand", String, :dns_server_update_command
-arvcfg.declare_config "Containers.SLURM.Managed.ComputeNodeDomain", String, :compute_node_domain
-arvcfg.declare_config "Containers.SLURM.Managed.ComputeNodeNameservers", Hash, :compute_node_nameservers, ->(cfg, k, v) { arrayToHash cfg, "Containers.SLURM.Managed.ComputeNodeNameservers", v }
-arvcfg.declare_config "Containers.SLURM.Managed.AssignNodeHostname", String, :assign_node_hostname
-arvcfg.declare_config "Containers.JobsAPI.Enable", String, :enable_legacy_jobs_api, ->(cfg, k, v) { ConfigLoader.set_cfg cfg, "Containers.JobsAPI.Enable", v.to_s }
-arvcfg.declare_config "Containers.JobsAPI.GitInternalDir", String, :git_internal_dir
 arvcfg.declare_config "Mail.MailchimpAPIKey", String, :mailchimp_api_key
 arvcfg.declare_config "Mail.MailchimpListID", String, :mailchimp_list_id
 arvcfg.declare_config "Services.Controller.ExternalURL", URI
 arvcfg.declare_config "Services.Workbench1.ExternalURL", URI, :workbench_address
 arvcfg.declare_config "Services.Websocket.ExternalURL", URI, :websocket_address
 arvcfg.declare_config "Services.WebDAV.ExternalURL", URI, :keep_web_service_url
-arvcfg.declare_config "Services.GitHTTP.ExternalURL", URI, :git_repo_https_base
-arvcfg.declare_config "Services.GitSSH.ExternalURL", URI, :git_repo_ssh_base, ->(cfg, k, v) { ConfigLoader.set_cfg cfg, "Services.GitSSH.ExternalURL", "ssh://#{v}" }
 arvcfg.declare_config "RemoteClusters", Hash, :remote_hosts, ->(cfg, k, v) {
   h = if cfg["RemoteClusters"] then
         cfg["RemoteClusters"].deep_dup
index b87e86f664de7e3230331e8233744ac589e4a169..df3c057b5758f0deb76420ba7a2f6908edd199d9 100644 (file)
@@ -34,8 +34,6 @@ Rails.application.routes.draw do
         post 'trash', on: :member
         post 'untrash', on: :member
       end
-      resources :humans
-      resources :job_tasks
       resources :containers do
         get 'auth', on: :member
         post 'lock', on: :member
@@ -47,33 +45,12 @@ Rails.application.routes.draw do
       resources :container_requests do
         get 'container_status', on: :member
       end
-      resources :jobs do
-        get 'queue', on: :collection
-        get 'queue_size', on: :collection
-        post 'cancel', on: :member
-        post 'lock', on: :member
-      end
-      resources :keep_disks do
-        post 'ping', on: :collection
-      end
       resources :keep_services do
         get 'accessible', on: :collection
       end
       resources :links
       resources :logs
-      resources :nodes do
-        post 'ping', on: :member
-      end
-      resources :pipeline_instances do
-        post 'cancel', on: :member
-      end
-      resources :pipeline_templates
       resources :workflows
-      resources :repositories do
-        get 'get_all_permissions', on: :collection
-      end
-      resources :specimens
-      resources :traits
       resources :user_agreements do
         get 'signatures', on: :collection
         post 'sign', on: :collection
index e09037819c64fff413df491ce9e74e6d5febfaef..995f6f334c3ab48e7b82a14755ad0dcde7bb58ac 100644 (file)
@@ -14,11 +14,23 @@ module CanBeAnOwner
     # record when other objects refer to it.
     ActiveRecord::Base.connection.tables.each do |t|
       next if t == base.table_name
-      next if t == 'schema_migrations'
-      next if t == 'permission_refresh_lock'
-      next if t == 'ar_internal_metadata'
-      next if t == 'commit_ancestors'
-      next if t == 'commits'
+      next if t.in?([
+                      'schema_migrations',
+                      'permission_refresh_lock',
+                      'ar_internal_metadata',
+                      'commit_ancestors',
+                      'commits',
+                      'humans',
+                      'jobs',
+                      'job_tasks',
+                      'keep_disks',
+                      'nodes',
+                      'pipeline_instances',
+                      'pipeline_templates',
+                      'repositories',
+                      'specimens',
+                      'traits',
+                    ])
       klass = t.classify.constantize
       next unless klass and 'owner_uuid'.in?(klass.columns.collect(&:name))
       base.has_many(t.to_sym,
diff --git a/services/api/script/arvados-git-sync.rb b/services/api/script/arvados-git-sync.rb
deleted file mode 100755 (executable)
index 9f8f050..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-#!/usr/bin/env ruby
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'rubygems'
-require 'pp'
-require 'arvados'
-require 'tempfile'
-require 'yaml'
-require 'fileutils'
-
-# This script does the actual gitolite config management on disk.
-#
-# Ward Vandewege <ward@curii.com>
-
-# Default is development
-production = ARGV[0] == "production"
-
-ENV["RAILS_ENV"] = "development"
-ENV["RAILS_ENV"] = "production" if production
-
-DEBUG = 1
-
-# load and merge in the environment-specific application config info
-# if present, overriding base config parameters as specified
-path = File.absolute_path('../../config/arvados-clients.yml', __FILE__)
-if File.exist?(path) then
-  cp_config = File.open(path) do |f|
-    YAML.safe_load(f, filename: path)[ENV['RAILS_ENV']]
-  end
-else
-  puts "Please create a\n #{path}\n file"
-  exit 1
-end
-
-gitolite_url = cp_config['gitolite_url']
-gitolite_arvados_git_user_key = cp_config['gitolite_arvados_git_user_key']
-
-gitolite_tmpdir = cp_config['gitolite_tmp']
-gitolite_admin = File.join(gitolite_tmpdir, 'gitolite-admin')
-gitolite_admin_keydir = File.join(gitolite_admin, 'keydir')
-gitolite_keydir = File.join(gitolite_admin, 'keydir', 'arvados')
-
-ENV['ARVADOS_API_HOST'] = cp_config['arvados_api_host']
-ENV['ARVADOS_API_TOKEN'] = cp_config['arvados_api_token']
-if cp_config['arvados_api_host_insecure']
-  ENV['ARVADOS_API_HOST_INSECURE'] = 'true'
-else
-  ENV.delete('ARVADOS_API_HOST_INSECURE')
-end
-
-def ensure_directory(path, mode)
-  begin
-    Dir.mkdir(path, mode)
-  rescue Errno::EEXIST
-  end
-end
-
-def replace_file(path, contents)
-  unlink_now = true
-  dirname, basename = File.split(path)
-  FileUtils.mkpath(dirname)
-  new_file = Tempfile.new([basename, ".tmp"], dirname)
-  begin
-    new_file.write(contents)
-    new_file.flush
-    File.rename(new_file, path)
-    unlink_now = false
-  ensure
-    new_file.close(unlink_now)
-  end
-end
-
-def file_has_contents?(path, contents)
-  begin
-    IO.read(path) == contents
-  rescue Errno::ENOENT
-    false
-  end
-end
-
-module TrackCommitState
-  module ClassMethods
-    # Note that all classes that include TrackCommitState will have
-    # @@need_commit = true if any of them set it.  Since this flag reports
-    # a boolean state of the underlying git repository, that's OK in the
-    # current implementation.
-    @@need_commit = false
-
-    def changed?
-      @@need_commit
-    end
-
-    def ensure_in_git(path, contents)
-      unless file_has_contents?(path, contents)
-        replace_file(path, contents)
-        system("git", "add", path)
-        @@need_commit = true
-      end
-    end
-  end
-
-  def ensure_in_git(path, contents)
-    self.class.ensure_in_git(path, contents)
-  end
-
-  def self.included(base)
-    base.extend(ClassMethods)
-  end
-end
-
-class UserSSHKeys
-  include TrackCommitState
-
-  def initialize(user_keys_map, key_dir)
-    @user_keys_map = user_keys_map
-    @key_dir = key_dir
-    @installed = {}
-  end
-
-  def install(filename, pubkey)
-    unless pubkey.nil?
-      key_path = File.join(@key_dir, filename)
-      ensure_in_git(key_path, pubkey)
-    end
-    @installed[filename] = true
-  end
-
-  def ensure_keys_for_user(user_uuid)
-    return unless key_list = @user_keys_map.delete(user_uuid)
-    key_list.map { |k| k[:public_key] }.compact.each_with_index do |pubkey, ii|
-      # Handle putty-style ssh public keys
-      pubkey.sub!(/^(Comment: "r[^\n]*\n)(.*)$/m,'ssh-rsa \2 \1')
-      pubkey.sub!(/^(Comment: "d[^\n]*\n)(.*)$/m,'ssh-dss \2 \1')
-      pubkey.gsub!(/\n/,'')
-      pubkey.strip!
-      install("#{user_uuid}@#{ii}.pub", pubkey)
-    end
-  end
-
-  def installed?(filename)
-    @installed[filename]
-  end
-end
-
-class Repository
-  include TrackCommitState
-
-  @@aliases = {}
-
-  def initialize(arv_repo, user_keys)
-    @arv_repo = arv_repo
-    @user_keys = user_keys
-  end
-
-  def self.ensure_system_config(conf_root)
-    ensure_in_git(File.join(conf_root, "conf", "gitolite.conf"),
-                  %Q{include "auto/*.conf"\ninclude "admin/*.conf"\n})
-    ensure_in_git(File.join(conf_root, "arvadosaliases.pl"), alias_config)
-
-    conf_path = File.join(conf_root, "conf", "admin", "arvados.conf")
-    conf_file = %Q{
-@arvados_git_user = arvados_git_user
-
-repo gitolite-admin
-     RW           = @arvados_git_user
-
-}
-    ensure_directory(File.dirname(conf_path), 0755)
-    ensure_in_git(conf_path, conf_file)
-  end
-
-  def ensure_config(conf_root)
-    if name and (File.exist?(auto_conf_path(conf_root, name)))
-      # This gitolite installation knows the repository by name, rather than
-      # UUID.  Leave it configured that way until a separate migration is run.
-      basename = name
-    else
-      basename = uuid
-      @@aliases[name] = uuid unless name.nil?
-    end
-    conf_file = "\nrepo #{basename}\n"
-    @arv_repo[:user_permissions].sort.each do |user_uuid, perm|
-      conf_file += "\t#{perm[:gitolite_permissions]}\t= #{user_uuid}\n"
-      @user_keys.ensure_keys_for_user(user_uuid)
-    end
-    ensure_in_git(auto_conf_path(conf_root, basename), conf_file)
-  end
-
-  private
-
-  def auto_conf_path(conf_root, basename)
-    File.join(conf_root, "conf", "auto", "#{basename}.conf")
-  end
-
-  def uuid
-    @arv_repo[:uuid]
-  end
-
-  def name
-    if @arv_repo[:name].nil?
-      nil
-    else
-      @clean_name ||=
-        @arv_repo[:name].sub(/^[^A-Za-z]+/, "").gsub(/[^\w\.\/]/, "")
-    end
-  end
-
-  def self.alias_config
-    conf_s = "{\n"
-    @@aliases.sort.each do |(repo_name, repo_uuid)|
-      conf_s += "\t'#{repo_name}' \t=> '#{repo_uuid}',\n"
-    end
-    conf_s += "};\n"
-    conf_s
-  end
-end
-
-begin
-  # Get our local gitolite-admin repo up to snuff
-  if not File.exist?(gitolite_admin) then
-    ensure_directory(gitolite_tmpdir, 0700)
-    Dir.chdir(gitolite_tmpdir)
-    `git clone #{gitolite_url}`
-    Dir.chdir(gitolite_admin)
-  else
-    Dir.chdir(gitolite_admin)
-    `git pull`
-  end
-
-  arv = Arvados.new
-  permissions = arv.repository.get_all_permissions
-
-  ensure_directory(gitolite_keydir, 0700)
-  admin_user_ssh_keys = UserSSHKeys.new(permissions[:user_keys], gitolite_admin_keydir)
-  # Make sure the arvados_git_user key is installed; put it in gitolite_admin_keydir
-  # because that is where gitolite will try to put it if we do not.
-  admin_user_ssh_keys.install('arvados_git_user.pub', gitolite_arvados_git_user_key)
-
-  user_ssh_keys = UserSSHKeys.new(permissions[:user_keys], gitolite_keydir)
-  permissions[:repositories].each do |repo_record|
-    repo = Repository.new(repo_record, user_ssh_keys)
-    repo.ensure_config(gitolite_admin)
-  end
-  Repository.ensure_system_config(gitolite_admin)
-
-  # Clean up public key files that should not be present
-  Dir.chdir(gitolite_keydir)
-  stale_keys = Dir.glob('*.pub').reject do |key_file|
-    user_ssh_keys.installed?(key_file)
-  end
-  if stale_keys.any?
-    stale_keys.each { |key_file| puts "Extra file #{key_file}" }
-    system("git", "rm", "--quiet", *stale_keys)
-  end
-
-  if UserSSHKeys.changed? or Repository.changed? or stale_keys.any?
-    message = "#{Time.now().to_s}: update from API"
-    Dir.chdir(gitolite_admin)
-    `git add --all`
-    `git commit -m '#{message}'`
-    `git push`
-  end
-
-rescue => bang
-  puts "Error: " + bang.to_s
-  puts bang.backtrace.join("\n")
-  exit 1
-end
-
diff --git a/services/api/script/migrate-gitolite-to-uuid-storage.rb b/services/api/script/migrate-gitolite-to-uuid-storage.rb
deleted file mode 100755 (executable)
index 98f25ca..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/usr/bin/env ruby
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-#
-# Prior to April 2015, Arvados Gitolite integration stored repositories by
-# name.  To improve user repository management, we switched to storing
-# repositories by UUID, and aliasing them to names.  This makes it easy to
-# have rich name hierarchies, and allow users to rename repositories.
-#
-# This script will migrate a name-based Gitolite configuration to a UUID-based
-# one.  To use it:
-#
-# 1. Change the value of REPOS_DIR below, if needed.
-# 2. Install this script in the same directory as `update-gitolite.rb`.
-# 3. Ensure that no *other* users can access Gitolite: edit gitolite's
-#    authorized_keys file so it only contains the arvados_git_user key,
-#    and disable the update-gitolite cron job.
-# 4. Run this script: `ruby migrate-gitolite-to-uuid-storage.rb production`.
-# 5. Undo step 3.
-
-require 'rubygems'
-require 'pp'
-require 'arvados'
-require 'tempfile'
-require 'yaml'
-
-REPOS_DIR = "/var/lib/gitolite/repositories"
-
-# Default is development
-production = ARGV[0] == "production"
-
-ENV["RAILS_ENV"] = "development"
-ENV["RAILS_ENV"] = "production" if production
-
-DEBUG = 1
-
-# load and merge in the environment-specific application config info
-# if present, overriding base config parameters as specified
-path = File.dirname(__FILE__) + '/config/arvados-clients.yml'
-if File.exist?(path) then
-  cp_config = File.open(path) do |f|
-    YAML.safe_load(f, filename: path)[ENV['RAILS_ENV']]
-  end
-else
-  puts "Please create a\n " + File.dirname(__FILE__) + "/config/arvados-clients.yml\n file"
-  exit 1
-end
-
-gitolite_url = cp_config['gitolite_url']
-gitolite_arvados_git_user_key = cp_config['gitolite_arvados_git_user_key']
-
-gitolite_tmpdir = File.join(File.absolute_path(File.dirname(__FILE__)),
-                            cp_config['gitolite_tmp'])
-gitolite_admin = File.join(gitolite_tmpdir, 'gitolite-admin')
-gitolite_keydir = File.join(gitolite_admin, 'keydir', 'arvados')
-
-ENV['ARVADOS_API_HOST'] = cp_config['arvados_api_host']
-ENV['ARVADOS_API_TOKEN'] = cp_config['arvados_api_token']
-if cp_config['arvados_api_host_insecure']
-  ENV['ARVADOS_API_HOST_INSECURE'] = 'true'
-else
-  ENV.delete('ARVADOS_API_HOST_INSECURE')
-end
-
-def ensure_directory(path, mode)
-  begin
-    Dir.mkdir(path, mode)
-  rescue Errno::EEXIST
-  end
-end
-
-def replace_file(path, contents)
-  unlink_now = true
-  dirname, basename = File.split(path)
-  new_file = Tempfile.new([basename, ".tmp"], dirname)
-  begin
-    new_file.write(contents)
-    new_file.flush
-    File.rename(new_file, path)
-    unlink_now = false
-  ensure
-    new_file.close(unlink_now)
-  end
-end
-
-def file_has_contents?(path, contents)
-  begin
-    IO.read(path) == contents
-  rescue Errno::ENOENT
-    false
-  end
-end
-
-module TrackCommitState
-  module ClassMethods
-    # Note that all classes that include TrackCommitState will have
-    # @@need_commit = true if any of them set it.  Since this flag reports
-    # a boolean state of the underlying git repository, that's OK in the
-    # current implementation.
-    @@need_commit = false
-
-    def changed?
-      @@need_commit
-    end
-
-    def ensure_in_git(path, contents)
-      unless file_has_contents?(path, contents)
-        replace_file(path, contents)
-        system("git", "add", path)
-        @@need_commit = true
-      end
-    end
-  end
-
-  def ensure_in_git(path, contents)
-    self.class.ensure_in_git(path, contents)
-  end
-
-  def self.included(base)
-    base.extend(ClassMethods)
-  end
-end
-
-class Repository
-  include TrackCommitState
-
-  @@aliases = {}
-
-  def initialize(arv_repo)
-    @arv_repo = arv_repo
-  end
-
-  def self.ensure_system_config(conf_root)
-    ensure_in_git(File.join(conf_root, "arvadosaliases.pl"), alias_config)
-  end
-
-  def self.rename_repos(repos_root)
-    @@aliases.each_pair do |uuid, name|
-      begin
-        File.rename(File.join(repos_root, "#{name}.git/"),
-                    File.join(repos_root, "#{uuid}.git"))
-      rescue Errno::ENOENT
-      end
-      if name == "arvados"
-        Dir.chdir(repos_root) { File.symlink("#{uuid}.git/", "arvados.git") }
-      end
-    end
-  end
-
-  def ensure_config(conf_root)
-    return if name.nil?
-    @@aliases[uuid] = name
-    name_conf_path = auto_conf_path(conf_root, name)
-    return unless File.exist?(name_conf_path)
-    conf_file = IO.read(name_conf_path)
-    conf_file.gsub!(/^repo #{Regexp.escape(name)}$/m, "repo #{uuid}")
-    ensure_in_git(auto_conf_path(conf_root, uuid), conf_file)
-    File.unlink(name_conf_path)
-    system("git", "rm", "--quiet", name_conf_path)
-  end
-
-  private
-
-  def auto_conf_path(conf_root, basename)
-    File.join(conf_root, "conf", "auto", "#{basename}.conf")
-  end
-
-  def uuid
-    @arv_repo[:uuid]
-  end
-
-  def name
-    if @arv_repo[:name].nil?
-      nil
-    else
-      @clean_name ||=
-        @arv_repo[:name].sub(/^[^A-Za-z]+/, "").gsub(/[^\w\.\/]/, "")
-    end
-  end
-
-  def self.alias_config
-    conf_s = "{\n"
-    @@aliases.sort.each do |(repo_name, repo_uuid)|
-      conf_s += "\t'#{repo_name}' \t=> '#{repo_uuid}',\n"
-    end
-    conf_s += "};\n"
-    conf_s
-  end
-end
-
-begin
-  # Get our local gitolite-admin repo up to snuff
-  if not File.exist?(gitolite_admin) then
-    ensure_directory(gitolite_tmpdir, 0700)
-    Dir.chdir(gitolite_tmpdir)
-    `git clone #{gitolite_url}`
-    Dir.chdir(gitolite_admin)
-  else
-    Dir.chdir(gitolite_admin)
-    `git pull`
-  end
-
-  arv = Arvados.new
-  permissions = arv.repository.get_all_permissions
-
-  permissions[:repositories].each do |repo_record|
-    repo = Repository.new(repo_record)
-    repo.ensure_config(gitolite_admin)
-  end
-  Repository.ensure_system_config(gitolite_admin)
-
-  message = "#{Time.now().to_s}: migrate to storing repositories by UUID"
-  Dir.chdir(gitolite_admin)
-  `git add --all`
-  `git commit -m '#{message}'`
-  Repository.rename_repos(REPOS_DIR)
-  `git push`
-
-rescue => bang
-  puts "Error: " + bang.to_s
-  puts bang.backtrace.join("\n")
-  exit 1
-end
-
index c6ade21f8bdf2333288581da93b0d47cab886f4c..882937034bb6dc33e9caa13bfcb52ca9b5e1c1e9 100644 (file)
@@ -128,14 +128,6 @@ active_userlist:
   expires_at: 2038-01-01 00:00:00
   scopes: ["GET /arvados/v1/users"]
 
-active_specimens:
-  uuid: zzzzz-gj3su-177z32aux8dg2s1
-  api_client: untrusted
-  user: active
-  api_token: activespecimensabcdefghijklmnopqrstuvwxyz123456890
-  expires_at: 2038-01-01 00:00:00
-  scopes: ["GET /arvados/v1/specimens/"]
-
 active_apitokens:
   uuid: zzzzz-gj3su-187z32aux8dg2s1
   api_client: trusted_workbench
@@ -160,14 +152,21 @@ spectator:
   api_token: zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu
   expires_at: 2038-01-01 00:00:00
 
-spectator_specimens:
+foo:
+  uuid: zzzzz-gj3su-fohzae5ib1aseiv
+  api_client: untrusted
+  user: user_foo_in_sharing_group
+  api_token: lokah4xip8ahgee8oof5zitah3ohdai6je9cu1uogh4bai3ohw
+  expires_at: 2038-01-01 00:00:00
+
+foo_collections:
   uuid: zzzzz-gj3su-217z32aux8dg2s1
   api_client: untrusted
-  user: spectator
-  api_token: spectatorspecimensabcdefghijklmnopqrstuvwxyz123245
+  user: user_foo_in_sharing_group
+  api_token: spectatorcollectionscdefghijklmnopqrstuvwxyz123245
   expires_at: 2038-01-01 00:00:00
-  scopes: ["GET /arvados/v1/specimens", "GET /arvados/v1/specimens/",
-           "POST /arvados/v1/specimens"]
+  scopes: ["GET /arvados/v1/collections", "GET /arvados/v1/collections/",
+           "POST /arvados/v1/collections"]
 
 inactive:
   uuid: zzzzz-gj3su-227z32aux8dg2s1
index 72aad1d68ee3f28e7fe853cf911ac4841cf896e0..a193150e29acaf885258820d7a4505f6ea3171b7 100644 (file)
@@ -451,22 +451,6 @@ unique_expired_collection2:
   manifest_text: ". 29d7797f1888013986899bc9083783fa+3 0:3:expired2\n"
   name: unique_expired_collection2
 
-# a collection with a log file that can be parsed by the log viewer
-# This collection hash matches the following log text:
-#    2014-01-01_12:00:01 zzzzz-8i9sb-abcdefghijklmno 0  log message 1
-#    2014-01-01_12:00:02 zzzzz-8i9sb-abcdefghijklmno 0  log message 2
-#    2014-01-01_12:00:03 zzzzz-8i9sb-abcdefghijklmno 0  log message 3
-#
-real_log_collection:
-  uuid: zzzzz-4zz18-op4e2lbej01tcvu
-  current_version_uuid: zzzzz-4zz18-op4e2lbej01tcvu
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-09-01 12:00:00
-  modified_at: 2014-09-01 12:00:00
-  portable_data_hash: 0b9a7787660e1fce4a93f33e01376ba6+81
-  manifest_text: ". cdd549ae79fe6640fa3d5c6261d8303c+195 0:195:zzzzz-8i9sb-0vsrcqi7whchuil.log.txt\n"
-  name: real_log_collection
-
 collection_in_home_project_with_same_name_as_in_aproject:
   uuid: zzzzz-4zz18-12342x4u7ftabcd
   current_version_uuid: zzzzz-4zz18-12342x4u7ftabcd
@@ -1076,6 +1060,18 @@ collection_with_uri_prop:
   properties:
     "http://schema.org/example": "value1"
 
+container_log_collection:
+  uuid: zzzzz-4zz18-logcollection00
+  current_version_uuid: zzzzz-4zz18-logcollection00
+  portable_data_hash: b1e66f713c04d28ddbaced89096f4838+210
+  owner_uuid: zzzzz-tpzed-000000000000000
+  created_at: 2020-10-29T00:51:44.075594000Z
+  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+  modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
+  modified_at: 2020-10-29T00:51:44.072109000Z
+  manifest_text: ". 8c12f5f5297b7337598170c6f531fcee+7882 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt\n"
+  name: a real log collection for a completed container
+
 log_collection:
   uuid: zzzzz-4zz18-logcollection01
   current_version_uuid: zzzzz-4zz18-logcollection01
@@ -1086,7 +1082,7 @@ log_collection:
   modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
   modified_at: 2020-10-29T00:51:44.072109000Z
   manifest_text: ". 8c12f5f5297b7337598170c6f531fcee+7882 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt\n./log\\040for\\040container\\040ce8i5-dz642-h4kd64itncdcz8l 8c12f5f5297b7337598170c6f531fcee+7882 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt\n"
-  name: a real log collection for a completed container
+  name: a real log collection for a completed container request
 
 log_collection2:
   uuid: zzzzz-4zz18-logcollection02
index 71c7a54df3981eb531f0b36d28788aa3a6d29247..3b035416cb09a3c992edde29add5075afe6b1a1f 100644 (file)
@@ -1056,6 +1056,36 @@ runtime_token:
     ram: 123
   mounts: {}
 
+read_foo_write_bar:
+  uuid: zzzzz-xvdhp-readfoowritebar
+  owner_uuid: zzzzz-tpzed-000000000000000
+  state: Final
+  created_at: 2024-01-11 11:11:11.111111111 Z
+  updated_at: 2024-01-11 11:11:11.111111111 Z
+  modified_at: 2024-01-11 11:11:11.111111111 Z
+  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  container_image: test
+  cwd: /
+  mounts:
+    stdin:
+      kind: collection
+      portable_data_hash: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
+      path: /foo
+    stdout:
+      kind: file
+      path: /mnt/out/bar
+    /mnt/out:
+      kind: tmp
+      capacity: 1000
+  container_uuid: zzzzz-dz642-readfoowritebar
+  log_uuid: zzzzz-4zz18-logcollection01
+  output_uuid: zzzzz-4zz18-ehbhgtheo8909or
+  output_path: test
+  command: ["echo", "-n", "bar"]
+  runtime_constraints:
+    ram: 10000000
+    vcpus: 1
+
 
 # Test Helper trims the rest of the file
 
index 46bc1e50f9da3bdbc417fef55116c74601e7c319..8e40554a9bda02cbfa99eb8e3c388c3470a8d456 100644 (file)
@@ -485,3 +485,36 @@ cuda_container:
       device_count: 1
   secret_mounts: {}
   secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
+
+read_foo_write_bar:
+  uuid: zzzzz-dz642-readfoowritebar
+  owner_uuid: zzzzz-tpzed-000000000000000
+  state: Complete
+  exit_code: 0
+  priority: 1
+  created_at: 2024-01-11 11:11:11.111111111 Z
+  updated_at: 2024-01-11 11:11:11.111111111 Z
+  started_at: 2024-01-11 11:11:11.111111111 Z
+  finished_at: 2024-01-12 11:12:13.111111111 Z
+  container_image: test
+  cwd: /
+  mounts:
+    stdin:
+      kind: collection
+      portable_data_hash: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
+      path: /foo
+    stdout:
+      kind: file
+      path: /mnt/out/bar
+    /mnt/out:
+      kind: tmp
+      capacity: 1000
+  log: ea10d51bcf88862dbcc36eb292017dfd+45
+  output: fa7aeb5140e2848d39b416daeef4ffc5+45
+  output_path: test
+  command: ["echo", "-n", "bar"]
+  runtime_constraints:
+    ram: 10000000
+    vcpus: 1
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
diff --git a/services/api/test/fixtures/humans.yml b/services/api/test/fixtures/humans.yml
deleted file mode 100644 (file)
index eee61ef..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-# File exists to ensure the table gets cleared during DatabaseController#reset
diff --git a/services/api/test/fixtures/job_tasks.yml b/services/api/test/fixtures/job_tasks.yml
deleted file mode 100644 (file)
index 6a857a0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-running_job_task_1:
-  uuid: zzzzz-ot0gb-runningjobtask1
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  job_uuid: zzzzz-8i9sb-with2components
-
-running_job_task_2:
-  uuid: zzzzz-ot0gb-runningjobtask2
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  job_uuid: zzzzz-8i9sb-with2components
diff --git a/services/api/test/fixtures/jobs.yml b/services/api/test/fixtures/jobs.yml
deleted file mode 100644 (file)
index 54b3825..0000000
+++ /dev/null
@@ -1,768 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-running:
-  uuid: zzzzz-8i9sb-pshmckwoma9plh7
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 2.7.minute.ago.to_fs(:db) %>
-  started_at: <%= 2.7.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  script: hash
-  repository: active/foo
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-running_cancelled:
-  uuid: zzzzz-8i9sb-4cf0nhn6xte809j
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: <%= 1.minute.ago.to_fs(:db) %>
-  cancelled_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  script: hash
-  repository: active/foo
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Cancelled
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-uses_nonexistent_script_version:
-  uuid: zzzzz-8i9sb-7m339pu0x9mla88
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  created_at: <%= 5.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: <%= 2.minute.ago.to_fs(:db) %>
-  script: hash
-  repository: active/foo
-  running: false
-  success: true
-  output: d41d8cd98f00b204e9800998ecf8427e+0
-  priority: 0
-  log: d41d8cd98f00b204e9800998ecf8427e+0
-  is_locked_by_uuid: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 0
-    done: 1
-  runtime_constraints: {}
-  state: Complete
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-foobar:
-  uuid: zzzzz-8i9sb-aceg2bnq7jt7kon
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  script: hash
-  repository: active/foo
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  script_parameters:
-    input: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: <%= 2.minute.ago.to_fs(:db) %>
-  running: false
-  success: true
-  output: fa7aeb5140e2848d39b416daeef4ffc5+45
-  priority: 0
-  log: ea10d51bcf88862dbcc36eb292017dfd+45
-  is_locked_by_uuid: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 0
-    done: 1
-  runtime_constraints: {}
-  state: Complete
-  script_parameters_digest: 03a43a7d84f7fb022467b876c2950acd
-
-barbaz:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykyuq
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: 1
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: <%= 2.minute.ago.to_fs(:db) %>
-  running: false
-  success: true
-  repository: active/foo
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  priority: 0
-  log: d41d8cd98f00b204e9800998ecf8427e+0
-  is_locked_by_uuid: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 0
-    done: 1
-  runtime_constraints: {}
-  state: Complete
-  script_parameters_digest: c3d19d3ec50ac0914baa56b149640f73
-
-runningbarbaz:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykyuj
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: 1
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: <%= 2.minute.ago.to_fs(:db) %>
-  running: true
-  success: ~
-  repository: active/foo
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  priority: 0
-  log: d41d8cd98f00b204e9800998ecf8427e+0
-  is_locked_by_uuid: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 1
-    done: 0
-  runtime_constraints: {}
-  state: Running
-  script_parameters_digest: c3d19d3ec50ac0914baa56b149640f73
-
-previous_job_run:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  finished_at: <%= 13.minutes.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "1"
-  success: true
-  log: d41d8cd98f00b204e9800998ecf8427e+0
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  state: Complete
-  script_parameters_digest: a5f03bbfb8ba88a2efe4a7852671605b
-
-previous_job_run_nil_log:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykqq3
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  finished_at: <%= 13.minutes.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "3"
-  success: true
-  log: ~
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  state: Complete
-  script_parameters_digest: 445702df4029b8a6e7075b451ff1256a
-
-previous_ancient_job_run:
-  uuid: zzzzz-8i9sb-ahd7cie8jah9qui
-  created_at: <%= 366.days.ago.to_fs(:db) %>
-  finished_at: <%= 365.days.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "2"
-  success: true
-  log: d41d8cd98f00b204e9800998ecf8427e+0
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  state: Complete
-  script_parameters_digest: 174dd339d44f2b259fadbab7ebdb8df9
-
-previous_docker_job_run:
-  uuid: zzzzz-8i9sb-k6emstgk4kw4yhi
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "1"
-  runtime_constraints:
-    docker_image: arvados/apitestfixture
-  success: true
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  docker_image_locator: fa3c1a9cb6783f85f2ecda037e07b8c3+167
-  state: Complete
-  script_parameters_digest: a5f03bbfb8ba88a2efe4a7852671605b
-  log: ea10d51bcf88862dbcc36eb292017dfd+45
-
-previous_ancient_docker_image_job_run:
-  uuid: zzzzz-8i9sb-t3b460aolxxuldl
-  created_at: <%= 144.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "2"
-  runtime_constraints:
-    docker_image: arvados/apitestfixture
-  success: true
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  docker_image_locator: b519d9cb706a29fc7ea24dbea2f05851+93
-  state: Complete
-  script_parameters_digest: 174dd339d44f2b259fadbab7ebdb8df9
-
-previous_job_run_with_arvados_sdk_version:
-  uuid: zzzzz-8i9sb-eoo0321or2dw2jg
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 31ce37fe365b3dc204300a3e4c396ad333ed0556
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "1"
-  runtime_constraints:
-    arvados_sdk_version: commit2
-    docker_image: arvados/apitestfixture
-  arvados_sdk_version: 00634b2b8a492d6f121e3cf1d6587b821136a9a7
-  docker_image_locator: fa3c1a9cb6783f85f2ecda037e07b8c3+167
-  success: true
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  state: Complete
-  script_parameters_digest: a5f03bbfb8ba88a2efe4a7852671605b
-  log: ea10d51bcf88862dbcc36eb292017dfd+45
-
-previous_job_run_no_output:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykppp
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "2"
-  success: true
-  output: ~
-  state: Complete
-  script_parameters_digest: 174dd339d44f2b259fadbab7ebdb8df9
-
-previous_job_run_superseded_by_hash_branch:
-  # This supplied_script_version is a branch name with later commits.
-  uuid: zzzzz-8i9sb-aeviezu5dahph3e
-  created_at: <%= 15.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/shabranchnames
-  script: testscript
-  script_version: 7387838c69a21827834586cc42b467ff6c63293b
-  supplied_script_version: 738783
-  script_parameters: {}
-  success: true
-  output: d41d8cd98f00b204e9800998ecf8427e+0
-  state: Complete
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-nondeterminisic_job_run:
-  uuid: zzzzz-8i9sb-cjs4pklxxjykyyy
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: hash2
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    an_integer: "1"
-  success: true
-  nondeterministic: true
-  state: Complete
-  script_parameters_digest: a5f03bbfb8ba88a2efe4a7852671605b
-
-nearly_finished_job:
-  uuid: zzzzz-8i9sb-2gx6rz0pjl033w3
-  created_at: <%= 14.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: arvados
-  script: doesnotexist
-  script_version: 309e25a64fe994867db8459543af372f850e25b9
-  script_parameters:
-    input: b519d9cb706a29fc7ea24dbea2f05851+249025
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  running: true
-  success: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 1
-    done: 0
-  runtime_constraints: {}
-  state: Complete
-  script_parameters_digest: 7ea26d58a79b7f5db9f90fb1e33d3006
-
-queued:
-  uuid: zzzzz-8i9sb-grx15v5mjnsyxk7
-  created_at: <%= 1.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  started_at: ~
-  finished_at: ~
-  script: foo
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters: {}
-  running: ~
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: ~
-  tasks_summary: {}
-  runtime_constraints: {}
-  state: Queued
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-# A job with a log collection that can be parsed by the log viewer.
-job_with_real_log:
-  uuid: zzzzz-8i9sb-0vsrcqi7whchuil
-  created_at: 2014-09-01 12:00:00
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  log: 0b9a7787660e1fce4a93f33e01376ba6+81
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  state: Complete
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-cancelled:
-  uuid: zzzzz-8i9sb-4cf0abc123e809j
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: <%= 1.minute.ago.to_fs(:db) %>
-  cancelled_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  running: false
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Cancelled
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-job_in_subproject:
-  uuid: zzzzz-8i9sb-subprojectjob01
-  created_at: 2014-10-15 12:00:00
-  owner_uuid: zzzzz-j7d0g-axqo7eu9pwvna1x
-  log: ~
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-job_in_trashed_project:
-  uuid: zzzzz-8i9sb-subprojectjob02
-  created_at: 2014-10-15 12:00:00
-  owner_uuid: zzzzz-j7d0g-trashedproject2
-  log: ~
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-running_will_be_completed:
-  uuid: zzzzz-8i9sb-rshmckwoma9pjh8
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-d9tiejq69daie8f
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-graph_stage1:
-  uuid: zzzzz-8i9sb-graphstage10000
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  repository: active/foo
-  script: hash
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  output: fa7aeb5140e2848d39b416daeef4ffc5+45
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-graph_stage2:
-  uuid: zzzzz-8i9sb-graphstage20000
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  repository: active/foo
-  script: hash2
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    input2: "stuff"
-  output: 65b17c95fdbc9800fc48acda4e9dcd0b+93
-  script_parameters_digest: 4900033ec5cfaf8a63566f3664aeaa70
-
-graph_stage3:
-  uuid: zzzzz-8i9sb-graphstage30000
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  repository: active/foo
-  script: hash2
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    input2: "stuff2"
-  output: ea10d51bcf88862dbcc36eb292017dfd+45
-  script_parameters_digest: 02a085407e751d00b5dc88f1bd5e8247
-
-job_with_latest_version:
-  uuid: zzzzz-8i9sb-nj8ioxnrvjtyk2b
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  script: hash
-  repository: active/foo
-  script_version: 7def43a4d3f20789dda4700f703b5514cc3ed250
-  supplied_script_version: main
-  script_parameters:
-    input: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  started_at: <%= 2.minute.ago.to_fs(:db) %>
-  finished_at: <%= 1.minute.ago.to_fs(:db) %>
-  running: false
-  success: true
-  output: fa7aeb5140e2848d39b416daeef4ffc5+45
-  priority: 0
-  log: ea10d51bcf88862dbcc36eb292017dfd+45
-  is_locked_by_uuid: ~
-  tasks_summary:
-    failed: 0
-    todo: 0
-    running: 0
-    done: 1
-  runtime_constraints: {}
-  state: Complete
-  script_parameters_digest: 03a43a7d84f7fb022467b876c2950acd
-
-running_job_in_publicly_accessible_project:
-  uuid: zzzzz-8i9sb-n7omg50bvt0m1nf
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/bar
-  script: running_job_script
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Running
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    input2: "stuff2"
-  script_parameters_digest: 02a085407e751d00b5dc88f1bd5e8247
-
-completed_job_in_publicly_accessible_project:
-  uuid: zzzzz-8i9sb-jyq01m7in1jlofj
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: completed_job_script
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    input2: "stuff2"
-  log: zzzzz-4zz18-4en62shvi99lxd4
-  output: b519d9cb706a29fc7ea24dbea2f05851+93
-  script_parameters_digest: 02a085407e751d00b5dc88f1bd5e8247
-  started_at: <%= 10.minute.ago.to_fs(:db) %>
-  finished_at: <%= 5.minute.ago.to_fs(:db) %>
-
-job_in_publicly_accessible_project_but_other_objects_elsewhere:
-  uuid: zzzzz-8i9sb-jyq01muyhgr4ofj
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  repository: active/foo
-  script: completed_job_script
-  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
-  state: Complete
-  script_parameters:
-    input: fa7aeb5140e2848d39b416daeef4ffc5+45
-    input2: "stuff2"
-  log: zzzzz-4zz18-fy296fx3hot09f7
-  output: zzzzz-4zz18-bv31uwvy3neko21
-  script_parameters_digest: 02a085407e751d00b5dc88f1bd5e8247
-
-running_job_with_components:
-  uuid: zzzzz-8i9sb-with2components
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  started_at: <%= 3.minute.ago.to_fs(:db) %>
-  finished_at: ~
-  script: hash
-  repository: active/foo
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  components:
-    component1: zzzzz-8i9sb-jyq01m7in1jlofj
-    component2: zzzzz-d1hrv-partdonepipelin
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-
-# This main level job is in running state with one job and one pipeline instance components
-running_job_with_components_at_level_1:
-  uuid: zzzzz-8i9sb-jobcomponentsl1
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  components:
-    component1: zzzzz-8i9sb-jobcomponentsl2
-    component2: zzzzz-d1hrv-picomponentsl02
-
-# This running job, a child of level_1, has one child component
-running_job_with_components_at_level_2:
-  uuid: zzzzz-8i9sb-jobcomponentsl2
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  components:
-    component1: zzzzz-8i9sb-job1atlevel3noc
-
-# The below two running jobs, children of level_2, have no child components
-running_job_1_with_components_at_level_3:
-  uuid: zzzzz-8i9sb-job1atlevel3noc
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-
-running_job_2_with_components_at_level_3:
-  uuid: zzzzz-8i9sb-job2atlevel3noc
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-
-# The two jobs below are so confused, they have circular relationship
-running_job_1_with_circular_component_relationship:
-  uuid: zzzzz-8i9sb-job1withcirculr
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  components:
-    component1: zzzzz-8i9sb-job2withcirculr
-
-running_job_2_with_circular_component_relationship:
-  uuid: zzzzz-8i9sb-job2withcirculr
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  cancelled_at: ~
-  cancelled_by_user_uuid: ~
-  cancelled_by_client_uuid: ~
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  finished_at: ~
-  repository: active/foo
-  script: hash
-  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
-  script_parameters_digest: 99914b932bd37a50b983c5e7c90ae93b
-  running: true
-  success: ~
-  output: ~
-  priority: 0
-  log: ~
-  is_locked_by_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  tasks_summary:
-    failed: 0
-    todo: 3
-    running: 1
-    done: 1
-  runtime_constraints: {}
-  state: Running
-  components:
-    component1: zzzzz-8i9sb-job1withcirculr
diff --git a/services/api/test/fixtures/keep_disks.yml b/services/api/test/fixtures/keep_disks.yml
deleted file mode 100644 (file)
index 5cccf49..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-nonfull:
-  uuid: zzzzz-penuu-5w2o2t1q5wy7fhn
-  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
-  node_uuid: zzzzz-7ekkf-53y36l1lu5ijveb
-  keep_service_uuid: zzzzz-bi6l4-6zhilxar6r8ey90
-  last_read_at: <%= 1.minute.ago.to_fs(:db) %>
-  last_write_at: <%= 2.minute.ago.to_fs(:db) %>
-  last_ping_at: <%= 3.minute.ago.to_fs(:db) %>
-  ping_secret: z9xz2tc69dho51g1dmkdy5fnupdhsprahcwxdbjs0zms4eo6i
-
-full:
-  uuid: zzzzz-penuu-4kmq58ui07xuftx
-  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
-  node_uuid: zzzzz-7ekkf-53y36l1lu5ijveb
-  keep_service_uuid: zzzzz-bi6l4-6zhilxar6r8ey90
-  last_read_at: <%= 1.minute.ago.to_fs(:db) %>
-  last_write_at: <%= 2.day.ago.to_fs(:db) %>
-  last_ping_at: <%= 3.minute.ago.to_fs(:db) %>
-  ping_secret: xx3ieejcufbjy4lli6yt5ig4e8w5l2hhgmbyzpzuq38gri6lj
-
-nonfull2:
-  uuid: zzzzz-penuu-1ydrih9k2er5j11
-  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
-  node_uuid: zzzzz-7ekkf-2z3mc76g2q73aio
-  keep_service_uuid: zzzzz-bi6l4-rsnj3c76ndxb7o0
-  last_read_at: <%= 1.minute.ago.to_fs(:db) %>
-  last_write_at: <%= 2.minute.ago.to_fs(:db) %>
-  last_ping_at: <%= 3.minute.ago.to_fs(:db) %>
-  ping_secret: 4rs260ibhdum1d242xy23qv320rlerc0j7qg9vyqnchbgmjeek
index 00d597153486ae391c255640d44dfaf93e8a71dd..61ad60451d088f15a554cf8661b28ed0f977def8 100644 (file)
@@ -254,104 +254,6 @@ baz_file_publicly_readable:
   head_uuid: zzzzz-4zz18-y9vne9npefyxh8g
   properties: {}
 
-barbaz_job_readable_by_spectator:
-  uuid: zzzzz-o0j2j-cpy7p41hpk531e1
-  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-tpzed-l1s2piq4t4mps8r
-  link_class: permission
-  name: can_read
-  head_uuid: zzzzz-8i9sb-cjs4pklxxjykyuq
-  properties: {}
-
-runningbarbaz_job_readable_by_spectator:
-  uuid: zzzzz-o0j2j-cpy7p41hpk531e2
-  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-tpzed-l1s2piq4t4mps8r
-  link_class: permission
-  name: can_read
-  head_uuid: zzzzz-8i9sb-cjs4pklxxjykyuj
-  properties: {}
-
-arvados_repository_readable_by_all_users:
-  uuid: zzzzz-o0j2j-allcanreadarvrp
-  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-fffffffffffffff
-  link_class: permission
-  name: can_read
-  head_uuid: zzzzz-s0uqq-arvadosrepo0123
-  properties: {}
-
-foo_repository_readable_by_spectator:
-  uuid: zzzzz-o0j2j-cpy7p41hpk5xxx
-  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-tpzed-l1s2piq4t4mps8r
-  link_class: permission
-  name: can_read
-  head_uuid: zzzzz-s0uqq-382brsig8rp3666
-  properties: {}
-
-foo_repository_manageable_by_active:
-  uuid: zzzzz-o0j2j-8tdfjd8g0s4rn1k
-  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-tpzed-xurymjxw79nv3jz
-  link_class: permission
-  name: can_manage
-  head_uuid: zzzzz-s0uqq-382brsig8rp3666
-  properties: {}
-
-repository3_readable_by_active:
-  uuid: zzzzz-o0j2j-43iem9bdtefa76g
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-09-23 13:52:46 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-09-23 13:52:46 -0400
-  updated_at: 2014-09-23 13:52:46 -0400
-  tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  link_class: permission
-  name: can_read
-  head_uuid: zzzzz-s0uqq-38orljkqpyo1j61
-  properties: {}
-
-repository4_writable_by_active:
-  uuid: zzzzz-o0j2j-lio9debdt6yhkil
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-09-23 13:52:46 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-09-23 13:52:46 -0400
-  updated_at: 2014-09-23 13:52:46 -0400
-  tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  link_class: permission
-  name: can_write
-  head_uuid: zzzzz-s0uqq-38oru8hnk57ht34
-  properties: {}
-
 miniadmin_user_is_a_testusergroup_admin:
   uuid: zzzzz-o0j2j-38vvkciz7qc12j9
   owner_uuid: zzzzz-tpzed-000000000000000
@@ -784,81 +686,6 @@ docker_image_tag_like_hash:
   properties:
     image_timestamp: "2014-06-10T14:30:00.184019565Z"
 
-job_reader_can_read_previous_job_run:
-  # Permission link giving job_reader permission
-  # to read previous_job_run
-  uuid: zzzzz-o0j2j-8bbd851795ebafd
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-06-13 20:42:26 -0800
-  modified_by_client_uuid: zzzzz-tpzed-000000000000000
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-06-13 20:42:26 -0800
-  updated_at: 2014-06-13 20:42:26 -0800
-  link_class: permission
-  name: can_read
-  tail_uuid: zzzzz-tpzed-905b42d1dd4a354
-  head_uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-
-job_reader_can_read_foo_repo:
-  # Permission link giving job_reader permission
-  # to read foo_repo
-  uuid: zzzzz-o0j2j-072ec05dc9487f8
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-06-13 20:42:26 -0800
-  modified_by_client_uuid: zzzzz-tpzed-000000000000000
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-06-13 20:42:26 -0800
-  updated_at: 2014-06-13 20:42:26 -0800
-  link_class: permission
-  name: can_read
-  tail_uuid: zzzzz-tpzed-905b42d1dd4a354
-  head_uuid: zzzzz-s0uqq-382brsig8rp3666
-
-job_reader2_can_read_job_with_components:
-  # Permission link giving job_reader2 permission
-  # to read running_job_with_components
-  uuid: zzzzz-o0j2j-jobcomps4jobrdr
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-06-13 20:42:26 -0800
-  modified_by_client_uuid: zzzzz-tpzed-000000000000000
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-06-13 20:42:26 -0800
-  updated_at: 2014-06-13 20:42:26 -0800
-  link_class: permission
-  name: can_read
-  tail_uuid: zzzzz-tpzed-readjobwithcomp
-  head_uuid: zzzzz-8i9sb-with2components
-
-job_reader2_can_read_pipeline_from_job_with_components:
-  # Permission link giving job_reader2 permission
-  # to read running_job_with_components
-  uuid: zzzzz-o0j2j-pi4comps4jobrdr
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-06-13 20:42:26 -0800
-  modified_by_client_uuid: zzzzz-tpzed-000000000000000
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-06-13 20:42:26 -0800
-  updated_at: 2014-06-13 20:42:26 -0800
-  link_class: permission
-  name: can_read
-  tail_uuid: zzzzz-tpzed-readjobwithcomp
-  head_uuid: zzzzz-d1hrv-partdonepipelin
-
-job_reader2_can_read_first_job_from_pipeline_from_job_with_components:
-  # Permission link giving job_reader2 permission
-  # to read running_job_with_components
-  uuid: zzzzz-o0j2j-job4pi4j4jobrdr
-  owner_uuid: zzzzz-tpzed-000000000000000
-  created_at: 2014-06-13 20:42:26 -0800
-  modified_by_client_uuid: zzzzz-tpzed-000000000000000
-  modified_by_user_uuid: zzzzz-tpzed-000000000000000
-  modified_at: 2014-06-13 20:42:26 -0800
-  updated_at: 2014-06-13 20:42:26 -0800
-  link_class: permission
-  name: can_read
-  tail_uuid: zzzzz-tpzed-readjobwithcomp
-  head_uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-
 baz_collection_name_in_asubproject:
   uuid: zzzzz-o0j2j-bazprojectname2
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
index 3b41550ae784802948e33c82b2ced53930718a6f..ee24d2ac649cf9243e5cf73a9f90e8612cc9bf32 100644 (file)
@@ -11,22 +11,22 @@ noop: # nothing happened ...to the 'spectator' user
   event_at: <%= 1.minute.ago.to_fs(:db) %>
   created_at: <%= 1.minute.ago.to_fs(:db) %>
 
-admin_changes_repository2: # admin changes repository2, which is owned by active user
+admin_changes_collection_owned_by_active:
   id: 2
   uuid: zzzzz-57u5n-pshmckwoma00002
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
-  object_uuid: zzzzz-2x53u-382brsig8rp3667 # repository foo
+  object_uuid: zzzzz-4zz18-bv31uwvy3neko21 # collection_owned_by_active
   object_owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   created_at: <%= 2.minute.ago.to_fs(:db) %>
   event_at: <%= 2.minute.ago.to_fs(:db) %>
   event_type: update
 
-admin_changes_specimen: # admin changes specimen owned_by_spectator
+admin_changes_collection_owned_by_foo:
   id: 3
   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
+  object_uuid: zzzzz-4zz18-50surkhkbhsp31b # collection_owned_by_foo
+  object_owner_uuid: zzzzz-tpzed-81hsbo6mk8nl05c # foo user
   created_at: <%= 3.minute.ago.to_fs(:db) %>
   event_at: <%= 3.minute.ago.to_fs(:db) %>
   event_type: update
@@ -60,101 +60,6 @@ log_owned_by_active:
   event_at: <%= 2.minute.ago.to_fs(:db) %>
   summary: non-admin use can read own logs
 
-crunchstat_for_running_job:
-  id: 7
-  uuid: zzzzz-57u5n-tmymyrojrbtnxh1
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  modified_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  object_uuid: zzzzz-8i9sb-pshmckwoma9plh7
-  event_at: 2014-11-07 23:33:42.347455000 Z
-  event_type: stderr
-  summary: ~
-  properties:
-    text: '2014-11-07_23:33:41 zzzzz-8i9sb-pshmckwoma9plh7 31708 1 stderr crunchstat:
-      cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
-      0.9900 sys'
-  created_at: 2014-11-07 23:33:42.351913000 Z
-  updated_at: 2014-11-07 23:33:42.347455000 Z
-  modified_at: 2014-11-07 23:33:42.347455000 Z
-  object_owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-
-log_line_for_pipeline_in_publicly_accessible_project:
-  id: 8
-  uuid: zzzzz-57u5n-tmymyrojrjyhb45
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  modified_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  object_uuid: zzzzz-d1hrv-n68vc490mloy4fi
-  event_at: 2014-11-07 23:33:42.347455000 Z
-  event_type: stderr
-  summary: ~
-  properties:
-    text: '2014-11-07_23:33:41 zzzzz-d1hrv-n68vc490mloy4fi 31708 1 stderr crunchstat:
-      cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
-      0.9900 sys'
-  created_at: 2014-11-07 23:33:42.351913000 Z
-  updated_at: 2014-11-07 23:33:42.347455000 Z
-  modified_at: 2014-11-07 23:33:42.347455000 Z
-  object_owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-
-log_line_for_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere:
-  id: 9
-  uuid: zzzzz-57u5n-tmyhy56k9lnhb45
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  modified_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  object_uuid: zzzzz-d1hrv-pisharednotobjs
-  event_at: 2014-11-07 23:33:42.347455000 Z
-  event_type: stderr
-  summary: ~
-  properties:
-    text: '2014-11-07_23:33:41 zzzzz-d1hrv-pisharednotobjs 31708 1 stderr crunchstat:
-      cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
-      0.9900 sys'
-  created_at: 2014-11-07 23:33:42.351913000 Z
-  updated_at: 2014-11-07 23:33:42.347455000 Z
-  modified_at: 2014-11-07 23:33:42.347455000 Z
-  object_owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-
-crunchstat_for_previous_job:
-  id: 10
-  uuid: zzzzz-57u5n-eir3aesha3kaene
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  modified_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  object_uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-  event_at: 2014-11-07 23:33:42.347455000 Z
-  event_type: stderr
-  summary: ~
-  properties:
-    text: '2014-11-07_23:33:41 zzzzz-8i9sb-cjs4pklxxjykqqq 11592 1 stderr crunchstat:
-      cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
-      0.9900 sys'
-  created_at: 2014-11-07 23:33:42.351913000 Z
-  updated_at: 2014-11-07 23:33:42.347455000 Z
-  modified_at: 2014-11-07 23:33:42.347455000 Z
-  object_owner_uuid: zzzzz-j7d0g-xurymjxw79nv3jz
-
-crunchstat_for_ancient_job:
-  id: 11
-  uuid: zzzzz-57u5n-ixioph7ieb5ung8
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  modified_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  object_uuid: zzzzz-8i9sb-ahd7cie8jah9qui
-  event_at: 2013-11-07 23:33:42.347455000 Z
-  event_type: stderr
-  summary: ~
-  properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
-      cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
-      0.9900 sys'
-  created_at: 2013-11-07 23:33:42.351913000 Z
-  updated_at: 2013-11-07 23:33:42.347455000 Z
-  modified_at: 2013-11-07 23:33:42.347455000 Z
-  object_owner_uuid: zzzzz-j7d0g-xurymjxw79nv3jz
-
 stderr_for_ancient_container:
   id: 12
   uuid: zzzzz-57u5n-containerlog001
@@ -166,7 +71,7 @@ stderr_for_ancient_container:
   event_type: stderr
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer01 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 2.year.ago.to_fs(:db) %>
@@ -185,7 +90,7 @@ crunchstat_for_ancient_container:
   event_type: crunchstat
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer01 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 2.year.ago.to_fs(:db) %>
@@ -204,7 +109,7 @@ stderr_for_previous_container:
   event_type: stderr
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer02 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 1.month.ago.to_fs(:db) %>
@@ -223,7 +128,7 @@ crunchstat_for_previous_container:
   event_type: crunchstat
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer02 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 1.month.ago.to_fs(:db) %>
@@ -242,7 +147,7 @@ stderr_for_running_container:
   event_type: crunchstat
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer03 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 1.hour.ago.to_fs(:db) %>
@@ -261,7 +166,7 @@ crunchstat_for_running_container:
   event_type: crunchstat
   summary: ~
   properties:
-    text: '2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat:
+    text: '2013-11-07_23:33:41 zzzzz-dz642-logscontainer03 29610 1 stderr crunchstat:
       cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user
       0.9900 sys'
   created_at: <%= 1.hour.ago.to_fs(:db) %>
diff --git a/services/api/test/fixtures/nodes.yml b/services/api/test/fixtures/nodes.yml
deleted file mode 100644 (file)
index d4589ed..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-busy:
-  uuid: zzzzz-7ekkf-53y36l1lu5ijveb
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: compute0
-  slot_number: 0
-  domain: ""
-  ip_address: 172.17.2.172
-  last_ping_at: <%= 1.minute.ago.to_fs(:db) %>
-  first_ping_at: <%= 23.hour.ago.to_fs(:db) %>
-  job_uuid: zzzzz-8i9sb-2gx6rz0pjl033w3  # nearly_finished_job
-  properties: {}
-  info:
-    ping_secret: "48dpm3b8ijyj3jkr2yczxw0844dqd2752bhll7klodvgz9bg80"
-    slurm_state: "alloc"
-
-down:
-  uuid: zzzzz-7ekkf-2vbompg3ecc6e2s
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: compute1
-  slot_number: 1
-  domain: ""
-  ip_address: 172.17.2.173
-  last_ping_at: <%= 1.hour.ago.to_fs(:db) %>
-  first_ping_at: <%= 23.hour.ago.to_fs(:db) %>
-  job_uuid: ~
-  properties: {}
-  info:
-    ping_secret: "2k3i71depad36ugwmlgzilbi4e8n0illb2r8l4efg9mzkb3a1k"
-
-idle:
-  uuid: zzzzz-7ekkf-2z3mc76g2q73aio
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: compute2
-  slot_number: 2
-  domain: ""
-  ip_address: 172.17.2.174
-  last_ping_at: <%= 2.minute.ago.to_fs(:db) %>
-  first_ping_at: <%= 23.hour.ago.to_fs(:db) %>
-  job_uuid: ~
-  info:
-    ping_secret: "69udawxvn3zzj45hs8bumvndricrha4lcpi23pd69e44soanc0"
-    slurm_state: "idle"
-  properties:
-    total_cpu_cores: 16
-
-was_idle_now_down:
-  uuid: zzzzz-7ekkf-xuzpkdasl0uzwyz
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: compute3
-  slot_number: ~
-  domain: ""
-  ip_address: 172.17.2.174
-  last_ping_at: <%= 1.hour.ago.to_fs(:db) %>
-  first_ping_at: <%= 23.hour.ago.to_fs(:db) %>
-  job_uuid: ~
-  info:
-    ping_secret: "1bd1yi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2"
-    slurm_state: "idle"
-  properties:
-    total_cpu_cores: 16
-
-new_with_no_hostname:
-  uuid: zzzzz-7ekkf-newnohostname00
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: ~
-  slot_number: ~
-  ip_address: 172.17.2.175
-  last_ping_at: ~
-  first_ping_at: ~
-  job_uuid: ~
-  properties: {}
-  info:
-    ping_secret: "abcdyi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2"
-
-new_with_custom_hostname:
-  uuid: zzzzz-7ekkf-newwithhostname
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: custom1
-  slot_number: 23
-  ip_address: 172.17.2.176
-  last_ping_at: ~
-  first_ping_at: ~
-  job_uuid: ~
-  properties: {}
-  info:
-    ping_secret: "abcdyi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2"
-
-node_with_no_ip_address_yet:
-  uuid: zzzzz-7ekkf-nodenoipaddryet
-  owner_uuid: zzzzz-tpzed-000000000000000
-  hostname: noipaddr
-  slot_number: ~
-  last_ping_at: ~
-  first_ping_at: ~
-  job_uuid: ~
-  properties: {}
-  info:
-    ping_secret: "abcdyefg4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2"
diff --git a/services/api/test/fixtures/pipeline_instances.yml b/services/api/test/fixtures/pipeline_instances.yml
deleted file mode 100644 (file)
index 714fc60..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-new_pipeline:
-  state: New
-  uuid: zzzzz-d1hrv-f4gneyn6br1xize
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 1.minute.ago.to_fs(:db) %>
-
-new_pipeline_in_subproject:
-  state: New
-  uuid: zzzzz-d1hrv-subprojpipeline
-  owner_uuid: zzzzz-j7d0g-axqo7eu9pwvna1x
-  created_at: <%= 1.minute.ago.to_fs(:db) %>
-
-has_component_with_no_script_parameters:
-  state: Ready
-  uuid: zzzzz-d1hrv-1xfj6xkicf2muk2
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 10.minute.ago.to_fs(:db) %>
-  components:
-   foo:
-    script: foo
-    script_version: main
-    script_parameters: {}
-
-has_component_with_empty_script_parameters:
-  state: Ready
-  uuid: zzzzz-d1hrv-jq16l10gcsnyumo
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 3.minute.ago.to_fs(:db) %>
-  components:
-   foo:
-    script: foo
-    script_version: main
-
-has_component_with_completed_jobs:
-  # Test that the job "started_at" and "finished_at" fields are parsed
-  # into Time fields when rendering. These jobs must *not* have their
-  # own fixtures; the point is to force the
-  # pipeline_instances_controller_test in Workbench to parse the
-  # "components" field. (The relevant code paths are also used when a
-  # user has permission to read the pipeline instance itself, but not
-  # the jobs referenced by its components hash.)
-  state: Complete
-  uuid: zzzzz-d1hrv-i3e77t9z5y8j9cc
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 11.minute.ago.to_fs(:db) %>
-  started_at: <%= 10.minute.ago.to_fs(:db) %>
-  finished_at: <%= 9.minute.ago.to_fs(:db) %>
-  components:
-   foo:
-    script: foo
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-rft1xdewxkwgxnz
-      script_version: main
-      created_at: <%= 10.minute.ago.to_fs(:db) %>
-      started_at: <%= 10.minute.ago.to_fs(:db) %>
-      finished_at: <%= 9.minute.ago.to_fs(:db) %>
-      state: Complete
-      tasks_summary:
-        failed: 0
-        todo: 0
-        running: 0
-        done: 1
-   bar:
-    script: bar
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-r2dtbzr6bfread7
-      script_version: main
-      created_at: <%= 9.minute.ago.to_fs(:db) %>
-      started_at: <%= 9.minute.ago.to_fs(:db) %>
-      state: Running
-      tasks_summary:
-        failed: 0
-        todo: 1
-        running: 2
-        done: 3
-   baz:
-    script: baz
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-c7408rni11o7r6s
-      script_version: main
-      created_at: <%= 9.minute.ago.to_fs(:db) %>
-      state: Queued
-      tasks_summary: {}
-
-has_job:
-  name: pipeline_with_job
-  state: Ready
-  uuid: zzzzz-d1hrv-1yfj6xkidf2muk3
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 2.9.minute.ago.to_fs(:db) %>
-  components:
-   foo:
-    script: foo
-    script_version: main
-    script_parameters: {}
-    job: {
-            uuid: zzzzz-8i9sb-pshmckwoma9plh7,
-            script_version: main
-         }
-
-components_is_jobspec:
-  # Helps test that clients cope with funny-shaped components.
-  # For an example, see #3321.
-  uuid: zzzzz-d1hrv-1yfj61234abcdk4
-  created_at: <%= 4.minute.ago.to_fs(:db) %>
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  state: RunningOnServer
-  components:
-    script: foo
-    script_version: main
-    script_parameters:
-      input:
-        required: true
-        dataclass: Collection
-        title: "Foo/bar pair"
-        description: "Provide a collection containing at least two files."
-
-pipeline_with_tagged_collection_input:
-  name: pipeline_with_tagged_collection_input
-  state: Ready
-  uuid: zzzzz-d1hrv-1yfj61234abcdk3
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 3.2.minute.ago.to_fs(:db) %>
-  components:
-    part-one:
-      script_parameters:
-        input:
-          value: zzzzz-4zz18-znfnqtbbv4spc3w
-
-pipeline_to_merge_params:
-  name: pipeline_to_merge_params
-  state: Ready
-  uuid: zzzzz-d1hrv-1yfj6dcba4321k3
-  pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 3.3.minute.ago.to_fs(:db) %>
-  components:
-    part-one:
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: "Foo/bar pair"
-          description: "Provide a collection containing at least two files."
-    part-two:
-      script_parameters:
-        input:
-          output_of: part-one
-        integer_with_default:
-          default: 123
-        integer_with_value:
-          value: 123
-        string_with_default:
-          default: baz
-        string_with_value:
-          value: baz
-        plain_string: qux
-        array_with_default:
-          default: [1,1,2,3,5]
-        array_with_value:
-          value: [1,1,2,3,5]
-
-pipeline_with_newer_template:
-  state: Complete
-  uuid: zzzzz-d1hrv-9fm8l10i9z2kqc6
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  pipeline_template_uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r
-  created_at: 2014-09-15 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-
-pipeline_instance_owned_by_fuse:
-  state: Complete
-  uuid: zzzzz-d1hrv-ri9dvgkgqs9y09j
-  owner_uuid: zzzzz-tpzed-0fusedrivertest
-  pipeline_template_uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r
-  created_at: 2014-09-16 12:00:00
-  name: "pipeline instance owned by FUSE"
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-
-pipeline_instance_in_fuse_project:
-  state: Complete
-  uuid: zzzzz-d1hrv-scarxiyajtshq3l
-  owner_uuid: zzzzz-j7d0g-0000ownedbyfuse
-  pipeline_template_uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r
-  created_at: 2014-09-17 12:00:00
-  name: "pipeline instance in FUSE project"
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-
-pipeline_owned_by_active_in_aproject:
-  name: Completed pipeline in A Project
-  state: Complete
-  uuid: zzzzz-d1hrv-ju5ghi0i9z2kqc6
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-09-18 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-
-pipeline_owned_by_active_in_home:
-  name: Completed pipeline in active user home
-  state: Complete
-  uuid: zzzzz-d1hrv-lihrbd0i9z2kqc6
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-09-19 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-
-pipeline_in_publicly_accessible_project:
-  uuid: zzzzz-d1hrv-n68vc490mloy4fi
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  name: Pipeline in publicly accessible project
-  pipeline_template_uuid: zzzzz-p5p6p-tmpltpublicproj
-  state: Complete
-  created_at: <%= 30.minute.ago.to_fs(:db) %>
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-      job:
-        uuid: zzzzz-8i9sb-jyq01m7in1jlofj
-        repository: active/foo
-        script: foo
-        script_version: main
-        script_parameters:
-          input: zzzzz-4zz18-4en62shvi99lxd4
-        log: zzzzz-4zz18-4en62shvi99lxd4
-        output: b519d9cb706a29fc7ea24dbea2f05851+93
-        state: Complete
-
-pipeline_in_publicly_accessible_project_but_other_objects_elsewhere:
-  uuid: zzzzz-d1hrv-pisharednotobjs
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  name: Pipeline in public project with other objects elsewhere
-  pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw
-  state: Complete
-  created_at: 2014-09-20 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-      job:
-        uuid: zzzzz-8i9sb-aceg2bnq7jt7kon
-        repository: active/foo
-        script: foo
-        script_version: main
-        script_parameters:
-          input: zzzzz-4zz18-bv31uwvy3neko21
-        log: zzzzz-4zz18-bv31uwvy3neko21
-        output: zzzzz-4zz18-bv31uwvy3neko21
-        state: Complete
-
-new_pipeline_in_publicly_accessible_project:
-  uuid: zzzzz-d1hrv-newpisharedobjs
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  name: Pipeline in New state in publicly accessible project
-  pipeline_template_uuid: zzzzz-p5p6p-tmpltpublicproj
-  state: New
-  created_at: 2014-09-21 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          value: b519d9cb706a29fc7ea24dbea2f05851+93
-
-new_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere:
-  uuid: zzzzz-d1hrv-newsharenotobjs
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  name: Pipeline in New state in public project with objects elsewhere
-  pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw
-  state: New
-  created_at: 2014-09-22 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          value: zzzzz-4zz18-bv31uwvy3neko21
-
-new_pipeline_in_publicly_accessible_project_with_dataclass_file_and_other_objects_elsewhere:
-  uuid: zzzzz-d1hrv-newsharenotfile
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  name: Pipeline in public project in New state with file type data class with objects elsewhere
-  pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw
-  state: New
-  created_at: 2014-09-23 12:00:00
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: File
-          value: zzzzz-4zz18-bv31uwvy3neko21/bar
-
-pipeline_in_running_state:
-  name: running_with_job
-  uuid: zzzzz-d1hrv-runningpipeline
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 2.8.minute.ago.to_fs(:db) %>
-  started_at: <%= 2.8.minute.ago.to_fs(:db) %>
-  state: RunningOnServer
-  components:
-   foo:
-    script: foo
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-pshmckwoma9plh7
-      script_version: main
-
-running_pipeline_with_complete_job:
-  uuid: zzzzz-d1hrv-partdonepipelin
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  state: RunningOnServer
-  created_at: <%= 15.minute.ago.to_fs(:db) %>
-  components:
-   previous:
-    job:
-      uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-      log: zzzzz-4zz18-op4e2lbej01tcvu
-   running:
-    job:
-      uuid: zzzzz-8i9sb-pshmckwoma9plh7
-
-complete_pipeline_with_two_jobs:
-  uuid: zzzzz-d1hrv-twodonepipeline
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  state: Complete
-  created_at: <%= 2.5.minute.ago.to_fs(:db) %>
-  started_at: <%= 2.minute.ago.to_fs(:db) %>
-  finished_at: <%= 1.minute.ago.to_fs(:db) %>
-  components:
-   ancient:
-    job:
-      uuid: zzzzz-8i9sb-ahd7cie8jah9qui
-      log: zzzzz-4zz18-op4e2lbej01tcvu
-   previous:
-    job:
-      uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-      log: zzzzz-4zz18-op4e2lbej01tcvu
-
-failed_pipeline_with_two_jobs:
-  uuid: zzzzz-d1hrv-twofailpipeline
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 55.minute.ago.to_fs(:db) %>
-  state: Failed
-  components:
-   ancient:
-    job:
-      uuid: zzzzz-8i9sb-ahd7cie8jah9qui
-      log: zzzzz-4zz18-op4e2lbej01tcvu
-   previous:
-    job:
-      uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
-      log: zzzzz-4zz18-op4e2lbej01tcvu
-
-# This pipeline is a child of another running job and has it's own running children
-job_child_pipeline_with_components_at_level_2:
-  state: RunningOnServer
-  uuid: zzzzz-d1hrv-picomponentsl02
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: <%= 12.hour.ago.to_fs(:db) %>
-  started_at: <%= 12.hour.ago.to_fs(:db) %>
-  components:
-   foo:
-    script: foo
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-job1atlevel3noc
-      script_version: main
-      created_at: <%= 12.hour.ago.to_fs(:db) %>
-      started_at: <%= 12.hour.ago.to_fs(:db) %>
-      state: Running
-      tasks_summary:
-        failed: 0
-        todo: 0
-        running: 1
-        done: 1
-   bar:
-    script: bar
-    script_version: main
-    script_parameters: {}
-    job:
-      uuid: zzzzz-8i9sb-job2atlevel3noc
-      script_version: main
-      created_at: <%= 12.hour.ago.to_fs(:db) %>
-      started_at: <%= 12.hour.ago.to_fs(:db) %>
-      state: Running
-      tasks_summary:
-        failed: 0
-        todo: 1
-        running: 2
-        done: 3
-
-# Test Helper trims the rest of the file
-
-# Do not add your fixtures below this line as the rest of this file will be trimmed by test_helper
-
-# pipelines in project_with_10_pipelines
-<% for i in 1..10 do %>
-pipeline_<%=i%>_of_10:
-  name: pipeline_<%= i %>
-  uuid: zzzzz-d1hrv-10pipelines0<%= i.to_s.rjust(3, '0') %>
-  owner_uuid: zzzzz-j7d0g-000010pipelines
-  created_at: <%= (2*(i-1)).hour.ago.to_fs(:db) %>
-  started_at: <%= (2*(i-1)).hour.ago.to_fs(:db) %>
-  finished_at: <%= (i-1).minute.ago.to_fs(:db) %>
-  state: Failed
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-      job:
-        state: Failed
-<% end %>
-
-# pipelines in project_with_2_pipelines_and_60_crs
-<% for i in 1..2 do %>
-pipeline_<%=i%>_of_2_pipelines_and_60_crs:
-  name: pipeline_<%= i %>
-  state: New
-  uuid: zzzzz-d1hrv-abcgneyn6brx<%= i.to_s.rjust(3, '0') %>
-  owner_uuid: zzzzz-j7d0g-nnncrspipelines
-  created_at: <%= i.minute.ago.to_fs(:db) %>
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-<% end %>
-
-# pipelines in project_with_25_pipelines
-<% for i in 1..25 do %>
-pipeline_<%=i%>_of_25:
-  name: pipeline_<%=i%>
-  state: Failed
-  uuid: zzzzz-d1hrv-25pipelines0<%= i.to_s.rjust(3, '0') %>
-  owner_uuid: zzzzz-j7d0g-000025pipelines
-  created_at: <%= i.hour.ago.to_fs(:db) %>
-  started_at: <%= i.hour.ago.to_fs(:db) %>
-  finished_at: <%= i.minute.ago.to_fs(:db) %>
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo instance input
-<% end %>
-
-# Do not add your fixtures below this line as the rest of this file will be trimmed by test_helper
diff --git a/services/api/test/fixtures/pipeline_templates.yml b/services/api/test/fixtures/pipeline_templates.yml
deleted file mode 100644 (file)
index 0c185ee..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-two_part:
-  uuid: zzzzz-p5p6p-aox0k0ofxrystgw
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Two Part Pipeline Template
-  components:
-    part-one:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: "Foo/bar pair"
-    part-two:
-      script: bar
-      script_version: main
-      script_parameters:
-        input:
-          output_of: part-one
-        integer_with_default:
-          default: 123
-        integer_with_value:
-          value: 123
-        string_with_default:
-          default: baz
-        string_with_value:
-          value: baz
-        plain_string: qux
-        array_with_default: # important to test repeating values in the array!
-          default: [1,1,2,3,5]
-        array_with_value: # important to test repeating values in the array!
-          value: [1,1,2,3,5]
-
-components_is_jobspec:
-  # Helps test that clients cope with funny-shaped components.
-  # For an example, see #3321.
-  uuid: zzzzz-p5p6p-jobspeccomponts
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Pipeline Template with Jobspec Components
-  components:
-    script: foo
-    script_version: main
-    script_parameters:
-      input:
-        required: true
-        dataclass: Collection
-        title: "Foo/bar pair"
-        description: "Provide a collection containing at least two files."
-
-parameter_with_search:
-  uuid: zzzzz-p5p6p-paramwsearch345
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Pipeline Template with Input Parameter with Search
-  components:
-    with-search:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: "Foo/bar pair"
-          description: "Provide a collection containing at least two files."
-          search_for: sometime  # Matches baz_collection_in_asubproject
-
-new_pipeline_template:
-  # This template must include components that are not
-  # present in the pipeline instance 'pipeline_with_newer_template',
-  # at least one of which has a script_parameter that is a hash
-  # with a 'dataclass' field (ticket #4000)
-  uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-09-14 12:00:00
-  modified_at: 2014-09-16 12:00:00
-  name: Pipeline Template Newer Than Instance
-  components:
-    foo:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: foo template input
-    bar:
-      script: bar
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: bar template input
-
-pipeline_template_in_fuse_project:
-  uuid: zzzzz-p5p6p-templinfuseproj
-  owner_uuid: zzzzz-j7d0g-0000ownedbyfuse
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-0fusedrivertest
-  name: pipeline template in FUSE project
-  components:
-    foo_component:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: "default input"
-          description: "input collection"
-
-template_with_dataclass_file:
-  uuid: zzzzz-p5p6p-k0xoa0ofxrystgw
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Two Part Template with dataclass File
-  components:
-    part-one:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: File
-          title: "Foo/bar pair"
-          description: "Provide an input file"
-    part-two:
-      script: bar
-      script_version: main
-      script_parameters:
-        input:
-          output_of: part-one
-        integer_with_default:
-          default: 123
-        integer_with_value:
-          value: 123
-        string_with_default:
-          default: baz
-        string_with_value:
-          value: baz
-        plain_string: qux
-        array_with_default: # important to test repeating values in the array!
-          default: [1,1,2,3,5]
-        array_with_value: # important to test repeating values in the array!
-          value: [1,1,2,3,5]
-
-template_with_dataclass_number:
-  uuid: zzzzz-p5p6p-numbertemplatea
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2015-01-14 12:35:04 -0400
-  updated_at: 2015-01-14 12:35:04 -0400
-  modified_at: 2015-01-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Template with dataclass number
-  components:
-    work:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: number
-          title: "Input number"
-
-pipeline_template_in_publicly_accessible_project:
-  uuid: zzzzz-p5p6p-tmpltpublicproj
-  owner_uuid: zzzzz-j7d0g-zhxawtyetzwc5f0
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Pipeline template in publicly accessible project
-  components:
-    foo_component:
-      script: foo
-      script_version: main
-      script_parameters:
-        input:
-          required: true
-          dataclass: Collection
-          title: "default input"
-          description: "input collection"
-
-# Used to test renaming when removed from the "aproject" subproject
-# while another such object with same name exists in home project.
-template_in_active_user_home_project_to_test_unique_key_violation:
-  uuid: zzzzz-p5p6p-templatsamenam1
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2013-04-14 12:35:04 -0400
-  updated_at: 2013-04-14 12:35:04 -0400
-  modified_at: 2013-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Template to test owner uuid and name unique key violation upon removal
-  components:
-    script: foo
-    script_version: main
-    script_parameters:
-      input:
-        required: true
-        dataclass: Collection
-        title: "Foo/bar pair"
-        description: "Provide a collection containing at least two files."
-
-template_in_asubproject_with_same_name_as_one_in_active_user_home:
-  uuid: zzzzz-p5p6p-templatsamenam2
-  owner_uuid: zzzzz-j7d0g-axqo7eu9pwvna1x
-  created_at: 2013-04-14 12:35:04 -0400
-  updated_at: 2013-04-14 12:35:04 -0400
-  modified_at: 2013-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Template to test owner uuid and name unique key violation upon removal
-  components:
-    script: foo
-    script_version: main
-    script_parameters:
-      input:
-        required: true
-        dataclass: Collection
-        title: "Foo/bar pair"
-        description: "Provide a collection containing at least two files."
-
-workflow_with_input_defaults:
-  uuid: zzzzz-p5p6p-aox0k0ofxrystg2
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-04-14 12:35:04 -0400
-  updated_at: 2014-04-14 12:35:04 -0400
-  modified_at: 2014-04-14 12:35:04 -0400
-  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
-  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  name: Pipeline with default input specifications
-  components:
-    part-one:
-      script: foo
-      script_version: main
-      script_parameters:
-        ex_string:
-          required: true
-          dataclass: string
-        ex_string_def:
-          required: true
-          dataclass: string
-          default: hello-testing-123
diff --git a/services/api/test/fixtures/repositories.yml b/services/api/test/fixtures/repositories.yml
deleted file mode 100644 (file)
index e4fe71e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-crunch_dispatch_test:
-  uuid: zzzzz-s0uqq-382brsig8rp3665
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
-  name: active/crunchdispatchtest
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-arvados:
-  uuid: zzzzz-s0uqq-arvadosrepo0123
-  owner_uuid: zzzzz-tpzed-000000000000000 # root
-  name: arvados
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-foo:
-  uuid: zzzzz-s0uqq-382brsig8rp3666
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
-  name: active/foo
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-repository2:
-  uuid: zzzzz-s0uqq-382brsig8rp3667
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
-  name: active/foo2
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-repository3:
-  uuid: zzzzz-s0uqq-38orljkqpyo1j61
-  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
-  name: admin/foo3
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-repository4:
-  uuid: zzzzz-s0uqq-38oru8hnk57ht34
-  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
-  name: admin/foo4
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
-
-has_branch_with_commit_hash_name:
-  uuid: zzzzz-s0uqq-382brsig8rp3668
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
-  name: active/shabranchnames
-  created_at: 2015-01-01T00:00:00.123456Z
-  modified_at: 2015-01-01T00:00:00.123456Z
diff --git a/services/api/test/fixtures/specimens.yml b/services/api/test/fixtures/specimens.yml
deleted file mode 100644 (file)
index bcae020..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-owned_by_active_user:
-  uuid: zzzzz-j58dm-3zx463qyo0k4xrn
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  created_at: 2014-04-21 15:37:48 -0400
-  modified_at: 2014-04-21 15:37:48 -0400
-
-owned_by_private_group:
-  uuid: zzzzz-j58dm-5m3qwg45g3nlpu6
-  owner_uuid: zzzzz-j7d0g-rew6elm53kancon
-  created_at: 2014-04-21 15:37:48 -0400
-  modified_at: 2014-04-21 15:37:48 -0400
-
-owned_by_spectator:
-  uuid: zzzzz-j58dm-3b0xxwzlbzxq5yr
-  owner_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
-  created_at: 2014-04-21 15:37:48 -0400
-  modified_at: 2014-04-21 15:37:48 -0400
-
-in_aproject:
-  uuid: zzzzz-j58dm-7r18rnd5nzhg5yk
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-04-21 15:37:48 -0400
-  modified_at: 2014-04-21 15:37:48 -0400
-
-in_asubproject:
-  uuid: zzzzz-j58dm-c40lddwcqqr1ffs
-  owner_uuid: zzzzz-j7d0g-axqo7eu9pwvna1x
-  created_at: 2014-04-21 15:37:48 -0400
-  modified_at: 2014-04-21 15:37:48 -0400
diff --git a/services/api/test/fixtures/traits.yml b/services/api/test/fixtures/traits.yml
deleted file mode 100644 (file)
index 83beb70..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-owned_by_aproject_with_no_name:
-  uuid: zzzzz-q1cn2-ypsjlol9dofwijz
-  owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso
-  created_at: 2014-05-05 04:11:52 -0400
-  modified_at: 2014-05-05 04:11:52 -0400
index af7882141e31973c7e28d0f42da16abb088ed88c..2a64e9c5e25fb7a3ee6125a225726221a8af8a34 100644 (file)
@@ -13,8 +13,8 @@ class ApplicationControllerTest < ActionController::TestCase
 
   setup do
     # These tests are meant to check behavior in ApplicationController.
-    # We instantiate a small concrete controller for convenience.
-    @controller = Arvados::V1::SpecimensController.new
+    # We instantiate an arbitrary concrete controller.
+    @controller = Arvados::V1::CollectionsController.new
     @start_stamp = now_timestamp
   end
 
@@ -42,13 +42,13 @@ class ApplicationControllerTest < ActionController::TestCase
 
   test "requesting object without read permission returns 404 error" do
     authorize_with :spectator
-    get(:show, params: {id: specimens(:owned_by_active_user).uuid})
+    get(:show, params: {id: collections(:collection_owned_by_active).uuid})
     check_404
   end
 
   test "submitting bad object returns error" do
     authorize_with :spectator
-    post(:create, params: {specimen: {badattr: "badvalue"}})
+    post(:create, params: {collection: {badattr: "badvalue"}})
     assert_response 422
     check_error_token
   end
index 43797035bce8c1531717006245b62ea2e89af9d8..3f65b934f5102f2c6641fd7c048989ece9dc1a12 100644 (file)
@@ -516,14 +516,10 @@ EOS
 
   test "get full provenance for baz file" do
     authorize_with :active
-    get :provenance, params: {id: 'ea10d51bcf88862dbcc36eb292017dfd+45'}
+    get :provenance, params: {id: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'}
     assert_response :success
     resp = JSON.parse(@response.body)
-    assert_not_nil resp['ea10d51bcf88862dbcc36eb292017dfd+45'] # baz
-    assert_not_nil resp['fa7aeb5140e2848d39b416daeef4ffc5+45'] # bar
-    assert_not_nil resp['1f4b0bc7583c2a7f9102c395f4ffc5e3+45'] # foo
-    assert_not_nil resp['zzzzz-8i9sb-cjs4pklxxjykyuq'] # bar->baz
-    assert_not_nil resp['zzzzz-8i9sb-aceg2bnq7jt7kon'] # foo->bar
+    assert_not_nil resp['1f4b0bc7583c2a7f9102c395f4ffc5e3+45'] # baz collection
   end
 
   test "get no provenance for foo file" do
@@ -540,10 +536,7 @@ EOS
     assert_response :success
     resp = JSON.parse(@response.body)
     assert_not_nil resp['ea10d51bcf88862dbcc36eb292017dfd+45'] # baz
-    assert_not_nil resp['fa7aeb5140e2848d39b416daeef4ffc5+45'] # bar
-    assert_not_nil resp['zzzzz-8i9sb-cjs4pklxxjykyuq']     # bar->baz
-    assert_nil resp['zzzzz-8i9sb-aceg2bnq7jt7kon']         # foo->bar
-    assert_nil resp['1f4b0bc7583c2a7f9102c395f4ffc5e3+45'] # foo
+    assert_nil resp['fa7aeb5140e2848d39b416daeef4ffc5+45'] # foo->bar
   end
 
   test "search collections with 'any' operator" do
diff --git a/services/api/test/functional/arvados/v1/commits_controller_test.rb b/services/api/test/functional/arvados/v1/commits_controller_test.rb
deleted file mode 100644 (file)
index bf285b0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::CommitsControllerTest < ActionController::TestCase
-end
index ee7f716c806ba77c7f449c5f970b16051cf56661..6e167bb91ea9fb19e579c332edfb2597e0560981 100644 (file)
@@ -65,12 +65,12 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     assert_equal 0, json_response['items_available']
   end
 
-  def check_project_contents_response disabled_kinds=[]
+  def check_project_contents_response
     assert_response :success
     assert_operator 2, :<=, json_response['items_available']
     assert_operator 2, :<=, json_response['items'].count
     kinds = json_response['items'].collect { |i| i['kind'] }.uniq
-    expect_kinds = %w'arvados#group arvados#specimen arvados#pipelineTemplate arvados#job' - disabled_kinds
+    expect_kinds = %w'arvados#group'
     assert_equal expect_kinds, (expect_kinds & kinds)
 
     json_response['items'].each do |i|
@@ -79,10 +79,6 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
                "group#contents returned a non-project group")
       end
     end
-
-    disabled_kinds.each do |d|
-      assert_equal true, !kinds.include?(d)
-    end
   end
 
   test 'get group-owned objects' do
@@ -107,17 +103,17 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     authorize_with :project_viewer
     get :contents, params: {
       format: :json,
-      filters: [['uuid', 'is_a', 'arvados#specimen']]
+      filters: [['uuid', 'is_a', 'arvados#collection']]
     }
     assert_response :success
     found_uuids = json_response['items'].collect { |i| i['uuid'] }
-    [[:in_aproject, true],
-     [:in_asubproject, true],
-     [:owned_by_private_group, false]].each do |specimen_fixture, should_find|
+    [[:foo_collection_in_aproject, true],
+     [:baz_collection_name_in_asubproject, true],
+     [:collection_not_readable_by_active, false]].each do |collection_fixture, should_find|
       if should_find
-        assert_includes found_uuids, specimens(specimen_fixture).uuid, "did not find specimen fixture '#{specimen_fixture}'"
+        assert_includes found_uuids, collections(collection_fixture).uuid, "did not find collection fixture '#{collection_fixture}'"
       else
-        refute_includes found_uuids, specimens(specimen_fixture).uuid, "found specimen fixture '#{specimen_fixture}'"
+        refute_includes found_uuids, collections(collection_fixture).uuid, "found collection fixture '#{collection_fixture}'"
       end
     end
   end
@@ -150,8 +146,8 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     }
     assert_response :success
     found_uuids = json_response['items'].collect { |i| i['uuid'] }
-    assert_includes found_uuids, specimens(:owned_by_active_user).uuid, "specimen did not appear in home project"
-    refute_includes found_uuids, specimens(:in_asubproject).uuid, "specimen appeared unexpectedly in home project"
+    assert_includes found_uuids, collections(:collection_owned_by_active).uuid, "collection did not appear in home project"
+    refute_includes found_uuids, collections(:foo_collection_in_aproject).uuid, "collection appeared unexpectedly in home project"
   end
 
   test "list collections in home project" do
@@ -279,20 +275,20 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
 
   test "user with project read permission can't rename items in it" do
     authorize_with :project_viewer
-    @controller = Arvados::V1::LinksController.new
+    @controller = Arvados::V1::CollectionsController.new
     post :update, params: {
-      id: jobs(:running).uuid,
+      id: collections(:collection_to_search_for_in_aproject).uuid,
       name: "Denied test name",
     }
     assert_includes(403..404, response.status)
   end
 
   test "user with project read permission can't remove items from it" do
-    @controller = Arvados::V1::PipelineTemplatesController.new
+    @controller = Arvados::V1::CollectionsController.new
     authorize_with :project_viewer
     post :update, params: {
-      id: pipeline_templates(:two_part).uuid,
-      pipeline_template: {
+      id: collections(:collection_to_search_for_in_aproject).uuid,
+      collection: {
         owner_uuid: users(:project_viewer).uuid,
       }
     }
@@ -339,8 +335,8 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
       select: ["uuid", "storage_classes_desired"]
     }
     assert_response :success
-    assert_equal 17, json_response['items_available']
-    assert_equal 17, json_response['items'].count
+    assert_equal 6, json_response['items_available']
+    assert_equal 6, json_response['items'].count
     json_response['items'].each do |item|
       # Expect collections to have a storage_classes field, other items should not.
       if item["kind"] == "arvados#collection"
@@ -480,9 +476,9 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
 
   [
     [['owner_uuid', '!=', 'zzzzz-tpzed-xurymjxw79nv3jz'], 200,
-        'zzzzz-d1hrv-subprojpipeline', 'zzzzz-d1hrv-1xfj6xkicf2muk2'],
-    [["pipeline_instances.state", "not in", ["Complete", "Failed"]], 200,
-        'zzzzz-d1hrv-1xfj6xkicf2muk2', 'zzzzz-d1hrv-i3e77t9z5y8j9cc'],
+        'zzzzz-j7d0g-publicfavorites', 'zzzzz-xvhdp-cr4queuedcontnr'],
+    [["container_requests.state", "not in", ["Final"]], 200,
+        'zzzzz-xvhdp-cr4queuedcontnr', 'zzzzz-xvhdp-cr4completedctr'],
     [['container_requests.requesting_container_uuid', '=', nil], 200,
         'zzzzz-xvhdp-cr4queuedcontnr', 'zzzzz-xvhdp-cr4requestercn2'],
     [['container_requests.no_such_column', '=', nil], 422],
@@ -503,25 +499,17 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     end
   end
 
-  test 'get contents with jobs and pipeline instances disabled' do
-    Rails.configuration.API.DisabledAPIs = ConfigLoader.to_OrderedOptions(
-      {'jobs.index'=>{}, 'pipeline_instances.index'=>{}})
-
-    authorize_with :active
-    get :contents, params: {
-      id: groups(:aproject).uuid,
-      format: :json,
-    }
-    check_project_contents_response %w'arvados#pipelineInstance arvados#job'
-  end
-
   test 'get contents with low max_index_database_read' do
     # Some result will certainly have at least 12 bytes in a
-    # restricted column
+    # restricted column.
+    #
+    # We cannot use collections.manifest_text to test this, because
+    # GroupsController refuses to select manifest_text, because
+    # controller doesn't sign manifests in a groups#contents response.
     Rails.configuration.API.MaxIndexDatabaseRead = 12
     authorize_with :active
     get :contents, params: {
-          id: groups(:aproject).uuid,
+          uuid: users(:active).uuid,
           format: :json,
         }
     assert_response :success
diff --git a/services/api/test/functional/arvados/v1/humans_controller_test.rb b/services/api/test/functional/arvados/v1/humans_controller_test.rb
deleted file mode 100644 (file)
index d73fb30..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::HumansControllerTest < ActionController::TestCase
-end
diff --git a/services/api/test/functional/arvados/v1/job_reuse_controller_test.rb b/services/api/test/functional/arvados/v1/job_reuse_controller_test.rb
deleted file mode 100644 (file)
index 46cfac5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-require 'helpers/git_test_helper'
-
-class Arvados::V1::JobReuseControllerTest < ActionController::TestCase
-  fixtures :repositories, :users, :jobs, :links, :collections
-
-  setup do
-    @controller = Arvados::V1::JobsController.new
-    authorize_with :active
-  end
-
-  BASE_FILTERS = {
-    'repository' => ['=', 'active/foo'],
-    'script' => ['=', 'hash'],
-    'script_version' => ['in git', 'main'],
-    'docker_image_locator' => ['=', nil],
-    'arvados_sdk_version' => ['=', nil],
-  }
-
-  def filters_from_hash(hash)
-    hash.each_pair.map { |name, filter| [name] + filter }
-  end
-
-  test "find Job with script version range" do
-    get :index, params: {
-      filters: [["repository", "=", "active/foo"],
-                ["script", "=", "hash"],
-                ["script_version", "in git", "tag1"]]
-    }
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    assert_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-  end
-
-  test "find Job with script version range exclusions" do
-    get :index, params: {
-      filters: [["repository", "=", "active/foo"],
-                ["script", "=", "hash"],
-                ["script_version", "not in git", "tag1"]]
-    }
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    refute_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-  end
-
-  test "find Job with Docker image range" do
-    get :index, params: {
-      filters: [["docker_image_locator", "in docker",
-                 "arvados/apitestfixture"]]
-    }
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    assert_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_docker_job_run).uuid)
-    refute_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-  end
-
-  test "find Job with Docker image using reader tokens" do
-    authorize_with :inactive
-    get(:index, params: {
-          filters: [["docker_image_locator", "in docker",
-                     "arvados/apitestfixture"]],
-          reader_tokens: [api_token(:active)],
-        })
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    assert_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_docker_job_run).uuid)
-    refute_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-  end
-
-  test "'in docker' filter accepts arrays" do
-    get :index, params: {
-      filters: [["docker_image_locator", "in docker",
-                ["_nonesuchname_", "arvados/apitestfixture"]]]
-    }
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    assert_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_docker_job_run).uuid)
-    refute_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-  end
-
-  test "'not in docker' filter accepts arrays" do
-    get :index, params: {
-      filters: [["docker_image_locator", "not in docker",
-                ["_nonesuchname_", "arvados/apitestfixture"]]]
-    }
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    assert_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_job_run).uuid)
-    refute_includes(assigns(:objects).map { |job| job.uuid },
-                    jobs(:previous_docker_job_run).uuid)
-  end
-
-end
diff --git a/services/api/test/functional/arvados/v1/job_tasks_controller_test.rb b/services/api/test/functional/arvados/v1/job_tasks_controller_test.rb
deleted file mode 100644 (file)
index d6f4347..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::JobTasksControllerTest < ActionController::TestCase
-end
diff --git a/services/api/test/functional/arvados/v1/jobs_controller_test.rb b/services/api/test/functional/arvados/v1/jobs_controller_test.rb
deleted file mode 100644 (file)
index 9298f23..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-require 'helpers/git_test_helper'
-
-class Arvados::V1::JobsControllerTest < ActionController::TestCase
-
-  test "search jobs by uuid with >= query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', '>=', 'zzzzz-8i9sb-pshmckwoma9plh7']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-    assert_equal false, !!found.index('zzzzz-8i9sb-4cf0nhn6xte809j')
-  end
-
-  test "search jobs by uuid with <= query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', '<=', 'zzzzz-8i9sb-pshmckwoma9plh7']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-    assert_equal true, !!found.index('zzzzz-8i9sb-4cf0nhn6xte809j')
-  end
-
-  test "search jobs by uuid with >= and <= query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', '>=', 'zzzzz-8i9sb-pshmckwoma9plh7'],
-              ['uuid', '<=', 'zzzzz-8i9sb-pshmckwoma9plh7']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal found, ['zzzzz-8i9sb-pshmckwoma9plh7']
-  end
-
-  test "search jobs by uuid with < query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', '<', 'zzzzz-8i9sb-pshmckwoma9plh7']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal false, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-    assert_equal true, !!found.index('zzzzz-8i9sb-4cf0nhn6xte809j')
-  end
-
-  test "search jobs by uuid with like query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', 'like', '%hmckwoma9pl%']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal found, ['zzzzz-8i9sb-pshmckwoma9plh7']
-  end
-
-  test "search jobs by uuid with 'in' query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', 'in', ['zzzzz-8i9sb-4cf0nhn6xte809j',
-                                'zzzzz-8i9sb-pshmckwoma9plh7']]]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal found.sort, ['zzzzz-8i9sb-4cf0nhn6xte809j',
-                              'zzzzz-8i9sb-pshmckwoma9plh7']
-  end
-
-  test "search jobs by uuid with 'not in' query" do
-    exclude_uuids = [jobs(:running).uuid,
-                     jobs(:running_cancelled).uuid]
-    authorize_with :active
-    get :index, params: {
-      filters: [['uuid', 'not in', exclude_uuids]]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_not_empty found, "'not in' query returned nothing"
-    assert_empty(found & exclude_uuids,
-                 "'not in' query returned uuids I asked not to get")
-  end
-
-  ['=', '!='].each do |operator|
-    [['uuid', 'zzzzz-8i9sb-pshmckwoma9plh7'],
-     ['output', nil]].each do |attr, operand|
-      test "search jobs with #{attr} #{operator} #{operand.inspect} query" do
-        authorize_with :active
-        get :index, params: {
-          filters: [[attr, operator, operand]]
-        }
-        assert_response :success
-        values = assigns(:objects).collect { |x| x.send(attr) }
-        assert_not_empty values, "query should return non-empty result"
-        if operator == '='
-          assert_empty values - [operand], "query results do not satisfy query"
-        else
-          assert_empty values & [operand], "query results do not satisfy query"
-        end
-      end
-    end
-  end
-
-  test "search jobs by started_at with < query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['started_at', '<', Time.now.to_s]]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-  end
-
-  test "search jobs by started_at with > query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['started_at', '>', Time.now.to_s]]
-    }
-    assert_response :success
-    assert_equal 0, assigns(:objects).count
-  end
-
-  test "search jobs by started_at with >= query on metric date" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['started_at', '>=', '2014-01-01']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-  end
-
-  test "search jobs by started_at with >= query on metric date and time" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['started_at', '>=', '2014-01-01 01:23:45']]
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-  end
-
-  test "search jobs with 'any' operator" do
-    authorize_with :active
-    get :index, params: {
-      where: { any: ['contains', 'pshmckw'] }
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal 0, found.index('zzzzz-8i9sb-pshmckwoma9plh7')
-    assert_equal 1, found.count
-  end
-
-  test "search jobs by nonexistent column with < query" do
-    authorize_with :active
-    get :index, params: {
-      filters: [['is_borked', '<', 'fizzbuzz']]
-    }
-    assert_response 422
-  end
-
-  [:spectator, :admin].each_with_index do |which_token, i|
-    test "get job queue as #{which_token} user" do
-      authorize_with which_token
-      get :queue
-      assert_response :success
-      assert_equal 0, assigns(:objects).count
-    end
-  end
-
-  test "job includes assigned nodes" do
-    authorize_with :active
-    get :show, params: {id: jobs(:nearly_finished_job).uuid}
-    assert_response :success
-    assert_equal([nodes(:busy).uuid], json_response["node_uuids"])
-  end
-
-  test 'get job with components' do
-    authorize_with :active
-    get :show, params: {id: jobs(:running_job_with_components).uuid}
-    assert_response :success
-    assert_not_nil json_response["components"]
-    assert_equal ["component1", "component2"], json_response["components"].keys
-  end
-end
diff --git a/services/api/test/functional/arvados/v1/keep_disks_controller_test.rb b/services/api/test/functional/arvados/v1/keep_disks_controller_test.rb
deleted file mode 100644 (file)
index 9da9d01..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
-
-  def default_ping_opts
-    {ping_secret: '', service_ssl_flag: false, service_port: 1234}
-  end
-
-  test "add keep disk with admin token" do
-    authorize_with :admin
-    post :ping, params: default_ping_opts.
-      merge(filesystem_uuid: 'eb1e77a1-db84-4193-b6e6-ca2894f67d5f')
-    assert_response :success
-    assert_not_nil assigns(:object)
-    new_keep_disk = JSON.parse(@response.body)
-    assert_not_nil new_keep_disk['uuid']
-    assert_not_nil new_keep_disk['ping_secret']
-    assert_not_equal '', new_keep_disk['ping_secret']
-  end
-
-  [
-    {},
-    {filesystem_uuid: ''},
-  ].each do |opts|
-    test "add keep disk with[out] filesystem_uuid #{opts}" do
-      authorize_with :admin
-      post :ping, params: default_ping_opts.merge(opts)
-      assert_response :success
-      assert_not_nil JSON.parse(@response.body)['uuid']
-    end
-  end
-
-  test "refuse to add keep disk without admin token" do
-    post :ping, params: default_ping_opts
-    assert_response 404
-  end
-
-  test "ping keep disk" do
-    post :ping, params: default_ping_opts.
-      merge(id: keep_disks(:nonfull).uuid,
-            ping_secret: keep_disks(:nonfull).ping_secret,
-            filesystem_uuid: keep_disks(:nonfull).filesystem_uuid)
-    assert_response :success
-    assert_not_nil assigns(:object)
-    keep_disk = JSON.parse(@response.body)
-    assert_not_nil keep_disk['uuid']
-    assert_not_nil keep_disk['ping_secret']
-  end
-
-  test "admin should get index with ping_secret" do
-    authorize_with :admin
-    get :index
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    items = JSON.parse(@response.body)['items']
-    assert_not_equal 0, items.size
-    assert_not_nil items[0]['ping_secret']
-  end
-
-  # inactive user sees keep disks
-  test "inactive user should get index" do
-    authorize_with :inactive
-    get :index
-    assert_response :success
-    items = JSON.parse(@response.body)['items']
-    assert_not_equal 0, items.size
-
-    # Check these are still included
-    assert items[0]['service_host']
-    assert items[0]['service_port']
-  end
-
-  # active user sees non-secret attributes of keep disks
-  test "active user should get non-empty index with no ping_secret" do
-    authorize_with :active
-    get :index
-    assert_response :success
-    items = JSON.parse(@response.body)['items']
-    assert_not_equal 0, items.size
-    items.each do |item|
-      assert_nil item['ping_secret']
-      assert_not_nil item['is_readable']
-      assert_not_nil item['is_writable']
-      assert_not_nil item['service_host']
-      assert_not_nil item['service_port']
-    end
-  end
-
-  test "search keep_services with 'any' operator" do
-    authorize_with :active
-    get :index, params: {
-      where: { any: ['contains', 'o2t1q5w'] }
-    }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal true, !!found.index('zzzzz-penuu-5w2o2t1q5wy7fhn')
-  end
-end
diff --git a/services/api/test/functional/arvados/v1/nodes_controller_test.rb b/services/api/test/functional/arvados/v1/nodes_controller_test.rb
deleted file mode 100644 (file)
index 47f6c5f..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::NodesControllerTest < ActionController::TestCase
-
-  test "should get index with ping_secret" do
-    authorize_with :admin
-    get :index
-    assert_response :success
-    assert_not_nil assigns(:objects)
-    node_items = JSON.parse(@response.body)['items']
-    assert_not_equal 0, node_items.size
-    assert_not_nil node_items[0]['info'].andand['ping_secret']
-  end
-
-  # inactive user does not see any nodes
-  test "inactive user should get empty index" do
-    authorize_with :inactive
-    get :index
-    assert_response :success
-    assert_equal 0, json_response['items'].size
-    assert_equal 0, json_response['items_available']
-  end
-
-  # active user sees non-secret attributes of up and recently-up nodes
-  test "active user should get non-empty index with no ping_secret" do
-    authorize_with :active
-    get :index
-    assert_response :success
-    assert_operator 0, :<, json_response['items_available']
-    node_items = json_response['items']
-    assert_operator 0, :<, node_items.size
-    found_busy_node = false
-    node_items.each do |node|
-      assert_nil node['info'].andand['ping_secret']
-      assert_not_nil node['crunch_worker_state']
-      if node['uuid'] == nodes(:busy).uuid
-        found_busy_node = true
-        assert_equal 'busy', node['crunch_worker_state']
-      end
-    end
-    assert_equal true, found_busy_node
-  end
-
-  test "node should ping with ping_secret and no token" do
-    post :ping, params: {
-      id: 'zzzzz-7ekkf-2z3mc76g2q73aio',
-      instance_id: 'i-0000000',
-      local_ipv4: '172.17.2.174',
-      ping_secret: '69udawxvn3zzj45hs8bumvndricrha4lcpi23pd69e44soanc0'
-    }
-    assert_response :success
-    response = JSON.parse(@response.body)
-    assert_equal 'zzzzz-7ekkf-2z3mc76g2q73aio', response['uuid']
-    # Ensure we are getting the "superuser" attributes, too
-    assert_not_nil response['first_ping_at'], '"first_ping_at" attr missing'
-    assert_not_nil response['info'], '"info" attr missing'
-    assert_not_nil response['nameservers'], '"nameservers" attr missing'
-  end
-
-  test "node should fail ping with invalid ping_secret" do
-    post :ping, params: {
-      id: 'zzzzz-7ekkf-2z3mc76g2q73aio',
-      instance_id: 'i-0000000',
-      local_ipv4: '172.17.2.174',
-      ping_secret: 'dricrha4lcpi23pd69e44soanc069udawxvn3zzj45hs8bumvn'
-    }
-    assert_response 401
-  end
-
-  test "create node" do
-    authorize_with :admin
-    post :create, params: {node: {}}
-    assert_response :success
-    assert_not_nil json_response['uuid']
-    assert_not_nil json_response['info'].is_a? Hash
-    assert_not_nil json_response['info']['ping_secret']
-    assert_nil json_response['slot_number']
-    assert_nil json_response['hostname']
-  end
-
-  test "create node and assign slot" do
-    authorize_with :admin
-    post :create, params: {node: {}, assign_slot: true}
-    assert_response :success
-    assert_not_nil json_response['uuid']
-    assert_not_nil json_response['info'].is_a? Hash
-    assert_not_nil json_response['info']['ping_secret']
-    assert_operator 0, :<, json_response['slot_number']
-    n = json_response['slot_number']
-    assert_equal "compute#{n}", json_response['hostname']
-
-    node = Node.where(uuid: json_response['uuid']).first
-    assert_equal n, node.slot_number
-    assert_equal "compute#{n}", node.hostname
-  end
-
-  test "update node and assign slot" do
-    authorize_with :admin
-    node = nodes(:new_with_no_hostname)
-    post :update, params: {id: node.uuid, node: {}, assign_slot: true}
-    assert_response :success
-    assert_operator 0, :<, json_response['slot_number']
-    n = json_response['slot_number']
-    assert_equal "compute#{n}", json_response['hostname']
-
-    node.reload
-    assert_equal n, node.slot_number
-    assert_equal "compute#{n}", node.hostname
-  end
-
-  test "update node and assign slot, don't clobber hostname" do
-    authorize_with :admin
-    node = nodes(:new_with_custom_hostname)
-    post :update, params: {id: node.uuid, node: {}, assign_slot: true}
-    assert_response :success
-    assert_operator 0, :<, json_response['slot_number']
-    n = json_response['slot_number']
-    assert_equal "custom1", json_response['hostname']
-  end
-
-  test "ping adds node stats to info" do
-    authorize_with :admin
-    node = nodes(:idle)
-    post :ping, params: {
-      id: node.uuid,
-      ping_secret: node.info['ping_secret'],
-      total_cpu_cores: 32,
-      total_ram_mb: 1024,
-      total_scratch_mb: 2048
-    }
-    assert_response :success
-    info = JSON.parse(@response.body)['info']
-    properties = JSON.parse(@response.body)['properties']
-    assert_equal(node.info['ping_secret'], info['ping_secret'])
-    assert_equal(32, properties['total_cpu_cores'].to_i)
-    assert_equal(1024, properties['total_ram_mb'].to_i)
-    assert_equal(2048, properties['total_scratch_mb'].to_i)
-  end
-
-  test "active user can see their assigned job" do
-    authorize_with :active
-    get :show, params: {id: nodes(:busy).uuid}
-    assert_response :success
-    assert_equal(jobs(:nearly_finished_job).uuid, json_response["job_uuid"])
-  end
-
-  test "user without job read permission can't see job" do
-    authorize_with :spectator
-    get :show, params: {id: nodes(:busy).uuid}
-    assert_response :success
-    assert_nil(json_response["job"], "spectator can see node's assigned job")
-  end
-
-  [:admin, :spectator].each do |user|
-    test "select param does not break node list for #{user}" do
-      authorize_with user
-      get :index, params: {select: ['domain']}
-      assert_response :success
-      assert_operator 0, :<, json_response['items_available']
-    end
-  end
-
-  test "admin can associate a job with a node" do
-    changed_node = nodes(:idle)
-    assigned_job = jobs(:queued)
-    authorize_with :admin
-    post :update, params: {
-      id: changed_node.uuid,
-      node: {job_uuid: assigned_job.uuid},
-    }
-    assert_response :success
-    assert_equal(changed_node.hostname, json_response["hostname"],
-                 "hostname mismatch after defining job")
-    assert_equal(assigned_job.uuid, json_response["job_uuid"],
-                 "mismatch in node's assigned job UUID")
-  end
-
-  test "non-admin can't associate a job with a node" do
-    authorize_with :active
-    post :update, params: {
-      id: nodes(:idle).uuid,
-      node: {job_uuid: jobs(:queued).uuid},
-    }
-    assert_response 403
-  end
-
-  test "admin can unassign a job from a node" do
-    changed_node = nodes(:busy)
-    authorize_with :admin
-    post :update, params: {
-      id: changed_node.uuid,
-      node: {job_uuid: nil},
-    }
-    assert_response :success
-    assert_equal(changed_node.hostname, json_response["hostname"],
-                 "hostname mismatch after defining job")
-    assert_nil(json_response["job_uuid"],
-               "node still has job assignment after update")
-  end
-
-  test "non-admin can't unassign a job from a node" do
-    authorize_with :project_viewer
-    post :update, params: {
-      id: nodes(:busy).uuid,
-      node: {job_uuid: nil},
-    }
-    assert_response 403
-  end
-
-  test "node should fail ping with invalid hostname config format" do
-    Rails.configuration.Containers.SLURM.Managed.AssignNodeHostname = 'compute%<slot_number>04'  # should end with "04d"
-    post :ping, params: {
-      id: nodes(:new_with_no_hostname).uuid,
-      ping_secret: nodes(:new_with_no_hostname).info['ping_secret'],
-    }
-    assert_response 422
-  end
-
-  test "first ping should set ip addr using local_ipv4 when provided" do
-    post :ping, params: {
-      id: 'zzzzz-7ekkf-nodenoipaddryet',
-      instance_id: 'i-0000000',
-      local_ipv4: '172.17.2.172',
-      ping_secret: 'abcdyefg4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2'
-    }
-    assert_response :success
-    response = JSON.parse(@response.body)
-    assert_equal 'zzzzz-7ekkf-nodenoipaddryet', response['uuid']
-    assert_equal '172.17.2.172', response['ip_address']
-  end
-
-  test "first ping should set ip addr using remote_ip when local_ipv4 is not provided" do
-    post :ping, params: {
-      id: 'zzzzz-7ekkf-nodenoipaddryet',
-      instance_id: 'i-0000000',
-      ping_secret: 'abcdyefg4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2'
-    }
-    assert_response :success
-    response = JSON.parse(@response.body)
-    assert_equal 'zzzzz-7ekkf-nodenoipaddryet', response['uuid']
-    assert_equal request.remote_ip, response['ip_address']
-  end
-
-  test "future pings should not change previous ip address" do
-    post :ping, params: {
-      id: 'zzzzz-7ekkf-2z3mc76g2q73aio',
-      instance_id: 'i-0000000',
-      local_ipv4: '172.17.2.175',
-      ping_secret: '69udawxvn3zzj45hs8bumvndricrha4lcpi23pd69e44soanc0'
-    }
-    assert_response :success
-    response = JSON.parse(@response.body)
-    assert_equal 'zzzzz-7ekkf-2z3mc76g2q73aio', response['uuid']
-    assert_equal '172.17.2.174', response['ip_address']   # original ip address is not overwritten
-  end
-end
diff --git a/services/api/test/functional/arvados/v1/pipeline_instances_controller_test.rb b/services/api/test/functional/arvados/v1/pipeline_instances_controller_test.rb
deleted file mode 100644 (file)
index e455354..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::PipelineInstancesControllerTest < ActionController::TestCase
-end
diff --git a/services/api/test/functional/arvados/v1/pipeline_templates_controller_test.rb b/services/api/test/functional/arvados/v1/pipeline_templates_controller_test.rb
deleted file mode 100644 (file)
index 992749c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::PipelineTemplatesControllerTest < ActionController::TestCase
-end
diff --git a/services/api/test/functional/arvados/v1/repositories_controller_test.rb b/services/api/test/functional/arvados/v1/repositories_controller_test.rb
deleted file mode 100644 (file)
index 84bd846..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::RepositoriesControllerTest < ActionController::TestCase
-  test "should get_all_logins with admin token" do
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-  end
-
-  test "should get_all_logins with non-admin token" do
-    authorize_with :active
-    get :get_all_permissions
-    assert_response 403
-  end
-
-  test "get_all_permissions gives RW to repository owner" do
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    ok = false
-    json_response['repositories'].each do |repo|
-      if repo['uuid'] == repositories(:repository2).uuid
-        if repo['user_permissions'][users(:active).uuid]['can_write']
-          ok = true
-        end
-      end
-    end
-    assert_equal(true, ok,
-                 "No permission on own repo '@{repositories(:repository2).uuid}'")
-  end
-
-  test "get_all_permissions takes into account is_admin flag" do
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    json_response['repositories'].each do |repo|
-      assert_not_nil(repo['user_permissions'][users(:admin).uuid],
-                     "Admin user is not listed in perms for #{repo['uuid']}")
-      assert_equal(true,
-                   repo['user_permissions'][users(:admin).uuid]['can_write'],
-                   "Admin has no perms for #{repo['uuid']}")
-    end
-  end
-
-  test "get_all_permissions takes into account is_active flag" do
-    act_as_user users(:active) do
-      Repository.create! name: 'active/testrepo'
-    end
-    act_as_system_user do
-      u = users(:active)
-      u.unsetup
-      u.save!
-    end
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    json_response['repositories'].each do |r|
-      r['user_permissions'].each do |user_uuid, perms|
-        refute_equal user_uuid, users(:active).uuid
-      end
-    end
-  end
-
-  test "get_all_permissions does not give any access to user without permission" do
-    viewer_uuid = users(:project_viewer).uuid
-    assert_equal(authorized_keys(:project_viewer).authorized_user_uuid,
-                 viewer_uuid,
-                 "project_viewer must have an authorized_key for this test to work")
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    readable_repos = json_response["repositories"].select do |repo|
-      repo["user_permissions"].has_key?(viewer_uuid)
-    end
-    assert_equal(["arvados"], readable_repos.map { |r| r["name"] },
-                 "project_viewer should only have permissions on public repos")
-  end
-
-  test "get_all_permissions gives gitolite R to user with read-only access" do
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    found_it = false
-    assert_equal(authorized_keys(:spectator).authorized_user_uuid,
-                 users(:spectator).uuid,
-                 "spectator must have an authorized_key for this test to work")
-    json_response['repositories'].each do |repo|
-      next unless repo['uuid'] == repositories(:foo).uuid
-      assert_equal('R',
-                   repo['user_permissions'][users(:spectator).uuid]['gitolite_permissions'],
-                   "spectator user should have just R access to #{repo['uuid']}")
-      found_it = true
-    end
-    assert_equal true, found_it, "spectator user does not have R on foo repo"
-  end
-
-  test "get_all_permissions provides admin and active user keys" do
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    [:active, :admin].each do |u|
-      assert_equal(1, json_response['user_keys'][users(u).uuid].andand.count,
-                   "expected 1 key for #{u} (#{users(u).uuid})")
-      assert_equal(json_response['user_keys'][users(u).uuid][0]['public_key'],
-                   authorized_keys(u).public_key,
-                   "response public_key does not match fixture #{u}.")
-    end
-  end
-
-  test "get_all_permissions lists all repos regardless of permissions" do
-    act_as_system_user do
-      # Create repos that could potentially be left out of the
-      # permission list by accident.
-
-      # No authorized_key, no username (this can't even be done
-      # without skipping validations)
-      r = Repository.create name: 'root/testrepo'
-      assert r.save validate: false
-
-      r = Repository.create name: 'invalid username / repo name', owner_uuid: users(:inactive).uuid
-      assert r.save validate: false
-    end
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    assert_equal(Repository.count, json_response["repositories"].size)
-  end
-
-  test "get_all_permissions lists user permissions for users with no authorized keys" do
-    authorize_with :admin
-    AuthorizedKey.destroy_all
-    get :get_all_permissions
-    assert_response :success
-    assert_equal(Repository.count, json_response["repositories"].size)
-    repos_with_perms = []
-    json_response['repositories'].each do |repo|
-      if repo['user_permissions'].any?
-        repos_with_perms << repo['uuid']
-      end
-    end
-    assert_not_empty repos_with_perms, 'permissions are missing'
-  end
-
-  # Ensure get_all_permissions correctly describes what the normal
-  # permission system would do.
-  test "get_all_permissions obeys group permissions" do
-    act_as_user system_user do
-      r = Repository.create!(name: 'admin/groupcanwrite', owner_uuid: users(:admin).uuid)
-      g = Group.create!(group_class: 'role', name: 'repo-writers')
-      u1 = users(:active)
-      u2 = users(:spectator)
-      Link.create!(tail_uuid: g.uuid, head_uuid: r.uuid, link_class: 'permission', name: 'can_manage')
-      Link.create!(tail_uuid: u1.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_write')
-      Link.create!(tail_uuid: u2.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_read')
-
-      r = Repository.create!(name: 'admin/groupreadonly', owner_uuid: users(:admin).uuid)
-      g = Group.create!(group_class: 'role', name: 'repo-readers')
-      u1 = users(:active)
-      u2 = users(:spectator)
-      Link.create!(tail_uuid: g.uuid, head_uuid: r.uuid, link_class: 'permission', name: 'can_read')
-      Link.create!(tail_uuid: u1.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_write')
-      Link.create!(tail_uuid: u2.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_read')
-    end
-    authorize_with :admin
-    get :get_all_permissions
-    assert_response :success
-    json_response['repositories'].each do |repo|
-      repo['user_permissions'].each do |user_uuid, perms|
-        u = User.find_by_uuid(user_uuid)
-        if perms['can_read']
-          assert u.can? read: repo['uuid']
-          assert_match(/R/, perms['gitolite_permissions'])
-        else
-          refute_match(/R/, perms['gitolite_permissions'])
-        end
-        if perms['can_write']
-          assert u.can? write: repo['uuid']
-          assert_match(/RW\+/, perms['gitolite_permissions'])
-        else
-          refute_match(/W/, perms['gitolite_permissions'])
-        end
-        if perms['can_manage']
-          assert u.can? manage: repo['uuid']
-          assert_match(/RW\+/, perms['gitolite_permissions'])
-        end
-      end
-    end
-  end
-
-  test "default index includes fetch_url" do
-    authorize_with :active
-    get(:index)
-    assert_response :success
-    assert_includes(json_response["items"].map { |r| r["fetch_url"] },
-                    "git@git.zzzzz.arvadosapi.com:active/foo.git")
-  end
-
-  [
-    {cfg: "GitSSH.ExternalURL", cfgval: URI("ssh://git@example.com"), match: %r"^git@example.com:"},
-    {cfg: "GitSSH.ExternalURL", cfgval: URI(""), match: %r"^git@git.zzzzz.arvadosapi.com:"},
-    {cfg: "GitSSH", cfgval: false, refute: /^git@/ },
-    {cfg: "GitHTTP.ExternalURL", cfgval: URI("https://example.com/"), match: %r"^https://example.com/"},
-    {cfg: "GitHTTP.ExternalURL", cfgval: URI(""), match: %r"^https://git.zzzzz.arvadosapi.com/"},
-    {cfg: "GitHTTP", cfgval: false, refute: /^http/ },
-  ].each do |expect|
-    test "set #{expect[:cfg]} to #{expect[:cfgval]}" do
-      ConfigLoader.set_cfg Rails.configuration.Services, expect[:cfg].to_s, expect[:cfgval]
-      authorize_with :active
-      get :index
-      assert_response :success
-      assert_not_empty json_response['items']
-      json_response['items'].each do |r|
-        if expect[:refute]
-          r['clone_urls'].each do |u|
-            refute_match expect[:refute], u
-          end
-        else
-          assert((r['clone_urls'].any? do |u|
-                    expect[:match].match u
-                  end),
-                 "no match for #{expect[:match]} in #{r['clone_urls'].inspect}")
-        end
-      end
-    end
-  end
-
-  test "select push_url in index" do
-    authorize_with :active
-    get(:index, params: {select: ["uuid", "push_url"]})
-    assert_response :success
-    assert_includes(json_response["items"].map { |r| r["push_url"] },
-                    "git@git.zzzzz.arvadosapi.com:active/foo.git")
-  end
-
-  test "select clone_urls in index" do
-    authorize_with :active
-    get(:index, params: {select: ["uuid", "clone_urls"]})
-    assert_response :success
-    assert_includes(json_response["items"].map { |r| r["clone_urls"] }.flatten,
-                    "git@git.zzzzz.arvadosapi.com:active/foo.git")
-  end
-end
index 65a2b64b8a4be509aee4eba716e310477d88a43b..39b0cfe8f99c5c48cf4136452674fd8ccd6bf2f5 100644 (file)
@@ -60,16 +60,16 @@ class Arvados::V1::SchemaControllerTest < ActionController::TestCase
     assert_response :success
     discovery_doc = JSON.parse(@response.body)
     assert_equal('POST',
-                 discovery_doc['resources']['jobs']['methods']['create']['httpMethod'])
+                 discovery_doc['resources']['collections']['methods']['create']['httpMethod'])
   end
 
   test "non-empty disable_api_methods" do
     Rails.configuration.API.DisabledAPIs = ConfigLoader.to_OrderedOptions(
-      {'jobs.create'=>{}, 'pipeline_instances.create'=>{}, 'pipeline_templates.create'=>{}})
+      {'collections.create'=>{}, 'workflows.create'=>{}})
     get :index
     assert_response :success
     discovery_doc = JSON.parse(@response.body)
-    ['jobs', 'pipeline_instances', 'pipeline_templates'].each do |r|
+    ['collections', 'workflows'].each do |r|
       refute_includes(discovery_doc['resources'][r]['methods'].keys(), 'create')
     end
   end
@@ -97,10 +97,10 @@ class Arvados::V1::SchemaControllerTest < ActionController::TestCase
 
     discovery_doc = JSON.parse(@response.body)
 
-    specimens_index_params = discovery_doc['resources']['specimens']['methods']['index']['parameters']  # no changes from super
+    workflows_index_params = discovery_doc['resources']['workflows']['methods']['index']['parameters']  # no changes from super
     coll_index_params = discovery_doc['resources']['collections']['methods']['index']['parameters']
 
-    assert_equal (specimens_index_params.keys + ['include_trash', 'include_old_versions']).sort, coll_index_params.keys.sort
+    assert_equal (workflows_index_params.keys + ['include_trash', 'include_old_versions']).sort, coll_index_params.keys.sort
 
     include_trash_param = coll_index_params['include_trash']
     assert_equal 'boolean', include_trash_param['type']
diff --git a/services/api/test/functional/arvados/v1/specimens_controller_test.rb b/services/api/test/functional/arvados/v1/specimens_controller_test.rb
deleted file mode 100644 (file)
index df681e6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::SpecimensControllerTest < ActionController::TestCase
-end
diff --git a/services/api/test/functional/arvados/v1/traits_controller_test.rb b/services/api/test/functional/arvados/v1/traits_controller_test.rb
deleted file mode 100644 (file)
index 3c8d097..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class Arvados::V1::TraitsControllerTest < ActionController::TestCase
-end
index cc0b5e1320988b1098f698528fb6e892f4b11ea1..2b643d4b27b6723d599ddf38f66b4e2d453778ab 100644 (file)
@@ -121,12 +121,10 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_nil updated['username'], 'expected no username'
   end
 
-  test "create user with user, vm and repo as input" do
+  test "create user with user and vm as input" do
     authorize_with :admin
-    repo_name = 'usertestrepo'
 
     post :setup, params: {
-      repo_name: repo_name,
       user: {
         uuid: 'zzzzz-tpzed-abcdefghijklmno',
         first_name: "in_create_test_first_name",
@@ -145,11 +143,8 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil created['email'], 'expected non-nil email'
     assert_nil created['identity_url'], 'expected no identity_url'
 
-    # repo link and link add user to 'All users' group
-    verify_links_added 3
-
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        "foo/#{repo_name}", created['uuid'], 'arvados#repository', true, 'Repository'
+    # added links: vm permission, 'all users' group
+    verify_links_added 2
 
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
@@ -165,7 +160,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
 
     post :setup, params: {
       uuid: 'bogus_uuid',
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid
     }
     response_body = JSON.parse(@response.body)
@@ -179,7 +173,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
 
     post :setup, params: {
       user: {uuid: 'bogus_uuid'},
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid,
     }
     response_body = JSON.parse(@response.body)
@@ -193,7 +186,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     authorize_with :admin
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid,
     }
     response_body = JSON.parse(@response.body)
@@ -208,7 +200,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
 
     post :setup, params: {
       user: {},
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid,
     }
     response_body = JSON.parse(@response.body)
@@ -218,13 +209,12 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
         'Expected ArgumentError'
   end
 
-  test "invoke setup with existing uuid, vm and repo and verify links" do
+  test "invoke setup with existing uuid and vm permission, and verify links" do
     authorize_with :admin
     inactive_user = users(:inactive)
 
     post :setup, params: {
       uuid: users(:inactive).uuid,
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid
     }
 
@@ -238,10 +228,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_equal inactive_user['email'], resp_obj['email'],
         'expecting inactive user email'
 
-    # expect repo and vm links
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'inactiveuser/usertestrepo', resp_obj['uuid'], 'arvados#repository', true, 'Repository'
-
+    # expect vm permission link
     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
         @vm_uuid, resp_obj['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
   end
@@ -266,7 +253,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
         'expecting inactive user email'
   end
 
-  test "setup user with valid email and repo as input" do
+  test "setup user with valid email and repo(ignored) as input" do
     authorize_with :admin
 
     post :setup, params: {
@@ -280,15 +267,14 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil response_object['uuid'], 'expected uuid for the new user'
     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
 
-    # three extra links; system_group, group and repo perms
-    verify_links_added 3
+    # added links: system_group, 'all users' group.
+    verify_links_added 2
   end
 
   test "setup user with fake vm and expect error" do
     authorize_with :admin
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       vm_uuid: 'no_such_vm',
       user: {email: 'foo@example.com'},
     }
@@ -300,11 +286,10 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
           'Expected RuntimeError: No vm found for no_such_vm'
   end
 
-  test "setup user with valid email, repo and real vm as input" do
+  test "setup user with valid email and real vm as input" do
     authorize_with :admin
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid,
       user: {email: 'foo@example.com'}
     }
@@ -315,8 +300,8 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil response_object['uuid'], 'expected uuid for the new user'
     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
 
-    # four extra links; system_group, group, vm, repo
-    verify_links_added 4
+    # added links; system_group, 'all users' group, vm.
+    verify_links_added 3
   end
 
   test "setup user with valid email, no vm and no repo as input" do
@@ -332,24 +317,20 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil response_object['uuid'], 'expected uuid for new user'
     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
 
-    # two extra links; system_group, and group
+    # added links; system_group, 'all users' group.
     verify_links_added 2
 
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', response_object['uuid'], 'arvados#group', true, 'Group'
 
-    verify_link response_items, 'arvados#repository', false, 'permission', 'can_manage',
-        'foo/usertestrepo', response_object['uuid'], 'arvados#repository', true, 'Repository'
-
     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
         nil, response_object['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
   end
 
-  test "setup user with email, first name, repo name and vm uuid" do
+  test "setup user with email, first name, and vm uuid" do
     authorize_with :admin
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       vm_uuid: @vm_uuid,
       user: {
         first_name: 'test_first_name',
@@ -365,8 +346,8 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_equal 'test_first_name', response_object['first_name'],
         'expecting first name'
 
-    # four extra links; system_group, group, repo and vm
-    verify_links_added 4
+    # added links: system_group, 'all users' group, vm.
+    verify_links_added 3
   end
 
   test "setup user with an existing user email and check different object is created" do
@@ -374,7 +355,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     inactive_user = users(:inactive)
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       user: {
         email: inactive_user['email']
       }
@@ -387,15 +367,14 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_equal response_object['uuid'], inactive_user['uuid'],
         'expected different uuid after create operation'
     assert_equal inactive_user['email'], response_object['email'], 'expected given email'
-    # system_group, group, and repo. No vm link.
-    verify_links_added 3
+    # added links: system_group, 'all users' group.
+    verify_links_added 2
   end
 
   test "setup user with openid prefix" do
     authorize_with :admin
 
     post :setup, params: {
-      repo_name: 'usertestrepo',
       user: {
         first_name: "in_create_test_first_name",
         last_name: "test_last_name",
@@ -413,12 +392,8 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil created['email'], 'expected non-nil email'
     assert_nil created['identity_url'], 'expected no identity_url'
 
-    # verify links
-    # three new links: system_group, repo, and 'All users' group.
-    verify_links_added 3
-
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
+    # added links: system_group, 'all users' group.
+    verify_links_added 2
 
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
@@ -427,7 +402,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
   end
 
-  test "setup user with user, vm and repo and verify links" do
+  test "setup user with user and vm, and verify links" do
     authorize_with :admin
 
     post :setup, params: {
@@ -437,7 +412,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
         email: "foo@example.com"
       },
       vm_uuid: @vm_uuid,
-      repo_name: 'usertestrepo',
     }
 
     assert_response :success
@@ -450,14 +424,11 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil created['email'], 'expected non-nil email'
     assert_nil created['identity_url'], 'expected no identity_url'
 
-    # four new links: system_group, repo, vm and 'All users' group link
-    verify_links_added 4
+    # added links: system_group, 'all users' group, vm
+    verify_links_added 3
 
     # system_group isn't part of the response.  See User#add_system_group_permission_link
 
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
-
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
 
@@ -493,13 +464,11 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
           'Expected Forbidden error'
   end
 
-  test "setup active user with repo and no vm" do
+  test "setup active user with no vm" do
     authorize_with :admin
     active_user = users(:active)
 
-    # invoke setup with a repository
     post :setup, params: {
-      repo_name: 'usertestrepo',
       uuid: active_user['uuid']
     }
 
@@ -510,13 +479,10 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
 
     assert_equal active_user[:email], created['email'], 'expected input email'
 
-     # verify links
+    # verify links
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
 
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'active/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
-
     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
   end
@@ -524,13 +490,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
   test "setup active user with vm and no repo" do
     authorize_with :admin
     active_user = users(:active)
-    repos_query = Repository.where(owner_uuid: active_user.uuid)
-    repo_link_query = Link.where(tail_uuid: active_user.uuid,
-                                 link_class: "permission", name: "can_manage")
-    repos_count = repos_query.count
-    repo_link_count = repo_link_query.count
 
-    # invoke setup with a repository
     post :setup, params: {
       vm_uuid: @vm_uuid,
       uuid: active_user['uuid'],
@@ -548,9 +508,6 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
 
-    assert_equal(repos_count, repos_query.count)
-    assert_equal(repo_link_count, repo_link_query.count)
-
     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
         @vm_uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
   end
@@ -655,7 +612,6 @@ The Arvados team.
     authorize_with :admin
     active_user = users(:active)
 
-    # invoke setup with a repository
     put :update, params: {
           id: active_user['uuid'],
           user: {
index ef1d0c6d05e6486e40a3e6456eac99f074d7a24f..ea44cbf453f5db44931706f7c30cbd8005a46414 100644 (file)
@@ -40,12 +40,12 @@ class DatabaseControllerTest < ActionController::TestCase
   test "reset succeeds with admin token" do
     new_uuid = nil
     act_as_system_user do
-      new_uuid = Specimen.create.uuid
+      new_uuid = Collection.create.uuid
     end
-    assert_not_empty Specimen.where(uuid: new_uuid)
+    assert_not_empty Collection.where(uuid: new_uuid)
     authorize_with :admin
     post :reset
     assert_response 200
-    assert_empty Specimen.where(uuid: new_uuid)
+    assert_empty Collection.where(uuid: new_uuid)
   end
 end
index e13d702983fe3c372debf3b55bc7b9156e44fe84..ab304c1c7ce94dbd07b3e46981a2957e04093a95 100644 (file)
@@ -96,7 +96,6 @@ class SysControllerTest < ActionController::TestCase
     g_bar = groups(:trashed_subproject)
     g_baz = groups(:trashed_subproject3)
     col = collections(:collection_in_trashed_subproject)
-    job = jobs(:job_in_trashed_project)
     cr = container_requests(:cr_in_trashed_project)
     # Save how many objects were before the sweep
     user_nr_was = User.all.length
@@ -104,12 +103,10 @@ class SysControllerTest < ActionController::TestCase
     group_nr_was = Group.where('group_class<>?', 'project').length
     project_nr_was = Group.where(group_class: 'project').length
     cr_nr_was = ContainerRequest.all.length
-    job_nr_was = Job.all.length
     assert_not_empty Group.where(uuid: g_foo.uuid)
     assert_not_empty Group.where(uuid: g_bar.uuid)
     assert_not_empty Group.where(uuid: g_baz.uuid)
     assert_not_empty Collection.where(uuid: col.uuid)
-    assert_not_empty Job.where(uuid: job.uuid)
     assert_not_empty ContainerRequest.where(uuid: cr.uuid)
 
     authorize_with :admin
@@ -120,7 +117,6 @@ class SysControllerTest < ActionController::TestCase
     assert_empty Group.where(uuid: g_bar.uuid)
     assert_empty Group.where(uuid: g_baz.uuid)
     assert_empty Collection.where(uuid: col.uuid)
-    assert_empty Job.where(uuid: job.uuid)
     assert_empty ContainerRequest.where(uuid: cr.uuid)
     # No unwanted deletions should have happened
     assert_equal user_nr_was, User.all.length
@@ -129,7 +125,6 @@ class SysControllerTest < ActionController::TestCase
     assert_equal group_nr_was, Group.where('group_class<>?', 'project').length
     assert_equal project_nr_was-3, Group.where(group_class: 'project').length
     assert_equal cr_nr_was-1, ContainerRequest.all.length
-    assert_equal job_nr_was-1, Job.all.length
   end
 
 end
diff --git a/services/api/test/helpers/git_test_helper.rb b/services/api/test/helpers/git_test_helper.rb
deleted file mode 100644 (file)
index cb30f68..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'fileutils'
-require 'tmpdir'
-
-# Commit log for "foo" repository in test.git.tar
-# main is the main branch
-# b1 is a branch off of main 
-# tag1 is a tag
-#
-# 1de84a8 * b1
-# 077ba2a * main
-# 4fe459a * tag1
-# 31ce37f * foo
-
-module GitTestHelper
-  def self.included base
-    base.setup do
-      # Extract the test repository data into the default test
-      # environment's Rails.configuration.Git.Repositories. (We
-      # don't use that config setting here, though: it doesn't seem
-      # worth the risk of stepping on a real git repo root.)
-      @tmpdir = Rails.root.join 'tmp', 'git'
-      FileUtils.mkdir_p @tmpdir
-      system("tar", "-xC", @tmpdir.to_s, "-f", "test/test.git.tar")
-      Rails.configuration.Git.Repositories = "#{@tmpdir}/test"
-      Rails.configuration.Containers.JobsAPI.GitInternalDir = "#{@tmpdir}/internal.git"
-    end
-
-    base.teardown do
-      FileUtils.remove_entry CommitsHelper.cache_dir_base, true
-      FileUtils.mkdir_p @tmpdir
-      system("tar", "-xC", @tmpdir.to_s, "-f", "test/test.git.tar")
-    end
-  end
-
-  def internal_tag tag
-    IO.read "|git --git-dir #{Rails.configuration.Containers.JobsAPI.GitInternalDir.shellescape} log --format=format:%H -n1 #{tag.shellescape}"
-  end
-
-  # Intercept fetch_remote_repository and fetch from a specified url
-  # or local fixture instead of the remote url requested. fakeurl can
-  # be a url (probably starting with file:///) or the name of a
-  # fixture (as a symbol)
-  def fetch_remote_from_local_repo url, fakeurl
-    if fakeurl.is_a? Symbol
-      fakeurl = 'file://' + repositories(fakeurl).server_path
-    end
-    CommitsHelper.expects(:fetch_remote_repository).once.with do |gitdir, giturl|
-      if giturl == url
-        CommitsHelper.unstub(:fetch_remote_repository)
-        CommitsHelper.fetch_remote_repository gitdir, fakeurl
-        true
-      end
-    end
-  end
-end
index e106d994cd9c9808e5a73358356e71c59f8855b4..c4dc72d3bac01ae1cda4729540c44847c7936015 100644 (file)
@@ -54,14 +54,10 @@ module UsersTestHelper
     # these don't get added any more!  they shouldn't appear ever.
     assert !oid_login_perms.any?, "expected all oid_login_perms deleted"
 
+    # these don't get added any more!  they shouldn't appear ever.
     repo_perms = Link.where(tail_uuid: uuid,
-                            link_class: 'permission',
-                            name: 'can_manage').where("head_uuid like ?", Repository.uuid_like_pattern)
-    if expect_repo_perms
-      assert repo_perms.any?, "expected repo_perms"
-    else
-      assert !repo_perms.any?, "expected all repo_perms deleted"
-    end
+                            link_class: 'permission').where("head_uuid like ?", '_____-s0uqq-_______________')
+    assert !repo_perms.any?, "expected all repo_perms deleted"
 
     vm_login_perms = Link.
       where(tail_uuid: uuid,
index 3b28a3163feef85b026345a39b061db3e9c8372c..83a633764427df0b56840b411bf7b26d49f7430d 100644 (file)
@@ -44,15 +44,15 @@ class ApiTokensScopeTest < ActionDispatch::IntegrationTest
     assert_response 403
    end
 
-  test "specimens token can see exactly owned specimens" do
-    get_args = {params: {}, headers: auth(:active_specimens)}
-    get(v1_url('specimens'), **get_args)
+  test "collections token can see exactly owned collections" do
+    get_args = {params: {}, headers: auth(:active_all_collections)}
+    get(v1_url('collections'), **get_args)
     assert_response 403
-    get(v1_url('specimens', specimens(:owned_by_active_user).uuid), **get_args)
+    get(v1_url('collections', collections(:collection_owned_by_active).uuid), **get_args)
     assert_response :success
-    head(v1_url('specimens', specimens(:owned_by_active_user).uuid), **get_args)
+    head(v1_url('collections', collections(:collection_owned_by_active).uuid), **get_args)
     assert_response :success
-    get(v1_url('specimens', specimens(:owned_by_spectator).uuid), **get_args)
+    get(v1_url('collections', collections(:collection_owned_by_foo).uuid), **get_args)
     assert_includes(403..404, @response.status)
   end
 
index 7015453a9a62b0825628a19f8883a8b70275d72c..aa778dbf9fdb601641e67bf03c1412711e798bbc 100644 (file)
@@ -31,22 +31,22 @@ class DatabaseResetTest < ActionDispatch::IntegrationTest
     post '/database/reset', params: {}, headers: admin_auth
     assert_response :success
 
-    post '/arvados/v1/specimens', params: {specimen: '{}'}, headers: active_auth
+    post '/arvados/v1/collections', params: {collection: '{}'}, headers: active_auth
     assert_response :success
     new_uuid = json_response['uuid']
 
-    get '/arvados/v1/specimens/'+new_uuid, params: {}, headers: active_auth
+    get '/arvados/v1/collections/'+new_uuid, params: {}, headers: active_auth
     assert_response :success
 
-    put('/arvados/v1/specimens/'+new_uuid,
-      params: {specimen: '{"properties":{}}'},
+    put('/arvados/v1/collections/'+new_uuid,
+      params: {collection: '{"properties":{}}'},
       headers: active_auth)
     assert_response :success
 
-    delete '/arvados/v1/specimens/'+new_uuid, params: {}, headers: active_auth
+    delete '/arvados/v1/collections/'+new_uuid, params: {}, headers: active_auth
     assert_response :success
 
-    get '/arvados/v1/specimens/'+new_uuid, params: {}, headers: active_auth
+    get '/arvados/v1/collections/'+new_uuid, params: {}, headers: active_auth
     assert_response 404
   end
 
@@ -54,14 +54,14 @@ class DatabaseResetTest < ActionDispatch::IntegrationTest
     active_auth = auth(:active)
     admin_auth = auth(:admin)
 
-    old_uuid = specimens(:owned_by_active_user).uuid
+    old_uuid = collections(:collection_owned_by_active).uuid
     authorize_with :admin
     post '/database/reset', params: {}, headers: admin_auth
     assert_response :success
 
-    delete '/arvados/v1/specimens/' + old_uuid, params: {}, headers: active_auth
+    delete '/arvados/v1/collections/' + old_uuid, params: {}, headers: active_auth
     assert_response :success
-    post '/arvados/v1/specimens', params: {specimen: '{}'}, headers: active_auth
+    post '/arvados/v1/collections', params: {collection: '{}'}, headers: active_auth
     assert_response :success
     new_uuid = json_response['uuid']
 
@@ -69,10 +69,10 @@ class DatabaseResetTest < ActionDispatch::IntegrationTest
     post '/database/reset', params: {}, headers: admin_auth
     assert_response :success
 
-    # New specimen should disappear. Old specimen should reappear.
-    get '/arvados/v1/specimens/'+new_uuid, params: {}, headers: active_auth
+    # New collection should disappear. Old collection should reappear.
+    get '/arvados/v1/collections/'+new_uuid, params: {}, headers: active_auth
     assert_response 404
-    get '/arvados/v1/specimens/'+old_uuid, params: {}, headers: active_auth
+    get '/arvados/v1/collections/'+old_uuid, params: {}, headers: active_auth
     assert_response :success
   end
 end
index e76f2b54068ad729fe94f87a3d2150846674db0b..bc5a08c2c8dced5e4f17a621965b1fef75f1a599 100644 (file)
@@ -140,7 +140,7 @@ class GroupsTest < ActionDispatch::IntegrationTest
 
   test 'count none works with offset' do
     first_results = nil
-    (0..10).each do |offset|
+    (0..5).each do |offset|
       get "/arvados/v1/groups/contents", params: {
         id: groups(:aproject).uuid,
         offset: offset,
diff --git a/services/api/test/integration/jobs_api_test.rb b/services/api/test/integration/jobs_api_test.rb
deleted file mode 100644 (file)
index 76d4fff..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class JobsApiTest < ActionDispatch::IntegrationTest
-end
index ba3b2ac6e3198bbc0ad1eee986b71a2eb80db444..7ad95ceebf3d3a8d908adf73459872d472f40a42 100644 (file)
@@ -6,8 +6,8 @@ require 'test_helper'
 
 class LoginWorkflowTest < ActionDispatch::IntegrationTest
   test "default prompt to login is JSON" do
-    post('/arvados/v1/specimens',
-      params: {specimen: {}},
+    post('/arvados/v1/collections',
+      params: {collection: {}},
       headers: {'HTTP_ACCEPT' => ''})
     assert_response 401
     json_response['errors'].each do |err|
@@ -16,8 +16,8 @@ class LoginWorkflowTest < ActionDispatch::IntegrationTest
   end
 
   test "login prompt respects JSON Accept header" do
-    post('/arvados/v1/specimens',
-      params: {specimen: {}},
+    post('/arvados/v1/collections',
+      params: {collection: {}},
       headers: {'HTTP_ACCEPT' => 'application/json'})
     assert_response 401
     json_response['errors'].each do |err|
@@ -26,8 +26,8 @@ class LoginWorkflowTest < ActionDispatch::IntegrationTest
   end
 
   test "login prompt respects HTML Accept header" do
-    post('/arvados/v1/specimens',
-      params: {specimen: {}},
+    post('/arvados/v1/collections',
+      params: {collection: {}},
       headers: {'HTTP_ACCEPT' => 'text/html'})
     assert_response 302
     assert_match(%r{http://www.example.com/login$}, @response.headers['Location'],
index d2dce44f018a0ce2e63232889d9d7cc4fe412aae..9636a82011ffd1e7d0559fa47d2ec5fa41dbc518 100644 (file)
@@ -302,26 +302,29 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     assert_response 404
   end
 
-  test "RO group-admin finds user's specimens, RW group-admin can update" do
+  test "RO group-admin finds user's collections, RW group-admin can update" do
+    other_user_collection = act_as_user(users(:user_foo_in_sharing_group)) do
+      Collection.create()
+    end
     [[:rominiadmin, false],
      [:miniadmin, true]].each do |which_user, update_should_succeed|
-      get "/arvados/v1/specimens",
+      get "/arvados/v1/collections",
         params: {:format => :json},
         headers: auth(which_user)
       assert_response :success
       resp_uuids = json_response['items'].collect { |i| i['uuid'] }
-      [[true, specimens(:owned_by_active_user).uuid],
-       [true, specimens(:owned_by_private_group).uuid],
-       [false, specimens(:owned_by_spectator).uuid],
+      [[true, collections(:collection_owned_by_active).uuid],
+       [true, collections(:foo_collection_in_aproject).uuid],
+       [false, other_user_collection.uuid],
       ].each do |should_find, uuid|
         assert_equal(should_find, !resp_uuids.index(uuid).nil?,
-                     "%s should%s see %s in specimen list" %
+                     "%s should%s see %s in collection list" %
                      [which_user.to_s,
-                      should_find ? '' : 'not ',
+                      should_find ? '' : ' not',
                       uuid])
-        put "/arvados/v1/specimens/#{uuid}",
+        put "/arvados/v1/collections/#{uuid}",
           params: {
-            :specimen => {
+            :collection => {
               properties: {
                 miniadmin_was_here: true
               }
index e8e8c910c7153a73411cb6602322a6ec64cf8f60..891bffbb1ddf4bd5d734fe6e6f2df310369e9199 100644 (file)
@@ -7,20 +7,20 @@ require 'test_helper'
 class ReaderTokensTest < ActionDispatch::IntegrationTest
   fixtures :all
 
-  def spectator_specimen
-    specimens(:owned_by_spectator).uuid
+  def owned_by_foo
+    collections(:collection_owned_by_foo).uuid
   end
 
-  def get_specimens(main_auth, read_auth, formatter=:to_a)
+  def get_collections(main_auth, read_auth, formatter=:to_a)
     params = {}
     params[:reader_tokens] = [api_token(read_auth)].send(formatter) if read_auth
     headers = {}
     headers.merge!(auth(main_auth)) if main_auth
-    get('/arvados/v1/specimens', params: params, headers: headers)
+    get('/arvados/v1/collections', params: params, headers: headers)
   end
 
-  def get_specimen_uuids(main_auth, read_auth, formatter=:to_a)
-    get_specimens(main_auth, read_auth, formatter)
+  def get_collection_uuids(main_auth, read_auth, formatter=:to_a)
+    get_collections(main_auth, read_auth, formatter)
     assert_response :success
     json_response['items'].map { |spec| spec['uuid'] }
   end
@@ -33,26 +33,26 @@ class ReaderTokensTest < ActionDispatch::IntegrationTest
       headers = {}
       expected = 401
     end
-    post('/arvados/v1/specimens.json',
-      params: {specimen: {}, reader_tokens: [api_token(read_auth)].send(formatter)},
+    post('/arvados/v1/collections.json',
+      params: {collection: {}, reader_tokens: [api_token(read_auth)].send(formatter)},
       headers: headers)
     assert_response expected
   end
 
-  test "active user can't see spectator specimen" do
+  test "active user can't see foo-owned collection" do
     # Other tests in this suite assume that the active user doesn't
-    # have read permission to the owned_by_spectator specimen.
+    # have read permission to the owned_by_foo collection.
     # This test checks that this assumption still holds.
-    refute_includes(get_specimen_uuids(:active, nil), spectator_specimen,
-                    ["active user can read the owned_by_spectator specimen",
+    refute_includes(get_collection_uuids(:active, nil), owned_by_foo,
+                    ["active user can read the owned_by_foo collection",
                      "other tests will return false positives"].join(" - "))
   end
 
   [nil, :active_noscope].each do |main_auth|
-    [:spectator, :spectator_specimens].each do |read_auth|
+    [:foo, :foo_collections].each do |read_auth|
       [:to_a, :to_json].each do |formatter|
         test "#{main_auth.inspect} auth with #{formatter} reader token #{read_auth} can#{"'t" if main_auth} read" do
-          get_specimens(main_auth, read_auth)
+          get_collections(main_auth, read_auth)
           assert_response(if main_auth then 403 else 200 end)
         end
 
@@ -65,18 +65,18 @@ class ReaderTokensTest < ActionDispatch::IntegrationTest
 
   test "scopes are still limited with reader tokens" do
     get('/arvados/v1/collections',
-      params: {reader_tokens: [api_token(:spectator_specimens)]},
+      params: {reader_tokens: [api_token(:foo_collections)]},
       headers: auth(:active_noscope))
     assert_response 403
   end
 
   test "reader tokens grant no permissions when expired" do
-    get_specimens(:active_noscope, :expired)
+    get_collections(:active_noscope, :expired)
     assert_response 403
   end
 
   test "reader tokens grant no permissions outside their scope" do
-    refute_includes(get_specimen_uuids(:active, :admin_vm), spectator_specimen,
+    refute_includes(get_collection_uuids(:active, :admin_vm), owned_by_foo,
                     "scoped reader token granted permissions out of scope")
   end
 end
index f41c033b3918c2fea8b9dc0e088f534600d38ab7..bf2d0062f222bad9676508238d40fdcadf01bb5d 100644 (file)
@@ -3,26 +3,13 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 require 'test_helper'
-require 'helpers/git_test_helper'
 
 class SerializedEncodingTest < ActionDispatch::IntegrationTest
-  include GitTestHelper
-
   fixtures :all
 
   {
     api_client_authorization: {scopes: []},
-
-    human: {properties: {eye_color: 'gray'}},
-
     link: {link_class: 'test', name: 'test', properties: {foo: :bar}},
-
-    node: {info: {uptime: 1234}},
-
-    specimen: {properties: {eye_color: 'meringue'}},
-
-    trait: {properties: {eye_color: 'brown'}},
-
     user: {prefs: {cookies: 'thin mint'}},
   }.each_pair do |resource, postdata|
     test "create json-encoded #{resource.to_s}" do
index eb49cf832e2fe9b2e86a6228a1ea7dc0b7eef59a..2b374542188bfef5ed7196728e4c6a3cad827689 100644 (file)
@@ -87,22 +87,20 @@ class UserSessionsApiTest < ActionDispatch::IntegrationTest
 
   # Test various combinations of auto_setup configuration and email
   # address provided during a new user's first session setup.
-  [{result: :nope, email: nil, cfg: {auto: true, repo: true, vm: true}},
+  [{result: :nope, email: nil, cfg: {auto: true, vm: true}},
    {result: :yup, email: nil, cfg: {auto: true}},
-   {result: :nope, email: '@example.com', cfg: {auto: true, repo: true, vm: true}},
+   {result: :nope, email: '@example.com', cfg: {auto: true, vm: true}},
    {result: :yup, email: '@example.com', cfg: {auto: true}},
-   {result: :nope, email: 'root@', cfg: {auto: true, repo: true, vm: true}},
-   {result: :nope, email: 'root@', cfg: {auto: true, repo: true}},
    {result: :nope, email: 'root@', cfg: {auto: true, vm: true}},
-   {result: :yup, email: 'root@', cfg: {auto: true}},
-   {result: :nope, email: 'gitolite@', cfg: {auto: true, repo: true}},
+   {result: :nope, email: 'root@', cfg: {auto: true}},
+   {result: :nope, email: 'gitolite@', cfg: {auto: true}},
    {result: :nope, email: '*_*@', cfg: {auto: true, vm: true}},
    {result: :yup, email: 'toor@', cfg: {auto: true, vm: true, repo: true}},
    {result: :yup, email: 'foo@', cfg: {auto: true, vm: true},
      uniqprefix: 'foo'},
-   {result: :yup, email: 'foo@', cfg: {auto: true, repo: true},
+   {result: :yup, email: 'foo@', cfg: {auto: true},
      uniqprefix: 'foo'},
-   {result: :yup, email: 'auto_setup_vm_login@', cfg: {auto: true, repo: true},
+   {result: :yup, email: 'auto_setup_vm_login@', cfg: {auto: true},
      uniqprefix: 'auto_setup_vm_login'},
    ].each do |testcase|
     test "user auto-activate #{testcase.inspect}" do
@@ -111,23 +109,16 @@ class UserSessionsApiTest < ActionDispatch::IntegrationTest
       Rails.configuration.Users.AutoSetupNewUsers = testcase[:cfg][:auto]
       Rails.configuration.Users.AutoSetupNewUsersWithVmUUID =
         (testcase[:cfg][:vm] ? virtual_machines(:testvm).uuid : "")
-      Rails.configuration.Users.AutoSetupNewUsersWithRepository =
-        testcase[:cfg][:repo]
 
       mock_auth_with(email: testcase[:email])
       u = assigns(:user)
       vm_links = Link.where('link_class=? and tail_uuid=? and head_uuid like ?',
                             'permission', u.uuid,
                             '%-' + VirtualMachine.uuid_prefix + '-%')
-      repo_links = Link.where('link_class=? and tail_uuid=? and head_uuid like ?',
-                              'permission', u.uuid,
-                              '%-' + Repository.uuid_prefix + '-%')
-      repos = Repository.where('uuid in (?)', repo_links.collect(&:head_uuid))
       case u[:result]
       when :nope
         assert_equal false, u.is_invited, "should not have been set up"
         assert_empty vm_links, "should not have VM login permission"
-        assert_empty repo_links, "should not have repo permission"
       when :yup
         assert_equal true, u.is_invited
         if testcase[:cfg][:vm]
@@ -135,21 +126,11 @@ class UserSessionsApiTest < ActionDispatch::IntegrationTest
         else
           assert_empty vm_links, "should not have VM login permission"
         end
-        if testcase[:cfg][:repo]
-          assert_equal 1, repo_links.count, "wrong number of repo perm links"
-          assert_equal 1, repos.count, "wrong number of repos"
-          assert_equal 'can_manage', repo_links.first.name, "wrong perm type"
-        else
-          assert_empty repo_links, "should not have repo permission"
-        end
       end
       if (prefix = testcase[:uniqprefix])
         # This email address conflicts with a test fixture. Make sure
-        # every VM login and repository name got digits added to make
-        # it unique.
-        (repos.collect(&:name) +
-         vm_links.collect { |link| link.properties['username'] }
-         ).each do |name|
+        # every VM login got digits added to make it unique.
+        vm_links.collect { |link| link.properties['username'] }.each do |name|
           r = name.match(/^(.{#{prefix.length}})(\d+)$/)
           assert_not_nil r, "#{name.inspect} does not match {prefix}\\d+"
           assert_equal(prefix, r[1],
index f8956b21e24a0772899b5c796dd2b2e650fc1e6e..a7d6245443e2c4318f604674adfbc20a8423f65d 100644 (file)
@@ -9,11 +9,8 @@ class UsersTest < ActionDispatch::IntegrationTest
   include UsersTestHelper
 
   test "setup user multiple times" do
-    repo_name = 'usertestrepo'
-
     post "/arvados/v1/users/setup",
       params: {
-        repo_name: repo_name,
         user: {
           uuid: 'zzzzz-tpzed-abcdefghijklmno',
           first_name: "in_create_test_first_name",
@@ -35,10 +32,7 @@ class UsersTest < ActionDispatch::IntegrationTest
     assert_not_nil created['email'], 'expected non-nil email'
     assert_nil created['identity_url'], 'expected no identity_url'
 
-    # repo link and link add user to 'All users' group
-
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
+    # link to add user to 'All users' group
 
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
@@ -51,7 +45,6 @@ class UsersTest < ActionDispatch::IntegrationTest
     # invoke setup again with the same data
     post "/arvados/v1/users/setup",
       params: {
-        repo_name: repo_name,
         vm_uuid: virtual_machines(:testvm).uuid,
         user: {
           uuid: 'zzzzz-tpzed-abcdefghijklmno',
@@ -66,7 +59,6 @@ class UsersTest < ActionDispatch::IntegrationTest
     # invoke setup on the same user
     post "/arvados/v1/users/setup",
       params: {
-        repo_name: repo_name,
         vm_uuid: virtual_machines(:testvm).uuid,
         uuid: 'zzzzz-tpzed-abcdefghijklmno',
       },
@@ -81,10 +73,7 @@ class UsersTest < ActionDispatch::IntegrationTest
     assert_not_nil created['email'], 'expected non-nil email'
     assert_nil created['identity_url'], 'expected no identity_url'
 
-    # arvados#user, repo link and link add user to 'All users' group
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
-
+    # arvados#user, and link to add user to 'All users' group
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
 
@@ -119,31 +108,6 @@ class UsersTest < ActionDispatch::IntegrationTest
     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
 
-   # invoke setup with a repository
-    post "/arvados/v1/users/setup",
-      params: {
-        repo_name: 'newusertestrepo',
-        uuid: created['uuid']
-      },
-      headers: auth(:admin)
-
-    assert_response :success
-
-    response_items = json_response['items']
-    created = find_obj_in_resp response_items, 'arvados#user', nil
-
-    assert_equal 'foo@example.com', created['email'], 'expected input email'
-
-     # verify links
-    verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
-        'All users', created['uuid'], 'arvados#group', true, 'Group'
-
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/newusertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
-
-    verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
-        nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
-
     # invoke setup with a vm_uuid
     post "/arvados/v1/users/setup",
       params: {
@@ -173,7 +137,6 @@ class UsersTest < ActionDispatch::IntegrationTest
   test "setup and unsetup user" do
     post "/arvados/v1/users/setup",
       params: {
-        repo_name: 'newusertestrepo',
         vm_uuid: virtual_machines(:testvm).uuid,
         user: {email: 'foo@example.com'},
       },
@@ -185,14 +148,11 @@ class UsersTest < ActionDispatch::IntegrationTest
     assert_not_nil created['uuid'], 'expected uuid for the new user'
     assert_equal created['email'], 'foo@example.com', 'expected given email'
 
-    # four extra links: system_group, login, group, repo and vm
+    # three extra links: system_group, login, group and vm
 
     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
         'All users', created['uuid'], 'arvados#group', true, 'Group'
 
-    verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
-        'foo/newusertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
-
     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
         virtual_machines(:testvm).uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
 
@@ -276,13 +236,6 @@ class UsersTest < ActionDispatch::IntegrationTest
     assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
     assert_equal(users(:project_viewer).uuid, json_response['authorized_user_uuid'])
 
-    get('/arvados/v1/repositories/' + repositories(:foo).uuid,
-      params: {},
-      headers: auth(:active))
-    assert_response(:success)
-    assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
-    assert_equal("#{users(:project_viewer).username}/foo", json_response['name'])
-
     get('/arvados/v1/groups/' + groups(:aproject).uuid,
       params: {},
       headers: auth(:active))
@@ -317,41 +270,6 @@ class UsersTest < ActionDispatch::IntegrationTest
     assert_equal 'barney', json_response['username']
   end
 
-  test 'merge with repository name conflict' do
-    post('/arvados/v1/groups',
-      params: {
-        group: {
-          group_class: 'project',
-          name: "active user's stuff",
-        },
-      },
-      headers: auth(:project_viewer))
-    assert_response(:success)
-    project_uuid = json_response['uuid']
-
-    post('/arvados/v1/repositories/',
-         params: { :repository => { :name => "#{users(:project_viewer).username}/foo", :owner_uuid => users(:project_viewer).uuid } },
-         headers: auth(:project_viewer))
-    assert_response(:success)
-
-    post('/arvados/v1/users/merge',
-      params: {
-        new_user_token: api_client_authorizations(:project_viewer_trustedclient).api_token,
-        new_owner_uuid: project_uuid,
-        redirect_to_new_user: true,
-      },
-      headers: auth(:active_trustedclient))
-    assert_response(:success)
-
-    get('/arvados/v1/repositories/' + repositories(:foo).uuid,
-      params: {},
-      headers: auth(:active))
-    assert_response(:success)
-    assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
-    assert_equal("#{users(:project_viewer).username}/migratedfoo", json_response['name'])
-
-  end
-
   test "cannot set is_active to false directly" do
     post('/arvados/v1/users',
       params: {
diff --git a/services/api/test/test.git.tar b/services/api/test/test.git.tar
deleted file mode 100644 (file)
index 7af80b0..0000000
Binary files a/services/api/test/test.git.tar and /dev/null differ
index 69a2710bb954caa04f3c3e86da8c13f3719bb10b..341a8462dded2f467de8a6c639c78dbc3ff9591b 100644 (file)
@@ -8,20 +8,20 @@ class ArvadosModelTest < ActiveSupport::TestCase
   fixtures :all
 
   def create_with_attrs attrs
-    a = Specimen.create({material: 'caloric'}.merge(attrs))
+    a = Collection.create({properties: {'foo' => 'bar'}}.merge(attrs))
     a if a.valid?
   end
 
   test 'non-admin cannot assign uuid' do
     set_user_from_auth :active_trustedclient
-    want_uuid = Specimen.generate_uuid
+    want_uuid = Collection.generate_uuid
     a = create_with_attrs(uuid: want_uuid)
     assert_nil a, "Non-admin should not assign uuid."
   end
 
   test 'admin can assign valid uuid' do
     set_user_from_auth :admin_trustedclient
-    want_uuid = Specimen.generate_uuid
+    want_uuid = Collection.generate_uuid
     a = create_with_attrs(uuid: want_uuid)
     assert_equal want_uuid, a.uuid, "Admin should assign valid uuid."
     assert a.uuid.length==27, "Auto assigned uuid length is wrong."
@@ -29,7 +29,7 @@ class ArvadosModelTest < ActiveSupport::TestCase
 
   test 'admin cannot assign uuid with wrong object type' do
     set_user_from_auth :admin_trustedclient
-    want_uuid = Human.generate_uuid
+    want_uuid = Group.generate_uuid
     a = create_with_attrs(uuid: want_uuid)
     assert_nil a, "Admin should not be able to assign invalid uuid."
   end
@@ -126,10 +126,23 @@ class ArvadosModelTest < ActiveSupport::TestCase
   end
 
   test "search index exists on models that go into projects" do
-    all_tables =  ActiveRecord::Base.connection.tables
-    all_tables.delete 'schema_migrations'
-    all_tables.delete 'permission_refresh_lock'
-    all_tables.delete 'ar_internal_metadata'
+    all_tables =  ActiveRecord::Base.connection.tables - [
+      'ar_internal_metadata',
+      'permission_refresh_lock',
+      'schema_migrations',
+      # tables that may still exist in the database even though model
+      # classes have been deleted:
+      'humans',
+      'jobs',
+      'job_tasks',
+      'keep_disks',
+      'nodes',
+      'pipeline_instances',
+      'pipeline_templates',
+      'repositories',
+      'specimens',
+      'traits',
+    ]
 
     all_tables.each do |table|
       table_class = table.classify.constantize
@@ -159,9 +172,6 @@ class ArvadosModelTest < ActiveSupport::TestCase
     %w[collections collections_trgm_text_search_idx],
     %w[container_requests container_requests_trgm_text_search_idx],
     %w[groups groups_trgm_text_search_idx],
-    %w[jobs jobs_trgm_text_search_idx],
-    %w[pipeline_instances pipeline_instances_trgm_text_search_idx],
-    %w[pipeline_templates pipeline_templates_trgm_text_search_idx],
     %w[workflows workflows_trgm_text_search_idx]
   ].each do |model|
     table = model[0]
@@ -180,25 +190,25 @@ class ArvadosModelTest < ActiveSupport::TestCase
   end
 
   test "selectable_attributes includes database attributes" do
-    assert_includes(Job.selectable_attributes, "success")
+    assert_includes(Collection.selectable_attributes, "name")
   end
 
   test "selectable_attributes includes non-database attributes" do
-    assert_includes(Job.selectable_attributes, "node_uuids")
+    assert_includes(Collection.selectable_attributes, "unsigned_manifest_text")
   end
 
   test "selectable_attributes includes common attributes in extensions" do
-    assert_includes(Job.selectable_attributes, "uuid")
+    assert_includes(Collection.selectable_attributes, "uuid")
   end
 
   test "selectable_attributes does not include unexposed attributes" do
-    refute_includes(Job.selectable_attributes, "nodes")
+    refute_includes(Collection.selectable_attributes, "id")
   end
 
   test "selectable_attributes on a non-default template" do
-    attr_a = Job.selectable_attributes(:common)
+    attr_a = Collection.selectable_attributes(:common)
     assert_includes(attr_a, "uuid")
-    refute_includes(attr_a, "success")
+    refute_includes(attr_a, "name")
   end
 
   test 'create and retrieve using created_at time' do
@@ -260,19 +270,21 @@ class ArvadosModelTest < ActiveSupport::TestCase
       else
         Rails.configuration.AuditLogs.MaxAge = 0
       end
+      tested_serialized = false
       [
         User.find_by_uuid(users(:active).uuid),
         ContainerRequest.find_by_uuid(container_requests(:queued).uuid),
         Container.find_by_uuid(containers(:queued).uuid),
-        PipelineInstance.find_by_uuid(pipeline_instances(:has_component_with_completed_jobs).uuid),
-        PipelineTemplate.find_by_uuid(pipeline_templates(:two_part).uuid),
-        Job.find_by_uuid(jobs(:running).uuid)
+        Group.find_by_uuid(groups(:afiltergroup).uuid),
+        Collection.find_by_uuid(collections(:collection_with_one_property).uuid),
       ].each do |obj|
-        assert_not(obj.class.serialized_attributes.empty?,
-          "#{obj.class} model doesn't have serialized attributes")
+        if !obj.class.serialized_attributes.empty?
+          tested_serialized = true
+        end
         # obj shouldn't have changed since it's just retrieved from the database
         assert_not(obj.changed?, "#{obj.class} model's attribute(s) appear as changed: '#{obj.changes.keys.join(',')}' with audit logs #{auditlogs_enabled ? '': 'not '}enabled.")
       end
+      assert(tested_serialized, "did not test any models with serialized attributes")
     end
   end
 end
diff --git a/services/api/test/unit/commit_ancestor_test.rb b/services/api/test/unit/commit_ancestor_test.rb
deleted file mode 100644 (file)
index 4604121..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class CommitAncestorTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
-end
diff --git a/services/api/test/unit/commit_test.rb b/services/api/test/unit/commit_test.rb
deleted file mode 100644 (file)
index e83061f..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-require 'helpers/git_test_helper'
-
-# NOTE: calling Commit.find_commit_range(nil, nil, 'rev')
-# produces an error message "fatal: bad object 'rev'" on stderr if
-# 'rev' does not exist in a given repository.  Many of these tests
-# report such errors; their presence does not represent a fatal
-# condition.
-
-class CommitTest < ActiveSupport::TestCase
-  # See git_setup.rb for the commit log for test.git.tar
-  include GitTestHelper
-
-  setup do
-    authorize_with :active
-  end
-
-  test 'find_commit_range does not bypass permissions' do
-    authorize_with :inactive
-    assert_raises ArgumentError do
-      CommitsHelper::find_commit_range 'foo', nil, 'main', []
-    end
-  end
-
-  def must_pipe(cmd)
-    begin
-      return IO.read("|#{cmd}")
-    ensure
-      assert $?.success?
-    end
-  end
-
-  [
-   'https://github.com/arvados/arvados.git',
-   'http://github.com/arvados/arvados.git',
-   'git://github.com/arvados/arvados.git',
-  ].each do |url|
-    test "find_commit_range uses fetch_remote_repository to get #{url}" do
-      fake_gitdir = repositories(:foo).server_path
-      CommitsHelper::expects(:cache_dir_for).once.with(url).returns fake_gitdir
-      CommitsHelper::expects(:fetch_remote_repository).once.with(fake_gitdir, url).returns true
-      c = CommitsHelper::find_commit_range url, nil, 'main', []
-      refute_empty c
-    end
-  end
-
-  [
-   'bogus/repo',
-   '/bogus/repo',
-   '/not/allowed/.git',
-   'file:///not/allowed.git',
-   'git.arvados.org/arvados.git',
-   'github.com/arvados/arvados.git',
-  ].each do |url|
-    test "find_commit_range skips fetch_remote_repository for #{url}" do
-      CommitsHelper::expects(:fetch_remote_repository).never
-      assert_raises ArgumentError do
-        CommitsHelper::find_commit_range url, nil, 'main', []
-      end
-    end
-  end
-
-  test 'fetch_remote_repository does not leak commits across repositories' do
-    url = "http://localhost:1/fake/fake.git"
-    fetch_remote_from_local_repo url, :foo
-    c = CommitsHelper::find_commit_range url, nil, 'main', []
-    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57'], c
-
-    url = "http://localhost:2/fake/fake.git"
-    fetch_remote_from_local_repo url, 'file://' + File.expand_path('../../.git', Rails.root)
-    c = CommitsHelper::find_commit_range url, nil, '077ba2ad3ea24a929091a9e6ce545c93199b8e57', []
-    assert_equal [], c
-  end
-
-  test 'tag_in_internal_repository creates and updates tags in internal.git' do
-    authorize_with :active
-    gitint = "git --git-dir #{Rails.configuration.Containers.JobsAPI.GitInternalDir}"
-    IO.read("|#{gitint} tag -d testtag 2>/dev/null") # "no such tag", fine
-    assert_match(/^fatal: /, IO.read("|#{gitint} show testtag 2>&1"))
-    refute $?.success?
-    CommitsHelper::tag_in_internal_repository 'active/foo', '31ce37fe365b3dc204300a3e4c396ad333ed0556', 'testtag'
-    assert_match(/^commit 31ce37f/, IO.read("|#{gitint} show testtag"))
-    assert $?.success?
-  end
-
-  def with_foo_repository
-    Dir.chdir("#{Rails.configuration.Git.Repositories}/#{repositories(:foo).uuid}") do
-      must_pipe("git checkout main 2>&1")
-      yield
-    end
-  end
-
-  test 'tag_in_internal_repository, new non-tip sha1 in local repo' do
-    tag = "tag#{rand(10**10)}"
-    sha1 = nil
-    with_foo_repository do
-      must_pipe("git checkout -b branch-#{rand(10**10)} 2>&1")
-      must_pipe("echo -n #{tag.shellescape} >bar")
-      must_pipe("git add bar")
-      must_pipe("git -c user.email=x@x -c user.name=X commit -m -")
-      sha1 = must_pipe("git log -n1 --format=%H").strip
-      must_pipe("git rm bar")
-      must_pipe("git -c user.email=x@x -c user.name=X commit -m -")
-    end
-    CommitsHelper::tag_in_internal_repository 'active/foo', sha1, tag
-    gitint = "git --git-dir #{Rails.configuration.Containers.JobsAPI.GitInternalDir.shellescape}"
-    assert_match(/^commit /, IO.read("|#{gitint} show #{tag.shellescape}"))
-    assert $?.success?
-  end
-
-  test 'tag_in_internal_repository, new unreferenced sha1 in local repo' do
-    tag = "tag#{rand(10**10)}"
-    sha1 = nil
-    with_foo_repository do
-      must_pipe("echo -n #{tag.shellescape} >bar")
-      must_pipe("git add bar")
-      must_pipe("git -c user.email=x@x -c user.name=X commit -m -")
-      sha1 = must_pipe("git log -n1 --format=%H").strip
-      must_pipe("git reset --hard HEAD^")
-    end
-    CommitsHelper::tag_in_internal_repository 'active/foo', sha1, tag
-    gitint = "git --git-dir #{Rails.configuration.Containers.JobsAPI.GitInternalDir.shellescape}"
-    assert_match(/^commit /, IO.read("|#{gitint} show #{tag.shellescape}"))
-    assert $?.success?
-  end
-
-  # In active/shabranchnames, "7387838c69a21827834586cc42b467ff6c63293b" is
-  # both a commit hash, and the name of a branch that begins from that same
-  # commit.
-  COMMIT_BRANCH_NAME = "7387838c69a21827834586cc42b467ff6c63293b"
-  # A commit that appears in the branch after 7387838c.
-  COMMIT_BRANCH_COMMIT_2 = "abec49829bf1758413509b7ffcab32a771b71e81"
-  # "738783" is another branch that starts from the above commit.
-  SHORT_COMMIT_BRANCH_NAME = COMMIT_BRANCH_NAME[0, 6]
-  # A commit that appears in branch 738783 after 7387838c.
-  SHORT_BRANCH_COMMIT_2 = "77e1a93093663705a63bb4d505698047e109dedd"
-
-  test "find_commit_range min_version prefers commits over branch names" do
-    assert_equal([COMMIT_BRANCH_NAME],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          COMMIT_BRANCH_NAME, nil, nil))
-  end
-
-  test "find_commit_range max_version prefers commits over branch names" do
-    assert_equal([COMMIT_BRANCH_NAME],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          nil, COMMIT_BRANCH_NAME, nil))
-  end
-
-  test "find_commit_range min_version with short branch name" do
-    assert_equal([SHORT_BRANCH_COMMIT_2],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          SHORT_COMMIT_BRANCH_NAME, nil, nil))
-  end
-
-  test "find_commit_range max_version with short branch name" do
-    assert_equal([SHORT_BRANCH_COMMIT_2],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          nil, SHORT_COMMIT_BRANCH_NAME, nil))
-  end
-
-  test "find_commit_range min_version with disambiguated branch name" do
-    assert_equal([COMMIT_BRANCH_COMMIT_2],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          "heads/#{COMMIT_BRANCH_NAME}",
-                                          nil, nil))
-  end
-
-  test "find_commit_range max_version with disambiguated branch name" do
-    assert_equal([COMMIT_BRANCH_COMMIT_2],
-                 CommitsHelper::find_commit_range("active/shabranchnames", nil,
-                                          "heads/#{COMMIT_BRANCH_NAME}", nil))
-  end
-
-  test "find_commit_range min_version with unambiguous short name" do
-    assert_equal([COMMIT_BRANCH_NAME],
-                 CommitsHelper::find_commit_range("active/shabranchnames",
-                                          COMMIT_BRANCH_NAME[0..-2], nil, nil))
-  end
-
-  test "find_commit_range max_version with unambiguous short name" do
-    assert_equal([COMMIT_BRANCH_NAME],
-                 CommitsHelper::find_commit_range("active/shabranchnames", nil,
-                                          COMMIT_BRANCH_NAME[0..-2], nil))
-  end
-
-  test "find_commit_range laundry list" do
-    authorize_with :active
-
-    # single
-    a = CommitsHelper::find_commit_range('active/foo', nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556', nil)
-    assert_equal ['31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
-
-    #test "test_branch1" do
-    a = CommitsHelper::find_commit_range('active/foo', nil, 'main', nil)
-    assert_includes(a, '077ba2ad3ea24a929091a9e6ce545c93199b8e57')
-
-    #test "test_branch2" do
-    a = CommitsHelper::find_commit_range('active/foo', nil, 'b1', nil)
-    assert_equal ['1de84a854e2b440dc53bf42f8548afa4c17da332'], a
-
-    #test "test_branch3" do
-    a = CommitsHelper::find_commit_range('active/foo', nil, 'HEAD', nil)
-    assert_equal ['1de84a854e2b440dc53bf42f8548afa4c17da332'], a
-
-    #test "test_single_revision_repo" do
-    a = CommitsHelper::find_commit_range('active/foo', nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556', nil)
-    assert_equal ['31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
-    a = CommitsHelper::find_commit_range('arvados', nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556', nil)
-    assert_equal [], a
-
-    #test "test_multi_revision" do
-    # complains "fatal: bad object 077ba2ad3ea24a929091a9e6ce545c93199b8e57"
-    a = CommitsHelper::find_commit_range('active/foo', '31ce37fe365b3dc204300a3e4c396ad333ed0556', '077ba2ad3ea24a929091a9e6ce545c93199b8e57', nil)
-    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '4fe459abe02d9b365932b8f5dc419439ab4e2577', '31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
-
-    #test "test_tag" do
-    # complains "fatal: ambiguous argument 'tag1': unknown revision or path
-    # not in the working tree."
-    a = CommitsHelper::find_commit_range('active/foo', 'tag1', 'main', nil)
-    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '4fe459abe02d9b365932b8f5dc419439ab4e2577'], a
-
-    #test "test_multi_revision_exclude" do
-    a = CommitsHelper::find_commit_range('active/foo', '31ce37fe365b3dc204300a3e4c396ad333ed0556', '077ba2ad3ea24a929091a9e6ce545c93199b8e57', ['4fe459abe02d9b365932b8f5dc419439ab4e2577'])
-    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
-
-    #test "test_multi_revision_tagged_exclude" do
-    # complains "fatal: bad object 077ba2ad3ea24a929091a9e6ce545c93199b8e57"
-    a = CommitsHelper::find_commit_range('active/foo', '31ce37fe365b3dc204300a3e4c396ad333ed0556', '077ba2ad3ea24a929091a9e6ce545c93199b8e57', ['tag1'])
-    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
-
-    Dir.mktmpdir do |touchdir|
-      # invalid input to maximum
-      a = CommitsHelper::find_commit_range('active/foo', nil, "31ce37fe365b3dc204300a3e4c396ad333ed0556 ; touch #{touchdir}/uh_oh", nil)
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'maximum' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-
-      # invalid input to maximum
-      a = CommitsHelper::find_commit_range('active/foo', nil, "$(uname>#{touchdir}/uh_oh)", nil)
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'maximum' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-
-      # invalid input to minimum
-      a = CommitsHelper::find_commit_range('active/foo', "31ce37fe365b3dc204300a3e4c396ad333ed0556 ; touch #{touchdir}/uh_oh", "31ce37fe365b3dc204300a3e4c396ad333ed0556", nil)
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'minimum' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-
-      # invalid input to minimum
-      a = CommitsHelper::find_commit_range('active/foo', "$(uname>#{touchdir}/uh_oh)", "31ce37fe365b3dc204300a3e4c396ad333ed0556", nil)
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'minimum' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-
-      # invalid input to 'excludes'
-      # complains "fatal: bad object 077ba2ad3ea24a929091a9e6ce545c93199b8e57"
-      a = CommitsHelper::find_commit_range('active/foo', "31ce37fe365b3dc204300a3e4c396ad333ed0556", "077ba2ad3ea24a929091a9e6ce545c93199b8e57", ["4fe459abe02d9b365932b8f5dc419439ab4e2577 ; touch #{touchdir}/uh_oh"])
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'excludes' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-
-      # invalid input to 'excludes'
-      # complains "fatal: bad object 077ba2ad3ea24a929091a9e6ce545c93199b8e57"
-      a = CommitsHelper::find_commit_range('active/foo', "31ce37fe365b3dc204300a3e4c396ad333ed0556", "077ba2ad3ea24a929091a9e6ce545c93199b8e57", ["$(uname>#{touchdir}/uh_oh)"])
-      assert !File.exist?("#{touchdir}/uh_oh"), "#{touchdir}/uh_oh should not exist, 'excludes' parameter of find_commit_range is exploitable"
-      assert_equal [], a
-    end
-  end
-end
index 60dcb48f18e0d1745692f7b008b2211e42b8cafe..88496b793f22ca26d3a3857d2fc9a14a84b6ce1d 100644 (file)
@@ -335,7 +335,7 @@ class ContainerTest < ActiveSupport::TestCase
     set_user_from_auth :dispatch1
 
     out1 = '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'
-    log1 = collections(:real_log_collection).portable_data_hash
+    log1 = collections(:log_collection).portable_data_hash
     c_output1.update!({state: Container::Locked})
     c_output1.update!({state: Container::Running})
     c_output1.update!(completed_attrs.merge({log: log1, output: out1}))
@@ -847,7 +847,7 @@ class ContainerTest < ActiveSupport::TestCase
     assert c.lock, show_errors(c)
     assert c.update(
              state: Container::Cancelled,
-             log: collections(:real_log_collection).portable_data_hash,
+             log: collections(:log_collection).portable_data_hash,
            ), show_errors(c)
     check_no_change_from_cancelled c
   end
@@ -935,7 +935,7 @@ class ContainerTest < ActiveSupport::TestCase
 
   test "locked_by_uuid can update log when locked/running, and output when running" do
     set_user_from_auth :active
-    logcoll = collections(:real_log_collection)
+    logcoll = collections(:container_log_collection)
     c, cr1 = minimal_new
     cr2 = ContainerRequest.new(DEFAULT_ATTRS)
     cr2.state = ContainerRequest::Committed
@@ -977,8 +977,8 @@ class ContainerTest < ActiveSupport::TestCase
     assert_equal cr1log_uuid, cr1.log_uuid
     assert_equal cr2log_uuid, cr2.log_uuid
     assert_equal 1, Collection.where(uuid: [cr1log_uuid, cr2log_uuid]).to_a.collect(&:portable_data_hash).uniq.length
-    assert_equal ". acbd18db4cc2f85cedef654fccc4a4d8+3 cdd549ae79fe6640fa3d5c6261d8303c+195 0:3:foo.txt 3:195:zzzzz-8i9sb-0vsrcqi7whchuil.log.txt
-./log\\040for\\040container\\040#{cr1.container_uuid} acbd18db4cc2f85cedef654fccc4a4d8+3 cdd549ae79fe6640fa3d5c6261d8303c+195 0:3:foo.txt 3:195:zzzzz-8i9sb-0vsrcqi7whchuil.log.txt
+    assert_equal ". 8c12f5f5297b7337598170c6f531fcee+7882 acbd18db4cc2f85cedef654fccc4a4d8+3 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 7882:3:foo.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt
+./log\\040for\\040container\\040#{cr1.container_uuid} 8c12f5f5297b7337598170c6f531fcee+7882 acbd18db4cc2f85cedef654fccc4a4d8+3 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 7882:3:foo.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt
 ", Collection.find_by_uuid(cr1log_uuid).manifest_text
   end
 
@@ -1015,7 +1015,7 @@ class ContainerTest < ActiveSupport::TestCase
       assert c.update(runtime_status: {'warning' => 'something happened'})
       assert c.update(progress: 0.5)
       assert c.update(exit_code: 0)
-      refute c.update(log: collections(:real_log_collection).portable_data_hash)
+      refute c.update(log: collections(:log_collection).portable_data_hash)
       c.reload
       assert c.update(state: Container::Complete, exit_code: 0)
     end
index 36f42006ff11511c3549286e31bdb21897cc1fbf..e03ca8da05eebd48d14c318adc55a7b9ab4e9877 100644 (file)
@@ -18,13 +18,13 @@ class GroupTest < ActiveSupport::TestCase
     assert g.save, "active user should be able to modify group #{g.uuid}"
 
     # Use the group as the owner of a new object
-    s = Specimen.
+    s = Collection.
       create(owner_uuid: groups(:bad_group_has_ownership_cycle_b).uuid)
     assert s.valid?, "ownership should pass validation #{s.errors.messages}"
     assert_equal false, s.save, "should not save object with #{g.uuid} as owner"
 
     # Use the group as the new owner of an existing object
-    s = specimens(:in_aproject)
+    s = collections(:collection_owned_by_active)
     s.owner_uuid = groups(:bad_group_has_ownership_cycle_b).uuid
     assert s.valid?, "ownership should pass validation"
     assert_equal false, s.save, "should not save object with #{g.uuid} as owner"
diff --git a/services/api/test/unit/helpers/api_client_authorizations_helper_test.rb b/services/api/test/unit/helpers/api_client_authorizations_helper_test.rb
deleted file mode 100644 (file)
index 01ed430..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class ApiClientAuthorizationsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/api_clients_helper_test.rb b/services/api/test/unit/helpers/api_clients_helper_test.rb
deleted file mode 100644 (file)
index 4901fb4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class ApiClientsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/authorized_keys_helper_test.rb b/services/api/test/unit/helpers/authorized_keys_helper_test.rb
deleted file mode 100644 (file)
index 010a0fe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class AuthorizedKeysHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/collections_helper_test.rb b/services/api/test/unit/helpers/collections_helper_test.rb
deleted file mode 100644 (file)
index dd01ca7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class CollectionsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/commit_ancestors_helper_test.rb b/services/api/test/unit/helpers/commit_ancestors_helper_test.rb
deleted file mode 100644 (file)
index 423dbf6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class CommitAncestorsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/commits_helper_test.rb b/services/api/test/unit/helpers/commits_helper_test.rb
deleted file mode 100644 (file)
index fd960a8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class CommitsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/groups_helper_test.rb b/services/api/test/unit/helpers/groups_helper_test.rb
deleted file mode 100644 (file)
index ce7a3fa..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class GroupsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/humans_helper_test.rb b/services/api/test/unit/helpers/humans_helper_test.rb
deleted file mode 100644 (file)
index 22f9e81..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class HumansHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/job_tasks_helper_test.rb b/services/api/test/unit/helpers/job_tasks_helper_test.rb
deleted file mode 100644 (file)
index af0302c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class JobTasksHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/jobs_helper_test.rb b/services/api/test/unit/helpers/jobs_helper_test.rb
deleted file mode 100644 (file)
index 9d64b7d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class JobsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/keep_disks_helper_test.rb b/services/api/test/unit/helpers/keep_disks_helper_test.rb
deleted file mode 100644 (file)
index 9dcc619..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class KeepDisksHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/links_helper_test.rb b/services/api/test/unit/helpers/links_helper_test.rb
deleted file mode 100644 (file)
index 918f145..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class LinksHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/logs_helper_test.rb b/services/api/test/unit/helpers/logs_helper_test.rb
deleted file mode 100644 (file)
index 616f6e6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class LogsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/nodes_helper_test.rb b/services/api/test/unit/helpers/nodes_helper_test.rb
deleted file mode 100644 (file)
index 8a92eb9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class NodesHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/pipeline_instances_helper_test.rb b/services/api/test/unit/helpers/pipeline_instances_helper_test.rb
deleted file mode 100644 (file)
index 9d3b5c4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class PipelineInstancesHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/pipeline_templates_helper_test.rb b/services/api/test/unit/helpers/pipeline_templates_helper_test.rb
deleted file mode 100644 (file)
index 9a9a417..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class PipelinesHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/repositories_helper_test.rb b/services/api/test/unit/helpers/repositories_helper_test.rb
deleted file mode 100644 (file)
index 33cb590..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class RepositoriesHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/specimens_helper_test.rb b/services/api/test/unit/helpers/specimens_helper_test.rb
deleted file mode 100644 (file)
index 3709198..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class SpecimensHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/traits_helper_test.rb b/services/api/test/unit/helpers/traits_helper_test.rb
deleted file mode 100644 (file)
index 03b6a97..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class TraitsHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/helpers/virtual_machines_helper_test.rb b/services/api/test/unit/helpers/virtual_machines_helper_test.rb
deleted file mode 100644 (file)
index 99fc258..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class VirtualMachinesHelperTest < ActionView::TestCase
-end
diff --git a/services/api/test/unit/human_test.rb b/services/api/test/unit/human_test.rb
deleted file mode 100644 (file)
index 83cc40e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class HumanTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
-end
diff --git a/services/api/test/unit/job_task_test.rb b/services/api/test/unit/job_task_test.rb
deleted file mode 100644 (file)
index 36a0e72..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class JobTaskTest < ActiveSupport::TestCase
-
-end
diff --git a/services/api/test/unit/job_test.rb b/services/api/test/unit/job_test.rb
deleted file mode 100644 (file)
index 815079f..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-require 'helpers/git_test_helper'
-require 'helpers/docker_migration_helper'
-
-class JobTest < ActiveSupport::TestCase
-  include DockerMigrationHelper
-  include GitTestHelper
-
-  BAD_COLLECTION = "#{'f' * 32}+0"
-
-  setup do
-    set_user_from_auth :active
-  end
-
-  def job_attrs merge_me={}
-    # Default (valid) set of attributes, with given overrides
-    {
-      script: "hash",
-      script_version: "main",
-      repository: "active/foo",
-    }.merge(merge_me)
-  end
-
-  test "Job without Docker image doesn't get locator" do
-    job = Job.new job_attrs
-    assert job.valid?, job.errors.full_messages.to_s
-    assert_nil job.docker_image_locator
-  end
-
-  { 'name' => [:links, :docker_image_collection_tag, :name],
-    'hash' => [:links, :docker_image_collection_hash, :name],
-    'locator' => [:collections, :docker_image, :portable_data_hash],
-  }.each_pair do |spec_type, (fixture_type, fixture_name, fixture_attr)|
-    test "Job initialized with Docker image #{spec_type} gets locator" do
-      image_spec = send(fixture_type, fixture_name).send(fixture_attr)
-      job = Job.new job_attrs(runtime_constraints:
-                              {'docker_image' => image_spec})
-      assert job.valid?, job.errors.full_messages.to_s
-      assert_equal(collections(:docker_image).portable_data_hash, job.docker_image_locator)
-    end
-
-    test "Job modified with Docker image #{spec_type} gets locator" do
-      job = Job.new job_attrs
-      assert job.valid?, job.errors.full_messages.to_s
-      assert_nil job.docker_image_locator
-      image_spec = send(fixture_type, fixture_name).send(fixture_attr)
-      job.runtime_constraints['docker_image'] = image_spec
-      assert job.valid?, job.errors.full_messages.to_s
-      assert_equal(collections(:docker_image).portable_data_hash, job.docker_image_locator)
-    end
-  end
-
-  test "removing a Docker runtime constraint removes the locator" do
-    image_locator = collections(:docker_image).portable_data_hash
-    job = Job.new job_attrs(runtime_constraints:
-                            {'docker_image' => image_locator})
-    assert job.valid?, job.errors.full_messages.to_s
-    assert_equal(image_locator, job.docker_image_locator)
-    job.runtime_constraints = {}
-    assert job.valid?, job.errors.full_messages.to_s + "after clearing runtime constraints"
-    assert_nil job.docker_image_locator
-  end
-
-  test "locate a Docker image with a repository + tag" do
-    image_repo, image_tag =
-      links(:docker_image_collection_tag2).name.split(':', 2)
-    job = Job.new job_attrs(runtime_constraints:
-                            {'docker_image' => image_repo,
-                              'docker_image_tag' => image_tag})
-    assert job.valid?, job.errors.full_messages.to_s
-    assert_equal(collections(:docker_image).portable_data_hash, job.docker_image_locator)
-  end
-
-  test "can't locate a Docker image with a nonexistent tag" do
-    image_repo = links(:docker_image_collection_tag).name
-    image_tag = '__nonexistent tag__'
-    job = Job.new job_attrs(runtime_constraints:
-                            {'docker_image' => image_repo,
-                              'docker_image_tag' => image_tag})
-    assert(job.invalid?, "Job with bad Docker tag valid")
-  end
-
-  [
-    false,
-    true
-  ].each do |use_config|
-    test "Job with no Docker image uses default docker image when configuration is set #{use_config}" do
-      default_docker_image = collections(:docker_image)[:portable_data_hash]
-      Rails.configuration.Containers.JobsAPI.DefaultDockerImage = default_docker_image if use_config
-
-      job = Job.new job_attrs
-      assert job.valid?, job.errors.full_messages.to_s
-
-      if use_config
-        refute_nil job.docker_image_locator
-        assert_equal default_docker_image, job.docker_image_locator
-      else
-        assert_nil job.docker_image_locator
-      end
-    end
-  end
-
-  test "locate a Docker image with a partial hash" do
-    image_hash = links(:docker_image_collection_hash).name[0..24]
-    job = Job.new job_attrs(runtime_constraints:
-                            {'docker_image' => image_hash})
-    assert job.valid?, job.errors.full_messages.to_s + " with partial hash #{image_hash}"
-    assert_equal(collections(:docker_image).portable_data_hash, job.docker_image_locator)
-  end
-
-  { 'name' => 'arvados_test_nonexistent',
-    'hash' => 'f' * 64,
-    'locator' => BAD_COLLECTION,
-  }.each_pair do |spec_type, image_spec|
-    test "Job validation fails with nonexistent Docker image #{spec_type}" do
-      Rails.configuration.RemoteClusters = ConfigLoader.to_OrderedOptions({})
-      job = Job.new job_attrs(runtime_constraints:
-                              {'docker_image' => image_spec})
-      assert(job.invalid?, "nonexistent Docker image #{spec_type} #{image_spec} was valid")
-    end
-  end
-
-  test "Job validation fails with non-Docker Collection constraint" do
-    job = Job.new job_attrs(runtime_constraints:
-                            {'docker_image' => collections(:foo_file).uuid})
-    assert(job.invalid?, "non-Docker Collection constraint was valid")
-  end
-
-  test "can create Job with Docker image Collection without Docker links" do
-    image_uuid = collections(:unlinked_docker_image).portable_data_hash
-    job = Job.new job_attrs(runtime_constraints: {"docker_image" => image_uuid})
-    assert(job.valid?, "Job created with unlinked Docker image was invalid")
-    assert_equal(image_uuid, job.docker_image_locator)
-  end
-
-  def check_attrs_unset(job, attrs)
-    assert_empty(attrs.each_key.map { |key| job.send(key) }.compact,
-                 "job has values for #{attrs.keys}")
-  end
-
-  def check_creation_prohibited(attrs)
-    begin
-      job = Job.new(job_attrs(attrs))
-    rescue ActiveModel::MassAssignmentSecurity::Error
-      # Test passes - expected attribute protection
-    else
-      check_attrs_unset(job, attrs)
-    end
-  end
-
-  def check_modification_prohibited(attrs)
-    job = Job.new(job_attrs)
-    attrs.each_pair do |key, value|
-      assert_raises(NoMethodError) { job.send("{key}=".to_sym, value) }
-    end
-    check_attrs_unset(job, attrs)
-  end
-
-  test "can't create Job with Docker image locator" do
-    check_creation_prohibited(docker_image_locator: BAD_COLLECTION)
-  end
-
-  test "can't assign Docker image locator to Job" do
-    check_modification_prohibited(docker_image_locator: BAD_COLLECTION)
-  end
-
-  SDK_MASTER = "ca68b24e51992e790f29df5cc4bc54ce1da4a1c2"
-  SDK_TAGGED = "00634b2b8a492d6f121e3cf1d6587b821136a9a7"
-
-  def sdk_constraint(version)
-    {runtime_constraints: {
-        "arvados_sdk_version" => version,
-        "docker_image" => links(:docker_image_collection_tag).name,
-      }}
-  end
-
-  def check_job_sdk_version(expected)
-    job = yield
-    if expected.nil?
-      refute(job.valid?, "job valid with bad Arvados SDK version")
-    else
-      assert(job.valid?, "job not valid with good Arvados SDK version")
-      assert_equal(expected, job.arvados_sdk_version)
-    end
-  end
-
-  test "can't create job with SDK version assigned directly" do
-    check_creation_prohibited(arvados_sdk_version: SDK_MASTER)
-  end
-
-  test "can't modify job to assign SDK version directly" do
-    check_modification_prohibited(arvados_sdk_version: SDK_MASTER)
-  end
-
-  test 'script_parameters_digest is independent of key order' do
-    j1 = Job.new(job_attrs(script_parameters: {'a' => 'a', 'ddee' => {'d' => 'd', 'e' => 'e'}}))
-    j2 = Job.new(job_attrs(script_parameters: {'ddee' => {'e' => 'e', 'd' => 'd'}, 'a' => 'a'}))
-    assert j1.valid?
-    assert j2.valid?
-    assert_equal(j1.script_parameters_digest, j2.script_parameters_digest)
-  end
-
-  test 'job fixtures have correct script_parameters_digest' do
-    Job.all.each do |j|
-      d = j.script_parameters_digest
-      assert_equal(j.update_script_parameters_digest, d,
-                   "wrong script_parameters_digest for #{j.uuid}")
-    end
-  end
-
-  test 'deep_sort_hash on array of hashes' do
-    a = {'z' => [[{'a' => 'a', 'b' => 'b'}]]}
-    b = {'z' => [[{'b' => 'b', 'a' => 'a'}]]}
-    assert_equal Job.deep_sort_hash(a).to_json, Job.deep_sort_hash(b).to_json
-  end
-
-  def try_find_reusable
-    foobar = jobs(:foobar)
-    example_attrs = {
-      script_version: foobar.script_version,
-      script: foobar.script,
-      script_parameters: foobar.script_parameters,
-      repository: foobar.repository,
-    }
-
-    # Two matching jobs exist with identical outputs. The older one
-    # should be reused.
-    j = Job.find_reusable(example_attrs, {}, [], [users(:active)])
-    assert j
-    assert_equal foobar.uuid, j.uuid
-
-    # Two matching jobs exist with different outputs. Neither should
-    # be reused.
-    Job.where(uuid: jobs(:job_with_latest_version).uuid).
-      update_all(output: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+1')
-    assert_nil Job.find_reusable(example_attrs, {}, [], [users(:active)])
-
-    # ...unless config says to reuse the earlier job in such cases.
-    Rails.configuration.Containers.JobsAPI.ReuseJobIfOutputsDiffer = true
-    j = Job.find_reusable(example_attrs, {}, [], [users(:active)])
-    assert_equal foobar.uuid, j.uuid
-  end
-
-  test 'enable legacy api configuration option = true' do
-    Rails.configuration.Containers.JobsAPI.Enable = "true"
-    check_enable_legacy_jobs_api
-    assert_equal(Disable_update_jobs_api_method_list, Rails.configuration.API.DisabledAPIs)
-  end
-
-  test 'enable legacy api configuration option = false' do
-    Rails.configuration.Containers.JobsAPI.Enable = "false"
-    check_enable_legacy_jobs_api
-    assert_equal Disable_jobs_api_method_list, Rails.configuration.API.DisabledAPIs
-  end
-
-  test 'enable legacy api configuration option = auto, has jobs' do
-    Rails.configuration.Containers.JobsAPI.Enable = "auto"
-    assert Job.count > 0
-    check_enable_legacy_jobs_api
-    assert_equal(Disable_update_jobs_api_method_list, Rails.configuration.API.DisabledAPIs)
-  end
-
-  test 'enable legacy api configuration option = auto, no jobs' do
-    Rails.configuration.Containers.JobsAPI.Enable = "auto"
-    act_as_system_user do
-      Job.destroy_all
-    end
-    assert_equal 0, Job.count
-    assert_equal({}, Rails.configuration.API.DisabledAPIs)
-    check_enable_legacy_jobs_api
-    assert_equal Disable_jobs_api_method_list, Rails.configuration.API.DisabledAPIs
-  end
-end
index b9806486adb381596b024a2ff2258d2d91b164b1..fb0d0283377a6828a972629edc8447f1177a3bc3 100644 (file)
@@ -13,7 +13,7 @@ class LinkTest < ActiveSupport::TestCase
 
   test "cannot delete an object referenced by unwritable links" do
     ob = act_as_user users(:active) do
-      Specimen.create
+      Collection.create
     end
     link = act_as_user users(:admin) do
       Link.create(tail_uuid: users(:active).uuid,
index d3a1b618d5e8d7ff9ed1c160627a468641997f5e..e69f0517e451577b548400d59d0666a97a7a2211 100644 (file)
@@ -32,6 +32,10 @@ class LogTest < ActiveSupport::TestCase
     Log.where(object_uuid: thing.uuid).order("created_at ASC").all
   end
 
+  def clear_logs_about(thing)
+    Log.where(object_uuid: thing.uuid).delete_all
+  end
+
   def assert_logged(thing, event_type)
     logs = get_logs_about(thing)
     assert_equal(@log_count, logs.size, "log count mismatch")
@@ -106,10 +110,11 @@ class LogTest < ActiveSupport::TestCase
 
   test "old_attributes preserves values deep inside a hash" do
     set_user_from_auth :active
-    it = specimens(:owned_by_active_user)
+    it = collections(:collection_owned_by_active)
+    clear_logs_about it
     it.properties = {'foo' => {'bar' => ['baz', 'qux', {'quux' => 'bleat'}]}}
     it.save!
-    @log_count += 1
+    assert_logged it, :update
     it.properties['foo']['bar'][2]['quux'] = 'blert'
     it.save!
     assert_logged it, :update do |props|
@@ -231,6 +236,7 @@ class LogTest < ActiveSupport::TestCase
   test "don't log changes only to Collection.preserve_version" do
     set_user_from_auth :admin_trustedclient
     col = collections(:collection_owned_by_active)
+    clear_logs_about col
     start_log_count = get_logs_about(col).size
     assert_equal false, col.preserve_version
     col.preserve_version = true
@@ -258,27 +264,29 @@ class LogTest < ActiveSupport::TestCase
 
   test "use ownership and permission links to determine which logs a user can see" do
     known_logs = [:noop,
-                  :admin_changes_repository2,
-                  :admin_changes_specimen,
+                  :admin_changes_collection_owned_by_active,
+                  :admin_changes_collection_owned_by_foo,
                   :system_adds_foo_file,
                   :system_adds_baz,
                   :log_owned_by_active,
-                  :crunchstat_for_running_job]
+                  :crunchstat_for_running_container]
 
     c = Log.readable_by(users(:admin)).order("id asc").each.to_a
     assert_log_result c, known_logs, known_logs
 
     c = Log.readable_by(users(:active)).order("id asc").each.to_a
-    assert_log_result c, known_logs, [:admin_changes_repository2, # owned by active
-                                      :system_adds_foo_file,      # readable via link
-                                      :system_adds_baz,           # readable via 'all users' group
-                                      :log_owned_by_active,       # log owned by active
-                                      :crunchstat_for_running_job] # log & job owned by active
+    assert_log_result c, known_logs, [:admin_changes_collection_owned_by_active,
+                                      :system_adds_foo_file,             # readable via link
+                                      :system_adds_baz,                  # readable via 'all users' group
+                                      :log_owned_by_active,              # log owned by active
+                                      :crunchstat_for_running_container] # log & job owned by active
 
     c = Log.readable_by(users(:spectator)).order("id asc").each.to_a
-    assert_log_result c, known_logs, [:noop,                   # object_uuid is spectator
-                                      :admin_changes_specimen, # object_uuid is a specimen owned by spectator
-                                      :system_adds_baz] # readable via 'all users' group
+    assert_log_result c, known_logs, [:noop,                             # object_uuid is spectator
+                                      :system_adds_baz]                  # readable via 'all users' group
+
+    c = Log.readable_by(users(:user_foo_in_sharing_group)).order("id asc").each.to_a
+    assert_log_result c, known_logs, [:admin_changes_collection_owned_by_foo] # collection's parent is readable via role group
   end
 
   def assert_log_result result, known_logs, expected_logs
index 1c1bd93b8169484b78ffe4948c69512c1c89bc4b..a96170c7162e137d0817eccfce67f3f5a069db25 100644 (file)
@@ -11,7 +11,7 @@ require 'test_helper'
 # "i" is an item.
 
 class OwnerTest < ActiveSupport::TestCase
-  fixtures :users, :groups, :specimens
+  fixtures :users, :groups
 
   setup do
     set_user_from_auth :admin_trustedclient
@@ -26,22 +26,22 @@ class OwnerTest < ActiveSupport::TestCase
       else
         o = o_class.create!
       end
-      i = Specimen.create(owner_uuid: o.uuid)
+      i = Collection.create(owner_uuid: o.uuid)
       assert i.valid?, "new item should pass validation"
       assert i.uuid, "new item should have an ID"
-      assert Specimen.where(uuid: i.uuid).any?, "new item should really be in DB"
+      assert Collection.where(uuid: i.uuid).any?, "new item should really be in DB"
     end
 
     test "create object with non-existent #{o_class} owner" do
       assert_raises(ActiveRecord::RecordInvalid,
                     "create should fail with random owner_uuid") do
-        Specimen.create!(owner_uuid: o_class.generate_uuid)
+        Collection.create!(owner_uuid: o_class.generate_uuid)
       end
 
-      i = Specimen.create(owner_uuid: o_class.generate_uuid)
+      i = Collection.create(owner_uuid: o_class.generate_uuid)
       assert !i.valid?, "object with random owner_uuid should not be valid?"
 
-      i = Specimen.new(owner_uuid: o_class.generate_uuid)
+      i = Collection.new(owner_uuid: o_class.generate_uuid)
       assert !i.valid?, "new item should not pass validation"
       assert !i.uuid, "new item should not have an ID"
     end
@@ -53,7 +53,7 @@ class OwnerTest < ActiveSupport::TestCase
             else
               o_class.create!
             end
-        i = Specimen.create!(owner_uuid: o.uuid)
+        i = Collection.create!(owner_uuid: o.uuid)
 
         new_o = if new_o_class == Group
               new_o_class.create! group_class: "project"
@@ -61,7 +61,7 @@ class OwnerTest < ActiveSupport::TestCase
               new_o_class.create!
             end
 
-        assert(Specimen.where(uuid: i.uuid).any?,
+        assert(Collection.where(uuid: i.uuid).any?,
                "new item should really be in DB")
         assert(i.update(owner_uuid: new_o.uuid),
                "should change owner_uuid from #{o.uuid} to #{new_o.uuid}")
@@ -102,7 +102,7 @@ class OwnerTest < ActiveSupport::TestCase
   ['users(:active)', 'groups(:aproject)'].each do |ofixt|
     test "delete #{ofixt} that owns other objects" do
       o = eval ofixt
-      assert_equal(true, Specimen.where(owner_uuid: o.uuid).any?,
+      assert_equal(true, Collection.where(owner_uuid: o.uuid).any?,
                    "need something to be owned by #{o.uuid} for this test")
 
       skip_check_permissions_against_full_refresh do
@@ -115,7 +115,7 @@ class OwnerTest < ActiveSupport::TestCase
 
     test "change uuid of #{ofixt} that owns other objects" do
       o = eval ofixt
-      assert_equal(true, Specimen.where(owner_uuid: o.uuid).any?,
+      assert_equal(true, Collection.where(owner_uuid: o.uuid).any?,
                    "need something to be owned by #{o.uuid} for this test")
       new_uuid = o.uuid.sub(/..........$/, rand(2**256).to_s(36)[0..9])
       assert(!o.update(uuid: new_uuid),
index 14c810d81ae363e4b3f45f166f48a8a11a7898fd..305989606198889f9098923c11d4c72dbe5681cd 100644 (file)
@@ -222,7 +222,7 @@ class PermissionTest < ActiveSupport::TestCase
     Rails.configuration.Users.ActivatedUsersAreVisibleToOthers = false
     manager = create :active_user, first_name: "Manage", last_name: "Er"
     minion = create :active_user, first_name: "Min", last_name: "Ion"
-    minions_specimen = act_as_user minion do
+    minions_collection = act_as_user minion do
       g = Group.create! name: "minon project", group_class: "project"
       Collection.create! owner_uuid: g.uuid
     end
@@ -289,11 +289,11 @@ class PermissionTest < ActiveSupport::TestCase
       end
       assert_empty(Collection
                      .readable_by(manager)
-                     .where(uuid: minions_specimen.uuid),
+                     .where(uuid: minions_collection.uuid),
                    "manager saw the minion's private stuff")
       assert_raises(ArvadosModel::PermissionDeniedError,
                    "manager could update minion's private stuff") do
-        minions_specimen.update(properties: {'x' => 'y'})
+        minions_collection.update(properties: {'x' => 'y'})
       end
     end
 
@@ -307,11 +307,11 @@ class PermissionTest < ActiveSupport::TestCase
       # Now, manager can read and write Minion's stuff.
       assert_not_empty(Collection
                          .readable_by(manager)
-                         .where(uuid: minions_specimen.uuid),
-                       "manager could not find minion's specimen by uuid")
+                         .where(uuid: minions_collection.uuid),
+                       "manager could not find minion's collection by uuid")
       assert_equal(true,
-                   minions_specimen.update(properties: {'x' => 'y'}),
-                   "manager could not update minion's specimen object")
+                   minions_collection.update(properties: {'x' => 'y'}),
+                   "manager could not update minion's collection object")
     end
   end
 
@@ -341,12 +341,12 @@ class PermissionTest < ActiveSupport::TestCase
     assert_not_empty(User.readable_by(a).where(uuid: b.uuid),
                      "#{a.first_name} should be able to see 'b' in the user list")
 
-    a_specimen = act_as_user a do
+    a_collection = act_as_user a do
       Collection.create!
     end
-    assert_not_empty(Collection.readable_by(a).where(uuid: a_specimen.uuid),
+    assert_not_empty(Collection.readable_by(a).where(uuid: a_collection.uuid),
                      "A cannot read own Collection, following test probably useless.")
-    assert_empty(Collection.readable_by(b).where(uuid: a_specimen.uuid),
+    assert_empty(Collection.readable_by(b).where(uuid: a_collection.uuid),
                  "B can read A's Collection")
     [a,b].each do |u|
       assert_empty(User.readable_by(u).where(uuid: other.uuid),
diff --git a/services/api/test/unit/pipeline_instance_test.rb b/services/api/test/unit/pipeline_instance_test.rb
deleted file mode 100644 (file)
index 614c169..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class PipelineInstanceTest < ActiveSupport::TestCase
-
-  [:has_component_with_no_script_parameters,
-   :has_component_with_empty_script_parameters].each do |pi_name|
-    test "update pipeline that #{pi_name}" do
-      pi = pipeline_instances pi_name
-
-      Thread.current[:user] = users(:active)
-      assert_equal PipelineInstance::Ready, pi.state
-    end
-  end
-end
diff --git a/services/api/test/unit/pipeline_template_test.rb b/services/api/test/unit/pipeline_template_test.rb
deleted file mode 100644 (file)
index 8ead613..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class PipelineTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
-end
diff --git a/services/api/test/unit/repository_test.rb b/services/api/test/unit/repository_test.rb
deleted file mode 100644 (file)
index 674a34f..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-require 'helpers/git_test_helper'
-
-class RepositoryTest < ActiveSupport::TestCase
-  include GitTestHelper
-
-  def new_repo(owner_key, attrs={})
-    set_user_from_auth owner_key
-    owner = users(owner_key)
-    Repository.new({owner_uuid: owner.uuid}.merge(attrs))
-  end
-
-  def changed_repo(repo_key, changes)
-    repo = repositories(repo_key)
-    changes.each_pair { |attr, value| repo.send("#{attr}=".to_sym, value) }
-    repo
-  end
-
-  def default_git_url(repo_name, user_name=nil)
-    if user_name
-      "git@git.%s.arvadosapi.com:%s/%s.git" %
-        [Rails.configuration.ClusterID, user_name, repo_name]
-    else
-      "git@git.%s.arvadosapi.com:%s.git" %
-        [Rails.configuration.ClusterID, repo_name]
-    end
-  end
-
-  def assert_server_path(path_tail, repo_sym)
-    assert_equal(File.join(Rails.configuration.Git.Repositories, path_tail),
-                 repositories(repo_sym).server_path)
-  end
-
-  ### name validation
-
-  {active: "active/", admin: "admin/", system_user: ""}.
-      each_pair do |user_sym, name_prefix|
-    test "valid names for #{user_sym} repo" do
-      %w(a aa a0 aA Aa AA A0).each do |name|
-        repo = new_repo(user_sym, name: name_prefix + name)
-        assert(repo.valid?)
-      end
-    end
-
-    test "name is required for #{user_sym} repo" do
-      refute(new_repo(user_sym).valid?)
-    end
-
-    test "repo name beginning with numeral is invalid for #{user_sym}" do
-      repo = new_repo(user_sym, name: "#{name_prefix}0a")
-      refute(repo.valid?)
-    end
-
-    test "name containing bad char is invalid for #{user_sym}" do
-      "\\.-_/!@#$%^&*()[]{}".each_char do |bad_char|
-        repo = new_repo(user_sym, name: "#{name_prefix}bad#{bad_char}reponame")
-        refute(repo.valid?)
-      end
-    end
-  end
-
-  test "admin can create valid repo for other user with correct name prefix" do
-    owner = users(:active)
-    repo = new_repo(:admin, name: "#{owner.username}/validnametest",
-                    owner_uuid: owner.uuid)
-    assert(repo.valid?)
-  end
-
-  test "admin can create valid system repo without name prefix" do
-    repo = new_repo(:admin, name: "validnametest",
-                    owner_uuid: users(:system_user).uuid)
-    assert(repo.valid?)
-  end
-
-  test "repo name prefix must match owner_uuid username" do
-    repo = new_repo(:admin, name: "admin/badusernametest",
-                    owner_uuid: users(:active).uuid)
-    refute(repo.valid?)
-  end
-
-  test "repo name prefix must be empty for system repo" do
-    repo = new_repo(:admin, name: "root/badprefixtest",
-                    owner_uuid: users(:system_user).uuid)
-    refute(repo.valid?)
-  end
-
-  ### owner validation
-
-  test "name must be unique per user" do
-    repo = new_repo(:active, name: repositories(:foo).name)
-    refute(repo.valid?)
-  end
-
-  test "name can be duplicated across users" do
-    repo = new_repo(:active, name: "active/#{repositories(:arvados).name}")
-    assert(repo.valid?)
-  end
-
-  test "repository cannot be owned by a group" do
-    set_user_from_auth :active
-    repo = Repository.new(owner_uuid: groups(:all_users).uuid,
-                          name: "ownedbygroup")
-    refute(repo.valid?)
-    refute_empty(repo.errors[:owner_uuid] || [])
-  end
-
-  ### URL generation
-
-  test "fetch_url" do
-    repo = new_repo(:active, name: "active/fetchtest")
-    repo.save
-    assert_equal(default_git_url("fetchtest", "active"), repo.fetch_url)
-  end
-
-  test "fetch_url owned by system user" do
-    set_user_from_auth :admin
-    repo = Repository.new(owner_uuid: users(:system_user).uuid,
-                          name: "fetchtest")
-    repo.save
-    assert_equal(default_git_url("fetchtest"), repo.fetch_url)
-  end
-
-  test "push_url" do
-    repo = new_repo(:active, name: "active/pushtest")
-    repo.save
-    assert_equal(default_git_url("pushtest", "active"), repo.push_url)
-  end
-
-  test "push_url owned by system user" do
-    set_user_from_auth :admin
-    repo = Repository.new(owner_uuid: users(:system_user).uuid,
-                          name: "pushtest")
-    repo.save
-    assert_equal(default_git_url("pushtest"), repo.push_url)
-  end
-
-  ### Path generation
-
-  test "disk path stored by UUID" do
-    assert_server_path("zzzzz-s0uqq-382brsig8rp3666/.git", :foo)
-  end
-
-  test "disk path stored by name" do
-    assert_server_path("arvados/.git", :arvados)
-  end
-
-  test "disk path for repository not on disk" do
-    assert_nil(Repository.new.server_path)
-  end
-
-  ### Repository creation
-
-  test "non-admin can create a repository for themselves" do
-    repo = new_repo(:active, name: "active/newtestrepo")
-    assert(repo.save)
-  end
-
-  test "non-admin can't create a repository for another visible user" do
-    repo = new_repo(:active, name: "repoforanon",
-                    owner_uuid: users(:anonymous).uuid)
-    assert_not_allowed { repo.save }
-  end
-
-  test "admin can create a repository for themselves" do
-    repo = new_repo(:admin, name: "admin/newtestrepo")
-    assert(repo.save)
-  end
-
-  test "admin can create a repository for others" do
-    repo = new_repo(:admin, name: "active/repoforactive",
-                    owner_uuid: users(:active).uuid)
-    assert(repo.save)
-  end
-
-  test "admin can create a system repository" do
-    repo = new_repo(:admin, name: "repoforsystem",
-                    owner_uuid: users(:system_user).uuid)
-    assert(repo.save)
-  end
-
-  ### Repository destruction
-
-  test "non-admin can destroy their own repository" do
-    set_user_from_auth :active
-    assert(repositories(:foo).destroy)
-  end
-
-  test "non-admin can't destroy others' repository" do
-    set_user_from_auth :active
-    assert_not_allowed { repositories(:repository3).destroy }
-  end
-
-  test "non-admin can't destroy system repository" do
-    set_user_from_auth :active
-    assert_not_allowed { repositories(:arvados).destroy }
-  end
-
-  test "admin can destroy their own repository" do
-    set_user_from_auth :admin
-    assert(repositories(:repository3).destroy)
-  end
-
-  test "admin can destroy others' repository" do
-    set_user_from_auth :admin
-    assert(repositories(:foo).destroy)
-  end
-
-  test "admin can destroy system repository" do
-    set_user_from_auth :admin
-    assert(repositories(:arvados).destroy)
-  end
-
-  ### Changing ownership
-
-  test "non-admin can't make their repository a system repository" do
-    set_user_from_auth :active
-    repo = changed_repo(:foo, owner_uuid: users(:system_user).uuid)
-    assert_not_allowed { repo.save }
-  end
-
-  test "admin can give their repository to someone else" do
-    set_user_from_auth :admin
-    repo = changed_repo(:repository3, owner_uuid: users(:active).uuid,
-                        name: "active/foo3")
-    assert(repo.save)
-  end
-
-  test "admin can make their repository a system repository" do
-    set_user_from_auth :admin
-    repo = changed_repo(:repository3, owner_uuid: users(:system_user).uuid,
-                        name: "foo3")
-    assert(repo.save)
-  end
-
-  test 'write permission allows changing modified_at' do
-    act_as_user users(:active) do
-      r = repositories(:foo)
-      modtime_was = r.modified_at
-      r.modified_at = Time.now
-      assert r.save
-      assert_operator modtime_was, :<, r.modified_at
-    end
-  end
-
-  test 'write permission necessary for changing modified_at' do
-    act_as_user users(:spectator) do
-      r = repositories(:foo)
-      modtime_was = r.modified_at
-      r.modified_at = Time.now
-      assert_raises ArvadosModel::PermissionDeniedError do
-        r.save!
-      end
-      r.reload
-      assert_equal modtime_was, r.modified_at
-    end
-  end
-
-  ### Renaming
-
-  test "non-admin can rename own repo" do
-    act_as_user users(:active) do
-      assert repositories(:foo).update(name: 'active/foo12345')
-    end
-  end
-
-  test "top level repo can be touched by non-admin with can_manage" do
-    add_permission_link users(:active), repositories(:arvados), 'can_manage'
-    act_as_user users(:active) do
-      assert changed_repo(:arvados, modified_at: Time.now).save
-    end
-  end
-
-  test "top level repo cannot be renamed by non-admin with can_manage" do
-    add_permission_link users(:active), repositories(:arvados), 'can_manage'
-    act_as_user users(:active) do
-      assert_not_allowed { changed_repo(:arvados, name: 'xarvados').save }
-    end
-  end
-end
diff --git a/services/api/test/unit/specimen_test.rb b/services/api/test/unit/specimen_test.rb
deleted file mode 100644 (file)
index 5b2eda2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class SpecimenTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
-end
diff --git a/services/api/test/unit/trait_test.rb b/services/api/test/unit/trait_test.rb
deleted file mode 100644 (file)
index fe63f16..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'test_helper'
-
-class TraitTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
-end
index 810e5b45ecb2e77ad5394d20ffc807fb46d458ea..71b5769be8b87b353b73d8c5851e6ef07d86fd73 100644 (file)
@@ -118,18 +118,7 @@ class UserTest < ActiveSupport::TestCase
     check_new_username_setting("_", nil)
   end
 
-  test "updating username updates repository names" do
-    set_user_from_auth :admin
-    user = users(:active)
-    user.username = "newtestname"
-    assert(user.save, "username update failed")
-    {foo: "newtestname/foo", repository2: "newtestname/foo2"}.
-        each_pair do |repo_sym, expect_name|
-      assert_equal(expect_name, repositories(repo_sym).name)
-    end
-  end
-
-  test "admin can clear username when user owns no repositories" do
+  test "admin can clear username" do
     set_user_from_auth :admin
     user = users(:spectator)
     user.username = nil
@@ -137,22 +126,6 @@ class UserTest < ActiveSupport::TestCase
     assert_nil(user.username)
   end
 
-  test "admin can't clear username when user owns repositories" do
-    set_user_from_auth :admin
-    user = users(:active)
-    user.username = nil
-    assert_not_allowed { user.save }
-    refute_empty(user.errors[:username])
-  end
-
-  test "failed username update doesn't change repository names" do
-    set_user_from_auth :admin
-    user = users(:active)
-    user.username = users(:fuse).username
-    assert_not_allowed { user.save }
-    assert_equal("active/foo", repositories(:foo).name)
-  end
-
   [[false, 'foo@example.com', true, false],
    [false, 'bar@example.com', false, true],
    [true, 'foo@example.com', true, false],
@@ -359,37 +332,33 @@ class UserTest < ActiveSupport::TestCase
 
   [
     # Easy inactive user tests.
-    [false, empty_notify_list, empty_notify_list, "inactive-none@example.com", false, false, "inactivenone"],
-    [false, empty_notify_list, empty_notify_list, "inactive-vm@example.com", true, false, "inactivevm"],
-    [false, empty_notify_list, empty_notify_list, "inactive-repo@example.com", false, true, "inactiverepo"],
-    [false, empty_notify_list, empty_notify_list, "inactive-both@example.com", true, true, "inactiveboth"],
+    [false, empty_notify_list, empty_notify_list, "inactive-none@example.com", false, "inactivenone"],
+    [false, empty_notify_list, empty_notify_list, "inactive-vm@example.com", true, "inactivevm"],
 
     # Easy active user tests.
-    [true, active_notify_list, inactive_notify_list, "active-none@example.com", false, false, "activenone"],
-    [true, active_notify_list, inactive_notify_list, "active-vm@example.com", true, false, "activevm"],
-    [true, active_notify_list, inactive_notify_list, "active-repo@example.com", false, true, "activerepo"],
-    [true, active_notify_list, inactive_notify_list, "active-both@example.com", true, true, "activeboth"],
+    [true, active_notify_list, inactive_notify_list, "active-none@example.com", false, "activenone"],
+    [true, active_notify_list, inactive_notify_list, "active-vm@example.com", true, "activevm"],
 
     # Test users with malformed e-mail addresses.
-    [false, empty_notify_list, empty_notify_list, nil, true, true, nil],
-    [false, empty_notify_list, empty_notify_list, "arvados", true, true, nil],
-    [false, empty_notify_list, empty_notify_list, "@example.com", true, true, nil],
-    [true, active_notify_list, inactive_notify_list, "*!*@example.com", true, false, nil],
-    [true, active_notify_list, inactive_notify_list, "*!*@example.com", false, false, nil],
+    [false, empty_notify_list, empty_notify_list, nil, true, nil],
+    [false, empty_notify_list, empty_notify_list, "arvados", true, nil],
+    [false, empty_notify_list, empty_notify_list, "@example.com", true, nil],
+    [true, active_notify_list, inactive_notify_list, "*!*@example.com", true, nil],
+    [true, active_notify_list, inactive_notify_list, "*!*@example.com", false, nil],
 
     # Test users with various username transformations.
-    [false, empty_notify_list, empty_notify_list, "arvados@example.com", false, false, "arvados2"],
-    [true, active_notify_list, inactive_notify_list, "arvados@example.com", false, false, "arvados2"],
-    [true, active_notify_list, inactive_notify_list, "root@example.com", true, false, "root2"],
-    [false, active_notify_list, empty_notify_list, "root@example.com", true, false, "root2"],
-    [true, active_notify_list, inactive_notify_list, "roo_t@example.com", false, true, "root2"],
-    [false, empty_notify_list, empty_notify_list, "^^incorrect_format@example.com", true, true, "incorrectformat"],
-    [true, active_notify_list, inactive_notify_list, "&4a_d9.@example.com", true, true, "ad9"],
-    [true, active_notify_list, inactive_notify_list, "&4a_d9.@example.com", false, false, "ad9"],
-    [false, active_notify_list, empty_notify_list, "&4a_d9.@example.com", true, true, "ad9"],
-    [false, active_notify_list, empty_notify_list, "&4a_d9.@example.com", false, false, "ad9"],
-  ].each do |active, new_user_recipients, inactive_recipients, email, auto_setup_vm, auto_setup_repo, expect_username|
-    test "create new user with auto setup active=#{active} email=#{email} vm=#{auto_setup_vm} repo=#{auto_setup_repo}" do
+    [false, empty_notify_list, empty_notify_list, "arvados@example.com", false, "arvados2"],
+    [true, active_notify_list, inactive_notify_list, "arvados@example.com", false, "arvados2"],
+    [true, active_notify_list, inactive_notify_list, "root@example.com", true, "root2"],
+    [false, active_notify_list, empty_notify_list, "root@example.com", true, "root2"],
+    [true, active_notify_list, inactive_notify_list, "roo_t@example.com", false, "root2"],
+    [false, empty_notify_list, empty_notify_list, "^^incorrect_format@example.com", true, "incorrectformat"],
+    [true, active_notify_list, inactive_notify_list, "&4a_d9.@example.com", true, "ad9"],
+    [true, active_notify_list, inactive_notify_list, "&4a_d9.@example.com", false, "ad9"],
+    [false, active_notify_list, empty_notify_list, "&4a_d9.@example.com", true, "ad9"],
+    [false, active_notify_list, empty_notify_list, "&4a_d9.@example.com", false, "ad9"],
+  ].each do |active, new_user_recipients, inactive_recipients, email, auto_setup_vm, expect_username|
+    test "create new user with auto setup active=#{active} email=#{email} vm=#{auto_setup_vm}" do
       set_user_from_auth :admin
 
       Rails.configuration.Users.AutoSetupNewUsers = true
@@ -400,8 +369,6 @@ class UserTest < ActiveSupport::TestCase
         Rails.configuration.Users.AutoSetupNewUsersWithVmUUID = ""
       end
 
-      Rails.configuration.Users.AutoSetupNewUsersWithRepository = auto_setup_repo
-
       create_user_and_verify_setup_and_notifications active, new_user_recipients, inactive_recipients, email, expect_username
     end
   end
@@ -460,8 +427,7 @@ class UserTest < ActiveSupport::TestCase
 
       vm = VirtualMachine.create
 
-      response = user.setup(repo_name: 'foo/testrepo',
-                            vm_uuid: vm.uuid)
+      response = user.setup(vm_uuid: vm.uuid)
 
       resp_user = find_obj_in_resp response, 'User'
       verify_user resp_user, email
@@ -476,9 +442,6 @@ class UserTest < ActiveSupport::TestCase
         assert_nil group_perm2
       end
 
-      repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
-      verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
-
       vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
       verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
       assert_equal("foo", vm_perm.properties["username"])
@@ -494,8 +457,7 @@ class UserTest < ActiveSupport::TestCase
 
     vm = VirtualMachine.create
 
-    response = user.setup(repo_name: 'foo/testrepo',
-                          vm_uuid: vm.uuid)
+    response = user.setup(vm_uuid: vm.uuid)
 
     resp_user = find_obj_in_resp response, 'User'
     verify_user resp_user, email
@@ -503,9 +465,6 @@ class UserTest < ActiveSupport::TestCase
     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
     verify_link group_perm, 'permission', 'can_write', resp_user[:uuid], groups(:all_users).uuid
 
-    repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
-    verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
-
     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
     assert_equal("foo", vm_perm.properties["username"])
@@ -529,23 +488,10 @@ class UserTest < ActiveSupport::TestCase
     group_perm2 = find_obj_in_resp response, 'Link', 'arvados#user'
     verify_link group_perm2, 'permission', 'can_read', groups(:all_users).uuid, nil
 
-    # invoke setup again with repo_name
-    response = user.setup(repo_name: 'foo/testrepo')
-    resp_user = find_obj_in_resp response, 'User', nil
-    verify_user resp_user, email
-    assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
-
-    group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
-    verify_link group_perm, 'permission', 'can_write', resp_user[:uuid], groups(:all_users).uuid
-
-    repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
-    verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
-
     # invoke setup again with a vm_uuid
     vm = VirtualMachine.create
 
-    response = user.setup(repo_name: 'foo/testrepo',
-                          vm_uuid: vm.uuid)
+    response = user.setup(vm_uuid: vm.uuid)
 
     resp_user = find_obj_in_resp response, 'User', nil
     verify_user resp_user, email
@@ -554,9 +500,6 @@ class UserTest < ActiveSupport::TestCase
     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
     verify_link group_perm, 'permission', 'can_write', resp_user[:uuid], groups(:all_users).uuid
 
-    repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
-    verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
-
     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
     assert_equal("foo", vm_perm.properties["username"])
@@ -614,8 +557,6 @@ class UserTest < ActiveSupport::TestCase
 
     can_setup = (Rails.configuration.Users.AutoSetupNewUsers and
                  (not expect_username.nil?))
-    expect_repo_name = "#{expect_username}/#{expect_username}"
-    prior_repo = Repository.where(name: expect_repo_name).first
 
     user = User.new
     user.first_name = "first_name_for_newly_created_user"
@@ -629,14 +570,6 @@ class UserTest < ActiveSupport::TestCase
                        groups(:all_users).uuid, user.uuid,
                        "permission", "can_write")
 
-    # Check for repository.
-    if named_repo = (prior_repo or
-                     Repository.where(name: expect_repo_name).first)
-      verify_link_exists((can_setup and prior_repo.nil? and
-                          Rails.configuration.Users.AutoSetupNewUsersWithRepository),
-                         named_repo.uuid, user.uuid, "permission", "can_manage")
-    end
-
     # Check for VM login.
     if (auto_vm_uuid = Rails.configuration.Users.AutoSetupNewUsersWithVmUUID) != ""
       verify_link_exists(can_setup, auto_vm_uuid, user.uuid,
index 046a835893d5117a7497d75f3ac9b12a2ae340f2..89076d72cb834e9507b0d1bff57719140fb26128 100644 (file)
@@ -65,8 +65,8 @@ class TokenExpiryTest(IntegrationTest):
 
     @staticmethod
     def _test_refresh_old_manifest(self, zzz):
-        uuid = 'zzzzz-4zz18-op4e2lbej01tcvu'
-        fnm = 'zzzzz-8i9sb-0vsrcqi7whchuil.log.txt'
+        uuid = 'zzzzz-4zz18-logcollection02'
+        fnm = 'crunch-run.txt'
         os.listdir(os.path.join(zzz, uuid))
         for _ in range(8):
             with open(os.path.join(zzz, uuid, fnm)) as f:
diff --git a/services/githttpd/auth_handler.go b/services/githttpd/auth_handler.go
deleted file mode 100644 (file)
index c6b23fd..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "errors"
-       "log"
-       "net/http"
-       "os"
-       "regexp"
-       "strings"
-       "time"
-
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadosclient"
-       "git.arvados.org/arvados.git/sdk/go/auth"
-       "git.arvados.org/arvados.git/sdk/go/httpserver"
-       "github.com/sirupsen/logrus"
-)
-
-type authHandler struct {
-       handler    http.Handler
-       clientPool *arvadosclient.ClientPool
-       cluster    *arvados.Cluster
-}
-
-func (h *authHandler) CheckHealth() error {
-       return nil
-}
-
-func (h *authHandler) Done() <-chan struct{} {
-       return nil
-}
-
-func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
-       var statusCode int
-       var statusText string
-       var apiToken string
-
-       w := httpserver.WrapResponseWriter(wOrig)
-
-       if r.Method == "OPTIONS" {
-               method := r.Header.Get("Access-Control-Request-Method")
-               if method != "GET" && method != "POST" {
-                       w.WriteHeader(http.StatusMethodNotAllowed)
-                       return
-               }
-               w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
-               w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
-               w.Header().Set("Access-Control-Allow-Origin", "*")
-               w.Header().Set("Access-Control-Max-Age", "86400")
-               w.WriteHeader(http.StatusOK)
-               return
-       }
-
-       if r.Header.Get("Origin") != "" {
-               // Allow simple cross-origin requests without user
-               // credentials ("user credentials" as defined by CORS,
-               // i.e., cookies, HTTP authentication, and client-side
-               // SSL certificates. See
-               // http://www.w3.org/TR/cors/#user-credentials).
-               w.Header().Set("Access-Control-Allow-Origin", "*")
-       }
-
-       defer func() {
-               if w.WroteStatus() == 0 {
-                       // Nobody has called WriteHeader yet: that
-                       // must be our job.
-                       w.WriteHeader(statusCode)
-                       if statusCode >= 400 {
-                               w.Write([]byte(statusText))
-                       }
-               }
-       }()
-
-       creds := auth.CredentialsFromRequest(r)
-       if len(creds.Tokens) == 0 {
-               statusCode, statusText = http.StatusUnauthorized, "no credentials provided"
-               w.Header().Add("WWW-Authenticate", "Basic realm=\"git\"")
-               return
-       }
-       apiToken = creds.Tokens[0]
-
-       // Access to paths "/foo/bar.git/*" and "/foo/bar/.git/*" are
-       // protected by the permissions on the repository named
-       // "foo/bar".
-       pathParts := strings.SplitN(r.URL.Path[1:], ".git/", 2)
-       if len(pathParts) != 2 {
-               statusCode, statusText = http.StatusNotFound, "not found"
-               return
-       }
-       repoName := pathParts[0]
-       repoName = strings.TrimRight(repoName, "/")
-       httpserver.SetResponseLogFields(r.Context(), logrus.Fields{
-               "repoName": repoName,
-       })
-
-       arv := h.clientPool.Get()
-       if arv == nil {
-               statusCode, statusText = http.StatusInternalServerError, "connection pool failed: "+h.clientPool.Err().Error()
-               return
-       }
-       defer h.clientPool.Put(arv)
-
-       // Log the UUID if the supplied token is a v2 token, otherwise
-       // just the last five characters.
-       httpserver.SetResponseLogFields(r.Context(), logrus.Fields{
-               "tokenUUID": func() string {
-                       if strings.HasPrefix(apiToken, "v2/") && strings.IndexRune(apiToken[3:], '/') == 27 {
-                               // UUID part of v2 token
-                               return apiToken[3:30]
-                       } else if len(apiToken) > 5 {
-                               return "[...]" + apiToken[len(apiToken)-5:]
-                       } else {
-                               return apiToken
-                       }
-               }(),
-       })
-
-       // Ask API server whether the repository is readable using
-       // this token (by trying to read it!)
-       arv.ApiToken = apiToken
-       repoUUID, err := h.lookupRepo(arv, repoName)
-       if err != nil {
-               statusCode, statusText = http.StatusInternalServerError, err.Error()
-               return
-       }
-       if repoUUID == "" {
-               statusCode, statusText = http.StatusNotFound, "not found"
-               return
-       }
-
-       isWrite := strings.HasSuffix(r.URL.Path, "/git-receive-pack")
-       if !isWrite {
-               statusText = "read"
-       } else {
-               err := arv.Update("repositories", repoUUID, arvadosclient.Dict{
-                       "repository": arvadosclient.Dict{
-                               "modified_at": time.Now().String(),
-                       },
-               }, &arvadosclient.Dict{})
-               if err != nil {
-                       statusCode, statusText = http.StatusForbidden, err.Error()
-                       return
-               }
-               statusText = "write"
-       }
-
-       // Regardless of whether the client asked for "/foo.git" or
-       // "/foo/.git", we choose whichever variant exists in our repo
-       // root, and we try {uuid}.git and {uuid}/.git first. If none
-       // of these exist, we 404 even though the API told us the repo
-       // _should_ exist (presumably this means the repo was just
-       // created, and gitolite sync hasn't run yet).
-       rewrittenPath := ""
-       tryDirs := []string{
-               "/" + repoUUID + ".git",
-               "/" + repoUUID + "/.git",
-               "/" + repoName + ".git",
-               "/" + repoName + "/.git",
-       }
-       for _, dir := range tryDirs {
-               if fileInfo, err := os.Stat(h.cluster.Git.Repositories + dir); err != nil {
-                       if !os.IsNotExist(err) {
-                               statusCode, statusText = http.StatusInternalServerError, err.Error()
-                               return
-                       }
-               } else if fileInfo.IsDir() {
-                       rewrittenPath = dir + "/" + pathParts[1]
-                       break
-               }
-       }
-       if rewrittenPath == "" {
-               log.Println("WARNING:", repoUUID,
-                       "git directory not found in", h.cluster.Git.Repositories, tryDirs)
-               // We say "content not found" to disambiguate from the
-               // earlier "API says that repo does not exist" error.
-               statusCode, statusText = http.StatusNotFound, "content not found"
-               return
-       }
-       r.URL.Path = rewrittenPath
-
-       h.handler.ServeHTTP(w, r)
-}
-
-var uuidRegexp = regexp.MustCompile(`^[0-9a-z]{5}-s0uqq-[0-9a-z]{15}$`)
-
-func (h *authHandler) lookupRepo(arv *arvadosclient.ArvadosClient, repoName string) (string, error) {
-       reposFound := arvadosclient.Dict{}
-       var column string
-       if uuidRegexp.MatchString(repoName) {
-               column = "uuid"
-       } else {
-               column = "name"
-       }
-       err := arv.List("repositories", arvadosclient.Dict{
-               "filters": [][]string{{column, "=", repoName}},
-       }, &reposFound)
-       if err != nil {
-               return "", err
-       } else if avail, ok := reposFound["items_available"].(float64); !ok {
-               return "", errors.New("bad list response from API")
-       } else if avail < 1 {
-               return "", nil
-       } else if avail > 1 {
-               return "", errors.New("name collision")
-       }
-       return reposFound["items"].([]interface{})[0].(map[string]interface{})["uuid"].(string), nil
-}
diff --git a/services/githttpd/auth_handler_test.go b/services/githttpd/auth_handler_test.go
deleted file mode 100644 (file)
index 2d1ec96..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "io"
-       "log"
-       "net/http"
-       "net/http/httptest"
-       "net/url"
-       "path/filepath"
-       "strings"
-
-       "git.arvados.org/arvados.git/lib/config"
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadosclient"
-       "git.arvados.org/arvados.git/sdk/go/arvadostest"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
-       check "gopkg.in/check.v1"
-)
-
-var _ = check.Suite(&AuthHandlerSuite{})
-
-type AuthHandlerSuite struct {
-       cluster *arvados.Cluster
-}
-
-func (s *AuthHandlerSuite) SetUpTest(c *check.C) {
-       arvadostest.ResetEnv()
-       repoRoot, err := filepath.Abs("../api/tmp/git/test")
-       c.Assert(err, check.IsNil)
-
-       cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load()
-       c.Assert(err, check.Equals, nil)
-       s.cluster, err = cfg.GetCluster("")
-       c.Assert(err, check.Equals, nil)
-
-       s.cluster.Services.GitHTTP.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: "localhost:0"}: {}}
-       s.cluster.TLS.Insecure = true
-       s.cluster.Git.GitCommand = "/usr/bin/git"
-       s.cluster.Git.Repositories = repoRoot
-}
-
-func (s *AuthHandlerSuite) TestPermission(c *check.C) {
-       client, err := arvados.NewClientFromConfig(s.cluster)
-       c.Assert(err, check.IsNil)
-       ac, err := arvadosclient.New(client)
-       c.Assert(err, check.IsNil)
-       h := &authHandler{
-               cluster:    s.cluster,
-               clientPool: &arvadosclient.ClientPool{Prototype: ac},
-               handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-                       log.Printf("%v", r.URL)
-                       io.WriteString(w, r.URL.Path)
-               }),
-       }
-       baseURL, err := url.Parse("http://git.example/")
-       c.Assert(err, check.IsNil)
-       for _, trial := range []struct {
-               label   string
-               token   string
-               pathIn  string
-               pathOut string
-               status  int
-       }{
-               {
-                       label:   "read repo by name",
-                       token:   arvadostest.ActiveToken,
-                       pathIn:  arvadostest.Repository2Name + ".git/git-upload-pack",
-                       pathOut: arvadostest.Repository2UUID + ".git/git-upload-pack",
-               },
-               {
-                       label:   "read repo by uuid",
-                       token:   arvadostest.ActiveToken,
-                       pathIn:  arvadostest.Repository2UUID + ".git/git-upload-pack",
-                       pathOut: arvadostest.Repository2UUID + ".git/git-upload-pack",
-               },
-               {
-                       label:   "write repo by name",
-                       token:   arvadostest.ActiveToken,
-                       pathIn:  arvadostest.Repository2Name + ".git/git-receive-pack",
-                       pathOut: arvadostest.Repository2UUID + ".git/git-receive-pack",
-               },
-               {
-                       label:   "write repo by uuid",
-                       token:   arvadostest.ActiveToken,
-                       pathIn:  arvadostest.Repository2UUID + ".git/git-receive-pack",
-                       pathOut: arvadostest.Repository2UUID + ".git/git-receive-pack",
-               },
-               {
-                       label:  "uuid not found",
-                       token:  arvadostest.ActiveToken,
-                       pathIn: strings.Replace(arvadostest.Repository2UUID, "6", "z", -1) + ".git/git-upload-pack",
-                       status: http.StatusNotFound,
-               },
-               {
-                       label:  "name not found",
-                       token:  arvadostest.ActiveToken,
-                       pathIn: "nonexistent-bogus.git/git-upload-pack",
-                       status: http.StatusNotFound,
-               },
-               {
-                       label:   "read read-only repo",
-                       token:   arvadostest.SpectatorToken,
-                       pathIn:  arvadostest.FooRepoName + ".git/git-upload-pack",
-                       pathOut: arvadostest.FooRepoUUID + "/.git/git-upload-pack",
-               },
-               {
-                       label:  "write read-only repo",
-                       token:  arvadostest.SpectatorToken,
-                       pathIn: arvadostest.FooRepoName + ".git/git-receive-pack",
-                       status: http.StatusForbidden,
-               },
-       } {
-               c.Logf("trial label: %q", trial.label)
-               u, err := baseURL.Parse(trial.pathIn)
-               c.Assert(err, check.IsNil)
-               resp := httptest.NewRecorder()
-               req := &http.Request{
-                       Method: "POST",
-                       URL:    u,
-                       Header: http.Header{
-                               "Authorization": {"Bearer " + trial.token}}}
-               h.ServeHTTP(resp, req)
-               if trial.status == 0 {
-                       trial.status = http.StatusOK
-               }
-               c.Check(resp.Code, check.Equals, trial.status)
-               if trial.status < 400 {
-                       if trial.pathOut != "" && !strings.HasPrefix(trial.pathOut, "/") {
-                               trial.pathOut = "/" + trial.pathOut
-                       }
-                       c.Check(resp.Body.String(), check.Equals, trial.pathOut)
-               }
-       }
-}
-
-func (s *AuthHandlerSuite) TestCORS(c *check.C) {
-       h := &authHandler{cluster: s.cluster}
-
-       // CORS preflight
-       resp := httptest.NewRecorder()
-       req := &http.Request{
-               Method: "OPTIONS",
-               Header: http.Header{
-                       "Origin":                        {"*"},
-                       "Access-Control-Request-Method": {"GET"},
-               },
-       }
-       h.ServeHTTP(resp, req)
-       c.Check(resp.Code, check.Equals, http.StatusOK)
-       c.Check(resp.Header().Get("Access-Control-Allow-Methods"), check.Equals, "GET, POST")
-       c.Check(resp.Header().Get("Access-Control-Allow-Headers"), check.Equals, "Authorization, Content-Type")
-       c.Check(resp.Header().Get("Access-Control-Allow-Origin"), check.Equals, "*")
-       c.Check(resp.Body.String(), check.Equals, "")
-
-       // CORS actual request. Bogus token and path ensure
-       // authHandler responds 4xx without calling our wrapped (nil)
-       // handler.
-       u, err := url.Parse("git.zzzzz.arvadosapi.com/test")
-       c.Assert(err, check.Equals, nil)
-       resp = httptest.NewRecorder()
-       req = &http.Request{
-               Method: "GET",
-               URL:    u,
-               Header: http.Header{
-                       "Origin":        {"*"},
-                       "Authorization": {"OAuth2 foobar"},
-               },
-       }
-       h.ServeHTTP(resp, req)
-       c.Check(resp.Header().Get("Access-Control-Allow-Origin"), check.Equals, "*")
-}
diff --git a/services/githttpd/cmd.go b/services/githttpd/cmd.go
deleted file mode 100644 (file)
index e6ca3c0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "context"
-
-       "git.arvados.org/arvados.git/lib/service"
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadosclient"
-       "github.com/prometheus/client_golang/prometheus"
-)
-
-var Command = service.Command(arvados.ServiceNameGitHTTP, newHandler)
-
-func newHandler(ctx context.Context, cluster *arvados.Cluster, token string, reg *prometheus.Registry) service.Handler {
-       client, err := arvados.NewClientFromConfig(cluster)
-       if err != nil {
-               return service.ErrorHandler(ctx, cluster, err)
-       }
-       ac, err := arvadosclient.New(client)
-       if err != nil {
-               return service.ErrorHandler(ctx, cluster, err)
-       }
-       return &authHandler{
-               clientPool: &arvadosclient.ClientPool{Prototype: ac},
-               cluster:    cluster,
-               handler:    newGitHandler(ctx, cluster),
-       }
-}
diff --git a/services/githttpd/git_handler.go b/services/githttpd/git_handler.go
deleted file mode 100644 (file)
index 7c94294..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "context"
-       "net"
-       "net/http"
-       "net/http/cgi"
-       "os"
-
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
-)
-
-// gitHandler is an http.Handler that invokes git-http-backend (or
-// whatever backend is configured) via CGI, with appropriate
-// environment variables in place for git-http-backend or
-// gitolite-shell.
-type gitHandler struct {
-       cgi.Handler
-}
-
-func newGitHandler(ctx context.Context, cluster *arvados.Cluster) http.Handler {
-       const glBypass = "GL_BYPASS_ACCESS_CHECKS"
-       const glHome = "GITOLITE_HTTP_HOME"
-       var env []string
-       path := os.Getenv("PATH")
-       if cluster.Git.GitoliteHome != "" {
-               env = append(env,
-                       glHome+"="+cluster.Git.GitoliteHome,
-                       glBypass+"=1")
-               path = path + ":" + cluster.Git.GitoliteHome + "/bin"
-       } else if home, bypass := os.Getenv(glHome), os.Getenv(glBypass); home != "" || bypass != "" {
-               env = append(env, glHome+"="+home, glBypass+"="+bypass)
-               ctxlog.FromContext(ctx).Printf("DEPRECATED: Passing through %s and %s environment variables. Use GitoliteHome configuration instead.", glHome, glBypass)
-       }
-
-       var listen arvados.URL
-       for listen = range cluster.Services.GitHTTP.InternalURLs {
-               break
-       }
-       env = append(env,
-               "GIT_PROJECT_ROOT="+cluster.Git.Repositories,
-               "GIT_HTTP_EXPORT_ALL=",
-               "SERVER_ADDR="+listen.Host,
-               "PATH="+path)
-       return &gitHandler{
-               Handler: cgi.Handler{
-                       Path: cluster.Git.GitCommand,
-                       Dir:  cluster.Git.Repositories,
-                       Env:  env,
-                       Args: []string{"http-backend"},
-               },
-       }
-}
-
-func (h *gitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-       remoteHost, remotePort, err := net.SplitHostPort(r.RemoteAddr)
-       if err != nil {
-               ctxlog.FromContext(r.Context()).Errorf("Internal error: SplitHostPort(r.RemoteAddr==%q): %s", r.RemoteAddr, err)
-               w.WriteHeader(http.StatusInternalServerError)
-               return
-       }
-
-       // Copy the wrapped cgi.Handler, so these request-specific
-       // variables don't leak into the next request.
-       handlerCopy := h.Handler
-       handlerCopy.Env = append(handlerCopy.Env,
-               // In Go1.5 we can skip this, net/http/cgi will do it for us:
-               "REMOTE_HOST="+remoteHost,
-               "REMOTE_ADDR="+remoteHost,
-               "REMOTE_PORT="+remotePort,
-               // Ideally this would be a real username:
-               "REMOTE_USER="+r.RemoteAddr,
-       )
-       handlerCopy.ServeHTTP(w, r)
-}
diff --git a/services/githttpd/git_handler_test.go b/services/githttpd/git_handler_test.go
deleted file mode 100644 (file)
index ef2ee28..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "context"
-       "net/http"
-       "net/http/httptest"
-       "net/url"
-       "regexp"
-
-       "git.arvados.org/arvados.git/lib/config"
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
-       check "gopkg.in/check.v1"
-)
-
-var _ = check.Suite(&GitHandlerSuite{})
-
-type GitHandlerSuite struct {
-       cluster *arvados.Cluster
-}
-
-func (s *GitHandlerSuite) SetUpTest(c *check.C) {
-       cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load()
-       c.Assert(err, check.Equals, nil)
-       s.cluster, err = cfg.GetCluster("")
-       c.Assert(err, check.Equals, nil)
-
-       s.cluster.Services.GitHTTP.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: "localhost:80"}: {}}
-       s.cluster.Git.GitoliteHome = "/test/ghh"
-       s.cluster.Git.Repositories = "/"
-}
-
-func (s *GitHandlerSuite) TestEnvVars(c *check.C) {
-       u, err := url.Parse("git.zzzzz.arvadosapi.com/test")
-       c.Check(err, check.Equals, nil)
-       resp := httptest.NewRecorder()
-       req := &http.Request{
-               Method:     "GET",
-               URL:        u,
-               RemoteAddr: "[::1]:12345",
-       }
-       h := newGitHandler(context.Background(), s.cluster)
-       h.(*gitHandler).Path = "/bin/sh"
-       h.(*gitHandler).Args = []string{"-c", "printf 'Content-Type: text/plain\r\n\r\n'; env"}
-
-       h.ServeHTTP(resp, req)
-
-       c.Check(resp.Code, check.Equals, http.StatusOK)
-       body := resp.Body.String()
-       c.Check(body, check.Matches, `(?ms).*^PATH=.*:/test/ghh/bin$.*`)
-       c.Check(body, check.Matches, `(?ms).*^GITOLITE_HTTP_HOME=/test/ghh$.*`)
-       c.Check(body, check.Matches, `(?ms).*^GL_BYPASS_ACCESS_CHECKS=1$.*`)
-       c.Check(body, check.Matches, `(?ms).*^REMOTE_HOST=::1$.*`)
-       c.Check(body, check.Matches, `(?ms).*^REMOTE_PORT=12345$.*`)
-       c.Check(body, check.Matches, `(?ms).*^SERVER_ADDR=`+regexp.QuoteMeta("localhost:80")+`$.*`)
-}
-
-func (s *GitHandlerSuite) TestCGIErrorOnSplitHostPortError(c *check.C) {
-       u, err := url.Parse("git.zzzzz.arvadosapi.com/test")
-       c.Check(err, check.Equals, nil)
-       resp := httptest.NewRecorder()
-       req := &http.Request{
-               Method:     "GET",
-               URL:        u,
-               RemoteAddr: "test.bad.address.missing.port",
-       }
-       h := newGitHandler(context.Background(), s.cluster)
-       h.ServeHTTP(resp, req)
-       c.Check(resp.Code, check.Equals, http.StatusInternalServerError)
-       c.Check(resp.Body.String(), check.Equals, "")
-}
diff --git a/services/githttpd/gitolite_test.go b/services/githttpd/gitolite_test.go
deleted file mode 100644 (file)
index d34c413..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "io/ioutil"
-       "os"
-       "os/exec"
-       "strings"
-
-       "git.arvados.org/arvados.git/lib/config"
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
-       check "gopkg.in/check.v1"
-)
-
-var _ = check.Suite(&GitoliteSuite{})
-
-// GitoliteSuite tests need an API server, an arvados-git-httpd
-// server, and a repository hosted by gitolite.
-type GitoliteSuite struct {
-       IntegrationSuite
-       gitoliteHome string
-}
-
-func (s *GitoliteSuite) SetUpTest(c *check.C) {
-       var err error
-       s.gitoliteHome, err = ioutil.TempDir("", "githttp")
-       c.Assert(err, check.Equals, nil)
-
-       runGitolite := func(prog string, args ...string) {
-               c.Log(prog, " ", args)
-               cmd := exec.Command(prog, args...)
-               cmd.Dir = s.gitoliteHome
-               cmd.Env = []string{"HOME=" + s.gitoliteHome}
-               for _, e := range os.Environ() {
-                       if !strings.HasPrefix(e, "HOME=") {
-                               cmd.Env = append(cmd.Env, e)
-                       }
-               }
-               diags, err := cmd.CombinedOutput()
-               c.Log(string(diags))
-               c.Assert(err, check.Equals, nil)
-       }
-
-       runGitolite("gitolite", "setup", "--admin", "root")
-
-       s.tmpRepoRoot = s.gitoliteHome + "/repositories"
-
-       cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load()
-       c.Assert(err, check.Equals, nil)
-       s.cluster, err = cfg.GetCluster("")
-       c.Assert(err, check.Equals, nil)
-
-       s.cluster.Services.GitHTTP.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: "localhost:0"}: {}}
-       s.cluster.TLS.Insecure = true
-       s.cluster.Git.GitCommand = "/usr/share/gitolite3/gitolite-shell"
-       s.cluster.Git.GitoliteHome = s.gitoliteHome
-       s.cluster.Git.Repositories = s.tmpRepoRoot
-
-       s.IntegrationSuite.SetUpTest(c)
-
-       // Install the gitolite hooks in the bare repo we made in
-       // (*IntegrationTest)SetUpTest() -- see 2.2.4 at
-       // http://gitolite.com/gitolite/gitolite.html
-       runGitolite("gitolite", "setup")
-}
-
-func (s *GitoliteSuite) TearDownTest(c *check.C) {
-       // We really want Unsetenv here, but it's not worth forcing an
-       // upgrade to Go 1.4.
-       os.Setenv("GITOLITE_HTTP_HOME", "")
-       os.Setenv("GL_BYPASS_ACCESS_CHECKS", "")
-       if s.gitoliteHome != "" {
-               err := os.RemoveAll(s.gitoliteHome)
-               c.Check(err, check.Equals, nil)
-       }
-       s.IntegrationSuite.TearDownTest(c)
-}
-
-func (s *GitoliteSuite) TestFetch(c *check.C) {
-       err := s.RunGit(c, activeToken, "fetch", "active/foo.git", "refs/heads/main")
-       c.Check(err, check.Equals, nil)
-}
-
-func (s *GitoliteSuite) TestFetchUnreadable(c *check.C) {
-       err := s.RunGit(c, anonymousToken, "fetch", "active/foo.git")
-       c.Check(err, check.ErrorMatches, `.* not found.*`)
-}
-
-func (s *GitoliteSuite) TestPush(c *check.C) {
-       err := s.RunGit(c, activeToken, "push", "active/foo.git", "main:gitolite-push")
-       c.Check(err, check.Equals, nil)
-
-       // Check that the commit hash appears in the gitolite log, as
-       // assurance that the gitolite hooks really did run.
-
-       sha1, err := exec.Command("git", "--git-dir", s.tmpWorkdir+"/.git",
-               "log", "-n1", "--format=%H").CombinedOutput()
-       c.Logf("git-log in workdir: %q", string(sha1))
-       c.Assert(err, check.Equals, nil)
-       c.Assert(len(sha1), check.Equals, 41)
-
-       gitoliteLog, err := exec.Command("grep", "-r", string(sha1[:40]), s.gitoliteHome+"/.gitolite/logs").CombinedOutput()
-       c.Check(err, check.Equals, nil)
-       c.Logf("gitolite log message: %q", string(gitoliteLog))
-}
-
-func (s *GitoliteSuite) TestPushUnwritable(c *check.C) {
-       err := s.RunGit(c, spectatorToken, "push", "active/foo.git", "main:gitolite-push-fail")
-       c.Check(err, check.ErrorMatches, `.*HTTP (code = )?403.*`)
-}
diff --git a/services/githttpd/integration_test.go b/services/githttpd/integration_test.go
deleted file mode 100644 (file)
index c819272..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "context"
-       "errors"
-       "io/ioutil"
-       "os"
-       "os/exec"
-       "strings"
-       "testing"
-
-       "git.arvados.org/arvados.git/lib/config"
-       "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadostest"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
-       "git.arvados.org/arvados.git/sdk/go/httpserver"
-       check "gopkg.in/check.v1"
-)
-
-// Gocheck boilerplate
-func Test(t *testing.T) {
-       check.TestingT(t)
-}
-
-// IntegrationSuite tests need an API server and an arvados-git-httpd
-// server. See GitSuite and GitoliteSuite.
-type IntegrationSuite struct {
-       tmpRepoRoot string
-       tmpWorkdir  string
-       testServer  *httpserver.Server
-       cluster     *arvados.Cluster
-}
-
-func (s *IntegrationSuite) SetUpTest(c *check.C) {
-       arvadostest.ResetEnv()
-
-       var err error
-       if s.tmpRepoRoot == "" {
-               s.tmpRepoRoot, err = ioutil.TempDir("", "githttp")
-               c.Assert(err, check.Equals, nil)
-       }
-       s.tmpWorkdir, err = ioutil.TempDir("", "githttp")
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("git", "init", "--bare", s.tmpRepoRoot+"/zzzzz-s0uqq-382brsig8rp3666.git").Output()
-       c.Assert(err, check.Equals, nil)
-       // we need git 2.28 to specify the initial branch with -b; Buster only has 2.20; so we do it in 2 steps
-       _, err = exec.Command("git", "init", s.tmpWorkdir).Output()
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("sh", "-c", "cd "+s.tmpWorkdir+" && git checkout -b main").Output()
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("sh", "-c", "cd "+s.tmpWorkdir+" && echo initial >initial && git add initial && git -c user.name=Initial -c user.email=Initial commit -am 'foo: initial commit'").CombinedOutput()
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("sh", "-c", "cd "+s.tmpWorkdir+" && git push "+s.tmpRepoRoot+"/zzzzz-s0uqq-382brsig8rp3666.git main:main").CombinedOutput()
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("sh", "-c", "cd "+s.tmpWorkdir+" && echo work >work && git add work && git -c user.name=Foo -c user.email=Foo commit -am 'workdir: test'").CombinedOutput()
-       c.Assert(err, check.Equals, nil)
-
-       if s.cluster == nil {
-               cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load()
-               c.Assert(err, check.Equals, nil)
-               s.cluster, err = cfg.GetCluster("")
-               c.Assert(err, check.Equals, nil)
-
-               s.cluster.Services.GitHTTP.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: "localhost:0"}: {}}
-               s.cluster.TLS.Insecure = true
-               s.cluster.Git.GitCommand = "/usr/bin/git"
-               s.cluster.Git.Repositories = s.tmpRepoRoot
-               s.cluster.ManagementToken = arvadostest.ManagementToken
-       }
-
-       s.testServer = &httpserver.Server{}
-       s.testServer.Handler = httpserver.LogRequests(newHandler(context.Background(), s.cluster, "", nil))
-       err = s.testServer.Start()
-       c.Assert(err, check.Equals, nil)
-
-       _, err = exec.Command("git", "config",
-               "--file", s.tmpWorkdir+"/.git/config",
-               "credential.http://"+s.testServer.Addr+"/.helper",
-               "!cred(){ cat >/dev/null; if [ \"$1\" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred").Output()
-       c.Assert(err, check.Equals, nil)
-       _, err = exec.Command("git", "config",
-               "--file", s.tmpWorkdir+"/.git/config",
-               "credential.http://"+s.testServer.Addr+"/.username",
-               "none").Output()
-       c.Assert(err, check.Equals, nil)
-
-       // Clear ARVADOS_API_* env vars before starting up the server,
-       // to make sure arvados-git-httpd doesn't use them or complain
-       // about them being missing.
-       os.Unsetenv("ARVADOS_API_HOST")
-       os.Unsetenv("ARVADOS_API_HOST_INSECURE")
-       os.Unsetenv("ARVADOS_API_TOKEN")
-}
-
-func (s *IntegrationSuite) TearDownTest(c *check.C) {
-       var err error
-       if s.testServer != nil {
-               err = s.testServer.Close()
-       }
-       c.Check(err, check.Equals, nil)
-       s.testServer = nil
-
-       if s.tmpRepoRoot != "" {
-               err = os.RemoveAll(s.tmpRepoRoot)
-               c.Check(err, check.Equals, nil)
-       }
-       s.tmpRepoRoot = ""
-
-       if s.tmpWorkdir != "" {
-               err = os.RemoveAll(s.tmpWorkdir)
-               c.Check(err, check.Equals, nil)
-       }
-       s.tmpWorkdir = ""
-
-       s.cluster = nil
-}
-
-func (s *IntegrationSuite) RunGit(c *check.C, token, gitCmd, repo string, args ...string) error {
-       cwd, err := os.Getwd()
-       c.Assert(err, check.Equals, nil)
-       defer os.Chdir(cwd)
-       os.Chdir(s.tmpWorkdir)
-
-       gitargs := append([]string{
-               gitCmd, "http://" + s.testServer.Addr + "/" + repo,
-       }, args...)
-       cmd := exec.Command("git", gitargs...)
-       cmd.Env = append(os.Environ(), "ARVADOS_API_TOKEN="+token)
-       w, err := cmd.StdinPipe()
-       c.Assert(err, check.Equals, nil)
-       w.Close()
-       output, err := cmd.CombinedOutput()
-       c.Log("git ", gitargs, " => ", err)
-       c.Log(string(output))
-       if err != nil && len(output) > 0 {
-               // If messages appeared on stderr, they are more
-               // helpful than the err returned by CombinedOutput().
-               //
-               // Easier to match error strings without newlines:
-               err = errors.New(strings.Replace(string(output), "\n", " // ", -1))
-       }
-       return err
-}
diff --git a/services/githttpd/server_test.go b/services/githttpd/server_test.go
deleted file mode 100644 (file)
index 02c13a3..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package githttpd
-
-import (
-       "os"
-       "os/exec"
-
-       check "gopkg.in/check.v1"
-)
-
-var _ = check.Suite(&GitSuite{})
-
-const (
-       spectatorToken = "zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu"
-       activeToken    = "3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi"
-       anonymousToken = "4kg6k6lzmp9kj4cpkcoxie964cmvjahbt4fod9zru44k4jqdmi"
-       expiredToken   = "2ym314ysp27sk7h943q6vtc378srb06se3pq6ghurylyf3pdmx"
-)
-
-type GitSuite struct {
-       IntegrationSuite
-}
-
-func (s *GitSuite) TestPathVariants(c *check.C) {
-       s.makeArvadosRepo(c)
-       for _, repo := range []string{"active/foo.git", "active/foo/.git", "arvados.git", "arvados/.git"} {
-               err := s.RunGit(c, spectatorToken, "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.Equals, nil)
-       }
-}
-
-func (s *GitSuite) TestReadonly(c *check.C) {
-       err := s.RunGit(c, spectatorToken, "fetch", "active/foo.git", "refs/heads/main")
-       c.Assert(err, check.Equals, nil)
-       err = s.RunGit(c, spectatorToken, "push", "active/foo.git", "main:newbranchfail")
-       c.Assert(err, check.ErrorMatches, `.*HTTP (code = )?403.*`)
-       _, err = os.Stat(s.tmpRepoRoot + "/zzzzz-s0uqq-382brsig8rp3666.git/refs/heads/newbranchfail")
-       c.Assert(err, check.FitsTypeOf, &os.PathError{})
-}
-
-func (s *GitSuite) TestReadwrite(c *check.C) {
-       err := s.RunGit(c, activeToken, "fetch", "active/foo.git", "refs/heads/main")
-       c.Assert(err, check.Equals, nil)
-       err = s.RunGit(c, activeToken, "push", "active/foo.git", "main:newbranch")
-       c.Assert(err, check.Equals, nil)
-       _, err = os.Stat(s.tmpRepoRoot + "/zzzzz-s0uqq-382brsig8rp3666.git/refs/heads/newbranch")
-       c.Assert(err, check.Equals, nil)
-}
-
-func (s *GitSuite) TestNonexistent(c *check.C) {
-       err := s.RunGit(c, spectatorToken, "fetch", "thisrepodoesnotexist.git", "refs/heads/main")
-       c.Assert(err, check.ErrorMatches, `.* not found.*`)
-}
-
-func (s *GitSuite) TestMissingGitdirReadableRepository(c *check.C) {
-       err := s.RunGit(c, activeToken, "fetch", "active/foo2.git", "refs/heads/main")
-       c.Assert(err, check.ErrorMatches, `.* not found.*`)
-}
-
-func (s *GitSuite) TestNoPermission(c *check.C) {
-       for _, repo := range []string{"active/foo.git", "active/foo/.git"} {
-               err := s.RunGit(c, anonymousToken, "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.ErrorMatches, `.* not found.*`)
-       }
-}
-
-func (s *GitSuite) TestExpiredToken(c *check.C) {
-       for _, repo := range []string{"active/foo.git", "active/foo/.git"} {
-               err := s.RunGit(c, expiredToken, "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.ErrorMatches, `.* (500 while accessing|requested URL returned error: 500).*`)
-       }
-}
-
-func (s *GitSuite) TestInvalidToken(c *check.C) {
-       for _, repo := range []string{"active/foo.git", "active/foo/.git"} {
-               err := s.RunGit(c, "s3cr3tp@ssw0rd", "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.ErrorMatches, `.* requested URL returned error.*`)
-       }
-}
-
-func (s *GitSuite) TestShortToken(c *check.C) {
-       for _, repo := range []string{"active/foo.git", "active/foo/.git"} {
-               err := s.RunGit(c, "s3cr3t", "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.ErrorMatches, `.* (500 while accessing|requested URL returned error: 500).*`)
-       }
-}
-
-func (s *GitSuite) TestShortTokenBadReq(c *check.C) {
-       for _, repo := range []string{"bogus"} {
-               err := s.RunGit(c, "s3cr3t", "fetch", repo, "refs/heads/main")
-               c.Assert(err, check.ErrorMatches, `.*not found.*`)
-       }
-}
-
-// Make a bare arvados repo at {tmpRepoRoot}/arvados.git
-func (s *GitSuite) makeArvadosRepo(c *check.C) {
-       msg, err := exec.Command("git", "init", "--bare", s.tmpRepoRoot+"/zzzzz-s0uqq-arvadosrepo0123.git").CombinedOutput()
-       c.Log(string(msg))
-       c.Assert(err, check.Equals, nil)
-       msg, err = exec.Command("git", "--git-dir", s.tmpRepoRoot+"/zzzzz-s0uqq-arvadosrepo0123.git", "fetch", "../../.git", "HEAD:main").CombinedOutput()
-       c.Log(string(msg))
-       c.Assert(err, check.Equals, nil)
-}
index 094a3f618c64c1502b66f2227eef6ca7c192c65e..4e5aa31f4dc2b209bcf1ae35927bf2477ac930d4 100644 (file)
@@ -215,8 +215,6 @@ describe("Search tests", function () {
                         DispatchCloud: { ExternalURL: "" },
                         DispatchLSF: { ExternalURL: "" },
                         DispatchSLURM: { ExternalURL: "" },
-                        GitHTTP: { ExternalURL: "https://xxxxx.fakecluster.tld:39105/" },
-                        GitSSH: { ExternalURL: "" },
                         Health: { ExternalURL: "https://xxxxx.fakecluster.tld:42915/" },
                         Keepbalance: { ExternalURL: "" },
                         Keepproxy: { ExternalURL: "https://xxxxx.fakecluster.tld:46773/" },
index d02b1999392bdce12dcb62f65a007945ece1a012..172f74ce7abea6bda96b1250e040ec01b90f0a55 100644 (file)
@@ -7,11 +7,14 @@ package ws
 import (
        "database/sql"
        "fmt"
+       "io/ioutil"
+       "sort"
        "sync"
        "time"
 
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "git.arvados.org/arvados.git/sdk/go/ctxlog"
+       "github.com/ghodss/yaml"
        "github.com/prometheus/client_golang/prometheus"
        check "gopkg.in/check.v1"
 )
@@ -41,6 +44,18 @@ func testDB() *sql.DB {
 }
 
 func (*eventSourceSuite) TestEventSource(c *check.C) {
+       var logfixtures map[string]struct {
+               ID int
+       }
+       yamldata, err := ioutil.ReadFile("../api/test/fixtures/logs.yml")
+       c.Assert(err, check.IsNil)
+       c.Assert(yaml.Unmarshal(yamldata, &logfixtures), check.IsNil)
+       var logIDs []int
+       for _, logfixture := range logfixtures {
+               logIDs = append(logIDs, logfixture.ID)
+       }
+       sort.Ints(logIDs)
+
        cfg := testDBConfig()
        db := testDB()
        pges := &pgEventSource{
@@ -61,8 +76,8 @@ func (*eventSourceSuite) TestEventSource(c *check.C) {
        done := make(chan bool, 1)
 
        go func() {
-               for i := range sinks {
-                       _, err := db.Exec(fmt.Sprintf(`NOTIFY logs, '%d'`, i))
+               for _, id := range logIDs {
+                       _, err := db.Exec(fmt.Sprintf(`NOTIFY logs, '%d'`, id))
                        if err != nil {
                                done <- true
                                c.Fatal(err)
@@ -77,17 +92,13 @@ func (*eventSourceSuite) TestEventSource(c *check.C) {
                go func(si int, s eventSink) {
                        defer wg.Done()
                        defer sinks[si].Stop()
-                       for i := 0; i <= si; i++ {
+                       for _, logID := range logIDs {
                                ev := <-sinks[si].Channel()
-                               c.Logf("sink %d received event %d", si, i)
-                               c.Check(ev.LogID, check.Equals, int64(i))
+                               c.Logf("sink %d received event %d", si, logID)
+                               c.Check(ev.LogID, check.Equals, int64(logID))
                                row := ev.Detail()
-                               if i == 0 {
-                                       // no matching row, null event
-                                       c.Check(row, check.IsNil)
-                               } else {
-                                       c.Check(row, check.NotNil)
-                                       c.Check(row.ID, check.Equals, int64(i))
+                               if c.Check(row, check.NotNil) {
+                                       c.Check(row.ID, check.Equals, int64(logID))
                                        c.Check(row.UUID, check.Not(check.Equals), "")
                                }
                        }
index 4665dfcd9ee9208fcb71794189ba115d0285fa55..f38bbbe5ad946cce77123ce85c58060e79aeb67e 100644 (file)
@@ -21,5 +21,5 @@ func (*eventSuite) TestDetail(c *check.C) {
        c.Check(logRow.UUID, check.Equals, "zzzzz-57u5n-containerlog006")
        c.Check(logRow.ObjectUUID, check.Equals, "zzzzz-dz642-logscontainer03")
        c.Check(logRow.EventType, check.Equals, "crunchstat")
-       c.Check(logRow.Properties["text"], check.Equals, "2013-11-07_23:33:41 zzzzz-8i9sb-ahd7cie8jah9qui 29610 1 stderr crunchstat: cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user 0.9900 sys")
+       c.Check(logRow.Properties["text"], check.Equals, "2013-11-07_23:33:41 zzzzz-dz642-logscontainer03 29610 1 stderr crunchstat: cpu 1935.4300 user 59.4100 sys 8 cpus -- interval 10.0002 seconds 12.9900 user 0.9900 sys")
 }
index d8b240883169e72b6914a5f23ca7d62f8aef9447..927b975f8f4baef077acbad3d560266d3f62a7d5 100644 (file)
@@ -137,8 +137,7 @@ RUN echo arvados_version is git commit $arvados_version
 
 COPY $workdir/fuse.conf /etc/
 
-COPY $workdir/gitolite.rc \
-    $workdir/keep-setup.sh $workdir/common.sh $workdir/createusers.sh \
+COPY $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 \
index 81a5369f5ebcb9a9a749c1a4d713458466e2c897..dfbeaa448cc6bbe92a4164df6085a30bb42f639e 100644 (file)
@@ -37,7 +37,6 @@ RUN sudo -u arvbox /var/lib/arvbox/service/keep-web/run-service --only-deps
 RUN sudo -u arvbox /var/lib/arvbox/service/doc/run-service --only-deps
 RUN sudo -u arvbox /var/lib/arvbox/service/vm/run-service --only-deps
 RUN sudo -u arvbox /var/lib/arvbox/service/keepproxy/run-service --only-deps
-RUN sudo -u arvbox /var/lib/arvbox/service/arv-git-httpd/run-service --only-deps
 RUN sudo -u arvbox /var/lib/arvbox/service/websockets/run --only-deps
 RUN sudo -u arvbox /usr/local/lib/arvbox/keep-setup.sh --only-deps
 RUN sudo -u arvbox /var/lib/arvbox/service/sdk/run-service
index 29cea1ecbe3ee2a5e39e04b66c64dab65f010a3a..b2d20a455c62a1f619882fdba1f65aae3f5e6af0 100755 (executable)
@@ -38,8 +38,6 @@ $RAILS_ENV:
   blob_signing_key: $blob_signing_key
   workbench_address: "https://$localip/"
   websocket_address: "wss://$localip:${services[websockets-ssl]}/websocket"
-  git_repo_ssh_base: "git@$localip:"
-  git_repo_https_base: "http://$localip:${services[arv-git-httpd]}/"
   new_users_are_active: true
   auto_admin_first_user: true
   auto_setup_new_users: true
index 9b55181c9169a52c6a8eb7fda8760eedcade0d9a..d07fc3d34d550c8ad4ba2f826a29ec01488e03ad 100755 (executable)
@@ -87,12 +87,6 @@ Clusters:
         ExternalURL: "wss://$localip:${services[websockets-ssl]}/websocket"
         InternalURLs:
           "http://localhost:${services[websockets]}": {}
-      GitSSH:
-        ExternalURL: "ssh://git@$localip:"
-      GitHTTP:
-        InternalURLs:
-          "http://localhost:${services[arv-git-httpd]}/": {}
-        ExternalURL: "https://$localip:${services[arv-git-httpd-ssl]}/"
       WebDAV:
         InternalURLs:
           "http://localhost:${services[keep-web]}/": {}
@@ -132,11 +126,6 @@ Clusters:
       AutoAdminFirstUser: true
       AutoSetupNewUsers: true
       AutoSetupNewUsersWithVmUUID: $vm_uuid
-      AutoSetupNewUsersWithRepository: true
-    Git:
-      GitCommand: /usr/share/gitolite3/gitolite-shell
-      GitoliteHome: $ARVADOS_CONTAINER_PATH/git
-      Repositories: $ARVADOS_CONTAINER_PATH/git/repositories
     Volumes:
       ${uuid_prefix}-nyw5e-000000000000000:
         Driver: Directory
index 40a540ac80d60cdf8899b0fac115a077b612b5d3..2232b63c4f9bca74823550ab4275d2cc7e2b6145 100644 (file)
@@ -37,8 +37,6 @@ services=(
   [api]=8004
   [controller]=8003
   [controller-ssl]=8000
-  [arv-git-httpd-ssl]=9000
-  [arv-git-httpd]=9001
   [keep-web]=9003
   [keep-web-ssl]=9002
   [keep-web-dl-ssl]=9004
diff --git a/tools/arvbox/lib/arvbox/docker/gitolite.rc b/tools/arvbox/lib/arvbox/docker/gitolite.rc
deleted file mode 100644 (file)
index 07a9ce0..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-# This is based on the default Gitolite configuration file with the following
-# changes applied as described here:
-# http://doc.arvados.org/install/install-arv-git-httpd.html
-
-# configuration variables for gitolite
-
-# This file is in perl syntax.  But you do NOT need to know perl to edit it --
-# just mind the commas, use single quotes unless you know what you're doing,
-# and make sure the brackets and braces stay matched up!
-
-# (Tip: perl allows a comma after the last item in a list also!)
-
-# HELP for commands can be had by running the command with "-h".
-
-# HELP for all the other FEATURES can be found in the documentation (look for
-# "list of non-core programs shipped with gitolite" in the master index) or
-# directly in the corresponding source file.
-
-my $repo_aliases;
-my $aliases_src = "$ENV{HOME}/.gitolite/arvadosaliases.pl";
-if ($ENV{HOME} && (-e $aliases_src)) {
-    $repo_aliases = do $aliases_src;
-}
-$repo_aliases ||= {};
-
-%RC = (
-
-    REPO_ALIASES => $repo_aliases,
-
-    # ------------------------------------------------------------------
-
-    # default umask gives you perms of '0700'; see the rc file docs for
-    # how/why you might change this
-    UMASK                           =>  0022,
-
-    # look for "git-config" in the documentation
-    GIT_CONFIG_KEYS                 =>  '',
-
-    # comment out if you don't need all the extra detail in the logfile
-    LOG_EXTRA                       =>  1,
-    # logging options
-    # 1. leave this section as is for 'normal' gitolite logging (default)
-    # 2. uncomment this line to log ONLY to syslog:
-    # LOG_DEST                      => 'syslog',
-    # 3. uncomment this line to log to syslog and the normal gitolite log:
-    # LOG_DEST                      => 'syslog,normal',
-    # 4. prefixing "repo-log," to any of the above will **also** log just the
-    #    update records to "gl-log" in the bare repo directory:
-    # LOG_DEST                      => 'repo-log,normal',
-    # LOG_DEST                      => 'repo-log,syslog',
-    # LOG_DEST                      => 'repo-log,syslog,normal',
-
-    # roles.  add more roles (like MANAGER, TESTER, ...) here.
-    #   WARNING: if you make changes to this hash, you MUST run 'gitolite
-    #   compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
-    ROLES => {
-        READERS                     =>  1,
-        WRITERS                     =>  1,
-    },
-
-    # enable caching (currently only Redis).  PLEASE RTFM BEFORE USING!!!
-    # CACHE                         =>  'Redis',
-
-    # ------------------------------------------------------------------
-
-    # rc variables used by various features
-
-    # the 'info' command prints this as additional info, if it is set
-        # SITE_INFO                 =>  'Please see http://blahblah/gitolite for more help',
-
-    # the CpuTime feature uses these
-        # display user, system, and elapsed times to user after each git operation
-        # DISPLAY_CPU_TIME          =>  1,
-        # display a warning if total CPU times (u, s, cu, cs) crosses this limit
-        # CPU_TIME_WARN_LIMIT       =>  0.1,
-
-    # the Mirroring feature needs this
-        # HOSTNAME                  =>  "foo",
-
-    # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING!
-        # CACHE_TTL                 =>  600,
-
-    # ------------------------------------------------------------------
-
-    # suggested locations for site-local gitolite code (see cust.html)
-
-        # this one is managed directly on the server
-        # LOCAL_CODE                =>  "$ENV{HOME}/local",
-
-        # or you can use this, which lets you put everything in a subdirectory
-        # called "local" in your gitolite-admin repo.  For a SECURITY WARNING
-        # on this, see http://gitolite.com/gitolite/non-core.html#pushcode
-        # LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",
-
-    # ------------------------------------------------------------------
-
-    # List of commands and features to enable
-
-    ENABLE => [
-
-        # COMMANDS
-
-            # These are the commands enabled by default
-            'help',
-            'desc',
-            'info',
-            'perms',
-            'writable',
-
-            # Uncomment or add new commands here.
-            # 'create',
-            # 'fork',
-            # 'mirror',
-            # 'readme',
-            # 'sskm',
-            # 'D',
-
-        # These FEATURES are enabled by default.
-
-            # essential (unless you're using smart-http mode)
-            'ssh-authkeys',
-
-            # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
-            'git-config',
-
-            # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
-            'daemon',
-
-            # creates projects.list file; if you don't use gitweb, comment this out
-            'gitweb',
-
-        # These FEATURES are disabled by default; uncomment to enable.  If you
-        # need to add new ones, ask on the mailing list :-)
-
-        # user-visible behaviour
-
-            # prevent wild repos auto-create on fetch/clone
-            # 'no-create-on-read',
-            # no auto-create at all (don't forget to enable the 'create' command!)
-            # 'no-auto-create',
-
-            # access a repo by another (possibly legacy) name
-            'Alias',
-
-            # give some users direct shell access.  See documentation in
-            # sts.html for details on the following two choices.
-            # "Shell $ENV{HOME}/.gitolite.shell-users",
-            # 'Shell alice bob',
-
-            # set default roles from lines like 'option default.roles-1 = ...', etc.
-            # 'set-default-roles',
-
-            # show more detailed messages on deny
-            # 'expand-deny-messages',
-
-            # show a message of the day
-            # 'Motd',
-
-        # system admin stuff
-
-            # enable mirroring (don't forget to set the HOSTNAME too!)
-            # 'Mirroring',
-
-            # allow people to submit pub files with more than one key in them
-            # 'ssh-authkeys-split',
-
-            # selective read control hack
-            # 'partial-copy',
-
-            # manage local, gitolite-controlled, copies of read-only upstream repos
-            # 'upstream',
-
-            # updates 'description' file instead of 'gitweb.description' config item
-            # 'cgit',
-
-            # allow repo-specific hooks to be added
-            # 'repo-specific-hooks',
-
-        # performance, logging, monitoring...
-
-            # be nice
-            # 'renice 10',
-
-            # log CPU times (user, system, cumulative user, cumulative system)
-            # 'CpuTime',
-
-        # syntactic_sugar for gitolite.conf and included files
-
-            # allow backslash-escaped continuation lines in gitolite.conf
-            # 'continuation-lines',
-
-            # create implicit user groups from directory names in keydir/
-            # 'keysubdirs-as-groups',
-
-            # allow simple line-oriented macros
-            # 'macros',
-
-        # Kindergarten mode
-
-            # disallow various things that sensible people shouldn't be doing anyway
-            # 'Kindergarten',
-    ],
-
-);
-
-# ------------------------------------------------------------------------------
-# per perl rules, this should be the last line in such a file:
-1;
-
-# Local variables:
-# mode: perl
-# End:
-# vim: set syn=perl:
diff --git a/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/main/.gitstub b/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/main/.gitstub
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run b/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run
deleted file mode 120000 (symlink)
index d6aef4a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run b/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run
deleted file mode 120000 (symlink)
index a388c8b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service b/tools/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service
deleted file mode 100755 (executable)
index b598a75..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-exec 2>&1
-set -ex -o pipefail
-
-. /usr/local/lib/arvbox/common.sh
-. /usr/local/lib/arvbox/go-setup.sh
-
-(cd /usr/local/bin && ln -sf arvados-server arvados-git-httpd)
-
-if test "$1" = "--only-deps" ; then
-    exit
-fi
-
-flock $ARVADOS_CONTAINER_PATH/cluster_config.yml.lock /usr/local/lib/arvbox/cluster-config.sh
-
-export PATH="$PATH:$ARVADOS_CONTAINER_PATH/git/bin"
-cd ~git
-exec /usr/local/bin/arvados-git-httpd
diff --git a/tools/arvbox/lib/arvbox/docker/service/gitolite/log/main/.gitstub b/tools/arvbox/lib/arvbox/docker/service/gitolite/log/main/.gitstub
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/arvbox/lib/arvbox/docker/service/gitolite/log/run b/tools/arvbox/lib/arvbox/docker/service/gitolite/log/run
deleted file mode 120000 (symlink)
index d6aef4a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/tools/arvbox/lib/arvbox/docker/service/gitolite/run b/tools/arvbox/lib/arvbox/docker/service/gitolite/run
deleted file mode 120000 (symlink)
index a388c8b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/tools/arvbox/lib/arvbox/docker/service/gitolite/run-service b/tools/arvbox/lib/arvbox/docker/service/gitolite/run-service
deleted file mode 100755 (executable)
index 5f2cbc8..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/bash
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-exec 2>&1
-set -eux -o pipefail
-
-. /usr/local/lib/arvbox/common.sh
-
-if test "$1" != "--only-deps" ; then
-  while [ ! -f $ARVADOS_CONTAINER_PATH/api.ready ]; do
-    sleep 1
-  done
-fi
-
-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 $ARVADOS_CONTAINER_PATH/superuser_token)
-
-export USER=git
-export USERNAME=git
-export LOGNAME=git
-export HOME=$ARVADOS_CONTAINER_PATH/git
-
-cd ~arvbox
-
-mkdir -p ~arvbox/.ssh ~git/.ssh
-chmod 0700 ~arvbox/.ssh ~git/.ssh
-
-if ! test -s ~arvbox/.ssh/id_rsa ; then
-    ssh-keygen -t rsa -P '' -f .ssh/id_rsa
-    cp ~arvbox/.ssh/id_rsa ~arvbox/.ssh/id_rsa.pub ~git/.ssh
-fi
-
-if test -s ~arvbox/.ssh/known_hosts ; then
-    ssh-keygen -f ".ssh/known_hosts" -R localhost
-fi
-
-if ! test -f $ARVADOS_CONTAINER_PATH/gitolite-setup ; then
-    cd ~git
-
-    # Do a no-op login to populate known_hosts
-    # with the hostkey, so it won't try to ask
-    # about it later.
-    cp .ssh/id_rsa.pub .ssh/authorized_keys
-    ssh -o stricthostkeychecking=no git@localhost true
-    rm .ssh/authorized_keys
-
-    cp /usr/local/lib/arvbox/gitolite.rc .gitolite.rc
-
-    gitolite setup -pk .ssh/id_rsa.pub
-
-    if ! test -d gitolite-admin ; then
-        git clone git@localhost:gitolite-admin
-    fi
-
-    cd gitolite-admin
-    git config user.email arvados
-    git config user.name arvados
-    git config push.default simple
-    git push
-
-    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
-    # about it later.  Don't run anything,
-    # get the default gitolite behavior.
-    ssh -o stricthostkeychecking=no git@localhost
-fi
-
-prefix=$(arv --format=uuid user current | cut -d- -f1)
-
-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 > $ARVADOS_CONTAINER_PATH/arvados-git-uuid
-fi
-
-repo_uuid=$(cat $ARVADOS_CONTAINER_PATH/arvados-git-uuid)
-
-if ! test -s $ARVADOS_CONTAINER_PATH/arvados-git-link-uuid ; then
-    all_users_group_uuid="$prefix-j7d0g-fffffffffffffff"
-
-    set +e
-    read -rd $'\000' newlink <<EOF
-{
- "tail_uuid":"$all_users_group_uuid",
- "head_uuid":"$repo_uuid",
- "link_class":"permission",
- "name":"can_read"
-}
-EOF
-    set -e
-    link_uuid=$(arv --format=uuid link create --link "$newlink")
-    echo $link_uuid > $ARVADOS_CONTAINER_PATH/arvados-git-link-uuid
-fi
-
-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=$ARVADOS_CONTAINER_PATH/git/repositories/$repo_uuid.git fetch -f /usr/src/arvados main:main
-fi
-
-cd /usr/src/arvados/services/api
-
-if test -s $ARVADOS_CONTAINER_PATH/api_rails_env ; then
-  RAILS_ENV=$(cat $ARVADOS_CONTAINER_PATH/api_rails_env)
-else
-  RAILS_ENV=development
-fi
-
-git_user_key=$(cat ~git/.ssh/id_rsa.pub)
-
-cat > config/arvados-clients.yml <<EOF
-$RAILS_ENV:
-  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
-  gitolite_arvados_git_user_key: "$git_user_key"
-EOF
-
-while true ; do
-    flock $GEMLOCK bundle exec script/arvados-git-sync.rb $RAILS_ENV
-    sleep 120
-done
index 528c6be8274a145a3e4cd3ad61e7972078f5d6ea..1ac38035bcd75b96a32c5e93a2b068bebf4fb88a 100755 (executable)
@@ -233,75 +233,51 @@ http {
     }
   }
 
-  upstream arvados-git-httpd {
-    server localhost:${services[arv-git-httpd]};
+  upstream arvados-webshell {
+    server                localhost:${services[webshell]};
   }
   server {
-    listen *:${services[arv-git-httpd-ssl]} ssl default_server;
-    server_name arvados-git-httpd;
+    listen                ${services[webshell-ssl]} ssl;
+    server_name           arvados-webshell;
+
     proxy_connect_timeout 90s;
-    proxy_read_timeout 300s;
+    proxy_read_timeout    300s;
 
-    ssl on;
+    ssl                   on;
     ssl_certificate "${server_cert}";
     ssl_certificate_key "${server_cert_key}";
-    client_max_body_size 50m;
-
-    location  / {
-      proxy_pass http://arvados-git-httpd;
-      proxy_set_header Host \$http_host;
-      proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
-      proxy_set_header X-Forwarded-Proto https;
-      proxy_redirect off;
-    }
-  }
-
 
-upstream arvados-webshell {
-  server                localhost:${services[webshell]};
-}
-server {
-  listen                ${services[webshell-ssl]} ssl;
-  server_name           arvados-webshell;
-
-  proxy_connect_timeout 90s;
-  proxy_read_timeout    300s;
-
-  ssl                   on;
-  ssl_certificate "${server_cert}";
-  ssl_certificate_key "${server_cert_key}";
-
-  location / {
-    if (\$request_method = 'OPTIONS') {
-       add_header 'Access-Control-Allow-Origin' '*';
-       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
-       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
-       add_header 'Access-Control-Max-Age' 1728000;
-       add_header 'Content-Type' 'text/plain charset=UTF-8';
-       add_header 'Content-Length' 0;
-       return 204;
-    }
-    if (\$request_method = 'POST') {
-       add_header 'Access-Control-Allow-Origin' '*';
-       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
-       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
-    }
-    if (\$request_method = 'GET') {
-       add_header 'Access-Control-Allow-Origin' '*';
-       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
-       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
+    location / {
+      if (\$request_method = 'OPTIONS') {
+         add_header 'Access-Control-Allow-Origin' '*';
+         add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+         add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
+         add_header 'Access-Control-Max-Age' 1728000;
+         add_header 'Content-Type' 'text/plain charset=UTF-8';
+         add_header 'Content-Length' 0;
+         return 204;
+      }
+      if (\$request_method = 'POST') {
+         add_header 'Access-Control-Allow-Origin' '*';
+         add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+         add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
+      }
+      if (\$request_method = 'GET') {
+         add_header 'Access-Control-Allow-Origin' '*';
+         add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+         add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
+      }
+
+      proxy_ssl_session_reuse off;
+      proxy_read_timeout  90;
+      proxy_set_header    X-Forwarded-Proto https;
+      proxy_set_header    Host \$http_host;
+      proxy_set_header    X-Real-IP \$remote_addr;
+      proxy_set_header    X-Forwarded-For \$proxy_add_x_forwarded_for;
+      proxy_pass          http://arvados-webshell;
     }
-
-    proxy_ssl_session_reuse off;
-    proxy_read_timeout  90;
-    proxy_set_header    X-Forwarded-Proto https;
-    proxy_set_header    Host \$http_host;
-    proxy_set_header    X-Real-IP \$remote_addr;
-    proxy_set_header    X-Forwarded-For \$proxy_add_x_forwarded_for;
-    proxy_pass          http://arvados-webshell;
   }
 }
-}
 
 EOF
 
index 61430d02bd0d4111b76e08d8a6db4bf1c9e41b41..17b661442eb11ec2d22b3c67d7f79467592e1f08 100755 (executable)
@@ -7,9 +7,6 @@ set -e
 
 . /usr/local/lib/arvbox/common.sh
 
-git config --system "credential.http://$localip:${services[arv-git-httpd]}/.username" none
-git config --system "credential.http://$localip:${services[arv-git-httpd]}/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
-
 /usr/local/lib/arvbox/runsu.sh $0-service
 
 cd /usr/src/arvados/services/login-sync
index 16e686ab8069747227a9a206c100496f2929b8ce..ce95a256b08a1fd647f3020688a170d0fd7d0406 100644 (file)
@@ -166,7 +166,6 @@ arvados:
       NewUsersAreActive: true
       AutoAdminFirstUser: true
       AutoSetupNewUsers: true
-      AutoSetupNewUsersWithRepository: true
 
     Services:
       Controller:
index 271ab502908578c70a7373787cb0d29213a576f5..a2bfdb19b0ddf3d75c357c2c3e3ba19c2d4d801a 100644 (file)
@@ -128,7 +128,6 @@ arvados:
       NewUsersAreActive: true
       AutoAdminFirstUser: true
       AutoSetupNewUsers: true
-      AutoSetupNewUsersWithRepository: true
 
     Services:
       Controller:
index 9e3a293110afaa76c0ad3d9ca27300174747a287..03db62ab5de38af869cdd1e074f904ac0602dc6c 100644 (file)
@@ -131,7 +131,6 @@ arvados:
       NewUsersAreActive: true
       AutoAdminFirstUser: true
       AutoSetupNewUsers: true
-      AutoSetupNewUsersWithRepository: true
 
     Services:
       Controller: