foreman-tasks 0.11.3 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb +7 -1
- data/app/controllers/foreman_tasks/tasks_controller.rb +1 -1
- data/app/helpers/foreman_tasks/tasks_helper.rb +2 -1
- data/app/models/foreman_tasks/task.rb +5 -0
- data/app/models/foreman_tasks/task/dynflow_task.rb +5 -0
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +1 -1
- data/app/views/foreman_tasks/task_groups/_common.html.erb +1 -1
- data/app/views/foreman_tasks/task_groups/recurring_logic_task_groups/_recurring_logic_task_group.html.erb +1 -1
- data/app/views/foreman_tasks/tasks/_details.html.erb +2 -1
- data/app/views/foreman_tasks/tasks/dashboard/_latest_tasks_in_error_warning.html.erb +1 -1
- data/app/views/foreman_tasks/tasks/dashboard/_tasks_status.html.erb +1 -1
- data/app/views/foreman_tasks/tasks/index.html.erb +2 -2
- data/db/migrate/20171026082635_add_task_action.foreman_tasks.rb +9 -0
- data/db/migrate/20180216092715_use_uuid.rb +44 -0
- data/lib/foreman_tasks/engine.rb +17 -2
- data/lib/foreman_tasks/tasks/generate_task_actions.rake +41 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +1 -1
- data/test/helpers/foreman_tasks/tasks_helper_test.rb +2 -0
- data/test/support/dummy_proxy_action.rb +6 -3
- data/test/tasks/generate_task_actions_test.rb +43 -0
- data/test/unit/actions/proxy_action_test.rb +2 -2
- data/test/unit/task_test.rb +3 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7c6574c1c5525bc889cdc026a5604229f0807b9
|
4
|
+
data.tar.gz: 4c79cb7a232ea3115f09c06e619667b7a203d821
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a4b956c2dd74d1cd3c20499636bcaf794accdd6442a21565bc2912c8c112827f5c1fdc709334393631e4e1d1d8460e090c6a9ea9a6904c072657a1743d21de0
|
7
|
+
data.tar.gz: 1b31d911db9af5260d56754779c068f53d66a9936e90a73b2b5889cdd2321d6aefdde41bfc6a3e68152d908312e2101c7e1fe971fd4851969bb4d51b11e05e08
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
module ForemanTasks
|
2
2
|
module Concerns
|
3
3
|
module HostsControllerExtension
|
4
|
-
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
alias_method_chain :facts, :dynflow
|
8
|
+
end
|
9
|
+
|
10
|
+
def facts_with_dynflow
|
5
11
|
task = ForemanTasks.async_task(::Actions::Foreman::Host::ImportFacts,
|
6
12
|
detect_host_type,
|
7
13
|
params[:name],
|
@@ -17,7 +17,7 @@ module ForemanTasks
|
|
17
17
|
render :index
|
18
18
|
end
|
19
19
|
format.csv do
|
20
|
-
csv_response(@tasks, [:
|
20
|
+
csv_response(@tasks, [:action_label, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :username], ['Action', 'State', 'Result', 'Started At', 'Ended At', 'User'])
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -36,6 +36,7 @@ module ForemanTasks
|
|
36
36
|
end
|
37
37
|
|
38
38
|
scoped_search :on => :id, :complete_value => false
|
39
|
+
scoped_search :on => :action, :complete_value => false
|
39
40
|
scoped_search :on => :label, :complete_value => true
|
40
41
|
scoped_search :on => :state, :complete_value => true
|
41
42
|
scoped_search :on => :result, :complete_value => true
|
@@ -202,6 +203,10 @@ module ForemanTasks
|
|
202
203
|
result.symbolize_keys
|
203
204
|
end
|
204
205
|
|
206
|
+
def action
|
207
|
+
super || to_label
|
208
|
+
end
|
209
|
+
|
205
210
|
def to_label
|
206
211
|
parts = []
|
207
212
|
parts << get_humanized(:name)
|
@@ -3,6 +3,7 @@ module ForemanTasks
|
|
3
3
|
include Algebrick::TypeCheck
|
4
4
|
|
5
5
|
scope :for_action, ->(action_class) { where(label: action_class.name) }
|
6
|
+
after_validation :set_action_field
|
6
7
|
|
7
8
|
def update_from_dynflow(data)
|
8
9
|
utc_zone = ActiveSupport::TimeZone.new('UTC')
|
@@ -152,6 +153,10 @@ module ForemanTasks
|
|
152
153
|
|
153
154
|
private
|
154
155
|
|
156
|
+
def set_action_field
|
157
|
+
self.action = to_label
|
158
|
+
end
|
159
|
+
|
155
160
|
def map_result(data)
|
156
161
|
if state_result_transitioned?(%w[planned pending], %w[stopped error], data) ||
|
157
162
|
(data[:result] == :error && cancelled?)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% title _("Recurring logics") %>
|
2
2
|
<% title_actions SETTINGS[:version].short <= '1.13' ? help_path : help_button %>
|
3
3
|
|
4
|
-
<table class="
|
4
|
+
<table class="<%= table_css_classes('table-condensed table-fixed') %>">
|
5
5
|
<thead>
|
6
6
|
<th><%= N_("Cron line") %></th>
|
7
7
|
<th><%= N_("Task count") %></th>
|
@@ -89,7 +89,8 @@
|
|
89
89
|
<div class="col-md-6">
|
90
90
|
<div>
|
91
91
|
<span class="param-name list-group-item-heading"><%= _("Name") %>:</span>
|
92
|
-
|
92
|
+
<% task_label = format_task_input(@task) %>
|
93
|
+
<span class="param-value" data-original-title="<%= task_label %>" rel="twipsy"> <%= truncate(task_label, :length => 50) %></span>
|
93
94
|
</div>
|
94
95
|
<div>
|
95
96
|
<span class="param-name list-group-item-heading"><%= _("Result") %>:</span>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<h4><%= link_to _("Latest Warning/Error Tasks"), foreman_tasks_tasks_path(:order=>'started_at DESC') %></h4>
|
2
|
-
<table class="
|
2
|
+
<table class="<%= table_css_classes('table-fixed') %>">
|
3
3
|
<tr>
|
4
4
|
<th class="col-md-5"><%= _("Name") %></th>
|
5
5
|
<th class="col-md-2"><%= _("State") %></th>
|
@@ -27,8 +27,8 @@ $(document).on('click', ".table-two-pane td.two-pane-link", function(e) {
|
|
27
27
|
<% for task in @tasks %>
|
28
28
|
<tr>
|
29
29
|
<td class="task-id two-pane-link ellipsis">
|
30
|
-
<%= link_to_if_authorized(task
|
31
|
-
|
30
|
+
<%= link_to_if_authorized(format_task_input(task),
|
31
|
+
hash_for_foreman_tasks_task_path(:id => task)) %>
|
32
32
|
</td>
|
33
33
|
<td class="ellipsis"><%= task.state %></td>
|
34
34
|
<td class="ellipsis"><%= task.result %></td>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class UseUuid < ActiveRecord::Migration[5.0]
|
2
|
+
# PostgreSQL has a special column type for storing UUIDs.
|
3
|
+
# Using this type instead of generic string should lead to having
|
4
|
+
# smaller DB and possibly better overall performance.
|
5
|
+
def up
|
6
|
+
if on_postgresql?
|
7
|
+
change_table :foreman_tasks_tasks do |t|
|
8
|
+
t.change :id, :uuid, :using => 'id::uuid'
|
9
|
+
t.change :parent_task_id, :uuid, :using => 'parent_task_id::uuid'
|
10
|
+
end
|
11
|
+
|
12
|
+
change_table :foreman_tasks_task_group_members do |t|
|
13
|
+
t.change :task_id, :uuid, :using => 'task_id::uuid'
|
14
|
+
end
|
15
|
+
|
16
|
+
change_table :foreman_tasks_locks do |t|
|
17
|
+
t.change :task_id, :uuid, :using => 'task_id::uuid'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def down
|
23
|
+
if on_postgresql?
|
24
|
+
change_table :foreman_tasks_tasks do |t|
|
25
|
+
t.change :id, :string
|
26
|
+
t.change :parent_task_id, :string
|
27
|
+
end
|
28
|
+
|
29
|
+
change_table :foreman_tasks_task_group_members do |t|
|
30
|
+
t.change :task_id, :string
|
31
|
+
end
|
32
|
+
|
33
|
+
change_table :foreman_tasks_locks do |t|
|
34
|
+
t.change :task_id, :string
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def on_postgresql?
|
42
|
+
ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
43
|
+
end
|
44
|
+
end
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -133,7 +133,7 @@ module ForemanTasks
|
|
133
133
|
# to enable async Foreman operations using Dynflow
|
134
134
|
if ENV['FOREMAN_TASKS_MONKEYS'] == 'true'
|
135
135
|
config.to_prepare do
|
136
|
-
::Api::V2::HostsController.send :
|
136
|
+
::Api::V2::HostsController.send :include, ForemanTasks::Concerns::HostsControllerExtension
|
137
137
|
::Host::Base.send :include, ForemanTasks::Concerns::HostActionSubject
|
138
138
|
end
|
139
139
|
end
|
@@ -144,8 +144,23 @@ module ForemanTasks
|
|
144
144
|
Authorizer.send(:prepend, AuthorizerExt)
|
145
145
|
end
|
146
146
|
|
147
|
+
config.after_initialize do
|
148
|
+
ForemanTasks.dynflow.eager_load_actions!
|
149
|
+
ForemanTasks.dynflow.config.increase_db_pool_size
|
150
|
+
|
151
|
+
unless ForemanTasks.dynflow.config.lazy_initialization
|
152
|
+
if defined?(PhusionPassenger)
|
153
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
154
|
+
ForemanTasks.dynflow.initialize! if forked
|
155
|
+
end
|
156
|
+
else
|
157
|
+
ForemanTasks.dynflow.initialize!
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
147
162
|
rake_tasks do
|
148
|
-
%w[dynflow.rake test.rake export_tasks.rake cleanup.rake].each do |rake_file|
|
163
|
+
%w[dynflow.rake test.rake export_tasks.rake cleanup.rake generate_task_actions.rake].each do |rake_file|
|
149
164
|
full_path = File.expand_path("../tasks/#{rake_file}", __FILE__)
|
150
165
|
load full_path if File.exist?(full_path)
|
151
166
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# generate_task_actions.rake is a data migration task to properly fill the missing
|
3
|
+
# values into the foreman_tasks_tasks table.
|
4
|
+
#
|
5
|
+
# Run "foreman-rake foreman_tasks:generate_task_actions" to generate missing values.
|
6
|
+
|
7
|
+
namespace :foreman_tasks do
|
8
|
+
desc 'Generate missing values for action column in foreman_tasks_tasks table.'
|
9
|
+
|
10
|
+
BATCH_SIZE = 100
|
11
|
+
|
12
|
+
task :generate_task_actions => :environment do
|
13
|
+
class ProgressReporter
|
14
|
+
def initialize(count, message = nil)
|
15
|
+
@count = count
|
16
|
+
@processed = 0
|
17
|
+
puts message % { :count => count } unless message.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def progress(count)
|
21
|
+
@processed += count
|
22
|
+
end
|
23
|
+
|
24
|
+
def report
|
25
|
+
puts _('Processed %{processed}/%{count} tasks') % { :processed => @processed, :count => @count }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
scope = ::ForemanTasks::Task.where(:action => nil).order(:started_at => :desc)
|
30
|
+
count = scope.count
|
31
|
+
reporter = ProgressReporter.new count, _('Generating action for %{count} tasks.')
|
32
|
+
scope.find_in_batches(:batch_size => BATCH_SIZE) do |group|
|
33
|
+
group.each do |task|
|
34
|
+
task.action = task.to_label
|
35
|
+
task.save!
|
36
|
+
end
|
37
|
+
reporter.progress group.size
|
38
|
+
reporter.report
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -41,7 +41,7 @@ module ForemanTasks
|
|
41
41
|
task.reload
|
42
42
|
task.state.must_equal 'stopped'
|
43
43
|
task.result.must_equal 'success'
|
44
|
-
task.main_action.output['proxy_task_id'].must_equal
|
44
|
+
task.main_action.output['proxy_task_id'].must_equal Support::DummyProxyAction.proxy.uuid
|
45
45
|
task.main_action.output['proxy_output'].must_equal('result' => 'success')
|
46
46
|
end
|
47
47
|
end
|
@@ -8,6 +8,7 @@ module ForemanTasks
|
|
8
8
|
humanized = { :humanized_name => 'Create', :humanized_input => [[:user, { :text => "user 'Anonymous Admin'", :link => nil }]] }
|
9
9
|
@task.instance_variable_set('@humanized_cache', humanized)
|
10
10
|
@task.stubs(:input).returns('user' => { 'id' => 1, 'name' => 'Anonymous Admin' }, 'locale' => 'en')
|
11
|
+
@task.stubs(:action).returns(@task.to_label)
|
11
12
|
end
|
12
13
|
|
13
14
|
it 'formats the task input properly' do
|
@@ -31,6 +32,7 @@ module ForemanTasks
|
|
31
32
|
'cp_id' => '1412251033866',
|
32
33
|
'locale' => 'en' }
|
33
34
|
@task.stubs(:input).returns(input)
|
35
|
+
@task.stubs(:action).returns(@task.to_label)
|
34
36
|
end
|
35
37
|
|
36
38
|
it 'formats the task input properly' do
|
@@ -1,17 +1,20 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module Support
|
2
4
|
class DummyProxyAction < Actions::ProxyAction
|
3
5
|
class DummyProxy
|
4
|
-
attr_reader :log, :task_triggered
|
6
|
+
attr_reader :log, :task_triggered, :uuid
|
5
7
|
|
6
8
|
def initialize
|
7
9
|
@log = Hash.new { |h, k| h[k] = [] }
|
8
10
|
@task_triggered = Concurrent.future
|
11
|
+
@uuid = SecureRandom.uuid
|
9
12
|
end
|
10
13
|
|
11
14
|
def trigger_task(*args)
|
12
15
|
@log[:trigger_task] << args
|
13
16
|
@task_triggered.success(true)
|
14
|
-
{ 'task_id' =>
|
17
|
+
{ 'task_id' => @uuid }
|
15
18
|
end
|
16
19
|
|
17
20
|
def cancel_task(*args)
|
@@ -36,7 +39,7 @@ module Support
|
|
36
39
|
def task
|
37
40
|
super
|
38
41
|
rescue ActiveRecord::RecordNotFound
|
39
|
-
ForemanTasks::Task::DynflowTask.new.tap { |task| task.id =
|
42
|
+
ForemanTasks::Task::DynflowTask.new.tap { |task| task.id = proxy.uuid }
|
40
43
|
end
|
41
44
|
|
42
45
|
class << self
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'foreman_tasks_test_helper'
|
3
|
+
|
4
|
+
class GenerateTaskActionsTest < ActiveSupport::TestCase
|
5
|
+
TASK_NAME = 'foreman_tasks:generate_task_actions'.freeze
|
6
|
+
|
7
|
+
setup do
|
8
|
+
Rake.application.rake_require 'foreman_tasks/tasks/generate_task_actions'
|
9
|
+
|
10
|
+
Rake::Task.define_task(:environment)
|
11
|
+
Rake::Task[TASK_NAME].reenable
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:tasks) do
|
15
|
+
(1..5).map { FactoryBot.build(:dynflow_task) }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'fixes the tasks' do
|
19
|
+
label = 'a label'
|
20
|
+
tasks
|
21
|
+
ForemanTasks::Task.update_all(:action => nil)
|
22
|
+
ForemanTasks::Task.any_instance.stubs(:to_label).returns(label)
|
23
|
+
|
24
|
+
stdout, _stderr = capture_io do
|
25
|
+
Rake.application.invoke_task TASK_NAME
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_match(%r{Generating action for #{tasks.count} tasks}, stdout)
|
29
|
+
ForemanTasks::Task.where(:action => label).count.must_equal tasks.count
|
30
|
+
assert_match(%r{Processed #{tasks.count}/#{tasks.count} tasks}, stdout)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'fixes only tasks with missing action' do
|
34
|
+
tasks
|
35
|
+
ForemanTasks::Task.any_instance.expects(:save!).never
|
36
|
+
|
37
|
+
stdout, _stderr = capture_io do
|
38
|
+
Rake.application.invoke_task TASK_NAME
|
39
|
+
end
|
40
|
+
|
41
|
+
assert_match(%r{Generating action for 0 tasks}, stdout)
|
42
|
+
end
|
43
|
+
end
|
@@ -29,7 +29,7 @@ module ForemanTasks
|
|
29
29
|
{ 'retry_interval' => 15, 'retry_count' => 4, 'timeout' => 60 },
|
30
30
|
'proxy_url' => 'proxy.example.com',
|
31
31
|
'proxy_action_name' => 'Proxy::DummyAction',
|
32
|
-
'callback' => { 'task_id' =>
|
32
|
+
'callback' => { 'task_id' => Support::DummyProxyAction.proxy.uuid, 'step_id' => @action.run_step_id } }]
|
33
33
|
proxy_call.must_equal(expected_call)
|
34
34
|
end
|
35
35
|
end
|
@@ -52,7 +52,7 @@ module ForemanTasks
|
|
52
52
|
describe 'cancel' do
|
53
53
|
it 'sends the cancel event to the proxy when the cancel event is sent for the first time' do
|
54
54
|
action = run_action(@action, ::Dynflow::Action::Cancellable::Cancel)
|
55
|
-
Support::DummyProxyAction.proxy.log[:cancel_task].first.must_equal [
|
55
|
+
Support::DummyProxyAction.proxy.log[:cancel_task].first.must_equal [Support::DummyProxyAction.proxy.uuid]
|
56
56
|
action.state.must_equal :suspended
|
57
57
|
end
|
58
58
|
|
data/test/unit/task_test.rb
CHANGED
@@ -58,9 +58,11 @@ class TasksTest < ActiveSupport::TestCase
|
|
58
58
|
|
59
59
|
describe 'task without valid execution plan' do
|
60
60
|
let(:task) do
|
61
|
-
FactoryBot.create(:dynflow_task).tap do |task|
|
61
|
+
task = FactoryBot.create(:dynflow_task).tap do |task|
|
62
62
|
task.external_id = 'missing-task'
|
63
|
+
task.save
|
63
64
|
end
|
65
|
+
ForemanTasks::Task.find(task.id)
|
64
66
|
end
|
65
67
|
|
66
68
|
it 'handles the error while loading the task and does not propagate errors unless necessary' do
|
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: 0.
|
4
|
+
version: 0.12.0
|
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: 2018-
|
11
|
+
date: 2018-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: foreman-tasks-core
|
@@ -200,6 +200,8 @@ files:
|
|
200
200
|
- db/migrate/20160920151810_add_more_lock_indexes.rb
|
201
201
|
- db/migrate/20160924213030_change_tasks_widget_names.rb
|
202
202
|
- db/migrate/20161003091412_add_missing_indexes.rb
|
203
|
+
- db/migrate/20171026082635_add_task_action.foreman_tasks.rb
|
204
|
+
- db/migrate/20180216092715_use_uuid.rb
|
203
205
|
- db/seeds.d/20-foreman_tasks_permissions.rb
|
204
206
|
- db/seeds.d/60-dynflow_proxy_feature.rb
|
205
207
|
- db/seeds.d/61-foreman_tasks_bookmarks.rb
|
@@ -220,6 +222,7 @@ files:
|
|
220
222
|
- lib/foreman_tasks/task_error.rb
|
221
223
|
- lib/foreman_tasks/tasks/cleanup.rake
|
222
224
|
- lib/foreman_tasks/tasks/export_tasks.rake
|
225
|
+
- lib/foreman_tasks/tasks/generate_task_actions.rake
|
223
226
|
- lib/foreman_tasks/test_extensions.rb
|
224
227
|
- lib/foreman_tasks/test_helpers.rb
|
225
228
|
- lib/foreman_tasks/triggers.rb
|
@@ -243,6 +246,7 @@ files:
|
|
243
246
|
- test/support/dummy_dynflow_action.rb
|
244
247
|
- test/support/dummy_proxy_action.rb
|
245
248
|
- test/support/dummy_task_group.rb
|
249
|
+
- test/tasks/generate_task_actions_test.rb
|
246
250
|
- test/unit/actions/action_with_sub_plans_test.rb
|
247
251
|
- test/unit/actions/proxy_action_test.rb
|
248
252
|
- test/unit/cleaner_test.rb
|
@@ -291,6 +295,7 @@ test_files:
|
|
291
295
|
- test/support/dummy_dynflow_action.rb
|
292
296
|
- test/support/dummy_proxy_action.rb
|
293
297
|
- test/support/dummy_task_group.rb
|
298
|
+
- test/tasks/generate_task_actions_test.rb
|
294
299
|
- test/unit/actions/action_with_sub_plans_test.rb
|
295
300
|
- test/unit/actions/proxy_action_test.rb
|
296
301
|
- test/unit/cleaner_test.rb
|