foreman-tasks 5.0.0 → 5.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.
- checksums.yaml +4 -4
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +4 -4
- data/app/controllers/foreman_tasks/tasks_controller.rb +5 -4
- data/app/graphql/types/recurring_logic.rb +1 -0
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +4 -1
- data/app/lib/actions/middleware/watch_delegated_proxy_sub_tasks.rb +2 -6
- data/app/lib/actions/trigger_proxy_batch.rb +79 -0
- data/app/models/foreman_tasks/recurring_logic.rb +8 -0
- data/app/models/foreman_tasks/task/dynflow_task.rb +8 -3
- data/app/models/foreman_tasks/task.rb +1 -0
- data/app/models/foreman_tasks/triggering.rb +12 -4
- data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
- data/app/views/foreman_tasks/layouts/react.html.erb +0 -1
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +4 -2
- data/app/views/foreman_tasks/task_groups/recurring_logic_task_groups/_recurring_logic_task_group.html.erb +4 -0
- data/db/migrate/20210720115251_add_purpose_to_recurring_logic.rb +6 -0
- data/extra/foreman-tasks-cleanup.sh +127 -0
- data/extra/foreman-tasks-export.sh +117 -0
- data/lib/foreman_tasks/tasks/export_tasks.rake +92 -47
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +29 -0
- data/test/controllers/tasks_controller_test.rb +19 -0
- data/test/unit/actions/trigger_proxy_batch_test.rb +59 -0
- data/test/unit/triggering_test.rb +22 -0
- data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +11 -4
- data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.test.js +27 -5
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +8 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +6 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +2 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +22 -11
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +17 -16
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +3 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +3 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +12 -2
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +5 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionHeaderCellFormatter.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -0
- metadata +8 -5
- data/app/services/foreman_tasks/dashboard_table_filter.rb +0 -56
- data/test/unit/dashboard_table_filter_test.rb +0 -77
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
PROGNAME="$0"
|
4
|
+
EXECUTE=0
|
5
|
+
RAKE_COMMAND="${RAKE_COMMAND:-"foreman-rake"}"
|
6
|
+
|
7
|
+
function die() {
|
8
|
+
local code="$1"
|
9
|
+
local message="$2"
|
10
|
+
echo "$message" >&2
|
11
|
+
exit $code
|
12
|
+
}
|
13
|
+
|
14
|
+
function build_rake() {
|
15
|
+
echo -n "$RAKE_COMMAND "
|
16
|
+
echo -n 'foreman_tasks:export_tasks '
|
17
|
+
for env in TASK_SEARCH TASK_FILE TASK_FORMAT TASK_DAYS; do
|
18
|
+
local value="${!env}"
|
19
|
+
[ -n "${value}" ] && echo -n "${env}=$(printf '%q' "$value") "
|
20
|
+
done
|
21
|
+
echo
|
22
|
+
}
|
23
|
+
|
24
|
+
function usage() {
|
25
|
+
cat << EOF
|
26
|
+
Usage: $PROGNAME [options]
|
27
|
+
|
28
|
+
An interface script for setting environment variables properly
|
29
|
+
for foreman-tasks:export_tasks rake task. By default only prints
|
30
|
+
the command to run, with -E|--execute flag performs the export.
|
31
|
+
|
32
|
+
Environment variables:
|
33
|
+
RAKE_COMMAND: can be used to redefine path to rake, by default foreman-rake
|
34
|
+
|
35
|
+
Script options:
|
36
|
+
EOF
|
37
|
+
cat <<EOF | column -s\& -t
|
38
|
+
-E|--execute & execute the created rake command
|
39
|
+
-h|--help & show this output
|
40
|
+
EOF
|
41
|
+
|
42
|
+
echo
|
43
|
+
echo Export options:
|
44
|
+
cat <<EOF | column -s\& -t
|
45
|
+
-d|--days DAYS & export only tasks started within the last DAYS days
|
46
|
+
-f|--format FORMAT & export tasks in FORMAT, one of html, html-dir, csv
|
47
|
+
-o|--output FILE & export tasks into FILE, a random file will be used if not provided
|
48
|
+
-s|--search QUERY & use QUERY in scoped search format to match tasks to export
|
49
|
+
EOF
|
50
|
+
}
|
51
|
+
|
52
|
+
SHORTOPTS="d:Ehs:o:f:"
|
53
|
+
LONGOPTS="days:,execute,help,search:,output:,format:"
|
54
|
+
|
55
|
+
ARGS=$(getopt -s bash \
|
56
|
+
--options $SHORTOPTS \
|
57
|
+
--longoptions $LONGOPTS \
|
58
|
+
--name $PROGNAME \
|
59
|
+
-- "$@" )
|
60
|
+
|
61
|
+
if [ $? -gt 0 ]; then
|
62
|
+
die 1 "getopt failed"
|
63
|
+
fi
|
64
|
+
|
65
|
+
eval set -- "$ARGS"
|
66
|
+
|
67
|
+
while true; do
|
68
|
+
case $1 in
|
69
|
+
-d|--days)
|
70
|
+
shift
|
71
|
+
TASK_DAYS="$1"
|
72
|
+
;;
|
73
|
+
-s|--search)
|
74
|
+
shift
|
75
|
+
TASK_SEARCH="$1"
|
76
|
+
;;
|
77
|
+
-o|--output)
|
78
|
+
shift
|
79
|
+
TASK_FILE="$1"
|
80
|
+
;;
|
81
|
+
-f|--format)
|
82
|
+
case "$2" in
|
83
|
+
"html" | "html-dir" | "csv")
|
84
|
+
shift
|
85
|
+
TASK_FORMAT="$1"
|
86
|
+
;;
|
87
|
+
*)
|
88
|
+
die 1 "Value for $1 must be one of html, csv. Given $2"
|
89
|
+
;;
|
90
|
+
esac
|
91
|
+
;;
|
92
|
+
-h|--help)
|
93
|
+
usage
|
94
|
+
exit 0
|
95
|
+
;;
|
96
|
+
-E|--execute)
|
97
|
+
EXECUTE=1
|
98
|
+
;;
|
99
|
+
\?)
|
100
|
+
die 1 "Invalid option: -$OPTARG"
|
101
|
+
;;
|
102
|
+
--)
|
103
|
+
;;
|
104
|
+
*)
|
105
|
+
[ -n "$1" ] || break
|
106
|
+
die 1 "Unaccepted parameter: $1"
|
107
|
+
shift
|
108
|
+
;;
|
109
|
+
esac
|
110
|
+
shift
|
111
|
+
done
|
112
|
+
|
113
|
+
if [ "$EXECUTE" -eq 1 ]; then
|
114
|
+
build_rake | sh
|
115
|
+
else
|
116
|
+
build_rake
|
117
|
+
fi
|
@@ -12,7 +12,7 @@ namespace :foreman_tasks do
|
|
12
12
|
|
13
13
|
* TASK_SEARCH : scoped search filter (example: 'label = "Actions::Foreman::Host::ImportFacts"')
|
14
14
|
* TASK_FILE : file to export to
|
15
|
-
* TASK_FORMAT : format to use for the export (either html or csv)
|
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
17
|
|
18
18
|
If TASK_SEARCH is not defined, it defaults to all tasks in the past 7 days and
|
@@ -185,23 +185,27 @@ namespace :foreman_tasks do
|
|
185
185
|
end
|
186
186
|
|
187
187
|
class PageHelper
|
188
|
-
def self.pagify(template)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
#{template}
|
202
|
-
<body>
|
203
|
-
</html>
|
188
|
+
def self.pagify(io, template = nil)
|
189
|
+
io.write <<~HTML
|
190
|
+
<html>
|
191
|
+
<head>
|
192
|
+
<title>Dynflow Console</title>
|
193
|
+
<script src="jquery.js"></script>
|
194
|
+
<link rel="stylesheet" type="text/css" href="bootstrap.css">
|
195
|
+
<link rel="stylesheet" type="text/css" href="application.css">
|
196
|
+
<script src="bootstrap.js"></script>
|
197
|
+
<script src="run_prettify.js"></script>
|
198
|
+
<script src="application.js"></script>
|
199
|
+
</head>
|
200
|
+
<body>
|
204
201
|
HTML
|
202
|
+
if block_given?
|
203
|
+
yield io
|
204
|
+
else
|
205
|
+
io.write template
|
206
|
+
end
|
207
|
+
ensure
|
208
|
+
io.write '</body></html>'
|
205
209
|
end
|
206
210
|
|
207
211
|
def self.copy_assets(tmp_dir)
|
@@ -216,13 +220,65 @@ namespace :foreman_tasks do
|
|
216
220
|
end
|
217
221
|
end
|
218
222
|
|
219
|
-
def self.
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
223
|
+
def self.generate_with_index(io)
|
224
|
+
io.write '<div><table class="table">'
|
225
|
+
yield io
|
226
|
+
ensure
|
227
|
+
io.write '</table></div>'
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.generate_index_entry(io, task)
|
231
|
+
io << <<~HTML
|
232
|
+
<tr>
|
233
|
+
<td><a href=\"#{task.id}.html\">#{task.label}</a></td>
|
234
|
+
<td>#{task.started_at}</td>
|
235
|
+
<td>#{task.duration}</td>
|
236
|
+
<td>#{task.state}</td>
|
237
|
+
<td>#{task.result}</td>
|
238
|
+
</tr>
|
239
|
+
HTML
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def csv_export(export_filename, tasks)
|
244
|
+
CSV.open(export_filename, 'wb') do |csv|
|
245
|
+
csv << %w[id state type label result parent_task_id started_at ended_at duration]
|
246
|
+
tasks.find_each do |task|
|
247
|
+
csv << [task.id, task.state, task.type, task.label, task.result,
|
248
|
+
task.parent_task_id, task.started_at, task.ended_at, task.duration]
|
224
249
|
end
|
225
|
-
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def html_export(workdir, tasks)
|
254
|
+
PageHelper.copy_assets(workdir)
|
255
|
+
|
256
|
+
renderer = TaskRender.new
|
257
|
+
total = tasks.count(:all)
|
258
|
+
index = File.open(File.join(workdir, 'index.html'), 'w')
|
259
|
+
|
260
|
+
File.open(File.join(workdir, 'index.html'), 'w') do |index|
|
261
|
+
PageHelper.pagify(index) do |io|
|
262
|
+
PageHelper.generate_with_index(io) do |index|
|
263
|
+
tasks.find_each.each_with_index do |task, count|
|
264
|
+
File.open(File.join(workdir, "#{task.id}.html"), 'w') { |file| PageHelper.pagify(file, renderer.render_task(task)) }
|
265
|
+
PageHelper.generate_index_entry(index, task)
|
266
|
+
puts "#{count + 1}/#{total}"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def generate_filename(format)
|
274
|
+
base = "/tmp/task-export-#{Time.now.to_i}"
|
275
|
+
case format
|
276
|
+
when 'html'
|
277
|
+
base + '.tar.gz'
|
278
|
+
when 'csv'
|
279
|
+
base + '.csv'
|
280
|
+
when 'html-dir'
|
281
|
+
base
|
226
282
|
end
|
227
283
|
end
|
228
284
|
|
@@ -239,36 +295,25 @@ namespace :foreman_tasks do
|
|
239
295
|
end
|
240
296
|
|
241
297
|
format = ENV['TASK_FORMAT'] || 'html'
|
242
|
-
export_filename = ENV['TASK_FILE'] ||
|
298
|
+
export_filename = ENV['TASK_FILE'] || generate_filename(format)
|
243
299
|
|
244
|
-
tasks = ForemanTasks::Task.search_for(filter)
|
300
|
+
tasks = ForemanTasks::Task.search_for(filter).order(:started_at => :desc).with_duration.distinct
|
245
301
|
|
246
302
|
puts _("Exporting all tasks matching filter #{filter}")
|
247
|
-
puts _("Gathering #{tasks.count} tasks.")
|
248
|
-
|
303
|
+
puts _("Gathering #{tasks.count(:all)} tasks.")
|
304
|
+
case format
|
305
|
+
when 'html'
|
249
306
|
Dir.mktmpdir('task-export') do |tmp_dir|
|
250
|
-
|
251
|
-
|
252
|
-
renderer = TaskRender.new
|
253
|
-
total = tasks.count
|
254
|
-
|
255
|
-
tasks.find_each.with_index do |task, count|
|
256
|
-
File.open(File.join(tmp_dir, "#{task.id}.html"), 'w') { |file| file.write(PageHelper.pagify(renderer.render_task(task))) }
|
257
|
-
puts "#{count + 1}/#{total}"
|
258
|
-
end
|
259
|
-
|
260
|
-
File.open(File.join(tmp_dir, 'index.html'), 'w') { |file| file.write(PageHelper.pagify(PageHelper.generate_index(tasks))) }
|
261
|
-
|
307
|
+
html_export(tmp_dir, tasks)
|
262
308
|
system("tar", "czf", export_filename, tmp_dir)
|
263
309
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
end
|
310
|
+
when 'html-dir'
|
311
|
+
FileUtils.mkdir_p(export_filename)
|
312
|
+
html_export(export_filename, tasks)
|
313
|
+
when 'csv'
|
314
|
+
csv_export(export_filename, tasks)
|
315
|
+
else
|
316
|
+
raise "Unkonwn export format '#{format}'"
|
272
317
|
end
|
273
318
|
|
274
319
|
puts "Created #{export_filename}"
|
@@ -68,6 +68,17 @@ module ForemanTasks
|
|
68
68
|
data = JSON.parse(response.body)
|
69
69
|
_(data[0]['results'][0]['id']).must_equal task.id
|
70
70
|
end
|
71
|
+
|
72
|
+
it 'can search for a specific resource' do
|
73
|
+
org = FactoryBot.create(:organization)
|
74
|
+
task = FactoryBot.create(:task_with_links, resource_id: org.id, resource_type: 'Organization')
|
75
|
+
|
76
|
+
post :bulk_search, params: { :searches => [{ :type => 'resource', :resource_id => org.id, :resource_type => 'Organization' }] }
|
77
|
+
|
78
|
+
assert_response :success
|
79
|
+
data = JSON.parse(response.body)
|
80
|
+
_(data[0]['results'][0]['id']).must_equal task.id
|
81
|
+
end
|
71
82
|
end
|
72
83
|
|
73
84
|
describe 'GET /api/tasks/show' do
|
@@ -91,6 +102,24 @@ module ForemanTasks
|
|
91
102
|
session: set_session_user(User.current)
|
92
103
|
assert_response :not_found
|
93
104
|
end
|
105
|
+
|
106
|
+
it 'shows duration column' do
|
107
|
+
task = ForemanTasks::Task.with_duration.find(FactoryBot.create(:dynflow_task).id)
|
108
|
+
get :show, params: { id: task.id }, session: set_session_user
|
109
|
+
assert_response :success
|
110
|
+
data = JSON.parse(response.body)
|
111
|
+
_(data['duration']).must_equal task.duration
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'GET /api/tasks/index' do
|
116
|
+
it 'shows duration column' do
|
117
|
+
task = ForemanTasks::Task.with_duration.find(FactoryBot.create(:dynflow_task).id)
|
118
|
+
get :index, session: set_session_user
|
119
|
+
assert_response :success
|
120
|
+
data = JSON.parse(response.body)
|
121
|
+
_(data['results'][0]['duration']).must_equal task.duration
|
122
|
+
end
|
94
123
|
end
|
95
124
|
|
96
125
|
describe 'GET /api/tasks/summary' do
|
@@ -91,6 +91,15 @@ module ForemanTasks
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
+
describe 'index' do
|
95
|
+
it 'shows duration column' do
|
96
|
+
task = ForemanTasks::Task.with_duration.find(FactoryBot.create(:some_task).id)
|
97
|
+
get(:index, params: {}, session: set_session_user)
|
98
|
+
assert_response :success
|
99
|
+
assert_include response.body.lines[1], task.duration
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
94
103
|
describe 'sub_tasks' do
|
95
104
|
it 'does not allow user without permissions to see task details' do
|
96
105
|
setup_user('view', 'foreman_tasks', 'owner.id = current_user')
|
@@ -109,6 +118,16 @@ module ForemanTasks
|
|
109
118
|
assert_equal 2, response.body.lines.size
|
110
119
|
assert_include response.body.lines[1], 'Child action'
|
111
120
|
end
|
121
|
+
|
122
|
+
it 'shows duration column' do
|
123
|
+
parent = ForemanTasks::Task.find(FactoryBot.create(:some_task).id)
|
124
|
+
child = ForemanTasks::Task.with_duration.find(FactoryBot.create(:some_task).id)
|
125
|
+
child.parent_task_id = parent.id
|
126
|
+
child.save!
|
127
|
+
get(:sub_tasks, params: { id: parent.id }, session: set_session_user)
|
128
|
+
assert_response :success
|
129
|
+
assert_include response.body.lines[1], child.duration
|
130
|
+
end
|
112
131
|
end
|
113
132
|
|
114
133
|
describe 'taxonomy scoping' do
|
@@ -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
|
@@ -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
|