foreman-tasks 0.10.4 → 0.10.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|