[ARVADOS] updated: eb7227693e8847a65798afa7f7e8a4ffe8a199a4

git at public.curoverse.com git at public.curoverse.com
Tue Apr 15 13:49:36 EDT 2014


Summary of changes:
 apps/workbench/.gitignore                          |    1 -
 .../app/assets/javascripts/application.js          |    3 +-
 .../app/controllers/actions_controller.rb          |    2 -
 .../app/controllers/application_controller.rb      |    1 +
 .../app/controllers/collections_controller.rb      |   14 +-
 apps/workbench/app/controllers/users_controller.rb |    4 +-
 apps/workbench/app/models/arvados_base.rb          |    8 +-
 apps/workbench/app/models/link.rb                  |    2 +-
 apps/workbench/config/application.default.yml      |    1 +
 apps/workbench/config/environments/test.rb         |    1 +
 .../pipeline_instances_controller_test.rb          |   58 +++++
 .../test/functional/users_controller_test.rb       |   21 ++
 apps/workbench/test/integration/logins_test.rb     |    8 +
 apps/workbench/test/integration_helper.rb          |   57 +-----
 apps/workbench/test/test_helper.rb                 |   78 +++++++
 doc/admin/cheat_sheet.html.textile.liquid          |    4 -
 doc/api/schema/Link.html.textile.liquid            |    2 -
 doc/api/schema/Log.html.textile.liquid             |    1 -
 .../create-standard-objects.html.textile.liquid    |    2 -
 .../tutorial-trait-search.html.textile.liquid      |   18 +-
 sdk/ruby/lib/arvados.rb                            |   32 ++--
 services/api/Gemfile                               |    4 +-
 services/api/Gemfile.lock                          |  115 +++++-----
 .../api/app/controllers/application_controller.rb  |   49 +++--
 .../arvados/v1/collections_controller.rb           |    7 -
 .../app/controllers/arvados/v1/jobs_controller.rb  |    7 +-
 .../arvados/v1/keep_disks_controller.rb            |   15 +-
 .../app/controllers/arvados/v1/links_controller.rb |   57 +++++-
 .../app/controllers/arvados/v1/logs_controller.rb  |   32 +++
 .../app/controllers/arvados/v1/nodes_controller.rb |   25 ++-
 .../arvados/v1/repositories_controller.rb          |    2 +-
 .../arvados/v1/user_agreements_controller.rb       |   26 +--
 .../app/controllers/arvados/v1/users_controller.rb |   28 ++-
 .../app/controllers/user_sessions_controller.rb    |   10 +-
 services/api/app/mailers/user_notifier.rb          |    8 +
 services/api/app/models/arvados_model.rb           |  103 +++++++--
 services/api/app/models/collection.rb              |    4 +
 services/api/app/models/job.rb                     |    4 +
 services/api/app/models/keep_disk.rb               |    6 +-
 services/api/app/models/link.rb                    |   24 ++-
 services/api/app/models/log.rb                     |   15 +-
 services/api/app/models/user.rb                    |   32 +---
 .../views/user_notifier/account_is_setup.text.erb  |    6 +
 services/api/config/application.default.yml        |    3 +
 services/api/config/routes.rb                      |    2 +
 .../migrate/20140325175653_remove_kind_columns.rb  |   27 +++
 services/api/db/schema.rb                          |   40 ++--
 services/api/lib/kind_and_etag.rb                  |    5 +-
 services/api/script/setup-new-user.rb              |    9 +-
 .../test/fixtures/api_client_authorizations.yml    |    6 +
 services/api/test/fixtures/groups.yml              |    6 +
 services/api/test/fixtures/jobs.yml                |   13 ++
 services/api/test/fixtures/links.yml               |   52 +----
 services/api/test/fixtures/logs.yml                |    3 +
 services/api/test/fixtures/pipeline_templates.yml  |   36 +++
 services/api/test/fixtures/virtual_machines.yml    |    5 +
 .../arvados/v1/job_reuse_controller_test.rb        |   20 ++-
 .../functional/arvados/v1/links_controller_test.rb |  224 +++++++++++++++++++-
 .../functional/arvados/v1/logs_controller_test.rb  |   27 +++
 .../functional/arvados/v1/users_controller_test.rb |   92 +++++++--
 .../api/test/functional/user_notifier_test.rb      |    2 +-
 services/api/test/integration/permissions_test.rb  |   18 --
 services/api/test/integration/valid_links_test.rb  |   39 ++++
 services/api/test/unit/log_test.rb                 |    1 -
 services/api/test/unit/user_notifier_test.rb       |   24 ++
 services/api/test/unit/user_test.rb                |   44 ++--
 services/keep/keep.go                              |   86 ++++++--
 services/keep/keep_test.go                         |   34 +--
 68 files changed, 1241 insertions(+), 474 deletions(-)
 create mode 120000 apps/workbench/config/environments/test.rb
 create mode 100644 services/api/app/mailers/user_notifier.rb
 create mode 100644 services/api/app/views/user_notifier/account_is_setup.text.erb
 create mode 100644 services/api/db/migrate/20140325175653_remove_kind_columns.rb
 create mode 100644 services/api/test/fixtures/logs.yml
 create mode 100644 services/api/test/fixtures/pipeline_templates.yml
 copy apps/workbench/test/unit/job_task_test.rb => services/api/test/functional/user_notifier_test.rb (61%)
 create mode 100644 services/api/test/integration/valid_links_test.rb
 create mode 100644 services/api/test/unit/user_notifier_test.rb

       via  eb7227693e8847a65798afa7f7e8a4ffe8a199a4 (commit)
       via  7c5ae57edcd37b5be47e0578b709f41cb97f0748 (commit)
       via  1452044e468074674b5a16c1990ada4f2c1485ec (commit)
       via  05d6da1868a2ecef39bcf17bbc336e1c58eba7ea (commit)
       via  481e341b75f1c6c0015171539c008e540dea2c2d (commit)
       via  0589ee6c2384e9a38720d67c8b86f5adf1d27902 (commit)
       via  f64a44536ad550ba4424a7f34f7358938b0e4dcc (commit)
       via  60a660385c1643efbdf11a8e5fa1deae1f008d2b (commit)
       via  4729ceb08aa3846326d1729f766f8f10179a2a78 (commit)
       via  c2aeaa729c350a33ec47ae1b012e50a6685ac2d2 (commit)
       via  bb45025e80abc00f8da524d9a78c0bab976d4f3a (commit)
       via  3a76b55556740564b8cfb44c7e430975cca6bf96 (commit)
       via  5df09e707c313fd88c32ad40f2d99030ecc2e639 (commit)
       via  28c07cc661b01747d4a3b090d0cac2e68067ad80 (commit)
       via  eeeceb21a479780dfa7d550523ab961f477e39ad (commit)
       via  0510460e9c5ad8f3d8cf20aa9428115e43284659 (commit)
       via  97279656db75b9b7f8282e3b98774a60935d39f3 (commit)
       via  065620721d198894d80f5d3ed409a1d158f0f41b (commit)
       via  6a210c4771acb18751e48f7e7c0841eb68469d90 (commit)
       via  f580cf6d3d86f6591e68b4501279fc45cbf847e0 (commit)
       via  bd11c0a9ff6ce23f0992af11d7dc7aef32860e22 (commit)
       via  f9578ab5cacc544dc1a5c3fa0fbea5fd627efdf9 (commit)
       via  9f3211fd8de463cb68febb4e3333721e026605b8 (commit)
       via  c2ccba382871ecad4f9336f250a90a95d8f5b987 (commit)
       via  658465e22d198a453646f0d845a9ccd50fb0a689 (commit)
       via  ee7753f7095f175c095f94794dd3e33f68d3fcc6 (commit)
       via  bdb591e730fffb6aba7c01d93528c59da91b05b0 (commit)
       via  239093640609a2267eb49a90d2f96ffcb2a462fe (commit)
       via  0f5d86d25f1e66723bbfe1f912d892f8a66321b8 (commit)
       via  2b571044517c19a2d3d20e5d4a3197a653667425 (commit)
       via  4c7323ea090e7570f962d821fa24c3ab20308e1e (commit)
       via  cc5023d40182e503e8ba109fc86e09efd6337836 (commit)
       via  db59e780872b7e7e5c9b1ee94f8e0ae136043d74 (commit)
       via  4f552c0187f8c31d94ff74485c57ef7f9888597e (commit)
       via  283dbf37a1b7d32332e295070de48b5e6e459248 (commit)
       via  9c40a72521dbfb4244d48069e4754a342f800492 (commit)
       via  04581ab4e5cea0389be8e641a1123381f0f7217c (commit)
       via  b288ebe08b16204d97c4911106bd5ca57fb2b36b (commit)
       via  4177bcc9b935391630c874a2abcedb81efa350f0 (commit)
       via  d334bf63821506a63afddb24c28ba86896958b03 (commit)
       via  3da41130c997f36f462feb1b34efbec53697d91e (commit)
       via  f60df78aec5cdc02ad50661f41a7d422e63742fc (commit)
       via  ff5f11f345307397d3d817f2bdef398d1660c22d (commit)
       via  de298e4e20a7ed07e16ed3cac87a18a66c0ceb83 (commit)
       via  417ff385d9e6bf111ebb1d5889c2081977dfe955 (commit)
       via  d1396b9eee6a939f5c675d5922d3708392d04936 (commit)
      from  2e86954da9d4561cc42d52e8505eb12aa95f6470 (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 eb7227693e8847a65798afa7f7e8a4ffe8a199a4
Merge: 7c5ae57 c2aeaa7
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Apr 15 13:47:52 2014 -0400

    Merge branch 'master' into 2596-refactor-pipeline-create
    
    Conflicts:
    	apps/workbench/test/functional/users_controller_test.rb
    	services/api/app/controllers/arvados/v1/jobs_controller.rb
    	services/api/test/functional/arvados/v1/links_controller_test.rb

diff --cc services/api/app/controllers/arvados/v1/jobs_controller.rb
index 0a4e308,3a9f624..336877b
--- a/services/api/app/controllers/arvados/v1/jobs_controller.rb
+++ b/services/api/app/controllers/arvados/v1/jobs_controller.rb
@@@ -28,25 -27,18 +28,24 @@@ class Arvados::V1::JobsController < App
                                            script_version: r).
          each do |j|
          if j.nondeterministic != true and
-             j.success != false and
-             !j.cancelled_at and
+             ((j.success == true and j.output != nil) or j.running == true) and
              j.script_parameters == resource_attrs[:script_parameters]
-           if j.success.nil?
 -          # Record the first job in the list
 -          if !@object
 -            @object = j
 -          end
 -          # Ensure that all candidate jobs actually did produce the same output
 -          if @object.output != j.output
 -            @object = nil
 -            break
++          if j.running
 +            # We'll use this if we don't find a job that has completed
 +            @incomplete_job ||= j
 +          else
 +            # Record the first job in the list
 +            if !@object
 +              @object = j
 +            end
 +            # Ensure that all candidate jobs actually did produce the same output
 +            if @object.output != j.output
 +              @object = nil
 +              break
 +            end
            end
          end
 +        @object ||= @incomplete_job
          if @object
            return show
          end
diff --cc services/api/app/controllers/arvados/v1/nodes_controller.rb
index 1461eec,4415a51..eda8b07
--- a/services/api/app/controllers/arvados/v1/nodes_controller.rb
+++ b/services/api/app/controllers/arvados/v1/nodes_controller.rb
@@@ -13,18 -13,21 +13,21 @@@ class Arvados::V1::NodesController < Ap
    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 
++    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 --cc services/api/app/controllers/arvados/v1/users_controller.rb
index 58661a0,08368cb..f5255bc
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@@ -141,4 -145,12 +145,12 @@@ class Arvados::V1::UsersController < Ap
      show
    end
  
+   protected
+ 
 -  def self._setup_requires_parameters 
++  def self._setup_requires_parameters
+     {
+       send_notification_email: { type: 'boolean', required: true },
 -    }  
++    }
+   end
+ 
  end
diff --cc services/api/test/fixtures/links.yml
index a04f74e,e3f6e2b..fc3f23d
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@@ -313,19 -275,5 +275,17 @@@ testusergroup_can_manage_active_user
    tail_uuid: zzzzz-j7d0g-48foin4vonvc2at
    link_class: permission
    name: can_manage
-   head_kind: arvados#user
    head_uuid: zzzzz-tpzed-xurymjxw79nv3jz
    properties: {}
 +
 +test_timestamps:
 +  uuid: zzzzz-o0j2j-4abnk2w5t86x4uc
 +  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
 +  created_at: 2014-04-15 13:17:14 -0400
 +  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
 +  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
 +  modified_at: 2014-04-15 13:17:14 -0400
 +  updated_at: 2014-04-15 13:17:14 -0400
 +  link_class: test
 +  name: test
 +  properties: {}
diff --cc services/api/test/functional/arvados/v1/links_controller_test.rb
index 13877fc,f4d65c1..4726e01
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@@ -22,40 -20,187 +20,224 @@@ class Arvados::V1::LinksControllerTest 
      end
    end
  
 +  %w(created_at updated_at modified_at).each do |attr|
 +    {nil: nil, bogus: 2.days.ago}.each do |bogustype, bogusvalue|
 +      test "cannot set #{bogustype} #{attr} in create" do
 +        authorize_with :active
 +        post :create, {
 +          link: {
 +            properties: {},
 +            link_class: 'test',
 +            name: 'test',
 +          }.merge(attr => bogusvalue)
 +        }
 +        assert_response :success
 +        resp = JSON.parse @response.body
 +        assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
 +      end
 +      test "cannot set #{bogustype} #{attr} in update" do
 +        really_created_at = links(:test_timestamps).created_at
 +        authorize_with :active
 +        put :update, {
 +          id: links(:test_timestamps).uuid,
 +          link: {
 +            :properties => {test: 'test'},
 +            attr => bogusvalue
 +          }
 +        }
 +        assert_response :success
 +        resp = JSON.parse @response.body
 +        case attr
 +        when 'created_at'
 +          assert_in_delta really_created_at, Time.parse(resp[attr]), 0.001
 +        else
 +          assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
 +        end
 +      end
 +    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 :admin
+     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 :admin
+     post :create, link: link
+     assert_response 422
+   end
+ 
+   test "head and tail exist, head_kind and tail_kind are returned" do
+     link = {
+       link_class: 'test',
+       name: 'stuff',
+       head_uuid: users(:active).uuid,
+       tail_uuid: users(:spectator).uuid,
+     }
+     authorize_with :admin
+     post :create, link: link
+     assert_response :success
+     l = JSON.parse(@response.body)
+     assert 'arvados#user', l['head_kind']
+     assert 'arvados#user', l['tail_kind']
+   end
+ 
+   test "can supply head_kind and tail_kind without error" do
+     link = {
+       link_class: 'test',
+       name: 'stuff',
+       head_uuid: users(:active).uuid,
+       tail_uuid: users(:spectator).uuid,
+       head_kind: "arvados#user",
+       tail_kind: "arvados#user",
+     }
+     authorize_with :admin
+     post :create, link: link
+     assert_response :success
+     l = JSON.parse(@response.body)
+     assert 'arvados#user', l['head_kind']
+     assert 'arvados#user', l['tail_kind']
+   end
+ 
+   test "tail must be visible by user" 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
+     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
+ 
+   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_not_equal 0, found.count
+     assert_equal found.count, (found.select { |f| f.head_uuid.match /[a-f0-9]{32}\+\d+/}).count
+   end
+ 
+   test "test can still use where tail_kind" do
+     authorize_with :admin
+     get :index, {
+       where: { tail_kind: '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 "test can still use where head_kind" do
+     authorize_with :admin
+     get :index, {
+       where: { head_kind: 'arvados#user' }
+     }
+     assert_response :success
+     found = assigns(:objects)
+     assert_not_equal 0, found.count
+     assert_equal found.count, (found.select { |f| f.head_uuid.match /[a-z0-9]{5}-tpzed-[a-z0-9]{15}/}).count
+   end
+ 
+   test "test can still use filter tail_kind" do
+     authorize_with :admin
+     get :index, {
+       filters: [ ['tail_kind', '=', '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 "test can still use filter head_kind" do
+     authorize_with :admin
+     get :index, {
+       filters: [ ['head_kind', '=', 'arvados#user'] ]
+     }
+     assert_response :success
+     found = assigns(:objects)
+     assert_not_equal 0, found.count
+     assert_equal found.count, (found.select { |f| f.head_uuid.match /[a-z0-9]{5}-tpzed-[a-z0-9]{15}/}).count
+   end
+ 
+   test "head_kind matches head_uuid" do
+     link = {
+       link_class: 'test',
+       name: 'stuff',
+       head_uuid: groups(:public).uuid,
+       head_kind: "arvados#user",
+       tail_uuid: users(:spectator).uuid,
+       tail_kind: "arvados#user",
+     }
+     authorize_with :admin
+     post :create, link: link
+     assert_response 422
+   end
+ 
+   test "tail_kind matches tail_uuid" do
+     link = {
+       link_class: 'test',
+       name: 'stuff',
+       head_uuid: users(:active).uuid,
+       head_kind: "arvados#user",
+       tail_uuid: groups(:public).uuid,
+       tail_kind: "arvados#user",
+     }
+     authorize_with :admin
+     post :create, link: link
+     assert_response 422
+   end
+ 
  end
diff --cc services/api/test/unit/user_notifier_test.rb
index 0000000,89d10c5..b280ae7
mode 000000,100644..100644
--- a/services/api/test/unit/user_notifier_test.rb
+++ b/services/api/test/unit/user_notifier_test.rb
@@@ -1,0 -1,24 +1,24 @@@
+ require 'test_helper'
 - 
++
+ class UserNotifierTest < ActionMailer::TestCase
+ 
+   # Send the email, then test that it got queued
+   test "account is setup" do
+     user = users :active
+     email = UserNotifier.account_is_setup user
+ 
+     assert_not_nil email
 - 
++
+     # Test the body of the sent email contains what we expect it to
+     assert_equal Rails.configuration.user_notifier_email_from, email.from.first
+     assert_equal user.email, email.to.first
+     assert_equal 'Welcome to Curoverse', email.subject
+     assert (email.body.to_s.include? 'Your Arvados account has been set up'),
+         'Expected Your Arvados account has been set up in email body'
+     assert (email.body.to_s.include? user.email),
+         'Expected user email in email body'
+     assert (email.body.to_s.include? Rails.configuration.workbench_address),
+         'Expected workbench url in email body'
+   end
+ 
+ end

commit 7c5ae57edcd37b5be47e0578b709f41cb97f0748
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Apr 15 13:36:12 2014 -0400

    Ensure created/modified/updated_at are correct, add tests.

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 921d2b1..845ef06 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -152,7 +152,7 @@ class ArvadosModel < ActiveRecord::Base
   end
 
   def update_modified_by_fields
-    self.created_at ||= Time.now
+    self.updated_at = Time.now
     self.owner_uuid ||= current_default_owner if self.respond_to? :owner_uuid=
     self.modified_at = Time.now
     self.modified_by_user_uuid = current_user ? current_user.uuid : nil
diff --git a/services/api/test/fixtures/links.yml b/services/api/test/fixtures/links.yml
index 0342d3d..a04f74e 100644
--- a/services/api/test/fixtures/links.yml
+++ b/services/api/test/fixtures/links.yml
@@ -317,3 +317,15 @@ testusergroup_can_manage_active_user:
   head_kind: arvados#user
   head_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   properties: {}
+
+test_timestamps:
+  uuid: zzzzz-o0j2j-4abnk2w5t86x4uc
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  created_at: 2014-04-15 13:17:14 -0400
+  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  modified_at: 2014-04-15 13:17:14 -0400
+  updated_at: 2014-04-15 13:17:14 -0400
+  link_class: test
+  name: test
+  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 afecc18..13877fc 100644
--- a/services/api/test/functional/arvados/v1/links_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/links_controller_test.rb
@@ -21,5 +21,41 @@ class Arvados::V1::LinksControllerTest < ActionController::TestCase
       assert_equal false, assigns(:object).properties.has_key?(:username)
     end
   end
-  
+
+  %w(created_at updated_at modified_at).each do |attr|
+    {nil: nil, bogus: 2.days.ago}.each do |bogustype, bogusvalue|
+      test "cannot set #{bogustype} #{attr} in create" do
+        authorize_with :active
+        post :create, {
+          link: {
+            properties: {},
+            link_class: 'test',
+            name: 'test',
+          }.merge(attr => bogusvalue)
+        }
+        assert_response :success
+        resp = JSON.parse @response.body
+        assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
+      end
+      test "cannot set #{bogustype} #{attr} in update" do
+        really_created_at = links(:test_timestamps).created_at
+        authorize_with :active
+        put :update, {
+          id: links(:test_timestamps).uuid,
+          link: {
+            :properties => {test: 'test'},
+            attr => bogusvalue
+          }
+        }
+        assert_response :success
+        resp = JSON.parse @response.body
+        case attr
+        when 'created_at'
+          assert_in_delta really_created_at, Time.parse(resp[attr]), 0.001
+        else
+          assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
+        end
+      end
+    end
+  end
 end

commit 1452044e468074674b5a16c1990ada4f2c1485ec
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Apr 15 13:03:44 2014 -0400

    Update local copy of updated_at if the server provides it.

diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index 3c224aa..5e32ead 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -138,7 +138,7 @@ class ArvadosBase < ActiveRecord::Base
     @kind = resp[:kind]
 
     # these attrs can be modified by "save" -- we should update our copies
-    %w(uuid owner_uuid created_at
+    %w(uuid owner_uuid created_at updated_at
        modified_at modified_by_user_uuid modified_by_client_uuid
       ).each do |attr|
       if self.respond_to? "#{attr}=".to_sym

commit 05d6da1868a2ecef39bcf17bbc336e1c58eba7ea
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Apr 15 12:22:57 2014 -0400

    Add tests, enable environments/test.rb to prevent CSRF checks in tests

diff --git a/apps/workbench/.gitignore b/apps/workbench/.gitignore
index a656a5b..fcfa458 100644
--- a/apps/workbench/.gitignore
+++ b/apps/workbench/.gitignore
@@ -20,7 +20,6 @@
 /public/assets
 
 /config/environments/development.rb
-/config/environments/test.rb
 /config/environments/production.rb
 /config/application.yml
 
diff --git a/apps/workbench/config/environments/test.rb b/apps/workbench/config/environments/test.rb
new file mode 120000
index 0000000..f1e9dbf
--- /dev/null
+++ b/apps/workbench/config/environments/test.rb
@@ -0,0 +1 @@
+test.rb.example
\ No newline at end of file
diff --git a/apps/workbench/test/functional/pipeline_instances_controller_test.rb b/apps/workbench/test/functional/pipeline_instances_controller_test.rb
index ffa2bfc..77da2ad 100644
--- a/apps/workbench/test/functional/pipeline_instances_controller_test.rb
+++ b/apps/workbench/test/functional/pipeline_instances_controller_test.rb
@@ -1,4 +1,62 @@
 require 'test_helper'
 
 class PipelineInstancesControllerTest < ActionController::TestCase
+  def create_instance_long_enough_to
+    pt_fixture = api_fixture('pipeline_templates')['two_part']
+    post :create, {
+      pipeline_instance: {
+        pipeline_template_uuid: pt_fixture['uuid']
+      },
+      format: :json
+    }, session_for(:active)
+    assert_response :success
+    pi_uuid = assigns(:object).uuid
+    assert_not_nil assigns(:object)
+    yield pi_uuid, pt_fixture
+    post :destroy, {
+      id: pi_uuid,
+      format: :json
+    }
+    assert_response :success
+  end
+
+  test "pipeline instance components populated after create" do
+    create_instance_long_enough_to do |new_instance_uuid, template_fixture|
+      assert_equal(template_fixture['components'].to_json,
+                   assigns(:object).components.to_json)
+    end
+  end
+
+  test "update script_parameters one at a time using merge param" do
+    create_instance_long_enough_to do |new_instance_uuid, template_fixture|
+      post :update, {
+        id: new_instance_uuid,
+        pipeline_instance: {
+          components: {
+            "part-two" => {
+              script_parameters: {
+                integer_with_value: {
+                  value: 9
+                },
+                plain_string: {
+                  value: 'quux'
+                },
+              }
+            }
+          }
+        },
+        merge: true,
+        format: :json
+      }, session_for(:active)
+      assert_response :success
+      assert_not_nil assigns(:object)
+      orig_params = template_fixture['components']['part-two']['script_parameters']
+      new_params = assigns(:object).components[:'part-two'][:script_parameters]
+      orig_params.keys.each do |k|
+        unless %w(integer_with_value plain_string).index(k)
+          assert_equal orig_params[k].to_json, new_params[k.to_sym].to_json
+        end
+      end
+    end
+  end
 end
diff --git a/apps/workbench/test/functional/users_controller_test.rb b/apps/workbench/test/functional/users_controller_test.rb
index aadee36..8b026cb 100644
--- a/apps/workbench/test/functional/users_controller_test.rb
+++ b/apps/workbench/test/functional/users_controller_test.rb
@@ -1,6 +1,11 @@
 require 'test_helper'
 
 class UsersControllerTest < ActionController::TestCase
+  test "valid token works in functional test" do
+    get :index, {}, session_for(:active)
+    assert_response :success
+  end
+
   test "ignore previously valid token (for deleted user), don't crash" do
     get :welcome, {}, session_for(:valid_token_deleted_user)
     assert_response :success
diff --git a/services/api/test/fixtures/pipeline_templates.yml b/services/api/test/fixtures/pipeline_templates.yml
new file mode 100644
index 0000000..454c184
--- /dev/null
+++ b/services/api/test/fixtures/pipeline_templates.yml
@@ -0,0 +1,36 @@
+two_part:
+  uuid: zzzzz-p5p6p-aox0k0ofxrystgw
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  created_at: 2014-04-14 12:35:04 -0400
+  updated_at: 2014-04-14 12:35:04 -0400
+  modified_at: 2014-04-14 12:35:04 -0400
+  modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  name: Two Part Pipeline Template
+  components:
+    part-one:
+      script: foo
+      script_version: master
+      script_parameters:
+        input:
+          required: true
+          dataclass: collection
+    part-two:
+      script: bar
+      script_version: master
+      script_parameters:
+        input:
+          output_of: part-one
+        integer_with_default:
+          default: 123
+        integer_with_value:
+          value: 123
+        string_with_default:
+          default: baz
+        string_with_value:
+          value: baz
+        plain_string: qux
+        array_with_default: # important to test repeating values in the array!
+          default: [1,1,2,3,5]
+        array_with_value: # important to test repeating values in the array!
+          value: [1,1,2,3,5]

commit 481e341b75f1c6c0015171539c008e540dea2c2d
Author: Tom Clegg <tom at curoverse.com>
Date:   Sun Apr 13 15:38:00 2014 -0400

    Fix exception when valid token points to missing user

diff --git a/apps/workbench/test/functional/users_controller_test.rb b/apps/workbench/test/functional/users_controller_test.rb
index ae395ae..aadee36 100644
--- a/apps/workbench/test/functional/users_controller_test.rb
+++ b/apps/workbench/test/functional/users_controller_test.rb
@@ -1,8 +1,7 @@
 require 'test_helper'
 
 class UsersControllerTest < ActionController::TestCase
-  test "valid token for deleted user ignored instead of crashing" do
-    skip
+  test "ignore previously valid token (for deleted user), don't crash" do
     get :welcome, {}, session_for(:valid_token_deleted_user)
     assert_response :success
     assert_nil assigns(:my_jobs)
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 06e1838..dffdd5d 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -340,6 +340,9 @@ class ApplicationController < ActionController::Base
           session[:api_client_authorization_id] = api_client_auth.id
           user = api_client_auth.user
           api_client = api_client_auth.api_client
+        else
+          # Token seems valid, but points to a non-existent (deleted?) user.
+          api_client_auth = nil
         end
       elsif session[:user_id]
         user = User.find(session[:user_id]) rescue nil
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 e62eff8..0a2418e 100644
--- a/services/api/test/functional/arvados/v1/users_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/users_controller_test.rb
@@ -44,6 +44,12 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_equal true, me['is_active']
   end
 
+  test "respond 401 if given token exists but user record is missing" do
+    authorize_with :valid_token_deleted_user
+    get :current, {format: :json}
+    assert_response 401
+  end
+
   test "create new user with user as input" do
     authorize_with :admin
     post :create, user: {

commit 0589ee6c2384e9a38720d67c8b86f5adf1d27902
Author: Tom Clegg <tom at curoverse.com>
Date:   Sun Apr 13 01:39:35 2014 -0400

    Add tests to expose some token handling bugs.

diff --git a/apps/workbench/test/functional/users_controller_test.rb b/apps/workbench/test/functional/users_controller_test.rb
index c67c56b..ae395ae 100644
--- a/apps/workbench/test/functional/users_controller_test.rb
+++ b/apps/workbench/test/functional/users_controller_test.rb
@@ -1,4 +1,21 @@
 require 'test_helper'
 
 class UsersControllerTest < ActionController::TestCase
+  test "valid token for deleted user ignored instead of crashing" do
+    skip
+    get :welcome, {}, session_for(:valid_token_deleted_user)
+    assert_response :success
+    assert_nil assigns(:my_jobs)
+    assert_nil assigns(:my_ssh_keys)
+  end
+
+  test "expired token redirects to api server login" do
+    get :show, {
+      id: api_fixture('users')['active']['uuid']
+    }, session_for(:expired_trustedclient)
+    assert_response :redirect
+    assert_match /^#{Rails.configuration.arvados_login_base}/, @response.redirect_url
+    assert_nil assigns(:my_jobs)
+    assert_nil assigns(:my_ssh_keys)
+  end
 end
diff --git a/apps/workbench/test/integration/logins_test.rb b/apps/workbench/test/integration/logins_test.rb
index 185d9cb..6e5389e 100644
--- a/apps/workbench/test/integration/logins_test.rb
+++ b/apps/workbench/test/integration/logins_test.rb
@@ -11,4 +11,12 @@ class LoginsTest < ActionDispatch::IntegrationTest
     visit page_with_token('expired_trustedclient')
     assert page.has_text? 'Log in'
   end
+
+  test "expired token yields login page, not error page" do
+    skip
+    visit page_with_token('expired_trustedclient')
+    # Even the error page has a "Log in" link. We should look for
+    # something that only appears the real login page.
+    assert page.has_text? 'Please log in'
+  end
 end

commit f64a44536ad550ba4424a7f34f7358938b0e4dcc
Author: Tom Clegg <tom at curoverse.com>
Date:   Sun Apr 13 01:33:33 2014 -0400

    Move test-api-server framework so it works in functional and unit tests too.

diff --git a/apps/workbench/test/integration_helper.rb b/apps/workbench/test/integration_helper.rb
index 30643bc..88aec2c 100644
--- a/apps/workbench/test/integration_helper.rb
+++ b/apps/workbench/test/integration_helper.rb
@@ -4,20 +4,12 @@ require 'capybara/poltergeist'
 require 'uri'
 require 'yaml'
 
-$ARV_API_SERVER_DIR = File.expand_path('../../../../services/api', __FILE__)
-SERVER_PID_PATH = 'tmp/pids/server.pid'
-
 class ActionDispatch::IntegrationTest
   # Make the Capybara DSL available in all integration tests
   include Capybara::DSL
+  include ApiFixtureLoader
 
-  def self.api_fixture(name)
-    # Returns the data structure from the named API server test fixture.
-    path = File.join($ARV_API_SERVER_DIR, 'test', 'fixtures', "#{name}.yml")
-    YAML.load(IO.read(path))
-  end
-
-  @@API_AUTHS = api_fixture('api_client_authorizations')
+  @@API_AUTHS = self.api_fixture('api_client_authorizations')
 
   def page_with_token(token, path='/')
     # Generate a page path with an embedded API token.
@@ -31,48 +23,3 @@ class ActionDispatch::IntegrationTest
     "#{path}#{sep}#{q_string}"
   end
 end
-
-class IntegrationTestRunner < MiniTest::Unit
-  # Make a hash that unsets Bundle's environment variables.
-  # We'll use this environment when we launch Bundle commands in the API
-  # server.  Otherwise, those commands will try to use Workbench's gems, etc.
-  @@APIENV = Hash[ENV.map { |key, val|
-                    (key =~ /^BUNDLE_/) ? [key, nil] : nil
-                  }.compact]
-
-  def _system(*cmd)
-    if not system(@@APIENV, *cmd)
-      raise RuntimeError, "#{cmd[0]} returned exit code #{$?.exitstatus}"
-    end
-  end
-
-  def _run(args=[])
-    Capybara.javascript_driver = :poltergeist
-    server_pid = Dir.chdir($ARV_API_SERVER_DIR) do |apidir|
-      _system('bundle', 'exec', 'rake', 'db:test:load')
-      _system('bundle', 'exec', 'rake', 'db:fixtures:load')
-      _system('bundle', 'exec', 'rails', 'server', '-d')
-      timeout = Time.now.tv_sec + 10
-      begin
-        sleep 0.2
-        begin
-          server_pid = IO.read(SERVER_PID_PATH).to_i
-          good_pid = (server_pid > 0) and (Process.kill(0, pid) rescue false)
-        rescue Errno::ENOENT
-          good_pid = false
-        end
-      end while (not good_pid) and (Time.now.tv_sec < timeout)
-      if not good_pid
-        raise RuntimeError, "could not find API server Rails pid"
-      end
-      server_pid
-    end
-    begin
-      super(args)
-    ensure
-      Process.kill('TERM', server_pid)
-    end
-  end
-end
-
-MiniTest::Unit.runner = IntegrationTestRunner.new
diff --git a/apps/workbench/test/test_helper.rb b/apps/workbench/test/test_helper.rb
index 8bf1192..145914f 100644
--- a/apps/workbench/test/test_helper.rb
+++ b/apps/workbench/test/test_helper.rb
@@ -2,6 +2,9 @@ ENV["RAILS_ENV"] = "test"
 require File.expand_path('../../config/environment', __FILE__)
 require 'rails/test_help'
 
+$ARV_API_SERVER_DIR = File.expand_path('../../../../services/api', __FILE__)
+SERVER_PID_PATH = 'tmp/pids/server.pid'
+
 class ActiveSupport::TestCase
   # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
   #
@@ -11,3 +14,78 @@ class ActiveSupport::TestCase
 
   # Add more helper methods to be used by all tests here...
 end
+
+module ApiFixtureLoader
+  def self.included(base)
+    base.extend(ClassMethods)
+  end
+
+  module ClassMethods
+    @@api_fixtures = {}
+    def api_fixture(name)
+      # Returns the data structure from the named API server test fixture.
+      @@api_fixtures[name] ||= \
+      begin
+        path = File.join($ARV_API_SERVER_DIR, 'test', 'fixtures', "#{name}.yml")
+        YAML.load(IO.read(path))
+      end
+    end
+  end
+  def api_fixture name
+    self.class.api_fixture name
+  end
+end
+
+class ActiveSupport::TestCase
+  include ApiFixtureLoader
+  def session_for api_client_auth_name
+    {
+      arvados_api_token: api_fixture('api_client_authorizations')[api_client_auth_name.to_s]['api_token']
+    }
+  end
+end
+
+class ApiServerBackedTestRunner < MiniTest::Unit
+  # Make a hash that unsets Bundle's environment variables.
+  # We'll use this environment when we launch Bundle commands in the API
+  # server.  Otherwise, those commands will try to use Workbench's gems, etc.
+  @@APIENV = Hash[ENV.map { |key, val|
+                    (key =~ /^BUNDLE_/) ? [key, nil] : nil
+                  }.compact]
+
+  def _system(*cmd)
+    if not system(@@APIENV, *cmd)
+      raise RuntimeError, "#{cmd[0]} returned exit code #{$?.exitstatus}"
+    end
+  end
+
+  def _run(args=[])
+    Capybara.javascript_driver = :poltergeist
+    server_pid = Dir.chdir($ARV_API_SERVER_DIR) do |apidir|
+      _system('bundle', 'exec', 'rake', 'db:test:load')
+      _system('bundle', 'exec', 'rake', 'db:fixtures:load')
+      _system('bundle', 'exec', 'rails', 'server', '-d')
+      timeout = Time.now.tv_sec + 10
+      begin
+        sleep 0.2
+        begin
+          server_pid = IO.read(SERVER_PID_PATH).to_i
+          good_pid = (server_pid > 0) and (Process.kill(0, pid) rescue false)
+        rescue Errno::ENOENT
+          good_pid = false
+        end
+      end while (not good_pid) and (Time.now.tv_sec < timeout)
+      if not good_pid
+        raise RuntimeError, "could not find API server Rails pid"
+      end
+      server_pid
+    end
+    begin
+      super(args)
+    ensure
+      Process.kill('TERM', server_pid)
+    end
+  end
+end
+
+MiniTest::Unit.runner = ApiServerBackedTestRunner.new

commit 60a660385c1643efbdf11a8e5fa1deae1f008d2b
Author: Tom Clegg <tom at curoverse.com>
Date:   Sun Apr 13 01:15:23 2014 -0400

    Add token that is valid except that it points to a missing user.

diff --git a/services/api/test/fixtures/api_client_authorizations.yml b/services/api/test/fixtures/api_client_authorizations.yml
index f60ba01..5cada90 100644
--- a/services/api/test/fixtures/api_client_authorizations.yml
+++ b/services/api/test/fixtures/api_client_authorizations.yml
@@ -71,3 +71,9 @@ expired_trustedclient:
   user: active
   api_token: 5hpni7izokzcatku2896xxwqdbt5ptomn04r6auc7fohnli82v
   expires_at: 1970-01-01 00:00:00
+
+valid_token_deleted_user:
+  api_client: trusted_workbench
+  user_id: 1234567
+  api_token: tewfa58099sndckyqhlgd37za6e47o6h03r9l1vpll23hudm8b
+  expires_at: 2038-01-01 00:00:00

commit 4729ceb08aa3846326d1729f766f8f10179a2a78
Author: Tom Clegg <tom at curoverse.com>
Date:   Sun Apr 13 01:14:05 2014 -0400

    Send HTTP 500 if we end up in render_error without a more specific status.

diff --git a/apps/workbench/app/controllers/application_controller.rb b/apps/workbench/app/controllers/application_controller.rb
index 18a5d4f..41d5566 100644
--- a/apps/workbench/app/controllers/application_controller.rb
+++ b/apps/workbench/app/controllers/application_controller.rb
@@ -30,6 +30,7 @@ class ApplicationController < ActionController::Base
   end
 
   def render_error(opts)
+    opts = {status: 500}.merge opts
     respond_to do |f|
       # json must come before html here, so it gets used as the
       # default format when js is requested by the client. This lets

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list