Merge branch 'master' into 4523-search-index
authorRadhika Chippada <radhika@curoverse.com>
Tue, 27 Jan 2015 17:38:42 +0000 (12:38 -0500)
committerRadhika Chippada <radhika@curoverse.com>
Tue, 27 Jan 2015 17:38:42 +0000 (12:38 -0500)
43 files changed:
apps/workbench/app/controllers/projects_controller.rb
apps/workbench/app/views/users/profile.html.erb
apps/workbench/test/controllers/projects_controller_test.rb
apps/workbench/test/integration/projects_test.rb
apps/workbench/test/integration/user_profile_test.rb
doc/_config.yml
doc/_includes/_navbar_top.liquid
doc/_layouts/default.html.liquid
doc/css/carousel-override.css [new file with mode: 0644]
doc/images/keyfeatures/chooseinputs.png [new file with mode: 0644]
doc/images/keyfeatures/collectionpage.png [new file with mode: 0644]
doc/images/keyfeatures/dashboard2.png [new file with mode: 0644]
doc/images/keyfeatures/graph.png [new file with mode: 0644]
doc/images/keyfeatures/log.png [new file with mode: 0644]
doc/images/keyfeatures/provenance.png [new file with mode: 0644]
doc/images/keyfeatures/rerun.png [new file with mode: 0644]
doc/images/keyfeatures/running2.png [new file with mode: 0644]
doc/images/keyfeatures/shared.png [new file with mode: 0644]
doc/images/keyfeatures/webupload.png [new file with mode: 0644]
doc/images/quickstart/1.png [new file with mode: 0644]
doc/images/quickstart/2.png [new file with mode: 0644]
doc/images/quickstart/3.png [new file with mode: 0644]
doc/images/quickstart/4.png [new file with mode: 0644]
doc/images/quickstart/5.png [new file with mode: 0644]
doc/images/quickstart/6.png [new file with mode: 0644]
doc/images/quickstart/7.png [new file with mode: 0644]
doc/images/uses/choosefiles.png [new file with mode: 0644]
doc/images/uses/gotohome.png [new file with mode: 0644]
doc/images/uses/rename.png [new file with mode: 0644]
doc/images/uses/share.png [new file with mode: 0644]
doc/images/uses/shared.png [new file with mode: 0644]
doc/images/uses/sharedsubdirs.png [new file with mode: 0644]
doc/images/uses/uploaddata.png [new file with mode: 0644]
doc/images/uses/uploading.png [new file with mode: 0644]
doc/index.html.liquid
doc/start/getting_started/firstpipeline.html.textile.liquid [new file with mode: 0644]
doc/start/getting_started/sharedata.html.textile.liquid [new file with mode: 0644]
doc/start/index.html.textile.liquid [new file with mode: 0644]
doc/start/index.html.textile.liquid.bkup [new file with mode: 0644]
sdk/cli/bin/crunch-job
sdk/python/arvados/events.py
services/crunchstat/crunchstat.go
services/crunchstat/crunchstat_test.go

index a0bf262c960384a58e11d34d5949be5b7dc60a38..df454f72afcf3e24948d67ea00e7f47957a0a720 100644 (file)
@@ -111,7 +111,13 @@ class ProjectsController < ApplicationController
         @removed_uuids << link.uuid
         link.destroy
       end
-      if item.owner_uuid == @object.uuid
+
+      # If this object has the 'expires_at' attribute, then simply mark it
+      # expired.
+      if item.attributes.include?("expires_at")
+        item.update_attributes expires_at: Time.now
+        @removed_uuids << item.uuid
+      elsif item.owner_uuid == @object.uuid
         # Object is owned by this project. Remove it from the project by
         # changing owner to the current user.
         begin
index aab8843930a3b9590862c7332bf5316c7d720c7e..45aea01b957c419375cb103c46aec5b60315c95e 100644 (file)
               <%= hidden_field_tag :offer_return_to, params[:offer_return_to] %>
               <%= hidden_field_tag :return_to, profile_user_path(current_user.uuid, offer_return_to: params[:offer_return_to]) %>
               <div class="form-group">
-                  <label for="email" class="col-sm-3 control-label"> Email </label>
+                  <label for="email" class="col-sm-3 control-label"> E-mail </label>
                   <div class="col-sm-8">
                     <p class="form-control-static" id="email" name="email"><%=current_user.email%></p>
                   </div>
               </div>
               <div class="form-group">
-                  <label for="first_name" class="col-sm-3 control-label"> First name </label>
+                  <label for="first_name" class="col-sm-3 control-label"> First Name </label>
                   <div class="col-sm-8">
                     <p class="form-control-static" id="first_name" name="first_name"><%=current_user.first_name%></p>
                   </div>
               </div>
               <div class="form-group">
-                  <label for="last_name" class="col-sm-3 control-label"> Last name </label>
+                  <label for="last_name" class="col-sm-3 control-label"> Last Name </label>
                   <div class="col-sm-8">
                     <p class="form-control-static" id="last_name" name="last_name"><%=current_user.last_name%></p>
                   </div>
index 8407dc324257518b51144ee9827a7de814f8b304..5d7b1e27b3b46453fad4c32ddbdf2b4bba3400c7 100644 (file)
@@ -100,7 +100,9 @@ class ProjectsControllerTest < ActionController::TestCase
     assert_response :success
   end
 
-  test "project admin can remove items from the project" do
+  test "project admin can remove collections from the project" do
+    # Deleting an object that supports 'expires_at' should make it
+    # completely inaccessible to API queries, not simply moved out of the project.
     coll_key = "collection_to_remove_from_subproject"
     coll_uuid = api_fixture("collections")[coll_key]["uuid"]
     delete(:remove_item,
@@ -111,6 +113,29 @@ class ProjectsControllerTest < ActionController::TestCase
     assert_response :success
     assert_match(/\b#{coll_uuid}\b/, @response.body,
                  "removed object not named in response")
+
+    use_token :subproject_admin
+    assert_raise ArvadosApiClient::NotFoundException do
+      Collection.find(coll_uuid)
+    end
+  end
+
+  test "project admin can remove items from project other than collections" do
+    # An object which does not have an expired_at field (e.g. Specimen)
+    # should be implicitly moved to the user's Home project when removed.
+    specimen_uuid = api_fixture('specimens', 'in_asubproject')['uuid']
+    delete(:remove_item,
+           { id: api_fixture('groups', 'asubproject')['uuid'],
+             item_uuid: specimen_uuid,
+             format: 'js' },
+           session_for(:subproject_admin))
+    assert_response :success
+    assert_match(/\b#{specimen_uuid}\b/, @response.body,
+                 "removed object not named in response")
+
+    use_token :subproject_admin
+    new_specimen = Specimen.find(specimen_uuid)
+    assert_equal api_fixture('users', 'subproject_admin')['uuid'], new_specimen.owner_uuid
   end
 
   test 'projects#show tab infinite scroll partial obeys limit' do
index 77d5722947abb24e0d02bc452819960c85b5ccfc..7f051f673f6f3d87cead8657f35e8d7732b09c34 100644 (file)
@@ -239,14 +239,6 @@ class ProjectsTest < ActionDispatch::IntegrationTest
 
       when 'Remove'
         assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after remove'
-        visit page_with_token 'active', '/'
-        find("#projects-menu").click
-        find(".dropdown-menu a", text: "Home").click
-        assert page.has_text?(my_collection['name']), 'Collection not found in home project after remove'
-        if expect_name_change
-          assert page.has_text?(my_collection['name']+' removed from ' + src['name']),
-            'Collection with update name is not found in home project after remove'
-        end
       end
     end
   end
index cbd591a38dcc69ff60f0340cc2d736ea3f01dd00..accc6a7963ef5a9a8dee8ad188f0c8552d9d070d 100644 (file)
@@ -63,10 +63,10 @@ class UserProfileTest < ActionDispatch::IntegrationTest
     assert page.has_no_text?('Projects shared with me'), 'Found text - Projects shared with me'
 
     assert page.has_text?('Profile'), 'No text - Profile'
-    assert page.has_text?('First name'), 'No text - First name'
-    assert page.has_text?('Last name'), 'No text - Last name'
+    assert page.has_text?('First Name'), 'No text - First Name'
+    assert page.has_text?('Last Name'), 'No text - Last Name'
     assert page.has_text?('Identity URL'), 'No text - Identity URL'
-    assert page.has_text?('Email'), 'No text - Email'
+    assert page.has_text?('E-mail'), 'No text - E-mail'
     assert page.has_text?(user['email']), 'No text - user email'
 
     # Using the default profile which has message and one required field
@@ -74,8 +74,8 @@ class UserProfileTest < ActionDispatch::IntegrationTest
     # Save profile without filling in the required field. Expect to be back in this profile page again
     click_button "Save profile"
     assert page.has_text?('Profile'), 'No text - Profile'
-    assert page.has_text?('First name'), 'No text - First name'
-    assert page.has_text?('Last name'), 'No text - Last name'
+    assert page.has_text?('First Name'), 'No text - First Name'
+    assert page.has_text?('Last Name'), 'No text - Last Name'
     assert page.has_text?('Save profile'), 'No text - Save profile'
 
     # This time fill in required field and then save. Expect to go to requested page after that.
index af5160f52602af292cf6470987200510a91dc03b..ab1eb9efabda2f79e967369d19e9cfa7f2bacb85 100644 (file)
@@ -13,6 +13,14 @@ arvados_workbench_host: localhost
 exclude: ["Rakefile", "tmp", "vendor"]
 
 navbar:
+  start:
+    - Getting Started:
+      - start/index.html.textile.liquid
+    - Quickstart:
+      - start/getting_started/firstpipeline.html.textile.liquid
+    - Common Use Cases:
+      - start/getting_started/sharedata.html.textile.liquid
+
   userguide:
     - Getting Started:
       - user/index.html.textile.liquid
index 9123893c38b95ce10a493349924171530fa8e5aa..73b7abb9a355f6647c78fb98f9ca38074ab1b056 100644 (file)
@@ -11,6 +11,7 @@
     </div>
     <div class="collapse navbar-collapse" id="bs-navbar-collapse">
       <ul class="nav navbar-nav">
+        <li {% if page.navsection == 'start' %} class="active" {% endif %}><a href="{{ site.baseurl }}/start/index.html">Getting&nbsp;Started</a></li>
         <li {% if page.navsection == 'userguide' %} class="active" {% endif %}><a href="{{ site.baseurl }}/user/index.html">User&nbsp;Guide</a></li>
         <li {% if page.navsection == 'sdk' %} class="active" {% endif %}><a href="{{ site.baseurl }}/sdk/index.html">SDK&nbsp;Reference</a></li>
         <li {% if page.navsection == 'api' %} class="active" {% endif %}><a href="{{ site.baseurl }}/api/index.html">API&nbsp;Reference</a></li>
index 88da01b178669ee2065536e9e2e532f802ee1d35..2a45dd5bd053b6507210b26856fa81cfa92a82e6 100644 (file)
@@ -13,6 +13,7 @@
     <link href="{{ site.baseurl }}/css/badges.css" rel="stylesheet">
     <link href="{{ site.baseurl }}/css/code.css" rel="stylesheet">
     <link href="{{ site.baseurl }}/css/font-awesome.css" rel="stylesheet">
+    <link href="{{ site.baseurl }}/css/carousel-override.css" rel="stylesheet">
     <style>
       html {
       height:100%;
diff --git a/doc/css/carousel-override.css b/doc/css/carousel-override.css
new file mode 100644 (file)
index 0000000..fa2c150
--- /dev/null
@@ -0,0 +1,25 @@
+.carousel-control {
+  width: 5%;
+}
+
+.carousel-caption {
+  position: static;
+  background: rgba(0,0,0,0.6);
+  color: white;
+  padding-bottom: 35px;
+  padding-left: 1em;
+  padding-right: 1em;
+  padding-top: 15px;
+}
+
+.carousel {
+  overflow: hidden;
+  border-radius: 5px;
+  max-width: 900px;
+  margin: 1em;
+}
+
+.carousel-indicators {
+  bottom: 0px;
+}
+
diff --git a/doc/images/keyfeatures/chooseinputs.png b/doc/images/keyfeatures/chooseinputs.png
new file mode 100644 (file)
index 0000000..38d3766
Binary files /dev/null and b/doc/images/keyfeatures/chooseinputs.png differ
diff --git a/doc/images/keyfeatures/collectionpage.png b/doc/images/keyfeatures/collectionpage.png
new file mode 100644 (file)
index 0000000..c002073
Binary files /dev/null and b/doc/images/keyfeatures/collectionpage.png differ
diff --git a/doc/images/keyfeatures/dashboard2.png b/doc/images/keyfeatures/dashboard2.png
new file mode 100644 (file)
index 0000000..b14d49b
Binary files /dev/null and b/doc/images/keyfeatures/dashboard2.png differ
diff --git a/doc/images/keyfeatures/graph.png b/doc/images/keyfeatures/graph.png
new file mode 100644 (file)
index 0000000..df20ea5
Binary files /dev/null and b/doc/images/keyfeatures/graph.png differ
diff --git a/doc/images/keyfeatures/log.png b/doc/images/keyfeatures/log.png
new file mode 100644 (file)
index 0000000..d74c72a
Binary files /dev/null and b/doc/images/keyfeatures/log.png differ
diff --git a/doc/images/keyfeatures/provenance.png b/doc/images/keyfeatures/provenance.png
new file mode 100644 (file)
index 0000000..730c776
Binary files /dev/null and b/doc/images/keyfeatures/provenance.png differ
diff --git a/doc/images/keyfeatures/rerun.png b/doc/images/keyfeatures/rerun.png
new file mode 100644 (file)
index 0000000..ae20804
Binary files /dev/null and b/doc/images/keyfeatures/rerun.png differ
diff --git a/doc/images/keyfeatures/running2.png b/doc/images/keyfeatures/running2.png
new file mode 100644 (file)
index 0000000..0bac277
Binary files /dev/null and b/doc/images/keyfeatures/running2.png differ
diff --git a/doc/images/keyfeatures/shared.png b/doc/images/keyfeatures/shared.png
new file mode 100644 (file)
index 0000000..1199a4a
Binary files /dev/null and b/doc/images/keyfeatures/shared.png differ
diff --git a/doc/images/keyfeatures/webupload.png b/doc/images/keyfeatures/webupload.png
new file mode 100644 (file)
index 0000000..1475711
Binary files /dev/null and b/doc/images/keyfeatures/webupload.png differ
diff --git a/doc/images/quickstart/1.png b/doc/images/quickstart/1.png
new file mode 100644 (file)
index 0000000..21bc3f9
Binary files /dev/null and b/doc/images/quickstart/1.png differ
diff --git a/doc/images/quickstart/2.png b/doc/images/quickstart/2.png
new file mode 100644 (file)
index 0000000..fac32c4
Binary files /dev/null and b/doc/images/quickstart/2.png differ
diff --git a/doc/images/quickstart/3.png b/doc/images/quickstart/3.png
new file mode 100644 (file)
index 0000000..a080b01
Binary files /dev/null and b/doc/images/quickstart/3.png differ
diff --git a/doc/images/quickstart/4.png b/doc/images/quickstart/4.png
new file mode 100644 (file)
index 0000000..a6345ef
Binary files /dev/null and b/doc/images/quickstart/4.png differ
diff --git a/doc/images/quickstart/5.png b/doc/images/quickstart/5.png
new file mode 100644 (file)
index 0000000..754d0a3
Binary files /dev/null and b/doc/images/quickstart/5.png differ
diff --git a/doc/images/quickstart/6.png b/doc/images/quickstart/6.png
new file mode 100644 (file)
index 0000000..29fb7c0
Binary files /dev/null and b/doc/images/quickstart/6.png differ
diff --git a/doc/images/quickstart/7.png b/doc/images/quickstart/7.png
new file mode 100644 (file)
index 0000000..e7be5c2
Binary files /dev/null and b/doc/images/quickstart/7.png differ
diff --git a/doc/images/uses/choosefiles.png b/doc/images/uses/choosefiles.png
new file mode 100644 (file)
index 0000000..2d38363
Binary files /dev/null and b/doc/images/uses/choosefiles.png differ
diff --git a/doc/images/uses/gotohome.png b/doc/images/uses/gotohome.png
new file mode 100644 (file)
index 0000000..144a3b1
Binary files /dev/null and b/doc/images/uses/gotohome.png differ
diff --git a/doc/images/uses/rename.png b/doc/images/uses/rename.png
new file mode 100644 (file)
index 0000000..d633242
Binary files /dev/null and b/doc/images/uses/rename.png differ
diff --git a/doc/images/uses/share.png b/doc/images/uses/share.png
new file mode 100644 (file)
index 0000000..f578c48
Binary files /dev/null and b/doc/images/uses/share.png differ
diff --git a/doc/images/uses/shared.png b/doc/images/uses/shared.png
new file mode 100644 (file)
index 0000000..86b7d54
Binary files /dev/null and b/doc/images/uses/shared.png differ
diff --git a/doc/images/uses/sharedsubdirs.png b/doc/images/uses/sharedsubdirs.png
new file mode 100644 (file)
index 0000000..6778f54
Binary files /dev/null and b/doc/images/uses/sharedsubdirs.png differ
diff --git a/doc/images/uses/uploaddata.png b/doc/images/uses/uploaddata.png
new file mode 100644 (file)
index 0000000..f369270
Binary files /dev/null and b/doc/images/uses/uploaddata.png differ
diff --git a/doc/images/uses/uploading.png b/doc/images/uses/uploading.png
new file mode 100644 (file)
index 0000000..473fc5a
Binary files /dev/null and b/doc/images/uses/uploading.png differ
index a4255b65d29c1f3dd64fd23cb98ed042806f8f06..7c7eaed76033249dce1184bcf592c14ce882e89a 100644 (file)
@@ -10,7 +10,7 @@ title: Arvados | Documentation
     <div class="row">
       <div class="col-sm-6">
         <h1>ARVADOS</h1>
-        <p>manuals, guides, and references</p>
+        <p>A free and open source platform for big data science</p>
       </div>
       <div class="col-sm-6">
         <img src="images/dax-reading-book.png" style="max-height: 10em" alt="Dax reading a book" />
@@ -22,9 +22,17 @@ title: Arvados | Documentation
 <div class="container-fluid">
   <div class="row">
     <div class="col-sm-5">
-      <p>This site contains documentation for the <a href="https://arvados.org/">Arvados platform</a>. The documentation is being developed as part of the open source project. It is a work in progress that has just gotten started. You can get involved by <a href="https://arvados.org/projects/arvados/wiki/Documentation">joining the documentation effort</a>.
+      <p><a href="https://arvados.org/">Arvados</a>  enables you to quickly begin using cloud computing resources in your data science work. It allows you to track your methods and datasets, share them securely, and easily re-run analyses.
+      </p>
+      <p>Check out our <a href="{{ site.baseurl }}/start/index.html">key features</a>, complete with screenshots, and then follow our tutorial to <a href="{{ site.baseurl }}/start/getting_started/firstpipeline.html">run your first pipeline</a> using our <a href="http://lp.curoverse.com/beta-signup/">public beta</a>.
+      </p>
+      <p>On this page, you can also find more in-depth guides for using Arvados.
+      </p>
     </div>
     <div class="col-sm-7" style="border-left: solid; border-width: 1px">
+      <p>
+        <a href="{{ site.baseurl }}/start/index.html">Getting Started</a> &mdash; Start here if you're new to Arvados.
+      </p>
       <p>
         <a href="{{ site.baseurl }}/user/index.html">User Guide</a> &mdash; How to manage data and do analysis with Arvados.
       </p>
diff --git a/doc/start/getting_started/firstpipeline.html.textile.liquid b/doc/start/getting_started/firstpipeline.html.textile.liquid
new file mode 100644 (file)
index 0000000..d5d7f98
--- /dev/null
@@ -0,0 +1,89 @@
+---
+layout: default
+navsection: start 
+title: Run your first pipeline in minutes
+...
+
+h2. LobSTR v3 
+
+In this quickstart guide, we'll run an existing pipeline with pre-existing data. Step-by-step instructions are shown below. You can follow along using your own local install or by using Curoverse's <a href="http://lp.curoverse.com/beta-signup/">hosted version of Arvados</a> (in public beta, any Google account can be used to login).
+
+(For more information about this pipeline, see our <a href="https://arvados.org/projects/arvados/wiki/LobSTR_tutorial">detailed lobSTR guide</a>).
+
+<div id="carousel-firstpipe" class="carousel slide" data-interval="false">
+  <!-- Indicators -->
+  <ol class="carousel-indicators">
+    <li data-target="#carousel-firstpipe" data-slide-to="0" class="active"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="1"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="2"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="3"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="4"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="5"></li>
+    <li data-target="#carousel-firstpipe" data-slide-to="6"></li>
+  </ol>
+
+  <!-- Wrapper for slides -->
+  <div class="carousel-inner" role="listbox">
+    <div class="item active">
+      <img src="{{ site.baseurl }}/images/quickstart/1.png" alt="Step 1. At the dashboard, click 'Run a pipeline...'.">
+      <div class="carousel-caption">
+        Step 1. At the dashboard, click 'Run a pipeline...'.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/2.png" alt="Choose 'lobstr v.3' and hit 'Next'.">
+      <div class="carousel-caption">
+        Choose 'lobstr v.3' and hit 'Next'.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/3.png" alt="Rename the pipeline instance, then click 'Run'. Click 'Choose' to change the default inputs.">
+      <div class="carousel-caption">
+        Rename the pipeline instance, then click 'Run'. Click 'Choose' to change the default inputs.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/4.png" alt="Here we search for and choose new inputs.">
+      <div class="carousel-caption">
+        Here we search for and choose new inputs.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/5.png" alt="After the job completes, you can re-run it with one click.">
+      <div class="carousel-caption">
+        After the job completes, you can re-run it with one click.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/6.png" alt="You can inspect details about the pipeline which are automatically logged.">
+      <div class="carousel-caption">
+        You can inspect automatically-logged details about the pipeline.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/quickstart/7.png" alt="Click 'Create sharing link' to share the output files with people outside Arvados. [END]">
+      <div class="carousel-caption">
+        Click 'Create sharing link' to share the output files with people outside Arvados. [END]
+      </div>
+    </div>
+
+  </div>
+
+  <!-- Controls -->
+  <a class="left carousel-control" href="#carousel-firstpipe" role="button" data-slide="prev">
+    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+    <span class="sr-only">Previous</span>
+  </a>
+  <a class="right carousel-control" href="#carousel-firstpipe" role="button" data-slide="next">
+    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+    <span class="sr-only">Next</span>
+  </a>
+</div>
+
+Tip: You may need to make your browser window bigger to see full-size images in the gallery above.
diff --git a/doc/start/getting_started/sharedata.html.textile.liquid b/doc/start/getting_started/sharedata.html.textile.liquid
new file mode 100644 (file)
index 0000000..572ed34
--- /dev/null
@@ -0,0 +1,97 @@
+---
+layout: default
+navsection: start 
+title: Sharing Data 
+...
+
+You can easily share data entirely through Workbench, the web interface to Arvados.
+
+h2. Upload and share your existing data
+
+Step-by-step instructions are shown below.
+
+<div id="carousel-sharedata" class="carousel slide" data-interval="false">
+  <!-- Indicators -->
+  <ol class="carousel-indicators">
+    <li data-target="#carousel-sharedata" data-slide-to="0" class="active"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="1"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="2"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="3"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="4"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="5"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="6"></li>
+    <li data-target="#carousel-sharedata" data-slide-to="7"></li>
+  </ol>
+
+  <!-- Wrapper for slides -->
+  <div class="carousel-inner" role="listbox">
+    <div class="item active">
+      <img src="{{ site.baseurl }}/images/uses/gotohome.png" alt="Step 1. From the dashboard, go to your Home project.">
+      <div class="carousel-caption">
+        Step 1. From the dashboard, go to your Home project.
+      </div>
+    </div>
+
+    <div class="item">
+    <img src="{{ site.baseurl }}/images/uses/uploaddata.png" alt="Click 'Add data' &rarr; 'Upload files'.">
+      <div class="carousel-caption">
+        Click 'Add data' &rarr; 'Upload files'.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/choosefiles.png" alt="A new collection is created automatically. Choose files to upload and hit Start.">
+      <div class="carousel-caption">
+        A new collection is created automatically. Choose files to upload and hit Start.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/uploading.png" alt="Files will upload and stay uploaded even if the browser is closed.">
+      <div class="carousel-caption">
+        Files will upload and stay uploaded even if the browser is closed.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/rename.png" alt="Rename the collection appropriately.">
+      <div class="carousel-caption">
+        Rename the collection appropriately.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/share.png" alt="Click 'Create sharing link'. You can click 'unshare' at any later point.">
+      <div class="carousel-caption">
+        Click 'Create sharing link'. You can click 'Unshare' at any later point.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/shared.png" alt="Now just share this link with anyone you want.">
+      <div class="carousel-caption">
+        Now just share this link with anyone you want.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/uses/sharedsubdirs.png" alt="Here's a more complex collection. [END]">
+      <div class="carousel-caption">
+        Here's a more complex collection. [END]
+      </div>
+    </div>
+
+  </div>
+
+  <!-- Controls -->
+  <a class="left carousel-control" href="#carousel-sharedata" role="button" data-slide="prev">
+    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+    <span class="sr-only">Previous</span>
+  </a>
+  <a class="right carousel-control" href="#carousel-sharedata" role="button" data-slide="next">
+    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+    <span class="sr-only">Next</span>
+  </a>
+</div>
+
+Tip: You may need to make your browser window bigger to see full-size images in the gallery above.
diff --git a/doc/start/index.html.textile.liquid b/doc/start/index.html.textile.liquid
new file mode 100644 (file)
index 0000000..0aa5064
--- /dev/null
@@ -0,0 +1,128 @@
+---
+layout: default
+navsection: start 
+title: Welcome to Arvados!
+...
+
+This guide provides an introduction to using Arvados to solve big data bioinformatics problems.
+
+h2. What is Arvados?
+
+Arvados is a free and open source bioinformatics platform for genomic and biomedical data.
+
+We address the needs of IT directors, lab principals, and bioinformaticians.
+
+h2. Why use Arvados?
+
+Arvados enables you to quickly begin using cloud computing resources in your bioinformatics work. It allows you to track your methods and datasets, share them securely, and easily re-run analyses.
+
+h3. Take a look (Screenshots gallery) 
+
+<div id="carousel-keyfeatures" class="carousel slide" data-interval="false">
+  <!-- Indicators -->
+  <ol class="carousel-indicators">
+    <li data-target="#carousel-keyfeatures" data-slide-to="0" class="active"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="1"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="2"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="3"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="4"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="5"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="6"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="7"></li>
+    <li data-target="#carousel-keyfeatures" data-slide-to="8"></li>
+  </ol>
+
+  <!-- Wrapper for slides -->
+  <div class="carousel-inner" role="listbox">
+    <div class="item active">
+      <img src="{{ site.baseurl }}/images/keyfeatures/dashboard2.png" alt="[START] After logging in, you will see Workbench's dashboard.">
+      <div class="carousel-caption">
+        [START] After logging in, you will see Workbench's dashboard.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/running2.png" alt="Pipelines describe a set of computational tasks (jobs).">
+      <div class="carousel-caption">
+        Pipelines describe a set of computational tasks (jobs).
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/log.png" alt="The output of all jobs is logged and stored automatically.">
+      <div class="carousel-caption">
+        The output of all jobs is logged and stored automatically.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/graph.png" alt="Pipelines can also be viewed in auto-generated graph form.">
+      <div class="carousel-caption">
+        Pipelines can also be viewed in auto-generated graph form.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/rerun.png" alt="Pipelines can easily be re-run exactly as before, or...">
+      <div class="carousel-caption">
+        Pipelines can easily be re-run exactly as before, or...
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/chooseinputs.png" alt="...you can change parameters or pick new datasets.">
+      <div class="carousel-caption">
+        ...you can change parameters or pick new datasets.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/webupload.png" alt="With web upload, data can be uploaded right in Workbench.">
+      <div class="carousel-caption">
+        With web upload, data can be uploaded right in Workbench.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/collectionpage.png" alt="Collections allow sharing datasets and job outputs easily. 'Create sharing link' with one click.">
+      <div class="carousel-caption">
+        Collections allow sharing datasets and job outputs easily. 'Create sharing link' with one click.
+      </div>
+    </div>
+
+    <div class="item">
+      <img src="{{ site.baseurl }}/images/keyfeatures/provenance.png" alt="Data provenance is tracked automatically. [END]">
+      <div class="carousel-caption">
+        Data provenance is tracked automatically. [END]
+      </div>
+    </div>
+
+
+  </div>
+
+  <!-- Controls -->
+  <a class="left carousel-control" href="#carousel-keyfeatures" role="button" data-slide="prev">
+    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+    <span class="sr-only">Previous</span>
+  </a>
+  <a class="right carousel-control" href="#carousel-keyfeatures" role="button" data-slide="next">
+    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+    <span class="sr-only">Next</span>
+  </a>
+</div>
+
+Note: Workbench is the web interface to Arvados.
+Tip: You may need to make your browser window bigger to see full-size images in the gallery above.
+
+h3. Key Features
+
+<ul>
+<li><strong>Track your methods</strong><br/>
+We log every compute job: software versions, machine images, input and output data hashes. Rely on a computer, not your memory and your note-taking skills.<br/><br/></li>
+<li><strong>Share your methods</strong><br/>
+Show other people what you did. Let them use your workflow on their own data. Publish a permalink to your methods and data, so others can reproduce and build on them easily.<br/><br/></li>
+<li><strong>Track data origin</strong><br/>
+Did you really only use fully consented public data in this analysis?<br/><br/></li>
+<li><strong>Get results sooner</strong><br/>
+Run your compute jobs faster by using multi-nodes and multi-cores, even if your programs are single-threaded.<br/><br/></li>
+</ul>
diff --git a/doc/start/index.html.textile.liquid.bkup b/doc/start/index.html.textile.liquid.bkup
new file mode 100644 (file)
index 0000000..339a84a
--- /dev/null
@@ -0,0 +1,50 @@
+---
+layout: default
+navsection: start 
+title: Welcome to Arvados!
+...
+
+This guide provides an introduction to using Arvados to solve big data bioinformatics problems.
+
+
+h2. Typographic conventions
+
+This manual uses the following typographic conventions:
+
+<notextile>
+<ul>
+<li>Code blocks which are set aside from the text indicate user input to the system.  Commands that should be entered into a Unix shell are indicated by the directory where you should  enter the command ('~' indicates your home directory) followed by '$', followed by the highlighted <span class="userinput">command to enter</span> (do not enter the '$'), and possibly followed by example command output in black.  For example, the following block indicates that you should type <code>ls foo.*</code> while in your home directory and the expected output will be "foo.input" and "foo.output".
+</notextile>
+
+<div class="custom-container key-features">
+<a class="prev" href="#">‹</a>
+
+<div class="carousel">
+    <ul>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/dashboard2.png" style="width:909px; height:503px;" title="[START] After logging in, you see Workbench's dashboard."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/running2.png" style="width:909px; height:503px;" title="Pipelines describe a set of computational tasks (jobs)."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/log.png" style="width:909px; height:503px;" title="The output of all jobs is logged and stored automatically."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/graph.png" style="width:909px; height:503px;" title="Pipelines can be also viewed in auto-generated graph form."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/rerun.png" style="width:909px; height:503px;" title="Pipelines can easily be re-run..."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/chooseinputs.png" style="width:909px; height:503px;" title="...by changing parameters or picking new datasets..."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/webupload.png" style="width:909px; height:503px;" title="...which can be uploaded right in Workbench."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/collectionpage.png" style="width:909px; height:503px;" title="Collections allow sharing datasets and job outputs easily."></li>
+        <li><img class="hascaption" src="{{ site.baseurl }}/images/keyfeatures/provenance.png" style="width:909px; height:503px;" title="Data provenance is tracked automatically. [END]"></li>
+    </ul>
+</div>
+<a class="next" href="#">›</a>
+<div class="clear"></div>
+</div>
+
+<script type="text/javascript">
+(function() {
+    $(".key-features .carousel").jCarouselLite({
+        btnNext: ".key-features .next",
+        btnPrev: ".key-features .prev",
+        visible: 1,
+    });
+});
+('.hascaption').each(function() {
+    $(this).after( "<div style='background: rgba(0,0,0,0.6); color: white; padding: 1.4em;'>" + $(this).attr('title') + "</div>" ); 
+});
+</script>
index 2415217a21bd4dbf6c7e2ae54cbca8d915870d3f..554a1431ee291469f7b46cfbaa24e33c435dcc5c 100755 (executable)
@@ -1907,10 +1907,15 @@ if (readlink ("$destdir.commit") eq $commit && -d $destdir) {
 
 unlink "$destdir.commit";
 mkdir $destdir;
-open TARX, "|-", "tar", "-xC", $destdir;
-{
-  local $/ = undef;
-  print TARX <DATA>;
+
+if (!open(TARX, "|-", "tar", "-xC", $destdir)) {
+  die "Error launching 'tar -xC $destdir': $!";
+}
+# If we send too much data to tar in one write (> 4-5 MiB), it stops, and we
+# get SIGPIPE.  We must feed it data incrementally.
+my $tar_input;
+while (read(DATA, $tar_input, 65536)) {
+  print TARX $tar_input;
 }
 if(!close(TARX)) {
   die "'tar -xC $destdir' exited $?: $!";
index f65486a7f1775e7cedb2bc3e40b2b5d7e9095c9e..7e8cdc3282113ad7984c9e9d93cdb187a0c77b4f 100644 (file)
@@ -13,12 +13,15 @@ _logger = logging.getLogger('arvados.events')
 
 class EventClient(WebSocketClient):
     def __init__(self, url, filters, on_event):
-        ssl_options = None
-        if re.match(r'(?i)^(true|1|yes)$',
-                    config.get('ARVADOS_API_HOST_INSECURE', 'no')):
-            ssl_options={'cert_reqs': ssl.CERT_NONE}
+        # Prefer system's CA certificates (if available)
+        ssl_options = {}
+        certs_path = '/etc/ssl/certs/ca-certificates.crt'
+        if os.path.exists(certs_path):
+            ssl_options['ca_certs'] = certs_path
+        if config.flag_is_true('ARVADOS_API_HOST_INSECURE'):
+            ssl_options['cert_reqs'] = ssl.CERT_NONE
         else:
-            ssl_options={'cert_reqs': ssl.CERT_REQUIRED}
+            ssl_options['cert_reqs'] = ssl.CERT_REQUIRED
         super(EventClient, self).__init__(url, ssl_options=ssl_options)
         self.filters = filters
         self.on_event = on_event
index 0cfdfa88ee168186b11958d92742098cf7dba6c6..e35e98aa59dedba5848d2a6cc1013fd322c15f09 100644 (file)
@@ -34,11 +34,19 @@ type Cgroup struct {
        cid    string
 }
 
-func CopyPipeToChan(in io.Reader, out chan string, done chan<- bool) {
+func CopyPipeToChan(in io.ReadCloser, out chan string, done chan<- bool) {
+       defer in.Close()
+
+       // TODO(twp): handle long input records gracefully, if possible
+       // without killing the child task (#4889)
+       //
        s := bufio.NewScanner(in)
        for s.Scan() {
                out <- s.Text()
        }
+       if s.Err() != nil {
+               out <- fmt.Sprintf("crunchstat: line buffering error: %s", s.Err())
+       }
        done <- true
 }
 
@@ -49,11 +57,12 @@ func CopyChanToPipe(in <-chan string, out io.Writer) {
 }
 
 var logChan chan string
+
 func LogPrintf(format string, args ...interface{}) {
        if logChan == nil {
                return
        }
-       logChan <- fmt.Sprintf("crunchstat: " + format, args...)
+       logChan <- fmt.Sprintf("crunchstat: "+format, args...)
 }
 
 func ReadAllOrWarn(in *os.File) ([]byte, error) {
index 48988a136743d63a352a0eda0a38895a9e8a797c..e3c3a597eacb640557e0e9fdd789a017ab35a8c8 100644 (file)
@@ -1,6 +1,8 @@
 package main
 
 import (
+       "bufio"
+       "io"
        "os"
        "regexp"
        "testing"
@@ -48,3 +50,30 @@ func TestReadAllOrWarnSuccess(t *testing.T) {
                t.Fatalf("Expected channel to close, got %s", msg)
        }
 }
+
+// Test that if CopyPipeToChan reads a line longer than
+// bufio.MaxScanTokenSize, it emits an error to the output channel.
+func TestCopyPipeToChanLongLines(t *testing.T) {
+       logChan := make(chan string)
+       control := make(chan bool)
+
+       pipeIn, pipeOut := io.Pipe()
+       go CopyPipeToChan(pipeIn, logChan, control)
+
+       go func() {
+               long_line := make([]byte, bufio.MaxScanTokenSize+1)
+               for i := range long_line {
+                       long_line[i] = byte('x')
+               }
+               pipeOut.Write(long_line)
+       }()
+
+       // Expect error message from logChan.
+
+       errmsg := <-logChan
+       if matched, err := regexp.MatchString("^crunchstat: line buffering error:.*token too long", errmsg); err != nil || !matched {
+               t.Fatalf("expected CopyPipeToChan error, got %s", errmsg)
+       }
+
+       <-control
+}