foreman-tasks 0.13.4 → 0.14.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 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