foreman-tasks 3.0.4 → 4.1.1
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/.github/workflows/ruby_tests.yml +5 -3
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +2 -5
- data/app/lib/actions/entry_action.rb +8 -4
- data/app/lib/actions/helpers/lock.rb +11 -5
- data/app/lib/actions/middleware/keep_current_request_id.rb +4 -1
- data/app/lib/actions/middleware/keep_current_user.rb +11 -1
- data/app/lib/actions/observable_action.rb +80 -0
- data/app/lib/actions/proxy_action.rb +2 -4
- data/app/models/foreman_tasks/concerns/action_subject.rb +0 -6
- data/app/models/foreman_tasks/link.rb +60 -0
- data/app/models/foreman_tasks/lock.rb +30 -128
- data/app/models/foreman_tasks/task.rb +20 -7
- data/app/models/foreman_tasks/task/search.rb +7 -6
- data/app/views/foreman_tasks/api/locks/show.json.rabl +4 -0
- data/app/views/foreman_tasks/api/tasks/details.json.rabl +5 -3
- data/app/views/foreman_tasks/tasks/_lock_card.html.erb +10 -0
- data/db/migrate/20180927120509_add_user_id.foreman_tasks.rb +4 -2
- data/db/migrate/20181206123910_create_foreman_tasks_links.foreman_tasks.rb +26 -0
- data/db/migrate/20181206124952_migrate_non_exclusive_locks_to_links.foreman_tasks.rb +14 -0
- data/db/migrate/20181206131436_drop_old_locks.foreman_tasks.rb +20 -0
- data/db/migrate/20181206131627_make_locks_exclusive.foreman_tasks.rb +25 -0
- data/lib/foreman_tasks/cleaner.rb +10 -0
- data/lib/foreman_tasks/engine.rb +5 -2
- data/lib/foreman_tasks/tasks/export_tasks.rake +2 -2
- data/lib/foreman_tasks/version.rb +1 -1
- data/package.json +6 -6
- data/test/controllers/api/tasks_controller_test.rb +1 -1
- data/test/controllers/tasks_controller_test.rb +3 -3
- data/test/core/unit/runner_test.rb +4 -17
- data/test/factories/task_factory.rb +31 -4
- data/test/unit/actions/action_with_sub_plans_test.rb +5 -2
- data/test/unit/actions/proxy_action_test.rb +4 -1
- data/test/unit/cleaner_test.rb +4 -4
- data/test/unit/locking_test.rb +85 -0
- data/test/unit/task_test.rb +15 -13
- data/test/unit/triggering_test.rb +2 -2
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Locks.js +2 -2
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +3 -2
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Locks.test.js.snap +4 -4
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +2 -0
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +4 -1
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +5 -1
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +3 -0
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +2 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +4 -3
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +2 -3
- data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +2 -3
- metadata +12 -4
- data/test/unit/lock_test.rb +0 -22
@@ -31,6 +31,7 @@ module ForemanTasks
|
|
31
31
|
has_many :recurring_logic_task_groups, -> { where :type => 'ForemanTasks::TaskGroups::RecurringLogicTaskGroup' },
|
32
32
|
:through => :task_group_members, :source => :task_group
|
33
33
|
belongs_to :user
|
34
|
+
has_many :links, :dependent => :destroy
|
34
35
|
|
35
36
|
scoped_search :on => :id, :complete_value => false
|
36
37
|
scoped_search :on => :action, :complete_value => false
|
@@ -46,10 +47,16 @@ module ForemanTasks
|
|
46
47
|
|
47
48
|
# Note: the following searches may return duplicates, this is due to
|
48
49
|
# one task maybe having multiple locks (e.g. read/write) for the same resource_id
|
49
|
-
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => '
|
50
|
-
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => '
|
51
|
-
scoped_search :relation => :locks, :on => :resource_type, :complete_value => true, :rename => '
|
52
|
-
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => '
|
50
|
+
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'locked_location_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
51
|
+
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'locked_organization_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
52
|
+
scoped_search :relation => :locks, :on => :resource_type, :complete_value => true, :rename => 'locked_resource_type', :ext_method => :search_by_generic_resource, :only_explicit => true
|
53
|
+
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'locked_resource_id', :ext_method => :search_by_generic_resource, :only_explicit => true
|
54
|
+
|
55
|
+
scoped_search :relation => :links, :on => :resource_id, :complete_value => false, :rename => 'location_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
56
|
+
scoped_search :relation => :links, :on => :resource_id, :complete_value => false, :rename => 'organization_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
57
|
+
scoped_search :relation => :links, :on => :resource_type, :complete_value => true, :rename => 'resource_type', :ext_method => :search_by_generic_resource, :only_explicit => true
|
58
|
+
scoped_search :relation => :links, :on => :resource_id, :complete_value => false, :rename => 'resource_id', :ext_method => :search_by_generic_resource, :only_explicit => true
|
59
|
+
|
53
60
|
scoped_search :on => :user_id,
|
54
61
|
:complete_value => true,
|
55
62
|
:rename => 'user.id',
|
@@ -65,8 +72,8 @@ module ForemanTasks
|
|
65
72
|
scope :running, -> { where("foreman_tasks_tasks.state NOT IN ('stopped', 'paused')") }
|
66
73
|
scope :for_resource,
|
67
74
|
(lambda do |resource|
|
68
|
-
joins(:
|
69
|
-
:"
|
75
|
+
joins(:links).where(:"foreman_tasks_links.resource_id" => resource.id,
|
76
|
+
:"foreman_tasks_links.resource_type" => resource.class.name)
|
70
77
|
end)
|
71
78
|
scope :for_action_types, (->(action_types) { where('foreman_tasks_tasks.label IN (?)', Array(action_types)) })
|
72
79
|
|
@@ -82,7 +89,7 @@ module ForemanTasks
|
|
82
89
|
property :ended_at, ActiveSupport::TimeWithZone, desc: 'Returns date with time the task ended at'
|
83
90
|
end
|
84
91
|
class Jail < Safemode::Jail
|
85
|
-
allow :started_at, :ended_at, :result, :state, :label, :main_action
|
92
|
+
allow :started_at, :ended_at, :result, :state, :label, :main_action, :action_continuous_output
|
86
93
|
end
|
87
94
|
|
88
95
|
def input
|
@@ -242,6 +249,12 @@ module ForemanTasks
|
|
242
249
|
parts.join(' ').strip
|
243
250
|
end
|
244
251
|
|
252
|
+
def action_continuous_output
|
253
|
+
return unless main_action.is_a?(Actions::Helpers::WithContinuousOutput)
|
254
|
+
main_action.continuous_output.sort!
|
255
|
+
main_action.continuous_output.raw_outputs
|
256
|
+
end
|
257
|
+
|
245
258
|
protected
|
246
259
|
|
247
260
|
def generate_id
|
@@ -5,9 +5,9 @@ module ForemanTasks
|
|
5
5
|
key = 'resource_type' if key.blank?
|
6
6
|
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
7
7
|
value = value.split(',') if operator.index(/IN/i)
|
8
|
-
condition = sanitize_sql_for_conditions(["
|
8
|
+
condition = sanitize_sql_for_conditions(["foreman_tasks_links.#{key_name} #{operator} (?)", value])
|
9
9
|
|
10
|
-
{ :conditions => condition, :joins => :
|
10
|
+
{ :conditions => condition, :joins => :links }
|
11
11
|
end
|
12
12
|
|
13
13
|
def search_by_taxonomy(key, operator, value)
|
@@ -15,12 +15,13 @@ module ForemanTasks
|
|
15
15
|
resource_type = key == 'location_id' ? 'Location' : 'Organization'
|
16
16
|
|
17
17
|
joins = <<-SQL
|
18
|
-
LEFT JOIN
|
19
|
-
ON (
|
20
|
-
|
18
|
+
LEFT JOIN foreman_tasks_links AS foreman_tasks_links_taxonomy#{uniq_suffix}
|
19
|
+
ON (foreman_tasks_links_taxonomy#{uniq_suffix}.task_id = foreman_tasks_tasks.id AND
|
20
|
+
foreman_tasks_links_taxonomy#{uniq_suffix}.resource_type = '#{resource_type}')
|
21
21
|
SQL
|
22
22
|
# Select only those tasks which either have the correct taxonomy or are not related to any
|
23
|
-
sql = "
|
23
|
+
sql = "foreman_tasks_links_taxonomy#{uniq_suffix}.resource_id #{operator} (?) OR foreman_tasks_links_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
24
|
+
value = value.split(',') if operator.index(/IN/i)
|
24
25
|
{ :conditions => sanitize_sql_for_conditions([sql, value]), :joins => joins }
|
25
26
|
end
|
26
27
|
|
@@ -9,10 +9,12 @@ node(:failed_steps) { @task.input_output_failed_steps }
|
|
9
9
|
node(:running_steps) { @task.input_output_running_steps }
|
10
10
|
node(:help) { troubleshooting_info_text }
|
11
11
|
node(:has_sub_tasks) { @task.sub_tasks.any? }
|
12
|
+
|
12
13
|
node(:locks) do
|
13
|
-
@task.locks.map
|
14
|
-
|
15
|
-
|
14
|
+
@task.locks.map { |lock| partial('foreman_tasks/api/locks/show', :object => lock) }
|
15
|
+
end
|
16
|
+
node(:links) do
|
17
|
+
@task.links.map { |link| partial('foreman_tasks/api/locks/show', :object => link, :locals => { :link => true }) }
|
16
18
|
end
|
17
19
|
node(:username_path) { username_link_task(@task.owner, @task.username) }
|
18
20
|
node(:dynflow_enable_console) { Setting['dynflow_enable_console'] }
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<div class="col-xs-6 col-sm-4 col-md-4">
|
2
|
+
<div class="card-pf card-pf-accented card-pf-aggregate-status">
|
3
|
+
<h2 class="card-pf-title">
|
4
|
+
<span class="fa <%= lock.is_a?(::ForemanTasks::Lock) ? 'fa-lock' : 'fa-unlock-alt' %>"></span> <%= lock.resource_type %>
|
5
|
+
</h2>
|
6
|
+
<div class="card-pf-body">
|
7
|
+
<%= format('id:%s', lock.resource_id) %><br>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
</div>
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class AddUserId < ActiveRecord::Migration[5.0]
|
2
|
+
OWNER_LOCK_NAME = :task_owner
|
3
|
+
|
2
4
|
def up
|
3
5
|
add_reference :foreman_tasks_tasks, :user, :foreign_key => true
|
4
6
|
|
@@ -29,7 +31,7 @@ class AddUserId < ActiveRecord::Migration[5.0]
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def create_lock(user_id, task)
|
32
|
-
ForemanTasks::Lock.new(:name =>
|
34
|
+
ForemanTasks::Lock.new(:name => OWNER_LOCK_NAME,
|
33
35
|
:resource_type => User.name,
|
34
36
|
:resource_id => user_id,
|
35
37
|
:task_id => task.id,
|
@@ -37,6 +39,6 @@ class AddUserId < ActiveRecord::Migration[5.0]
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def user_locks
|
40
|
-
ForemanTasks::Lock.where(:name =>
|
42
|
+
ForemanTasks::Lock.where(:name => OWNER_LOCK_NAME)
|
41
43
|
end
|
42
44
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class CreateForemanTasksLinks < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
# rubocop:disable Rails/CreateTableWithTimestamps
|
4
|
+
create_table :foreman_tasks_links do |t|
|
5
|
+
task_id_options = { :index => true, :null => true }
|
6
|
+
if on_postgresql?
|
7
|
+
t.uuid :task_id, task_id_options
|
8
|
+
else
|
9
|
+
t.string :task_id, task_id_options
|
10
|
+
end
|
11
|
+
t.string :resource_type
|
12
|
+
t.integer :resource_id
|
13
|
+
end
|
14
|
+
# rubocop:enable Rails/CreateTableWithTimestamps
|
15
|
+
|
16
|
+
add_index :foreman_tasks_links, [:resource_type, :resource_id]
|
17
|
+
add_index :foreman_tasks_links, [:task_id, :resource_type, :resource_id],
|
18
|
+
:unique => true, :name => 'foreman_tasks_links_unique_index'
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def on_postgresql?
|
24
|
+
ActiveRecord::Base.connection.adapter_name.casecmp('postgresql').zero?
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class MigrateNonExclusiveLocksToLinks < ActiveRecord::Migration[5.0]
|
2
|
+
def up
|
3
|
+
execute <<-SQL
|
4
|
+
INSERT INTO foreman_tasks_links(task_id, resource_type, resource_id)
|
5
|
+
SELECT DISTINCT locks.task_id, locks.resource_type, locks.resource_id
|
6
|
+
FROM foreman_tasks_locks AS locks
|
7
|
+
LEFT JOIN foreman_tasks_links AS links
|
8
|
+
ON links.task_id = locks.task_id
|
9
|
+
AND links.resource_type = locks.resource_type
|
10
|
+
AND links.resource_id = locks.resource_id
|
11
|
+
WHERE locks.exclusive = FALSE AND links.task_id IS NULL;
|
12
|
+
SQL
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class DropOldLocks < ActiveRecord::Migration[5.0]
|
2
|
+
BATCH_SIZE = 10_000
|
3
|
+
|
4
|
+
# Delete all locks which are exclusive or have a stopped task or are orphaned
|
5
|
+
def up
|
6
|
+
scope = ForemanTasks::Lock.left_outer_joins(:task)
|
7
|
+
scope = scope.where(:exclusive => false)
|
8
|
+
.or(scope.where("#{ForemanTasks::Task.table_name}.state" => ['stopped', nil]))
|
9
|
+
scope.limit(BATCH_SIZE).delete_all while scope.any?
|
10
|
+
|
11
|
+
# For each group of locks, where each lock has the same task_id, resource_type and resource_id
|
12
|
+
# return the highest id within the group, if there is more than 1 lock in the group
|
13
|
+
scope = ForemanTasks::Lock.select("MAX(id) as id")
|
14
|
+
.group(:task_id, :resource_type, :resource_id)
|
15
|
+
.having("count(*) > 1")
|
16
|
+
|
17
|
+
# Make sure there is at most one lock per task and resource
|
18
|
+
ForemanTasks::Lock.where(:id => scope.limit(BATCH_SIZE)).delete_all while scope.any?
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class MakeLocksExclusive < ActiveRecord::Migration[5.0]
|
2
|
+
BATCH_SIZE = 2
|
3
|
+
|
4
|
+
def up
|
5
|
+
change_table :foreman_tasks_locks do |t|
|
6
|
+
t.remove :exclusive
|
7
|
+
t.remove :name
|
8
|
+
t.remove_index :name => 'index_foreman_tasks_locks_on_resource_type_and_resource_id'
|
9
|
+
t.index [:resource_type, :resource_id], :unique => true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def down
|
14
|
+
change_table :foreman_tasks_locks do |t|
|
15
|
+
t.boolean :exclusive, index: true
|
16
|
+
t.string :name, index: true
|
17
|
+
t.remove_index :name => 'index_foreman_tasks_locks_on_resource_type_and_resource_id'
|
18
|
+
t.index [:resource_type, :resource_id]
|
19
|
+
end
|
20
|
+
|
21
|
+
scope = ForemanTasks::Lock.where(:name => nil)
|
22
|
+
while scope.limit(BATCH_SIZE).update_all(:name => 'lock') == BATCH_SIZE; end
|
23
|
+
change_column_null(:foreman_tasks_locks, :name, false)
|
24
|
+
end
|
25
|
+
end
|
@@ -103,6 +103,7 @@ module ForemanTasks
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
delete_orphaned_locks
|
106
|
+
delete_orphaned_links
|
106
107
|
delete_orphaned_dynflow_tasks
|
107
108
|
end
|
108
109
|
|
@@ -156,6 +157,15 @@ module ForemanTasks
|
|
156
157
|
end
|
157
158
|
end
|
158
159
|
|
160
|
+
def delete_orphaned_links
|
161
|
+
orphaned_links = ForemanTasks::Link.left_outer_joins(:task).where(:'foreman_tasks_tasks.id' => nil)
|
162
|
+
with_noop(orphaned_links, 'orphaned task links') do |source, name|
|
163
|
+
with_batches(source, name) do |chunk|
|
164
|
+
ForemanTasks::Link.where(id: chunk.pluck(:id)).delete_all
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
159
169
|
def delete_orphaned_dynflow_tasks
|
160
170
|
with_noop(orphaned_dynflow_tasks, 'orphaned execution plans') do |source, name|
|
161
171
|
with_batches(source, name) do |chunk|
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -34,7 +34,7 @@ module ForemanTasks
|
|
34
34
|
|
35
35
|
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do |_app|
|
36
36
|
Foreman::Plugin.register :"foreman-tasks" do
|
37
|
-
requires_foreman '>= 2.
|
37
|
+
requires_foreman '>= 2.4.0'
|
38
38
|
divider :top_menu, :parent => :monitor_menu, :last => true, :caption => N_('Foreman Tasks')
|
39
39
|
menu :top_menu, :tasks,
|
40
40
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
@@ -76,6 +76,9 @@ module ForemanTasks
|
|
76
76
|
|
77
77
|
widget 'foreman_tasks/tasks/dashboard/tasks_status', :sizex => 6, :sizey => 1, :name => N_('Task Status')
|
78
78
|
widget 'foreman_tasks/tasks/dashboard/latest_tasks_in_error_warning', :sizex => 6, :sizey => 1, :name => N_('Latest Warning/Error Tasks')
|
79
|
+
|
80
|
+
ForemanTasks.dynflow.eager_load_actions!
|
81
|
+
extend_observable_events(::Dynflow::Action.descendants.select { |klass| klass <= ::Actions::ObservableAction }.map(&:namespaced_event_names))
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
@@ -108,7 +111,7 @@ module ForemanTasks
|
|
108
111
|
ForemanTasks.dynflow.require!
|
109
112
|
::ForemanTasks.dynflow.config.on_init(false) do |world|
|
110
113
|
world.middleware.use Actions::Middleware::KeepCurrentTaxonomies
|
111
|
-
world.middleware.use Actions::Middleware::KeepCurrentUser
|
114
|
+
world.middleware.use Actions::Middleware::KeepCurrentUser, :before => ::Dynflow::Middleware::Common::Transaction
|
112
115
|
world.middleware.use Actions::Middleware::KeepCurrentTimezone
|
113
116
|
world.middleware.use Actions::Middleware::KeepCurrentRequestID
|
114
117
|
end
|
@@ -252,7 +252,7 @@ namespace :foreman_tasks do
|
|
252
252
|
renderer = TaskRender.new
|
253
253
|
total = tasks.count
|
254
254
|
|
255
|
-
tasks.
|
255
|
+
tasks.find_each.with_index do |task, count|
|
256
256
|
File.open(File.join(tmp_dir, "#{task.id}.html"), 'w') { |file| file.write(PageHelper.pagify(renderer.render_task(task))) }
|
257
257
|
puts "#{count + 1}/#{total}"
|
258
258
|
end
|
@@ -264,7 +264,7 @@ namespace :foreman_tasks do
|
|
264
264
|
elsif format == 'csv'
|
265
265
|
CSV.open(export_filename, 'wb') do |csv|
|
266
266
|
csv << %w[id state type label result parent_task_id started_at ended_at]
|
267
|
-
tasks.
|
267
|
+
tasks.find_each do |task|
|
268
268
|
csv << [task.id, task.state, task.type, task.label, task.result,
|
269
269
|
task.parent_task_id, task.started_at, task.ended_at]
|
270
270
|
end
|
data/package.json
CHANGED
@@ -23,7 +23,7 @@
|
|
23
23
|
"url": "http://projects.theforeman.org/projects/foreman-tasks/issues"
|
24
24
|
},
|
25
25
|
"peerDependencies": {
|
26
|
-
"@theforeman/vendor": ">=
|
26
|
+
"@theforeman/vendor": ">= 6.0.0"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
29
|
"c3": "^0.4.11",
|
@@ -32,11 +32,11 @@
|
|
32
32
|
},
|
33
33
|
"devDependencies": {
|
34
34
|
"@babel/core": "^7.7.0",
|
35
|
-
"@theforeman/builder": "^
|
36
|
-
"@theforeman/eslint-plugin-foreman": "
|
37
|
-
"@theforeman/stories": "^
|
38
|
-
"@theforeman/test": "^
|
39
|
-
"@theforeman/vendor-dev": "^
|
35
|
+
"@theforeman/builder": "^6.0.0",
|
36
|
+
"@theforeman/eslint-plugin-foreman": "6.0.0",
|
37
|
+
"@theforeman/stories": "^6.0.0",
|
38
|
+
"@theforeman/test": "^6.0.0",
|
39
|
+
"@theforeman/vendor-dev": "^6.0.0",
|
40
40
|
"babel-eslint": "^10.0.3",
|
41
41
|
"eslint": "^6.7.2",
|
42
42
|
"jed": "^1.1.1",
|
@@ -29,7 +29,7 @@ module ForemanTasks
|
|
29
29
|
|
30
30
|
it 'renders task ids when searching by resource id' do
|
31
31
|
task = FactoryBot.create(:dynflow_task, :product_create_task)
|
32
|
-
ForemanTasks::
|
32
|
+
ForemanTasks::Link.create!(resource_type: "Katello::Product", resource_id: 1, task_id: task.id)
|
33
33
|
get :index, params: { :search => "label = Actions::Katello::Product::Create and resource_id = 1" }
|
34
34
|
assert_response :success
|
35
35
|
data = JSON.parse(response.body)
|
@@ -10,7 +10,7 @@ module ForemanTasks
|
|
10
10
|
# rubocop:enable Naming/AccessorMethodName
|
11
11
|
|
12
12
|
def linked_task(resource)
|
13
|
-
FactoryBot.create(:some_task).tap { |t| ForemanTasks::
|
13
|
+
FactoryBot.create(:some_task).tap { |t| ForemanTasks::Link.link!(resource, t) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def in_taxonomy_scope(organization, location = nil)
|
@@ -44,8 +44,8 @@ module ForemanTasks
|
|
44
44
|
@locations = [0, 0].map { FactoryBot.create(:location) }
|
45
45
|
@tasks = [0, 0].map { FactoryBot.create(:some_task) }
|
46
46
|
@tasks.zip(@organizations, @locations).each do |task, org, loc|
|
47
|
-
|
48
|
-
|
47
|
+
Link.link!(org, task)
|
48
|
+
Link.link!(loc, task)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -53,7 +53,7 @@ module ForemanTasksCore
|
|
53
53
|
describe '#initialize_continuous_outputs' do
|
54
54
|
it 'initializes outputs for targets and parent' do
|
55
55
|
outputs = runner.initialize_continuous_outputs
|
56
|
-
_(outputs.keys.count).must_equal
|
56
|
+
_(outputs.keys.count).must_equal 2
|
57
57
|
outputs.values.each { |output| _(output).must_be_instance_of ContinuousOutput }
|
58
58
|
end
|
59
59
|
end
|
@@ -66,23 +66,10 @@ module ForemanTasksCore
|
|
66
66
|
_(updates.keys.count).must_equal 1
|
67
67
|
end
|
68
68
|
|
69
|
-
it 'works in compatibility mode' do
|
70
|
-
runner = Parent.new targets
|
71
|
-
_(runner.generate_updates).must_equal({})
|
72
|
-
runner.broadcast_data('something', 'stdout')
|
73
|
-
updates = runner.generate_updates
|
74
|
-
_(updates.keys.count).must_equal 3
|
75
|
-
# One of the keys is nil in compatibility mode
|
76
|
-
_(updates.keys.compact.count).must_equal 2
|
77
|
-
updates.keys.compact.each do |key|
|
78
|
-
_(key).must_be_instance_of ::Dynflow::Action::Suspended
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
69
|
it 'works without compatibility mode' do
|
83
70
|
runner.broadcast_data('something', 'stdout')
|
84
71
|
updates = runner.generate_updates
|
85
|
-
_(updates.keys.count).must_equal
|
72
|
+
_(updates.keys.count).must_equal 2
|
86
73
|
updates.keys.each do |key|
|
87
74
|
_(key).must_be_instance_of ::Dynflow::Action::Suspended
|
88
75
|
end
|
@@ -99,7 +86,7 @@ module ForemanTasksCore
|
|
99
86
|
describe '#broadcast_data' do
|
100
87
|
it 'publishes data for all hosts' do
|
101
88
|
runner.broadcast_data('message', 'stdout')
|
102
|
-
_(runner.generate_updates.keys.count).must_equal
|
89
|
+
_(runner.generate_updates.keys.count).must_equal 2
|
103
90
|
end
|
104
91
|
end
|
105
92
|
|
@@ -115,7 +102,7 @@ module ForemanTasksCore
|
|
115
102
|
it 'broadcasts the exception to all targets' do
|
116
103
|
runner.expects(:publish_exit_status).never
|
117
104
|
runner.publish_exception('general failure', exception, false)
|
118
|
-
_(runner.generate_updates.keys.count).must_equal
|
105
|
+
_(runner.generate_updates.keys.count).must_equal 2
|
119
106
|
end
|
120
107
|
|
121
108
|
it 'publishes exit status if fatal' do
|
@@ -42,11 +42,34 @@ FactoryBot.define do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
factory :task_with_links do
|
46
|
+
# posts_count is declared as a transient attribute and available in
|
47
|
+
# attributes on the factory, as well as the callback via the evaluator
|
48
|
+
transient do
|
49
|
+
locks_count { 1 }
|
50
|
+
resource_id { 1 }
|
51
|
+
resource_type { 'type1' }
|
52
|
+
end
|
53
|
+
|
54
|
+
# the after(:create) yields two values; the user instance itself and the
|
55
|
+
# evaluator, which stores all values from the factory, including transient
|
56
|
+
# attributes; `create_list`'s second argument is the number of records
|
57
|
+
# to create and we make sure the user is associated properly to the post
|
58
|
+
after(:create) do |task, evaluator|
|
59
|
+
create_list(
|
60
|
+
:link,
|
61
|
+
1,
|
62
|
+
task: task,
|
63
|
+
resource_type: evaluator.resource_type,
|
64
|
+
resource_id: evaluator.resource_id
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
45
69
|
factory :task_with_locks do
|
46
70
|
# posts_count is declared as a transient attribute and available in
|
47
71
|
# attributes on the factory, as well as the callback via the evaluator
|
48
72
|
transient do
|
49
|
-
locks_count { 3 }
|
50
73
|
resource_id { 1 }
|
51
74
|
resource_type { 'type1' }
|
52
75
|
end
|
@@ -58,7 +81,7 @@ FactoryBot.define do
|
|
58
81
|
after(:create) do |task, evaluator|
|
59
82
|
create_list(
|
60
83
|
:lock,
|
61
|
-
|
84
|
+
1,
|
62
85
|
task: task,
|
63
86
|
resource_type: evaluator.resource_type,
|
64
87
|
resource_id: evaluator.resource_id
|
@@ -68,11 +91,15 @@ FactoryBot.define do
|
|
68
91
|
end
|
69
92
|
end
|
70
93
|
|
94
|
+
factory :link, :class => ForemanTasks::Link do
|
95
|
+
resource_type { 'Katello::Repository' }
|
96
|
+
resource_id { 1 }
|
97
|
+
association :task, factory: :task_with_links
|
98
|
+
end
|
99
|
+
|
71
100
|
factory :lock, :class => ForemanTasks::Lock do
|
72
|
-
name { 'read' }
|
73
101
|
resource_type { 'Katello::Repository' }
|
74
102
|
resource_id { 1 }
|
75
|
-
exclusive { true }
|
76
103
|
association :task, factory: :task_with_locks
|
77
104
|
end
|
78
105
|
end
|