foreman-tasks 11.0.0 → 11.0.2
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/.github/workflows/js_tests.yml +8 -27
- data/app/lib/actions/bulk_action.rb +14 -7
- data/app/models/foreman_tasks/triggering.rb +13 -6
- data/lib/foreman_tasks/engine.rb +105 -104
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/factories/triggering_factory.rb +1 -1
- data/test/unit/triggering_test.rb +23 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +1 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14937b8abb913127b2f1ab4028a967e25ed56ae35a476dc99dfd4bce07d9ec2a
|
4
|
+
data.tar.gz: 124922626f20e21268d8fd2c341be934af3d17a1e1fe9df34a61d8a90718508f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed4850116bdc86ba5118a2c1a08e4d475285f3236dee047f8b3c98c24c5eb4030b31a409b0293e5016153e92522f90ef31fccca48e901c7ca30f56b95f55d06b
|
7
|
+
data.tar.gz: c93ab2b4c78fac530e6bef4efca4c0baee0d03931522b15726526406881f8e538cec47dbba5ad863f86faca1a3ec025585453b3b47560435cd56fb1cd6fffb20
|
@@ -1,33 +1,14 @@
|
|
1
1
|
name: JavaScript Testing
|
2
|
+
|
2
3
|
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
3
7
|
pull_request:
|
4
|
-
paths:
|
5
|
-
- 'webpack/**'
|
6
|
-
- 'package.json'
|
7
|
-
- '.github/workflows/js_tests.yml'
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
test_js:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
node-version:
|
16
|
-
- 12
|
17
|
-
- 14
|
18
|
-
steps:
|
19
|
-
- uses: actions/checkout@v2
|
20
|
-
- name: Setup Node
|
21
|
-
uses: actions/setup-node@v1
|
22
|
-
with:
|
23
|
-
node-version: ${{ matrix.node-version }}
|
24
|
-
- name: Npm install
|
25
|
-
run: npm install
|
26
|
-
- name: Run plugin linter
|
27
|
-
run: npm run lint
|
28
|
-
- name: Run plugin tests
|
29
|
-
run: npm run test
|
30
|
-
- name: Publish Coveralls
|
31
|
-
uses: coverallsapp/github-action@master
|
32
|
-
with:
|
33
|
-
github-token: ${{ secrets.GITHUB_TOKEN }}
|
11
|
+
name: JavaScript
|
12
|
+
uses: theforeman/actions/.github/workflows/foreman_plugin_js.yml@v0
|
13
|
+
with:
|
14
|
+
plugin: foreman-tasks
|
@@ -23,11 +23,7 @@ module Actions
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def humanized_name
|
26
|
-
|
27
|
-
task.sub_tasks.first.humanized[:action]
|
28
|
-
else
|
29
|
-
_('Bulk action')
|
30
|
-
end
|
26
|
+
with_sub_task { |t| t.humanized[:action] } || _('Bulk action')
|
31
27
|
end
|
32
28
|
|
33
29
|
def rescue_strategy
|
@@ -35,8 +31,7 @@ module Actions
|
|
35
31
|
end
|
36
32
|
|
37
33
|
def humanized_input
|
38
|
-
|
39
|
-
if a_sub_task
|
34
|
+
with_sub_task do |a_sub_task|
|
40
35
|
[a_sub_task.humanized[:action].to_s.downcase] +
|
41
36
|
Array(a_sub_task.humanized[:input]) + ['...']
|
42
37
|
end
|
@@ -79,5 +74,17 @@ module Actions
|
|
79
74
|
def extract_concurrency_limit(args = [], limit = nil)
|
80
75
|
args.find { |arg| arg.is_a?(Hash) && arg.key?(:concurrency_limit) }&.fetch(:concurrency_limit) || limit
|
81
76
|
end
|
77
|
+
|
78
|
+
def with_sub_task
|
79
|
+
sub_task = begin
|
80
|
+
task.sub_tasks.first
|
81
|
+
rescue ActiveRecord::RecordNotFound
|
82
|
+
# #task raises if the action has no task linked to it
|
83
|
+
# While it shouldn't happen, there's not much of a difference
|
84
|
+
# between a action not having a task and an action having a
|
85
|
+
# task but no sub tasks
|
86
|
+
end
|
87
|
+
yield sub_task if sub_task
|
88
|
+
end
|
82
89
|
end
|
83
90
|
end
|
@@ -8,11 +8,9 @@ module ForemanTasks
|
|
8
8
|
graphql_type '::Types::Triggering'
|
9
9
|
|
10
10
|
before_save do
|
11
|
-
|
11
|
+
unless immediate?
|
12
12
|
parse_start_at!
|
13
13
|
parse_start_before!
|
14
|
-
else
|
15
|
-
self.start_at ||= Time.zone.now
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
@@ -31,20 +29,20 @@ module ForemanTasks
|
|
31
29
|
:inclusion => { :in => ALLOWED_INPUT_TYPES,
|
32
30
|
:message => _('%{value} is not allowed input type') }
|
33
31
|
validates :start_at_raw, format: { :with => TIME_REGEXP, :if => ->(triggering) { triggering.future? || (triggering.recurring? && triggering.start_at_raw) },
|
34
|
-
:message => _('%{value} is wrong format') }
|
32
|
+
:message => _('%{value} is wrong format'), :allow_blank => true }
|
35
33
|
validates :start_before_raw, format: { :with => TIME_REGEXP, :if => :future?,
|
36
34
|
:message => _('%{value} is wrong format'), :allow_blank => true }
|
37
35
|
validates :days, format: { :with => DAYS_REGEXP,
|
38
36
|
:if => proc { |t| t.recurring? && t.input_type == :monthly } }
|
39
37
|
validate :can_start_recurring, :if => :recurring?
|
40
38
|
validate :can_start_future, :if => :future?
|
39
|
+
validate :start_at_is_not_past, :if => ->(triggering) { triggering.start_at_relevant? && triggering.start_at_changed? }
|
41
40
|
|
42
41
|
def self.new_from_params(params = {})
|
43
42
|
new(params.except(:mode, :start_at, :start_before)).tap do |triggering|
|
44
43
|
triggering.mode = params.fetch(:mode, :immediate).to_sym
|
45
44
|
triggering.input_type = params.fetch(:input_type, :daily).to_sym
|
46
45
|
triggering.end_time_limited = params[:end_time_limited] == 'true'
|
47
|
-
triggering.start_at_raw ||= Time.zone.now.strftime(TIME_FORMAT)
|
48
46
|
triggering.recurring_logic = ::ForemanTasks::RecurringLogic.new_from_triggering(triggering) if triggering.recurring?
|
49
47
|
end
|
50
48
|
end
|
@@ -76,7 +74,7 @@ module ForemanTasks
|
|
76
74
|
|
77
75
|
def delay_options
|
78
76
|
{
|
79
|
-
:start_at => start_at.utc,
|
77
|
+
:start_at => start_at.try(:utc),
|
80
78
|
:start_before => start_before.try(:utc),
|
81
79
|
}
|
82
80
|
end
|
@@ -107,6 +105,11 @@ module ForemanTasks
|
|
107
105
|
self.start_before ||= Time.zone.parse(start_before_raw) if start_before_raw.present?
|
108
106
|
end
|
109
107
|
|
108
|
+
# start_at is required for future execution and optional for recurring execution
|
109
|
+
def start_at_relevant?
|
110
|
+
future? || (recurring? && (start_at || start_at_raw))
|
111
|
+
end
|
112
|
+
|
110
113
|
private
|
111
114
|
|
112
115
|
def can_start_recurring
|
@@ -121,5 +124,9 @@ module ForemanTasks
|
|
121
124
|
parse_start_at!
|
122
125
|
errors.add(:start_before_raw, _('The task could not be started')) if !start_before.nil? && start_before < start_at
|
123
126
|
end
|
127
|
+
|
128
|
+
def start_at_is_not_past
|
129
|
+
errors.add(:start_at, _('is in the past')) if !start_at.nil? && start_at < Time.zone.now
|
130
|
+
end
|
124
131
|
end
|
125
132
|
end
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -16,121 +16,122 @@ module ForemanTasks
|
|
16
16
|
SETTINGS[:foreman_tasks] = { :assets => { :precompile => assets_to_precompile } }
|
17
17
|
end
|
18
18
|
|
19
|
-
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
19
|
+
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do
|
20
|
+
Foreman::Plugin.register :"foreman-tasks" do
|
21
|
+
requires_foreman '>= 3.15'
|
22
|
+
divider :top_menu, :parent => :monitor_menu, :last => true, :caption => N_('Foreman Tasks')
|
23
|
+
menu :top_menu, :tasks,
|
24
|
+
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
25
|
+
:caption => N_('Tasks'),
|
26
|
+
:parent => :monitor_menu,
|
27
|
+
:last => true
|
28
|
+
|
29
|
+
menu :top_menu, :recurring_logics,
|
30
|
+
:url_hash => { :controller => 'foreman_tasks/recurring_logics', :action => :index },
|
31
|
+
:caption => N_('Recurring Logics'),
|
32
|
+
:parent => :monitor_menu,
|
33
|
+
:last => true
|
34
|
+
|
35
|
+
security_block :foreman_tasks do |_map|
|
36
|
+
permission :view_foreman_tasks, { :'foreman_tasks/tasks' => [:auto_complete_search, :sub_tasks, :index, :summary, :summary_sub_tasks, :show],
|
37
|
+
:'foreman_tasks/react' => [:index],
|
38
|
+
:'foreman_tasks/api/tasks' => [:bulk_search, :show, :index, :summary, :summary_sub_tasks, :details, :sub_tasks] }, :resource_type => 'ForemanTasks::Task'
|
39
|
+
permission :edit_foreman_tasks, { :'foreman_tasks/tasks' => [:resume, :unlock, :force_unlock, :cancel_step, :cancel, :abort],
|
40
|
+
:'foreman_tasks/api/tasks' => [:bulk_resume, :bulk_cancel, :bulk_stop] }, :resource_type => 'ForemanTasks::Task'
|
41
|
+
|
42
|
+
permission :create_recurring_logics, {}, :resource_type => 'ForemanTasks::RecurringLogic'
|
43
|
+
|
44
|
+
permission :view_recurring_logics, { :'foreman_tasks/recurring_logics' => [:auto_complete_search, :index, :show],
|
45
|
+
:'foreman_tasks/api/recurring_logics' => [:index, :show] }, :resource_type => 'ForemanTasks::RecurringLogic'
|
46
|
+
|
47
|
+
permission :edit_recurring_logics, { :'foreman_tasks/recurring_logics' => [:cancel, :enable, :disable, :clear_cancelled],
|
48
|
+
:'foreman_tasks/api/recurring_logics' => [:cancel, :update, :bulk_destroy] }, :resource_type => 'ForemanTasks::RecurringLogic'
|
49
|
+
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
51
|
+
add_all_permissions_to_default_roles
|
52
|
+
|
53
|
+
settings do
|
54
|
+
category(:tasks, N_('Tasks')) do
|
55
|
+
setting('foreman_tasks_sync_task_timeout',
|
56
|
+
type: :integer,
|
57
|
+
description: N_('Number of seconds to wait for synchronous task to finish.'),
|
58
|
+
default: 120,
|
59
|
+
full_name: N_('Sync task timeout'))
|
60
|
+
setting('dynflow_enable_console',
|
61
|
+
type: :boolean,
|
62
|
+
description: N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'),
|
63
|
+
default: true,
|
64
|
+
full_name: N_('Enable dynflow console'))
|
65
|
+
setting('dynflow_console_require_auth',
|
66
|
+
type: :boolean,
|
67
|
+
description: N_('Require user to be authenticated as user with admin rights when accessing dynflow console'),
|
68
|
+
default: true,
|
69
|
+
full_name: N_('Require auth for dynflow console'))
|
70
|
+
setting('foreman_tasks_proxy_action_retry_count',
|
71
|
+
type: :integer,
|
72
|
+
description: N_('Number of attempts to start a task on the smart proxy before failing'),
|
73
|
+
default: 4,
|
74
|
+
full_name: N_('Proxy action retry count'))
|
75
|
+
setting('foreman_tasks_proxy_action_retry_interval',
|
76
|
+
type: :integer,
|
77
|
+
description: N_('Time in seconds between retries'),
|
78
|
+
default: 15,
|
79
|
+
full_name: N_('Proxy action retry interval'))
|
80
|
+
setting('foreman_tasks_proxy_batch_trigger',
|
81
|
+
type: :boolean,
|
82
|
+
description: N_('Allow triggering tasks on the smart proxy in batches'),
|
83
|
+
default: true,
|
84
|
+
full_name: N_('Allow proxy batch tasks'))
|
85
|
+
setting('foreman_tasks_proxy_batch_size',
|
86
|
+
type: :integer,
|
87
|
+
description: N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'),
|
88
|
+
default: 100,
|
89
|
+
full_name: N_('Proxy tasks batch size'))
|
90
|
+
setting('foreman_tasks_troubleshooting_url',
|
91
|
+
type: :string,
|
92
|
+
description: N_('Url pointing to the task troubleshooting documentation. '\
|
93
|
+
'It should contain %{label} placeholder, that will be replaced with normalized task label '\
|
94
|
+
'(restricted to only alphanumeric characters)). %{version} placeholder is also available.'),
|
95
|
+
default: nil,
|
96
|
+
full_name: N_('Tasks troubleshooting URL'))
|
97
|
+
setting('foreman_tasks_polling_multiplier',
|
98
|
+
type: :integer,
|
99
|
+
description: N_('Polling multiplier which is used to multiply the default polling intervals. '\
|
100
|
+
'This can be used to prevent polling too frequently for long running tasks.'),
|
101
|
+
default: 1,
|
102
|
+
full_name: N_("Polling intervals multiplier"),
|
103
|
+
validate: { numericality: { greater_than: 0 } })
|
106
104
|
end
|
105
|
+
end
|
107
106
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
register_graphql_mutation_field :cancel_recurring_logic, '::Mutations::RecurringLogics::Cancel'
|
107
|
+
register_graphql_query_field :task, '::Types::Task', :record_field
|
108
|
+
register_graphql_query_field :tasks, '::Types::Task', :collection_field
|
109
|
+
register_graphql_query_field :recurring_logic, '::Types::RecurringLogic', :record_field
|
110
|
+
register_graphql_query_field :recurring_logics, '::Types::RecurringLogic', :collection_field
|
114
111
|
|
115
|
-
|
116
|
-
logger :action, :enabled => true
|
112
|
+
register_graphql_mutation_field :cancel_recurring_logic, '::Mutations::RecurringLogics::Cancel'
|
117
113
|
|
118
|
-
|
119
|
-
|
120
|
-
role 'Tasks Reader', [:view_foreman_tasks],
|
121
|
-
'Role granting permissions to inspect tasks'
|
114
|
+
logger :dynflow, :enabled => true
|
115
|
+
logger :action, :enabled => true
|
122
116
|
|
123
|
-
|
124
|
-
|
117
|
+
role 'Tasks Manager', [:view_foreman_tasks, :edit_foreman_tasks],
|
118
|
+
'Role granting permissions to inspect, cancel, resume and unlock tasks'
|
119
|
+
role 'Tasks Reader', [:view_foreman_tasks],
|
120
|
+
'Role granting permissions to inspect tasks'
|
125
121
|
|
126
|
-
|
122
|
+
widget 'foreman_tasks/tasks/dashboard/tasks_status', :sizex => 6, :sizey => 1, :name => N_('Task Status')
|
123
|
+
widget 'foreman_tasks/tasks/dashboard/latest_tasks_in_error_warning', :sizex => 6, :sizey => 1, :name => N_('Latest Warning/Error Tasks')
|
127
124
|
|
128
|
-
|
129
|
-
extend_observable_events(::Dynflow::Action.descendants.select { |klass| klass <= ::Actions::ObservableAction }.map(&:namespaced_event_names))
|
130
|
-
end
|
125
|
+
register_gettext domain: "foreman_tasks"
|
131
126
|
end
|
132
127
|
end
|
133
128
|
|
129
|
+
config.after_initialize do
|
130
|
+
ForemanTasks.dynflow.eager_load_actions!
|
131
|
+
plugin = ::Foreman::Plugin.find("foreman-tasks")
|
132
|
+
plugin.extend_observable_events(::Dynflow::Action.descendants.select { |klass| klass <= ::Actions::ObservableAction }.map(&:namespaced_event_names))
|
133
|
+
end
|
134
|
+
|
134
135
|
initializer 'foreman_tasks.apipie' do
|
135
136
|
# this condition is here for compatibility reason to work with Foreman 1.4.x
|
136
137
|
if Apipie.configuration.api_controllers_matcher.is_a?(Array) &&
|
@@ -13,6 +13,13 @@ class TriggeringTest < ActiveSupport::TestCase
|
|
13
13
|
assert_not_predicate(triggering, :valid?)
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'is invalid when future execution is in the past' do
|
17
|
+
triggering = FactoryBot.build(:triggering, :future)
|
18
|
+
assert_predicate(triggering, :valid?)
|
19
|
+
triggering.start_at = Time.zone.now - 1.day
|
20
|
+
assert_not_predicate(triggering, :valid?)
|
21
|
+
end
|
22
|
+
|
16
23
|
it 'is invalid when recurring logic is invalid' do
|
17
24
|
triggering = FactoryBot.build(:triggering, :recurring)
|
18
25
|
assert_predicate(triggering, :valid?)
|
@@ -41,6 +48,22 @@ class TriggeringTest < ActiveSupport::TestCase
|
|
41
48
|
triggering = FactoryBot.build(:triggering, :recurring_logic => logic, :mode => :recurring, :input_type => :cronline, :cronline => '* * * * *')
|
42
49
|
assert_predicate(triggering, :valid?)
|
43
50
|
end
|
51
|
+
|
52
|
+
it 'is valid by default' do
|
53
|
+
triggering = ForemanTasks::Triggering.new_from_params
|
54
|
+
assert triggering.save
|
55
|
+
assert_predicate triggering.start_at, :blank?
|
56
|
+
assert_predicate triggering, :valid?
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'stays valid once created' do
|
60
|
+
triggering = ForemanTasks::Triggering.new_from_params({ :mode => "future" })
|
61
|
+
triggering.start_at = Time.zone.now + 1.second
|
62
|
+
triggering.save!
|
63
|
+
assert_predicate(triggering, :valid?)
|
64
|
+
Time.zone.expects(:now).never # No time comparisons should be done as nothing changed
|
65
|
+
assert_predicate(triggering, :valid?)
|
66
|
+
end
|
44
67
|
end
|
45
68
|
|
46
69
|
it 'cannot have mode set to arbitrary value' do
|
@@ -1,5 +1,5 @@
|
|
1
|
-
@import '
|
2
|
-
@import '
|
1
|
+
@import 'foremanReact/common/variables';
|
2
|
+
@import 'foremanReact/common/scss/mixins';
|
3
3
|
|
4
4
|
@mixin create-tasks-dashboard-column($columns: 12, $screen-min: 0, $gutter: $grid-gutter-width) {
|
5
5
|
@media (min-width: $screen-min) {
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 11.0.
|
4
|
+
version: 11.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: dynflow
|
@@ -117,8 +117,8 @@ email:
|
|
117
117
|
executables: []
|
118
118
|
extensions: []
|
119
119
|
extra_rdoc_files:
|
120
|
-
- README.md
|
121
120
|
- LICENSE
|
121
|
+
- README.md
|
122
122
|
files:
|
123
123
|
- ".eslintrc"
|
124
124
|
- ".github/workflows/js_tests.yml"
|
@@ -640,7 +640,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
640
640
|
- !ruby/object:Gem::Version
|
641
641
|
version: '0'
|
642
642
|
requirements: []
|
643
|
-
rubygems_version: 3.6.
|
643
|
+
rubygems_version: 3.6.9
|
644
644
|
specification_version: 4
|
645
645
|
summary: Foreman plugin for showing tasks information for resources and users
|
646
646
|
test_files:
|