foreman_remote_execution 14.0.2 → 14.1.0

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/job_invocations_controller.rb +34 -17
  3. data/app/helpers/remote_execution_helper.rb +2 -2
  4. data/app/lib/actions/remote_execution/proxy_action.rb +10 -5
  5. data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
  6. data/app/lib/actions/remote_execution/template_invocation_progress_logging.rb +2 -3
  7. data/app/views/api/v2/job_invocations/hosts.json.rabl +15 -0
  8. data/config/routes.rb +1 -0
  9. data/db/migrate/20240312133027_extend_template_invocation_events.rb +19 -0
  10. data/lib/foreman_remote_execution/version.rb +1 -1
  11. data/webpack/JobInvocationDetail/JobInvocationActions.js +1 -1
  12. data/webpack/JobInvocationDetail/JobInvocationConstants.js +84 -0
  13. data/webpack/JobInvocationDetail/JobInvocationDetail.scss +0 -1
  14. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +210 -0
  15. data/webpack/JobInvocationDetail/JobInvocationSelectors.js +2 -2
  16. data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +5 -1
  17. data/webpack/JobInvocationDetail/__tests__/fixtures.js +9 -0
  18. data/webpack/JobInvocationDetail/index.js +56 -34
  19. data/webpack/__mocks__/foremanReact/components/HostDetails/DetailsCard/DefaultLoaderEmptyState.js +1 -2
  20. data/webpack/react_app/components/RecentJobsCard/JobStatusIcon.js +38 -7
  21. data/webpack/react_app/components/RecentJobsCard/constants.js +4 -0
  22. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap +1 -1
  23. data/webpack/react_app/components/TargetingHosts/components/HostStatus.js +6 -6
  24. metadata +6 -94
  25. data/.babelrc.js +0 -3
  26. data/.eslintignore +0 -3
  27. data/.eslintrc +0 -13
  28. data/.github/workflows/js_ci.yml +0 -32
  29. data/.github/workflows/release.yml +0 -16
  30. data/.github/workflows/ruby_ci.yml +0 -19
  31. data/.gitignore +0 -19
  32. data/.packit.yaml +0 -45
  33. data/.prettierrc +0 -4
  34. data/.rubocop.yml +0 -105
  35. data/.rubocop_todo.yml +0 -516
  36. data/.tx/config +0 -10
  37. data/Gemfile +0 -5
  38. data/app/mailers/.gitkeep +0 -0
  39. data/app/views/dashboard/.gitkeep +0 -0
  40. data/foreman_remote_execution.gemspec +0 -33
  41. data/jsconfig.json +0 -8
  42. data/test/benchmark/run_hosts_job_benchmark.rb +0 -70
  43. data/test/benchmark/targeting_benchmark.rb +0 -31
  44. data/test/factories/foreman_remote_execution_factories.rb +0 -147
  45. data/test/functional/api/v2/foreign_input_sets_controller_test.rb +0 -58
  46. data/test/functional/api/v2/job_invocations_controller_test.rb +0 -446
  47. data/test/functional/api/v2/job_templates_controller_test.rb +0 -110
  48. data/test/functional/api/v2/registration_controller_test.rb +0 -73
  49. data/test/functional/api/v2/remote_execution_features_controller_test.rb +0 -34
  50. data/test/functional/api/v2/template_invocations_controller_test.rb +0 -33
  51. data/test/functional/cockpit_controller_test.rb +0 -16
  52. data/test/functional/job_invocations_controller_test.rb +0 -132
  53. data/test/functional/job_templates_controller_test.rb +0 -31
  54. data/test/functional/ui_job_wizard_controller_test.rb +0 -16
  55. data/test/graphql/mutations/job_invocations/create_test.rb +0 -58
  56. data/test/graphql/queries/job_invocation_query_test.rb +0 -31
  57. data/test/graphql/queries/job_invocations_query_test.rb +0 -35
  58. data/test/helpers/remote_execution_helper_test.rb +0 -46
  59. data/test/support/remote_execution_helper.rb +0 -5
  60. data/test/test_plugin_helper.rb +0 -9
  61. data/test/unit/actions/run_host_job_test.rb +0 -115
  62. data/test/unit/actions/run_hosts_job_test.rb +0 -214
  63. data/test/unit/api_params_test.rb +0 -25
  64. data/test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb +0 -29
  65. data/test/unit/concerns/host_extensions_test.rb +0 -219
  66. data/test/unit/concerns/nic_extensions_test.rb +0 -9
  67. data/test/unit/execution_task_status_mapper_test.rb +0 -92
  68. data/test/unit/input_template_renderer_test.rb +0 -503
  69. data/test/unit/job_invocation_composer_test.rb +0 -974
  70. data/test/unit/job_invocation_report_template_test.rb +0 -60
  71. data/test/unit/job_invocation_test.rb +0 -232
  72. data/test/unit/job_template_effective_user_test.rb +0 -37
  73. data/test/unit/job_template_test.rb +0 -316
  74. data/test/unit/remote_execution_feature_test.rb +0 -86
  75. data/test/unit/remote_execution_provider_test.rb +0 -298
  76. data/test/unit/renderer_scope_input_test.rb +0 -49
  77. data/test/unit/targeting_test.rb +0 -206
  78. data/test/unit/template_invocation_input_value_test.rb +0 -38
@@ -1,214 +0,0 @@
1
- require 'test_plugin_helper'
2
- require 'securerandom'
3
-
4
- module ForemanRemoteExecution
5
- class RunHostsJobTest < ActiveSupport::TestCase
6
- include Dynflow::Testing
7
-
8
- # Adding run_step_id wich is needed in RunHostsJob as a quick fix
9
- # it will be added to dynflow in the future see https://github.com/Dynflow/dynflow/pull/391
10
- # rubocop:disable Style/ClassAndModuleChildren
11
- class Dynflow::Testing::DummyPlannedAction
12
- def run_step_id
13
- Dynflow::Testing.get_id
14
- end
15
- end
16
- # rubocop:enable Style/ClassAndModuleChildren
17
-
18
- let(:host) { FactoryBot.create(:host, :with_execution) }
19
- let(:proxy) { host.remote_execution_proxies('SSH')[:subnet].first }
20
- let(:targeting) { FactoryBot.create(:targeting, :search_query => "name = #{host.name}", :user => User.current) }
21
- let(:job_invocation) do
22
- FactoryBot.build(:job_invocation, :with_template).tap do |invocation|
23
- invocation.targeting = targeting
24
- invocation.description = 'Some short description'
25
- invocation.password = 'changeme'
26
- invocation.key_passphrase = 'changemetoo'
27
- invocation.effective_user_password = 'sudopassword'
28
- invocation.save
29
- end
30
- end
31
-
32
- let(:uuid) { SecureRandom.uuid }
33
- let(:task) do
34
- OpenStruct.new(:id => uuid).tap do |o|
35
- o.stubs(:add_missing_task_groups)
36
- o.stubs(:task_groups).returns([])
37
- o.stubs(:pending?).returns(true)
38
- end
39
- end
40
- let(:action) do
41
- create_action(Actions::RemoteExecution::RunHostsJob).tap do |action|
42
- action.expects(:action_subject).with(job_invocation, job_features: [])
43
- ForemanTasks::Task::DynflowTask.stubs(:where).returns(mock.tap { |m| m.stubs(:first! => task) })
44
- end
45
- end
46
- let(:planned) do
47
- plan_action action, job_invocation
48
- end
49
-
50
- let(:delayed) do
51
- action.delay({ :start_at => Time.now.getlocal }, job_invocation)
52
- action
53
- end
54
-
55
- before do
56
- ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.stubs(:tasks_count).returns(0)
57
- User.current = users :admin
58
- action
59
- end
60
-
61
- context 'targeting resolving' do
62
- it 'resolves dynamic targeting in plan' do
63
- targeting.targeting_type = 'dynamic_query'
64
- assert_not targeting.resolved?
65
- delayed
66
- assert_not targeting.resolved?
67
- planned
68
- assert_includes targeting.hosts, host
69
- end
70
-
71
- it 'resolves the hosts on static targeting in delay' do
72
- assert_not targeting.resolved?
73
- delayed
74
- assert_includes targeting.hosts, host
75
- # Verify Targeting#resolve_hosts! won't be hit again
76
- targeting.expects(:resolve_hosts!).never
77
- planned
78
- end
79
-
80
- it 'resolves the hosts on static targeting in plan phase if not resolved yet' do
81
- planned
82
- assert_includes targeting.hosts, host
83
- end
84
- end
85
-
86
- it 'triggers the RunHostJob actions on the resolved hosts in run phase' do
87
- planned.expects(:output).at_most(5).returns(:planned_count => 0)
88
- planned.expects(:trigger).with { |*args| args[0] == Actions::RemoteExecution::RunHostJob }
89
- planned.create_sub_plans
90
- end
91
-
92
- it 'uses the BindJobInvocation middleware' do
93
- planned
94
- assert_equal job_invocation.task_id, uuid
95
- end
96
-
97
- # In plan phase this is handled by #action_subject
98
- # which is expected in tests
99
- it 'sets input in delay phase when delayed' do
100
- job_invocation_hash = delayed.input[:job_invocation]
101
- assert_equal job_invocation_hash['id'], job_invocation.id
102
- assert_equal job_invocation_hash['name'], job_invocation.job_category
103
- assert_equal job_invocation_hash['description'], job_invocation.description
104
- planned # To make the expectations happy
105
- end
106
-
107
- describe '#proxy_batch_size' do
108
- it 'defaults to Setting[foreman_tasks_proxy_batch_size]' do
109
- Setting.expects(:[]).with('foreman_tasks_proxy_batch_size').returns(14)
110
- planned
111
- assert_equal 14, planned.proxy_batch_size
112
- end
113
-
114
- it 'gets the provider value' do
115
- provider = mock('provider')
116
- provider.expects(:proxy_batch_size).returns(15)
117
- JobTemplate.any_instance.expects(:provider).returns(provider)
118
-
119
- assert_equal 15, planned.proxy_batch_size
120
- end
121
- end
122
-
123
- describe 'concurrency control' do
124
- let(:level) { 5 }
125
-
126
- it 'can be disabled' do
127
- assert_nil planned.concurrency_limit
128
- end
129
-
130
- it 'can limit concurrency level' do
131
- job_invocation.expects(:concurrency_level).twice.returns(level)
132
- assert_equal level, planned.concurrency_limit
133
- end
134
- end
135
-
136
- describe 'notifications' do
137
- it 'creates drawer notification on succeess' do
138
- blueprint = planned.job_invocation.build_notification
139
- blueprint.expects(:deliver!)
140
- planned.job_invocation.expects(:build_notification).returns(blueprint)
141
- planned.notify_on_success(nil)
142
- end
143
-
144
- it 'creates drawer notification on failure' do
145
- blueprint = planned.job_invocation.build_notification
146
- blueprint.expects(:deliver!)
147
- planned.job_invocation.expects(:build_notification).returns(blueprint)
148
- planned.notify_on_failure(nil)
149
- end
150
-
151
- describe 'ignoring drawer notification' do
152
- before do
153
- blueprint = planned.job_invocation.build_notification
154
- blueprint.expects(:deliver!)
155
- planned.job_invocation.expects(:build_notification).returns(blueprint)
156
- end
157
-
158
- let(:mail) do
159
- object = mock
160
- object.stubs(:deliver_now)
161
- object
162
- end
163
-
164
- describe 'for user subscribed to all' do
165
- before do
166
- planned.expects(:mail_notification_preference).returns(UserMailNotification.new(:interval => RexMailNotification::ALL_JOBS))
167
- end
168
-
169
- it 'sends the mail notification on success' do
170
- RexJobMailer.expects(:job_finished).returns(mail)
171
- planned.notify_on_success(nil)
172
- end
173
-
174
- it 'sends the mail notification on failure' do
175
- RexJobMailer.expects(:job_finished).returns(mail)
176
- planned.notify_on_failure(nil)
177
- end
178
- end
179
-
180
- describe 'for user subscribed to failures' do
181
- before do
182
- planned.expects(:mail_notification_preference).returns(UserMailNotification.new(:interval => RexMailNotification::FAILED_JOBS))
183
- end
184
-
185
- it 'it does not send the mail notification on success' do
186
- RexJobMailer.expects(:job_finished).never
187
- planned.notify_on_success(nil)
188
- end
189
-
190
- it 'sends the mail notification on failure' do
191
- RexJobMailer.expects(:job_finished).returns(mail)
192
- planned.notify_on_failure(nil)
193
- end
194
- end
195
-
196
- describe 'for user subscribed to successful jobs' do
197
- before do
198
- planned.expects(:mail_notification_preference).returns(UserMailNotification.new(:interval => RexMailNotification::SUCCEEDED_JOBS))
199
- end
200
-
201
- it 'sends the mail notification on success' do
202
- RexJobMailer.expects(:job_finished).returns(mail)
203
- planned.notify_on_success(nil)
204
- end
205
-
206
- it 'does not send the mail notification on failure' do
207
- RexJobMailer.expects(:job_finished).never
208
- planned.notify_on_failure(nil)
209
- end
210
- end
211
- end
212
- end
213
- end
214
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_plugin_helper'
4
-
5
- class ApiParamsTest < ActiveSupport::TestCase
6
- describe '#format_datetime' do
7
- let(:params) { JobInvocationComposer::ApiParams.allocate }
8
-
9
- it 'leaves empty string as is' do
10
- assert_equal params.send(:format_datetime, ''), ''
11
- end
12
-
13
- it 'honors explicitly supplied time zone' do
14
- Time.use_zone(ActiveSupport::TimeZone['America/New_York']) do
15
- assert_equal '2022-07-08 08:53', params.send(:format_datetime, '2022-07-08 12:53:20 UTC')
16
- end
17
- end
18
-
19
- it 'implicitly honors current user\'s time zone' do
20
- Time.use_zone(ActiveSupport::TimeZone['America/New_York']) do
21
- assert_equal '2022-07-08 12:53', params.send(:format_datetime, '2022-07-08 12:53:20')
22
- end
23
- end
24
- end
25
- end
@@ -1,29 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class ForemanRemoteExecutionForemanTasksCleanerExtensionsTest < ActiveSupport::TestCase
4
- # Apply the same stubbing as in foreman-tasks
5
- before do
6
- # To stop dynflow from backing up actions, execution_plans and steps
7
- ForemanTasks.dynflow.world.persistence.adapter.stubs(:backup_to_csv)
8
- ForemanTasks::Cleaner.any_instance.stubs(:say) # Make the tests silent
9
- # Hack to make the tests pass due to ActiveRecord shenanigans
10
- ForemanTasks::Cleaner.any_instance.stubs(:delete_orphaned_dynflow_tasks)
11
- end
12
-
13
- it 'tries to delete associated job invocations' do
14
- job = FactoryBot.create(:job_invocation, :with_task)
15
- ForemanTasks::Cleaner.new(:filter => "id = #{job.task.id}").delete
16
- assert_empty JobInvocation.where(:id => job.id)
17
- end
18
-
19
- it 'removes orphaned job invocations' do
20
- job = FactoryBot.create(:job_invocation, :with_task)
21
- assert_equal 1, JobInvocation.where(:id => job.id).count
22
- job.task.delete
23
- job.reload
24
- assert_nil job.task
25
- refute_nil job.task_id
26
- ForemanTasks::Cleaner.new(:filter => '').delete
27
- assert_empty JobInvocation.where(:id => job.id)
28
- end
29
- end
@@ -1,219 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class ForemanRemoteExecutionHostExtensionsTest < ActiveSupport::TestCase
4
- let(:provider) { 'SSH' }
5
-
6
- before { User.current = FactoryBot.build(:user, :admin) }
7
- after { User.current = nil }
8
-
9
- describe 'ssh specific params' do
10
- let(:host) { FactoryBot.create(:host, :with_execution) }
11
- let(:sshkey) { 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQ foo@example.com' }
12
-
13
- before do
14
- SmartProxy.any_instance.stubs(:pubkey).returns(sshkey)
15
- Setting[:remote_execution_ssh_user] = 'root'
16
- Setting[:remote_execution_effective_user_method] = 'sudo'
17
- end
18
-
19
- it 'has ssh user in the parameters' do
20
- assert_equal Setting[:remote_execution_ssh_user], host.host_param('remote_execution_ssh_user')
21
- end
22
-
23
- it 'can override ssh user' do
24
- host.host_parameters << FactoryBot.create(:host_parameter, :host => host, :name => 'remote_execution_ssh_user', :value => 'amy')
25
- assert_equal 'amy', host.host_param('remote_execution_ssh_user')
26
- end
27
-
28
- it 'has effective user method in the parameters' do
29
- assert_equal Setting[:remote_execution_effective_user_method], host.host_param('remote_execution_effective_user_method')
30
- end
31
-
32
- it 'can override effective user method' do
33
- host.host_parameters << FactoryBot.create(:host_parameter, :host => host, :name => 'remote_execution_effective_user_method', :value => 'su')
34
- assert_equal 'su', host.host_param('remote_execution_effective_user_method')
35
- end
36
-
37
- it 'has ssh keys in the parameters' do
38
- assert_includes host.remote_execution_ssh_keys, sshkey
39
- end
40
-
41
- it 'merges ssh keys from host parameters and proxies' do
42
- key = 'ssh-rsa not-even-a-key something@somewhere.com'
43
- host.host_parameters << FactoryBot.create(:host_parameter, :host => host, :name => 'remote_execution_ssh_keys', :value => [key])
44
- assert_includes host.host_param('remote_execution_ssh_keys'), key
45
- assert_includes host.host_param('remote_execution_ssh_keys'), sshkey
46
- end
47
-
48
- it 'merges ssh key as a string from host parameters and proxies' do
49
- key = 'ssh-rsa not-even-a-key something@somewhere.com'
50
- host.host_parameters << FactoryBot.create(:host_parameter, :host => host, :name => 'remote_execution_ssh_keys', :value => key)
51
- assert_includes host.host_param('remote_execution_ssh_keys'), key
52
- assert_includes host.host_param('remote_execution_ssh_keys'), sshkey
53
- end
54
-
55
- it 'has ssh keys in the parameters even when no user specified' do
56
- # this is a case, when using the helper in provisioning templates
57
- FactoryBot.create(:smart_proxy, :ssh)
58
- host.interfaces.first.subnet.remote_execution_proxies.clear
59
- User.current = nil
60
- assert_includes host.remote_execution_ssh_keys, sshkey
61
- end
62
- end
63
-
64
- context 'host has multiple nics' do
65
- let(:host) { FactoryBot.build(:host, :with_execution) }
66
-
67
- it 'should only have one execution interface' do
68
- host.interfaces << FactoryBot.build(:nic_managed)
69
- host.interfaces.each { |interface| interface.execution = true }
70
- assert_predicate host, :valid?
71
- assert_equal 1, host.interfaces.count(&:execution?)
72
- end
73
-
74
- it 'returns the execution interface' do
75
- assert_kind_of Nic::Managed, host.execution_interface
76
- end
77
- end
78
-
79
- context 'scoped search' do
80
- let(:job) do
81
- job = FactoryBot.create(:job_invocation, :with_task)
82
- job.template_invocations << FactoryBot.create(:template_invocation, :with_host, :with_failed_task)
83
- job
84
- end
85
-
86
- let(:job2) do
87
- job = FactoryBot.create(:job_invocation, :with_task)
88
- job.template_invocations << FactoryBot.create(:template_invocation, :with_host, :with_failed_task)
89
- job
90
- end
91
-
92
- it 'finds hosts for job_invocation.id' do
93
- found_ids = Host.search_for("job_invocation.id = #{job.id}").map(&:id).sort
94
- assert_equal job.template_invocations_host_ids.sort, found_ids
95
- end
96
-
97
- it 'finds hosts by job_invocation.result' do
98
- success, failed = job.template_invocations
99
- .partition { |template| template.run_host_job_task.result == 'success' }
100
- found_ids = Host.search_for('job_invocation.result = success').map(&:id)
101
- assert_equal success.map(&:host_id), found_ids
102
- found_ids = Host.search_for('job_invocation.result = failed').map(&:id)
103
- assert_equal failed.map(&:host_id), found_ids
104
- end
105
-
106
- it 'finds hosts by job_invocation.id and job_invocation.result' do
107
- # Force evaluation of the jobs
108
- job
109
- job2
110
-
111
- assert_equal 2, Host.search_for("job_invocation.id = #{job.id}").count
112
- assert_equal 2, Host.search_for("job_invocation.id = #{job2.id}").count
113
- assert_equal 2, Host.search_for('job_invocation.result = success').count
114
- assert_equal 2, Host.search_for('job_invocation.result = failed').count
115
-
116
- success, failed = job.template_invocations
117
- .partition { |template| template.run_host_job_task.result == 'success' }
118
- found_ids = Host.search_for("job_invocation.id = #{job.id} AND job_invocation.result = success").map(&:id)
119
- assert_equal success.map(&:host_id), found_ids
120
- found_ids = Host.search_for("job_invocation.id = #{job.id} AND job_invocation.result = failed").map(&:id)
121
- assert_equal failed.map(&:host_id), found_ids
122
- end
123
- end
124
-
125
- describe 'proxy determination strategies' do
126
- context 'subnet strategy' do
127
- let(:host) { FactoryBot.build(:host, :with_execution) }
128
- it { assert_includes host.remote_execution_proxies(provider)[:subnet], host.subnet.remote_execution_proxies.first }
129
- end
130
-
131
- context 'fallback strategy' do
132
- let(:host) { FactoryBot.build(:host, :with_tftp_subnet) }
133
-
134
- context 'enabled' do
135
- before do
136
- Setting[:remote_execution_fallback_proxy] = true
137
- host.subnet.tftp.features << FactoryBot.create(:feature, :ssh)
138
- end
139
-
140
- it 'returns a fallback proxy' do
141
- assert_includes host.remote_execution_proxies(provider)[:fallback], host.subnet.tftp
142
- end
143
- end
144
-
145
- context 'disabled' do
146
- before do
147
- Setting[:remote_execution_fallback_proxy] = false
148
- host.subnet.tftp.features << FactoryBot.create(:feature, :ssh)
149
- end
150
-
151
- it 'returns no proxy' do
152
- assert_empty host.remote_execution_proxies(provider)[:fallback]
153
- end
154
- end
155
- end
156
-
157
- context 'global strategy' do
158
- let(:tax_organization) { FactoryBot.build(:organization) }
159
- let(:tax_location) { FactoryBot.build(:location) }
160
- let(:host) { FactoryBot.build(:host, :organization => tax_organization, :location => tax_location) }
161
- let(:proxy_in_taxonomies) { FactoryBot.create(:smart_proxy, :ssh, :organizations => [tax_organization], :locations => [tax_location]) }
162
- let(:proxy_no_taxonomies) { FactoryBot.create(:smart_proxy, :ssh) }
163
-
164
- context 'enabled' do
165
- before { Setting[:remote_execution_global_proxy] = true }
166
-
167
- it 'returns correct proxies confined by taxonomies' do
168
- proxy_in_taxonomies
169
- proxy_no_taxonomies
170
- assert_includes host.remote_execution_proxies(provider)[:global], proxy_in_taxonomies
171
- refute_includes host.remote_execution_proxies(provider)[:global], proxy_no_taxonomies
172
- end
173
- end
174
-
175
- context 'disabled' do
176
- before { Setting[:remote_execution_global_proxy] = false }
177
- it 'returns no proxy' do
178
- assert_empty host.remote_execution_proxies(provider)[:global]
179
- end
180
- end
181
- end
182
- end
183
-
184
- describe '#execution_scope' do
185
- let(:host) { FactoryBot.create(:host) }
186
- let(:infra_host) { FactoryBot.create(:host, :with_infrastructure_facet) }
187
-
188
- before do
189
- host
190
- infra_host
191
- end
192
-
193
- context 'without infrastructure host permission' do
194
- it 'omits the infrastructure host' do
195
- setup_user('view', 'hosts')
196
-
197
- hosts = ::Host::Managed.execution_scope
198
- assert_includes hosts, host
199
- refute_includes hosts, infra_host
200
- end
201
- end
202
-
203
- context 'with infrastructure host permission' do
204
- it 'finds the host as admin' do
205
- assert User.current.admin?
206
- hosts = ::Host::Managed.execution_scope
207
- assert_includes hosts, host
208
- assert_includes hosts, infra_host
209
- end
210
-
211
- it 'finds the host as user with needed permissions' do
212
- setup_user('execute_jobs_on', 'infrastructure_hosts')
213
- hosts = ::Host::Managed.execution_scope
214
- assert_includes hosts, host
215
- assert_includes hosts, infra_host
216
- end
217
- end
218
- end
219
- end
@@ -1,9 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class ForemanRemoteExecutionNicExtensionsTest < ActiveSupport::TestCase
4
- let(:host) { FactoryBot.create(:host) }
5
-
6
- it 'sets the first primary interface as the execution interface' do
7
- assert_equal host.interfaces.first, host.execution_interface
8
- end
9
- end
@@ -1,92 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class ExecutionTaskStatusMapperTest < ActiveSupport::TestCase
4
- describe '.sql_conditions_for(status)' do
5
- let(:subject) { HostStatus::ExecutionStatus::ExecutionTaskStatusMapper }
6
-
7
- it 'accepts status number as well as string representation' do
8
- assert_equal subject.sql_conditions_for('failed'), subject.sql_conditions_for(HostStatus::ExecutionStatus::ERROR)
9
- end
10
-
11
- it 'does not find any task for unknown state' do
12
- assert_equal [ '1 = 0' ], subject.sql_conditions_for(-1)
13
- end
14
- end
15
-
16
- let(:task) { ForemanTasks::Task.new }
17
- let(:mapper) { HostStatus::ExecutionStatus::ExecutionTaskStatusMapper.new(task) }
18
-
19
- describe '#status' do
20
- let(:subject) { mapper }
21
-
22
- describe 'is queued' do
23
- context 'when there is no task' do
24
- before { subject.task = nil }
25
- specify { assert_equal HostStatus::ExecutionStatus::QUEUED, subject.status }
26
- end
27
-
28
- context 'when the task is scheduled in future' do
29
- before { subject.task.state = 'scheduled' }
30
- specify { assert_equal HostStatus::ExecutionStatus::QUEUED, subject.status }
31
- end
32
- end
33
-
34
- context 'when task is stopped' do
35
- before { subject.task.state = 'stopped' }
36
-
37
- describe 'is succeeded' do
38
- context 'without error' do
39
- before { subject.task.result = 'success' }
40
- specify { assert_equal HostStatus::ExecutionStatus::OK, subject.status }
41
- end
42
- end
43
-
44
- describe 'is failed' do
45
- context 'with error' do
46
- before { subject.task.result = 'error' }
47
- specify { assert_equal HostStatus::ExecutionStatus::ERROR, subject.status }
48
- end
49
-
50
- context 'without error but just with warning (sub task failed)' do
51
- before { subject.task.result = 'warning' }
52
- specify { assert_equal HostStatus::ExecutionStatus::ERROR, subject.status }
53
- end
54
- end
55
- end
56
-
57
- context 'when task is pending' do
58
- before { subject.task.state = 'running' }
59
-
60
- describe 'is pending' do
61
- specify { assert_equal HostStatus::ExecutionStatus::RUNNING, subject.status }
62
- end
63
- end
64
- end
65
-
66
- describe '#status_label' do
67
- let(:subject) { mapper.status_label }
68
-
69
- context 'status is OK' do
70
- before do
71
- mapper.task.state = 'stopped'
72
- mapper.task.result = 'success'
73
- end
74
-
75
- it 'returns ok label' do
76
- assert_equal HostStatus::ExecutionStatus::STATUS_NAMES[HostStatus::ExecutionStatus::OK], subject
77
- end
78
- end
79
-
80
- context 'status is ERROR' do
81
- before do
82
- mapper.task.state = 'stopped'
83
- mapper.task.result = 'error'
84
- end
85
-
86
- it 'returns failed label' do
87
- assert_equal HostStatus::ExecutionStatus::STATUS_NAMES[HostStatus::ExecutionStatus::ERROR], subject
88
- end
89
- end
90
- end
91
-
92
- end