foreman-tasks 5.2.1 → 5.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: affb6b8dabd35bf7600c2c76aa6f129dab3d43cbddc24120d89bbe898355adf2
4
- data.tar.gz: 57e68fca3c4e837f5ccb5073c8c8459dbda2e98975c2211d4f583daa478ebbf0
3
+ metadata.gz: 882587333f9ebd555b6bd0ca6adf6c9e75789fce2e84cbbc2e3af0943cdf0051
4
+ data.tar.gz: 1db069d66971fed8af95856a2d582b1320c02c48fddec68f9f9a1061abc6965c
5
5
  SHA512:
6
- metadata.gz: 117021731b7da694348b5b29564a3662b35a6de175b056db4ede99707ccace227f5815ace3adb9caee3e094aeba2fd9a0b722ad71c67c9405b8d2a97f33c16d1
7
- data.tar.gz: 95a05ed5983f03aa8db0233d5f8c2dce7031eeae15f79ecb1fa936212920017da59d629a28908fde3469c3b7652c8ee4ae68f89b0aef4229152fad4f509283fc
6
+ metadata.gz: b204e43fe719216b44377fa0eb69654a404dfc7d53fbd5ed803efca3f5dd649d2dc901abd1b29b4048c1f99f7a37bd1b94c5c349ae9844e08ae95bd86a942b35
7
+ data.tar.gz: 90c69b77188a55d8d993a6e098945448dce1ff720697def8ea1914ba2c03fe2ed7efec30b4a7e33224afa9b32d3b9f1c8eb4fd37cdee37566321e69d67d78b1a
@@ -4,6 +4,8 @@ module ForemanTasks
4
4
  include Foreman::Controller::CsvResponder
5
5
  include ForemanTasks::FindTasksCommon
6
6
 
7
+ before_action :find_dynflow_task, only: [:unlock, :force_unlock, :cancel, :cancel_step, :resume]
8
+
7
9
  def show
8
10
  @task = resource_base.find(params[:id])
9
11
  render :layout => !request.xhr?
@@ -31,8 +33,7 @@ module ForemanTasks
31
33
  end
32
34
 
33
35
  def cancel_step
34
- task = find_dynflow_task
35
- result = ForemanTasks.dynflow.world.event(task.external_id, params[:step_id].to_i, ::Dynflow::Action::Cancellable::Cancel).wait
36
+ result = ForemanTasks.dynflow.world.event(@dynflow_task.external_id, params[:step_id].to_i, ::Dynflow::Action::Cancellable::Cancel).wait
36
37
  if result.rejected?
37
38
  render json: { error: result.reason }, status: :bad_request
38
39
  else
@@ -41,8 +42,7 @@ module ForemanTasks
41
42
  end
42
43
 
43
44
  def cancel
44
- task = find_dynflow_task
45
- if task.cancel
45
+ if @dynflow_task.cancel
46
46
  render json: { statusText: 'OK' }
47
47
  else
48
48
  render json: {}, status: :bad_request
@@ -50,19 +50,17 @@ module ForemanTasks
50
50
  end
51
51
 
52
52
  def abort
53
- task = find_dynflow_task
54
- if task.abort
53
+ if @dynflow_task.abort
55
54
  flash[:info] = _('Trying to abort the task')
56
55
  else
57
56
  flash[:warning] = _('The task cannot be aborted at the moment.')
58
57
  end
59
- redirect_back(:fallback_location => foreman_tasks_task_path(task))
58
+ redirect_back(:fallback_location => foreman_tasks_task_path(@dynflow_task))
60
59
  end
61
60
 
62
61
  def resume
63
- task = find_dynflow_task
64
- if task.resumable?
65
- ForemanTasks.dynflow.world.execute(task.execution_plan.id)
62
+ if @dynflow_task.resumable?
63
+ ForemanTasks.dynflow.world.execute(@dynflow_task.execution_plan.id)
66
64
  render json: { statusText: 'OK' }
67
65
  else
68
66
  render json: {}, status: :bad_request
@@ -70,10 +68,8 @@ module ForemanTasks
70
68
  end
71
69
 
72
70
  def unlock
73
- task = find_dynflow_task
74
- if task.paused?
75
- task.state = :stopped
76
- task.save!
71
+ if @dynflow_task.paused?
72
+ unlock_task(@dynflow_task)
77
73
  render json: { statusText: 'OK' }
78
74
  else
79
75
  render json: {}, status: :bad_request
@@ -81,9 +77,7 @@ module ForemanTasks
81
77
  end
82
78
 
83
79
  def force_unlock
84
- task = find_dynflow_task
85
- task.state = :stopped
86
- task.save!
80
+ unlock_task(@dynflow_task)
87
81
  render json: { statusText: 'OK' }
88
82
  end
89
83
 
@@ -98,6 +92,12 @@ module ForemanTasks
98
92
 
99
93
  private
100
94
 
95
+ def unlock_task(task)
96
+ task.state = :stopped
97
+ task.locks.destroy_all
98
+ task.save!
99
+ end
100
+
101
101
  def respond_with_tasks(scope)
102
102
  @tasks = filter(scope, paginate: false).with_duration
103
103
  csv_response(@tasks, [:id, :action, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :duration, :username], ['Id', 'Action', 'State', 'Result', 'Started At', 'Ended At', 'Duration', 'User'])
@@ -123,7 +123,7 @@ module ForemanTasks
123
123
  end
124
124
 
125
125
  def find_dynflow_task
126
- resource_scope.where(:type => 'ForemanTasks::Task::DynflowTask').find(params[:id])
126
+ @dynflow_task = resource_scope.where(:type => 'ForemanTasks::Task::DynflowTask').find(params[:id])
127
127
  end
128
128
 
129
129
  def filter(scope, paginate: true)
@@ -40,7 +40,8 @@ module Actions
40
40
  end
41
41
  output[:planned_count] += batch.size
42
42
  rescue => e
43
- action_logger.warn "Could not trigger task on the smart proxy: #{e.message}"
43
+ action_logger.warn "Could not trigger task on the smart proxy"
44
+ action_logger.warn e
44
45
  batch.each { |remote_task| remote_task.update_from_batch_trigger({}) }
45
46
  output[:failed_count] += batch.size
46
47
  end
@@ -18,7 +18,8 @@ module ForemanTasks
18
18
  response = begin
19
19
  proxy.launch_tasks('single', :action_class => proxy_action_name, :action_input => input)
20
20
  rescue RestClient::Exception => e
21
- logger.warn "Could not trigger task on the smart proxy: #{e.message}"
21
+ logger.warn "Could not trigger task on the smart proxy"
22
+ logger.warn e
22
23
  {}
23
24
  end
24
25
  update_from_batch_trigger(response)
@@ -26,13 +27,13 @@ module ForemanTasks
26
27
  end
27
28
 
28
29
  def self.batch_trigger(operation, remote_tasks)
29
- remote_tasks.group_by(&:proxy_url).values.map do |group|
30
+ remote_tasks.group_by(&:proxy_url).each_value do |group|
30
31
  input_hash = group.reduce({}) do |acc, remote_task|
31
32
  acc.merge(remote_task.execution_plan_id => { :action_input => remote_task.proxy_input,
32
33
  :action_class => remote_task.proxy_action_name })
33
34
  end
34
- results = remote_tasks.first.proxy.launch_tasks(operation, input_hash)
35
- remote_tasks.each { |remote_task| remote_task.update_from_batch_trigger results[remote_task.execution_plan_id] }
35
+ results = group.first.proxy.launch_tasks(operation, input_hash)
36
+ group.each { |remote_task| remote_task.update_from_batch_trigger results[remote_task.execution_plan_id] }
36
37
  end
37
38
  remote_tasks
38
39
  end
@@ -241,35 +241,42 @@ namespace :foreman_tasks do
241
241
  end
242
242
  end
243
243
 
244
- def csv_export(export_filename, tasks)
244
+ def csv_export(export_filename, id_scope, task_scope)
245
245
  CSV.open(export_filename, 'wb') do |csv|
246
246
  csv << %w[id state type label result parent_task_id started_at ended_at duration]
247
- tasks.find_each do |task|
248
- with_error_handling(task) do
249
- csv << [task.id, task.state, task.type, task.label, task.result,
250
- task.parent_task_id, task.started_at, task.ended_at, task.duration]
247
+ id_scope.pluck(:id).each_slice(1000).each do |ids|
248
+ task_scope.where(id: ids).each do |task|
249
+ with_error_handling(task) do
250
+ csv << [task.id, task.state, task.type, task.label, task.result,
251
+ task.parent_task_id, task.started_at, task.ended_at, task.duration]
252
+ end
251
253
  end
252
254
  end
253
255
  end
254
256
  end
255
257
 
256
- def html_export(workdir, tasks)
258
+ def html_export(workdir, id_scope, task_scope)
257
259
  PageHelper.copy_assets(workdir)
258
260
 
261
+ ids = id_scope.pluck(:id)
259
262
  renderer = TaskRender.new
260
- total = tasks.count(:all)
263
+ count = 0
264
+ total = ids.count
261
265
  index = File.open(File.join(workdir, 'index.html'), 'w')
262
266
 
263
267
  File.open(File.join(workdir, 'index.html'), 'w') do |index|
264
268
  PageHelper.pagify(index) do |io|
265
269
  PageHelper.generate_with_index(io) do |index|
266
- tasks.find_each.each_with_index do |task, count|
267
- content = with_error_handling(task) { renderer.render_task(task) }
268
- if content
269
- File.open(File.join(workdir, "#{task.id}.html"), 'w') { |file| PageHelper.pagify(file, content) }
270
- with_error_handling(task, _('task index entry')) { PageHelper.generate_index_entry(index, task) }
270
+ ids.each_slice(1000).each do |ids|
271
+ task_scope.where(id: ids).each do |task|
272
+ content = with_error_handling(task) { renderer.render_task(task) }
273
+ if content
274
+ File.open(File.join(workdir, "#{task.id}.html"), 'w') { |file| PageHelper.pagify(file, content) }
275
+ with_error_handling(task, _('task index entry')) { PageHelper.generate_index_entry(index, task) }
276
+ end
277
+ count += 1
278
+ puts "#{count}/#{total}"
271
279
  end
272
- puts "#{count + 1}/#{total}"
273
280
  end
274
281
  end
275
282
  end
@@ -317,21 +324,22 @@ namespace :foreman_tasks do
317
324
  format = ENV['TASK_FORMAT'] || 'html'
318
325
  export_filename = ENV['TASK_FILE'] || generate_filename(format)
319
326
 
320
- tasks = ForemanTasks::Task.search_for(filter).order(:started_at => :desc).with_duration.distinct
327
+ task_scope = ForemanTasks::Task.search_for(filter).with_duration.order(:started_at => :desc)
328
+ id_scope = task_scope.group(:id, :started_at)
321
329
 
322
330
  puts _("Exporting all tasks matching filter #{filter}")
323
- puts _("Gathering #{tasks.count(:all)} tasks.")
331
+ puts _("Gathering #{id_scope.count(:all).count} tasks.")
324
332
  case format
325
333
  when 'html'
326
334
  Dir.mktmpdir('task-export') do |tmp_dir|
327
- html_export(tmp_dir, tasks)
335
+ html_export(tmp_dir, id_scope, task_scope)
328
336
  system("tar", "czf", export_filename, tmp_dir)
329
337
  end
330
338
  when 'html-dir'
331
339
  FileUtils.mkdir_p(export_filename)
332
- html_export(export_filename, tasks)
340
+ html_export(export_filename, id_scope, task_scope)
333
341
  when 'csv'
334
- csv_export(export_filename, tasks)
342
+ csv_export(export_filename, id_scope, task_scope)
335
343
  else
336
344
  raise "Unkonwn export format '#{format}'"
337
345
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '5.2.1'.freeze
2
+ VERSION = '5.2.2'.freeze
3
3
  end
@@ -28,6 +28,32 @@ module ForemanTasks
28
28
  _(remote_task.remote_task_id).must_equal((remote_task.id + 5).to_s)
29
29
  end
30
30
  end
31
+
32
+ it 'honors the batches with multiple proxies' do
33
+ remote_task = remote_tasks.last
34
+ remote_task.proxy_url = 'something else'
35
+
36
+ results = remote_tasks.reduce({}) do |acc, cur|
37
+ acc.merge(cur.execution_plan_id.to_s => { 'task_id' => cur.id + 5, 'result' => 'success' })
38
+ end
39
+ other_results = { remote_task.execution_plan_id => results.delete(remote_task.execution_plan_id) }
40
+
41
+ fake_proxy = mock
42
+ fake_proxy.expects(:launch_tasks).returns(results)
43
+
44
+ another_fake_proxy = mock
45
+ another_fake_proxy.expects(:launch_tasks).returns(other_results)
46
+
47
+ remote_tasks.first.expects(:proxy).returns(fake_proxy)
48
+ remote_tasks.last.expects(:proxy).returns(another_fake_proxy)
49
+
50
+ RemoteTask.batch_trigger('a_operation', remote_tasks)
51
+ remote_tasks.each do |remote_task|
52
+ remote_task.reload
53
+ _(remote_task.state).must_equal 'triggered'
54
+ _(remote_task.remote_task_id).must_equal((remote_task.id + 5).to_s)
55
+ end
56
+ end
31
57
  end
32
58
  end
33
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.1
4
+ version: 5.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-26 00:00:00.000000000 Z
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dynflow
@@ -607,7 +607,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
607
607
  - !ruby/object:Gem::Version
608
608
  version: '0'
609
609
  requirements: []
610
- rubygems_version: 3.1.2
610
+ rubygems_version: 3.2.26
611
611
  signing_key:
612
612
  specification_version: 4
613
613
  summary: Foreman plugin for showing tasks information for resources and users