foreman-tasks 0.10.4 → 0.10.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +0 -2
- data/app/lib/actions/base.rb +2 -0
- data/app/lib/actions/entry_action.rb +2 -1
- data/app/lib/actions/middleware/rails_executor_wrap.rb +25 -0
- data/app/models/foreman_tasks/task.rb +14 -12
- data/app/models/foreman_tasks/task_group.rb +2 -2
- data/app/models/foreman_tasks/task_groups/recurring_logic_task_group.rb +1 -1
- data/app/models/foreman_tasks/triggering.rb +1 -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 +14 -14
- data/foreman-tasks.gemspec +2 -0
- data/lib/foreman_tasks.rb +21 -10
- data/lib/foreman_tasks/dynflow.rb +0 -1
- data/lib/foreman_tasks/dynflow/console_authorizer.rb +0 -1
- data/lib/foreman_tasks/engine.rb +2 -2
- data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +1 -1
- data/test/factories/recurring_logic_factory.rb +1 -1
- data/test/factories/task_factory.rb +1 -1
- data/test/factories/triggering_factory.rb +1 -1
- data/test/foreman_tasks_test_helper.rb +2 -2
- data/test/helpers/foreman_tasks/tasks_helper_test.rb +2 -2
- data/test/unit/actions/action_with_sub_plans_test.rb +1 -1
- data/test/unit/cleaner_test.rb +12 -12
- data/test/unit/dynflow_console_authorizer_test.rb +11 -11
- data/test/unit/proxy_selector_test.rb +4 -4
- data/test/unit/recurring_logic_test.rb +2 -2
- data/test/unit/task_test.rb +28 -23
- data/test/unit/triggering_test.rb +4 -4
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8c05ea538a9cdd681bcd80073a82d7fdd8aa15f
|
4
|
+
data.tar.gz: cdfc54af9ee6edfe6165e744fb5b4b5eea22209a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31dad9d8f904055a9a17b6a7d06e73d1b0e6ed9eaf3e6702845e3edaf6318ce80d2948b558759ca808b800965dcde2564491c6cae8e8325988cc2ed4acaf29f5
|
7
|
+
data.tar.gz: db3c8119caec600812d8353f30be0ed80d965ece6255f6191725804188e7459d9c5651fa758f16d6b1d3f62caf442872925f0da0e0bf05aff4b548f1757beeb8
|
data/.rubocop.yml
CHANGED
data/app/lib/actions/base.rb
CHANGED
@@ -28,7 +28,8 @@ module Actions
|
|
28
28
|
# The additional args can include more resources and/or a hash
|
29
29
|
# with more data describing the action that should appear in the
|
30
30
|
# action's input.
|
31
|
-
|
31
|
+
# TODO redo as a middleware
|
32
|
+
def action_subject(resource, *additional_args)
|
32
33
|
Type! resource, ForemanTasks::Concerns::ActionSubject
|
33
34
|
input.update serialize_args(resource, *resource.all_related_resources, *additional_args)
|
34
35
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Actions
|
2
|
+
module Middleware
|
3
|
+
# In development with Rails auto-reloading and using `sync_task` method,
|
4
|
+
# it could lead to dead-locking due to the Rails main thread locking the
|
5
|
+
# the class loader.
|
6
|
+
#
|
7
|
+
# This middleware marks the part of the code that can
|
8
|
+
# use the auto-loader so that Rails know they should avoid the locking there.
|
9
|
+
# See https://github.com/ruby-concurrency/concurrent-ruby/issues/585#issuecomment-256131537
|
10
|
+
# for more details.
|
11
|
+
class RailsExecutorWrap < Dynflow::Middleware
|
12
|
+
def run(*args)
|
13
|
+
Rails.application.executor.wrap do
|
14
|
+
pass(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def finalize
|
19
|
+
Rails.application.executor.wrap do
|
20
|
+
pass
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -17,10 +17,10 @@ module ForemanTasks
|
|
17
17
|
before_create :generate_id
|
18
18
|
|
19
19
|
belongs_to :parent_task, :class_name => 'ForemanTasks::Task'
|
20
|
-
has_many :sub_tasks, :class_name => 'ForemanTasks::Task', :foreign_key => :parent_task_id
|
21
|
-
has_many :locks
|
20
|
+
has_many :sub_tasks, :class_name => 'ForemanTasks::Task', :foreign_key => :parent_task_id, :dependent => :nullify
|
21
|
+
has_many :locks, :dependent => :destroy
|
22
22
|
|
23
|
-
has_many :task_group_members
|
23
|
+
has_many :task_group_members, :dependent => :destroy
|
24
24
|
has_many :task_groups, :through => :task_group_members
|
25
25
|
if Rails::VERSION::MAJOR < 4
|
26
26
|
has_many :recurring_logic_task_groups, :through => :task_group_members, :conditions => { :type => 'ForemanTasks::TaskGroups::RecurringLogicTaskGroup' }, :source => :task_group
|
@@ -134,26 +134,28 @@ module ForemanTasks
|
|
134
134
|
return { :conditions => '0 = 1' } if value == 'current_user' && User.current.nil?
|
135
135
|
|
136
136
|
key = 'owners.login' if key == 'user'
|
137
|
+
# using uniq suffix to avoid colisions when searching by two different owners via ScopedSearch
|
138
|
+
uniq_suffix = SecureRandom.hex(3)
|
137
139
|
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
138
140
|
joins = <<-SQL
|
139
|
-
INNER JOIN foreman_tasks_locks AS foreman_tasks_locks_owner
|
140
|
-
ON (foreman_tasks_locks_owner.task_id = foreman_tasks_tasks.id AND
|
141
|
-
foreman_tasks_locks_owner.resource_type = 'User' AND
|
142
|
-
foreman_tasks_locks_owner.name = '#{Lock::OWNER_LOCK_NAME}')
|
141
|
+
INNER JOIN foreman_tasks_locks AS foreman_tasks_locks_owner#{uniq_suffix}
|
142
|
+
ON (foreman_tasks_locks_owner#{uniq_suffix}.task_id = foreman_tasks_tasks.id AND
|
143
|
+
foreman_tasks_locks_owner#{uniq_suffix}.resource_type = 'User' AND
|
144
|
+
foreman_tasks_locks_owner#{uniq_suffix}.name = '#{Lock::OWNER_LOCK_NAME}')
|
143
145
|
SQL
|
144
146
|
if key !~ /\.id\Z/
|
145
147
|
joins << <<-SQL
|
146
|
-
INNER JOIN users
|
147
|
-
ON (users.id = foreman_tasks_locks_owner.resource_id)
|
148
|
+
INNER JOIN users as users#{uniq_suffix}
|
149
|
+
ON (users#{uniq_suffix}.id = foreman_tasks_locks_owner#{uniq_suffix}.resource_id)
|
148
150
|
SQL
|
149
151
|
end
|
150
152
|
condition = if key.blank?
|
151
|
-
sanitize_sql_for_conditions(["users.login #{operator} ? or users.firstname #{operator} ? ", value, value])
|
153
|
+
sanitize_sql_for_conditions(["users#{uniq_suffix}.login #{operator} ? or users#{uniq_suffix}.firstname #{operator} ? ", value, value])
|
152
154
|
elsif key =~ /\.id\Z/
|
153
155
|
value = User.current.id if value == 'current_user'
|
154
|
-
sanitize_sql_for_conditions(["foreman_tasks_locks_owner.resource_id #{operator} ?", value])
|
156
|
+
sanitize_sql_for_conditions(["foreman_tasks_locks_owner#{uniq_suffix}.resource_id #{operator} ?", value])
|
155
157
|
else
|
156
|
-
sanitize_sql_for_conditions(["users.#{key_name} #{operator} ?", value])
|
158
|
+
sanitize_sql_for_conditions(["users#{uniq_suffix}.#{key_name} #{operator} ?", value])
|
157
159
|
end
|
158
160
|
{ :conditions => condition, :joins => joins }
|
159
161
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ForemanTasks
|
2
2
|
class TaskGroup < ActiveRecord::Base
|
3
|
-
has_many :task_group_members
|
4
|
-
has_many :tasks, :through => :task_group_members
|
3
|
+
has_many :task_group_members, :dependent => :destroy
|
4
|
+
has_many :tasks, :through => :task_group_members, :dependent => :nullify
|
5
5
|
|
6
6
|
def resource_name
|
7
7
|
raise NotImplementedError
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ForemanTasks
|
2
2
|
module TaskGroups
|
3
3
|
class RecurringLogicTaskGroup < ::ForemanTasks::TaskGroup
|
4
|
-
has_one :recurring_logic, :foreign_key => :task_group_id
|
4
|
+
has_one :recurring_logic, :foreign_key => :task_group_id, :dependent => :nullify
|
5
5
|
|
6
6
|
alias resource recurring_logic
|
7
7
|
|
@@ -21,7 +21,7 @@ module ForemanTasks
|
|
21
21
|
TIME_REGEXP = /\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}\Z/
|
22
22
|
DAYS_REGEXP = /\A(\s*\d{1,2}\s*)(,\s*\d{1,2}\s*)*\Z/
|
23
23
|
|
24
|
-
has_one :recurring_logic, :foreign_key => :triggering_id
|
24
|
+
has_one :recurring_logic, :foreign_key => :triggering_id, :dependent => :nullify
|
25
25
|
|
26
26
|
validates :mode, :inclusion => { :in => ALLOWED_MODES,
|
27
27
|
:message => _('%{value} is not allowed triggering mode') }
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<td class="ellipsis"><%= link_to task.humanized[:action], defined?(main_app) ? main_app.foreman_tasks_task_path(task.id) : foreman_tasks_task_path(task.id) %></td>
|
12
12
|
<td><%= task.state %></td>
|
13
13
|
<td><%= task.result %></td>
|
14
|
-
<td><%= task.started_at ? (_(
|
14
|
+
<td><%= task.started_at ? (_(date_time_relative(task.started_at))) : _('N/A') %></td>
|
15
15
|
</tr>
|
16
16
|
<% end %>
|
17
17
|
</table>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<td><%= result.state %></td>
|
12
12
|
<td><%= result.result %></td>
|
13
13
|
<td><%= link_to result.count, main_app.foreman_tasks_tasks_path(:search => "state=#{result.state}&result=#{result.result}") %></td>
|
14
|
-
<td><%= result.started_at ? (_(
|
14
|
+
<td><%= result.started_at ? (_(date_time_relative(result.started_at))) : _('N/A') %></td>
|
15
15
|
</tr>
|
16
16
|
<% end %>
|
17
17
|
</table>
|
@@ -15,26 +15,26 @@ $(document).on('click', ".table-two-pane td.two-pane-link", function(e) {
|
|
15
15
|
});
|
16
16
|
|
17
17
|
</script>
|
18
|
-
<table class="
|
18
|
+
<table class="<%= table_css_classes('table-fixed table-two-pane') %>">
|
19
19
|
<tr>
|
20
|
-
<th><%= _("Action") %></th>
|
21
|
-
<th><%= _("State") %></th>
|
22
|
-
<th><%= _("Result") %></th>
|
23
|
-
<th><%= sort :started_at, :as => _("Started at") %></th>
|
24
|
-
<th><%= sort :ended_at, :as => _("Ended at") %></th>
|
25
|
-
<th><%= _("User") %></th>
|
20
|
+
<th class="col-md-4"><%= _("Action") %></th>
|
21
|
+
<th class="col-md-1"><%= _("State") %></th>
|
22
|
+
<th class="col-md-1"><%= _("Result") %></th>
|
23
|
+
<th class="col-md-2"><%= sort :started_at, :as => _("Started at") %></th>
|
24
|
+
<th class="col-md-2"><%= sort :ended_at, :as => _("Ended at") %></th>
|
25
|
+
<th class="col-md-2"><%= _("User") %></th>
|
26
26
|
</tr>
|
27
27
|
<% for task in @tasks %>
|
28
28
|
<tr>
|
29
|
-
<td class="task-id two-pane-link">
|
30
|
-
<%= link_to_if_authorized(
|
29
|
+
<td class="task-id two-pane-link ellipsis">
|
30
|
+
<%= link_to_if_authorized(format_task_input(task, true),
|
31
31
|
hash_for_foreman_tasks_task_path(:id => task)) %>
|
32
32
|
</td>
|
33
|
-
<td><%= task.state %></td>
|
34
|
-
<td><%= task.result %></td>
|
35
|
-
<td><%= task.started_at.try(:in_time_zone) %></td>
|
36
|
-
<td><%= task.ended_at.try(:in_time_zone) %></td>
|
37
|
-
<td><%= task.username %></td>
|
33
|
+
<td class="ellipsis"><%= task.state %></td>
|
34
|
+
<td class="ellipsis"><%= task.result %></td>
|
35
|
+
<td class="ellipsis"><%= task.started_at.try(:in_time_zone) %></td>
|
36
|
+
<td class="ellipsis"><%= task.ended_at.try(:in_time_zone) %></td>
|
37
|
+
<td class="ellipsis"><%= task.username %></td>
|
38
38
|
</tr>
|
39
39
|
<% end %>
|
40
40
|
</table>
|
data/foreman-tasks.gemspec
CHANGED
@@ -33,4 +33,6 @@ same resource. It also optionally provides Dynflow infrastructure for using it f
|
|
33
33
|
s.add_dependency "sinatra" # for Dynflow web console
|
34
34
|
s.add_dependency "parse-cron", '~> 0.1.4'
|
35
35
|
s.add_dependency "get_process_mem" # for memory polling
|
36
|
+
|
37
|
+
s.add_development_dependency 'factory_bot_rails', '~> 4.8.0'
|
36
38
|
end
|
data/lib/foreman_tasks.rb
CHANGED
@@ -20,16 +20,27 @@ module ForemanTasks
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.trigger_task(async, action, *args, &block)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
rails_safe_trigger_task do
|
24
|
+
Match! async, true, false
|
25
|
+
match trigger(action, *args, &block),
|
26
|
+
(on ::Dynflow::World::PlaningFailed.call(error: ~any) do |error|
|
27
|
+
raise error
|
28
|
+
end),
|
29
|
+
(on ::Dynflow::World::Triggered.call(execution_plan_id: ~any, future: ~any) do |id, finished|
|
30
|
+
finished.wait if async == false
|
31
|
+
ForemanTasks::Task::DynflowTask.where(:external_id => id).first!
|
32
|
+
end)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.rails_safe_trigger_task
|
37
|
+
if Rails::VERSION::MAJOR > 4
|
38
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
else
|
42
|
+
yield
|
43
|
+
end
|
33
44
|
end
|
34
45
|
|
35
46
|
def self.async_task(action, *args, &block)
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -41,7 +41,7 @@ module ForemanTasks
|
|
41
41
|
|
42
42
|
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do |_app|
|
43
43
|
Foreman::Plugin.register :"foreman-tasks" do
|
44
|
-
requires_foreman '>= 1.
|
44
|
+
requires_foreman '>= 1.16.0'
|
45
45
|
divider :top_menu, :parent => :monitor_menu, :last => true
|
46
46
|
menu :top_menu, :tasks,
|
47
47
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
@@ -121,7 +121,7 @@ module ForemanTasks
|
|
121
121
|
end
|
122
122
|
|
123
123
|
initializer 'foreman_tasks.set_core_settings' do
|
124
|
-
ForemanTasksCore::SettingsLoader.settings_registry.
|
124
|
+
ForemanTasksCore::SettingsLoader.settings_registry.each_key do |settings_keys|
|
125
125
|
settings = settings_keys.inject({}) do |h, settings_key|
|
126
126
|
h.merge(SETTINGS[settings_key] || {})
|
127
127
|
end
|
@@ -241,7 +241,7 @@ namespace :foreman_tasks do
|
|
241
241
|
end
|
242
242
|
|
243
243
|
format = ENV['TASK_FORMAT'] || 'html'
|
244
|
-
export_filename = ENV['TASK_FILE'] || "/tmp/task-export-#{
|
244
|
+
export_filename = ENV['TASK_FILE'] || "/tmp/task-export-#{Time.now.to_i}.#{format == 'csv' ? 'csv' : 'tar.gz'}"
|
245
245
|
|
246
246
|
tasks = ForemanTasks::Task.search_for(filter)
|
247
247
|
|
@@ -9,7 +9,7 @@ module ForemanRecurringLogic
|
|
9
9
|
User.current = User.where(:login => 'apiadmin').first
|
10
10
|
@request.env['HTTP_ACCEPT'] = 'application/json'
|
11
11
|
@request.env['CONTENT_TYPE'] = 'application/json'
|
12
|
-
@recurring_logic =
|
12
|
+
@recurring_logic = FactoryBot.create(:recurring_logic)
|
13
13
|
end
|
14
14
|
|
15
15
|
describe 'GET /api/recurring_logics' do
|
@@ -13,7 +13,7 @@ module ForemanTasks
|
|
13
13
|
|
14
14
|
describe 'GET /api/tasks/show' do
|
15
15
|
it 'searches for task' do
|
16
|
-
task =
|
16
|
+
task = FactoryBot.create(:dynflow_task, :user_create_task)
|
17
17
|
get :show, :id => task.id
|
18
18
|
assert_response :success
|
19
19
|
assert_template 'api/tasks/show'
|
@@ -4,8 +4,8 @@ require_relative './support/dummy_proxy_action'
|
|
4
4
|
|
5
5
|
require 'dynflow/testing'
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
FactoryBot.definition_file_paths = ["#{ForemanTasks::Engine.root}/test/factories"]
|
8
|
+
FactoryBot.find_definitions
|
9
9
|
|
10
10
|
ForemanTasks.dynflow.require!
|
11
11
|
ForemanTasks.dynflow.config.disable_active_record_actions = true
|
@@ -4,7 +4,7 @@ module ForemanTasks
|
|
4
4
|
class TasksHelperTest < ActionView::TestCase
|
5
5
|
describe 'when formatting simple input' do
|
6
6
|
before do
|
7
|
-
@task =
|
7
|
+
@task = FactoryBot.build(:dynflow_task, :user_create_task)
|
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')
|
@@ -22,7 +22,7 @@ module ForemanTasks
|
|
22
22
|
|
23
23
|
describe 'when formatting input' do
|
24
24
|
before do
|
25
|
-
@task =
|
25
|
+
@task = FactoryBot.build(:dynflow_task, :product_create_task)
|
26
26
|
humanized = { :humanized_name => 'Create',
|
27
27
|
:humanized_input => [[:product, { :text => "product 'product-2'", :link => '#/products/3/info' }], [:organization, { :text => "organization 'test-0'", :link => '/organizations/3/edit' }]] }
|
28
28
|
@task.instance_variable_set('@humanized_cache', humanized)
|
@@ -34,7 +34,7 @@ module ForemanTasks
|
|
34
34
|
|
35
35
|
describe Actions::ActionWithSubPlans do
|
36
36
|
let(:task) do
|
37
|
-
user =
|
37
|
+
user = FactoryBot.create(:user)
|
38
38
|
triggered = ForemanTasks.trigger(ParentAction, user)
|
39
39
|
raise triggered.error if triggered.respond_to?(:error)
|
40
40
|
triggered.finished.wait(2)
|
data/test/unit/cleaner_test.rb
CHANGED
@@ -10,13 +10,13 @@ class TasksTest < ActiveSupport::TestCase
|
|
10
10
|
it 'is able to delete tasks (including the dynflow plans) based on filter' do
|
11
11
|
cleaner = ForemanTasks::Cleaner.new(:filter => 'label = "Actions::User::Create"', :after => '10d')
|
12
12
|
|
13
|
-
tasks_to_delete = [
|
14
|
-
|
15
|
-
tasks_to_keep = [
|
13
|
+
tasks_to_delete = [FactoryBot.create(:dynflow_task, :user_create_task),
|
14
|
+
FactoryBot.create(:dynflow_task, :user_create_task)]
|
15
|
+
tasks_to_keep = [FactoryBot.create(:dynflow_task, :user_create_task) do |task|
|
16
16
|
task.started_at = task.ended_at = Time.zone.now
|
17
17
|
task.save
|
18
18
|
end,
|
19
|
-
|
19
|
+
FactoryBot.create(:dynflow_task, :product_create_task)]
|
20
20
|
cleaner.expects(:tasks_to_csv)
|
21
21
|
cleaner.delete
|
22
22
|
ForemanTasks::Task.where(id: tasks_to_delete).must_be_empty
|
@@ -31,13 +31,13 @@ class TasksTest < ActiveSupport::TestCase
|
|
31
31
|
|
32
32
|
it 'deletes all tasks matching the filter when the time limit is not specified' do
|
33
33
|
cleaner = ForemanTasks::Cleaner.new(:filter => 'label = "Actions::User::Create"')
|
34
|
-
tasks_to_delete = [
|
35
|
-
|
34
|
+
tasks_to_delete = [FactoryBot.create(:dynflow_task, :user_create_task),
|
35
|
+
FactoryBot.create(:dynflow_task, :user_create_task) do |task|
|
36
36
|
task.started_at = task.ended_at = Time.zone.now
|
37
37
|
task.save
|
38
38
|
end]
|
39
39
|
|
40
|
-
tasks_to_keep = [
|
40
|
+
tasks_to_keep = [FactoryBot.create(:dynflow_task, :product_create_task)]
|
41
41
|
cleaner.expects(:tasks_to_csv)
|
42
42
|
cleaner.delete
|
43
43
|
ForemanTasks::Task.where(id: tasks_to_delete).must_be_empty
|
@@ -46,10 +46,10 @@ class TasksTest < ActiveSupport::TestCase
|
|
46
46
|
|
47
47
|
it 'supports passing empty filter (just delete all)' do
|
48
48
|
cleaner = ForemanTasks::Cleaner.new(:filter => '', :after => '10d')
|
49
|
-
tasks_to_delete = [
|
50
|
-
|
49
|
+
tasks_to_delete = [FactoryBot.create(:dynflow_task, :user_create_task),
|
50
|
+
FactoryBot.create(:dynflow_task, :product_create_task)]
|
51
51
|
|
52
|
-
tasks_to_keep = [
|
52
|
+
tasks_to_keep = [FactoryBot.create(:dynflow_task, :user_create_task) do |task|
|
53
53
|
task.started_at = task.ended_at = Time.zone.now
|
54
54
|
task.save
|
55
55
|
end]
|
@@ -62,8 +62,8 @@ class TasksTest < ActiveSupport::TestCase
|
|
62
62
|
it 'backs tasks up before deleting' do
|
63
63
|
dir = '/tmp'
|
64
64
|
cleaner = ForemanTasks::Cleaner.new(:filter => '', :after => '10d', :backup_dir => dir)
|
65
|
-
tasks_to_delete = [
|
66
|
-
|
65
|
+
tasks_to_delete = [FactoryBot.create(:dynflow_task, :user_create_task),
|
66
|
+
FactoryBot.create(:dynflow_task, :product_create_task)]
|
67
67
|
|
68
68
|
r, w = IO.pipe
|
69
69
|
cleaner.expects(:with_backup_file)
|
@@ -8,8 +8,8 @@ module ForemanTasks
|
|
8
8
|
User.current = User.where(:login => 'apiadmin').first
|
9
9
|
end
|
10
10
|
|
11
|
-
let(:own_task) {
|
12
|
-
let(:foreign_task) {
|
11
|
+
let(:own_task) { FactoryBot.create(:dynflow_task, :set_owner => user) }
|
12
|
+
let(:foreign_task) { FactoryBot.create(:dynflow_task) }
|
13
13
|
|
14
14
|
let(:edit_foreman_tasks_permission) do
|
15
15
|
Permission.where(:name => :edit_foreman_tasks).first
|
@@ -24,7 +24,7 @@ module ForemanTasks
|
|
24
24
|
end
|
25
25
|
|
26
26
|
describe 'admin user' do
|
27
|
-
let(:user) {
|
27
|
+
let(:user) { FactoryBot.create(:user, :admin) }
|
28
28
|
it 'can see all tasks' do
|
29
29
|
assert dynflow_console_authorized?
|
30
30
|
assert dynflow_console_authorized?(own_task)
|
@@ -34,9 +34,9 @@ module ForemanTasks
|
|
34
34
|
|
35
35
|
describe 'user with unlimited edit_foreman_tasks permissions' do
|
36
36
|
let(:user) do
|
37
|
-
user_role =
|
38
|
-
|
39
|
-
|
37
|
+
user_role = FactoryBot.create(:user_user_role)
|
38
|
+
FactoryBot.create(:filter,
|
39
|
+
:role => user_role.role, :permissions => [edit_foreman_tasks_permission])
|
40
40
|
user_role.owner
|
41
41
|
end
|
42
42
|
|
@@ -49,10 +49,10 @@ module ForemanTasks
|
|
49
49
|
|
50
50
|
describe 'user with limited edit_foreman_tasks permissions' do
|
51
51
|
let(:user) do
|
52
|
-
user_role =
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
user_role = FactoryBot.create(:user_user_role)
|
53
|
+
FactoryBot.create(:filter,
|
54
|
+
:search => 'owner.id = current_user',
|
55
|
+
:role => user_role.role, :permissions => [edit_foreman_tasks_permission])
|
56
56
|
user_role.owner
|
57
57
|
end
|
58
58
|
|
@@ -64,7 +64,7 @@ module ForemanTasks
|
|
64
64
|
end
|
65
65
|
|
66
66
|
describe 'user without edit_foreman_tasks permissions' do
|
67
|
-
let(:user) {
|
67
|
+
let(:user) { FactoryBot.create(:user) }
|
68
68
|
it 'can not see any tasks' do
|
69
69
|
refute dynflow_console_authorized?
|
70
70
|
refute dynflow_console_authorized?(own_task)
|
@@ -12,7 +12,7 @@ describe ForemanTasks::ProxySelector do
|
|
12
12
|
count = 3
|
13
13
|
ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.expects(:tasks_count).raises
|
14
14
|
.then.times(count - 1).returns(0)
|
15
|
-
proxies =
|
15
|
+
proxies = FactoryBot.create_list(:smart_proxy, count)
|
16
16
|
|
17
17
|
available = proxies.reduce([]) do |found, _|
|
18
18
|
found << proxy_selector.select_by_jobs_count(proxies)
|
@@ -40,14 +40,14 @@ describe ForemanTasks::ProxySelector do
|
|
40
40
|
count = 3
|
41
41
|
ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.expects(:tasks_count).times(count).raises
|
42
42
|
proxy_selector.stubs(:available_proxies =>
|
43
|
-
{ :global =>
|
43
|
+
{ :global => FactoryBot.create_list(:smart_proxy, count) })
|
44
44
|
proxy_selector.determine_proxy.must_equal :not_available
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'returns first available proxy, prioritizing by strategy' do
|
48
48
|
ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.expects(:tasks_count).returns(0)
|
49
|
-
fallback_proxy =
|
50
|
-
global_proxy =
|
49
|
+
fallback_proxy = FactoryBot.build(:smart_proxy)
|
50
|
+
global_proxy = FactoryBot.build(:smart_proxy)
|
51
51
|
ForemanTasks::ProxySelector.any_instance.stubs(:available_proxies =>
|
52
52
|
{ :fallback => [fallback_proxy],
|
53
53
|
:global => [global_proxy] })
|
@@ -89,14 +89,14 @@ class RecurringLogicsTest < ActiveSupport::TestCase
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'can be created from triggering' do
|
92
|
-
triggering =
|
92
|
+
triggering = FactoryBot.build(:triggering, :recurring, :end_time_limited)
|
93
93
|
logic = ForemanTasks::RecurringLogic.new_from_triggering(triggering)
|
94
94
|
# Mysql coerces the times a bit
|
95
95
|
logic.end_time.must_be_close_to(triggering.end_time, 1.second)
|
96
96
|
end
|
97
97
|
|
98
98
|
describe 'validation' do
|
99
|
-
let(:logic) {
|
99
|
+
let(:logic) { FactoryBot.build(:recurring_logic) }
|
100
100
|
|
101
101
|
it 'is valid by default' do
|
102
102
|
logic.must_be :valid?
|
data/test/unit/task_test.rb
CHANGED
@@ -2,33 +2,39 @@ require 'foreman_tasks_test_helper'
|
|
2
2
|
|
3
3
|
class TasksTest < ActiveSupport::TestCase
|
4
4
|
describe 'filtering by current user' do
|
5
|
-
before
|
6
|
-
|
5
|
+
before do
|
6
|
+
@original_current_user = User.current
|
7
|
+
@user_one = FactoryBot.create(:user)
|
8
|
+
@user_two = FactoryBot.create(:user)
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
@task_one = FactoryBot.create(:some_task, :set_owner => @user_one)
|
11
|
+
FactoryBot.create(:some_task, :set_owner => @user_two)
|
12
|
+
|
13
|
+
User.current = @user_one
|
14
|
+
end
|
15
|
+
after { User.current = @original_current_user }
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
test 'can search the tasks by current_user' do
|
18
|
+
assert_equal [@task_one], ForemanTasks::Task.search_for('owner.id = current_user')
|
19
|
+
end
|
14
20
|
|
15
|
-
|
16
|
-
assert_equal [task_one], ForemanTasks::Task.search_for(
|
21
|
+
test 'can search the tasks by current_user in combination with implicit search' do
|
22
|
+
assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id = current_user AND #{@task_one.label}")
|
17
23
|
end
|
18
24
|
end
|
19
25
|
|
20
26
|
describe 'authorization filtering' do
|
21
27
|
it 'can filter by the task subject' do
|
22
|
-
user_role =
|
28
|
+
user_role = FactoryBot.create(:user_user_role)
|
23
29
|
user = user_role.owner
|
24
30
|
role = user_role.role
|
25
|
-
permission =
|
31
|
+
permission = FactoryBot.build(:permission)
|
26
32
|
permission.resource_type = 'ForemanTasks::Task'
|
27
33
|
permission.save!
|
28
|
-
|
34
|
+
FactoryBot.create(:filter, :role => role, :permissions => [permission])
|
29
35
|
|
30
36
|
User.current = user
|
31
|
-
task =
|
37
|
+
task = FactoryBot.create(:dynflow_task)
|
32
38
|
|
33
39
|
auth = Authorizer.new(user)
|
34
40
|
assert auth.can?(permission.name.to_sym, task)
|
@@ -36,8 +42,8 @@ class TasksTest < ActiveSupport::TestCase
|
|
36
42
|
end
|
37
43
|
|
38
44
|
describe 'consistency check' do
|
39
|
-
let(:consistent_task) {
|
40
|
-
let(:inconsistent_task) {
|
45
|
+
let(:consistent_task) { FactoryBot.create(:dynflow_task, :sync_with_dynflow => true) }
|
46
|
+
let(:inconsistent_task) { FactoryBot.create(:dynflow_task, :inconsistent_dynflow_task) }
|
41
47
|
|
42
48
|
it 'ensures the tasks marked as running are really running in Dynflow' do
|
43
49
|
running_task_count = ForemanTasks::Task::DynflowTask.running.count
|
@@ -54,7 +60,7 @@ class TasksTest < ActiveSupport::TestCase
|
|
54
60
|
|
55
61
|
describe 'task without valid execution plan' do
|
56
62
|
let(:task) do
|
57
|
-
|
63
|
+
FactoryBot.create(:dynflow_task).tap do |task|
|
58
64
|
task.external_id = 'missing-task'
|
59
65
|
end
|
60
66
|
end
|
@@ -80,7 +86,7 @@ class TasksTest < ActiveSupport::TestCase
|
|
80
86
|
:pending => 0
|
81
87
|
}
|
82
88
|
end
|
83
|
-
let(:task) {
|
89
|
+
let(:task) { FactoryBot.create(:dynflow_task) }
|
84
90
|
|
85
91
|
describe 'without sub tasks' do
|
86
92
|
it 'calculates the progress report correctly' do
|
@@ -89,8 +95,8 @@ class TasksTest < ActiveSupport::TestCase
|
|
89
95
|
end
|
90
96
|
|
91
97
|
describe 'with sub tasks' do
|
92
|
-
let(:failed) {
|
93
|
-
let(:success) {
|
98
|
+
let(:failed) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :error } }
|
99
|
+
let(:success) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :success } }
|
94
100
|
before { task.sub_tasks = [success, failed] }
|
95
101
|
|
96
102
|
it 'calculate the progress report correctly' do
|
@@ -99,7 +105,6 @@ class TasksTest < ActiveSupport::TestCase
|
|
99
105
|
end
|
100
106
|
|
101
107
|
it 'calculates the progress report correctly when using batch planning' do
|
102
|
-
# rubocop:disable Style/RedundantSelf - not redundant, as otherwise it conflicts with local variable
|
103
108
|
result_base = self.result_base.merge(:success => 1, :error => 1, :total => 25)
|
104
109
|
fake_action = OpenStruct.new(:total_count => 25)
|
105
110
|
task.stubs(:main_action).returns(fake_action)
|
@@ -116,8 +121,8 @@ class TasksTest < ActiveSupport::TestCase
|
|
116
121
|
end
|
117
122
|
|
118
123
|
describe 'recurring task' do
|
119
|
-
let(:logic) {
|
120
|
-
let(:task) {
|
124
|
+
let(:logic) { FactoryBot.build(:recurring_logic) }
|
125
|
+
let(:task) { FactoryBot.create(:some_task) }
|
121
126
|
|
122
127
|
it 'can indicate it is recurring' do
|
123
128
|
refute task.recurring?
|
@@ -128,7 +133,7 @@ class TasksTest < ActiveSupport::TestCase
|
|
128
133
|
end
|
129
134
|
|
130
135
|
describe 'delayed task' do
|
131
|
-
let(:task) {
|
136
|
+
let(:task) { FactoryBot.create(:some_task) }
|
132
137
|
|
133
138
|
it 'can indicate it is delayed' do
|
134
139
|
refute task.delayed?
|
@@ -3,18 +3,18 @@ require 'foreman_tasks_test_helper'
|
|
3
3
|
class TriggeringTest < ActiveSupport::TestCase
|
4
4
|
describe 'validation' do
|
5
5
|
it 'is valid when immediate' do
|
6
|
-
|
6
|
+
FactoryBot.build(:triggering).must_be :valid?
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'is validates future execution' do
|
10
|
-
triggering =
|
10
|
+
triggering = FactoryBot.build(:triggering, :future)
|
11
11
|
triggering.must_be :valid?
|
12
12
|
triggering.start_before = triggering.start_at - 120
|
13
13
|
triggering.wont_be :valid?
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'is invalid when recurring logic is invalid' do
|
17
|
-
triggering =
|
17
|
+
triggering = FactoryBot.build(:triggering, :recurring)
|
18
18
|
triggering.must_be :valid?
|
19
19
|
triggering.recurring_logic.stubs(:valid?).returns(false)
|
20
20
|
triggering.wont_be :valid?
|
@@ -22,7 +22,7 @@ class TriggeringTest < ActiveSupport::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'cannot have mode set to arbitrary value' do
|
25
|
-
triggering =
|
25
|
+
triggering = FactoryBot.build(:triggering)
|
26
26
|
triggering.must_be :valid?
|
27
27
|
proc { triggering.mode = 'bogus' }.must_raise ArgumentError
|
28
28
|
proc { triggering.mode = 27 }.must_raise ArgumentError
|
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.10.
|
4
|
+
version: 0.10.6
|
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: 2017-
|
11
|
+
date: 2017-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: foreman-tasks-core
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: factory_bot_rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.8.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.8.0
|
83
97
|
description: |
|
84
98
|
The goal of this plugin is to unify the way of showing task statuses across the Foreman instance.
|
85
99
|
It defines Task model for keeping the information about the tasks and Lock for assigning the tasks
|
@@ -125,6 +139,7 @@ files:
|
|
125
139
|
- app/lib/actions/helpers/with_delegated_action.rb
|
126
140
|
- app/lib/actions/middleware/inherit_task_groups.rb
|
127
141
|
- app/lib/actions/middleware/keep_current_user.rb
|
142
|
+
- app/lib/actions/middleware/rails_executor_wrap.rb
|
128
143
|
- app/lib/actions/middleware/recurring_logic.rb
|
129
144
|
- app/lib/actions/proxy_action.rb
|
130
145
|
- app/lib/actions/serializers/active_record_serializer.rb
|