foreman-tasks 4.1.5 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby_tests.yml +0 -1
  3. data/.rubocop.yml +0 -4
  4. data/.rubocop_todo.yml +0 -2
  5. data/README.md +8 -6
  6. data/app/assets/javascripts/foreman_tasks/trigger_form.js +7 -0
  7. data/app/controllers/foreman_tasks/api/tasks_controller.rb +2 -2
  8. data/app/controllers/foreman_tasks/tasks_controller.rb +2 -2
  9. data/app/graphql/mutations/recurring_logics/cancel.rb +27 -0
  10. data/app/graphql/types/recurring_logic.rb +21 -0
  11. data/app/graphql/types/task.rb +25 -0
  12. data/app/graphql/types/triggering.rb +16 -0
  13. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +4 -1
  14. data/app/lib/actions/helpers/with_continuous_output.rb +1 -1
  15. data/app/lib/actions/proxy_action.rb +2 -12
  16. data/app/lib/actions/trigger_proxy_batch.rb +79 -0
  17. data/app/models/foreman_tasks/recurring_logic.rb +10 -0
  18. data/app/models/foreman_tasks/remote_task.rb +3 -19
  19. data/app/models/foreman_tasks/task.rb +29 -0
  20. data/app/models/foreman_tasks/triggering.rb +14 -4
  21. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
  22. data/app/views/foreman_tasks/layouts/react.html.erb +0 -1
  23. data/app/views/foreman_tasks/recurring_logics/index.html.erb +4 -2
  24. data/app/views/foreman_tasks/task_groups/recurring_logic_task_groups/_recurring_logic_task_group.html.erb +8 -0
  25. data/db/migrate/20210720115251_add_purpose_to_recurring_logic.rb +6 -0
  26. data/extra/foreman-tasks-cleanup.sh +127 -0
  27. data/extra/foreman-tasks-export.sh +121 -0
  28. data/foreman-tasks.gemspec +1 -4
  29. data/lib/foreman_tasks/continuous_output.rb +50 -0
  30. data/lib/foreman_tasks/engine.rb +8 -15
  31. data/lib/foreman_tasks/tasks/export_tasks.rake +29 -8
  32. data/lib/foreman_tasks/version.rb +1 -1
  33. data/lib/foreman_tasks.rb +2 -5
  34. data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
  35. data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
  36. data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
  37. data/package.json +7 -9
  38. data/test/controllers/api/tasks_controller_test.rb +19 -1
  39. data/test/controllers/tasks_controller_test.rb +19 -0
  40. data/test/factories/recurring_logic_factory.rb +7 -1
  41. data/test/graphql/mutations/recurring_logics/cancel_mutation_test.rb +66 -0
  42. data/test/graphql/queries/recurring_logic_test.rb +28 -0
  43. data/test/graphql/queries/recurring_logics_query_test.rb +30 -0
  44. data/test/graphql/queries/task_query_test.rb +33 -0
  45. data/test/graphql/queries/tasks_query_test.rb +31 -0
  46. data/test/support/dummy_proxy_action.rb +6 -0
  47. data/test/unit/actions/proxy_action_test.rb +11 -11
  48. data/test/unit/actions/trigger_proxy_batch_test.rb +59 -0
  49. data/test/unit/remote_task_test.rb +0 -8
  50. data/test/unit/task_test.rb +39 -8
  51. data/test/unit/triggering_test.rb +22 -0
  52. metadata +23 -26
  53. data/test/core/unit/dispatcher_test.rb +0 -43
  54. data/test/core/unit/runner_test.rb +0 -116
  55. data/test/core/unit/task_launcher_test.rb +0 -56
  56. data/test/foreman_tasks_core_test_helper.rb +0 -4
  57. data/test/unit/otp_manager_test.rb +0 -77
@@ -0,0 +1,28 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module Queries
4
+ class RecurringLogicTest < GraphQLQueryTestCase
5
+ let(:query) do
6
+ <<-GRAPHQL
7
+ query($id: String!) {
8
+ recurringLogic(id: $id) {
9
+ id
10
+ cronLine
11
+ }
12
+ }
13
+ GRAPHQL
14
+ end
15
+
16
+ let(:cron_line) { '5 4 3 2 1' }
17
+ let(:recurring_logic) { FactoryBot.create(:recurring_logic, :cron_line => cron_line) }
18
+ let(:global_id) { Foreman::GlobalId.for(recurring_logic) }
19
+ let(:variables) { { id: global_id } }
20
+ let(:data) { result['data']['recurringLogic'] }
21
+
22
+ test "should fetch recurring logic" do
23
+ assert_empty result['errors']
24
+ assert_equal global_id, data['id']
25
+ assert_equal cron_line, data['cronLine']
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module Queries
4
+ class RecurringLogicsTest < GraphQLQueryTestCase
5
+ let(:query) do
6
+ <<-GRAPHQL
7
+ query {
8
+ recurringLogics {
9
+ nodes {
10
+ id
11
+ cronLine
12
+ }
13
+ }
14
+ }
15
+ GRAPHQL
16
+ end
17
+
18
+ let(:data) { result['data']['recurringLogics'] }
19
+
20
+ setup do
21
+ FactoryBot.create_list(:recurring_logic, 2)
22
+ end
23
+
24
+ test "should fetch recurring logics" do
25
+ assert_empty result['errors']
26
+ expected_count = ::ForemanTasks::RecurringLogic.count
27
+ assert_not_equal 0, expected_count
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module Queries
4
+ class TaskQueryTest < GraphQLQueryTestCase
5
+ let(:query) do
6
+ <<-GRAPHQL
7
+ query (
8
+ $id: String!
9
+ ) {
10
+ task(id: $id) {
11
+ id
12
+ action
13
+ result
14
+ }
15
+ }
16
+ GRAPHQL
17
+ end
18
+
19
+ let(:res) { 'inconclusive' }
20
+ let(:task) { FactoryBot.create(:some_task, :result => res) }
21
+
22
+ let(:global_id) { Foreman::GlobalId.for(task) }
23
+ let(:variables) { { id: global_id } }
24
+ let(:data) { result['data']['task'] }
25
+
26
+ test 'should fetch task data' do
27
+ assert_empty result['errors']
28
+
29
+ assert_equal global_id, data['id']
30
+ assert_equal task.result, data['result']
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module Queries
4
+ class TasksQueryTest < GraphQLQueryTestCase
5
+ let(:query) do
6
+ <<-GRAPHQL
7
+ query {
8
+ tasks {
9
+ nodes {
10
+ id
11
+ action
12
+ result
13
+ }
14
+ }
15
+ }
16
+ GRAPHQL
17
+ end
18
+
19
+ let(:data) { result['data']['tasks'] }
20
+
21
+ setup do
22
+ FactoryBot.create_list(:some_task, 2)
23
+ end
24
+
25
+ test "should fetch recurring logics" do
26
+ assert_empty result['errors']
27
+ expected_count = ::ForemanTasks::Task.count
28
+ assert_not_equal 0, expected_count
29
+ end
30
+ end
31
+ end
@@ -36,6 +36,12 @@ module Support
36
36
  def statuses
37
37
  { version: DummyProxyVersion.new('1.21.0') }
38
38
  end
39
+
40
+ def launch_tasks(operation, args = {})
41
+ @log[:trigger_task] << [operation, args]
42
+ @task_triggered.fulfill(true)
43
+ { 'task_id' => @uuid, 'result' => 'success' }
44
+ end
39
45
  end
40
46
 
41
47
  class ProxySelector < ::ForemanTasks::ProxySelector
@@ -11,12 +11,11 @@ module ForemanTasks
11
11
  let(:batch_triggering) { false }
12
12
 
13
13
  before do
14
- Support::DummyProxyAction.any_instance.stubs(:with_batch_triggering?).returns(batch_triggering)
15
14
  Support::DummyProxyAction.reset
16
15
  RemoteTask.any_instance.stubs(:proxy).returns(Support::DummyProxyAction.proxy)
17
16
  Setting.stubs(:[]).with('foreman_tasks_proxy_action_retry_interval')
18
17
  Setting.stubs(:[]).with('foreman_tasks_proxy_action_retry_count')
19
- Setting.stubs(:[]).with('foreman_tasks_proxy_batch_trigger')
18
+ Setting.stubs(:[]).with('foreman_tasks_proxy_batch_trigger').returns(batch_triggering)
20
19
  @action = create_and_plan_action(Support::DummyProxyAction,
21
20
  Support::DummyProxyAction.proxy,
22
21
  'Proxy::DummyAction',
@@ -29,17 +28,18 @@ module ForemanTasks
29
28
  describe 'first run' do
30
29
  it 'triggers the corresponding action on the proxy' do
31
30
  proxy_call = Support::DummyProxyAction.proxy.log[:trigger_task].first
32
- expected_call = ['Proxy::DummyAction',
33
- { 'foo' => 'bar',
34
- 'secrets' => secrets,
35
- 'connection_options' =>
31
+ expected_call = ['single',
32
+ { :action_class => 'Proxy::DummyAction',
33
+ :action_input =>
34
+ { 'foo' => 'bar',
35
+ 'secrets' => secrets,
36
+ 'connection_options' =>
36
37
  { 'retry_interval' => 15, 'retry_count' => 4,
37
38
  'proxy_batch_triggering' => batch_triggering },
38
- 'use_batch_triggering' => batch_triggering,
39
- 'proxy_url' => 'proxy.example.com',
40
- 'proxy_action_name' => 'Proxy::DummyAction',
41
- "proxy_version" => { "major" => 1, "minor" => 21, "patch" => 0 },
42
- 'callback' => { 'task_id' => Support::DummyProxyAction.proxy.uuid, 'step_id' => @action.run_step_id } }]
39
+ 'use_batch_triggering' => batch_triggering,
40
+ 'proxy_url' => 'proxy.example.com',
41
+ 'proxy_action_name' => 'Proxy::DummyAction',
42
+ 'callback' => { 'task_id' => Support::DummyProxyAction.proxy.uuid, 'step_id' => @action.run_step_id } } }]
43
43
  _(proxy_call).must_equal(expected_call)
44
44
  end
45
45
 
@@ -0,0 +1,59 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module ForemanTasks
4
+ class TriggerProxyBatchTest < ActiveSupport::TestCase
5
+ describe Actions::TriggerProxyBatch do
6
+ include ::Dynflow::Testing
7
+
8
+ let(:batch_size) { 20 }
9
+ let(:total_count) { 100 }
10
+ let(:action) { create_and_plan_action(Actions::TriggerProxyBatch, total_count: total_count, batch_size: batch_size) }
11
+ let(:triggered) { run_action(action) }
12
+
13
+ describe 'triggering' do
14
+ it 'doesnt run anything on trigger' do
15
+ Actions::TriggerProxyBatch.any_instance.expects(:trigger_remote_tasks_batch).never
16
+ _(triggered.state).must_equal :suspended
17
+ _(triggered.output[:planned_count]).must_equal 0
18
+ end
19
+
20
+ it 'triggers remote tasks on TriggerNextBatch' do
21
+ Actions::TriggerProxyBatch.any_instance.expects(:trigger_remote_tasks_batch).once
22
+ run_action(triggered, Actions::TriggerProxyBatch::TriggerNextBatch[1])
23
+ end
24
+
25
+ it 'triggers remote tasks on TriggerNextBatch defined number of times' do
26
+ Actions::TriggerProxyBatch.any_instance.expects(:trigger_remote_tasks_batch).twice
27
+ run_action(triggered, Actions::TriggerProxyBatch::TriggerNextBatch[2])
28
+ end
29
+
30
+ it 'triggers the last batch on resume' do
31
+ Actions::TriggerProxyBatch.any_instance.expects(:trigger_remote_tasks_batch).once
32
+ triggered.output[:planned_count] = ((total_count - 1) / batch_size) * batch_size
33
+ run_action(triggered)
34
+ end
35
+ end
36
+
37
+ describe '#trigger_remote_tasks_batch' do
38
+ let(:proxy_operation_name) { 'ansible_runner' }
39
+ let(:grouped_remote_batch) { Array.new(batch_size).map { |i| mock("RemoteTask#{i}") } }
40
+ let(:remote_tasks) do
41
+ m = mock('RemoteTaskARScope')
42
+ m.stubs(pending: m, order: m)
43
+ m.stubs(group_by: { proxy_operation_name => grouped_remote_batch })
44
+ m
45
+ end
46
+
47
+ it 'fetches batch_size of tasks and triggers them' do
48
+ remote_tasks.expects(:first).with(batch_size).returns(remote_tasks)
49
+ remote_tasks.expects(:size).returns(batch_size)
50
+ triggered.expects(:remote_tasks).returns(remote_tasks)
51
+ ForemanTasks::RemoteTask.expects(:batch_trigger).with(proxy_operation_name, grouped_remote_batch)
52
+
53
+ triggered.trigger_remote_tasks_batch
54
+ _(triggered.output[:planned_count]).must_equal(batch_size)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -28,14 +28,6 @@ module ForemanTasks
28
28
  _(remote_task.remote_task_id).must_equal((remote_task.id + 5).to_s)
29
29
  end
30
30
  end
31
-
32
- it 'fallbacks to old way when batch trigger gets 404' do
33
- fake_proxy = mock
34
- fake_proxy.expects(:launch_tasks).raises(RestClient::NotFound.new)
35
- remote_tasks.first.expects(:proxy).returns(fake_proxy)
36
- remote_tasks.each { |task| task.expects(:trigger) }
37
- RemoteTask.batch_trigger('a_operation', remote_tasks)
38
- end
39
31
  end
40
32
  end
41
33
  end
@@ -296,12 +296,12 @@ class TasksTest < ActiveSupport::TestCase
296
296
  end
297
297
 
298
298
  describe 'search for resource_ids' do
299
- it 'finds tasks' do
300
- label = 'label1'
301
- resource_ids = [1, 2]
302
- resource_type = 'restype1'
299
+ label = 'label1'
300
+ resource_ids = [1, 2]
301
+ resource_type = 'restype1'
303
302
 
304
- task1_old = FactoryBot.create(
303
+ let(:task1_old) do
304
+ FactoryBot.create(
305
305
  :task_with_links,
306
306
  started_at: '2019-10-01 11:15:55',
307
307
  ended_at: '2019-10-01 11:15:57',
@@ -309,7 +309,9 @@ class TasksTest < ActiveSupport::TestCase
309
309
  label: label,
310
310
  resource_type: resource_type
311
311
  )
312
- task1_new = FactoryBot.create(
312
+ end
313
+ let(:task1_new) do
314
+ FactoryBot.create(
313
315
  :task_with_links,
314
316
  started_at: '2019-10-02 11:15:55',
315
317
  ended_at: '2019-10-02 11:15:57',
@@ -317,7 +319,9 @@ class TasksTest < ActiveSupport::TestCase
317
319
  label: label,
318
320
  resource_type: resource_type
319
321
  )
320
- task2 = FactoryBot.create(
322
+ end
323
+ let(:task2) do
324
+ FactoryBot.create(
321
325
  :task_with_links,
322
326
  started_at: '2019-10-03 11:15:55',
323
327
  ended_at: '2019-10-03 11:15:57',
@@ -325,7 +329,9 @@ class TasksTest < ActiveSupport::TestCase
325
329
  label: label,
326
330
  resource_type: resource_type
327
331
  )
328
- task3 = FactoryBot.create(
332
+ end
333
+ let(:task3) do
334
+ FactoryBot.create(
329
335
  :task_with_links,
330
336
  started_at: '2019-10-03 11:15:55',
331
337
  ended_at: '2019-10-03 11:15:57',
@@ -333,6 +339,13 @@ class TasksTest < ActiveSupport::TestCase
333
339
  label: label,
334
340
  resource_type: 'another_type'
335
341
  )
342
+ end
343
+
344
+ it 'finds tasks' do
345
+ task1_old
346
+ task1_new
347
+ task2
348
+ task3
336
349
 
337
350
  result = ForemanTasks::Task.search_for(
338
351
  "resource_id ^ (#{resource_ids.join(',')}) and resource_type = #{resource_type}"
@@ -343,5 +356,23 @@ class TasksTest < ActiveSupport::TestCase
343
356
  assert_includes result, task2
344
357
  assert_not_includes result, task3
345
358
  end
359
+
360
+ it 'finds latest task for each resource_id' do
361
+ task1_old
362
+ task1_new
363
+ task2
364
+ task3
365
+
366
+ result = ForemanTasks::Task.latest_tasks_by_resource_ids(
367
+ label,
368
+ resource_type,
369
+ resource_ids
370
+ )
371
+ assert_equal 2, result.length
372
+ assert_equal resource_ids, result.keys.sort
373
+ assert_equal task1_new, result[1]
374
+ assert_equal task2, result[2]
375
+ assert_not_includes result.values, task3
376
+ end
346
377
  end
347
378
  end
@@ -19,6 +19,28 @@ class TriggeringTest < ActiveSupport::TestCase
19
19
  triggering.recurring_logic.stubs(:valid?).returns(false)
20
20
  _(triggering).wont_be :valid?
21
21
  end
22
+
23
+ it 'is valid when recurring logic has purpose' do
24
+ logic = FactoryBot.build(:recurring_logic, :purpose => 'test', :state => 'active')
25
+ triggering = FactoryBot.build(:triggering, :recurring_logic => logic, :mode => :recurring, :input_type => :cronline, :cronline => '* * * * *')
26
+ _(triggering).must_be :valid?
27
+ end
28
+
29
+ it 'is invalid when recurring logic with given purpose exists' do
30
+ FactoryBot.create(:recurring_logic, :purpose => 'test', :state => 'active')
31
+ logic = FactoryBot.build(:recurring_logic, :purpose => 'test', :state => 'active')
32
+ triggering = FactoryBot.build(:triggering, :recurring_logic => logic, :mode => :recurring, :input_type => :cronline, :cronline => '* * * * *')
33
+ _(triggering).wont_be :valid?
34
+ end
35
+
36
+ it 'is valid when recurring logic with given purpose exists and is not active or disabled' do
37
+ ['finished', 'cancelled', 'failed'].each do |item|
38
+ FactoryBot.create(:recurring_logic, :purpose => 'test', :state => item)
39
+ end
40
+ logic = FactoryBot.build(:recurring_logic, :purpose => 'test')
41
+ triggering = FactoryBot.build(:triggering, :recurring_logic => logic, :mode => :recurring, :input_type => :cronline, :cronline => '* * * * *')
42
+ _(triggering).must_be :valid?
43
+ end
22
44
  end
23
45
 
24
46
  it 'cannot have mode set to arbitrary value' 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: 4.1.5
4
+ version: 5.2.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: 2021-08-31 00:00:00.000000000 Z
11
+ date: 2021-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dynflow
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.2.3
27
- - !ruby/object:Gem::Dependency
28
- name: foreman-tasks-core
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: get_process_mem
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +133,10 @@ files:
147
133
  - app/controllers/foreman_tasks/react_controller.rb
148
134
  - app/controllers/foreman_tasks/recurring_logics_controller.rb
149
135
  - app/controllers/foreman_tasks/tasks_controller.rb
136
+ - app/graphql/mutations/recurring_logics/cancel.rb
137
+ - app/graphql/types/recurring_logic.rb
138
+ - app/graphql/types/task.rb
139
+ - app/graphql/types/triggering.rb
150
140
  - app/helpers/foreman_tasks/foreman_tasks_helper.rb
151
141
  - app/helpers/foreman_tasks/tasks_helper.rb
152
142
  - app/lib/actions/action_with_sub_plans.rb
@@ -176,6 +166,7 @@ files:
176
166
  - app/lib/actions/proxy_action.rb
177
167
  - app/lib/actions/recurring_action.rb
178
168
  - app/lib/actions/serializers/active_record_serializer.rb
169
+ - app/lib/actions/trigger_proxy_batch.rb
179
170
  - app/lib/foreman_tasks/concerns/polling_action_extensions.rb
180
171
  - app/lib/proxy_api/foreman_dynflow/dynflow_proxy.rb
181
172
  - app/models/foreman_tasks/concerns/action_subject.rb
@@ -259,6 +250,7 @@ files:
259
250
  - db/migrate/20200517215015_rename_bookmarks_controller.rb
260
251
  - db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb
261
252
  - db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb
253
+ - db/migrate/20210720115251_add_purpose_to_recurring_logic.rb
262
254
  - db/seeds.d/20-foreman_tasks_permissions.rb
263
255
  - db/seeds.d/30-notification_blueprints.rb
264
256
  - db/seeds.d/60-dynflow_proxy_feature.rb
@@ -267,12 +259,15 @@ files:
267
259
  - deploy/foreman-tasks.sysconfig
268
260
  - extra/dynflow-debug.sh
269
261
  - extra/dynflow-executor.example
262
+ - extra/foreman-tasks-cleanup.sh
263
+ - extra/foreman-tasks-export.sh
270
264
  - foreman-tasks.gemspec
271
265
  - gemfile.d/foreman-tasks.rb
272
266
  - lib/foreman-tasks.rb
273
267
  - lib/foreman_tasks.rb
274
268
  - lib/foreman_tasks/authorizer_ext.rb
275
269
  - lib/foreman_tasks/cleaner.rb
270
+ - lib/foreman_tasks/continuous_output.rb
276
271
  - lib/foreman_tasks/dynflow.rb
277
272
  - lib/foreman_tasks/dynflow/configuration.rb
278
273
  - lib/foreman_tasks/dynflow/console_authorizer.rb
@@ -306,14 +301,15 @@ files:
306
301
  - test/controllers/api/tasks_controller_test.rb
307
302
  - test/controllers/recurring_logics_controller_test.rb
308
303
  - test/controllers/tasks_controller_test.rb
309
- - test/core/unit/dispatcher_test.rb
310
- - test/core/unit/runner_test.rb
311
- - test/core/unit/task_launcher_test.rb
312
304
  - test/factories/recurring_logic_factory.rb
313
305
  - test/factories/task_factory.rb
314
306
  - test/factories/triggering_factory.rb
315
- - test/foreman_tasks_core_test_helper.rb
316
307
  - test/foreman_tasks_test_helper.rb
308
+ - test/graphql/mutations/recurring_logics/cancel_mutation_test.rb
309
+ - test/graphql/queries/recurring_logic_test.rb
310
+ - test/graphql/queries/recurring_logics_query_test.rb
311
+ - test/graphql/queries/task_query_test.rb
312
+ - test/graphql/queries/tasks_query_test.rb
317
313
  - test/helpers/foreman_tasks/foreman_tasks_helper_test.rb
318
314
  - test/helpers/foreman_tasks/tasks_helper_test.rb
319
315
  - test/lib/actions/middleware/keep_current_request_id_test.rb
@@ -332,11 +328,11 @@ files:
332
328
  - test/unit/actions/bulk_action_test.rb
333
329
  - test/unit/actions/proxy_action_test.rb
334
330
  - test/unit/actions/recurring_action_test.rb
331
+ - test/unit/actions/trigger_proxy_batch_test.rb
335
332
  - test/unit/cleaner_test.rb
336
333
  - test/unit/config/environment.rb
337
334
  - test/unit/dynflow_console_authorizer_test.rb
338
335
  - test/unit/locking_test.rb
339
- - test/unit/otp_manager_test.rb
340
336
  - test/unit/proxy_selector_test.rb
341
337
  - test/unit/recurring_logic_test.rb
342
338
  - test/unit/remote_task_test.rb
@@ -620,14 +616,15 @@ test_files:
620
616
  - test/controllers/api/tasks_controller_test.rb
621
617
  - test/controllers/recurring_logics_controller_test.rb
622
618
  - test/controllers/tasks_controller_test.rb
623
- - test/core/unit/dispatcher_test.rb
624
- - test/core/unit/runner_test.rb
625
- - test/core/unit/task_launcher_test.rb
626
619
  - test/factories/recurring_logic_factory.rb
627
620
  - test/factories/task_factory.rb
628
621
  - test/factories/triggering_factory.rb
629
- - test/foreman_tasks_core_test_helper.rb
630
622
  - test/foreman_tasks_test_helper.rb
623
+ - test/graphql/mutations/recurring_logics/cancel_mutation_test.rb
624
+ - test/graphql/queries/recurring_logic_test.rb
625
+ - test/graphql/queries/recurring_logics_query_test.rb
626
+ - test/graphql/queries/task_query_test.rb
627
+ - test/graphql/queries/tasks_query_test.rb
631
628
  - test/helpers/foreman_tasks/foreman_tasks_helper_test.rb
632
629
  - test/helpers/foreman_tasks/tasks_helper_test.rb
633
630
  - test/lib/actions/middleware/keep_current_request_id_test.rb
@@ -646,11 +643,11 @@ test_files:
646
643
  - test/unit/actions/bulk_action_test.rb
647
644
  - test/unit/actions/proxy_action_test.rb
648
645
  - test/unit/actions/recurring_action_test.rb
646
+ - test/unit/actions/trigger_proxy_batch_test.rb
649
647
  - test/unit/cleaner_test.rb
650
648
  - test/unit/config/environment.rb
651
649
  - test/unit/dynflow_console_authorizer_test.rb
652
650
  - test/unit/locking_test.rb
653
- - test/unit/otp_manager_test.rb
654
651
  - test/unit/proxy_selector_test.rb
655
652
  - test/unit/recurring_logic_test.rb
656
653
  - test/unit/remote_task_test.rb
@@ -1,43 +0,0 @@
1
- require 'foreman_tasks_core_test_helper'
2
- require 'foreman_tasks/test_helpers'
3
- require 'foreman_tasks_core/runner'
4
-
5
- module ForemanTasksCore
6
- module Runner
7
- describe Dispatcher::RunnerActor do
8
- include ForemanTasks::TestHelpers::WithInThreadExecutor
9
-
10
- let(:dispatcher) { Dispatcher.instance }
11
- let(:suspended_action) { mock }
12
- let(:runner) { mock.tap { |r| r.stubs(:id) } }
13
- let(:clock) { ForemanTasks.dynflow.world.clock }
14
- let(:logger) { mock.tap { |l| l.stubs(:debug) } }
15
- let(:actor) do
16
- Dispatcher::RunnerActor.new dispatcher, suspended_action, runner, clock, logger
17
- end
18
-
19
- it 'delivers all updates to actions' do
20
- targets = (0..2).map { mock }.each_with_index { |mock, index| mock.expects(:<<).with(index) }
21
- updates = targets.each_with_index.reduce({}) { |acc, (cur, index)| acc.merge(cur => index) }
22
- runner.expects(:run_refresh).returns(updates)
23
- actor.expects(:plan_next_refresh)
24
- actor.refresh_runner
25
- end
26
-
27
- it 'plans next refresh' do
28
- runner.expects(:run_refresh).returns({})
29
- actor.expects(:plan_next_refresh)
30
- actor.refresh_runner
31
- end
32
-
33
- it 'does not plan next resfresh if done' do
34
- update = Update.new(nil, 0)
35
- suspended_action.expects(:<<).with(update)
36
- runner.expects(:run_refresh).returns(suspended_action => update)
37
- dispatcher.expects(:finish)
38
- dispatcher.ticker.expects(:tell).never
39
- actor.refresh_runner
40
- end
41
- end
42
- end
43
- end
@@ -1,116 +0,0 @@
1
- require 'foreman_tasks_core_test_helper'
2
- require 'foreman_tasks/test_helpers'
3
- require 'foreman_tasks_core/runner'
4
- require 'ostruct'
5
-
6
- module ForemanTasksCore
7
- module Runner
8
- class RunnerTest < ActiveSupport::TestCase
9
- include ForemanTasks::TestHelpers::WithInThreadExecutor
10
-
11
- describe Base do
12
- let(:suspended_action) { Class.new }
13
- let(:runner) { Base.new suspended_action: suspended_action }
14
-
15
- describe '#generate_updates' do
16
- it 'returns empty hash when there are no outputs' do
17
- _(runner.generate_updates).must_be :empty?
18
- end
19
-
20
- it 'returns a hash with outputs' do
21
- message = 'a message'
22
- type = 'stdout'
23
- runner.publish_data(message, type)
24
- updates = runner.generate_updates
25
- _(updates.keys).must_equal [suspended_action]
26
- update = updates.values.first
27
- _(update.exit_status).must_be :nil?
28
- _(update.continuous_output.raw_outputs.count).must_equal 1
29
- end
30
-
31
- it 'works in compatibility mode' do
32
- runner = Base.new
33
- message = 'a message'
34
- type = 'stdout'
35
- runner.publish_data(message, type)
36
- updates = runner.generate_updates
37
- _(updates.keys).must_equal [nil]
38
- update = updates.values.first
39
- _(update.exit_status).must_be :nil?
40
- _(update.continuous_output.raw_outputs.count).must_equal 1
41
- end
42
- end
43
- end
44
-
45
- describe Parent do
46
- let(:suspended_action) { ::Dynflow::Action::Suspended.allocate }
47
- let(:runner) { Parent.new targets, suspended_action: suspended_action }
48
- let(:targets) do
49
- { 'foo' => { 'execution_plan_id' => '123', 'run_step_id' => 2 },
50
- 'bar' => { 'execution_plan_id' => '456', 'run_step_id' => 2 } }
51
- end
52
-
53
- describe '#initialize_continuous_outputs' do
54
- it 'initializes outputs for targets and parent' do
55
- outputs = runner.initialize_continuous_outputs
56
- _(outputs.keys.count).must_equal 2
57
- outputs.values.each { |output| _(output).must_be_instance_of ContinuousOutput }
58
- end
59
- end
60
-
61
- describe '#generate_updates' do
62
- it 'returns only updates for hosts with pending outputs' do
63
- _(runner.generate_updates).must_equal({})
64
- runner.publish_data_for('foo', 'something', 'something')
65
- updates = runner.generate_updates
66
- _(updates.keys.count).must_equal 1
67
- end
68
-
69
- it 'works without compatibility mode' do
70
- runner.broadcast_data('something', 'stdout')
71
- updates = runner.generate_updates
72
- _(updates.keys.count).must_equal 2
73
- updates.keys.each do |key|
74
- _(key).must_be_instance_of ::Dynflow::Action::Suspended
75
- end
76
- end
77
- end
78
-
79
- describe '#publish_data_for' do
80
- it 'publishes data for a single host' do
81
- runner.publish_data_for('foo', 'message', 'stdout')
82
- _(runner.generate_updates.keys.count).must_equal 1
83
- end
84
- end
85
-
86
- describe '#broadcast_data' do
87
- it 'publishes data for all hosts' do
88
- runner.broadcast_data('message', 'stdout')
89
- _(runner.generate_updates.keys.count).must_equal 2
90
- end
91
- end
92
-
93
- describe '#publish_exception' do
94
- let(:exception) do
95
- exception = RuntimeError.new
96
- exception.stubs(:backtrace).returns([])
97
- exception
98
- end
99
-
100
- before { runner.logger.stubs(:error) }
101
-
102
- it 'broadcasts the exception to all targets' do
103
- runner.expects(:publish_exit_status).never
104
- runner.publish_exception('general failure', exception, false)
105
- _(runner.generate_updates.keys.count).must_equal 2
106
- end
107
-
108
- it 'publishes exit status if fatal' do
109
- runner.expects(:publish_exit_status)
110
- runner.publish_exception('general failure', exception, true)
111
- end
112
- end
113
- end
114
- end
115
- end
116
- end