foreman-tasks 6.0.3 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby_tests.yml +1 -1
- data/app/lib/actions/helpers/with_delegated_action.rb +2 -2
- data/app/models/foreman_tasks/remote_task.rb +1 -1
- data/app/views/foreman_tasks/layouts/react.html.erb +1 -1
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +10 -10
- data/app/views/foreman_tasks/task_groups/_common.html.erb +2 -2
- data/app/views/foreman_tasks/task_groups/recurring_logic_task_groups/_recurring_logic_task_group.html.erb +11 -11
- data/config/foreman-tasks.yaml.example +12 -5
- data/lib/foreman_tasks/cleaner.rb +61 -23
- data/lib/foreman_tasks/engine.rb +1 -1
- data/lib/foreman_tasks/tasks/cleanup.rake +5 -10
- data/lib/foreman_tasks/version.rb +1 -1
- data/package.json +6 -6
- data/test/controllers/api/tasks_controller_test.rb +2 -2
- data/test/controllers/tasks_controller_test.rb +4 -2
- data/test/unit/cleaner_test.rb +11 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b653c4a46abfb110f3a5c1ff0f130814110475989e364d39aa2756bc76c4ae2
|
4
|
+
data.tar.gz: b7ad044c96a9cd2f7f7dbf10416ce42b88e5f2ddaf4fe5cbed696cfde39dee32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0525a6e659bf05476e86b69c6147600463f16274e71fc15b1ccee628011a785dc53fc6b8cad0ef5f3439cac8c6581a73cea7a1175c4489778f5204fe3914c76
|
7
|
+
data.tar.gz: feab08efc57055c27fab6010dd1f5dac438f74091dee9c239da5722a7236eacf467433f17838066e3ef707f2268e39e2f3130615a25a9094286a9c65d66b2485
|
@@ -3,7 +3,7 @@ module Actions
|
|
3
3
|
module WithDelegatedAction
|
4
4
|
include ::Actions::Helpers::WithContinuousOutput
|
5
5
|
|
6
|
-
def plan_delegated_action(proxy, klass, options)
|
6
|
+
def plan_delegated_action(proxy, klass, options, proxy_action_class: ::Actions::ProxyAction)
|
7
7
|
case proxy
|
8
8
|
when :not_defined
|
9
9
|
if klass.is_a?(String)
|
@@ -14,7 +14,7 @@ module Actions
|
|
14
14
|
when :not_available
|
15
15
|
raise Foreman::Exception, _('All proxies with the required feature are unavailable at the moment')
|
16
16
|
when ::SmartProxy
|
17
|
-
delegated_action = plan_action(
|
17
|
+
delegated_action = plan_action(proxy_action_class, proxy, klass, options)
|
18
18
|
end
|
19
19
|
|
20
20
|
input[:delegated_action_id] = delegated_action.id
|
@@ -7,7 +7,7 @@ module ForemanTasks
|
|
7
7
|
:foreign_key => :execution_plan_id,
|
8
8
|
:inverse_of => :remote_tasks
|
9
9
|
|
10
|
-
scope :triggered, -> { where(:state => 'triggered') }
|
10
|
+
scope :triggered, -> { where(:state => ['triggered', 'parent-triggered']) }
|
11
11
|
scope :pending, -> { where(:state => 'new') }
|
12
12
|
scope :external, -> { where(:state => 'external') }
|
13
13
|
|
@@ -38,16 +38,16 @@
|
|
38
38
|
<table class="<%= table_css_classes('table-condensed table-fixed') %>">
|
39
39
|
<thead>
|
40
40
|
<th class="col-md-1"><%= N_("ID") %></th>
|
41
|
-
<th><%=
|
42
|
-
<th><%=
|
43
|
-
<th><%=
|
44
|
-
<th><%=
|
45
|
-
<th><%=
|
46
|
-
<th><%=
|
47
|
-
<th><%=
|
48
|
-
<th><%=
|
49
|
-
<th><%=
|
50
|
-
<th><%=
|
41
|
+
<th><%= _("Cron line") %></th>
|
42
|
+
<th><%= _("Task count") %></th>
|
43
|
+
<th><%= _("Action") %></th>
|
44
|
+
<th><%= _("Last occurrence") %></th>
|
45
|
+
<th><%= _("Next occurrence") %></th>
|
46
|
+
<th><%= _("Current iteration") %></th>
|
47
|
+
<th><%= _("Iteration limit") %></th>
|
48
|
+
<th><%= _("Repeat until") %></th>
|
49
|
+
<th><%= _("State") %></th>
|
50
|
+
<th><%= _("Purpose") %></th>
|
51
51
|
<th/>
|
52
52
|
</thead>
|
53
53
|
<% @recurring_logics.each do |recurring_logic| %>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<div>
|
2
2
|
<table class='<%= table_css_classes('table-condensed') %>'>
|
3
3
|
<tr>
|
4
|
-
<th><%=
|
4
|
+
<th><%= _('ID') %></th>
|
5
5
|
<td><%= link_to(task_group.id, foreman_tasks_task_group_url(task_group)) %></td>
|
6
6
|
</tr>
|
7
7
|
<tr>
|
8
|
-
<th><%=
|
8
|
+
<th><%= _('Task count') %></th>
|
9
9
|
<td><%= link_to(task_group.tasks.count, foreman_tasks_tasks_url(:search => "task_group.id = #{task_group.id}")) %></td>
|
10
10
|
</tr>
|
11
11
|
</table>
|
@@ -1,47 +1,47 @@
|
|
1
1
|
<% recurring_logic = task_group.recurring_logic -%>
|
2
2
|
<table class='<%= table_css_classes('table-condensed') %>'>
|
3
3
|
<tr>
|
4
|
-
<th
|
4
|
+
<th><%= _('ID') %></th>
|
5
5
|
<td><%= link_to(recurring_logic.id, recurring_logic) %></td>
|
6
6
|
</tr>
|
7
7
|
<tr>
|
8
|
-
<th><%=
|
8
|
+
<th><%= _("Cron line") %></th>
|
9
9
|
<td><%= recurring_logic.cron_line %></td>
|
10
10
|
</tr>
|
11
11
|
<tr>
|
12
|
-
<th><%=
|
12
|
+
<th><%= _("Action") %></th>
|
13
13
|
<td><%= format_task_input(recurring_logic.tasks.last) %></td>
|
14
14
|
</tr>
|
15
15
|
<tr>
|
16
|
-
<th><%=
|
16
|
+
<th><%= _("Last occurrence") %></th>
|
17
17
|
<td><%= recurring_logic.tasks.order(:started_at).where('started_at IS NOT NULL').last.try(:started_at) || '-' %></td>
|
18
18
|
</tr>
|
19
19
|
<tr>
|
20
|
-
<th><%=
|
20
|
+
<th><%= _("Next occurrence") %></th>
|
21
21
|
<td><%= recurring_logic_next_occurrence recurring_logic %></td>
|
22
22
|
</tr>
|
23
23
|
<tr>
|
24
|
-
<th><%=
|
24
|
+
<th><%= _("Current iteration") %></th>
|
25
25
|
<td><%= recurring_logic.iteration %></td>
|
26
26
|
</tr>
|
27
27
|
<tr>
|
28
|
-
<th><%=
|
28
|
+
<th><%= _("Iteration limit") %></th>
|
29
29
|
<td><%= format_recurring_logic_limit recurring_logic.max_iteration %></td>
|
30
30
|
</tr>
|
31
31
|
<tr>
|
32
|
-
<th><%=
|
32
|
+
<th><%= _("Repeat until") %></th>
|
33
33
|
<td><%= format_recurring_logic_limit recurring_logic.end_time.try(:in_time_zone) %></td>
|
34
34
|
</tr>
|
35
35
|
<tr>
|
36
|
-
<th><%=
|
36
|
+
<th><%= _("State") %></th>
|
37
37
|
<td><%= recurring_logic_state(recurring_logic) %></td>
|
38
38
|
</tr>
|
39
39
|
<tr>
|
40
|
-
<th><%=
|
40
|
+
<th><%= _("Purpose") %></th>
|
41
41
|
<td><%= recurring_logic.purpose %></td>
|
42
42
|
</tr>
|
43
43
|
<tr>
|
44
|
-
<th><%=
|
44
|
+
<th><%= _("Task count") %></th>
|
45
45
|
<td><%= link_to(task_group.tasks.count, foreman_tasks_tasks_url(:search => "task_group.id = #{task_group.id}")) %></td>
|
46
46
|
</tr>
|
47
47
|
</table>
|
@@ -27,16 +27,23 @@
|
|
27
27
|
#
|
28
28
|
:cleanup:
|
29
29
|
#
|
30
|
-
# the period after which to delete all the tasks (by default all tasks are not being deleted after some period)
|
31
|
-
# will be deprecated in Foreman 1.18 and the use of rules is recommended.
|
32
|
-
#
|
33
|
-
# :after: 30d
|
34
|
-
#
|
35
30
|
# per action settings to override the default defined in the actions (self.cleanup_after method)
|
36
31
|
#
|
37
32
|
# :actions:
|
38
33
|
# - :name: Actions::Foreman::Host::ImportFacts
|
39
34
|
# :after: 10d
|
35
|
+
# # Actions name can also be a list of names
|
36
|
+
# - :name:
|
37
|
+
# - Actions::Katello::Host::Erratum::Install
|
38
|
+
# - Actions::Katello::Host::Erratum::ApplicableErrataInstall
|
39
|
+
# :after: 90d
|
40
|
+
# # Actions can also define a condition
|
41
|
+
# - :name:
|
42
|
+
# - Actions::RemoteExecution::RunHostJob
|
43
|
+
# - Actions::RemoteExecution::RunHostsJob
|
44
|
+
# :filter: remote_execution_feature.label = katello_errata_install
|
45
|
+
# :after: 90d
|
46
|
+
|
40
47
|
#
|
41
48
|
# Rules defined in this section by default don't operate
|
42
49
|
# on tasks specified in the actions section. This behavior
|
@@ -2,6 +2,50 @@ require 'csv'
|
|
2
2
|
|
3
3
|
module ForemanTasks
|
4
4
|
# Represents the cleanup mechanism for tasks
|
5
|
+
class ActionRule
|
6
|
+
attr_reader :klass, :after, :condition
|
7
|
+
def initialize(klass, after, condition = nil)
|
8
|
+
@klass = klass
|
9
|
+
@after = after
|
10
|
+
@condition = condition
|
11
|
+
end
|
12
|
+
|
13
|
+
def exclude_search
|
14
|
+
"NOT (#{include_search})"
|
15
|
+
end
|
16
|
+
|
17
|
+
def include_search
|
18
|
+
parts = if klass.is_a? Array
|
19
|
+
["label ^ (#{klass.join(', ')})"]
|
20
|
+
else
|
21
|
+
["label = \"#{klass}\""]
|
22
|
+
end
|
23
|
+
parts << "(#{@condition})" if @condition
|
24
|
+
'(' + parts.join(' AND ') + ')'
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.compose_include_rules(rules)
|
28
|
+
rules.group_by { |rule| [rule.after, rule.condition] }
|
29
|
+
.map do |(after, condition), rules|
|
30
|
+
ActionRule.new(rules.map(&:klass), after, condition)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class CompositeActionRule
|
36
|
+
def initialize(*rules)
|
37
|
+
@rules = rules
|
38
|
+
end
|
39
|
+
|
40
|
+
def exclude_search
|
41
|
+
partial_condition = @rules.group_by(&:condition)
|
42
|
+
.map do |condition, rules|
|
43
|
+
ActionRule.new(rules.map(&:klass), nil, condition).include_search
|
44
|
+
end.join(' OR ')
|
45
|
+
"NOT (#{partial_condition})"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
5
49
|
class Cleaner
|
6
50
|
def self.run(options)
|
7
51
|
if options.key?(:filter)
|
@@ -12,36 +56,30 @@ module ForemanTasks
|
|
12
56
|
raise "The option #{invalid_option} is not valid unless the filter specified"
|
13
57
|
end
|
14
58
|
end
|
15
|
-
if cleanup_settings[:after]
|
16
|
-
Foreman::Deprecation.deprecation_warning('1.18', _(':after setting in tasks cleanup section is deprecated, use :after in :rules section to set the value. to cleanup rules'))
|
17
|
-
new(options.merge(:filter => '', :after => cleanup_settings[:after])).delete
|
18
|
-
end
|
19
59
|
with_periods = actions_with_default_cleanup
|
20
|
-
with_periods.each do |
|
21
|
-
new(options.merge(:filter =>
|
60
|
+
ActionRule.compose_include_rules(with_periods).each do |rule|
|
61
|
+
new(options.merge(:filter => rule.include_search, :after => rule.after)).delete
|
22
62
|
end
|
23
|
-
actions_by_rules(with_periods).each do |hash|
|
63
|
+
actions_by_rules(CompositeActionRule.new(*with_periods)).each do |hash|
|
24
64
|
new(options.merge(hash)).delete
|
25
65
|
end
|
26
66
|
end
|
27
67
|
end
|
28
68
|
|
29
69
|
def self.actions_with_default_cleanup
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
actions_with_periods[action_class] = action[:after]
|
35
|
-
rescue => e
|
36
|
-
Foreman::Logging.exception("Error handling #{action} cleanup settings", e)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
(ForemanTasks.dynflow.world.action_classes - actions_with_periods.keys).each do |action_class|
|
40
|
-
if action_class.respond_to?(:cleanup_after)
|
41
|
-
actions_with_periods[action_class] = action_class.cleanup_after
|
70
|
+
actions = cleanup_settings.fetch(:actions, [])
|
71
|
+
.flat_map do |action|
|
72
|
+
Array(action[:name]).map do |klass|
|
73
|
+
ActionRule.new(klass.safe_constantize || klass, action[:after], action[:filter])
|
42
74
|
end
|
43
|
-
|
44
|
-
|
75
|
+
rescue => e
|
76
|
+
Foreman::Logging.exception("Error handling #{action} cleanup settings", e)
|
77
|
+
nil
|
78
|
+
end.compact
|
79
|
+
hardcoded = (ForemanTasks.dynflow.world.action_classes - actions.map(&:klass))
|
80
|
+
.select { |klass| klass.respond_to?(:cleanup_after) || klass.respond_to?(:cleanup_rules) }
|
81
|
+
.flat_map { |klass| klass.respond_to?(:cleanup_rules) ? klass.cleanup_rules : ActionRule.new(klass, klass.cleanup_after) }
|
82
|
+
actions + hardcoded
|
45
83
|
end
|
46
84
|
|
47
85
|
def self.cleanup_settings
|
@@ -49,8 +87,8 @@ module ForemanTasks
|
|
49
87
|
@cleanup_settings = SETTINGS[:'foreman-tasks'] && SETTINGS[:'foreman-tasks'][:cleanup] || {}
|
50
88
|
end
|
51
89
|
|
52
|
-
def self.actions_by_rules(
|
53
|
-
disable_actions_with_periods =
|
90
|
+
def self.actions_by_rules(action_rules)
|
91
|
+
disable_actions_with_periods = action_rules.exclude_search
|
54
92
|
cleanup_settings.fetch(:rules, []).map do |hash|
|
55
93
|
next if hash[:after].nil?
|
56
94
|
conditions = []
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -25,7 +25,7 @@ module ForemanTasks
|
|
25
25
|
|
26
26
|
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do |_app|
|
27
27
|
Foreman::Plugin.register :"foreman-tasks" do
|
28
|
-
requires_foreman '>= 3.
|
28
|
+
requires_foreman '>= 3.3.0'
|
29
29
|
divider :top_menu, :parent => :monitor_menu, :last => true, :caption => N_('Foreman Tasks')
|
30
30
|
menu :top_menu, :tasks,
|
31
31
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
@@ -39,23 +39,18 @@ namespace :foreman_tasks do
|
|
39
39
|
|
40
40
|
desc 'Show the current configuration for auto-cleanup'
|
41
41
|
task :config => ['environment', 'dynflow:client'] do
|
42
|
-
if ForemanTasks::Cleaner.cleanup_settings[:after]
|
43
|
-
puts _('The tasks will be deleted after %{after}') % { :after => ForemanTasks::Cleaner.cleanup_settings[:after] }
|
44
|
-
else
|
45
|
-
puts _('Global period for cleaning up tasks is not set')
|
46
|
-
end
|
47
|
-
|
48
42
|
if ForemanTasks::Cleaner.actions_with_default_cleanup.empty?
|
49
43
|
puts _('No actions are configured to be cleaned automatically')
|
50
44
|
else
|
51
45
|
puts _('The following actions are configured to be deleted automatically after some time:')
|
52
|
-
printf("%-50s
|
53
|
-
ForemanTasks::Cleaner.actions_with_default_cleanup.each do |action,
|
54
|
-
|
46
|
+
printf("%-75s %-20s %-50s\n", _('name'), _('delete after'), _('filter'))
|
47
|
+
ForemanTasks::Cleaner.actions_with_default_cleanup.each do |action, _after|
|
48
|
+
klass = action.klass
|
49
|
+
printf("%-75s %-20s %-50s\n", klass.try(:name) || klass, action.after, action.condition)
|
55
50
|
end
|
56
51
|
end
|
57
52
|
puts
|
58
|
-
by_rules = ForemanTasks::Cleaner.actions_by_rules(ForemanTasks::Cleaner.actions_with_default_cleanup)
|
53
|
+
by_rules = ForemanTasks::Cleaner.actions_by_rules(ForemanTasks::CompositeActionRule.new(*ForemanTasks::Cleaner.actions_with_default_cleanup))
|
59
54
|
if by_rules.empty?
|
60
55
|
puts _('No cleanup rules are configured')
|
61
56
|
else
|
data/package.json
CHANGED
@@ -23,18 +23,18 @@
|
|
23
23
|
"url": "http://projects.theforeman.org/projects/foreman-tasks/issues"
|
24
24
|
},
|
25
25
|
"peerDependencies": {
|
26
|
-
"@theforeman/vendor": "^
|
26
|
+
"@theforeman/vendor": "^10.1.0"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
29
|
"c3": "^0.4.11"
|
30
30
|
},
|
31
31
|
"devDependencies": {
|
32
32
|
"@babel/core": "^7.7.0",
|
33
|
-
"@theforeman/builder": "^
|
34
|
-
"@theforeman/eslint-plugin-foreman": "^
|
35
|
-
"@theforeman/stories": "^
|
36
|
-
"@theforeman/test": "^
|
37
|
-
"@theforeman/vendor-dev": "^
|
33
|
+
"@theforeman/builder": "^10.1.0",
|
34
|
+
"@theforeman/eslint-plugin-foreman": "^10.1.0",
|
35
|
+
"@theforeman/stories": "^10.1.0",
|
36
|
+
"@theforeman/test": "^10.1.0",
|
37
|
+
"@theforeman/vendor-dev": "^10.1.0",
|
38
38
|
"babel-eslint": "^10.0.3",
|
39
39
|
"eslint": "^6.7.2",
|
40
40
|
"jed": "^1.1.1",
|
@@ -108,7 +108,7 @@ module ForemanTasks
|
|
108
108
|
get :show, params: { id: task.id }, session: set_session_user
|
109
109
|
assert_response :success
|
110
110
|
data = JSON.parse(response.body)
|
111
|
-
_(data['duration']).must_equal task.duration
|
111
|
+
_(data['duration']).must_equal task.duration.in_seconds.to_s
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -118,7 +118,7 @@ module ForemanTasks
|
|
118
118
|
get :index, session: set_session_user
|
119
119
|
assert_response :success
|
120
120
|
data = JSON.parse(response.body)
|
121
|
-
_(data['results'][0]['duration']).must_equal task.duration
|
121
|
+
_(data['results'][0]['duration']).must_equal task.duration.in_seconds.to_s
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
@@ -96,7 +96,8 @@ module ForemanTasks
|
|
96
96
|
task = ForemanTasks::Task.with_duration.find(FactoryBot.create(:some_task).id)
|
97
97
|
get(:index, params: {}, session: set_session_user)
|
98
98
|
assert_response :success
|
99
|
-
|
99
|
+
row = CSV.parse(response.body, headers: true).first
|
100
|
+
assert_include row['Duration'], task.duration.in_seconds.to_s
|
100
101
|
end
|
101
102
|
end
|
102
103
|
|
@@ -126,7 +127,8 @@ module ForemanTasks
|
|
126
127
|
child.save!
|
127
128
|
get(:sub_tasks, params: { id: parent.id }, session: set_session_user)
|
128
129
|
assert_response :success
|
129
|
-
|
130
|
+
row = CSV.parse(response.body, headers: true).first
|
131
|
+
assert_include row['Duration'], child.duration.in_seconds.to_s
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
data/test/unit/cleaner_test.rb
CHANGED
@@ -133,33 +133,31 @@ class TasksTest < ActiveSupport::TestCase
|
|
133
133
|
describe 'default behaviour' do
|
134
134
|
it 'searches for the actions that have the cleanup_after defined' do
|
135
135
|
ForemanTasks::Cleaner.stubs(:cleanup_settings => {})
|
136
|
-
|
136
|
+
actions = ForemanTasks::Cleaner.actions_with_default_cleanup
|
137
|
+
example = actions.find { |rule| rule.klass == ActionWithCleanup }
|
138
|
+
_(example.after).must_equal '15d'
|
137
139
|
end
|
138
140
|
|
139
141
|
it 'searches for the actions that have the cleanup_after defined' do
|
140
142
|
ForemanTasks::Cleaner.stubs(:cleanup_settings =>
|
141
143
|
{ :actions => [{ :name => ActionWithCleanup.name, :after => '5d' }] })
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
it 'deprecates the usage of :after' do
|
146
|
-
Foreman::Deprecation.expects(:deprecation_warning)
|
147
|
-
ForemanTasks::Cleaner.any_instance.expects(:delete)
|
148
|
-
ForemanTasks::Cleaner.stubs(:cleanup_settings =>
|
149
|
-
{ :after => '1d' })
|
150
|
-
ForemanTasks::Cleaner.stubs(:actions_with_default_cleanup).returns({})
|
151
|
-
ForemanTasks::Cleaner.run({})
|
144
|
+
actions = ForemanTasks::Cleaner.actions_with_default_cleanup
|
145
|
+
example = actions.find { |rule| rule.klass == ActionWithCleanup }
|
146
|
+
_(example.after).must_equal '5d'
|
152
147
|
end
|
153
148
|
|
154
149
|
it 'generates filters from rules properly' do
|
155
|
-
actions_with_default =
|
150
|
+
actions_with_default = ForemanTasks::CompositeActionRule.new(
|
151
|
+
ForemanTasks::ActionRule.new('action1', nil),
|
152
|
+
ForemanTasks::ActionRule.new('action2', nil)
|
153
|
+
)
|
156
154
|
rules = [{ :after => nil },
|
157
155
|
{ :after => '10d', :filter => 'label = something', :states => %w[stopped paused] },
|
158
156
|
{ :after => '15d', :filter => 'label = something_else',
|
159
157
|
:override_actions => true, :states => 'all' }]
|
160
158
|
ForemanTasks::Cleaner.stubs(:cleanup_settings).returns(:rules => rules)
|
161
159
|
r1, r2 = ForemanTasks::Cleaner.actions_by_rules actions_with_default
|
162
|
-
_(r1[:filter]).must_equal '(label
|
160
|
+
_(r1[:filter]).must_equal '(NOT ((label ^ (action1, action2)))) AND (label = something)'
|
163
161
|
_(r1[:states]).must_equal %w[stopped paused]
|
164
162
|
_(r2[:filter]).must_equal '(label = something_else)'
|
165
163
|
_(r2[:states]).must_equal []
|
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
|
+
version: 7.1.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: 2022-
|
11
|
+
date: 2022-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|