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 +4 -4
- data/app/controllers/foreman_tasks/tasks_controller.rb +18 -18
- data/app/lib/actions/trigger_proxy_batch.rb +2 -1
- data/app/models/foreman_tasks/remote_task.rb +5 -4
- data/lib/foreman_tasks/tasks/export_tasks.rake +26 -18
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/unit/remote_task_test.rb +26 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 882587333f9ebd555b6bd0ca6adf6c9e75789fce2e84cbbc2e3af0943cdf0051
|
4
|
+
data.tar.gz: 1db069d66971fed8af95856a2d582b1320c02c48fddec68f9f9a1061abc6965c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
58
|
+
redirect_back(:fallback_location => foreman_tasks_task_path(@dynflow_task))
|
60
59
|
end
|
61
60
|
|
62
61
|
def resume
|
63
|
-
|
64
|
-
|
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
|
-
|
74
|
-
|
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
|
-
|
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
|
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
|
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).
|
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 =
|
35
|
-
|
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,
|
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
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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,
|
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
|
-
|
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
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
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
|
-
|
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 #{
|
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,
|
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,
|
340
|
+
html_export(export_filename, id_scope, task_scope)
|
333
341
|
when 'csv'
|
334
|
-
csv_export(export_filename,
|
342
|
+
csv_export(export_filename, id_scope, task_scope)
|
335
343
|
else
|
336
344
|
raise "Unkonwn export format '#{format}'"
|
337
345
|
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.
|
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:
|
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.
|
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
|