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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31ae188eb51b073634a6022419eca1a9da0386ae
4
- data.tar.gz: ac58624747c4767a2a6281a5b528bd7bec73cdfc
3
+ metadata.gz: 6af64bff2142846ebf7fcc41ca5202b3f1bf5850
4
+ data.tar.gz: a001ea05b594c4180546b6505f20fd66bf01e14b
5
5
  SHA512:
6
- metadata.gz: 6ee4441852726080335eed0f0b98b50a90aab99cebeacc774bff9e213068d4d6853338007d7b589a04703f96abd6792721a186536e48d58281f758ed1cb48655
7
- data.tar.gz: 2989a4a292c841fcc829f9b3882edb3702915a0e40f32115c722fde27bf74c9f68507830df9938643c9f98a6673d58b6abd786a73f220c3d4114eda9225d7cb1
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
- fields.datetime_select attr, datetime_options, html_options
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 can_continue?(time = Time.now)
73
- self.state == 'active' &&
74
- (end_time.nil? || next_occurrence_time(time) < end_time) &&
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 :correct_cronline, :if => Proc.new { |t| t.recurring? && t.input_type == :cronline }
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
- ::ForemanTasks::RecurringLogic.new_from_triggering(self)
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 correct_cronline
97
- ForemanTasks::RecurringLogic.new_from_cronline(cronline).next_occurrence_time
98
- rescue ArgumentError => _
99
- self.errors.add(:cronline, _("%s is not valid format of cron line")) % (cronline)
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?
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = "0.7.16"
2
+ VERSION = "0.7.17"
3
3
  end
@@ -13,6 +13,7 @@ FactoryGirl.define do
13
13
  mode :recurring
14
14
  input_type :cronline
15
15
  cronline '* * * * *'
16
+ after(:build) { |triggering| triggering.recurring_logic = build(:recurring_logic) }
16
17
  end
17
18
 
18
19
  trait :end_time_limited do
@@ -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.create(:triggering, :recurring, :end_time_limited)
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.16
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-08 00:00:00.000000000 Z
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: