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?)
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
end
def child_summary
- get(:tasks_summary)
+ if children.any?
+ super
+ else
+ get(:tasks_summary)
+ end
end
def can_cancel?
class PipelineInstanceWorkUnit < ProxyWorkUnit
def children
+ return self.my_children if self.my_children
+
items = []
jobs = {}
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
attr_accessor :lbl
attr_accessor :proxied
+ attr_accessor :my_children
attr_accessor :unreadable_children
def initialize proxied, label
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
# 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
<%# column offset 8 %>
<div class="col-md-3">
<span class="task-summary-status">
- <% if current_obj.child_summary[:done] %>
- <%= current_obj.child_summary[:done] %> <%= "child".pluralize(current_obj.child_summary[:done]) %> done,
- <% end %>
- <% if current_obj.child_summary[:failed] %>
- <%= current_obj.child_summary[:failed] %> failed,
- <% end %>
- <% if current_obj.child_summary[:running] %>
- <%= current_obj.child_summary[:running] %> running,
- <% end %>
- <% if current_obj.child_summary[:todo] %>
- <%= current_obj.child_summary[:todo] %> pending
+ <% if current_obj.child_summary_str %>
+ <%= current_obj.child_summary_str %>
<% end %>
</span>
</div>
<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" >
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
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],
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