foreman-tasks 0.13.4 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fac96114cba4bed5007f60b44da68f30a3660951
4
- data.tar.gz: ad625aafcc0ef55569672bd5864813555051c9ff
3
+ metadata.gz: 99bc7ed098375451dddebc63a0d2c5af37ec3374
4
+ data.tar.gz: 573580a8808e4c68f84a82db9a05919b960aa771
5
5
  SHA512:
6
- metadata.gz: 2fe01c9e536d2b991bd452e226935e4832945d92b34e184226dddfd1ddc3f33588ec11ebb4b93ae24a50b772eba0e715d9744a11c6b3edef6907ebebd20bdb27
7
- data.tar.gz: 22d258e052528cf2d9ff5f2c3579e9c5bb4c83eb719722edd344b187631d1d74b3bb50d1ccb5d8d64645a3c94a49e2bc0fd3f0a8b5caea14e544c4c700e0527a
6
+ metadata.gz: 9f37b871477d68c476aef947749d516337e3ae8fe5d71bc7f49f82bc5f0467fa265ac324661cb3ad9a2e7368159e92e017e101cd940422b2f1eaea24e4960948
7
+ data.tar.gz: a11510b41ff6b00d8d76acaa01a3dede47792c732711ee916e86979e2f56cd02ca861a8d648673ac34e9d8d0bf73452677029969557311446c90b391ecebcb24
@@ -2,6 +2,7 @@ module ForemanTasks
2
2
  module Api
3
3
  class RecurringLogicsController < ::Api::V2::BaseController
4
4
  include ::Api::Version2
5
+ include Concerns::Parameters::RecurringLogic
5
6
 
6
7
  resource_description do
7
8
  resource_id 'recurring_logics'
@@ -9,7 +10,7 @@ module ForemanTasks
9
10
  api_base_url '/foreman_tasks/api'
10
11
  end
11
12
 
12
- before_action :find_resource, :only => %w[show cancel]
13
+ before_action :find_resource, :only => %w[show cancel update]
13
14
 
14
15
  api :GET, '/recurring_logics', N_('List recurring logics')
15
16
  param_group :search_and_pagination, ::Api::V2::BaseController
@@ -21,6 +22,13 @@ module ForemanTasks
21
22
  param :id, :identifier, desc: 'ID of the recurring logic', required: true
22
23
  def show; end
23
24
 
25
+ api :PUT, '/recurring_logics/:id', N_('Update recurring logic')
26
+ param :id, :identifier, desc: 'ID of the recurring logic', required: true
27
+ param :enabled, :boolean, desc: 'Whether the recurring logic is enabled or disabled.', required: false
28
+ def update
29
+ process_response @recurring_logic.update(recurring_logic_params)
30
+ end
31
+
24
32
  api :POST, '/recurring_logics/:id/cancel', N_('Cancel recurring logic')
25
33
  param :id, :identifier, desc: 'ID of the recurring logic', required: true
26
34
  def cancel
@@ -0,0 +1,21 @@
1
+ module ForemanTasks
2
+ module Concerns
3
+ module Parameters
4
+ module RecurringLogic
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def recurring_logic_params_filter
9
+ Foreman::ParameterFilter.new(::ForemanTasks::RecurringLogic).tap do |filter|
10
+ filter.permit(:enabled)
11
+ end
12
+ end
13
+ end
14
+
15
+ def recurring_logic_params
16
+ self.class.recurring_logic_params_filter.filter_params(params, parameter_filter_context, :recurring_logic)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,13 +1,22 @@
1
1
  module ForemanTasks
2
2
  class RecurringLogicsController < ::ApplicationController
3
- before_action :find_recurring_logic, :only => [:show, :cancel]
3
+ before_action :find_recurring_logic, :only => [:show, :cancel, :enable, :disable]
4
4
 
5
5
  def index
6
+ @errors = params[:errors]
6
7
  @recurring_logics = filter(resource_base)
7
8
  end
8
9
 
9
10
  def show; end
10
11
 
12
+ def enable
13
+ change_enabled(true)
14
+ end
15
+
16
+ def disable
17
+ change_enabled(false)
18
+ end
19
+
11
20
  def cancel
12
21
  @recurring_logic.cancel
13
22
  redirect_to :action => :index
@@ -23,6 +32,15 @@ module ForemanTasks
23
32
 
24
33
  private
25
34
 
35
+ def change_enabled(value)
36
+ begin
37
+ @recurring_logic.update!(:enabled => value)
38
+ rescue RecurringLogicCancelledException => e
39
+ @errors = e.message
40
+ end
41
+ redirect_to :action => :index, :errors => @errors
42
+ end
43
+
26
44
  def find_recurring_logic
27
45
  @recurring_logic ||= ::ForemanTasks::RecurringLogic.find(params[:id])
28
46
  end
@@ -1,9 +1,12 @@
1
1
  module ForemanTasks
2
+ # rubocop:disable Metrics/ModuleLength
2
3
  module ForemanTasksHelper
3
4
  def recurring_logic_state(recurring_logic)
4
5
  icon, status = case recurring_logic.state
5
6
  when 'active'
6
7
  'glyphicon-info-sign'
8
+ when 'disabled'
9
+ 'glyphicon glyphicon-pause'
7
10
  when 'finished'
8
11
  ['glyphicon-ok-sign', 'status-ok']
9
12
  when 'cancelled'
@@ -52,14 +55,16 @@ module ForemanTasks
52
55
  def recurring_logic_action_buttons(recurring_logic)
53
56
  buttons = []
54
57
  if authorized_for(:permission => :edit_recurring_logics, :auth_object => recurring_logic)
55
- buttons << link_to(N_('Cancel'), cancel_foreman_tasks_recurring_logic_path(recurring_logic), :method => :post, :class => 'btn btn-danger') unless %w[cancelled finished].include? recurring_logic.state
58
+ buttons << link_to(N_('Enable'), enable_foreman_tasks_recurring_logic_path(recurring_logic), :method => :put, :class => '') if !recurring_logic.done? && recurring_logic.disabled?
59
+ buttons << link_to(N_('Disable'), disable_foreman_tasks_recurring_logic_path(recurring_logic), :method => :put, :class => '') if !recurring_logic.done? && recurring_logic.enabled?
60
+ buttons << link_to(N_('Cancel'), cancel_foreman_tasks_recurring_logic_path(recurring_logic), :method => :post, :class => '') unless recurring_logic.done?
56
61
  end
57
- button_group buttons
62
+ action_buttons buttons
58
63
  end
59
64
 
60
65
  def recurring_logic_next_occurrence(recurring_logic)
61
66
  default = '-'
62
- return default if %w[finished cancelled].include? recurring_logic.state
67
+ return default if recurring_logic.done? || recurring_logic.disabled?
63
68
 
64
69
  last_task = recurring_logic.tasks.order(:start_at).last
65
70
  last_task ? last_task.start_at : default
@@ -197,4 +202,5 @@ module ForemanTasks
197
202
  tags.join.html_safe
198
203
  end
199
204
  end
205
+ # rubocop:enable Metrics/ModuleLength
200
206
  end
@@ -20,7 +20,30 @@ module ForemanTasks
20
20
  end
21
21
 
22
22
  def self.allowed_states
23
- %w[active finished cancelled failed]
23
+ %w[active disabled finished cancelled failed]
24
+ end
25
+
26
+ def enabled=(value)
27
+ task = tasks.find_by(:state => :scheduled)
28
+ if task
29
+ ForemanTasks.dynflow.world.persistence.set_delayed_plan_frozen(task.execution_plan.id, !value, next_occurrence_time)
30
+ if value
31
+ task.update!(:start_at => next_occurrence_time) if task.start_at < Time.zone.now
32
+ update(:state => 'active')
33
+ else
34
+ update(:state => 'disabled')
35
+ end
36
+ else
37
+ raise RecurringLogicCancelledException
38
+ end
39
+ end
40
+
41
+ def enabled?
42
+ state != 'disabled'
43
+ end
44
+
45
+ def disabled?
46
+ !enabled?
24
47
  end
25
48
 
26
49
  def start(action_class, *args)
@@ -67,7 +90,8 @@ module ForemanTasks
67
90
  {
68
91
  :start_at => next_occurrence_time(time),
69
92
  :start_before => options['start_before'],
70
- :recurring_logic_id => id
93
+ :recurring_logic_id => id,
94
+ :frozen => disabled?
71
95
  }
72
96
  end
73
97
 
@@ -87,7 +111,7 @@ module ForemanTasks
87
111
  end
88
112
 
89
113
  def can_continue?(time = Time.zone.now)
90
- state == 'active' && can_start?(time)
114
+ %w[active disabled].include?(state) && can_start?(time)
91
115
  end
92
116
 
93
117
  def finished?
@@ -98,6 +122,10 @@ module ForemanTasks
98
122
  state == 'cancelled'
99
123
  end
100
124
 
125
+ def done?
126
+ %w[cancelled finished].include?(state)
127
+ end
128
+
101
129
  def humanized_state
102
130
  case state
103
131
  when 'active'
@@ -106,6 +134,8 @@ module ForemanTasks
106
134
  N_('Cancelled')
107
135
  when 'finished'
108
136
  N_('Finished')
137
+ when 'disabled'
138
+ N_('Disabled')
109
139
  else
110
140
  N_('N/A')
111
141
  end
@@ -0,0 +1,7 @@
1
+ module ForemanTasks
2
+ class RecurringLogicCancelledException < ::Foreman::Exception
3
+ def initialize(msg = N_("Cannot update a cancelled Recurring Logic."))
4
+ super
5
+ end
6
+ end
7
+ end
@@ -65,6 +65,14 @@ module ForemanTasks
65
65
  nil
66
66
  end
67
67
 
68
+ def frozen
69
+ delayed_plan.try(:frozen)
70
+ end
71
+
72
+ def delayed_plan
73
+ ForemanTasks.dynflow.world.persistence.load_delayed_plan(external_id) if state == :scheduled
74
+ end
75
+
68
76
  def execution_plan!
69
77
  execution_plan(false)
70
78
  end
@@ -0,0 +1,3 @@
1
+ object @recurring_logic
2
+
3
+ extends "foreman_tasks/api/recurring_logics/show"
@@ -1,6 +1,10 @@
1
1
  <% title _("Recurring logics") %>
2
2
  <% title_actions SETTINGS[:version].short <= '1.13' ? help_path : help_button %>
3
3
 
4
+ <% if @errors %>
5
+ <%= alert(:class => 'alert-info', :id => 'multiple-alert', :close => false, :header => '', :text => @errors) %>
6
+ <% end %>
7
+
4
8
  <table class="<%= table_css_classes('table-condensed table-fixed') %>">
5
9
  <thead>
6
10
  <th><%= N_("Cron line") %></th>
@@ -114,7 +114,7 @@
114
114
  </div>
115
115
  <div>
116
116
  <span class="param-name list-group-item-heading"><%= _("Execution type") %>:</span>
117
- <span class="param-value"><%= _(@task.execution_type) %></span>
117
+ <span class="param-value"><%= _(@task.execution_type) %> <%= _("(Disabled)") if @task.frozen %></span>
118
118
  </div>
119
119
  </div>
120
120
 
@@ -17,7 +17,7 @@
17
17
  <%= link_to_if_authorized(format_task_input(task),
18
18
  hash_for_foreman_tasks_task_path(:id => task)) %>
19
19
  </td>
20
- <td class="ellipsis"><%= task.state %></td>
20
+ <td class="ellipsis"><%= task.state %> <%= _("(Disabled)") if task.frozen %></td>
21
21
  <td class="ellipsis"><%= task.result %></td>
22
22
  <td class="ellipsis"><%= task.started_at.try(:in_time_zone) %></td>
23
23
  <td class="ellipsis"><%= task.ended_at.try(:in_time_zone) %></td>
data/config/routes.rb CHANGED
@@ -3,6 +3,8 @@ Foreman::Application.routes.draw do
3
3
  resources :recurring_logics, :only => [:index, :show] do
4
4
  member do
5
5
  post :cancel
6
+ put :enable
7
+ put :disable
6
8
  end
7
9
  end
8
10
 
@@ -22,7 +24,7 @@ Foreman::Application.routes.draw do
22
24
  end
23
25
 
24
26
  namespace :api do
25
- resources :recurring_logics, :only => [:index, :show] do
27
+ resources :recurring_logics, :only => [:index, :show, :update] do
26
28
  member do
27
29
  post :cancel
28
30
  end
@@ -29,7 +29,7 @@ same resource. It also optionally provides Dynflow infrastructure for using it f
29
29
  s.extra_rdoc_files = Dir['README*', 'LICENSE']
30
30
 
31
31
  s.add_dependency "foreman-tasks-core"
32
- s.add_dependency "dynflow", '~> 1.0', '>= 1.0.5'
32
+ s.add_dependency "dynflow", '~> 1.0', '>= 1.1.0'
33
33
  s.add_dependency "sinatra" # for Dynflow web console
34
34
  s.add_dependency "parse-cron", '~> 0.1.4'
35
35
  s.add_dependency "get_process_mem" # for memory polling
@@ -66,8 +66,8 @@ module ForemanTasks
66
66
  permission :view_recurring_logics, { :'foreman_tasks/recurring_logics' => [:index, :show],
67
67
  :'foreman_tasks/api/recurring_logics' => [:index, :show] }, :resource_type => ForemanTasks::RecurringLogic.name
68
68
 
69
- permission :edit_recurring_logics, { :'foreman_tasks/recurring_logics' => [:cancel],
70
- :'foreman_tasks/api/recurring_logics' => [:cancel] }, :resource_type => ForemanTasks::RecurringLogic.name
69
+ permission :edit_recurring_logics, { :'foreman_tasks/recurring_logics' => [:cancel, :enable, :disable],
70
+ :'foreman_tasks/api/recurring_logics' => [:cancel, :update] }, :resource_type => ForemanTasks::RecurringLogic.name
71
71
  end
72
72
 
73
73
  add_all_permissions_to_default_roles
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '0.13.4'.freeze
2
+ VERSION = '0.14.0'.freeze
3
3
  end
@@ -28,6 +28,17 @@ module ForemanRecurringLogic
28
28
  end
29
29
  end
30
30
 
31
+ describe 'PUT /api/recurring_logics/:id' do
32
+ it 'updates a recurring logic' do
33
+ @recurring_logic.start(::Support::DummyRecurringDynflowAction)
34
+
35
+ put :update, params: { :id => @recurring_logic.id, :recurring_logic => { :enabled => false } }
36
+ assert_response :success
37
+ assert_template 'api/recurring_logics/update'
38
+ assert @recurring_logic.reload.disabled?
39
+ end
40
+ end
41
+
31
42
  describe 'POST /api/recurring_logics/:id/cancel' do
32
43
  it 'cancels recurring logic' do
33
44
  post :cancel, params: { :id => @recurring_logic.id }
@@ -1,14 +1,37 @@
1
+ require 'test_helper'
1
2
  require 'foreman_tasks_test_helper'
2
3
 
3
4
  module ForemanTasks
4
5
  class RecurringLogicsControllerTest < ActionController::TestCase
5
- basic_index_test('recurring_logics')
6
- basic_pagination_per_page_test
6
+ describe ForemanTasks::RecurringLogicsController do
7
+ basic_index_test('recurring_logics')
8
+ basic_pagination_per_page_test
7
9
 
8
- # rubocop:disable Naming/AccessorMethodName
9
- def get_factory_name
10
- :recurring_logic
10
+ # rubocop:disable Naming/AccessorMethodName
11
+ def get_factory_name
12
+ :recurring_logic
13
+ end
14
+ # rubocop:enable Naming/AccessorMethodName
15
+
16
+ describe 'PUT /recurring_logics/ID/enable' do
17
+ let(:recurring_logic) do
18
+ recurring_logic = FactoryBot.create(:recurring_logic)
19
+ recurring_logic.start(::Support::DummyRecurringDynflowAction)
20
+ recurring_logic
21
+ end
22
+
23
+ it 'disables' do
24
+ put :enable, params: { :id => recurring_logic.id }, session: set_session_user
25
+ assert_redirected_to '/foreman_tasks/recurring_logics'
26
+ end
27
+
28
+ it 'enables' do
29
+ recurring_logic.update(:enabled => false)
30
+ put :disable, params: { :id => recurring_logic.id }, session: set_session_user
31
+
32
+ assert_redirected_to '/foreman_tasks/recurring_logics'
33
+ end
34
+ end
11
35
  end
12
- # rubocop:enable Naming/AccessorMethodName
13
36
  end
14
37
  end
@@ -75,7 +75,7 @@ class RecurringLogicsTest < ActiveSupport::TestCase
75
75
  parser = ForemanTasks::RecurringLogic.new_from_cronline('* * * * *')
76
76
  parser.stubs(:id).returns(1)
77
77
  reference_time = Time.utc(2015, 9, 29, 15)
78
- expected_hash = { :start_at => reference_time + 60, :start_before => nil, :recurring_logic_id => parser.id }
78
+ expected_hash = { :start_at => reference_time + 60, :start_before => nil, :recurring_logic_id => parser.id, :frozen => false }
79
79
  parser.generate_delay_options(reference_time).must_equal expected_hash
80
80
  parser.generate_delay_options(reference_time, 'start_before' => reference_time + 3600)
81
81
  .must_equal expected_hash.merge(:start_before => reference_time + 3600)
@@ -122,6 +122,36 @@ class RecurringLogicsTest < ActiveSupport::TestCase
122
122
  recurring_logic.trigger_repeat('this is not important', 'neither is this')
123
123
  end
124
124
 
125
+ describe 'enable/disable' do
126
+ let(:logic) do
127
+ recurring_logic = ForemanTasks::RecurringLogic.new_from_cronline('0 15 * * *')
128
+
129
+ future_time = Time.zone.now - 1.week
130
+ recurring_logic.start(::Support::DummyRecurringDynflowAction, future_time)
131
+ recurring_logic
132
+ end
133
+
134
+ it 'properly updates on disable' do
135
+ logic.update!(:enabled => false)
136
+
137
+ assert_equal 'disabled', logic.state
138
+
139
+ task = logic.tasks.find_by(:state => 'scheduled')
140
+ assert ForemanTasks.dynflow.world.persistence.load_delayed_plan(task.execution_plan.id).frozen
141
+ end
142
+
143
+ it 'properly re-enables on disable' do
144
+ logic.update!(:enabled => false)
145
+ logic.update!(:enabled => true)
146
+
147
+ assert_equal 'active', logic.state
148
+
149
+ task = logic.tasks.find_by(:state => 'scheduled')
150
+ refute ForemanTasks.dynflow.world.persistence.load_delayed_plan(task.execution_plan.id).frozen
151
+ assert task.start_at > Time.zone.now
152
+ end
153
+ end
154
+
125
155
  describe 'validation' do
126
156
  let(:logic) { FactoryBot.build(:recurring_logic) }
127
157
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.4
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '1.0'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 1.0.5
36
+ version: 1.1.0
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '1.0'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.0.5
46
+ version: 1.1.0
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sinatra
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -127,6 +127,7 @@ files:
127
127
  - app/controllers/foreman_tasks/api/recurring_logics_controller.rb
128
128
  - app/controllers/foreman_tasks/api/tasks_controller.rb
129
129
  - app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb
130
+ - app/controllers/foreman_tasks/concerns/parameters/recurring_logic.rb
130
131
  - app/controllers/foreman_tasks/concerns/parameters/triggering.rb
131
132
  - app/controllers/foreman_tasks/recurring_logics_controller.rb
132
133
  - app/controllers/foreman_tasks/tasks_controller.rb
@@ -159,6 +160,7 @@ files:
159
160
  - app/models/foreman_tasks/concerns/host_action_subject.rb
160
161
  - app/models/foreman_tasks/lock.rb
161
162
  - app/models/foreman_tasks/recurring_logic.rb
163
+ - app/models/foreman_tasks/recurring_logic_cancelled_exception.rb
162
164
  - app/models/foreman_tasks/remote_task.rb
163
165
  - app/models/foreman_tasks/task.rb
164
166
  - app/models/foreman_tasks/task/dynflow_task.rb
@@ -176,6 +178,7 @@ files:
176
178
  - app/views/foreman_tasks/api/recurring_logics/index.json.rabl
177
179
  - app/views/foreman_tasks/api/recurring_logics/main.json.rabl
178
180
  - app/views/foreman_tasks/api/recurring_logics/show.json.rabl
181
+ - app/views/foreman_tasks/api/recurring_logics/update.json.rabl
179
182
  - app/views/foreman_tasks/api/tasks/show.json.rabl
180
183
  - app/views/foreman_tasks/recurring_logics/_tab_related.html.erb
181
184
  - app/views/foreman_tasks/recurring_logics/index.html.erb