8876: For jobs also, compute progress from it's children if present; otherwise, use...
authorradhika <radhika@curoverse.com>
Tue, 31 May 2016 00:41:32 +0000 (20:41 -0400)
committerradhika <radhika@curoverse.com>
Tue, 31 May 2016 00:41:32 +0000 (20:41 -0400)
apps/workbench/app/models/job_work_unit.rb
apps/workbench/app/models/pipeline_instance_work_unit.rb
apps/workbench/app/models/proxy_work_unit.rb
apps/workbench/app/models/work_unit.rb
apps/workbench/app/views/work_unit/_show_child.html.erb
apps/workbench/app/views/work_unit/_show_component.html.erb
apps/workbench/test/integration/jobs_test.rb
apps/workbench/test/unit/work_unit_test.rb
services/api/test/fixtures/links.yml

index 8fc328585712f8c9a51fd3628f9c2446ae75afea..256003795adcd9c9d1e1775593af853bfb67dd82 100644 (file)
@@ -1,9 +1,9 @@
 class JobWorkUnit < ProxyWorkUnit
   def children
-    uuid = get(:uuid)
-    items = []
+    return self.my_children if self.my_children
 
     # Jobs components
+    items = []
     components = get(:components)
     uuids = components.andand.collect {|_, v| v}
     return items if (!uuids or uuids.empty?)
@@ -19,26 +19,8 @@ class JobWorkUnit < ProxyWorkUnit
         items << obj.work_unit(components.key(obj.uuid))
       end
     end
-    items
-  end
-
-  def progress
-    state = get(:state)
-    if state == 'Complete'
-      return 1.0
-    end
 
-    tasks_summary = get(:tasks_summary)
-    failed = tasks_summary[:failed] || 0 rescue 0
-    done = tasks_summary[:done] || 0 rescue 0
-    running = tasks_summary[:running] || 0 rescue 0
-    todo = tasks_summary[:todo] || 0 rescue 0
-    if done + running + failed + todo > 0
-      total_tasks = done + running + failed + todo
-      (done+failed).to_f / total_tasks
-    else
-      0.0
-    end
+    self.my_children = items
   end
 
   def docker_image
@@ -62,7 +44,11 @@ class JobWorkUnit < ProxyWorkUnit
   end
 
   def child_summary
-    get(:tasks_summary)
+    if children.any?
+      super
+    else
+      get(:tasks_summary)
+    end
   end
 
   def can_cancel?
index 578e193c6e08315cdec182dc00703435b2838aeb..8285424a2982c0f0630f01abc509619e6b556918 100644 (file)
@@ -1,5 +1,7 @@
 class PipelineInstanceWorkUnit < ProxyWorkUnit
   def children
+    return self.my_children if self.my_children
+
     items = []
 
     jobs = {}
@@ -27,34 +29,7 @@ class PipelineInstanceWorkUnit < ProxyWorkUnit
       end
     end
 
-    items
-  end
-
-  def progress
-    state = get(:state)
-    if state == 'Complete'
-      return 1.0
-    end
-
-    done = 0
-    failed = 0
-    todo = 0
-    children.each do |c|
-      if c.success?.nil?
-        todo = todo+1
-      elsif c.success?
-        done = done+1
-      else
-        failed = failed+1
-      end
-    end
-
-    if done + failed + todo > 0
-      total = done + failed + todo
-      (done+failed).to_f / total
-    else
-      0.0
-    end
+    self.my_children = items
   end
 
   def uri
index 97983618064591626be7bc22f2d00260a700f99d..b8680a6b502e1b6d04724a5183da57b62abcf553 100644 (file)
@@ -3,6 +3,7 @@ class ProxyWorkUnit < WorkUnit
 
   attr_accessor :lbl
   attr_accessor :proxied
+  attr_accessor :my_children
   attr_accessor :unreadable_children
 
   def initialize proxied, label
@@ -74,6 +75,76 @@ class ProxyWorkUnit < WorkUnit
     end
   end
 
+  def child_summary
+    done = 0
+    failed = 0
+    todo = 0
+    running = 0
+    children.each do |c|
+      case c.state_label
+      when 'Complete'
+        done = done+1
+      when 'Failed', 'Cancelled'
+        failed = failed+1
+      when 'Running'
+        running = running+1
+      else
+        todo = todo+1
+      end
+    end
+
+    summary = {}
+    summary[:done] = done
+    summary[:failed] = failed
+    summary[:todo] = todo
+    summary[:running] = running
+    summary
+  end
+
+  def child_summary_str
+    summary = child_summary
+    summary_txt = ''
+
+    if state_label == 'Running'
+      if summary[:done]
+        summary_txt += "#{summary[:done]} #{'child'.pluralize(summary[:done])} done,"
+      end
+      if summary[:failed]
+        summary_txt += "#{summary[:failed]} failed,"
+      end
+      if summary[:running]
+        summary_txt += "#{summary[:running]} running,"
+      end
+      if summary[:todo]
+        summary_txt += "#{summary[:todo]} pending"
+      end
+    end
+    summary_txt
+  end
+
+  def progress
+    state = get(:state)
+    if state == 'Complete'
+      return 1.0
+    elsif state == 'Failed' or state== 'Cancelled'
+      return 0.0
+    end
+
+    summary = child_summary
+    return 0.0 if summary.nil?
+
+    done = summary[:done] || 0
+    running = summary[:running] || 0
+    failed = summary[:failed] || 0
+    todo = summary[:todo] || 0
+    total = done + running + failed + todo
+    if total > 0
+      (done+failed).to_f / total
+    else
+      0.0
+    end
+  end
+
   def parameters
     get(:script_parameters)
   end
index 7439128ed7e00257e78c9bc4c79b33584024e8cd..fba9015d19f2c5c3a42dd6fa3f10b37addd10f37 100644 (file)
@@ -95,6 +95,10 @@ class WorkUnit
     # summary status of any children of this work unit
   end
 
+  def child_summary_str
+    # textual representation of child summary
+  end
+
   def can_cancel?
     # returns true if this work unit can be canceled
   end
index 0824871fb279cf3c1b350c3f9dec1d643fef090d..64881a1ff0a167dfe54f8c25b7fd9e952bcf1e70 100644 (file)
               <%# column offset 8 %>
               <div class="col-md-3">
                 <span class="task-summary-status">
-                  <% if current_obj.child_summary[:done] %>
-                    <%= current_obj.child_summary[:done] %>&nbsp;<%= "child".pluralize(current_obj.child_summary[:done]) %> done,
-                  <% end %>
-                  <% if current_obj.child_summary[:failed] %>
-                    <%= current_obj.child_summary[:failed] %>&nbsp;failed,
-                  <% end %>
-                  <% if current_obj.child_summary[:running] %>
-                    <%= current_obj.child_summary[:running] %>&nbsp;running,
-                  <% end %>
-                  <% if current_obj.child_summary[:todo] %>
-                    <%= current_obj.child_summary[:todo] %>&nbsp;pending
+                  <% if current_obj.child_summary_str %>
+                    <%= current_obj.child_summary_str %>
                   <% end %>
                 </span>
               </div>
index 23ac3d393d5025cce157566036488982fe0a1ad0..dbf1c11f8d1ac86a0d642614cd3620a3c24b24fc 100644 (file)
@@ -4,10 +4,18 @@
   <div class="row-fluid">
     <%# Need additional handling for main object display  %>
     <% if @object.uuid == wu.uuid %>
-      <div class="col-md-2 pull-right">
+    <div class="container-fluid">
+      <div class="pull-right">
         <div class="container-fluid">
-          <div class="row-fluid">
-            <%# column offset 0 %>
+          <div class="row-fulid pipeline-instance-spacing">
+            <% if wu.state_label == 'Running' and wu.child_summary_str %>
+              <div class="col-md-8">
+                <%= wu.child_summary_str %>
+              </div>
+            <% end %>
+            <div class="col-md-3">
+              <%= render partial: 'work_unit/progress', locals: {wu: wu} %>
+            </div>
             <% if wu.state_label.in? ["Queued", "Running"] and wu.can_cancel? and @object.editable? %>
                 <div class="col-md-1">
                   <%= form_tag "#{wu.uri}/cancel", remote: true, style: "display:inline; padding-left: 1em" do |f| %>
                   <% end %>
                 </div>
             <% end %>
-            <%# column offset 1 %>
-            <div class="pull-right col-md-5 pipeline-instance-spacing">
-              <%= render partial: 'work_unit/progress', locals: {wu: wu} %>
-            </div>
           </div>
         </div>
       </div>
+    </div>
     <% end %>
 
     <div class="col-md-10" >
index de04aa8c735494bf1853f56ef273f459ee836b26..1ad3296071e95dff37a78730367e2f99cabbd79e 100644 (file)
@@ -127,44 +127,59 @@ class JobsTest < ActionDispatch::IntegrationTest
     end
   end
 
-  test 'view job with components' do
-    job = api_fixture('jobs')['running_job_with_components']
-    component1 = api_fixture('jobs')['completed_job_in_publicly_accessible_project']
-    component2 = api_fixture('pipeline_instances')['running_pipeline_with_complete_job']
-    component2_child1 = api_fixture('jobs')['previous_job_run']
-    component2_child2 = api_fixture('jobs')['running']
-
-    visit page_with_token("active", "/jobs/#{job['uuid']}")
-    assert page.has_text? job['script_version']
-    assert page.has_no_text? 'script_parameters'
+  [
+    ['active', true],
+    ['job_reader', false],
+  ].each do |user, readable|
+    test "view job with components as #{user} user" do
+      job = api_fixture('jobs')['running_job_with_components']
+      component1 = api_fixture('jobs')['completed_job_in_publicly_accessible_project']
+      component2 = api_fixture('pipeline_instances')['running_pipeline_with_complete_job']
+      component2_child1 = api_fixture('jobs')['previous_job_run']
+      component2_child2 = api_fixture('jobs')['running']
+
+      visit page_with_token(user, "/jobs/#{job['uuid']}")
+      assert page.has_text? job['script_version']
+      assert page.has_no_text? 'script_parameters'
+
+      if readable
+        assert page.has_link? 'component1'
+        assert page.has_link? 'component2'
+      else
+        # children are not readable by user
+        assert page.has_no_link? 'component1'
+        assert page.has_no_link? 'component2'
+        return
+      end
 
-    click_link('component1')
-    within('#collapse1') do
-      assert(has_text? component1['uuid'])
-      assert(has_text? component1['script_version'])
-      assert(has_text? 'script_parameters')
-    end
-    click_link('component1')
-
-    click_link('component2')
-    within('#collapse2') do
-      assert(has_text? component2['uuid'])
-      assert(has_text? component2['script_version'])
-      assert(has_no_text? 'script_parameters')
-      assert(has_link? 'previous')
-      assert(has_link? 'running')
-
-      click_link('previous')
-      within('#collapse3') do
-        assert(has_text? component2_child1['uuid'])
-        assert(has_text? component2_child1['script_version'])
+      click_link('component1')
+      within('#collapse1') do
+        assert(has_text? component1['uuid'])
+        assert(has_text? component1['script_version'])
+        assert(has_text? 'script_parameters')
       end
-      click_link('previous')
+      click_link('component1')
+
+      click_link('component2')
+      within('#collapse2') do
+        assert(has_text? component2['uuid'])
+        assert(has_text? component2['script_version'])
+        assert(has_no_text? 'script_parameters')
+        assert(has_link? 'previous')
+        assert(has_link? 'running')
+
+        click_link('previous')
+        within('#collapse3') do
+          assert(has_text? component2_child1['uuid'])
+          assert(has_text? component2_child1['script_version'])
+        end
+        click_link('previous')
 
-      click_link('running')
-      within('#collapse4') do
-        assert(has_text? component2_child2['uuid'])
-        assert(has_text? component2_child2['script_version'])
+        click_link('running')
+        within('#collapse4') do
+          assert(has_text? component2_child2['uuid'])
+          assert(has_text? component2_child2['script_version'])
+        end
       end
     end
   end
index 63f6a5aacdf17ca2395c3ebe5b7a44bc5f0a4c92..a1de629609843a964486f3608d159ae1c5e44a25 100644 (file)
@@ -2,7 +2,7 @@ require 'test_helper'
 
 class WorkUnitTest < ActiveSupport::TestCase
   [
-    [Job, 'running_job_with_components', "jwu", 2, "Running", nil, 0.2],
+    [Job, 'running_job_with_components', "jwu", 2, "Running", nil, 0.5],
     [PipelineInstance, 'pipeline_in_running_state', nil, 1, "Running", nil, 0.0],
     [PipelineInstance, 'has_component_with_completed_jobs', nil, 3, "Complete", true, 1.0],
     [PipelineInstance, 'pipeline_with_tagged_collection_input', "pwu", 1, "Ready", nil, 0.0],
index 7ed7f6bcf35636ad4ccc572b2da2e3044f6a277a..96e82ccbc93ab4dd930cbacf9813ed36a42b03ca 100644 (file)
@@ -702,6 +702,21 @@ job_reader_can_read_previous_job_run:
   tail_uuid: zzzzz-tpzed-905b42d1dd4a354
   head_uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
 
+job_reader_can_read_job_with_components:
+  # Permission link giving job_reader permission
+  # to read running_job_with_components
+  uuid: zzzzz-o0j2j-jobcomps4jobrdr
+  owner_uuid: zzzzz-tpzed-000000000000000
+  created_at: 2014-06-13 20:42:26 -0800
+  modified_by_client_uuid: zzzzz-tpzed-000000000000000
+  modified_by_user_uuid: zzzzz-tpzed-000000000000000
+  modified_at: 2014-06-13 20:42:26 -0800
+  updated_at: 2014-06-13 20:42:26 -0800
+  link_class: permission
+  name: can_read
+  tail_uuid: zzzzz-tpzed-905b42d1dd4a354
+  head_uuid: zzzzz-8i9sb-with2components
+
 job_reader_can_read_foo_repo:
   # Permission link giving job_reader permission
   # to read foo_repo