foreman_patch 1.1.1 → 1.1.3
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/Rakefile +0 -6
- data/app/controllers/foreman_patch/api/v2/invocations_controller.rb +23 -1
- data/app/lib/actions/foreman_patch/cycle/initiate.rb +6 -1
- data/app/lib/actions/foreman_patch/invocation/patch.rb +6 -2
- data/app/lib/actions/foreman_patch/invocation/wait_for_host.rb +9 -16
- data/app/lib/actions/foreman_patch/window/patch.rb +4 -4
- data/app/models/foreman_patch/invocation.rb +6 -0
- data/app/models/foreman_patch/plan.rb +1 -1
- data/app/models/foreman_patch/round.rb +9 -26
- data/app/models/foreman_patch/window.rb +1 -1
- data/app/views/foreman_patch/api/v2/rounds/base.json.rabl +1 -1
- data/app/views/foreman_patch/api/v2/rounds/status.json.rabl +2 -8
- data/app/views/templates/ensure_services.erb +7 -4
- data/config/api_routes.rb +7 -1
- data/lib/foreman_patch/version.rb +1 -1
- data/webpack/components/Invocations/Invocations.js +48 -16
- data/webpack/components/Invocations/InvocationsPage.js +24 -1
- data/webpack/components/Invocations/InvocationsSelectors.js +1 -1
- data/webpack/components/Invocations/components/{InvocationItem.js → InvocationActions.js} +4 -16
- data/webpack/components/Invocations/index.js +93 -10
- data/webpack/components/RoundProgress/AggregateStatus.js +6 -5
- data/webpack/components/RoundProgress/RoundProgress.js +7 -6
- data/webpack/components/RoundProgress/RoundProgressSelectors.js +3 -2
- metadata +7 -56
- data/app/lib/actions/foreman_patch/invocation/ensure_services.rb +0 -47
- data/app/lib/actions/foreman_patch/invocation/restart.rb +0 -101
- data/app/lib/actions/foreman_patch/invocation/update_packages.rb +0 -52
- data/app/lib/actions/helpers/failure_notification.rb +0 -20
- data/app/lib/actions/helpers/with_feature_action.rb +0 -102
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css +0 -1
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css.gz +0 -0
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js +0 -6
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.gz +0 -0
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map +0 -1
- data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map.gz +0 -0
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css +0 -1
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css.gz +0 -0
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js +0 -6
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.gz +0 -0
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map +0 -1
- data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map.gz +0 -0
- data/public/webpack/foreman_patch/manifest.json +0 -26
- data/public/webpack/foreman_patch/manifest.json.gz +0 -0
- data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js +0 -2
- data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.gz +0 -0
- data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map +0 -1
- data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map.gz +0 -0
- /data/webpack/components/Invocations/{InvocationsPage.scss → Invocations.scss} +0 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
2
2
|
import { useSelector, useDispatch } from 'react-redux';
|
3
3
|
import PropTypes from 'prop-types';
|
4
|
+
import { Grid } from 'patternfly-react';
|
4
5
|
|
5
6
|
import {
|
6
7
|
withInterval,
|
@@ -8,7 +9,13 @@ import {
|
|
8
9
|
} from 'foremanReact/redux/middlewares/IntervalMiddleware';
|
9
10
|
import { get } from 'foremanReact/redux/API';
|
10
11
|
import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
|
12
|
+
import { getControllerSearchProps } from 'foremanReact/constants';
|
13
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
14
|
+
import SearchBar from 'foremanReact/components/SearchBar';
|
15
|
+
import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
|
16
|
+
import { ActionButtons } from 'foremanReact/components/common/ActionButtons/ActionButtons';
|
11
17
|
|
18
|
+
import Invocations from './Invocations';
|
12
19
|
import {
|
13
20
|
selectItems,
|
14
21
|
selectTotal,
|
@@ -18,7 +25,8 @@ import {
|
|
18
25
|
} from './InvocationsSelectors';
|
19
26
|
import { getUrl } from './InvocationsHelpers';
|
20
27
|
import { INVOCATIONS } from './InvocationsConstants';
|
21
|
-
|
28
|
+
|
29
|
+
import './Invocations.scss';
|
22
30
|
|
23
31
|
const WrappedInvocations = ({ round }) => {
|
24
32
|
const dispatch = useDispatch();
|
@@ -36,6 +44,9 @@ const WrappedInvocations = ({ round }) => {
|
|
36
44
|
});
|
37
45
|
const [url, setUrl] = useState(getUrl(round, searchQuery, pagination));
|
38
46
|
const intervalExists = useSelector(selectIntervalExists);
|
47
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
48
|
+
const [recentSelectedItemIndex, setRecentSelectedRowIndex] = useState(null);
|
49
|
+
const [shifting, setShifting] = useState(false);
|
39
50
|
|
40
51
|
const handleSearch = query => {
|
41
52
|
const defaultPagination = { page: 1, perPage: pagination.perPage };
|
@@ -52,6 +63,32 @@ const WrappedInvocations = ({ round }) => {
|
|
52
63
|
setUrl(getUrl(round, searchQuery, args));
|
53
64
|
};
|
54
65
|
|
66
|
+
const selectAll = (isSelecting) => setSelectedItems(isSelecting ? items.map(item => item.id) : []);
|
67
|
+
|
68
|
+
const areAllSelected = selectedItems.length == items.length;
|
69
|
+
|
70
|
+
const setItemSelected = (item, isSelecting) =>
|
71
|
+
setSelectedItems(prevSelected => {
|
72
|
+
const otherSelectedItems = prevSelected.filter(i => i !== item.id);
|
73
|
+
return isSelecting ? [...otherSelectedItems, item.id] : otherSelectedItems;
|
74
|
+
});
|
75
|
+
|
76
|
+
const onSelect = (item, rowIndex, isSelecting) => {
|
77
|
+
if (shifting && recentSelectedRowIndex !== null) {
|
78
|
+
const numberSelected = rowIndex - recentSelectedRowIndex;
|
79
|
+
const intermediateIndexes =
|
80
|
+
numberSelected > 0
|
81
|
+
? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex)
|
82
|
+
: Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex);
|
83
|
+
intermediateIndexes.forEach(index, setItemSelected(items[index], isSelecting));
|
84
|
+
} else {
|
85
|
+
setItemSelected(item, isSelecting);
|
86
|
+
}
|
87
|
+
setRecentSelectedRowIndex(rowIndex);
|
88
|
+
};
|
89
|
+
|
90
|
+
const isSelected = item => selectedItems.includes(item.id);
|
91
|
+
|
55
92
|
const stopApiInterval = () => {
|
56
93
|
if (intervalExists) {
|
57
94
|
dispatch(stopInterval(INVOCATIONS));
|
@@ -67,27 +104,73 @@ const WrappedInvocations = ({ round }) => {
|
|
67
104
|
}), 5000);
|
68
105
|
|
69
106
|
useEffect(() => {
|
107
|
+
const onKeyDown = (e) => {
|
108
|
+
if (e.key === 'Shift') {
|
109
|
+
setShifting(true);
|
110
|
+
}
|
111
|
+
};
|
112
|
+
const onKeyUp = (e) => {
|
113
|
+
if (e.key === 'Shift') {
|
114
|
+
setShifting(false);
|
115
|
+
}
|
116
|
+
};
|
117
|
+
|
70
118
|
dispatch(getData(url));
|
71
119
|
|
72
120
|
if (!autoRefresh) {
|
73
121
|
dispatch(stopInterval(INVOCATIONS));
|
74
122
|
}
|
75
123
|
|
124
|
+
document.addEventListener('keydown', onKeyDown);
|
125
|
+
document.addEventListener('keyup', onKeyUp);
|
126
|
+
|
76
127
|
return () => {
|
77
128
|
dispatch(stopInterval(INVOCATIONS));
|
129
|
+
document.removeEventListener('keydown', onKeyDown);
|
130
|
+
document.removeEventListener('keyup', onKeyUp);
|
78
131
|
};
|
79
132
|
}, [dispatch, url, autoRefresh]);
|
80
133
|
|
81
134
|
return (
|
82
|
-
<
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
135
|
+
<React.Fragment>
|
136
|
+
<Grid.Row>
|
137
|
+
<Grid.Col md={6} className="title_filter">
|
138
|
+
<SearchBar
|
139
|
+
onSearch={handleSearch}
|
140
|
+
data={{
|
141
|
+
...getControllerSearchProps('foreman_patch/invocations'),
|
142
|
+
autocomplete: {
|
143
|
+
id: 'invocations_search',
|
144
|
+
searchQuery,
|
145
|
+
url: '/foreman_patch/invocations/auto_complete_search',
|
146
|
+
useKeyShortcuts: true,
|
147
|
+
},
|
148
|
+
bookmarks: {},
|
149
|
+
}}
|
150
|
+
/>
|
151
|
+
</Grid.Col>
|
152
|
+
<Grid.Col md={6}>
|
153
|
+
<ActionButtons buttons={actions} />
|
154
|
+
</Grid.Col>
|
155
|
+
</Grid.Row>
|
156
|
+
<br />
|
157
|
+
<Invocations
|
158
|
+
status={status}
|
159
|
+
items={items}
|
160
|
+
selectAll={selectAll}
|
161
|
+
areAllSelected={areAllSelected}
|
162
|
+
isSelected={isSelected}
|
163
|
+
onSelect={onSelect}
|
164
|
+
/>
|
165
|
+
<Pagination
|
166
|
+
viewType="table"
|
167
|
+
itemCount={total}
|
168
|
+
pagination={pagination}
|
169
|
+
onChange={handlePagination}
|
170
|
+
dropdownButtonId="invocations-pagination-dropdown"
|
171
|
+
className="invocations-pagination"
|
172
|
+
/>
|
173
|
+
</React.Fragment>
|
91
174
|
);
|
92
175
|
};
|
93
176
|
|
@@ -19,7 +19,7 @@ const AggregateStatus = ({ progress }) => (
|
|
19
19
|
<span className="card-pf-aggregate-status-notification">
|
20
20
|
<span id="failed_count">
|
21
21
|
<span className="pficon pficon-error-circle-o" />
|
22
|
-
{progress.
|
22
|
+
{progress.error}
|
23
23
|
</span>
|
24
24
|
</span>
|
25
25
|
<span className="card-pf-aggregate-status-notification">
|
@@ -31,7 +31,7 @@ const AggregateStatus = ({ progress }) => (
|
|
31
31
|
<span className="card-pf-aggregate-status-notification">
|
32
32
|
<span id="pending_count">
|
33
33
|
<span className="pficon pficon-pending" />
|
34
|
-
{progress.pending}
|
34
|
+
{progress.pending + progress.planned}
|
35
35
|
</span>
|
36
36
|
</span>
|
37
37
|
<span className="card-pf-aggregate-status-notification">
|
@@ -46,11 +46,12 @@ const AggregateStatus = ({ progress }) => (
|
|
46
46
|
|
47
47
|
AggregateStatus.propTypes = {
|
48
48
|
progress: PropTypes.shape({
|
49
|
+
planned: PropTypes.number,
|
50
|
+
pending: PropTypes.number,
|
51
|
+
running: PropTypes.number,
|
49
52
|
success: PropTypes.number,
|
50
53
|
warning: PropTypes.number,
|
51
|
-
|
52
|
-
running: PropTypes.number,
|
53
|
-
pending: PropTypes.number,
|
54
|
+
error: PropTypes.number,
|
54
55
|
cancelled: PropTypes.number,
|
55
56
|
}).isRequired,
|
56
57
|
};
|
@@ -11,14 +11,14 @@ const RoundProgress = ({ progress }) => {
|
|
11
11
|
const data = [
|
12
12
|
[__('Success'), progress.success, '#5CB85C'],
|
13
13
|
[__('Warning'), progress.warning, '#DB843D'],
|
14
|
-
[__('Failed'), progress.
|
14
|
+
[__('Failed'), progress.error, '#D9534F'],
|
15
15
|
[__('Running'), progress.running, '#3D96AE'],
|
16
|
-
[__('Pending'), progress.pending, '#DEDEDE'],
|
16
|
+
[__('Pending'), progress.pending + progress.planned, '#DEDEDE'],
|
17
17
|
[__('Cancelled'), progress.cancelled, '#B7312D'],
|
18
18
|
];
|
19
19
|
|
20
20
|
const iMax = data.reduce((im, e, i, arr) =>
|
21
|
-
(e[1] > arr[im][
|
21
|
+
(e[1] > arr[im][1] ? i : im), 0);
|
22
22
|
|
23
23
|
return (
|
24
24
|
<div id="round_progress">
|
@@ -36,11 +36,12 @@ const RoundProgress = ({ progress }) => {
|
|
36
36
|
|
37
37
|
RoundProgress.propTypes = {
|
38
38
|
progress: PropTypes.shape({
|
39
|
+
pending: PropTypes.number,
|
40
|
+
planned: PropTypes.number,
|
41
|
+
running: PropTypes.number,
|
39
42
|
success: PropTypes.number,
|
40
43
|
warning: PropTypes.number,
|
41
|
-
|
42
|
-
running: PropTypes.number,
|
43
|
-
pending: PropTypes.number,
|
44
|
+
error: PropTypes.number,
|
44
45
|
cancelled: PropTypes.number,
|
45
46
|
}).isRequired,
|
46
47
|
};
|
@@ -8,9 +8,10 @@ import { ROUND_PROGRESS } from './RoundProgressConstants';
|
|
8
8
|
const defaultProgress = {
|
9
9
|
success: 0,
|
10
10
|
warning: 0,
|
11
|
-
|
11
|
+
error: 0,
|
12
12
|
running: 0,
|
13
13
|
pending: 0,
|
14
|
+
planned: 0,
|
14
15
|
cancelled: 0,
|
15
16
|
};
|
16
17
|
|
@@ -18,7 +19,7 @@ export const selectProgress = state =>
|
|
18
19
|
selectAPIResponse(state, ROUND_PROGRESS).progress || defaultProgress;
|
19
20
|
|
20
21
|
export const selectAutoRefresh = state =>
|
21
|
-
|
22
|
+
selectAPIResponse(state, ROUND_PROGRESS).status != 'complete';
|
22
23
|
|
23
24
|
export const selectStatus = state =>
|
24
25
|
selectAPIStatus(state, ROUND_PROGRESS);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_patch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Galens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: katello
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '4'
|
19
|
+
version: '4.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '4'
|
26
|
+
version: '4.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: foreman-tasks
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,9 +31,6 @@ dependencies:
|
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.0'
|
34
|
-
- - "<"
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: '6.0'
|
37
34
|
type: :runtime
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -41,9 +38,6 @@ dependencies:
|
|
41
38
|
- - ">="
|
42
39
|
- !ruby/object:Gem::Version
|
43
40
|
version: '4.0'
|
44
|
-
- - "<"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '6.0'
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: foreman_remote_execution
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,9 +45,6 @@ dependencies:
|
|
51
45
|
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '4.0'
|
54
|
-
- - "<"
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '6.0'
|
57
48
|
type: :runtime
|
58
49
|
prerelease: false
|
59
50
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -61,23 +52,6 @@ dependencies:
|
|
61
52
|
- - ">="
|
62
53
|
- !ruby/object:Gem::Version
|
63
54
|
version: '4.0'
|
64
|
-
- - "<"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '6.0'
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
name: rake-version
|
69
|
-
requirement: !ruby/object:Gem::Requirement
|
70
|
-
requirements:
|
71
|
-
- - "~>"
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: 1.0.1
|
74
|
-
type: :development
|
75
|
-
prerelease: false
|
76
|
-
version_requirements: !ruby/object:Gem::Requirement
|
77
|
-
requirements:
|
78
|
-
- - "~>"
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: 1.0.1
|
81
55
|
- !ruby/object:Gem::Dependency
|
82
56
|
name: rubocop
|
83
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,11 +115,8 @@ files:
|
|
141
115
|
- app/lib/actions/foreman_patch/cycle/prepare_content.rb
|
142
116
|
- app/lib/actions/foreman_patch/host/reschedule.rb
|
143
117
|
- app/lib/actions/foreman_patch/invocation/action.rb
|
144
|
-
- app/lib/actions/foreman_patch/invocation/ensure_services.rb
|
145
118
|
- app/lib/actions/foreman_patch/invocation/patch.rb
|
146
119
|
- app/lib/actions/foreman_patch/invocation/reschedule.rb
|
147
|
-
- app/lib/actions/foreman_patch/invocation/restart.rb
|
148
|
-
- app/lib/actions/foreman_patch/invocation/update_packages.rb
|
149
120
|
- app/lib/actions/foreman_patch/invocation/wait_for_host.rb
|
150
121
|
- app/lib/actions/foreman_patch/round/add_missing_hosts.rb
|
151
122
|
- app/lib/actions/foreman_patch/round/create.rb
|
@@ -157,8 +128,6 @@ files:
|
|
157
128
|
- app/lib/actions/foreman_patch/window/plan.rb
|
158
129
|
- app/lib/actions/foreman_patch/window/publish.rb
|
159
130
|
- app/lib/actions/foreman_patch/window/resolve_hosts.rb
|
160
|
-
- app/lib/actions/helpers/failure_notification.rb
|
161
|
-
- app/lib/actions/helpers/with_feature_action.rb
|
162
131
|
- app/lib/actions/middleware/check_exit_status.rb
|
163
132
|
- app/mailers/foreman_patch/cycle_mailer.rb
|
164
133
|
- app/mailers/foreman_patch/group_mailer.rb
|
@@ -325,24 +294,6 @@ files:
|
|
325
294
|
- public/assets/foreman_patch/foreman_patch.json
|
326
295
|
- public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js
|
327
296
|
- public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js.gz
|
328
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css
|
329
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css.gz
|
330
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js
|
331
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.gz
|
332
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map
|
333
|
-
- public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map.gz
|
334
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css
|
335
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css.gz
|
336
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js
|
337
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.gz
|
338
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map
|
339
|
-
- public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map.gz
|
340
|
-
- public/webpack/foreman_patch/manifest.json
|
341
|
-
- public/webpack/foreman_patch/manifest.json.gz
|
342
|
-
- public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js
|
343
|
-
- public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.gz
|
344
|
-
- public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map
|
345
|
-
- public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map.gz
|
346
297
|
- test/factories/foreman_patch_factories.rb
|
347
298
|
- test/test_plugin_helper.rb
|
348
299
|
- test/unit/foreman_patch_test.rb
|
@@ -363,12 +314,12 @@ files:
|
|
363
314
|
- webpack/components/Invocation/InvocationSelectors.js
|
364
315
|
- webpack/components/Invocation/index.js
|
365
316
|
- webpack/components/Invocations/Invocations.js
|
317
|
+
- webpack/components/Invocations/Invocations.scss
|
366
318
|
- webpack/components/Invocations/InvocationsConstants.js
|
367
319
|
- webpack/components/Invocations/InvocationsHelpers.js
|
368
320
|
- webpack/components/Invocations/InvocationsPage.js
|
369
|
-
- webpack/components/Invocations/InvocationsPage.scss
|
370
321
|
- webpack/components/Invocations/InvocationsSelectors.js
|
371
|
-
- webpack/components/Invocations/components/
|
322
|
+
- webpack/components/Invocations/components/InvocationActions.js
|
372
323
|
- webpack/components/Invocations/components/InvocationStatus.js
|
373
324
|
- webpack/components/Invocations/index.js
|
374
325
|
- webpack/components/Plan/Plan.js
|
@@ -428,7 +379,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
428
379
|
- !ruby/object:Gem::Version
|
429
380
|
version: '0'
|
430
381
|
requirements: []
|
431
|
-
rubygems_version: 3.
|
382
|
+
rubygems_version: 3.3.25
|
432
383
|
signing_key:
|
433
384
|
specification_version: 4
|
434
385
|
summary: Foreman Plugin for Managing Patching
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Actions
|
2
|
-
module ForemanPatch
|
3
|
-
module Invocation
|
4
|
-
class EnsureServices < Actions::EntryAction
|
5
|
-
include Actions::Helpers::WithFeatureAction
|
6
|
-
|
7
|
-
def resource_locks
|
8
|
-
:link
|
9
|
-
end
|
10
|
-
|
11
|
-
def plan(host)
|
12
|
-
action_subject(host)
|
13
|
-
|
14
|
-
sequence do
|
15
|
-
plan_feature_action('ensure_services', host)
|
16
|
-
plan_self
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def run
|
21
|
-
if exit_status != 0
|
22
|
-
users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
|
23
|
-
|
24
|
-
begin
|
25
|
-
MailNotification[:patch_invocation_failure].deliver(users: users, host: host, output: live_output) unless users.blank?
|
26
|
-
rescue => error
|
27
|
-
message = _('Unable to send patch invocation failure: %{error}') % {error: error}
|
28
|
-
Rails.logger.error(message)
|
29
|
-
end
|
30
|
-
|
31
|
-
fail _('Ensure services failed')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def rescue_strategy
|
36
|
-
::Dynflow::Action::Rescue::Skip
|
37
|
-
end
|
38
|
-
|
39
|
-
def host
|
40
|
-
@host ||= ::Host.find(input[:host][:id])
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
@@ -1,101 +0,0 @@
|
|
1
|
-
module Actions
|
2
|
-
module ForemanPatch
|
3
|
-
module Invocation
|
4
|
-
class Restart < Actions::EntryAction
|
5
|
-
include Actions::Helpers::WithFeatureAction
|
6
|
-
include Dynflow::Action::Polling
|
7
|
-
|
8
|
-
def plan(host)
|
9
|
-
action_subject(host)
|
10
|
-
|
11
|
-
sequence do
|
12
|
-
plan_feature_action('power_action', host, action: 'restart')
|
13
|
-
plan_self
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def done?
|
18
|
-
external_task[:status] == :running
|
19
|
-
end
|
20
|
-
|
21
|
-
def invoke_external_task
|
22
|
-
if exit_status != 0
|
23
|
-
send_failure_notification
|
24
|
-
fail(_('Restart command failed to execute'))
|
25
|
-
end
|
26
|
-
|
27
|
-
schedule_timeout(Setting[:host_max_wait_for_up]) if Setting[:host_max_wait_for_up]
|
28
|
-
|
29
|
-
{ status: :stopping }
|
30
|
-
end
|
31
|
-
|
32
|
-
def poll_external_task
|
33
|
-
socket = TCPSocket.new(host.ip, Setting[:remote_execution_ssh_port])
|
34
|
-
socket.close
|
35
|
-
|
36
|
-
if external_task[:status] == :stopping
|
37
|
-
log_poll_result(_('Server status: stopping'))
|
38
|
-
{ status: :stopping }
|
39
|
-
else
|
40
|
-
log_poll_result(_('Server status: running'))
|
41
|
-
{ status: :running }
|
42
|
-
end
|
43
|
-
rescue
|
44
|
-
log_poll_result(_('Server status: starting'))
|
45
|
-
|
46
|
-
{ status: :starting }
|
47
|
-
end
|
48
|
-
|
49
|
-
def poll_intervals
|
50
|
-
case external_task[:status]
|
51
|
-
when :stopping
|
52
|
-
[1]
|
53
|
-
when :starting
|
54
|
-
[10]
|
55
|
-
else
|
56
|
-
super
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def process_timeout
|
61
|
-
continuous_output.add_output(_('Server did not respond within alloted time after restart.'))
|
62
|
-
|
63
|
-
send_failure_notification
|
64
|
-
|
65
|
-
fail("Timeout exceeded.")
|
66
|
-
end
|
67
|
-
|
68
|
-
def log_poll_result(status)
|
69
|
-
results = delegated_output.fetch('result', [])
|
70
|
-
|
71
|
-
results << {
|
72
|
-
'output_type' => 'debug',
|
73
|
-
'output' => status,
|
74
|
-
'timestamp' => Time.now.getlocal
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
|
-
def send_failure_notification
|
79
|
-
users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
|
80
|
-
|
81
|
-
begin
|
82
|
-
MailNotification[:patch_invocation_failure].deliver(user: users, host: host, output: live_output) unless users.blank?
|
83
|
-
rescue => error
|
84
|
-
message = _('Unable to send patch invocation failure: %{error}') % {error: error}
|
85
|
-
Rails.logger.error(message)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def rescue_strategy
|
90
|
-
::Dynflow::Action::Rescue::Fail
|
91
|
-
end
|
92
|
-
|
93
|
-
def host
|
94
|
-
@host ||= ::Host.find(input[:host][:id])
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Actions
|
2
|
-
module ForemanPatch
|
3
|
-
module Invocation
|
4
|
-
class UpdatePackages < Actions::EntryAction
|
5
|
-
include Actions::Helpers::WithFeatureAction
|
6
|
-
|
7
|
-
def resource_locks
|
8
|
-
:link
|
9
|
-
end
|
10
|
-
|
11
|
-
def plan(host)
|
12
|
-
action_subject(host)
|
13
|
-
|
14
|
-
sequence do
|
15
|
-
plan_feature_action('katello_package_update', host,
|
16
|
-
pre_script: 'yum clean all; subscription-manager refresh',
|
17
|
-
package: Setting[:skip_broken_patches] ? '--skip-broken' : nil)
|
18
|
-
plan_self
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def run
|
23
|
-
if exit_status != 0
|
24
|
-
users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
|
25
|
-
|
26
|
-
begin
|
27
|
-
MailNotification[:patch_invocation_failure].deliver(users: users, host: host, output: live_output) unless users.blank?
|
28
|
-
rescue => error
|
29
|
-
message = _('Unable to send patch invocation failure: %{error}') % {error: error}
|
30
|
-
Rails.logger.error(message)
|
31
|
-
end
|
32
|
-
|
33
|
-
fail _('Package update failed')
|
34
|
-
else
|
35
|
-
host.group_facet.last_patched_at = Time.current
|
36
|
-
host.group_facet.save!
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def rescue_strategy
|
41
|
-
::Dynflow::Action::Rescue::Fail
|
42
|
-
end
|
43
|
-
|
44
|
-
def host
|
45
|
-
@host ||= ::Host.find(input[:host][:id])
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Actions
|
2
|
-
module Helpers
|
3
|
-
module FailureNotification
|
4
|
-
|
5
|
-
def send_failure_notification
|
6
|
-
users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
|
7
|
-
|
8
|
-
MailNotification[:patch_invocation_failure].deliver(
|
9
|
-
users: users,
|
10
|
-
host: host,
|
11
|
-
output: live_output
|
12
|
-
) unless users.blank?
|
13
|
-
rescue => error
|
14
|
-
message = _('Unable to send patch invocation failure: %{error}') % {error: error}
|
15
|
-
Rails.logger.error(message)
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|