foreman-tasks 5.1.1 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -4
- data/.rubocop_todo.yml +0 -2
- data/README.md +8 -6
- data/app/graphql/mutations/recurring_logics/cancel.rb +27 -0
- data/app/graphql/types/recurring_logic.rb +2 -0
- data/app/lib/actions/proxy_action.rb +2 -12
- data/app/models/foreman_tasks/remote_task.rb +3 -19
- data/app/views/foreman_tasks/task_groups/recurring_logic_task_groups/_recurring_logic_task_group.html.erb +4 -0
- data/extra/foreman-tasks-export.sh +7 -3
- data/foreman-tasks.gemspec +1 -3
- data/lib/foreman_tasks/engine.rb +2 -0
- data/lib/foreman_tasks/tasks/export_tasks.rake +24 -4
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/package.json +7 -9
- data/test/controllers/api/tasks_controller_test.rb +1 -1
- data/test/factories/recurring_logic_factory.rb +7 -1
- data/test/graphql/mutations/recurring_logics/cancel_mutation_test.rb +66 -0
- data/test/support/dummy_proxy_action.rb +6 -0
- data/test/unit/actions/proxy_action_test.rb +11 -11
- data/test/unit/remote_task_test.rb +0 -8
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa2189368cc093a6ca613ca1b91add99bc3689b2cb22cd0c04a3718821b5f27f
|
4
|
+
data.tar.gz: f7e82294bbbb76fe6576b6c2de9e55c16342962f711a8e5c9070787be304a87c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f20e5fba4dbc2401a4fed1f5eb68961ccc7095071fc309316ad14392b9209141e96aa2372eb7bb5db0e7f829ef08727ff2e232e53de86baa8385183ddb722252
|
7
|
+
data.tar.gz: 534ac74d1c8010ac25330562a6bdb713beacc413d2c681ee72f865727741cfb17e04d9dda2c0ea8ab7bde2f7f2e08f54fa4266e25686ca9d1f38c5309b24b94c
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -11,7 +11,6 @@
|
|
11
11
|
# Include: **/*.gemspec
|
12
12
|
Gemspec/RequiredRubyVersion:
|
13
13
|
Exclude:
|
14
|
-
- 'foreman-tasks-core.gemspec'
|
15
14
|
- 'foreman-tasks.gemspec'
|
16
15
|
|
17
16
|
# Offense count: 1
|
@@ -37,7 +36,6 @@ Naming/MemoizedInstanceVariableName:
|
|
37
36
|
Exclude:
|
38
37
|
- 'app/controllers/foreman_tasks/recurring_logics_controller.rb'
|
39
38
|
- 'app/lib/actions/recurring_action.rb'
|
40
|
-
- 'lib/foreman_tasks_core/otp_manager.rb'
|
41
39
|
|
42
40
|
# Offense count: 11
|
43
41
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
data/README.md
CHANGED
@@ -6,7 +6,8 @@ happening/happened in your Foreman instance. A framework for asynchronous tasks
|
|
6
6
|
|
7
7
|
* Website: [TheForeman.org](http://theforeman.org)
|
8
8
|
* ServerFault tag: [Foreman](http://serverfault.com/questions/tagged/foreman)
|
9
|
-
* Issues: [
|
9
|
+
* Issues: [Foreman-tasks Redmine](http://projects.theforeman.org/projects/foreman-tasks)
|
10
|
+
* Manual: [Foreman-tasks Manual](https://www.theforeman.org/plugins/foreman_tasks/0.8/index.html)
|
10
11
|
* Wiki: [Foreman wiki](http://projects.theforeman.org/projects/foreman/wiki/About)
|
11
12
|
* Community and support: #theforeman for general support, #theforeman-dev for development chat in [Freenode](irc.freenode.net)
|
12
13
|
* Mailing lists:
|
@@ -25,6 +26,7 @@ happening/happened in your Foreman instance. A framework for asynchronous tasks
|
|
25
26
|
| >= 1.22 | ~> 0.15.0 |
|
26
27
|
| >= 2.0 | ~> 1.0.0 |
|
27
28
|
| >= 2.1 | ~> 2.0.0 |
|
29
|
+
| >= 2.6 | ~> 5.2.0 |
|
28
30
|
|
29
31
|
Installation
|
30
32
|
------------
|
@@ -154,9 +156,9 @@ rails root directory. See `-h` for more details and options
|
|
154
156
|
Tasks cleanup
|
155
157
|
-------------
|
156
158
|
|
157
|
-
Although
|
158
|
-
tasks can
|
159
|
-
|
159
|
+
Although the history of tasks has an auditing value, some kinds of
|
160
|
+
tasks can rapidly increase. Therefore, there is a mechanism for
|
161
|
+
cleaning up the tasks using a rake command. When running without
|
160
162
|
any arguments, the tasks are deleted based on the default parameters
|
161
163
|
defined in the code.
|
162
164
|
|
@@ -179,7 +181,7 @@ override the default configuration inside the configuration
|
|
179
181
|
```
|
180
182
|
:foreman-tasks:
|
181
183
|
:cleanup:
|
182
|
-
# the period after
|
184
|
+
# the period after which to delete all the tasks (by default, all tasks are not deleted after some period)
|
183
185
|
:after: 365d
|
184
186
|
# per action settings to override the default defined in the actions (cleanup_after method)
|
185
187
|
:actions:
|
@@ -194,7 +196,7 @@ to specify the search criteria for the cleanup manually:
|
|
194
196
|
* `TASK_SEARCH`: scoped search filter (example: 'label =
|
195
197
|
"Actions::Foreman::Host::ImportFacts"')
|
196
198
|
* `AFTER`: delete tasks created after `AFTER` period. Expected format
|
197
|
-
is a number followed by the time unit (`s`, `h`, `m`, `y`), such as
|
199
|
+
is a number followed by the time unit (`s`, `h`, `d`, `m`, `y`), such as
|
198
200
|
`10d` for 10 days (applicable only when the `TASK_SEARCH` option is
|
199
201
|
specified)
|
200
202
|
* `STATES`: comma separated list of task states to touch with the
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mutations
|
2
|
+
module RecurringLogics
|
3
|
+
class Cancel < BaseMutation
|
4
|
+
graphql_name 'CancelRecurringLogic'
|
5
|
+
description 'Cancels recurring logic and all its active tasks'
|
6
|
+
resource_class ::ForemanTasks::RecurringLogic
|
7
|
+
|
8
|
+
argument :id, ID, required: true
|
9
|
+
|
10
|
+
field :errors, [Types::AttributeError], null: false
|
11
|
+
field :recurring_logic, Types::RecurringLogic, null: true
|
12
|
+
|
13
|
+
def resolve(id:)
|
14
|
+
recurring_logic = load_object_by(id: id)
|
15
|
+
authorize!(recurring_logic, :edit)
|
16
|
+
task_errors = []
|
17
|
+
begin
|
18
|
+
recurring_logic.cancel
|
19
|
+
rescue => e
|
20
|
+
task_errors = [{ path: ['tasks'], message: "There has been an error when canceling one of the tasks: #{e}" }]
|
21
|
+
end
|
22
|
+
errors = recurring_logic.errors.any? ? map_errors_to_path(recurring_logic) : []
|
23
|
+
{ recurring_logic: recurring_logic, errors: (errors + task_errors) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -29,10 +29,10 @@ module Actions
|
|
29
29
|
default_connection_options.each do |key, value|
|
30
30
|
options[:connection_options][key] = value unless options[:connection_options].key?(key)
|
31
31
|
end
|
32
|
-
plan_self(options.merge(:proxy_url => proxy.url, :proxy_action_name => klass.to_s
|
32
|
+
plan_self(options.merge(:proxy_url => proxy.url, :proxy_action_name => klass.to_s))
|
33
33
|
# Just saving the RemoteTask is enough when using batch triggering
|
34
34
|
# It will be picked up by the ProxyBatchTriggering middleware
|
35
|
-
if input[:use_batch_triggering] &&
|
35
|
+
if input[:use_batch_triggering] && input.dig(:connection_options, :proxy_batch_triggering)
|
36
36
|
prepare_remote_task.save!
|
37
37
|
end
|
38
38
|
end
|
@@ -193,11 +193,6 @@ module Actions
|
|
193
193
|
:proxy_batch_triggering => Setting['foreman_tasks_proxy_batch_trigger'] || false }
|
194
194
|
end
|
195
195
|
|
196
|
-
def with_batch_triggering?(proxy_version)
|
197
|
-
((proxy_version[:major] == 1 && proxy_version[:minor] > 20) || proxy_version[:major] > 1) &&
|
198
|
-
input.fetch(:connection_options, {}).fetch(:proxy_batch_triggering, false)
|
199
|
-
end
|
200
|
-
|
201
196
|
def clean_remote_task(*_args)
|
202
197
|
remote_task.destroy! if remote_task
|
203
198
|
end
|
@@ -222,11 +217,6 @@ module Actions
|
|
222
217
|
.try(:fetch, 'output', {}) || {}
|
223
218
|
end
|
224
219
|
|
225
|
-
def proxy_version(proxy)
|
226
|
-
match = proxy.statuses[:version].version['version'].match(/(\d+)\.(\d+)\.(\d+)/)
|
227
|
-
{ :major => match[1].to_i, :minor => match[2].to_i, :patch => match[3].to_i }
|
228
|
-
end
|
229
|
-
|
230
220
|
def failed_proxy_tasks
|
231
221
|
metadata[:failed_proxy_tasks] ||= []
|
232
222
|
end
|
@@ -16,7 +16,7 @@ module ForemanTasks
|
|
16
16
|
# Triggers a task on the proxy "the old way"
|
17
17
|
def trigger(proxy_action_name, input)
|
18
18
|
response = begin
|
19
|
-
proxy.
|
19
|
+
proxy.launch_tasks('single', :action_class => proxy_action_name, :action_input => input)
|
20
20
|
rescue RestClient::Exception => e
|
21
21
|
logger.warn "Could not trigger task on the smart proxy: #{e.message}"
|
22
22
|
{}
|
@@ -31,28 +31,12 @@ module ForemanTasks
|
|
31
31
|
acc.merge(remote_task.execution_plan_id => { :action_input => remote_task.proxy_input,
|
32
32
|
:action_class => remote_task.proxy_action_name })
|
33
33
|
end
|
34
|
-
|
34
|
+
results = remote_tasks.first.proxy.launch_tasks(operation, input_hash)
|
35
|
+
remote_tasks.each { |remote_task| remote_task.update_from_batch_trigger results[remote_task.execution_plan_id] }
|
35
36
|
end
|
36
37
|
remote_tasks
|
37
38
|
end
|
38
39
|
|
39
|
-
# Attempt to trigger the tasks using the new API and fall back to the old one
|
40
|
-
# if it fails
|
41
|
-
def self.safe_batch_trigger(operation, remote_tasks, input_hash)
|
42
|
-
results = remote_tasks.first.proxy.launch_tasks(operation, input_hash)
|
43
|
-
remote_tasks.each { |remote_task| remote_task.update_from_batch_trigger results[remote_task.execution_plan_id] }
|
44
|
-
rescue RestClient::NotFound
|
45
|
-
fallback_batch_trigger remote_tasks, input_hash
|
46
|
-
end
|
47
|
-
|
48
|
-
# Trigger the tasks one-by-one using the old API
|
49
|
-
def self.fallback_batch_trigger(remote_tasks, input_hash)
|
50
|
-
remote_tasks.each do |remote_task|
|
51
|
-
task_data = input_hash[remote_task.execution_plan_id]
|
52
|
-
remote_task.trigger(task_data[:action_class], task_data[:action_input])
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
40
|
def update_from_batch_trigger(data)
|
57
41
|
if data['result'] == 'success'
|
58
42
|
self.remote_task_id = data['task_id']
|
@@ -40,4 +40,8 @@
|
|
40
40
|
<th><%= N_("Purpose") %></th>
|
41
41
|
<td><%= recurring_logic.purpose %></td>
|
42
42
|
</tr>
|
43
|
+
<tr>
|
44
|
+
<th><%= N_("Task count") %></th>
|
45
|
+
<td><%= link_to(task_group.tasks.count, foreman_tasks_tasks_url(:search => "task_group.id = #{task_group.id}")) %></td>
|
46
|
+
</tr>
|
43
47
|
</table>
|
@@ -14,7 +14,7 @@ function die() {
|
|
14
14
|
function build_rake() {
|
15
15
|
echo -n "$RAKE_COMMAND "
|
16
16
|
echo -n 'foreman_tasks:export_tasks '
|
17
|
-
for env in TASK_SEARCH TASK_FILE TASK_FORMAT TASK_DAYS; do
|
17
|
+
for env in TASK_SEARCH TASK_FILE TASK_FORMAT TASK_DAYS SKIP_FAILED; do
|
18
18
|
local value="${!env}"
|
19
19
|
[ -n "${value}" ] && echo -n "${env}=$(printf '%q' "$value") "
|
20
20
|
done
|
@@ -46,11 +46,12 @@ EOF
|
|
46
46
|
-f|--format FORMAT & export tasks in FORMAT, one of html, html-dir, csv
|
47
47
|
-o|--output FILE & export tasks into FILE, a random file will be used if not provided
|
48
48
|
-s|--search QUERY & use QUERY in scoped search format to match tasks to export
|
49
|
+
-S|--skip-failed & skip tasks that fail to export
|
49
50
|
EOF
|
50
51
|
}
|
51
52
|
|
52
|
-
SHORTOPTS="d:Ehs:o:f:"
|
53
|
-
LONGOPTS="days:,execute,help,search:,output:,format
|
53
|
+
SHORTOPTS="d:Ehs:o:f:S"
|
54
|
+
LONGOPTS="days:,execute,help,search:,output:,format:,skip-failed"
|
54
55
|
|
55
56
|
ARGS=$(getopt -s bash \
|
56
57
|
--options $SHORTOPTS \
|
@@ -96,6 +97,9 @@ while true; do
|
|
96
97
|
-E|--execute)
|
97
98
|
EXECUTE=1
|
98
99
|
;;
|
100
|
+
-S|--skip-failed)
|
101
|
+
SKIP_FAILED=1
|
102
|
+
;;
|
99
103
|
\?)
|
100
104
|
die 1 "Invalid option: -$OPTARG"
|
101
105
|
;;
|
data/foreman-tasks.gemspec
CHANGED
@@ -20,9 +20,7 @@ same resource. It also optionally provides Dynflow infrastructure for using it f
|
|
20
20
|
DESC
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n").reject do |file|
|
23
|
-
file.end_with?("test.rake")
|
24
|
-
file.start_with?('lib/foreman_tasks_core') ||
|
25
|
-
file == 'foreman-tasks-core.gemspec'
|
23
|
+
file.end_with?("test.rake")
|
26
24
|
end
|
27
25
|
|
28
26
|
s.test_files = `git ls-files test`.split("\n")
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -70,6 +70,8 @@ module ForemanTasks
|
|
70
70
|
register_graphql_query_field :recurring_logic, '::Types::RecurringLogic', :record_field
|
71
71
|
register_graphql_query_field :recurring_logics, '::Types::RecurringLogic', :collection_field
|
72
72
|
|
73
|
+
register_graphql_mutation_field :cancel_recurring_logic, ::Mutations::RecurringLogics::Cancel
|
74
|
+
|
73
75
|
logger :dynflow, :enabled => true
|
74
76
|
logger :action, :enabled => true
|
75
77
|
|
@@ -14,6 +14,7 @@ namespace :foreman_tasks do
|
|
14
14
|
* TASK_FILE : file to export to
|
15
15
|
* TASK_FORMAT : format to use for the export (either html, html-dir or csv)
|
16
16
|
* TASK_DAYS : number of days to go back
|
17
|
+
* SKIP_FAILED : skip tasks that fail to export (true or false[default])
|
17
18
|
|
18
19
|
If TASK_SEARCH is not defined, it defaults to all tasks in the past 7 days and
|
19
20
|
all unsuccessful tasks in the past 60 days. The default TASK_FORMAT is html
|
@@ -244,8 +245,10 @@ namespace :foreman_tasks do
|
|
244
245
|
CSV.open(export_filename, 'wb') do |csv|
|
245
246
|
csv << %w[id state type label result parent_task_id started_at ended_at duration]
|
246
247
|
tasks.find_each do |task|
|
247
|
-
|
248
|
-
|
248
|
+
with_error_handling(task) do
|
249
|
+
csv << [task.id, task.state, task.type, task.label, task.result,
|
250
|
+
task.parent_task_id, task.started_at, task.ended_at, task.duration]
|
251
|
+
end
|
249
252
|
end
|
250
253
|
end
|
251
254
|
end
|
@@ -261,8 +264,11 @@ namespace :foreman_tasks do
|
|
261
264
|
PageHelper.pagify(index) do |io|
|
262
265
|
PageHelper.generate_with_index(io) do |index|
|
263
266
|
tasks.find_each.each_with_index do |task, count|
|
264
|
-
|
265
|
-
|
267
|
+
content = with_error_handling(task) { renderer.render_task(task) }
|
268
|
+
if content
|
269
|
+
File.open(File.join(workdir, "#{task.id}.html"), 'w') { |file| PageHelper.pagify(file, content) }
|
270
|
+
with_error_handling(task, _('task index entry')) { PageHelper.generate_index_entry(index, task) }
|
271
|
+
end
|
266
272
|
puts "#{count + 1}/#{total}"
|
267
273
|
end
|
268
274
|
end
|
@@ -282,6 +288,20 @@ namespace :foreman_tasks do
|
|
282
288
|
end
|
283
289
|
end
|
284
290
|
|
291
|
+
def with_error_handling(task, what = _('task'))
|
292
|
+
yield
|
293
|
+
rescue StandardError => e
|
294
|
+
resolution = SKIP_ERRORS ? _(', skipping') : ''
|
295
|
+
puts _("WARNING: %{what} failed to export%{resolution}. Additional task details below.") % { :what => what, :resolution => resolution }
|
296
|
+
puts task.inspect
|
297
|
+
unless SKIP_ERRORS
|
298
|
+
puts _("Re-run with SKIP_FAILED=true if you want to simply skip any tasks that fail to export.")
|
299
|
+
raise e
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
SKIP_ERRORS = ['true', '1', 'y', 'yes'].include? ENV['SKIP_FAILED'].downcase
|
304
|
+
|
285
305
|
filter = if ENV['TASK_SEARCH'].nil? && ENV['TASK_DAYS'].nil?
|
286
306
|
"started_at > \"#{7.days.ago.to_s(:db)}\" || " \
|
287
307
|
"(result != success && started_at > \"#{60.days.ago.to_s(:db)})\""
|
Binary file
|
Binary file
|
Binary file
|
data/package.json
CHANGED
@@ -23,20 +23,18 @@
|
|
23
23
|
"url": "http://projects.theforeman.org/projects/foreman-tasks/issues"
|
24
24
|
},
|
25
25
|
"peerDependencies": {
|
26
|
-
"@theforeman/vendor": "
|
26
|
+
"@theforeman/vendor": "^8.15.0"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
|
-
"c3": "^0.4.11"
|
30
|
-
"humanize-duration": "^3.20.1",
|
31
|
-
"react-intl": "^2.8.0"
|
29
|
+
"c3": "^0.4.11"
|
32
30
|
},
|
33
31
|
"devDependencies": {
|
34
32
|
"@babel/core": "^7.7.0",
|
35
|
-
"@theforeman/builder": "^
|
36
|
-
"@theforeman/eslint-plugin-foreman": "
|
37
|
-
"@theforeman/stories": "^
|
38
|
-
"@theforeman/test": "^
|
39
|
-
"@theforeman/vendor-dev": "^
|
33
|
+
"@theforeman/builder": "^8.15.0",
|
34
|
+
"@theforeman/eslint-plugin-foreman": "^8.15.0",
|
35
|
+
"@theforeman/stories": "^8.15.0",
|
36
|
+
"@theforeman/test": "^8.15.0",
|
37
|
+
"@theforeman/vendor-dev": "^8.15.0",
|
40
38
|
"babel-eslint": "^10.0.3",
|
41
39
|
"eslint": "^6.7.2",
|
42
40
|
"jed": "^1.1.1",
|
@@ -192,7 +192,7 @@ module ForemanTasks
|
|
192
192
|
_(task.state).must_equal 'running'
|
193
193
|
_(task.result).must_equal 'pending'
|
194
194
|
|
195
|
-
callback = Support::DummyProxyAction.proxy.log[:trigger_task].first[1][:callback]
|
195
|
+
callback = Support::DummyProxyAction.proxy.log[:trigger_task].first[1][:action_input][:callback]
|
196
196
|
post :callback, params: { 'callback' => callback, 'data' => { 'result' => 'success' } }
|
197
197
|
triggered.finished.wait(5)
|
198
198
|
|
@@ -1,8 +1,14 @@
|
|
1
1
|
FactoryBot.define do
|
2
2
|
factory :recurring_logic, :class => ForemanTasks::RecurringLogic do
|
3
3
|
cron_line { '* * * * *' }
|
4
|
-
|
4
|
+
association :task_group
|
5
5
|
end
|
6
6
|
|
7
|
+
factory :task_group, :class => ::ForemanTasks::TaskGroup do
|
8
|
+
type { "ForemanTasks::TaskGroups::RecurringLogicTaskGroup" }
|
9
|
+
end
|
7
10
|
factory :recurring_logic_task_group, :class => ::ForemanTasks::TaskGroups::RecurringLogicTaskGroup
|
11
|
+
factory :task_group_member, :class => ::ForemanTasks::TaskGroupMember do
|
12
|
+
association :task_group, :task
|
13
|
+
end
|
8
14
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'foreman_tasks_test_helper'
|
2
|
+
|
3
|
+
module Mutations
|
4
|
+
module RecurringLogics
|
5
|
+
class CancelMutationTest < ActiveSupport::TestCase
|
6
|
+
setup do
|
7
|
+
@task = FactoryBot.create(:dynflow_task, state: 'pending')
|
8
|
+
@task_group = FactoryBot.create(:recurring_logic_task_group)
|
9
|
+
@task_group_member = FactoryBot.create(:task_group_member, task: @task, task_group: @task_group)
|
10
|
+
@recurring_logic = FactoryBot.create(:recurring_logic, task_group: @task_group)
|
11
|
+
@id = Foreman::GlobalId.for(@recurring_logic)
|
12
|
+
@variables = { id: @id }
|
13
|
+
@query =
|
14
|
+
<<-GRAPHQL
|
15
|
+
mutation CancelRecurringLogic($id:ID!) {
|
16
|
+
cancelRecurringLogic(input: { id: $id }){
|
17
|
+
recurringLogic {
|
18
|
+
id
|
19
|
+
state
|
20
|
+
cronLine
|
21
|
+
}
|
22
|
+
errors {
|
23
|
+
message
|
24
|
+
path
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
GRAPHQL
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'as admin' do
|
32
|
+
setup do
|
33
|
+
@context = { current_user: FactoryBot.create(:user, :admin) }
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'should cancel recurring logic' do
|
37
|
+
assert_not_equal 'cancelled', @recurring_logic.state
|
38
|
+
result = ForemanGraphqlSchema.execute(@query, variables: @variables, context: @context)
|
39
|
+
assert_empty result['errors']
|
40
|
+
assert_empty result['data']['cancelRecurringLogic']['errors']
|
41
|
+
assert_equal 'cancelled', result['data']['cancelRecurringLogic']['recurringLogic']['state']
|
42
|
+
@recurring_logic.reload
|
43
|
+
assert_equal 'cancelled', @recurring_logic.state
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'should handle errors on execution plan load failure' do
|
47
|
+
invalid_plan = ::Dynflow::ExecutionPlan::InvalidPlan.new(StandardError.new('This is a failure'), 'xyz', 'test-label', 'invalid')
|
48
|
+
::Dynflow::Persistence.any_instance.stubs(:load_execution_plan).returns(invalid_plan)
|
49
|
+
result = ForemanGraphqlSchema.execute(@query, variables: @variables, context: @context)
|
50
|
+
assert_equal "There has been an error when canceling one of the tasks: This is a failure", result['data']['cancelRecurringLogic']['errors'].first['message']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'as viewer' do
|
55
|
+
setup do
|
56
|
+
@context = { current_user: setup_user('view', 'recurring_logics') }
|
57
|
+
end
|
58
|
+
|
59
|
+
test 'should not allow to cancel recurring logic' do
|
60
|
+
result = ForemanGraphqlSchema.execute(@query, variables: @variables, context: @context)
|
61
|
+
assert_includes result['errors'].first['message'], 'Unauthorized.'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
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 = ['
|
33
|
-
{
|
34
|
-
|
35
|
-
'
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
|
@@ -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
|
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: 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-
|
11
|
+
date: 2021-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- app/controllers/foreman_tasks/react_controller.rb
|
134
134
|
- app/controllers/foreman_tasks/recurring_logics_controller.rb
|
135
135
|
- app/controllers/foreman_tasks/tasks_controller.rb
|
136
|
+
- app/graphql/mutations/recurring_logics/cancel.rb
|
136
137
|
- app/graphql/types/recurring_logic.rb
|
137
138
|
- app/graphql/types/task.rb
|
138
139
|
- app/graphql/types/triggering.rb
|
@@ -304,6 +305,7 @@ files:
|
|
304
305
|
- test/factories/task_factory.rb
|
305
306
|
- test/factories/triggering_factory.rb
|
306
307
|
- test/foreman_tasks_test_helper.rb
|
308
|
+
- test/graphql/mutations/recurring_logics/cancel_mutation_test.rb
|
307
309
|
- test/graphql/queries/recurring_logic_test.rb
|
308
310
|
- test/graphql/queries/recurring_logics_query_test.rb
|
309
311
|
- test/graphql/queries/task_query_test.rb
|
@@ -618,6 +620,7 @@ test_files:
|
|
618
620
|
- test/factories/task_factory.rb
|
619
621
|
- test/factories/triggering_factory.rb
|
620
622
|
- test/foreman_tasks_test_helper.rb
|
623
|
+
- test/graphql/mutations/recurring_logics/cancel_mutation_test.rb
|
621
624
|
- test/graphql/queries/recurring_logic_test.rb
|
622
625
|
- test/graphql/queries/recurring_logics_query_test.rb
|
623
626
|
- test/graphql/queries/task_query_test.rb
|