foreman-tasks 0.7.16 → 0.7.17
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/helpers/foreman_tasks/foreman_tasks_helper.rb +18 -1
- data/app/models/foreman_tasks/concerns/action_triggering.rb +20 -0
- data/app/models/foreman_tasks/recurring_logic.rb +16 -5
- data/app/models/foreman_tasks/triggering.rb +25 -11
- data/app/views/common/_trigger_form.html.erb +7 -6
- data/lib/foreman_tasks/tasks/export_tasks.rake +8 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/factories/triggering_factory.rb +1 -0
- data/test/unit/recurring_logic_test.rb +26 -1
- data/test/unit/triggering_test.rb +31 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6af64bff2142846ebf7fcc41ca5202b3f1bf5850
|
4
|
+
data.tar.gz: a001ea05b594c4180546b6505f20fd66bf01e14b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 995c854d10a044c6cdcd8d33b52b342b639d134623145afe198908936f3c4d14ca2ab97dbdcf4c3f2703b8c27253da788ac87913009f35e633ba8139f862264e
|
7
|
+
data.tar.gz: 343184b0db3a10549586fdda4fc0e89361f39a9dc8576ebdcfc466f0c044411c7abfb5de6c3dfc34c4f65145fa4ab171c2d5cd22263845ec964bb72d55fe0294
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
module ForemanTasks
|
2
3
|
module ForemanTasksHelper
|
3
4
|
|
@@ -39,10 +40,26 @@ module ForemanTasks
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
def date_f(f, attr, field_options = {}, date_options = {}, html_options = {})
|
44
|
+
f.fields_for attr do |fields|
|
45
|
+
field(fields, attr, field_options) do
|
46
|
+
fields.date_select attr, date_options, html_options
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
42
51
|
def datetime_f(f, attr, field_options = {}, datetime_options = {}, html_options = {})
|
43
52
|
f.fields_for attr do |fields|
|
44
53
|
field(fields, attr, field_options) do
|
45
|
-
|
54
|
+
[
|
55
|
+
content_tag(:span, nil, :class => 'date', :style => 'white-space: nowrap;') do
|
56
|
+
fields.date_select(attr, datetime_options, html_options)
|
57
|
+
end,
|
58
|
+
' — ',
|
59
|
+
content_tag(:span, nil, :class => 'time', :style => 'white-space: nowrap;') do
|
60
|
+
fields.time_select(attr, datetime_options.merge(:ignore_date => true), html_options)
|
61
|
+
end
|
62
|
+
].join
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
@@ -45,6 +45,25 @@ module ForemanTasks
|
|
45
45
|
dynflow_task_wrap(:save) { super(*args) }
|
46
46
|
end
|
47
47
|
|
48
|
+
# this can be used when HostActionSubject is used for orchestration but you want to avoid
|
49
|
+
# triggering more tasks by ActiveRecord callbacks within run/finalize phase of your task
|
50
|
+
# e.g. host.disable_dynflow_hooks { |h| h.save }
|
51
|
+
def disable_dynflow_hooks(&block)
|
52
|
+
@_disable_dynflow_hooks = true
|
53
|
+
|
54
|
+
if block_given?
|
55
|
+
begin
|
56
|
+
block.call(self)
|
57
|
+
ensure
|
58
|
+
@_disable_dynflow_hooks = false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def enable_dynflow_hooks
|
64
|
+
@_disable_dynflow_hooks = false
|
65
|
+
end
|
66
|
+
|
48
67
|
protected
|
49
68
|
|
50
69
|
def sync_action_flag_reset!
|
@@ -96,6 +115,7 @@ module ForemanTasks
|
|
96
115
|
# to unexpected results.
|
97
116
|
def dynflow_task_wrap(method)
|
98
117
|
if ForemanTasks.dynflow.config.disable_active_record_actions ||
|
118
|
+
@_disable_dynflow_hooks ||
|
99
119
|
@_dynflow_task_wrapped
|
100
120
|
return yield
|
101
121
|
end
|
@@ -15,8 +15,6 @@ module ForemanTasks
|
|
15
15
|
has_many :task_groups, -> { uniq }, :through => :tasks
|
16
16
|
end
|
17
17
|
|
18
|
-
validates :cron_line, :presence => true
|
19
|
-
|
20
18
|
scoped_search :on => :id, :complete_value => false
|
21
19
|
scoped_search :on => :max_iteration, :complete_value => false, :rename => :iteration_limit
|
22
20
|
scoped_search :on => :iteration, :complete_value => false
|
@@ -69,12 +67,25 @@ module ForemanTasks
|
|
69
67
|
}
|
70
68
|
end
|
71
69
|
|
72
|
-
def
|
73
|
-
self.state
|
74
|
-
|
70
|
+
def valid?(*_)
|
71
|
+
cron_line.present? && valid_cronline? && !self.state.nil? || can_start?
|
72
|
+
end
|
73
|
+
|
74
|
+
def valid_cronline?
|
75
|
+
!!next_occurrence_time
|
76
|
+
rescue ArgumentError => _
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def can_start?(time = Time.now)
|
81
|
+
(end_time.nil? || next_occurrence_time(time) < end_time) &&
|
75
82
|
(max_iteration.nil? || iteration < max_iteration)
|
76
83
|
end
|
77
84
|
|
85
|
+
def can_continue?(time = Time.now)
|
86
|
+
self.state == 'active' && can_start?(time)
|
87
|
+
end
|
88
|
+
|
78
89
|
def finished?
|
79
90
|
self.state == 'finished'
|
80
91
|
end
|
@@ -15,10 +15,6 @@ module ForemanTasks
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
after_find do |triggering|
|
19
|
-
triggering.mode = triggering.mode.to_sym
|
20
|
-
end
|
21
|
-
|
22
18
|
ALLOWED_MODES = [:immediate, :future, :recurring]
|
23
19
|
ALLOWED_INPUT_TYPES = [:cronline, :monthly, :weekly, :daily, :hourly]
|
24
20
|
|
@@ -39,7 +35,8 @@ module ForemanTasks
|
|
39
35
|
:message => _("%{value} is wrong format"), :allow_blank => true
|
40
36
|
validates_format_of :days, :with => DAYS_REGEXP,
|
41
37
|
:if => Proc.new { |t| t.recurring? && t.input_type == :monthly }
|
42
|
-
validate :
|
38
|
+
validate :can_start_recurring, :if => :recurring?
|
39
|
+
validate :can_start_future, :if => :future?
|
43
40
|
|
44
41
|
def self.new_from_params(params = {})
|
45
42
|
self.new(params.except(:mode, :start_at, :start_before)).tap do |triggering|
|
@@ -47,6 +44,19 @@ module ForemanTasks
|
|
47
44
|
triggering.input_type = params.fetch(:input_type, :daily).to_sym
|
48
45
|
triggering.end_time_limited = params[:end_time_limited] == "true"
|
49
46
|
triggering.start_at_raw ||= Time.now.strftime(TIME_FORMAT)
|
47
|
+
triggering.recurring_logic = ::ForemanTasks::RecurringLogic.new_from_triggering(triggering) if triggering.recurring?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def mode
|
52
|
+
super.to_sym
|
53
|
+
end
|
54
|
+
|
55
|
+
def mode=(mod)
|
56
|
+
if (mod.is_a?(String) || mod.is_a?(Symbol)) && ALLOWED_MODES.map(&:to_s).include?(mod.downcase.to_s)
|
57
|
+
super(mod.downcase.to_sym)
|
58
|
+
else
|
59
|
+
raise ArgumentError, _('mode has to be one of %{allowed_modes}') % { :allowed_modes => ALLOWED_MODES.join(', ') }
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
@@ -59,8 +69,7 @@ module ForemanTasks
|
|
59
69
|
delay_options,
|
60
70
|
*args
|
61
71
|
when :recurring
|
62
|
-
|
63
|
-
.start(action, *args)
|
72
|
+
recurring_logic.start(action, *args)
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
@@ -93,10 +102,15 @@ module ForemanTasks
|
|
93
102
|
|
94
103
|
private
|
95
104
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
105
|
+
def can_start_recurring
|
106
|
+
self.errors.add(:input_type, _('No task could be started')) unless recurring_logic.valid?
|
107
|
+
self.errors.add(:cronline, _('%s is not valid format of cron line') % (cronline)) unless recurring_logic.valid_cronline?
|
108
|
+
end
|
109
|
+
|
110
|
+
def can_start_future
|
111
|
+
parse_start_before!
|
112
|
+
parse_start_at!
|
113
|
+
self.errors.add(:start_before_raw, _('The task could not be started')) if !start_before.nil? && start_before < start_at
|
100
114
|
end
|
101
115
|
end
|
102
116
|
end
|
@@ -12,11 +12,12 @@
|
|
12
12
|
<%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'immediate', :text => _("Execute now") %>
|
13
13
|
<%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'future', :text => _("Schedule future execution") %>
|
14
14
|
<%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'recurring', :text => _("Set up recurring execution") %>
|
15
|
-
|
16
|
-
<div class="trigger_fields">
|
17
|
-
<%= future_mode_fieldset trigger_fields, triggering %>
|
18
|
-
<%= recurring_mode_fieldset trigger_fields, triggering %>
|
19
|
-
</div>
|
20
|
-
<% end %>
|
21
15
|
</div>
|
22
16
|
</div>
|
17
|
+
|
18
|
+
<div class="trigger_fields">
|
19
|
+
<%= future_mode_fieldset trigger_fields, triggering %>
|
20
|
+
<%= recurring_mode_fieldset trigger_fields, triggering %>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
23
|
+
|
@@ -93,6 +93,14 @@ namespace :foreman_tasks do
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
def show_world(world_id)
|
97
|
+
if registered_world = world.coordinator.find_worlds(false, id: world_id).first
|
98
|
+
"%{world_id} %{world_meta}" % { world_id: world_id, world_meta: registered_world.meta.inspect }
|
99
|
+
else
|
100
|
+
world_id
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
96
104
|
def show_action_data(label, value)
|
97
105
|
value_html = prettyprint(value)
|
98
106
|
if !value_html.empty?
|
@@ -87,9 +87,34 @@ class RecurringLogicsTest < ActiveSupport::TestCase
|
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'can be created from triggering' do
|
90
|
-
triggering = FactoryGirl.
|
90
|
+
triggering = FactoryGirl.build(:triggering, :recurring, :end_time_limited)
|
91
91
|
logic = ForemanTasks::RecurringLogic.new_from_triggering(triggering)
|
92
92
|
logic.end_time.must_equal triggering.end_time
|
93
93
|
end
|
94
|
+
|
95
|
+
describe 'validation' do
|
96
|
+
let(:logic) { FactoryGirl.build(:recurring_logic) }
|
97
|
+
|
98
|
+
it 'is valid by default' do
|
99
|
+
logic.must_be :valid?
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'is invalid when end time in past' do
|
103
|
+
logic.end_time = (Time.now - 120)
|
104
|
+
logic.wont_be :valid?
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'is invalid when iteration limit < 1' do
|
108
|
+
logic.max_iteration = 0
|
109
|
+
logic.wont_be :valid?
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'is valid when in active state' do
|
113
|
+
logic.end_time = (Time.now - 120)
|
114
|
+
logic.wont_be :valid?
|
115
|
+
logic.state = 'active'
|
116
|
+
logic.must_be :valid?
|
117
|
+
end
|
118
|
+
end
|
94
119
|
end
|
95
120
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'foreman_tasks_test_helper'
|
2
|
+
|
3
|
+
class TriggeringTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
describe 'validation' do
|
6
|
+
it 'is valid when immediate' do
|
7
|
+
FactoryGirl.build(:triggering).must_be :valid?
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'is validates future execution' do
|
11
|
+
triggering = FactoryGirl.build(:triggering, :future)
|
12
|
+
triggering.must_be :valid?
|
13
|
+
triggering.start_before = triggering.start_at - 120
|
14
|
+
triggering.wont_be :valid?
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'is invalid when recurring logic is invalid' do
|
18
|
+
triggering = FactoryGirl.build(:triggering, :recurring)
|
19
|
+
triggering.must_be :valid?
|
20
|
+
triggering.recurring_logic.stubs(:valid?).returns(false)
|
21
|
+
triggering.wont_be :valid?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'cannot have mode set to arbitrary value' do
|
26
|
+
triggering = FactoryGirl.build(:triggering)
|
27
|
+
triggering.must_be :valid?
|
28
|
+
proc { triggering.mode = 'bogus' }.must_raise ArgumentError
|
29
|
+
proc { triggering.mode = 27 }.must_raise ArgumentError
|
30
|
+
end
|
31
|
+
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: 0.7.
|
4
|
+
version: 0.7.17
|
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: 2016-04-
|
11
|
+
date: 2016-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -225,6 +225,7 @@ files:
|
|
225
225
|
- test/unit/recurring_logic_test.rb
|
226
226
|
- test/unit/task_groups_test.rb
|
227
227
|
- test/unit/task_test.rb
|
228
|
+
- test/unit/triggering_test.rb
|
228
229
|
homepage: https://github.com/theforeman/foreman-tasks
|
229
230
|
licenses: []
|
230
231
|
metadata: {}
|
@@ -265,4 +266,5 @@ test_files:
|
|
265
266
|
- test/unit/recurring_logic_test.rb
|
266
267
|
- test/unit/task_groups_test.rb
|
267
268
|
- test/unit/task_test.rb
|
269
|
+
- test/unit/triggering_test.rb
|
268
270
|
has_rdoc:
|