[ARVADOS] updated: 01567e1c9675b9342187ae5872dbd2fd271fd838

git at public.curoverse.com git at public.curoverse.com
Sat Jan 25 01:44:34 EST 2014


Summary of changes:
 apps/admin/setup-new-user.rb                       |    2 +-
 .../app/assets/javascripts/keep_disks.js.coffee    |    0
 .../app/assets/stylesheets/keep_disks.css.scss     |    0
 .../app/controllers/keep_disks_controller.rb       |    2 +
 .../workbench}/app/helpers/keep_disks_helper.rb    |    0
 apps/workbench/app/models/arvados_api_client.rb    |    4 ++
 apps/workbench/app/models/arvados_base.rb          |   31 ++++++++--------
 apps/workbench/app/models/keep_disk.rb             |    5 +++
 apps/workbench/app/models/node.rb                  |    4 ++-
 .../app/views/layouts/application.html.erb         |   26 +++++++------
 apps/workbench/config/routes.rb                    |    1 +
 .../test/functional/keep_disks_controller_test.rb  |    4 ++
 .../test/unit/helpers/keep_disks_helper_test.rb    |    0
 apps/workbench/test/unit/keep_disk_test.rb         |    4 ++
 doc/admin/cheat_sheet.textile                      |    2 +-
 doc/api/resources.textile                          |    2 +-
 .../api/app/controllers/application_controller.rb  |   22 +++++++-----
 .../app/controllers/arvados/v1/jobs_controller.rb  |    1 +
 .../arvados/v1/keep_disks_controller.rb            |   37 ++++++++++---------
 .../app/controllers/arvados/v1/nodes_controller.rb |    1 +
 .../controllers/arvados/v1/schema_controller.rb    |    2 +
 .../arvados/v1/user_agreements_controller.rb       |    3 +-
 .../app/controllers/arvados/v1/users_controller.rb |    7 +++-
 .../arvados/v1/virtual_machines_controller.rb      |    1 +
 services/api/app/controllers/static_controller.rb  |    2 +
 .../app/controllers/user_sessions_controller.rb    |    1 +
 services/api/app/models/node.rb                    |   20 +++++++---
 services/api/config/environments/test.rb.example   |    1 +
 .../20140124222114_fix_link_kind_underscores.rb    |   17 +++++++++
 services/api/db/schema.rb                          |    2 +-
 services/api/lib/kind_and_etag.rb                  |    2 +-
 services/api/test/fixtures/groups.yml              |    6 +++
 services/api/test/fixtures/links.yml               |   32 +++++++++++++++++
 services/api/test/fixtures/virtual_machines.yml    |    4 ++
 .../arvados/v1/groups_controller_test.rb           |    8 ++++-
 .../arvados/v1/keep_disks_controller_test.rb       |   30 ++++++++--------
 .../functional/arvados/v1/links_controller_test.rb |   21 +++++++++++
 .../functional/arvados/v1/users_controller_test.rb |    2 +-
 .../api/test/integration/collections_api_test.rb   |   21 ++++++++++-
 39 files changed, 243 insertions(+), 87 deletions(-)
 copy {services/api => apps/workbench}/app/assets/javascripts/keep_disks.js.coffee (100%)
 copy {services/api => apps/workbench}/app/assets/stylesheets/keep_disks.css.scss (100%)
 create mode 100644 apps/workbench/app/controllers/keep_disks_controller.rb
 copy {services/api => apps/workbench}/app/helpers/keep_disks_helper.rb (100%)
 create mode 100644 apps/workbench/app/models/keep_disk.rb
 create mode 100644 apps/workbench/test/functional/keep_disks_controller_test.rb
 copy {services/api => apps/workbench}/test/unit/helpers/keep_disks_helper_test.rb (100%)
 create mode 100644 apps/workbench/test/unit/keep_disk_test.rb
 create mode 100644 services/api/db/migrate/20140124222114_fix_link_kind_underscores.rb
 create mode 100644 services/api/test/fixtures/virtual_machines.yml

       via  01567e1c9675b9342187ae5872dbd2fd271fd838 (commit)
       via  bdf067b92a5f0659a3c212c136a9cb9882f5924d (commit)
       via  453593b30c7e0fd59fe25d62772113103c86811b (commit)
       via  50a594a71b26bd091731ae52bcfed5ddd27a0c9f (commit)
       via  2a4f5a6e96c19ea65c35af705ab2561cccc2289a (commit)
       via  f66156884166e4f52327b744d1a8303f87b8ac63 (commit)
       via  f902ff3c640e3d7d279cb0ea112643e405c871f3 (commit)
       via  fa8ab6f3576881b80e2edf4b9066ca15f46f05b4 (commit)
       via  79548cf316986bb06dde783dbdfea9c5584ac886 (commit)
       via  92ccdadd52d417f5aa4494edaee0d2cec4cb3d43 (commit)
       via  4cda46df7b9c5493bfc49af70e5b27d66271a873 (commit)
       via  23aec28ff071904f5145ebb535a1c6d32e915f85 (commit)
       via  28590c1712c7c3c552cb5acbf01c482dc834b927 (commit)
      from  59994ce0b7623c84d2d633c7c0bac0966245932c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 01567e1c9675b9342187ae5872dbd2fd271fd838
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 22:43:36 2014 -0800

    Do not offer to let non-admin users create new keepDisks and nodes.

diff --git a/apps/workbench/app/models/keep_disk.rb b/apps/workbench/app/models/keep_disk.rb
index fd1c06d..8ced4eb 100644
--- a/apps/workbench/app/models/keep_disk.rb
+++ b/apps/workbench/app/models/keep_disk.rb
@@ -1,2 +1,5 @@
 class KeepDisk < ArvadosBase
+  def self.creatable?
+    current_user and current_user.is_admin
+  end
 end
diff --git a/apps/workbench/app/models/node.rb b/apps/workbench/app/models/node.rb
index 048ac59..0a324ff 100644
--- a/apps/workbench/app/models/node.rb
+++ b/apps/workbench/app/models/node.rb
@@ -1,5 +1,7 @@
 class Node < ArvadosBase
-  attr_accessor :object
+  def self.creatable?
+    current_user and current_user.is_admin
+  end
   def friendly_link_name
     self.hostname
   end

commit bdf067b92a5f0659a3c212c136a9cb9882f5924d
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 22:41:29 2014 -0800

    Change underscores to camelcase in "kind" strings as documented.

diff --git a/services/api/lib/kind_and_etag.rb b/services/api/lib/kind_and_etag.rb
index 38a9288..9df1289 100644
--- a/services/api/lib/kind_and_etag.rb
+++ b/services/api/lib/kind_and_etag.rb
@@ -8,7 +8,7 @@ module KindAndEtag
   end
 
   def kind
-    'arvados#' + self.class.to_s.underscore
+    'arvados#' + self.class.to_s.camelcase(:lower)
   end
 
   def etag

commit 453593b30c7e0fd59fe25d62772113103c86811b
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 22:40:37 2014 -0800

    Add virtualMachine test fixture.

diff --git a/services/api/test/fixtures/virtual_machines.yml b/services/api/test/fixtures/virtual_machines.yml
new file mode 100644
index 0000000..72e2130
--- /dev/null
+++ b/services/api/test/fixtures/virtual_machines.yml
@@ -0,0 +1,4 @@
+testvm:
+  uuid: zzzzz-2x53u-382brsig8rp3064
+  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
+  hostname: testvm.shell

commit 50a594a71b26bd091731ae52bcfed5ddd27a0c9f
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 22:38:54 2014 -0800

    Replace Admin menu with System menu (users can see those things too).

diff --git a/apps/workbench/app/views/layouts/application.html.erb b/apps/workbench/app/views/layouts/application.html.erb
index 53a39b8..1def50e 100644
--- a/apps/workbench/app/views/layouts/application.html.erb
+++ b/apps/workbench/app/views/layouts/application.html.erb
@@ -76,22 +76,23 @@
               <li><%= link_to 'Collections', collections_path %></li>
               <li><%= link_to 'Links', links_path %></li>
               <li><%= link_to 'Humans', humans_path %></li>
+              <li><%= link_to 'Specimens', specimens_path %></li>
               <li><%= link_to 'Traits', traits_path %></li>
             </ul>
           </li>
-          <% if current_user.is_admin %>
-            <li class="dropdown">
-              <a href="#" class="dropdown-toggle" data-toggle="dropdown">
-                Admin <b class="caret"></b>
-              </a>
-              <ul class="dropdown-menu">
-                <li><%= link_to 'Users', users_path %></li>
-                <li><%= link_to 'Groups', groups_path %></li>
-                <li><%= link_to 'Nodes', nodes_path %></li>
-                <li><%= link_to 'Keep disks', keep_disks_path %></li>
-              </ul>
-            </li>
-          <% end %>
+          <li class="dropdown">
+            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+              System <b class="caret"></b>
+            </a>
+            <ul class="dropdown-menu">
+              <% if current_user.is_admin %>
+              <li><%= link_to 'Users', users_path %></li>
+              <% end %>
+              <li><%= link_to 'Groups', groups_path %></li>
+              <li><%= link_to 'Compute nodes', nodes_path %></li>
+              <li><%= link_to 'Keep disks', keep_disks_path %></li>
+            </ul>
+          </li>
           <li class="dropdown">
             <a href="#" class="dropdown-toggle" data-toggle="dropdown">
               Docs <b class="caret"></b>

commit 2a4f5a6e96c19ea65c35af705ab2561cccc2289a
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 22:24:37 2014 -0800

    Always use symbol keys for object attribute names and string keys
    inside serialized hashes, rather than HashWithIndifferentAccess.
    
    This ensures serialized attributes go into the database as plain
    hashes with string keys, even when Rails was responsible for
    unserializing the data coming from the client.
    
    refs #1944
    refs #1987

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index fff52f5..dcb9c0c 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -220,6 +220,7 @@ class ApplicationController < ActionController::Base
     %w(created_at modified_by_client_uuid modified_by_user_uuid modified_at).each do |x|
       @attrs.delete x.to_sym
     end
+    @attrs = @attrs.symbolize_keys if @attrs.is_a? HashWithIndifferentAccess
     @attrs
   end
 
diff --git a/services/api/test/functional/arvados/v1/links_controller_test.rb b/services/api/test/functional/arvados/v1/links_controller_test.rb
index b3bc586..afecc18 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -1,4 +1,25 @@
 require 'test_helper'
 
 class Arvados::V1::LinksControllerTest < ActionController::TestCase
+
+  test "no symbol keys in serialized hash" do
+    link = {
+      properties: {username: 'testusername'},
+      link_class: 'test',
+      name: 'encoding',
+      tail_kind: 'arvados#user',
+      tail_uuid: users(:admin).uuid,
+      head_kind: 'arvados#virtualMachine',
+      head_uuid: virtual_machines(:testvm).uuid
+    }
+    authorize_with :admin
+    [link, link.to_json].each do |formatted_link|
+      post :create, link: formatted_link
+      assert_response :success
+      assert_not_nil assigns(:object)
+      assert_equal 'testusername', assigns(:object).properties['username']
+      assert_equal false, assigns(:object).properties.has_key?(:username)
+    end
+  end
+  
 end

commit f66156884166e4f52327b744d1a8303f87b8ac63
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 21:42:04 2014 -0800

    Ensure we always respond with json (except the redirect at the root
    URI).
    
    closes #1739

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 7ffa38a..fff52f5 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -1,6 +1,7 @@
 class ApplicationController < ActionController::Base
   include CurrentApiClient
 
+  respond_to :json
   protect_from_forgery
   around_filter :thread_with_auth_info, :except => [:render_error, :render_not_found]
 
diff --git a/services/api/app/controllers/static_controller.rb b/services/api/app/controllers/static_controller.rb
index 7765499..ba69b84 100644
--- a/services/api/app/controllers/static_controller.rb
+++ b/services/api/app/controllers/static_controller.rb
@@ -1,4 +1,5 @@
 class StaticController < ApplicationController
+  respond_to :json, :html
 
   skip_before_filter :find_object_by_uuid
   skip_before_filter :render_404_if_no_object
diff --git a/services/api/test/integration/collections_api_test.rb b/services/api/test/integration/collections_api_test.rb
index f2dfbee..076b234 100644
--- a/services/api/test/integration/collections_api_test.rb
+++ b/services/api/test/integration/collections_api_test.rb
@@ -3,11 +3,28 @@ require 'test_helper'
 class CollectionsApiTest < ActionDispatch::IntegrationTest
   fixtures :all
 
+  def jresponse
+    @jresponse ||= ActiveSupport::JSON.decode @response.body
+  end
+
   test "should get index" do
     get "/arvados/v1/collections", {:format => :json}, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:active).api_token}"}
-    @json_response ||= ActiveSupport::JSON.decode @response.body
     assert_response :success
-    assert_equal "arvados#collectionList", @json_response['kind']
+    assert_equal "arvados#collectionList", jresponse['kind']
+  end
+
+  test "controller 404 response is json" do
+    get "/arvados/v1/thingsthatdonotexist", {:format => :xml}, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:active).api_token}"}
+    assert_response 404
+    assert_equal 1, jresponse['errors'].length
+    assert_equal true, jresponse['errors'][0].is_a?(String)
+  end
+
+  test "object 404 response is json" do
+    get "/arvados/v1/groups/zzzzz-j7d0g-o5ba971173cup4f", {}, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:active).api_token}"}
+    assert_response 404
+    assert_equal 1, jresponse['errors'].length
+    assert_equal true, jresponse['errors'][0].is_a?(String)
   end
 
 end

commit f902ff3c640e3d7d279cb0ea112643e405c871f3
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 21:31:29 2014 -0800

    Do not run ec2 commands in test mode.

diff --git a/services/api/app/models/node.rb b/services/api/app/models/node.rb
index 08dc662..0934f2e 100644
--- a/services/api/app/models/node.rb
+++ b/services/api/app/models/node.rb
@@ -89,9 +89,11 @@ class Node < ArvadosModel
     if o[:ec2_instance_id]
       if !self.info[:ec2_instance_id] 
         self.info[:ec2_instance_id] = o[:ec2_instance_id]
-        tag_cmd = ("ec2-create-tags #{o[:ec2_instance_id]} " +
-                   "--tag 'Name=#{self.uuid}'")
-        `#{tag_cmd}`
+        if (Rails.configuration.compute_node_ec2_tag_enable rescue true)
+          tag_cmd = ("ec2-create-tags #{o[:ec2_instance_id]} " +
+                     "--tag 'Name=#{self.uuid}'")
+          `#{tag_cmd}`
+        end
       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]}"
@@ -113,7 +115,9 @@ class Node < ArvadosModel
       end while true
       self.hostname = self.class.hostname_for_slot(self.slot_number)
       if info[:ec2_instance_id]
-        `ec2-create-tags #{self.info[:ec2_instance_id]} --tag 'hostname=#{self.hostname}'`
+        if (Rails.configuration.compute_node_ec2_tag_enable rescue true)
+          `ec2-create-tags #{self.info[:ec2_instance_id]} --tag 'hostname=#{self.hostname}'`
+        end
       end
     end
 
@@ -144,12 +148,16 @@ class Node < ArvadosModel
     result.match(/INSTANCE\s*(i-[0-9a-f]+)/) do |m|
       instance_id = m[1]
       self.info[:ec2_instance_id] = instance_id
-      `ec2-create-tags #{instance_id} --tag 'Name=#{self.uuid}'`
+      if (Rails.configuration.compute_node_ec2_tag_enable rescue true)
+        `ec2-create-tags #{instance_id} --tag 'Name=#{self.uuid}'`
+      end
     end
     result.match(/SPOTINSTANCEREQUEST\s*(sir-[0-9a-f]+)/) do |m|
       sir_id = m[1]
       self.info[:ec2_sir_id] = sir_id
-      `ec2-create-tags #{sir_id} --tag 'Name=#{self.uuid}'`
+      if (Rails.configuration.compute_node_ec2_tag_enable rescue true)
+        `ec2-create-tags #{sir_id} --tag 'Name=#{self.uuid}'`
+      end
     end
     self.save!
   end
diff --git a/services/api/config/environments/test.rb.example b/services/api/config/environments/test.rb.example
index 39cbe69..82973ac 100644
--- a/services/api/config/environments/test.rb.example
+++ b/services/api/config/environments/test.rb.example
@@ -54,6 +54,7 @@ Server::Application.configure do
   # config.compute_node_ami = 'ami-cbca41a2'
   # config.compute_node_ec2run_args = '-g arvados-compute'
   # config.compute_node_spot_bid = 0.11
+  config.compute_node_ec2_tag_enable = false
 
   # config.compute_node_domain = `hostname --domain`.strip
 

commit fa8ab6f3576881b80e2edf4b9066ca15f46f05b4
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 21:08:58 2014 -0800

    Update tests to match recent permission changes; dry up "404 if no
    object found" logic; fix status codes in some error responses.

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 78284c8..7ffa38a 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -14,6 +14,9 @@ class ApplicationController < ActionController::Base
                                                   :render_error,
                                                   :render_not_found]
   before_filter :reload_object_before_update, :only => :update
+  before_filter :render_404_if_no_object, except: [:index, :create,
+                                                   :render_error,
+                                                   :render_not_found]
 
   attr_accessor :resource_attrs
 
@@ -26,11 +29,7 @@ class ApplicationController < ActionController::Base
   end
 
   def show
-    if @object
-      render json: @object.as_api_response
-    else
-      render_not_found("object not found")
-    end
+    render json: @object.as_api_response
   end
 
   def create
@@ -43,9 +42,6 @@ class ApplicationController < ActionController::Base
   end
 
   def update
-    if !@object
-      return render_not_found("object not found")
-    end
     attrs_to_update = resource_attrs.reject { |k,v|
       [:kind, :etag, :href].index k
     }
@@ -84,6 +80,10 @@ class ApplicationController < ActionController::Base
     :with => :render_error
   end
 
+  def render_404_if_no_object
+    render_not_found "Object not found" if !@object
+  end
+
   def render_error(e)
     logger.error e.inspect
     logger.error e.backtrace.collect { |x| x + "\n" }.join('') if e.backtrace
diff --git a/services/api/app/controllers/arvados/v1/jobs_controller.rb b/services/api/app/controllers/arvados/v1/jobs_controller.rb
index 42501d1..6c45f88 100644
--- a/services/api/app/controllers/arvados/v1/jobs_controller.rb
+++ b/services/api/app/controllers/arvados/v1/jobs_controller.rb
@@ -3,6 +3,7 @@ class Arvados::V1::JobsController < ApplicationController
   accept_attribute_as_json :runtime_constraints, Hash
   accept_attribute_as_json :tasks_summary, Hash
   skip_before_filter :find_object_by_uuid, :only => :queue
+  skip_before_filter :render_404_if_no_object, :only => :queue
 
   def index
     want_ancestor = @where[:script_version_descends_from]
diff --git a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
index cfe657e..7db295d 100644
--- a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
+++ b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
@@ -1,6 +1,5 @@
 class Arvados::V1::KeepDisksController < ApplicationController
   skip_before_filter :require_auth_scope_all, :only => :ping
-  skip_before_filter :find_object_by_uuid, :only => :ping
 
   def self._ping_requires_parameters
     {
@@ -14,27 +13,13 @@ class Arvados::V1::KeepDisksController < ApplicationController
     }
   end
   def ping
-    @object = Node.where(uuid: (params[:id] || params[:uuid])).first
-    if !@object
-      if current_user.andand.is_admin
-        @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
-        # KeepNode.ping() understands this update is properly
-        # authenticated.
-        params[:ping_secret] = @object.ping_secret
-      else
-        return render_not_found "object not found"
-      end
-    end
-
     params[:service_host] ||= request.env['REMOTE_ADDR']
     if not @object.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.
     render json: @object.as_api_response(:superuser)
   end
 
@@ -43,4 +28,20 @@ class Arvados::V1::KeepDisksController < ApplicationController
     @objects = model_class.where('1=1')
     super
   end
+
+  def find_object_by_uuid
+    @object = KeepDisk.where(uuid: (params[:id] || params[:uuid])).first
+    if !@object && 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
+      # KeepNode.ping() understands this update is properly
+      # authenticated.
+      params[:ping_secret] = @object.ping_secret
+    end
+  end
 end
diff --git a/services/api/app/controllers/arvados/v1/nodes_controller.rb b/services/api/app/controllers/arvados/v1/nodes_controller.rb
index 8f5b097..1461eec 100644
--- a/services/api/app/controllers/arvados/v1/nodes_controller.rb
+++ b/services/api/app/controllers/arvados/v1/nodes_controller.rb
@@ -1,6 +1,7 @@
 class Arvados::V1::NodesController < ApplicationController
   skip_before_filter :require_auth_scope_all, :only => :ping
   skip_before_filter :find_object_by_uuid, :only => :ping
+  skip_before_filter :render_404_if_no_object, :only => :ping
 
   def create
     @object = Node.new
diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb
index fc3c576..1c75488 100644
--- a/services/api/app/controllers/arvados/v1/schema_controller.rb
+++ b/services/api/app/controllers/arvados/v1/schema_controller.rb
@@ -1,5 +1,6 @@
 class Arvados::V1::SchemaController < ApplicationController
   skip_before_filter :find_object_by_uuid
+  skip_before_filter :render_404_if_no_object
   skip_before_filter :require_auth_scope_all
 
   def show
diff --git a/services/api/app/controllers/arvados/v1/user_agreements_controller.rb b/services/api/app/controllers/arvados/v1/user_agreements_controller.rb
index c1b81dd..4ad959e 100644
--- a/services/api/app/controllers/arvados/v1/user_agreements_controller.rb
+++ b/services/api/app/controllers/arvados/v1/user_agreements_controller.rb
@@ -1,6 +1,7 @@
 class Arvados::V1::UserAgreementsController < ApplicationController
   before_filter :admin_required, except: [:index, :sign, :signatures]
-  skip_before_filter :find_object, only: [:sign, :signatures]
+  skip_before_filter :find_object_by_uuid, only: [:sign, :signatures]
+  skip_before_filter :render_404_if_no_object, only: [:sign, :signatures]
 
   def model_class
     Link
diff --git a/services/api/app/controllers/arvados/v1/users_controller.rb b/services/api/app/controllers/arvados/v1/users_controller.rb
index 441db99..133df0f 100644
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@ -1,4 +1,9 @@
 class Arvados::V1::UsersController < ApplicationController
+  skip_before_filter :find_object_by_uuid, only:
+    [:activate, :event_stream, :current, :system]
+  skip_before_filter :render_404_if_no_object, only:
+    [:activate, :event_stream, :current, :system]
+
   def current
     @object = current_user
     show
@@ -75,7 +80,7 @@ class Arvados::V1::UsersController < ApplicationController
         else
           logger.warn "User #{@object.uuid} called users.activate " +
             "before signing agreements #{todo_uuids.inspect}"
-          raise ArgumentError.new \
+          raise ArvadosModel::PermissionDeniedError.new \
           "Cannot activate without user agreements #{todo_uuids.inspect}."
         end
       end
diff --git a/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb b/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
index 67b693b..10b4bd8 100644
--- a/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
+++ b/services/api/app/controllers/arvados/v1/virtual_machines_controller.rb
@@ -1,5 +1,6 @@
 class Arvados::V1::VirtualMachinesController < ApplicationController
   skip_before_filter :find_object_by_uuid, :only => :get_all_logins
+  skip_before_filter :render_404_if_no_object, :only => :get_all_logins
   skip_before_filter(:require_auth_scope_all,
                      :only => [:logins, :get_all_logins])
   before_filter(:admin_required,
diff --git a/services/api/app/controllers/static_controller.rb b/services/api/app/controllers/static_controller.rb
index f64e9a4..7765499 100644
--- a/services/api/app/controllers/static_controller.rb
+++ b/services/api/app/controllers/static_controller.rb
@@ -1,6 +1,7 @@
 class StaticController < ApplicationController
 
   skip_before_filter :find_object_by_uuid
+  skip_before_filter :render_404_if_no_object
   skip_before_filter :require_auth_scope_all, :only => [ :home, :login_failure ]
 
   def home
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 3ac47d4..046da5c 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -2,6 +2,7 @@ class UserSessionsController < ApplicationController
   before_filter :require_auth_scope_all, :only => [ :destroy ]
 
   skip_before_filter :find_object_by_uuid
+  skip_before_filter :render_404_if_no_object
 
   respond_to :html
 
diff --git a/services/api/test/fixtures/groups.yml b/services/api/test/fixtures/groups.yml
index c9b52dc..1a5125a 100644
--- a/services/api/test/fixtures/groups.yml
+++ b/services/api/test/fixtures/groups.yml
@@ -4,6 +4,12 @@ public:
   name: Public
   description: Public Group
 
+private:
+  uuid: zzzzz-j7d0g-rew6elm53kancon
+  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
+  name: Private
+  description: Private Group
+
 all_users:
   uuid: zzzzz-j7d0g-fffffffffffffff
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
diff --git a/services/api/test/fixtures/links.yml b/services/api/test/fixtures/links.yml
index e871c9b..24b76c6 100644
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@ -14,6 +14,38 @@ user_agreement_required:
   head_uuid: b519d9cb706a29fc7ea24dbea2f05851
   properties: {}
 
+user_agreement_readable:
+  uuid: zzzzz-o0j2j-qpf60gg4fwjlmex
+  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-d9tiejq69daie8f
+  modified_at: 2014-01-24 20:42:26 -0800
+  updated_at: 2014-01-24 20:42:26 -0800
+  tail_kind: arvados#group
+  tail_uuid: zzzzz-j7d0g-fffffffffffffff
+  link_class: permission
+  name: can_read
+  head_kind: arvados#collection
+  head_uuid: b519d9cb706a29fc7ea24dbea2f05851
+  properties: {}
+
+active_user_member_of_all_users_group:
+  uuid: zzzzz-o0j2j-ctbysaduejxfrs5
+  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-d9tiejq69daie8f
+  modified_at: 2014-01-24 20:42:26 -0800
+  updated_at: 2014-01-24 20:42:26 -0800
+  tail_kind: arvados#user
+  tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  link_class: permission
+  name: can_read
+  head_kind: arvados#group
+  head_uuid: zzzzz-j7d0g-fffffffffffffff
+  properties: {}
+
 user_agreement_signed_by_active:
   uuid: zzzzz-o0j2j-4x85a69tqlrud1z
   owner_uuid: zzzzz-tpzed-000000000000000
diff --git a/services/api/test/functional/arvados/v1/groups_controller_test.rb b/services/api/test/functional/arvados/v1/groups_controller_test.rb
index 6530181..15bdd7e 100644
--- a/services/api/test/functional/arvados/v1/groups_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/groups_controller_test.rb
@@ -2,9 +2,15 @@ require 'test_helper'
 
 class Arvados::V1::GroupsControllerTest < ActionController::TestCase
 
+  test "attempt to delete group without read or write access" do
+    authorize_with :active
+    post :destroy, id: groups(:private).uuid
+    assert_response 404
+  end
+
   test "attempt to delete group without write access" do
     authorize_with :active
-    post :destroy, id: groups(:public).uuid
+    post :destroy, id: groups(:all_users).uuid
     assert_response 403
   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
index 57cbd00..3ccfa05 100644
--- a/services/api/test/functional/arvados/v1/keep_disks_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/keep_disks_controller_test.rb
@@ -2,7 +2,7 @@ require 'test_helper'
 
 class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
 
-  test "add keep node with admin token" do
+  test "add keep disk with admin token" do
     authorize_with :admin
     post :ping, {
       ping_secret: '',          # required by discovery doc, but ignored
@@ -13,13 +13,13 @@ class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
     }
     assert_response :success
     assert_not_nil assigns(:object)
-    new_keep_node = JSON.parse(@response.body)
-    assert_not_nil new_keep_node['uuid']
-    assert_not_nil new_keep_node['ping_secret']
-    assert_not_equal '', new_keep_node['ping_secret']
+    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
 
-  test "add keep node with no filesystem_uuid" do
+  test "add keep disk with no filesystem_uuid" do
     authorize_with :admin
     opts = {
       ping_secret: '',
@@ -36,7 +36,7 @@ class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
     assert_not_nil JSON.parse(@response.body)['uuid']
   end
 
-  test "refuse to add keep node without admin token" do
+  test "refuse to add keep disk without admin token" do
     post :ping, {
       ping_secret: '',
       service_host: '::1',
@@ -46,7 +46,7 @@ class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
     assert_response 404
   end
 
-  test "ping from keep node" do
+  test "ping keep disk" do
     post :ping, {
       uuid: keep_disks(:nonfull).uuid,
       ping_secret: keep_disks(:nonfull).ping_secret,
@@ -54,12 +54,12 @@ class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
     }
     assert_response :success
     assert_not_nil assigns(:object)
-    keep_node = JSON.parse(@response.body)
-    assert_not_nil keep_node['uuid']
-    assert_not_nil keep_node['ping_secret']
+    keep_disk = JSON.parse(@response.body)
+    assert_not_nil keep_disk['uuid']
+    assert_not_nil keep_disk['ping_secret']
   end
 
-  test "should get index with ping_secret" do
+  test "admin should get index with ping_secret" do
     authorize_with :admin
     get :index
     assert_response :success
@@ -69,13 +69,13 @@ class Arvados::V1::KeepDisksControllerTest < ActionController::TestCase
     assert_not_nil items[0]['ping_secret']
   end
 
-  # inactive user does not see any keep disks
-  test "inactive user should get empty index" do
+  # 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_equal 0, items.size
+    assert_not_equal 0, items.size
   end
 
   # active user sees non-secret attributes of keep disks
diff --git a/services/api/test/functional/arvados/v1/users_controller_test.rb b/services/api/test/functional/arvados/v1/users_controller_test.rb
index 4b52c9b..6d129d8 100644
--- a/services/api/test/functional/arvados/v1/users_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/users_controller_test.rb
@@ -20,7 +20,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_response :success
     me = JSON.parse(@response.body)
     post :activate, uuid: me['uuid']
-    assert_response 422
+    assert_response 403
     get :current
     assert_response :success
     me = JSON.parse(@response.body)

commit 79548cf316986bb06dde783dbdfea9c5584ac886
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 14:59:51 2014 -0800

    Use discovery document to build infix->kind map instead of using a
    hard-coded list.

diff --git a/apps/workbench/app/models/arvados_api_client.rb b/apps/workbench/app/models/arvados_api_client.rb
index a8bcb4d..b2d774c 100644
--- a/apps/workbench/app/models/arvados_api_client.rb
+++ b/apps/workbench/app/models/arvados_api_client.rb
@@ -138,6 +138,10 @@ class ArvadosApiClient
     @arvados_schema ||= api 'schema', ''
   end
 
+  def discovery
+    @discovery ||= api '../../discovery/v1/apis/arvados/v1/rest', ''
+  end
+
   def kind_class(kind)
     kind.match(/^arvados\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
   end
diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index 02e7bce..5c7e44f 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -3,21 +3,22 @@ class ArvadosBase < ActiveRecord::Base
   attr_accessor :attribute_sortkey
 
   def self.uuid_infix_object_kind
-    @@uuid_infix_object_kind ||= {
-      '4zz18' => 'arvados#collection',
-      'tpzed' => 'arvados#user',
-      'ozdt8' => 'arvados#apiClient',
-      '8i9sb' => 'arvados#job',
-      'o0j2j' => 'arvados#link',
-      '57u5n' => 'arvados#log',
-      'j58dm' => 'arvados#specimen',
-      'p5p6p' => 'arvados#pipelineTemplate',
-      'mxsvm' => 'arvados#pipelineTemplate', # legacy Pipeline objects
-      'd1hrv' => 'arvados#pipelineInstance',
-      'uo14g' => 'arvados#pipelineInstance', # legacy PipelineInstance objects
-      'j7d0g' => 'arvados#group',
-      'ldvyl' => 'arvados#group' # only needed for legacy Project objects
-    }
+    @@uuid_infix_object_kind ||=
+      begin
+        infix_kind = {}
+        $arvados_api_client.discovery[:schemas].each do |name, schema|
+          if schema[:uuidPrefix]
+            infix_kind[schema[:uuidPrefix]] =
+              'arvados#' + name.to_s.camelcase(:lower)
+          end
+        end
+
+        # Recognize obsolete types.
+        infix_kind.
+          merge('mxsvm' => 'arvados#pipelineTemplate', # Pipeline
+                'uo14g' => 'arvados#pipelineInstance', # PipelineInvocation
+                'ldvyl' => 'arvados#group') # Project
+      end
   end
 
   def initialize(*args)

commit 92ccdadd52d417f5aa4494edaee0d2cec4cb3d43
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 14:59:07 2014 -0800

    Provide UUID prefix used for each schema in discovery document.

diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb
index e57ca52..fc3c576 100644
--- a/services/api/app/controllers/arvados/v1/schema_controller.rb
+++ b/services/api/app/controllers/arvados/v1/schema_controller.rb
@@ -148,6 +148,7 @@ class Arvados::V1::SchemaController < ApplicationController
           id: k.to_s,
           description: k.to_s,
           type: "object",
+          uuidPrefix: (k.respond_to?(:uuid_prefix) ? k.uuid_prefix : nil),
           properties: {
             uuid: {
               type: "string",

commit 4cda46df7b9c5493bfc49af70e5b27d66271a873
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 14:57:21 2014 -0800

    Fix crash on error pages by removing before_filters that assume there
    is a current_user.

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 62ed762..78284c8 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -10,7 +10,9 @@ class ApplicationController < ActionController::Base
 
   before_filter :load_where_param, :only => :index
   before_filter :find_objects_for_index, :only => :index
-  before_filter :find_object_by_uuid, :except => [:index, :create]
+  before_filter :find_object_by_uuid, :except => [:index, :create,
+                                                  :render_error,
+                                                  :render_not_found]
   before_filter :reload_object_before_update, :only => :update
 
   attr_accessor :resource_attrs

commit 23aec28ff071904f5145ebb535a1c6d32e915f85
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 14:54:38 2014 -0800

    Change underscores to camelcase in "kind" strings as documented.

diff --git a/apps/admin/setup-new-user.rb b/apps/admin/setup-new-user.rb
index 61c711f..09fd8a7 100755
--- a/apps/admin/setup-new-user.rb
+++ b/apps/admin/setup-new-user.rb
@@ -151,7 +151,7 @@ log.info { "repo permission: " + repo_perm[:uuid] }
 login_perm = arv.link.create(link: {
                                tail_kind: 'arvados#user',
                                tail_uuid: user[:uuid],
-                               head_kind: 'arvados#virtual_machine',
+                               head_kind: 'arvados#virtualMachine',
                                head_uuid: vm[:uuid],
                                link_class: 'permission',
                                name: 'can_login',
diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index a648a8f..02e7bce 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -6,15 +6,15 @@ class ArvadosBase < ActiveRecord::Base
     @@uuid_infix_object_kind ||= {
       '4zz18' => 'arvados#collection',
       'tpzed' => 'arvados#user',
-      'ozdt8' => 'arvados#api_client',
+      'ozdt8' => 'arvados#apiClient',
       '8i9sb' => 'arvados#job',
       'o0j2j' => 'arvados#link',
       '57u5n' => 'arvados#log',
       'j58dm' => 'arvados#specimen',
-      'p5p6p' => 'arvados#pipeline_template',
-      'mxsvm' => 'arvados#pipeline_template', # legacy Pipeline objects
-      'd1hrv' => 'arvados#pipeline_instance',
-      'uo14g' => 'arvados#pipeline_instance', # legacy PipelineInstance objects
+      'p5p6p' => 'arvados#pipelineTemplate',
+      'mxsvm' => 'arvados#pipelineTemplate', # legacy Pipeline objects
+      'd1hrv' => 'arvados#pipelineInstance',
+      'uo14g' => 'arvados#pipelineInstance', # legacy PipelineInstance objects
       'j7d0g' => 'arvados#group',
       'ldvyl' => 'arvados#group' # only needed for legacy Project objects
     }
diff --git a/doc/admin/cheat_sheet.textile b/doc/admin/cheat_sheet.textile
index 4c26877..78841f4 100644
--- a/doc/admin/cheat_sheet.textile
+++ b/doc/admin/cheat_sheet.textile
@@ -41,7 +41,7 @@ read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
 {
 "tail_kind":"arvados#user",
 "tail_uuid":"$user_uuid",
-"head_kind":"arvados#virtual_machine",
+"head_kind":"arvados#virtualMachine",
 "head_uuid":"$vm_uuid",
 "link_class":"permission",
 "name":"can_login",
diff --git a/doc/api/resources.textile b/doc/api/resources.textile
index f7c1e69..2783af6 100644
--- a/doc/api/resources.textile
+++ b/doc/api/resources.textile
@@ -35,7 +35,7 @@ h2. Attributes of resource lists
 
 table(table table-bordered table-condensed).
 |*Attribute*|*Type*|*Description*|*Example*|
-|kind|string|@arvados#{resource_type}_list@|@arvados#project_list@|
+|kind|string|@arvados#{resource_type}List@|@arvados#projectList@|
 |etag|string|The ETag[1] of the resource list|@cd3o1wi9sf934saajykawrz2e@|
 |self_link|string|||
 |next_page_token|string|||
diff --git a/services/api/db/migrate/20140124222114_fix_link_kind_underscores.rb b/services/api/db/migrate/20140124222114_fix_link_kind_underscores.rb
new file mode 100644
index 0000000..3d13c00
--- /dev/null
+++ b/services/api/db/migrate/20140124222114_fix_link_kind_underscores.rb
@@ -0,0 +1,17 @@
+class FixLinkKindUnderscores < ActiveRecord::Migration
+  def up
+    update_sql <<-EOS
+UPDATE links
+ SET head_kind = 'arvados#virtualMachine'
+ WHERE head_kind = 'arvados#virtual_machine'
+EOS
+  end
+
+  def down
+    update_sql <<-EOS
+UPDATE links
+ SET head_kind = 'arvados#virtual_machine'
+ WHERE head_kind = 'arvados#virtualMachine'
+EOS
+  end
+end
diff --git a/services/api/db/schema.rb b/services/api/db/schema.rb
index 99b6129..62d41f6 100644
--- a/services/api/db/schema.rb
+++ b/services/api/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20140117231056) do
+ActiveRecord::Schema.define(:version => 20140124222114) do
 
   create_table "api_client_authorizations", :force => true do |t|
     t.string   "api_token",                                           :null => false

commit 28590c1712c7c3c552cb5acbf01c482dc834b927
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jan 24 10:17:21 2014 -0800

    Add /keep_disks page to Admin menu.

diff --git a/apps/workbench/app/assets/javascripts/keep_disks.js.coffee b/apps/workbench/app/assets/javascripts/keep_disks.js.coffee
new file mode 100644
index 0000000..7615679
--- /dev/null
+++ b/apps/workbench/app/assets/javascripts/keep_disks.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/apps/workbench/app/assets/stylesheets/keep_disks.css.scss b/apps/workbench/app/assets/stylesheets/keep_disks.css.scss
new file mode 100644
index 0000000..1f7780b
--- /dev/null
+++ b/apps/workbench/app/assets/stylesheets/keep_disks.css.scss
@@ -0,0 +1,3 @@
+// 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/apps/workbench/app/controllers/keep_disks_controller.rb b/apps/workbench/app/controllers/keep_disks_controller.rb
new file mode 100644
index 0000000..482a2d3
--- /dev/null
+++ b/apps/workbench/app/controllers/keep_disks_controller.rb
@@ -0,0 +1,2 @@
+class KeepDisksController < ApplicationController
+end
diff --git a/apps/workbench/app/helpers/keep_disks_helper.rb b/apps/workbench/app/helpers/keep_disks_helper.rb
new file mode 100644
index 0000000..9cf6b4a
--- /dev/null
+++ b/apps/workbench/app/helpers/keep_disks_helper.rb
@@ -0,0 +1,2 @@
+module KeepDisksHelper
+end
diff --git a/apps/workbench/app/models/keep_disk.rb b/apps/workbench/app/models/keep_disk.rb
new file mode 100644
index 0000000..fd1c06d
--- /dev/null
+++ b/apps/workbench/app/models/keep_disk.rb
@@ -0,0 +1,2 @@
+class KeepDisk < ArvadosBase
+end
diff --git a/apps/workbench/app/views/layouts/application.html.erb b/apps/workbench/app/views/layouts/application.html.erb
index 2c44a26..53a39b8 100644
--- a/apps/workbench/app/views/layouts/application.html.erb
+++ b/apps/workbench/app/views/layouts/application.html.erb
@@ -88,6 +88,7 @@
                 <li><%= link_to 'Users', users_path %></li>
                 <li><%= link_to 'Groups', groups_path %></li>
                 <li><%= link_to 'Nodes', nodes_path %></li>
+                <li><%= link_to 'Keep disks', keep_disks_path %></li>
               </ul>
             </li>
           <% end %>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index cf0dcec..f2480c6 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -1,6 +1,7 @@
 ArvadosWorkbench::Application.routes.draw do
   themes_for_rails
 
+  resources :keep_disks
   resources :user_agreements
   post '/user_agreements/sign' => 'user_agreements#sign'
   get '/user_agreements/signatures' => 'user_agreements#signatures'
diff --git a/apps/workbench/test/functional/keep_disks_controller_test.rb b/apps/workbench/test/functional/keep_disks_controller_test.rb
new file mode 100644
index 0000000..d6f2954
--- /dev/null
+++ b/apps/workbench/test/functional/keep_disks_controller_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class KeepDisksControllerTest < ActionController::TestCase
+end
diff --git a/apps/workbench/test/unit/helpers/keep_disks_helper_test.rb b/apps/workbench/test/unit/helpers/keep_disks_helper_test.rb
new file mode 100644
index 0000000..a3b064e
--- /dev/null
+++ b/apps/workbench/test/unit/helpers/keep_disks_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class KeepDisksHelperTest < ActionView::TestCase
+end
diff --git a/apps/workbench/test/unit/keep_disk_test.rb b/apps/workbench/test/unit/keep_disk_test.rb
new file mode 100644
index 0000000..42ab63b
--- /dev/null
+++ b/apps/workbench/test/unit/keep_disk_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class KeepDiskTest < ActiveSupport::TestCase
+end

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list