foreman-tasks 0.15.1 → 0.15.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.babelrc +9 -1
- data/.eslintrc +6 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -0
- data/.storybook/webpack.config.js +51 -54
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +0 -2
- data/app/controllers/foreman_tasks/tasks_controller.rb +6 -1
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +8 -0
- data/app/lib/actions/base.rb +7 -0
- data/app/lib/actions/helpers/lifecycle_logging.rb +21 -0
- data/app/lib/actions/proxy_action.rb +4 -2
- data/app/models/foreman_tasks/task.rb +23 -0
- data/app/models/foreman_tasks/task/summarizer.rb +96 -6
- data/app/models/foreman_tasks/triggering.rb +2 -2
- data/app/models/setting/foreman_tasks.rb +8 -1
- data/app/services/foreman_tasks/dashboard_table_filter.rb +47 -0
- data/app/services/foreman_tasks/troubleshooting_help_generator.rb +92 -0
- data/app/services/ui_notifications/tasks.rb +20 -0
- data/app/services/ui_notifications/tasks/task_paused_admin.rb +43 -0
- data/app/services/ui_notifications/tasks/task_paused_owner.rb +30 -0
- data/app/views/foreman_tasks/tasks/_details.html.erb +5 -3
- data/app/views/foreman_tasks/tasks/index.html.erb +13 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20190318153925_add_task_state_updated_at.foreman_tasks.rb +5 -0
- data/db/migrate/20190404132157_add_implicit_varchar_uuid_cast.rb +25 -0
- data/db/seeds.d/30-notification_blueprints.rb +33 -0
- data/foreman-tasks.gemspec +1 -1
- data/lib/foreman_tasks/cleaner.rb +5 -4
- data/lib/foreman_tasks/engine.rb +1 -1
- data/lib/foreman_tasks/test_helpers.rb +10 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/package.json +14 -11
- data/test/controllers/tasks_controller_test.rb +10 -0
- data/test/foreman_tasks_test_helper.rb +4 -0
- data/test/support/dummy_dynflow_action.rb +29 -0
- data/test/support/history_tasks_builder.rb +42 -0
- data/test/unit/actions/action_with_sub_plans_test.rb +4 -1
- data/test/unit/actions/bulk_action_test.rb +2 -0
- data/test/unit/cleaner_test.rb +15 -0
- data/test/unit/dashboard_table_filter_test.rb +65 -0
- data/test/unit/summarizer_test.rb +39 -0
- data/test/unit/task_test.rb +14 -0
- data/test/unit/troubleshooting_help_generator_test.rb +71 -0
- data/test/unit/ui_notifications_test.rb +86 -0
- data/webpack/ForemanTasks/Components/Chart/Chart.js +128 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.js +20 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.stories.js +51 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +11 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +36 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.js +20 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.stories.js +51 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +11 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +36 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +64 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +25 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.stories.js +28 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +18 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +94 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +89 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +46 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.stories.js +72 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +48 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardHelper.js +63 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +973 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +96 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +17 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.stories.js +46 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +43 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/__snapshots__/TasksDonutCard.test.js.snap +183 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.js +166 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.scss +24 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.stories.js +25 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +40 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartConstants.js +13 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.js +94 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.test.js +152 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChart.test.js.snap +302 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChartHelper.test.js.snap +21 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.fixtures.js +25 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.js +72 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.stories.js +52 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +21 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +223 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.js +57 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +26 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.stories.js +22 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +57 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/__snapshots__/TasksLabelsRow.test.js.snap +47 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.js +51 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.js +23 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +19 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/__snapshots__/TimeDropDown.test.js.snap +85 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.js +33 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.scss +11 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.stories.js +22 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.test.js +15 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/__snapshots__/TasksTimeRow.test.js.snap +41 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +77 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +6 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +62 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +94 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +78 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardPropTypes.js +13 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardReducer.js +50 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +44 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +13 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +37 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardHelper.test.js +36 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js +58 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test..js +59 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +51 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardActions.test.js.snap +61 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardReducer.test.js.snap +280 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/index.js +25 -0
- data/webpack/ForemanTasks/ForemanTasksReducers.js +10 -0
- data/webpack/ForemanTasks/ForemanTasksSelectors.js +1 -0
- data/webpack/__mocks__/foremanReact/API.js +7 -0
- data/webpack/__mocks__/foremanReact/common/I18n.js +5 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +3 -0
- data/webpack/index.js +13 -1
- data/webpack/stories/decorators/index.js +1 -0
- data/webpack/stories/decorators/withCardsDecorator.js +14 -0
- data/webpack/stories/index.js +1 -3
- data/webpack/stories/index.scss +6 -0
- metadata +101 -8
- data/webpack/ForemanTasks/components/Hello/Hello.stories.js +0 -5
- data/webpack/ForemanTasks/components/Hello/__tests__/Hello.test.js +0 -11
- data/webpack/ForemanTasks/components/Hello/__tests__/__snapshots__/Hello.test.js.snap +0 -7
- data/webpack/ForemanTasks/components/Hello/index.js +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9daa93c0112f4c796a124787624ad95f01e241bcc2f80912560eb548cabc080d
|
4
|
+
data.tar.gz: 0f2577e225a712c6e5041cb9c5006ac5707bf6f36cde9d9525f5118557037249
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5aafc0509dedd3a27aeadbca202772220916f0e3ac20b35f28a8f25ece3190273b7c845f054d0be09ff1298a9cd244430cadf9294566a1cbfa570054a1a0de99
|
7
|
+
data.tar.gz: 25705ff172efabb0cbba2725c61571f113a017cc85c4a386825d151dac30799d3c7257b38640c7a5ee7f460bcd1baa3a6e2d7b221397c57debba3e62c2949a0f
|
data/.babelrc
CHANGED
@@ -18,7 +18,15 @@
|
|
18
18
|
],
|
19
19
|
"env": {
|
20
20
|
"test": {
|
21
|
-
"plugins": [
|
21
|
+
"plugins": [
|
22
|
+
["module-resolver", {
|
23
|
+
"alias": {
|
24
|
+
"root": ["./"],
|
25
|
+
"foremanReact": "./webpack/__mocks__/foremanReact"
|
26
|
+
}
|
27
|
+
}],
|
28
|
+
"dynamic-import-node"
|
29
|
+
]
|
22
30
|
}
|
23
31
|
}
|
24
32
|
}
|
data/.eslintrc
CHANGED
@@ -5,6 +5,12 @@
|
|
5
5
|
"prettier/prettier": ["error", {
|
6
6
|
"singleQuote": true,
|
7
7
|
"trailingComma": "es5"
|
8
|
+
}],
|
9
|
+
"import/no-unresolved": ["error", {
|
10
|
+
"ignore": ['foremanReact/.*']
|
11
|
+
}],
|
12
|
+
"import/extensions": ["error", {
|
13
|
+
"ignore": ['foremanReact/.*']
|
8
14
|
}]
|
9
15
|
},
|
10
16
|
"settings": {
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,66 +1,63 @@
|
|
1
1
|
let path = require('path');
|
2
2
|
|
3
|
-
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
exclude: /node_modules/,
|
11
|
-
loader: 'babel-loader',
|
12
|
-
options: {
|
13
|
-
presets: [
|
14
|
-
path.join(__dirname, '..', 'node_modules/babel-preset-react'),
|
15
|
-
path.join(__dirname, '..', 'node_modules/babel-preset-env')
|
16
|
-
],
|
17
|
-
plugins: [
|
18
|
-
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-class-properties'),
|
19
|
-
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-object-rest-spread'),
|
20
|
-
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-object-assign'),
|
21
|
-
path.join(__dirname, '..', 'node_modules/babel-plugin-syntax-dynamic-import')
|
22
|
-
]
|
23
|
-
}
|
24
|
-
},
|
25
|
-
{
|
26
|
-
test: /(\.png|\.gif)$/,
|
27
|
-
loader: 'url-loader?limit=32767'
|
28
|
-
},
|
29
|
-
{
|
30
|
-
test: /\.css$/,
|
31
|
-
loaders: ['style-loader', 'css-loader']
|
32
|
-
},
|
33
|
-
{
|
34
|
-
test: /\.scss$/,
|
35
|
-
loaders: ['style-loader', 'css-loader', {
|
36
|
-
loader: 'sass-loader',
|
3
|
+
module.exports = {
|
4
|
+
module: {
|
5
|
+
rules: [
|
6
|
+
{
|
7
|
+
test: /\.js$/,
|
8
|
+
exclude: /node_modules/,
|
9
|
+
loader: 'babel-loader',
|
37
10
|
options: {
|
38
|
-
|
39
|
-
|
40
|
-
path.
|
41
|
-
|
42
|
-
|
11
|
+
presets: [
|
12
|
+
path.join(__dirname, '..', 'node_modules/babel-preset-react'),
|
13
|
+
path.join(__dirname, '..', 'node_modules/babel-preset-env')
|
14
|
+
],
|
15
|
+
plugins: [
|
16
|
+
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-class-properties'),
|
17
|
+
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-object-rest-spread'),
|
18
|
+
path.join(__dirname, '..', 'node_modules/babel-plugin-transform-object-assign'),
|
19
|
+
path.join(__dirname, '..', 'node_modules/babel-plugin-syntax-dynamic-import')
|
43
20
|
]
|
44
21
|
}
|
45
|
-
}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
22
|
+
},
|
23
|
+
{
|
24
|
+
test: /(\.png|\.gif)$/,
|
25
|
+
loader: 'url-loader?limit=32767'
|
26
|
+
},
|
27
|
+
{
|
28
|
+
test: /\.css$/,
|
29
|
+
loaders: ['style-loader', 'css-loader'],
|
30
|
+
},
|
31
|
+
{
|
32
|
+
test: /\.scss$/,
|
33
|
+
loaders: ['style-loader', 'css-loader', {
|
34
|
+
loader: 'sass-loader',
|
35
|
+
options: {
|
36
|
+
includePaths: [
|
37
|
+
// teach webpack to resolve patternfly dependencies
|
38
|
+
path.resolve(__dirname, '..', 'node_modules', 'patternfly', 'dist', 'sass'),
|
39
|
+
path.resolve(__dirname, '..', 'node_modules', 'bootstrap-sass', 'assets', 'stylesheets'),
|
40
|
+
path.resolve(__dirname, '..', 'node_modules', 'font-awesome-sass', 'assets', 'stylesheets')
|
41
|
+
]
|
42
|
+
}
|
43
|
+
}]
|
44
|
+
},
|
45
|
+
{
|
46
|
+
test: /\.md$/,
|
47
|
+
loaders: ['raw-loader']
|
48
|
+
},
|
49
|
+
{
|
50
|
+
test: /(\.ttf|\.woff|\.woff2|\.eot|\.svg|\.jpg)$/,
|
51
|
+
loaders: ['url-loader']
|
52
|
+
},
|
53
|
+
],
|
54
|
+
},
|
56
55
|
|
57
|
-
|
56
|
+
resolve: {
|
58
57
|
modules: [
|
59
58
|
path.join(__dirname, '..', 'webpack'),
|
60
59
|
path.join(__dirname, '..', 'node_modules'),
|
61
60
|
'node_modules/',
|
62
61
|
],
|
63
|
-
}
|
64
|
-
|
65
|
-
return defaultConfig;
|
62
|
+
},
|
66
63
|
};
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module ForemanTasks
|
2
|
-
# rubocop:disable Metrics/ClassLength
|
3
2
|
module Api
|
4
3
|
class TasksController < ::Api::V2::BaseController
|
5
4
|
include ::Foreman::Controller::SmartProxyAuth
|
@@ -285,5 +284,4 @@ module ForemanTasks
|
|
285
284
|
end
|
286
285
|
end
|
287
286
|
end
|
288
|
-
# rubocop:enable Metrics/ClassLength
|
289
287
|
end
|
@@ -24,6 +24,10 @@ module ForemanTasks
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def summary
|
28
|
+
render json: Task::Summarizer.new(params[:recent_timeframe].to_i).summary
|
29
|
+
end
|
30
|
+
|
27
31
|
def sub_tasks
|
28
32
|
task = Task.find(params[:id])
|
29
33
|
@tasks = filter(task.sub_tasks)
|
@@ -109,7 +113,7 @@ module ForemanTasks
|
|
109
113
|
|
110
114
|
def action_permission
|
111
115
|
case params[:action]
|
112
|
-
when 'sub_tasks'
|
116
|
+
when 'sub_tasks', 'summary'
|
113
117
|
:view
|
114
118
|
when 'resume', 'unlock', 'force_unlock', 'cancel_step', 'cancel', 'abort'
|
115
119
|
:edit
|
@@ -129,6 +133,7 @@ module ForemanTasks
|
|
129
133
|
def filter(scope, paginate: true)
|
130
134
|
search = current_taxonomy_search
|
131
135
|
search = [search, params[:search]].select(&:present?).join(' AND ')
|
136
|
+
scope = DashboardTableFilter.new(scope, params).scope
|
132
137
|
scope = scope.search_for(search, :order => params[:order])
|
133
138
|
scope = scope.paginate(:page => params[:page], :per_page => params[:per_page]) if paginate
|
134
139
|
scope.distinct
|
@@ -17,6 +17,14 @@ module ForemanTasks
|
|
17
17
|
content_tag(:i, ' '.html_safe, :class => "glyphicon #{icon}") + content_tag(:span, recurring_logic.humanized_state, :class => status)
|
18
18
|
end
|
19
19
|
|
20
|
+
def troubleshooting_info
|
21
|
+
return if @task.state != 'paused' || @task.main_action.nil?
|
22
|
+
helper = TroubleshootingHelpGenerator.new(@task.main_action)
|
23
|
+
ret = '<p><b>Troubleshooting</b></p>'
|
24
|
+
ret += '<p>%{help}</p>' % { help: helper.generate_html }
|
25
|
+
ret.html_safe
|
26
|
+
end
|
27
|
+
|
20
28
|
def task_result_icon_class(task)
|
21
29
|
return 'task-status pficon-help' if task.state != 'stopped'
|
22
30
|
|
data/app/lib/actions/base.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Actions
|
2
2
|
class Base < Dynflow::Action
|
3
3
|
middleware.use ::Actions::Middleware::RailsExecutorWrap
|
4
|
+
include Actions::Helpers::LifecycleLogging
|
5
|
+
|
6
|
+
execution_plan_hooks.use :notify_paused, :on => [:paused]
|
4
7
|
|
5
8
|
def task
|
6
9
|
@task ||= ::ForemanTasks::Task::DynflowTask.where(:external_id => execution_plan_id).first!
|
@@ -52,5 +55,9 @@ module Actions
|
|
52
55
|
def serializer_class
|
53
56
|
::Actions::Serializers::ActiveRecordSerializer
|
54
57
|
end
|
58
|
+
|
59
|
+
def notify_paused(*_args)
|
60
|
+
task.build_notifications.each(&:deliver!) if root_action?
|
61
|
+
end
|
55
62
|
end
|
56
63
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Actions
|
2
|
+
module Helpers
|
3
|
+
module LifecycleLogging
|
4
|
+
def self.included(base)
|
5
|
+
base.execution_plan_hooks.use :log_task_state_change
|
6
|
+
end
|
7
|
+
|
8
|
+
def log_task_state_change(execution_plan)
|
9
|
+
return unless root_action?
|
10
|
+
logger = Rails.application.dynflow.world.action_logger
|
11
|
+
task_id = ForemanTasks::Task::DynflowTask.where(external_id: execution_plan.id).pluck(:id).first
|
12
|
+
|
13
|
+
task_id_parts = []
|
14
|
+
task_id_parts << "id: #{task_id}" if task_id
|
15
|
+
task_id_parts << "execution_plan_id: #{execution_plan.id}"
|
16
|
+
result_info = " result: #{execution_plan.result}" if [:stopped, :paused].include?(execution_plan.state)
|
17
|
+
logger.info("Task {label: #{execution_plan.label}, #{task_id_parts.join(', ')}} state changed: #{execution_plan.state} #{result_info}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -154,7 +154,9 @@ module Actions
|
|
154
154
|
if output.key?(:proxy_output) || state == :error
|
155
155
|
output.fetch(:proxy_output, {})
|
156
156
|
elsif live && proxy_task_id
|
157
|
-
proxy_data = proxy.status_of_task(proxy_task_id)['actions'].detect
|
157
|
+
proxy_data = proxy.status_of_task(proxy_task_id)['actions'].detect do |action|
|
158
|
+
action['class'] == proxy_action_name || action.fetch('input', {})['proxy_operation_name'] == proxy_operation_name
|
159
|
+
end
|
158
160
|
proxy_data.fetch('output', {})
|
159
161
|
else
|
160
162
|
{}
|
@@ -193,7 +195,7 @@ module Actions
|
|
193
195
|
end
|
194
196
|
|
195
197
|
def with_batch_triggering?(proxy_version)
|
196
|
-
(proxy_version[:major] == 1 && proxy_version[:minor] > 20) || proxy_version[:major] > 1 &&
|
198
|
+
((proxy_version[:major] == 1 && proxy_version[:minor] > 20) || proxy_version[:major] > 1) &&
|
197
199
|
input.fetch(:connection_options, {}).fetch(:proxy_batch_triggering, false)
|
198
200
|
end
|
199
201
|
|
@@ -15,6 +15,7 @@ module ForemanTasks
|
|
15
15
|
|
16
16
|
self.primary_key = :id
|
17
17
|
before_create :generate_id
|
18
|
+
before_save :update_state_updated_at
|
18
19
|
|
19
20
|
belongs_to :parent_task, :class_name => 'ForemanTasks::Task'
|
20
21
|
has_many :sub_tasks, :class_name => 'ForemanTasks::Task', :foreign_key => :parent_task_id, :dependent => :nullify
|
@@ -39,6 +40,7 @@ module ForemanTasks
|
|
39
40
|
scoped_search :on => :state, :complete_value => true
|
40
41
|
scoped_search :on => :result, :complete_value => true
|
41
42
|
scoped_search :on => :started_at, :complete_value => false
|
43
|
+
scoped_search :on => :state_updated_at, :complete_value => false
|
42
44
|
scoped_search :on => :start_at, :complete_value => false
|
43
45
|
scoped_search :on => :ended_at, :complete_value => false
|
44
46
|
scoped_search :on => :parent_task_id, :complete_value => true
|
@@ -146,6 +148,23 @@ module ForemanTasks
|
|
146
148
|
end
|
147
149
|
end
|
148
150
|
|
151
|
+
# used by Foreman notifications framework
|
152
|
+
def notification_recipients_ids
|
153
|
+
owner_ids
|
154
|
+
end
|
155
|
+
|
156
|
+
def build_notifications
|
157
|
+
notifications = []
|
158
|
+
if paused?
|
159
|
+
owner = self.owner
|
160
|
+
if owner && !owner.hidden?
|
161
|
+
notifications << UINotifications::Tasks::TaskPausedOwner.new(self)
|
162
|
+
end
|
163
|
+
notifications << UINotifications::Tasks::TaskPausedAdmin.new(self)
|
164
|
+
end
|
165
|
+
notifications
|
166
|
+
end
|
167
|
+
|
149
168
|
def self.search_by_generic_resource(key, operator, value)
|
150
169
|
key = 'resource_type' if key.blank?
|
151
170
|
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
@@ -269,5 +288,9 @@ module ForemanTasks
|
|
269
288
|
def generate_id
|
270
289
|
self.id ||= SecureRandom.uuid
|
271
290
|
end
|
291
|
+
|
292
|
+
def update_state_updated_at
|
293
|
+
self.state_updated_at = Time.now.utc if changes.key?(:state)
|
294
|
+
end
|
272
295
|
end
|
273
296
|
end
|
@@ -1,15 +1,105 @@
|
|
1
1
|
module ForemanTasks
|
2
2
|
class Task::Summarizer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
ENSURED_STATE_KEYS = %w[running paused stopped scheduled].freeze
|
4
|
+
ENSURED_RESULT_KEYS = %w[success error warning].freeze
|
5
|
+
|
6
|
+
# number of recent/total tasks for specific classification (state/result)
|
7
|
+
class Record
|
8
|
+
def initialize
|
9
|
+
@data = { recent: 0, total: 0 }
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_h
|
13
|
+
@data.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
# updates `field` (one of [:recent, :total]) with counts from aggregated_scope
|
17
|
+
def update(field, counts)
|
18
|
+
raise ArgumentError, "Unexpected field #{field}" unless @data.key?(field)
|
19
|
+
@data[field] = counts.sum(&:count)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# number of recent/total tasks for specific state + distribution across different results
|
24
|
+
# in `by_result` attribute
|
25
|
+
class RecordWithResult < Record
|
26
|
+
attr_reader :by_result
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
@by_result = Hash.new { |h, k| h[k] = Record.new }
|
31
|
+
ENSURED_RESULT_KEYS.each { |result_value| @by_result[result_value] = Record.new }
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
by_result_hash = @by_result.each.with_object({}) do |(result, record), hash|
|
36
|
+
hash[result] = record.to_h
|
37
|
+
end
|
38
|
+
super.update(by_result: by_result_hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Updates the `field` summary + grouping by result
|
42
|
+
def update(field, counts)
|
43
|
+
super(field, counts)
|
44
|
+
counts.group_by(&:result).each do |(result, result_counts)|
|
45
|
+
@by_result[result].update(field, result_counts)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(recent_timeframe = 24)
|
51
|
+
@recent_timeframe = recent_timeframe.hours
|
52
|
+
end
|
53
|
+
|
54
|
+
def summarize_by_status
|
55
|
+
aggregated_scope.where("result <> 'success'")
|
9
56
|
end
|
10
57
|
|
11
58
|
def latest_tasks_in_errors_warning(limit = 5)
|
12
59
|
::ForemanTasks::Task.where('result in (?)', %w[error warning]).order('started_at DESC').limit(limit)
|
13
60
|
end
|
61
|
+
|
62
|
+
# Returns summary of tasks count, grouped by `state` and `result`, if form of:
|
63
|
+
#
|
64
|
+
# { 'running' => { recent: 3, total: 6 },
|
65
|
+
# 'paused' => { recent: 1, total: 3 },
|
66
|
+
# 'stopped' => { recent: 3, total: 7,
|
67
|
+
# by_result: {
|
68
|
+
# 'success' => { recent: 2, total: 4 },
|
69
|
+
# 'warning' => { recent: 1, total: 2 },
|
70
|
+
# 'error' => { recent: 0, total: 1 },
|
71
|
+
# }}
|
72
|
+
# 'scheduled' => { recent: 0, total: 3 }}
|
73
|
+
#
|
74
|
+
def summary
|
75
|
+
@summary = Hash.new { |h, state| h[state] = Record.new }
|
76
|
+
ENSURED_STATE_KEYS.each do |state|
|
77
|
+
@summary[state] = state == 'stopped' ? RecordWithResult.new : Record.new
|
78
|
+
end
|
79
|
+
|
80
|
+
add_to_summary(aggregated_scope, :total)
|
81
|
+
add_to_summary(aggregated_recent_scope, :recent)
|
82
|
+
|
83
|
+
@summary.each.with_object({}) do |(key, record), hash|
|
84
|
+
hash[key] = record.to_h
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def add_to_summary(aggregated_scope, field)
|
91
|
+
aggregated_scope.group_by(&:state).each do |(state, state_counts)|
|
92
|
+
@summary[state].update(field, state_counts)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def aggregated_scope
|
97
|
+
::ForemanTasks::Task.select('count(state) AS count, state, result, max(started_at) AS started_at')
|
98
|
+
.group(:state, :result).order(:state)
|
99
|
+
end
|
100
|
+
|
101
|
+
def aggregated_recent_scope
|
102
|
+
aggregated_scope.where("state_updated_at > ?", Time.now.utc - @recent_timeframe)
|
103
|
+
end
|
14
104
|
end
|
15
105
|
end
|