[ARVADOS] created: d334bf63821506a63afddb24c28ba86896958b03

git at public.curoverse.com git at public.curoverse.com
Tue Mar 25 14:22:50 EDT 2014


        at  d334bf63821506a63afddb24c28ba86896958b03 (commit)


commit d334bf63821506a63afddb24c28ba86896958b03
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 25 14:22:33 2014 -0400

    Removed '_kind' from documentation.

diff --git a/doc/admin/cheat_sheet.html.textile.liquid b/doc/admin/cheat_sheet.html.textile.liquid
index daaf012..83fa5e8 100644
--- a/doc/admin/cheat_sheet.html.textile.liquid
+++ b/doc/admin/cheat_sheet.html.textile.liquid
@@ -38,9 +38,7 @@ target_username=xxxxxxxchangeme
 
 read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
 {
-"tail_kind":"arvados#user",
 "tail_uuid":"$user_uuid",
-"head_kind":"arvados#virtualMachine",
 "head_uuid":"$vm_uuid",
 "link_class":"permission",
 "name":"can_login",
@@ -60,9 +58,7 @@ repo_username=xxxxxxxchangeme
 
 read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
 {
-"tail_kind":"arvados#user",
 "tail_uuid":"$user_uuid",
-"head_kind":"arvados#repository",
 "head_uuid":"$repo_uuid",
 "link_class":"permission",
 "name":"can_write",
diff --git a/doc/api/schema/Link.html.textile.liquid b/doc/api/schema/Link.html.textile.liquid
index 1191f87..8ae43b3 100644
--- a/doc/api/schema/Link.html.textile.liquid
+++ b/doc/api/schema/Link.html.textile.liquid
@@ -27,11 +27,9 @@ Each link has, in addition to the usual "attributes of Arvados resources":/api/r
 table(table table-bordered table-condensed).
 |_. Attribute|_. Type|_. Description|
 |tail_uuid|string|Object UUID at the tail (start, source, origin) of this link|
-|tail_kind|string|Object kind at the tail (start, source, origin) of this link|
 |link_class|string|Class (see below)|
 |name|string|Link type (see below)|
 |head_uuid|string|Object UUID at the head (end, destination, target) of this link|
-|head_kind|string|Object kind at the head (end, destination, target) of this link|
 |properties{}|list|Additional information, expressed as a key→value hash. Key: string. Value: string, number, array, or hash.|
 
 h2. Link classes
diff --git a/doc/api/schema/Log.html.textile.liquid b/doc/api/schema/Log.html.textile.liquid
index c9530f4..aa5ddda 100644
--- a/doc/api/schema/Log.html.textile.liquid
+++ b/doc/api/schema/Log.html.textile.liquid
@@ -30,7 +30,6 @@ Each Log has, in addition to the usual "attributes of Arvados resources":/api/re
 
 table(table table-bordered table-condensed).
 |_. Attribute|_. Type|_. Description|_. Example|
-|object_kind|string|||
 |object_uuid|string|||
 |event_at|datetime|||
 |event_type|string|A user-defined category or type for this event.|@LOGIN@|
diff --git a/doc/install/create-standard-objects.html.textile.liquid b/doc/install/create-standard-objects.html.textile.liquid
index 678127b..b56a503 100644
--- a/doc/install/create-standard-objects.html.textile.liquid
+++ b/doc/install/create-standard-objects.html.textile.liquid
@@ -33,9 +33,7 @@ echo "Arvados repository uuid is $repo_uuid"
 
 read -rd $'\000' newlink <<EOF; arv link create --link "$newlink" 
 {
- "tail_kind":"arvados#group",
  "tail_uuid":"$all_users_group_uuid",
- "head_kind":"arvados#repository",
  "head_uuid":"$repo_uuid",
  "link_class":"permission",
  "name":"can_read" 
diff --git a/doc/user/topics/tutorial-trait-search.html.textile.liquid b/doc/user/topics/tutorial-trait-search.html.textile.liquid
index 001fbbc..a79495e 100644
--- a/doc/user/topics/tutorial-trait-search.html.textile.liquid
+++ b/doc/user/topics/tutorial-trait-search.html.textile.liquid
@@ -67,22 +67,22 @@ h2. Finding humans with the selected trait
 We query the "links" resource to find humans that report the selected trait.  Links are directional connections between Arvados data items, for example, from a human to their reported traits.
 
 <notextile>
-<pre><code>>>> <span class="userinput">trait_query = {
-    'link_class': 'human_trait',
-    'tail_kind': 'arvados#human',
-    'head_uuid': non_melanoma_cancer
-  }
+<pre><code>>>> <span class="userinput">trait_filter = [
+    ['link_class', '=', 'human_trait'],
+    ['tail_uuid', 'is_a', 'arvados#human'],
+    ['head_uuid', '=', non_melanoma_cancer],
+  ]
 </code></pre>
 </notextile>
 
-* @'link_class'@ queries for links that describe the traits of a particular human.
-* @'tail_kind'@ queries for links where the tail of the link is a human.
-* @'head_uuit'@ queries for links where the head of the link is a specific data item.
+* @['link_class', '=', 'human_trait']@ filters on links that connect phenotype traits to individuals in the database.
+* @['tail_uuid', 'is_a', 'arvados#human']@ filters that the "tail" must be a "human" database object.
+* @['head_uuid', '=', non_melanoma_cancer]@ filters that the "head" of the link must connect to the "trait" database object non_melanoma_cancer .
 
 The query will return links that match all three conditions.
 
 <notextile>
-<pre><code>>>> <span class="userinput">trait_links = arvados.api().links().list(limit=1000, where=trait_query).execute()</span>
+<pre><code>>>> <span class="userinput">trait_links = arvados.api().links().list(limit=1000, filters=trait_filter).execute()</span>
 </code></pre>
 </notextile>
 

commit 3da41130c997f36f462feb1b34efbec53697d91e
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 25 14:06:44 2014 -0400

    Actually remove _kind columns from schema and tests.

diff --git a/services/api/app/models/link.rb b/services/api/app/models/link.rb
index bb22156..8e17ce6 100644
--- a/services/api/app/models/link.rb
+++ b/services/api/app/models/link.rb
@@ -13,11 +13,9 @@ class Link < ArvadosModel
   attr_accessor :tail
 
   api_accessible :user, extend: :common do |t|
-    t.add :tail_kind
     t.add :tail_uuid
     t.add :link_class
     t.add :name
-    t.add :head_kind
     t.add :head_uuid
     t.add :head, :if => :head
     t.add :tail, :if => :tail
diff --git a/services/api/app/models/log.rb b/services/api/app/models/log.rb
index 29efc9d..bf3c8d3 100644
--- a/services/api/app/models/log.rb
+++ b/services/api/app/models/log.rb
@@ -7,7 +7,6 @@ class Log < ArvadosModel
   attr_accessor :object
 
   api_accessible :user, extend: :common do |t|
-    t.add :object_kind
     t.add :object_uuid
     t.add :object, :if => :object
     t.add :event_at
diff --git a/services/api/db/migrate/20140325175653_remove_kind_columns.rb b/services/api/db/migrate/20140325175653_remove_kind_columns.rb
new file mode 100644
index 0000000..115048d
--- /dev/null
+++ b/services/api/db/migrate/20140325175653_remove_kind_columns.rb
@@ -0,0 +1,13 @@
+class RemoveKindColumns < ActiveRecord::Migration
+  def up
+    remove_column :links, :head_kind
+    remove_column :links, :tail_kind
+    remove_column :logs, :object_kind
+  end
+
+  def down
+    add_column :links, :head_kind, :string
+    add_column :links, :tail_kind, :string
+    add_column :logs, :object_kind, :string
+  end
+end
diff --git a/services/api/db/schema.rb b/services/api/db/schema.rb
index df6ea9b..53655d2 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 => 20140129184311) do
+ActiveRecord::Schema.define(:version => 20140325175653) do
 
   create_table "api_client_authorizations", :force => true do |t|
     t.string   "api_token",                                           :null => false
@@ -70,7 +70,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "collections", :force => true do |t|
     t.string   "locator"
     t.string   "owner_uuid"
-    t.datetime "created_at",                          :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
@@ -80,7 +80,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "redundancy_confirmed_by_client_uuid"
     t.datetime "redundancy_confirmed_at"
     t.integer  "redundancy_confirmed_as"
-    t.datetime "updated_at",                          :null => false
+    t.datetime "updated_at"
     t.string   "uuid"
     t.text     "manifest_text"
   end
@@ -104,8 +104,8 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "repository_name"
     t.string   "sha1"
     t.string   "message"
-    t.datetime "created_at",      :null => false
-    t.datetime "updated_at",      :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "commits", ["repository_name", "sha1"], :name => "index_commits_on_repository_name_and_sha1", :unique => true
@@ -133,8 +133,8 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
     t.text     "properties"
-    t.datetime "created_at",              :null => false
-    t.datetime "updated_at",              :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "humans", ["uuid"], :name => "index_humans_on_uuid", :unique => true
@@ -182,13 +182,15 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.boolean  "running"
     t.boolean  "success"
     t.string   "output"
-    t.datetime "created_at",               :null => false
-    t.datetime "updated_at",               :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
     t.string   "priority"
     t.string   "is_locked_by_uuid"
     t.string   "log"
     t.text     "tasks_summary"
     t.text     "runtime_constraints"
+    t.boolean  "nondeterministic"
+    t.string   "repository"
   end
 
   add_index "jobs", ["created_at"], :name => "index_jobs_on_created_at"
@@ -232,25 +234,21 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "links", :force => true do |t|
     t.string   "uuid"
     t.string   "owner_uuid"
-    t.datetime "created_at",              :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
     t.string   "tail_uuid"
-    t.string   "tail_kind"
     t.string   "link_class"
     t.string   "name"
     t.string   "head_uuid"
     t.text     "properties"
-    t.datetime "updated_at",              :null => false
-    t.string   "head_kind"
+    t.datetime "updated_at"
   end
 
   add_index "links", ["created_at"], :name => "index_links_on_created_at"
-  add_index "links", ["head_kind"], :name => "index_links_on_head_kind"
   add_index "links", ["head_uuid"], :name => "index_links_on_head_uuid"
   add_index "links", ["modified_at"], :name => "index_links_on_modified_at"
-  add_index "links", ["tail_kind"], :name => "index_links_on_tail_kind"
   add_index "links", ["tail_uuid"], :name => "index_links_on_tail_uuid"
   add_index "links", ["uuid"], :name => "index_links_on_uuid", :unique => true
 
@@ -259,7 +257,6 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "owner_uuid"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
-    t.string   "object_kind"
     t.string   "object_uuid"
     t.datetime "event_at"
     t.string   "event_type"
@@ -274,7 +271,6 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   add_index "logs", ["event_at"], :name => "index_logs_on_event_at"
   add_index "logs", ["event_type"], :name => "index_logs_on_event_type"
   add_index "logs", ["modified_at"], :name => "index_logs_on_modified_at"
-  add_index "logs", ["object_kind"], :name => "index_logs_on_object_kind"
   add_index "logs", ["object_uuid"], :name => "index_logs_on_object_uuid"
   add_index "logs", ["summary"], :name => "index_logs_on_summary"
   add_index "logs", ["uuid"], :name => "index_logs_on_uuid", :unique => true
@@ -305,7 +301,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "pipeline_instances", :force => true do |t|
     t.string   "uuid"
     t.string   "owner_uuid"
-    t.datetime "created_at",                                 :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
@@ -314,7 +310,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.text     "components"
     t.boolean  "success"
     t.boolean  "active",                  :default => false
-    t.datetime "updated_at",                                 :null => false
+    t.datetime "updated_at"
     t.text     "properties"
   end
 
diff --git a/services/api/test/fixtures/links.yml b/services/api/test/fixtures/links.yml
index a0832d6..523c466 100644
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@ -6,11 +6,9 @@ user_agreement_required:
   modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
   modified_at: 2013-12-26T19:52:21Z
   updated_at: 2013-12-26T19:52:21Z
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-000000000000000
   link_class: signature
   name: require
-  head_kind: arvados#collection
   head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
@@ -22,11 +20,9 @@ user_agreement_readable:
   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+93
   properties: {}
 
@@ -38,11 +34,9 @@ active_user_member_of_all_users_group:
   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: {}
 
@@ -54,11 +48,9 @@ active_user_can_manage_system_owned_group:
   modified_by_user_uuid: zzzzz-tpzed-000000000000000
   modified_at: 2014-02-03 15:42:26 -0800
   updated_at: 2014-02-03 15:42:26 -0800
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   link_class: permission
   name: can_manage
-  head_kind: arvados#group
   head_uuid: zzzzz-j7d0g-8ulrifv67tve5sx
   properties: {}
 
@@ -70,11 +62,9 @@ user_agreement_signed_by_active:
   modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   modified_at: 2013-12-26T20:52:21Z
   updated_at: 2013-12-26T20:52:21Z
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   link_class: signature
   name: click
-  head_kind: arvados#collection
   head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
@@ -86,11 +76,9 @@ user_agreement_signed_by_inactive:
   modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
   modified_at: 2013-12-26T20:52:21Z
   updated_at: 2013-12-26T20:52:21Z
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-7sg468ezxwnodxs
   link_class: signature
   name: click
-  head_kind: arvados#collection
   head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
@@ -102,11 +90,9 @@ spectator_user_member_of_all_users_group:
   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-l1s2piq4t4mps8r
   link_class: permission
   name: can_read
-  head_kind: arvados#group
   head_uuid: zzzzz-j7d0g-fffffffffffffff
   properties: {}
 
@@ -118,11 +104,9 @@ inactive_user_member_of_all_users_group:
   modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
   modified_at: 2013-12-26T20:52:21Z
   updated_at: 2013-12-26T20:52:21Z
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-x9kqpd79egh49c7
   link_class: permission
   name: can_read
-  head_kind: arvados#group
   head_uuid: zzzzz-j7d0g-fffffffffffffff
   properties: {}
 
@@ -134,11 +118,9 @@ inactive_signed_ua_user_member_of_all_users_group:
   modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
   modified_at: 2013-12-26T20:52:21Z
   updated_at: 2013-12-26T20:52:21Z
-  tail_kind: arvados#user
   tail_uuid: zzzzz-tpzed-7sg468ezxwnodxs
   link_class: permission
   name: can_read
-  head_kind: arvados#group
   head_uuid: zzzzz-j7d0g-fffffffffffffff
   properties: {}
 
@@ -150,11 +132,9 @@ foo_file_readable_by_active:
   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_kind: arvados#user
   tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   link_class: permission
   name: can_read
-  head_kind: arvados#collection
   head_uuid: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
   properties: {}
 
@@ -166,11 +146,9 @@ bar_file_readable_by_active:
   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_kind: arvados#user
   tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   link_class: permission
   name: can_read
-  head_kind: arvados#collection
   head_uuid: fa7aeb5140e2848d39b416daeef4ffc5+45
   properties: {}
 
@@ -182,11 +160,9 @@ bar_file_readable_by_spectator:
   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_kind: arvados#user
   tail_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
   link_class: permission
   name: can_read
-  head_kind: arvados#collection
   head_uuid: fa7aeb5140e2848d39b416daeef4ffc5+45
   properties: {}
 
@@ -198,11 +174,9 @@ baz_file_publicly_readable:
   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_kind: arvados#group
   tail_uuid: zzzzz-j7d0g-fffffffffffffff
   link_class: permission
   name: can_read
-  head_kind: arvados#collection
   head_uuid: ea10d51bcf88862dbcc36eb292017dfd+45
   properties: {}
 
@@ -214,11 +188,9 @@ barbaz_job_readable_by_spectator:
   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_kind: arvados#user
   tail_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
   link_class: permission
   name: can_read
-  head_kind: arvados#job
   head_uuid: zzzzz-8i9sb-cjs4pklxxjykyuq
   properties: {}
 
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 0f84075..d2863f3 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -7,9 +7,7 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
       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
diff --git a/services/api/test/integration/permissions_test.rb b/services/api/test/integration/permissions_test.rb
index c6597d5..8ae56b4 100644
--- a/services/api/test/integration/permissions_test.rb
+++ b/services/api/test/integration/permissions_test.rb
@@ -15,11 +15,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#user',
         tail_uuid: users(:spectator).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#collection',
         head_uuid: collections(:foo_file).uuid,
         properties: {}
       }
@@ -30,11 +28,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#user',
         tail_uuid: users(:spectator).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#collection',
         head_uuid: collections(:foo_file).uuid,
         properties: {}
       }
@@ -72,11 +68,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#user',
         tail_uuid: users(:spectator).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#group',
         head_uuid: groups(:private).uuid,
         properties: {}
       }
@@ -91,11 +85,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#group',
         tail_uuid: groups(:private).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#collection',
         head_uuid: collections(:foo_file).uuid,
         properties: {}
       }
@@ -130,11 +122,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#group',
         tail_uuid: groups(:private).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#collection',
         head_uuid: collections(:foo_file).uuid,
         properties: {}
       }
@@ -149,11 +139,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#user',
         tail_uuid: users(:spectator).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#group',
         head_uuid: groups(:private).uuid,
         properties: {}
       }
@@ -187,11 +175,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#user',
         tail_uuid: users(:spectator).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#group',
         head_uuid: groups(:private).uuid,
         properties: {}
       }
@@ -202,11 +188,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#group',
         tail_uuid: groups(:private).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#group',
         head_uuid: groups(:empty_lonely_group).uuid,
         properties: {}
       }
@@ -217,11 +201,9 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     post "/arvados/v1/links", {
       :format => :json,
       :link => {
-        tail_kind: 'arvados#group',
         tail_uuid: groups(:empty_lonely_group).uuid,
         link_class: 'permission',
         name: 'can_read',
-        head_kind: 'arvados#collection',
         head_uuid: collections(:foo_file).uuid,
         properties: {}
       }

commit f60df78aec5cdc02ad50661f41a7d422e63742fc
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 25 13:56:08 2014 -0400

    Removed internal uses of _kind column in API server.  Tests pass.

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 979e2d1..70a2a4c 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -164,16 +164,13 @@ class ApplicationController < ActionController::Base
           operand = [operand] unless operand.is_a? Array
           cond = []
           operand.each do |op|
-            m = op.match /arvados#(.+)/
-            begin
-              cl = m[1].classify.andand.constantize if m
+              cl = ArvadosModel::kind_class op
               if cl
                 cond << "#{table_name}.#{attr} like ?"
-                param_out << "_____-#{cl.uuid_prefix}-_______________"
+                param_out << cl.uuid_like_pattern
+              else
+                cond << "1=0"
               end
-            rescue NameError
-              cond << "1=0"
-            end
           end
           cond_out << cond.join(' OR ')
         end
diff --git a/services/api/app/controllers/arvados/v1/collections_controller.rb b/services/api/app/controllers/arvados/v1/collections_controller.rb
index c0cd419..8db93c3 100644
--- a/services/api/app/controllers/arvados/v1/collections_controller.rb
+++ b/services/api/app/controllers/arvados/v1/collections_controller.rb
@@ -6,11 +6,6 @@ class Arvados::V1::CollectionsController < ApplicationController
     # exist) giving the current user (or specified owner_uuid)
     # permission to read it.
     owner_uuid = resource_attrs.delete(:owner_uuid) || current_user.uuid
-    owner_kind = if owner_uuid.match(/-(\w+)-/)[1] == User.uuid_prefix
-                   'arvados#user'
-                 else
-                   'arvados#group'
-                 end
     unless current_user.can? write: owner_uuid
       logger.warn "User #{current_user.andand.uuid} tried to set collection owner_uuid to #{owner_uuid}"
       raise ArvadosModel::PermissionDeniedError
@@ -36,9 +31,7 @@ class Arvados::V1::CollectionsController < ApplicationController
           owner_uuid: owner_uuid,
           link_class: 'permission',
           name: 'can_read',
-          head_kind: 'arvados#collection',
           head_uuid: @object.uuid,
-          tail_kind: owner_kind,
           tail_uuid: owner_uuid
         }
         ActiveRecord::Base.transaction do
diff --git a/services/api/app/controllers/arvados/v1/repositories_controller.rb b/services/api/app/controllers/arvados/v1/repositories_controller.rb
index 19504e1..390aa73 100644
--- a/services/api/app/controllers/arvados/v1/repositories_controller.rb
+++ b/services/api/app/controllers/arvados/v1/repositories_controller.rb
@@ -14,7 +14,7 @@ class Arvados::V1::RepositoriesController < ApplicationController
       gitolite_permissions = ''
       perms = []
       repo.permissions.each do |perm|
-        if perm.tail_kind == 'arvados#group'
+        if ArvadosModel::resource_class_for_uuid(perm.tail_uuid) == Group
           @users.each do |user_uuid, user|
             user.group_permissions.each do |group_uuid, perm_mask|
               if perm_mask[:write]
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 4ad959e..32adde9 100644
--- a/services/api/app/controllers/arvados/v1/user_agreements_controller.rb
+++ b/services/api/app/controllers/arvados/v1/user_agreements_controller.rb
@@ -19,12 +19,12 @@ class Arvados::V1::UserAgreementsController < ApplicationController
     else
       current_user_uuid = current_user.uuid
       act_as_system_user do
-        uuids = Link.where(owner_uuid: system_user_uuid,
-                           link_class: 'signature',
-                           name: 'require',
-                           tail_kind: 'arvados#user',
-                           tail_uuid: system_user_uuid,
-                           head_kind: 'arvados#collection').
+        uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+                           system_user_uuid,
+                           'signature',
+                           'require',
+                           system_user_uuid,
+                           Collection.uuid_like_pattern).
           collect &:head_uuid
         @objects = Collection.where('uuid in (?)', uuids)
       end
@@ -37,12 +37,12 @@ class Arvados::V1::UserAgreementsController < ApplicationController
     current_user_uuid = (current_user.andand.is_admin && params[:uuid]) ||
       current_user.uuid
     act_as_system_user do
-      @objects = Link.where(owner_uuid: system_user_uuid,
-                            link_class: 'signature',
-                            name: 'click',
-                            tail_kind: 'arvados#user',
-                            tail_uuid: current_user_uuid,
-                            head_kind: 'arvados#collection')
+      @objects = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+                            system_user_uuid,
+                            'signature',
+                            'click',
+                            current_user_uuid,
+                            Collection.uuid_like_pattern)
     end
     @response_resource_name = 'link'
     render_list
@@ -53,9 +53,7 @@ class Arvados::V1::UserAgreementsController < ApplicationController
     act_as_system_user do
       @object = Link.create(link_class: 'signature',
                             name: 'click',
-                            tail_kind: 'arvados#user',
                             tail_uuid: current_user_uuid,
-                            head_kind: 'arvados#collection',
                             head_uuid: params[:uuid])
     end
     show
diff --git a/services/api/app/controllers/arvados/v1/users_controller.rb b/services/api/app/controllers/arvados/v1/users_controller.rb
index 133df0f..6b35015 100644
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@ -58,19 +58,18 @@ class Arvados::V1::UsersController < ApplicationController
           "but is not invited"
         raise ArgumentError.new "Cannot activate without being invited."
       end
-      act_as_system_user do
-        required_uuids = Link.where(owner_uuid: system_user_uuid,
-                                    link_class: 'signature',
-                                    name: 'require',
-                                    tail_uuid: system_user_uuid,
-                                    head_kind: 'arvados#collection').
+      act_as_system_user do       
+        required_uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+                                    system_user_uuid,
+                                    'signature',
+                                    'require',
+                                    system_user_uuid,
+                                    Collection.uuid_like_pattern).
           collect(&:head_uuid)
         signed_uuids = Link.where(owner_uuid: system_user_uuid,
                                   link_class: 'signature',
                                   name: 'click',
-                                  tail_kind: 'arvados#user',
                                   tail_uuid: @object.uuid,
-                                  head_kind: 'arvados#collection',
                                   head_uuid: required_uuids).
           collect(&:head_uuid)
         todo_uuids = required_uuids - signed_uuids
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 3674c01..a7391bd 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -24,11 +24,11 @@ class UserSessionsController < ApplicationController
     if not user
       # Check for permission to log in to an existing User record with
       # a different identity_url
-      Link.where(link_class: 'permission',
-                 name: 'can_login',
-                 tail_kind: 'email',
-                 tail_uuid: omniauth['info']['email'],
-                 head_kind: 'arvados#user').each do |link|
+      Link.where("link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+                 'permission',
+                 'can_login',
+                 omniauth['info']['email'],
+                 User.uuid_like_pattern).each do |link|
         if prefix = link.properties['identity_url_prefix']
           if prefix == omniauth['info']['identity_url'][0..prefix.size-1]
             user = User.find_by_uuid(link.head_uuid)
diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 8ffd881..e2cc2f1 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -32,7 +32,7 @@ class ArvadosModel < ActiveRecord::Base
   end
 
   def self.kind_class(kind)
-    kind.match(/^arvados\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
+    kind.match(/^arvados\#(.+)$/)[1].classify.safe_constantize rescue nil
   end
 
   def href
@@ -51,18 +51,18 @@ class ArvadosModel < ActiveRecord::Base
     self.columns.select { |col| col.name == attr.to_s }.first
   end
 
-  def eager_load_associations
-    self.class.columns.each do |col|
-      re = col.name.match /^(.*)_kind$/
-      if (re and
-          self.respond_to? re[1].to_sym and
-          (auuid = self.send((re[1] + '_uuid').to_sym)) and
-          (aclass = self.class.kind_class(self.send(col.name.to_sym))) and
-          (aobject = aclass.where('uuid=?', auuid).first))
-        self.instance_variable_set('@'+re[1], aobject)
-      end
-    end
-  end
+  # def eager_load_associations
+  #   self.class.columns.each do |col|
+  #     re = col.name.match /^(.*)_kind$/
+  #     if (re and
+  #         self.respond_to? re[1].to_sym and
+  #         (auuid = self.send((re[1] + '_uuid').to_sym)) and
+  #         (aclass = self.class.kind_class(self.send(col.name.to_sym))) and
+  #         (aobject = aclass.where('uuid=?', auuid).first))
+  #       self.instance_variable_set('@'+re[1], aobject)
+  #     end
+  #   end
+  # end
 
   def self.readable_by user
     uuid_list = [user.uuid, *user.groups_i_can(:read)]
@@ -195,11 +195,15 @@ class ArvadosModel < ActiveRecord::Base
         if k.respond_to?(:uuid_prefix)
           @@prefixes_hash[k.uuid_prefix] = k
         end
-      end      
+      end
     end
     @@prefixes_hash
   end
 
+  def self.uuid_like_pattern
+    "_____-#{uuid_prefix}-_______________"
+  end
+
   def ensure_valid_uuids
     specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
 
diff --git a/services/api/app/models/collection.rb b/services/api/app/models/collection.rb
index 620b74a..600c075 100644
--- a/services/api/app/models/collection.rb
+++ b/services/api/app/models/collection.rb
@@ -128,6 +128,10 @@ class Collection < ArvadosModel
     end
   end
 
+  def self.uuid_like_pattern
+    "________________________________+%"
+  end
+
   def self.normalize_uuid uuid
     hash_part = nil
     size_part = nil
diff --git a/services/api/app/models/link.rb b/services/api/app/models/link.rb
index 1d4e13d..bb22156 100644
--- a/services/api/app/models/link.rb
+++ b/services/api/app/models/link.rb
@@ -43,7 +43,7 @@ class Link < ArvadosModel
 
     # All users can grant permissions on objects they own
     head_obj = self.class.
-      kind_class(self.head_kind).
+      kind_class(self.head_uuid).
       where('uuid=?',head_uuid).
       first
     if head_obj
diff --git a/services/api/app/models/user.rb b/services/api/app/models/user.rb
index 0896571..5c15fa2 100644
--- a/services/api/app/models/user.rb
+++ b/services/api/app/models/user.rb
@@ -79,10 +79,10 @@ class User < ArvadosModel
         Group.where('owner_uuid in (?)', lookup_uuids).each do |group|
           newgroups << [group.owner_uuid, group.uuid, 'can_manage']
         end
-        Link.where('tail_uuid in (?) and link_class = ? and head_kind = ?',
+        Link.where('tail_uuid in (?) and link_class = ? and head_uuid like ?',
                    lookup_uuids,
                    'permission',
-                   'arvados#group').each do |link|
+                   Group.uuid_like_pattern).each do |link|
           newgroups << [link.tail_uuid, link.head_uuid, link.name]
         end
         newgroups.each do |tail_uuid, head_uuid, perm_name|
diff --git a/services/api/test/fixtures/collections.yml b/services/api/test/fixtures/collections.yml
index 85b02ae..11cbc0e 100644
--- a/services/api/test/fixtures/collections.yml
+++ b/services/api/test/fixtures/collections.yml
@@ -1,5 +1,5 @@
 user_agreement:
-  uuid: b519d9cb706a29fc7ea24dbea2f05851
+  uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   owner_uuid: qr1hi-tpzed-tpj2ff66551eyym
   created_at: 2013-12-26T19:22:54Z
   modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
diff --git a/services/api/test/fixtures/links.yml b/services/api/test/fixtures/links.yml
index 6cb8c63..a0832d6 100644
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@ -11,7 +11,7 @@ user_agreement_required:
   link_class: signature
   name: require
   head_kind: arvados#collection
-  head_uuid: b519d9cb706a29fc7ea24dbea2f05851
+  head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
 user_agreement_readable:
@@ -27,7 +27,7 @@ user_agreement_readable:
   link_class: permission
   name: can_read
   head_kind: arvados#collection
-  head_uuid: b519d9cb706a29fc7ea24dbea2f05851
+  head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
 active_user_member_of_all_users_group:
@@ -75,7 +75,7 @@ user_agreement_signed_by_active:
   link_class: signature
   name: click
   head_kind: arvados#collection
-  head_uuid: b519d9cb706a29fc7ea24dbea2f05851
+  head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
 user_agreement_signed_by_inactive:
@@ -91,7 +91,7 @@ user_agreement_signed_by_inactive:
   link_class: signature
   name: click
   head_kind: arvados#collection
-  head_uuid: b519d9cb706a29fc7ea24dbea2f05851
+  head_uuid: b519d9cb706a29fc7ea24dbea2f05851+93
   properties: {}
 
 spectator_user_member_of_all_users_group:
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 32cf1e0..0f84075 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -90,5 +90,18 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
     assert_equal 0, found.count
   end
 
+  test "filter links with 'is_a' operator with collection" do
+    authorize_with :admin
+    get :index, {
+      filters: [ ['head_uuid', 'is_a', ['arvados#collection'] ] ],
+    }
+    assert_response :success
+    found = assigns(:objects)
+    assert_response :success
+    found = assigns(:objects)
+    assert_not_equal 0, found.count
+    assert_equal found.count, (found.select { |f| f.head_uuid.match /[a-f0-9]{32}\+\d+/}).count
+  end
+
 
 end

commit ff5f11f345307397d3d817f2bdef398d1660c22d
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 25 11:17:11 2014 -0400

    Added 'is_a' filter and tests, refs #2418 #2228

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index e1b85aa..979e2d1 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -160,6 +160,22 @@ class ApplicationController < ActionController::Base
             cond_out << "#{table_name}.#{attr} IN (?)"
             param_out << operand
           end
+        when 'is_a'
+          operand = [operand] unless operand.is_a? Array
+          cond = []
+          operand.each do |op|
+            m = op.match /arvados#(.+)/
+            begin
+              cl = m[1].classify.andand.constantize if m
+              if cl
+                cond << "#{table_name}.#{attr} like ?"
+                param_out << "_____-#{cl.uuid_prefix}-_______________"
+              end
+            rescue NameError
+              cond << "1=0"
+            end
+          end
+          cond_out << cond.join(' OR ')
         end
       end
       if cond_out.any?
diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index e6f5b36..8ffd881 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -187,6 +187,19 @@ class ArvadosModel < ActiveRecord::Base
 
   @@UUID_REGEX = /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/
 
+  @@prefixes_hash = nil
+  def self.uuid_prefixes
+    unless @@prefixes_hash
+      @@prefixes_hash = {}
+      ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
+        if k.respond_to?(:uuid_prefix)
+          @@prefixes_hash[k.uuid_prefix] = k
+        end
+      end      
+    end
+    @@prefixes_hash
+  end
+
   def ensure_valid_uuids
     specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
 
@@ -221,13 +234,7 @@ class ArvadosModel < ActiveRecord::Base
 
     Rails.application.eager_load!
     uuid.match @@UUID_REGEX do |re|
-      ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
-        if k.respond_to?(:uuid_prefix)
-          if k.uuid_prefix == re[1]
-            return k
-          end
-        end
-      end
+      return uuid_prefixes[re[1]] if uuid_prefixes[re[1]]
     end
     nil
   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 19e821e..32cf1e0 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -58,4 +58,37 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
     assert_response 422
   end
 
+  test "filter links with 'is_a' operator" do
+    authorize_with :admin
+    get :index, {
+      filters: [ ['tail_uuid', 'is_a', 'arvados#user'] ]
+    }
+    assert_response :success
+    found = assigns(:objects)
+    assert_not_equal 0, found.count
+    assert_equal found.count, (found.select { |f| f.tail_uuid.match /[a-z0-9]{5}-tpzed-[a-z0-9]{15}/}).count
+  end
+
+  test "filter links with 'is_a' operator with more than one" do
+    authorize_with :admin
+    get :index, {
+      filters: [ ['tail_uuid', 'is_a', ['arvados#user', 'arvados#group'] ] ],
+    }
+    assert_response :success
+    found = assigns(:objects)
+    assert_not_equal 0, found.count
+    assert_equal found.count, (found.select { |f| f.tail_uuid.match /[a-z0-9]{5}-(tpzed|j7d0g)-[a-z0-9]{15}/}).count
+  end
+
+  test "filter links with 'is_a' operator with bogus type" do
+    authorize_with :admin
+    get :index, {
+      filters: [ ['tail_uuid', 'is_a', ['arvados#bogus'] ] ],
+    }
+    assert_response :success
+    found = assigns(:objects)
+    assert_equal 0, found.count
+  end
+
+
 end

commit de298e4e20a7ed07e16ed3cac87a18a66c0ceb83
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 25 10:19:20 2014 -0400

    All tests pass!

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 6932dc7..e1b85aa 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -44,11 +44,8 @@ class ApplicationController < ActionController::Base
     attrs_to_update = resource_attrs.reject { |k,v|
       [:kind, :etag, :href].index k
     }
-    if @object.update_attributes attrs_to_update
-      show
-    else
-      raise "Update failed"
-    end
+    @object.update_attributes! attrs_to_update
+    show
   end
 
   def destroy
diff --git a/services/api/app/controllers/arvados/v1/jobs_controller.rb b/services/api/app/controllers/arvados/v1/jobs_controller.rb
index b7b0e67..46dd0ec 100644
--- a/services/api/app/controllers/arvados/v1/jobs_controller.rb
+++ b/services/api/app/controllers/arvados/v1/jobs_controller.rb
@@ -44,7 +44,7 @@ class Arvados::V1::JobsController < ApplicationController
 
   def cancel
     reload_object_before_update
-    @object.update_attributes cancelled_at: Time.now
+    @object.update_attributes! cancelled_at: Time.now
     show
   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
index 7db295d..3d91916 100644
--- a/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
+++ b/services/api/app/controllers/arvados/v1/keep_disks_controller.rb
@@ -12,15 +12,18 @@ class Arvados::V1::KeepDisksController < ApplicationController
       service_ssl_flag: true
     }
   end
+
   def ping
     params[:service_host] ||= request.env['REMOTE_ADDR']
-    if not @object.ping params
-      return render_not_found "object not found"
+    act_as_system_user do
+      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
-    # 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
 
   def find_objects_for_index
diff --git a/services/api/app/controllers/arvados/v1/nodes_controller.rb b/services/api/app/controllers/arvados/v1/nodes_controller.rb
index 1461eec..4415a51 100644
--- a/services/api/app/controllers/arvados/v1/nodes_controller.rb
+++ b/services/api/app/controllers/arvados/v1/nodes_controller.rb
@@ -13,18 +13,21 @@ class Arvados::V1::NodesController < ApplicationController
   def self._ping_requires_parameters
     { ping_secret: true }
   end
+
   def ping
-    @object = Node.where(uuid: (params[:id] || params[:uuid])).first
-    if !@object
-      return render_not_found
-    end
-    @object.ping({ ip: params[:local_ipv4] || request.env['REMOTE_ADDR'],
-                   ping_secret: params[:ping_secret],
-                   ec2_instance_id: params[:instance_id] })
-    if @object.info[:ping_secret] == params[:ping_secret]
-      render json: @object.as_api_response(:superuser)
-    else
-      raise "Invalid ping_secret after ping"
+    act_as_system_user do 
+      @object = Node.where(uuid: (params[:id] || params[:uuid])).first
+      if !@object
+        return render_not_found
+      end
+      @object.ping({ ip: params[:local_ipv4] || request.env['REMOTE_ADDR'],
+                     ping_secret: params[:ping_secret],
+                     ec2_instance_id: params[:instance_id] })
+      if @object.info[:ping_secret] == params[:ping_secret]
+        render json: @object.as_api_response(:superuser)
+      else
+        raise "Invalid ping_secret after ping"
+      end
     end
   end
 
diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index ed19636..e6f5b36 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -167,6 +167,10 @@ class ArvadosModel < ActiveRecord::Base
     attributes.keys.select { |a| a.match /_uuid$/ }
   end
 
+  def skip_uuid_read_permission_check
+    %w(modified_by_client_uuid)
+  end
+
   def normalize_collection_uuids
     foreign_key_attributes.each do |attr|
       attr_value = send attr
@@ -187,15 +191,18 @@ class ArvadosModel < ActiveRecord::Base
     specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
 
     foreign_key_attributes.each do |attr|
-      next if attr == "modified_by_client_uuid"
       begin
-        attr_value = send attr
-        r = ArvadosModel::resource_class_for_uuid attr_value if attr_value
-        if r and r.readable_by(current_user).where(uuid: attr_value).count == 0 and not specials.include? attr_value
-          errors.add(attr, "'#{attr_value}' not found")
+        if new_record? or send (attr + "_changed?")
+          attr_value = send attr
+          r = ArvadosModel::resource_class_for_uuid attr_value if attr_value
+          r = r.readable_by(current_user) if r and not skip_uuid_read_permission_check.include? attr
+          if r and r.where(uuid: attr_value).count == 0 and not specials.include? attr_value
+            errors.add(attr, "'#{attr_value}' not found")
+          end
         end
       rescue Exception => e
-          errors.add(attr, "'#{attr_value}' error #{e}")
+        bt = e.backtrace.join("\n")
+        errors.add(attr, "'#{attr_value}' error '#{e}'\n#{bt}\n")
       end
     end
   end
diff --git a/services/api/app/models/job.rb b/services/api/app/models/job.rb
index 1f0ef75..e9ec10d 100644
--- a/services/api/app/models/job.rb
+++ b/services/api/app/models/job.rb
@@ -62,6 +62,10 @@ class Job < ArvadosModel
     super + %w(output log)
   end
 
+  def skip_uuid_read_permission_check
+    super + %w(cancelled_by_client_uuid)
+  end
+
   def ensure_script_version_is_commit
     if self.is_locked_by_uuid and self.started_at
       # Apparently client has already decided to go for it. This is
diff --git a/services/api/app/models/keep_disk.rb b/services/api/app/models/keep_disk.rb
index 0998fcd..77fc627 100644
--- a/services/api/app/models/keep_disk.rb
+++ b/services/api/app/models/keep_disk.rb
@@ -22,6 +22,10 @@ class KeepDisk < ArvadosModel
     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]
 
@@ -31,7 +35,7 @@ class KeepDisk < ArvadosModel
     end
 
     @bypass_arvados_authorization = true
-    self.update_attributes(o.select { |k,v|
+    self.update_attributes!(o.select { |k,v|
                              [:service_host,
                               :service_port,
                               :service_ssl_flag,

commit 417ff385d9e6bf111ebb1d5889c2081977dfe955
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Mar 24 17:10:09 2014 -0400

    Fighting with tests

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 30e907c..ed19636 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -187,10 +187,11 @@ class ArvadosModel < ActiveRecord::Base
     specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
 
     foreign_key_attributes.each do |attr|
+      next if attr == "modified_by_client_uuid"
       begin
         attr_value = send attr
         r = ArvadosModel::resource_class_for_uuid attr_value if attr_value
-        if r and r.where(uuid: attr_value).count == 0 and not specials.include? attr_value
+        if r and r.readable_by(current_user).where(uuid: attr_value).count == 0 and not specials.include? attr_value
           errors.add(attr, "'#{attr_value}' not found")
         end
       rescue Exception => e
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 352ce55..19e821e 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -29,7 +29,7 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
       tail_uuid: users(:active).uuid,
       head_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
     }
-    authorize_with :active
+    authorize_with :admin
     post :create, link: link
     assert_response 422
   end
@@ -41,12 +41,12 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
       head_uuid: users(:active).uuid,
       tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
     }
-    authorize_with :active
+    authorize_with :admin
     post :create, link: link
     assert_response 422
   end
 
-  test "tail must exist on update" do
+  test "tail must be visible by user" do
     link = {
       link_class: 'test',
       name: 'stuff',
@@ -55,20 +55,6 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
     }
     authorize_with :active
     post :create, link: link
-    u = (ActiveSupport::JSON.decode @response.body)['uuid']
-    assert_response :success
-
-    link = {
-      tail_uuid: virtual_machines(:testvm2).uuid
-    }
-    put :update, {id: u, link: link}
-    assert_equal virtual_machines(:testvm2).uuid, (ActiveSupport::JSON.decode @response.body)['tail_uuid']
-    assert_response :success
-
-    link = {
-      tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
-    }
-    put :update, {id: u, link: link}
     assert_response 422
   end
 
diff --git a/services/api/test/integration/valid_links_test.rb b/services/api/test/integration/valid_links_test.rb
new file mode 100644
index 0000000..65431f3
--- /dev/null
+++ b/services/api/test/integration/valid_links_test.rb
@@ -0,0 +1,42 @@
+require 'test_helper'
+
+class ValidLinksTest < ActionDispatch::IntegrationTest
+  fixtures :all
+
+  test "tail must exist on update" do
+    admin_auth = {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:admin).api_token}"}
+
+    post "/arvados/v1/links", {
+      :format => :json,
+      :link => {
+        link_class: 'test',
+        name: 'stuff',
+        head_uuid: users(:active).uuid,
+        tail_uuid: virtual_machines(:testvm).uuid
+      }
+    }, admin_auth
+    assert_response :success
+    u = jresponse['uuid']
+
+    put "/arvados/v1/links/#{u}", {
+      :format => :json,
+      :link => {
+        tail_uuid: virtual_machines(:testvm2).uuid
+      }
+    }, admin_auth
+    assert_response :success
+    #puts @response.body
+    #puts jresponse['tail_uuid']
+    #puts virtual_machines(:testvm2)
+    assert_equal virtual_machines(:testvm2).uuid, (ActiveSupport::JSON.decode @response.body)['tail_uuid']
+
+    put "/arvados/v1/links/#{u}", {
+      :format => :json,
+      :link => {
+        tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+      }
+    }, admin_auth
+    assert_response 422
+  end
+
+end

commit d1396b9eee6a939f5c675d5922d3708392d04936
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Mar 24 15:55:34 2014 -0400

    Arvados model now validates that all "foreign_key_attributes" exist before create/update.

diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 3101781..6932dc7 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -36,11 +36,8 @@ class ApplicationController < ActionController::Base
 
   def create
     @object = model_class.new resource_attrs
-    if @object.save
-      show
-    else
-      raise "Save failed"
-    end
+    @object.save!
+    show
   end
 
   def update
diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 8e37898..30e907c 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -11,10 +11,11 @@ class ArvadosModel < ActiveRecord::Base
   before_create :ensure_permission_to_create
   before_update :ensure_permission_to_update
   before_destroy :ensure_permission_to_destroy
-  before_create :update_modified_by_fields
-  before_update :maybe_update_modified_by_fields
+
+  before_validation :maybe_update_modified_by_fields
   validate :ensure_serialized_attribute_type
   validate :normalize_collection_uuids
+  validate :ensure_valid_uuids
 
   has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'"
 
@@ -135,7 +136,7 @@ class ArvadosModel < ActiveRecord::Base
   end
 
   def maybe_update_modified_by_fields
-    update_modified_by_fields if self.changed?
+    update_modified_by_fields if self.changed? or self.new_record?
   end
 
   def update_modified_by_fields
@@ -180,6 +181,24 @@ class ArvadosModel < ActiveRecord::Base
     end
   end
 
+  @@UUID_REGEX = /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/
+
+  def ensure_valid_uuids
+    specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
+
+    foreign_key_attributes.each do |attr|
+      begin
+        attr_value = send attr
+        r = ArvadosModel::resource_class_for_uuid attr_value if attr_value
+        if r and r.where(uuid: attr_value).count == 0 and not specials.include? attr_value
+          errors.add(attr, "'#{attr_value}' not found")
+        end
+      rescue Exception => e
+          errors.add(attr, "'#{attr_value}' error #{e}")
+      end
+    end
+  end
+
   def self.resource_class_for_uuid(uuid)
     if uuid.is_a? ArvadosModel
       return uuid.class
@@ -193,7 +212,7 @@ class ArvadosModel < ActiveRecord::Base
     resource_class = nil
 
     Rails.application.eager_load!
-    uuid.match /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/ do |re|
+    uuid.match @@UUID_REGEX do |re|
       ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
         if k.respond_to?(:uuid_prefix)
           if k.uuid_prefix == re[1]
diff --git a/services/api/test/fixtures/virtual_machines.yml b/services/api/test/fixtures/virtual_machines.yml
index 72e2130..f5e0163 100644
--- a/services/api/test/fixtures/virtual_machines.yml
+++ b/services/api/test/fixtures/virtual_machines.yml
@@ -2,3 +2,8 @@ testvm:
   uuid: zzzzz-2x53u-382brsig8rp3064
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
   hostname: testvm.shell
+
+testvm2:
+  uuid: zzzzz-2x53u-382brsig8rp3065
+  owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
+  hostname: testvm2.shell
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 afecc18..352ce55 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -22,4 +22,54 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
     end
   end
   
+  test "head must exist" do
+    link = {
+      link_class: 'test',
+      name: 'stuff',
+      tail_uuid: users(:active).uuid,
+      head_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+    }
+    authorize_with :active
+    post :create, link: link
+    assert_response 422
+  end
+
+  test "tail must exist" do
+    link = {
+      link_class: 'test',
+      name: 'stuff',
+      head_uuid: users(:active).uuid,
+      tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+    }
+    authorize_with :active
+    post :create, link: link
+    assert_response 422
+  end
+
+  test "tail must exist on update" do
+    link = {
+      link_class: 'test',
+      name: 'stuff',
+      head_uuid: users(:active).uuid,
+      tail_uuid: virtual_machines(:testvm).uuid
+    }
+    authorize_with :active
+    post :create, link: link
+    u = (ActiveSupport::JSON.decode @response.body)['uuid']
+    assert_response :success
+
+    link = {
+      tail_uuid: virtual_machines(:testvm2).uuid
+    }
+    put :update, {id: u, link: link}
+    assert_equal virtual_machines(:testvm2).uuid, (ActiveSupport::JSON.decode @response.body)['tail_uuid']
+    assert_response :success
+
+    link = {
+      tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+    }
+    put :update, {id: u, link: link}
+    assert_response 422
+  end
+
 end

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list