foreman_remote_execution 16.6.6 → 16.7.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 +4 -4
- data/app/controllers/api/v2/job_invocations_controller.rb +22 -13
- data/app/models/remote_execution_provider.rb +1 -1
- data/app/views/api/v2/job_invocations/main.json.rabl +15 -11
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/package.json +3 -3
- data/test/functional/api/v2/job_invocations_controller_test.rb +68 -3
- data/test/unit/remote_execution_provider_test.rb +1 -1
- data/webpack/JobInvocationDetail/CheckboxesActions.js +4 -10
- data/webpack/JobInvocationDetail/JobInvocationActions.js +2 -1
- data/webpack/JobInvocationDetail/JobInvocationConstants.js +4 -4
- data/webpack/JobInvocationDetail/JobInvocationEmptyState.js +52 -0
- data/webpack/JobInvocationDetail/JobInvocationSelectors.js +0 -15
- data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +201 -150
- data/webpack/JobInvocationDetail/__tests__/JobInvocationDetailEmptyState.test.js +53 -0
- data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +109 -11
- data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +3 -1
- data/webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js +30 -0
- data/webpack/JobInvocationDetail/index.js +42 -9
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js +15 -0
- data/webpack/__mocks__/foremanReact/common/hooks/Permissions/permissionHooks.js +1 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +5 -0
- metadata +7 -9
|
@@ -2,6 +2,7 @@ import '@testing-library/jest-dom/extend-expect';
|
|
|
2
2
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
5
|
+
import { usePermissions } from 'foremanReact/common/hooks/Permissions/permissionHooks';
|
|
5
6
|
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
|
|
6
7
|
import React from 'react';
|
|
7
8
|
import { Provider } from 'react-redux';
|
|
@@ -13,6 +14,7 @@ import { PopupAlert } from '../OpenAllInvocationsModal';
|
|
|
13
14
|
|
|
14
15
|
jest.mock('axios');
|
|
15
16
|
jest.mock('foremanReact/common/hooks/API/APIHooks');
|
|
17
|
+
jest.mock('foremanReact/common/hooks/Permissions/permissionHooks');
|
|
16
18
|
jest.mock('../JobInvocationSelectors');
|
|
17
19
|
|
|
18
20
|
jest.mock('../JobInvocationConstants', () => ({
|
|
@@ -26,8 +28,8 @@ jest.mock('../JobInvocationConstants', () => ({
|
|
|
26
28
|
selectors.selectItems.mockImplementation(() => ({
|
|
27
29
|
targeting: { search_query: 'name~*' },
|
|
28
30
|
}));
|
|
29
|
-
selectors.selectHasPermission.mockImplementation(() => () => true);
|
|
30
31
|
selectors.selectTaskCancelable.mockImplementation(() => true);
|
|
32
|
+
usePermissions.mockReturnValue(true);
|
|
31
33
|
|
|
32
34
|
const mockStore = configureStore([]);
|
|
33
35
|
const store = mockStore({});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
|
|
4
|
+
|
|
5
|
+
export const createForemanContextWrapper = (
|
|
6
|
+
permissions = ['view_job_invocations', 'create_job_invocations']
|
|
7
|
+
) => {
|
|
8
|
+
const foremanContextValue = {
|
|
9
|
+
context: {
|
|
10
|
+
metadata: {
|
|
11
|
+
permissions: new Set(permissions),
|
|
12
|
+
UISettings: { perPage: 20 },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
setContext: jest.fn(),
|
|
16
|
+
};
|
|
17
|
+
const ForemanContext = getForemanContext(foremanContextValue);
|
|
18
|
+
|
|
19
|
+
const ForemanContextWrapper = ({ children }) => (
|
|
20
|
+
<ForemanContext.Provider value={foremanContextValue}>
|
|
21
|
+
{children}
|
|
22
|
+
</ForemanContext.Provider>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
ForemanContextWrapper.propTypes = {
|
|
26
|
+
children: PropTypes.node.isRequired,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return ForemanContextWrapper;
|
|
30
|
+
};
|
|
@@ -5,29 +5,33 @@ import {
|
|
|
5
5
|
PageSectionVariants,
|
|
6
6
|
Skeleton,
|
|
7
7
|
} from '@patternfly/react-core';
|
|
8
|
-
import React, { useEffect, useState } from 'react';
|
|
8
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
9
9
|
import { translate as __, documentLocale } from 'foremanReact/common/I18n';
|
|
10
10
|
import { useDispatch, useSelector } from 'react-redux';
|
|
11
11
|
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
|
12
12
|
import PropTypes from 'prop-types';
|
|
13
13
|
import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
|
|
14
14
|
import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
|
|
15
|
-
import {
|
|
15
|
+
import { STATUS as API_STATUS } from 'foremanReact/constants';
|
|
16
|
+
import {
|
|
17
|
+
selectAPIErrorMessage,
|
|
18
|
+
selectAPIHttpStatus,
|
|
19
|
+
selectAPIStatus,
|
|
20
|
+
} from 'foremanReact/redux/API/APISelectors';
|
|
16
21
|
|
|
17
22
|
import { JobAdditionInfo } from './JobAdditionInfo';
|
|
18
23
|
import JobInvocationHostTable from './JobInvocationHostTable';
|
|
19
24
|
import JobInvocationOverview from './JobInvocationOverview';
|
|
20
25
|
import JobInvocationSystemStatusChart from './JobInvocationSystemStatusChart';
|
|
26
|
+
import JobInvocationEmptyState from './JobInvocationEmptyState';
|
|
21
27
|
import JobInvocationToolbarButtons from './JobInvocationToolbarButtons';
|
|
22
28
|
import { getJobInvocation, getTask } from './JobInvocationActions';
|
|
23
29
|
import './JobInvocationDetail.scss';
|
|
24
30
|
import {
|
|
25
|
-
CURRENT_PERMISSIONS,
|
|
26
31
|
DATE_OPTIONS,
|
|
27
32
|
JOB_INVOCATION_KEY,
|
|
28
33
|
STATUS,
|
|
29
34
|
STATUS_UPPERCASE,
|
|
30
|
-
currentPermissionsUrl,
|
|
31
35
|
} from './JobInvocationConstants';
|
|
32
36
|
import { selectItems } from './JobInvocationSelectors';
|
|
33
37
|
|
|
@@ -51,9 +55,15 @@ const JobInvocationDetailPage = ({
|
|
|
51
55
|
statusLabel === STATUS.SUCCEEDED ||
|
|
52
56
|
statusLabel === STATUS.CANCELLED;
|
|
53
57
|
const autoRefresh = task?.state === STATUS.PENDING || false;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const jobInvocationApiStatus = useSelector(state =>
|
|
59
|
+
selectAPIStatus(state, JOB_INVOCATION_KEY)
|
|
60
|
+
);
|
|
61
|
+
const jobInvocationErrorMessage = useSelector(state =>
|
|
62
|
+
selectAPIErrorMessage(state, JOB_INVOCATION_KEY)
|
|
63
|
+
);
|
|
64
|
+
const jobInvocationHttpStatus = useSelector(state =>
|
|
65
|
+
selectAPIHttpStatus(state, JOB_INVOCATION_KEY)
|
|
66
|
+
);
|
|
57
67
|
const [selectedFilter, setSelectedFilter] = useState('');
|
|
58
68
|
|
|
59
69
|
const handleFilterChange = newFilter => {
|
|
@@ -72,7 +82,7 @@ const JobInvocationDetailPage = ({
|
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
useEffect(() => {
|
|
75
|
-
dispatch(getJobInvocation(`/api/job_invocations/${id}
|
|
85
|
+
dispatch(getJobInvocation(`/api/job_invocations/${id}`));
|
|
76
86
|
if (finished && !autoRefresh) {
|
|
77
87
|
dispatch(stopInterval(JOB_INVOCATION_KEY));
|
|
78
88
|
}
|
|
@@ -88,6 +98,25 @@ const JobInvocationDetailPage = ({
|
|
|
88
98
|
}
|
|
89
99
|
}, [dispatch, taskId]);
|
|
90
100
|
|
|
101
|
+
const apiFailed = jobInvocationApiStatus === API_STATUS.ERROR;
|
|
102
|
+
|
|
103
|
+
const backendErrorMessage = useMemo(() => {
|
|
104
|
+
if (jobInvocationApiStatus === API_STATUS.ERROR) {
|
|
105
|
+
return jobInvocationErrorMessage || null;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}, [jobInvocationApiStatus, jobInvocationErrorMessage]);
|
|
109
|
+
|
|
110
|
+
if (apiFailed) {
|
|
111
|
+
return (
|
|
112
|
+
<JobInvocationEmptyState
|
|
113
|
+
jobInvocationId={id}
|
|
114
|
+
httpStatus={jobInvocationHttpStatus}
|
|
115
|
+
errorMessage={backendErrorMessage}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
91
120
|
const pageStatus =
|
|
92
121
|
items.id === undefined
|
|
93
122
|
? STATUS_UPPERCASE.PENDING
|
|
@@ -123,7 +152,11 @@ const JobInvocationDetailPage = ({
|
|
|
123
152
|
<PageLayout
|
|
124
153
|
header={description}
|
|
125
154
|
breadcrumbOptions={breadcrumbOptions}
|
|
126
|
-
toolbarButtons={
|
|
155
|
+
toolbarButtons={
|
|
156
|
+
items.id !== undefined && (
|
|
157
|
+
<JobInvocationToolbarButtons jobId={id} data={items} />
|
|
158
|
+
)
|
|
159
|
+
}
|
|
127
160
|
searchable={false}
|
|
128
161
|
>
|
|
129
162
|
<Flex className="job-invocation-detail-flex">
|
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const getForemanContext = contextData => {
|
|
4
|
+
window.tfm_forced_singletons = window.tfm_forced_singletons || {};
|
|
5
|
+
|
|
6
|
+
if (!window.tfm_forced_singletons.Context) {
|
|
7
|
+
window.tfm_forced_singletons.Context = React.createContext(contextData);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return window.tfm_forced_singletons.Context;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { getForemanContext };
|
|
1
14
|
export const useForemanOrganization = () => ({ id: 1 });
|
|
2
15
|
export const useForemanLocation = () => ({ id: 2 });
|
|
3
16
|
export const useForemanVersion = () => '3.7';
|
|
4
17
|
export const useForemanHostsPageUrl = () => '/hosts';
|
|
5
18
|
export const useForemanHostDetailsPageUrl = () => '/hosts/';
|
|
6
19
|
export const useForemanSettings = () => ({ perPage: 20 });
|
|
20
|
+
export const useForemanPermissions = () =>
|
|
21
|
+
new Set(['view_job_invocations', 'create_job_invocations']);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const usePermissions = jest.fn(() => true);
|
|
@@ -19,3 +19,8 @@ export const selectAPIErrorMessage = (state, key) => {
|
|
|
19
19
|
const error = selectAPIError(state, key);
|
|
20
20
|
return error && error.message;
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
export const selectAPIHttpStatus = (state, key) => {
|
|
24
|
+
const error = selectAPIError(state, key);
|
|
25
|
+
return error?.response?.status;
|
|
26
|
+
};
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_remote_execution
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 16.
|
|
4
|
+
version: 16.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Foreman Remote Execution team
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-07-13 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: deface
|
|
@@ -30,9 +30,6 @@ dependencies:
|
|
|
30
30
|
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: 8.3.0
|
|
33
|
-
- - "<"
|
|
34
|
-
- !ruby/object:Gem::Version
|
|
35
|
-
version: '13'
|
|
36
33
|
type: :runtime
|
|
37
34
|
prerelease: false
|
|
38
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -40,9 +37,6 @@ dependencies:
|
|
|
40
37
|
- - ">="
|
|
41
38
|
- !ruby/object:Gem::Version
|
|
42
39
|
version: 8.3.0
|
|
43
|
-
- - "<"
|
|
44
|
-
- !ruby/object:Gem::Version
|
|
45
|
-
version: '13'
|
|
46
40
|
description: A plugin bringing remote execution to the Foreman, completing the config
|
|
47
41
|
management functionality with remote management functionality.
|
|
48
42
|
email:
|
|
@@ -388,6 +382,7 @@ files:
|
|
|
388
382
|
- webpack/JobInvocationDetail/JobInvocationActions.js
|
|
389
383
|
- webpack/JobInvocationDetail/JobInvocationConstants.js
|
|
390
384
|
- webpack/JobInvocationDetail/JobInvocationDetail.scss
|
|
385
|
+
- webpack/JobInvocationDetail/JobInvocationEmptyState.js
|
|
391
386
|
- webpack/JobInvocationDetail/JobInvocationHostTable.js
|
|
392
387
|
- webpack/JobInvocationDetail/JobInvocationOverview.js
|
|
393
388
|
- webpack/JobInvocationDetail/JobInvocationSelectors.js
|
|
@@ -401,11 +396,13 @@ files:
|
|
|
401
396
|
- webpack/JobInvocationDetail/TemplateInvocationComponents/TemplateActionButtons.js
|
|
402
397
|
- webpack/JobInvocationDetail/TemplateInvocationComponents/index.scss
|
|
403
398
|
- webpack/JobInvocationDetail/TemplateInvocationPage.js
|
|
399
|
+
- webpack/JobInvocationDetail/__tests__/JobInvocationDetailEmptyState.test.js
|
|
404
400
|
- webpack/JobInvocationDetail/__tests__/MainInformation.test.js
|
|
405
401
|
- webpack/JobInvocationDetail/__tests__/OutputCodeBlock.test.js
|
|
406
402
|
- webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js
|
|
407
403
|
- webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js
|
|
408
404
|
- webpack/JobInvocationDetail/__tests__/fixtures.js
|
|
405
|
+
- webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js
|
|
409
406
|
- webpack/JobInvocationDetail/index.js
|
|
410
407
|
- webpack/JobWizard/Footer.js
|
|
411
408
|
- webpack/JobWizard/JobWizard.js
|
|
@@ -475,6 +472,7 @@ files:
|
|
|
475
472
|
- webpack/__mocks__/foremanReact/common/globalIdHelpers.js
|
|
476
473
|
- webpack/__mocks__/foremanReact/common/helpers.js
|
|
477
474
|
- webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js
|
|
475
|
+
- webpack/__mocks__/foremanReact/common/hooks/Permissions/permissionHooks.js
|
|
478
476
|
- webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js
|
|
479
477
|
- webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js
|
|
480
478
|
- webpack/__mocks__/foremanReact/components/BreadcrumbBar/index.js
|
|
@@ -566,7 +564,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
566
564
|
- !ruby/object:Gem::Version
|
|
567
565
|
version: '0'
|
|
568
566
|
requirements: []
|
|
569
|
-
rubygems_version: 4.0.
|
|
567
|
+
rubygems_version: 4.0.10
|
|
570
568
|
specification_version: 4
|
|
571
569
|
summary: A plugin bringing remote execution to the Foreman, completing the config
|
|
572
570
|
management functionality with remote management functionality.
|