foreman_rh_cloud 12.1.4 → 12.2.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/insights_cloud/api/machine_telemetries_controller.rb +1 -2
- data/app/controllers/insights_cloud/ui_requests_controller.rb +99 -0
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +7 -13
- data/app/services/foreman_rh_cloud/gateway_request.rb +26 -0
- data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +116 -0
- data/app/services/foreman_rh_cloud/tags_auth.rb +55 -0
- data/config/routes.rb +7 -0
- data/lib/foreman_rh_cloud/engine.rb +7 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud.rb +8 -0
- data/package.json +5 -1
- data/test/controllers/insights_cloud/ui_requests_controller_test.rb +169 -0
- data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +3 -3
- data/test/unit/services/foreman_rh_cloud/insights_api_forwarder_test.rb +176 -0
- data/test/unit/services/foreman_rh_cloud/tags_auth_test.rb +29 -0
- data/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js +30 -10
- data/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js +18 -11
- data/webpack/CVEsHostDetailsTab/index.js +2 -2
- data/webpack/CveDetailsPage/CveDetailsPage.js +20 -0
- data/webpack/CveDetailsPage/CveDetailsPage.test.js +31 -0
- data/webpack/CveDetailsPage/index.js +1 -0
- data/webpack/ForemanColumnExtensions/index.js +49 -14
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilter.test.js.snap +1 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/MinimalInventoryDropdown.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +8 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +4 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +3 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +3 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +10 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +6 -6
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/SettingsWarning.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/__snapshots__/SettingsWarning.test.js.snap +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +1 -0
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +3 -0
- data/webpack/ForemanRhCloudFills.js +6 -3
- data/webpack/ForemanRhCloudPages.js +21 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +2 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +1 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +3 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +12 -2
- data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +1 -0
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +6 -1
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +39 -1
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +6 -50
- data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +51 -1
- data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js +21 -0
- data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js +20 -0
- data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +45 -0
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +28 -0
- data/webpack/IopRecommendationDetails/IopRecommendationDetails.js +44 -0
- data/webpack/common/DropdownToggle.js +1 -0
- data/webpack/common/ScalprumModule/ScalprumContext.js +73 -0
- data/webpack/common/Switcher/SwitcherPF4.js +1 -0
- data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -0
- data/webpack/common/Switcher/index.js +1 -0
- metadata +21 -4
- data/webpack/InsightsVulnerability/InsightsVulnerability.js +0 -13
- data/webpack/InsightsVulnerability/InsightsVulnerability.test.js +0 -18
@@ -13,18 +13,18 @@ export const PageDescription = () => {
|
|
13
13
|
|
14
14
|
return (
|
15
15
|
<div id="inventory_page_description">
|
16
|
-
<Text>
|
16
|
+
<Text ouiaId="text-cloud-console">
|
17
17
|
{__(
|
18
18
|
'The Red Hat Hybrid Cloud Console provides a set of cloud services, including Red Hat Insights and Subscriptions, that provide predictive analysis, remediation of issues, and unified subscription reporting for this Foreman instance.'
|
19
19
|
)}
|
20
20
|
</Text>
|
21
|
-
<Text>
|
21
|
+
<Text ouiaId="text-inventory-upload">
|
22
22
|
{__(
|
23
23
|
'The Foreman inventory upload plugin automatically uploads Foreman host inventory data to the Inventory service of Insights, where it can also be used by the Subscriptions service for subscription reporting. If you use the Subscriptions service, enabling inventory uploads is required.'
|
24
24
|
)}
|
25
25
|
</Text>
|
26
26
|
{subscriptionConnectionEnabled && (
|
27
|
-
<Text>
|
27
|
+
<Text ouiaId="text-enable-report">
|
28
28
|
<FormattedMessage
|
29
29
|
id="enable-upload-hint"
|
30
30
|
defaultMessage={__(
|
@@ -39,7 +39,7 @@ export const PageDescription = () => {
|
|
39
39
|
</Text>
|
40
40
|
)}
|
41
41
|
{subscriptionConnectionEnabled && (
|
42
|
-
<Text>
|
42
|
+
<Text ouiaId="text-restart-button">
|
43
43
|
<FormattedMessage
|
44
44
|
id="restart-button-hint"
|
45
45
|
defaultMessage={__(
|
@@ -53,7 +53,7 @@ export const PageDescription = () => {
|
|
53
53
|
/>
|
54
54
|
</Text>
|
55
55
|
)}
|
56
|
-
<Text>
|
56
|
+
<Text ouiaId="text-more-info-subscription">
|
57
57
|
{__('For more information about the Subscriptions service, see:')}
|
58
58
|
|
59
59
|
<a
|
@@ -64,7 +64,7 @@ export const PageDescription = () => {
|
|
64
64
|
{__('About subscription watch')}
|
65
65
|
</a>
|
66
66
|
</Text>
|
67
|
-
<Text>
|
67
|
+
<Text ouiaId="text-more-info-insights">
|
68
68
|
{__('For more information about Insights and Cloud Connector, see:')}
|
69
69
|
|
70
70
|
<a
|
@@ -22,6 +22,7 @@ export const SettingsWarning = ({
|
|
22
22
|
alerts.push(
|
23
23
|
<Alert
|
24
24
|
key="auto-upload"
|
25
|
+
ouiaId="auto-upload"
|
25
26
|
variant="warning"
|
26
27
|
title={__(
|
27
28
|
"Cloud Connector has been configured however the inventory auto-upload is disabled, it's recommended to enable it"
|
@@ -36,6 +37,7 @@ export const SettingsWarning = ({
|
|
36
37
|
alerts.push(
|
37
38
|
<Alert
|
38
39
|
key="obfuscating-host"
|
40
|
+
ouiaId="obfuscating-host"
|
39
41
|
variant="warning"
|
40
42
|
title={__(
|
41
43
|
"Cloud Connector has been configured however obfuscating host names setting is enabled, it's recommended to disable it"
|
@@ -11,6 +11,7 @@ exports[`SettingsWarning with 2 alerts 1`] = `
|
|
11
11
|
/>
|
12
12
|
}
|
13
13
|
key="auto-upload"
|
14
|
+
ouiaId="auto-upload"
|
14
15
|
title="Cloud Connector has been configured however the inventory auto-upload is disabled, it's recommended to enable it"
|
15
16
|
variant="warning"
|
16
17
|
/>
|
@@ -21,6 +22,7 @@ exports[`SettingsWarning with 2 alerts 1`] = `
|
|
21
22
|
/>
|
22
23
|
}
|
23
24
|
key="obfuscating-host"
|
25
|
+
ouiaId="obfuscating-host"
|
24
26
|
title="Cloud Connector has been configured however obfuscating host names setting is enabled, it's recommended to disable it"
|
25
27
|
variant="warning"
|
26
28
|
/>
|
@@ -48,6 +48,7 @@ const InventoryAutoUploadSwitcher = ({
|
|
48
48
|
position="right"
|
49
49
|
>
|
50
50
|
<Button
|
51
|
+
ouiaId="button-advanced-settings"
|
51
52
|
variant="secondary"
|
52
53
|
style={{ fontSize: 'small', marginTop: '-4px' }}
|
53
54
|
>
|
@@ -59,9 +60,10 @@ const InventoryAutoUploadSwitcher = ({
|
|
59
60
|
<br />
|
60
61
|
<Grid.Row>
|
61
62
|
<Grid.Col sm={12}>
|
62
|
-
<Text component={TextVariants.p}>
|
63
|
+
<Text component={TextVariants.p} ouiaId="text-more-details">
|
63
64
|
<InfoAltIcon /> {__('More details can be found in')}{' '}
|
64
65
|
<Text
|
66
|
+
ouiaId="text-details-link"
|
65
67
|
component={TextVariants.a}
|
66
68
|
href={foremanUrl('/foreman_rh_cloud/inventory_upload')}
|
67
69
|
target="_blank"
|
@@ -41,6 +41,7 @@ exports[`InventoryAutoUpload rendering render with props 1`] = `
|
|
41
41
|
position="right"
|
42
42
|
>
|
43
43
|
<Button
|
44
|
+
ouiaId="button-advanced-settings"
|
44
45
|
style={
|
45
46
|
Object {
|
46
47
|
"fontSize": "small",
|
@@ -68,6 +69,7 @@ exports[`InventoryAutoUpload rendering render with props 1`] = `
|
|
68
69
|
>
|
69
70
|
<Text
|
70
71
|
component="p"
|
72
|
+
ouiaId="text-more-details"
|
71
73
|
>
|
72
74
|
<InfoAltIcon />
|
73
75
|
|
@@ -76,6 +78,7 @@ exports[`InventoryAutoUpload rendering render with props 1`] = `
|
|
76
78
|
<Text
|
77
79
|
component="a"
|
78
80
|
href="/foreman_rh_cloud/inventory_upload"
|
81
|
+
ouiaId="text-details-link"
|
79
82
|
rel="noopener noreferrer"
|
80
83
|
target="_blank"
|
81
84
|
>
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
3
4
|
import InventoryAutoUploadSwitcher from './ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload';
|
4
5
|
import NewHostDetailsTab from './InsightsHostDetailsTab/NewHostDetailsTab';
|
5
6
|
import { InsightsTotalRiskChartWrapper } from './InsightsHostDetailsTab/InsightsTotalRiskChartWrapper';
|
6
7
|
import { isNotRhelHost, vulnerabilityDisabled } from './ForemanRhCloudHelpers';
|
7
|
-
import
|
8
|
+
import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab/CVEsHostDetailsTab';
|
8
9
|
|
9
10
|
const fills = [
|
10
11
|
{
|
@@ -20,6 +21,7 @@ const fills = [
|
|
20
21
|
weight: 400,
|
21
22
|
metadata: {
|
22
23
|
hideTab: isNotRhelHost,
|
24
|
+
title: __('Insights'),
|
23
25
|
},
|
24
26
|
},
|
25
27
|
{
|
@@ -30,11 +32,12 @@ const fills = [
|
|
30
32
|
},
|
31
33
|
{
|
32
34
|
slot: 'host-details-page-tabs',
|
33
|
-
name: '
|
34
|
-
component: props => <
|
35
|
+
name: 'Vulnerabilities',
|
36
|
+
component: props => <CVEsHostDetailsTabWrapper {...props} />,
|
35
37
|
weight: 300,
|
36
38
|
metadata: {
|
37
39
|
hideTab: vulnerabilityDisabled,
|
40
|
+
title: __('Vulnerabilities'),
|
38
41
|
},
|
39
42
|
},
|
40
43
|
];
|
@@ -1,16 +1,24 @@
|
|
1
|
+
/* eslint-disable spellcheck/spell-checker */
|
1
2
|
import React from 'react';
|
2
3
|
import componentRegistry from 'foremanReact/components/componentRegistry';
|
3
4
|
import { registerRoutes as foremanRegisterRoutes } from 'foremanReact/routes/RoutingService';
|
4
5
|
import ForemanInventoryUpload from './ForemanInventoryUpload';
|
5
|
-
import
|
6
|
+
import InsightsVulnerabilityListPage from './InsightsVulnerability/InsightsVulnerabilityListPage';
|
6
7
|
import InsightsCloudSync from './InsightsCloudSync';
|
8
|
+
import IopRecommendationDetails from './IopRecommendationDetails/IopRecommendationDetails';
|
7
9
|
import InsightsHostDetailsTab from './InsightsHostDetailsTab';
|
10
|
+
import CveDetailsPage from './CveDetailsPage';
|
8
11
|
|
9
12
|
const pages = [
|
10
13
|
{ name: 'ForemanInventoryUpload', type: ForemanInventoryUpload },
|
11
14
|
{ name: 'InsightsCloudSync', type: InsightsCloudSync },
|
15
|
+
{ name: 'IopRecommendationDetails', type: IopRecommendationDetails },
|
12
16
|
{ name: 'InsightsHostDetailsTab', type: InsightsHostDetailsTab },
|
13
|
-
{
|
17
|
+
{
|
18
|
+
name: 'InsightsVulnerabilityListPage',
|
19
|
+
type: InsightsVulnerabilityListPage,
|
20
|
+
},
|
21
|
+
{ name: 'CveDetailsPage', type: CveDetailsPage },
|
14
22
|
];
|
15
23
|
|
16
24
|
export const registerPages = () => {
|
@@ -23,6 +31,11 @@ export const routes = [
|
|
23
31
|
exact: true,
|
24
32
|
render: props => <InsightsCloudSync {...props} />,
|
25
33
|
},
|
34
|
+
{
|
35
|
+
path: '/foreman_rh_cloud/recommendations',
|
36
|
+
exact: false,
|
37
|
+
render: props => <IopRecommendationDetails {...props} />,
|
38
|
+
},
|
26
39
|
{
|
27
40
|
path: '/foreman_rh_cloud/inventory_upload',
|
28
41
|
exact: true,
|
@@ -31,7 +44,12 @@ export const routes = [
|
|
31
44
|
{
|
32
45
|
path: '/foreman_rh_cloud/insights_vulnerability',
|
33
46
|
exact: true,
|
34
|
-
render: props => <
|
47
|
+
render: props => <InsightsVulnerabilityListPage {...props} />,
|
48
|
+
},
|
49
|
+
{
|
50
|
+
path: '/foreman_rh_cloud/insights_vulnerability/:cveId',
|
51
|
+
exact: true,
|
52
|
+
render: props => <CveDetailsPage {...props} />,
|
35
53
|
},
|
36
54
|
];
|
37
55
|
|
@@ -75,6 +75,7 @@ const InsightsTable = ({
|
|
75
75
|
/>
|
76
76
|
<Table
|
77
77
|
className="rh-cloud-recommendations-table"
|
78
|
+
ouiaId="rh-cloud-recommendations-table"
|
78
79
|
aria-label="Recommendations Table"
|
79
80
|
onSelect={(_event, isSelected, rowId) =>
|
80
81
|
onTableSelect(isSelected, rowId, rows, selectedIds)
|
@@ -18,6 +18,7 @@ const SelectAllAlert = ({
|
|
18
18
|
<Alert
|
19
19
|
isInline
|
20
20
|
variant="info"
|
21
|
+
ouiaId="alert-recommendations-selected"
|
21
22
|
title={sprintf(__('Recommendations selected: %s.'), selectedCount)}
|
22
23
|
actionLinks={
|
23
24
|
<AlertActionLink onClick={selectAll}>
|
@@ -32,6 +33,7 @@ const SelectAllAlert = ({
|
|
32
33
|
<Alert
|
33
34
|
isInline
|
34
35
|
variant="info"
|
36
|
+
ouiaId="alert-all-selected"
|
35
37
|
title={__('All recommendations are now selected.')}
|
36
38
|
actionLinks={
|
37
39
|
<AlertActionLink onClick={clearAllSelection}>
|
@@ -46,6 +46,7 @@ const RemediationModal = ({
|
|
46
46
|
return (
|
47
47
|
<React.Fragment>
|
48
48
|
<Button
|
49
|
+
ouiaId="button-remediate"
|
49
50
|
variant="primary"
|
50
51
|
isDisabled={isEmpty(selectedIds)}
|
51
52
|
onClick={() => {
|
@@ -56,6 +57,7 @@ const RemediationModal = ({
|
|
56
57
|
</Button>{' '}
|
57
58
|
<Modal
|
58
59
|
id="remediation-modal"
|
60
|
+
ouiaId="remediation-modal"
|
59
61
|
appendTo={document.body}
|
60
62
|
variant={ModalVariant.large}
|
61
63
|
title={__('Remediation summary')}
|
@@ -71,6 +73,7 @@ const RemediationModal = ({
|
|
71
73
|
>
|
72
74
|
<Table
|
73
75
|
className="remediations-table"
|
76
|
+
ouiaId="remediations-table"
|
74
77
|
aria-label="remediations Table"
|
75
78
|
cells={columns}
|
76
79
|
rows={rows}
|
@@ -9,10 +9,20 @@ const ModalFooter = ({ toggleModal, resolutions, hostsIds }) => {
|
|
9
9
|
token = token?.content || '';
|
10
10
|
return (
|
11
11
|
<form action={JOB_INVOCATION_PATH} method="post">
|
12
|
-
<Button
|
12
|
+
<Button
|
13
|
+
type="submit"
|
14
|
+
ouiaId="button-confirm"
|
15
|
+
key="confirm"
|
16
|
+
variant="primary"
|
17
|
+
>
|
13
18
|
{__('Remediate')}
|
14
19
|
</Button>
|
15
|
-
<Button
|
20
|
+
<Button
|
21
|
+
key="cancel"
|
22
|
+
ouiaId="button-cancel"
|
23
|
+
variant="link"
|
24
|
+
onClick={toggleModal}
|
25
|
+
>
|
16
26
|
{__('Cancel')}
|
17
27
|
</Button>
|
18
28
|
<input type="hidden" name="feature" value="rh_cloud_remediate_hosts" />
|
@@ -18,6 +18,7 @@ const Resolutions = ({
|
|
18
18
|
{resolutions.map(({ id: resolution_id, description }) => (
|
19
19
|
<Radio
|
20
20
|
key={resolution_id}
|
21
|
+
ouiaId={`resolution-radio-${resolution_id}`}
|
21
22
|
className="resolution-radio"
|
22
23
|
id={resolution_id}
|
23
24
|
isChecked={resolution_id === checkedID}
|
@@ -19,11 +19,15 @@ const ToolbarDropdown = ({ onRecommendationSync }) => {
|
|
19
19
|
const dropdownItems = [
|
20
20
|
<DropdownItem
|
21
21
|
key="recommendation-manual-sync"
|
22
|
+
ouiaId="recommendation-manual-sync"
|
22
23
|
onClick={onRecommendationSync}
|
23
24
|
>
|
24
25
|
{__('Sync recommendations')}
|
25
26
|
</DropdownItem>,
|
26
|
-
<DropdownItem
|
27
|
+
<DropdownItem
|
28
|
+
key="cloud-advisor-systems-link"
|
29
|
+
ouiaId="cloud-advisor-systems-link"
|
30
|
+
>
|
27
31
|
<a
|
28
32
|
href={redHatAdvisorSystems()}
|
29
33
|
target="_blank"
|
@@ -38,6 +42,7 @@ const ToolbarDropdown = ({ onRecommendationSync }) => {
|
|
38
42
|
return (
|
39
43
|
<Dropdown
|
40
44
|
className="title-dropdown"
|
45
|
+
ouiaId="title-dropdown"
|
41
46
|
onSelect={() => setIsDropdownOpen(false)}
|
42
47
|
toggle={
|
43
48
|
<KebabToggle onToggle={(_event, isOpen) => setIsDropdownOpen(isOpen)} />
|
@@ -1,7 +1,10 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
4
|
+
import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core';
|
4
5
|
import InsightsTable from './Components/InsightsTable';
|
6
|
+
import { useAdvisorEngineConfig } from '../common/Hooks/ConfigHooks';
|
7
|
+
import { foremanUrl } from '../ForemanRhCloudHelpers';
|
5
8
|
import RemediationModal from './Components/RemediationModal';
|
6
9
|
import {
|
7
10
|
INSIGHTS_SYNC_PAGE_TITLE,
|
@@ -11,7 +14,9 @@ import './InsightsCloudSync.scss';
|
|
11
14
|
import Pagination from './Components/InsightsTable/Pagination';
|
12
15
|
import ToolbarDropdown from './Components/ToolbarDropdown';
|
13
16
|
import InsightsSettings from './Components/InsightsSettings';
|
17
|
+
import { providerOptions } from '../common/ScalprumModule/ScalprumContext';
|
14
18
|
|
19
|
+
// Hosted Insights advisor
|
15
20
|
const InsightsCloudSync = ({ syncInsights, query, fetchInsights }) => {
|
16
21
|
const onRecommendationSync = () => syncInsights(fetchInsights, query);
|
17
22
|
const toolbarButtons = (
|
@@ -54,4 +59,37 @@ InsightsCloudSync.defaultProps = {
|
|
54
59
|
query: '',
|
55
60
|
};
|
56
61
|
|
57
|
-
|
62
|
+
// Local Insights advisor
|
63
|
+
const scope = 'advisor';
|
64
|
+
const module = './ListWrapped';
|
65
|
+
|
66
|
+
export const generateRuleUrl = ruleId =>
|
67
|
+
foremanUrl(`/foreman_rh_cloud/recommendations/${ruleId}`);
|
68
|
+
|
69
|
+
const IopRecommendationsPage = props => (
|
70
|
+
<ScalprumComponent
|
71
|
+
scope={scope}
|
72
|
+
module={module}
|
73
|
+
IopRemediationModal={RemediationModal}
|
74
|
+
generateRuleUrl={generateRuleUrl}
|
75
|
+
{...props}
|
76
|
+
/>
|
77
|
+
);
|
78
|
+
|
79
|
+
const IopRecommendationsPageWrapped = props => (
|
80
|
+
<ScalprumProvider {...providerOptions}>
|
81
|
+
<IopRecommendationsPage {...props} />
|
82
|
+
</ScalprumProvider>
|
83
|
+
);
|
84
|
+
|
85
|
+
const RecommendationsPage = props => {
|
86
|
+
const isLocalAdvisorEngine = useAdvisorEngineConfig();
|
87
|
+
|
88
|
+
return isLocalAdvisorEngine ? (
|
89
|
+
<IopRecommendationsPageWrapped {...props} />
|
90
|
+
) : (
|
91
|
+
<InsightsCloudSync {...props} />
|
92
|
+
);
|
93
|
+
};
|
94
|
+
|
95
|
+
export default RecommendationsPage;
|
@@ -1,54 +1,10 @@
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
2
|
|
3
3
|
exports[`InsightsCloudSync render 1`] = `
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
header="Red Hat Insights"
|
11
|
-
onSearch={[Function]}
|
12
|
-
searchProps={
|
13
|
-
Object {
|
14
|
-
"autocomplete": Object {
|
15
|
-
"id": "searchBar",
|
16
|
-
"searchQuery": "",
|
17
|
-
"url": "/insights_cloud/hits/auto_complete_search",
|
18
|
-
"useKeyShortcuts": true,
|
19
|
-
},
|
20
|
-
"bookmarks": Object {
|
21
|
-
"canCreateBookmarks": true,
|
22
|
-
"documentationUrl": "4.1.5Searching",
|
23
|
-
"url": "/api/bookmarks",
|
24
|
-
},
|
25
|
-
"controller": "insights_hits",
|
26
|
-
}
|
27
|
-
}
|
28
|
-
searchQuery=""
|
29
|
-
searchable={true}
|
30
|
-
toolbarButtons={
|
31
|
-
<React.Fragment>
|
32
|
-
<span
|
33
|
-
className="insights-toolbar-buttons"
|
34
|
-
>
|
35
|
-
<Memo(Connect(RemediationModal)) />
|
36
|
-
<ToolbarDropdown
|
37
|
-
onRecommendationSync={[Function]}
|
38
|
-
/>
|
39
|
-
</span>
|
40
|
-
<span
|
41
|
-
className="pull-right"
|
42
|
-
>
|
43
|
-
<Pagination
|
44
|
-
isCompact={true}
|
45
|
-
variant="top"
|
46
|
-
/>
|
47
|
-
</span>
|
48
|
-
</React.Fragment>
|
49
|
-
}
|
50
|
-
>
|
51
|
-
<Connect(InsightsTable) />
|
52
|
-
</PageLayout>
|
53
|
-
</div>
|
4
|
+
<InsightsCloudSync
|
5
|
+
fetchInsights={[Function]}
|
6
|
+
query=""
|
7
|
+
status="RESOLVED"
|
8
|
+
syncInsights={[Function]}
|
9
|
+
/>
|
54
10
|
`;
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
3
3
|
import { useDispatch, useSelector } from 'react-redux';
|
4
4
|
import SearchBar from 'foremanReact/components/SearchBar';
|
5
5
|
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core';
|
6
7
|
import { Grid, GridItem } from '@patternfly/react-core';
|
7
8
|
import {
|
8
9
|
Dropdown,
|
@@ -21,7 +22,10 @@ import {
|
|
21
22
|
} from '../InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors';
|
22
23
|
import { redHatAdvisorSystems } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
|
23
24
|
import { useAdvisorEngineConfig } from '../common/Hooks/ConfigHooks';
|
25
|
+
import { generateRuleUrl } from '../InsightsCloudSync/InsightsCloudSync';
|
26
|
+
import { providerOptions } from '../common/ScalprumModule/ScalprumContext';
|
24
27
|
|
28
|
+
// Hosted Insights advisor
|
25
29
|
const NewHostDetailsTab = ({ hostName, router }) => {
|
26
30
|
const dispatch = useDispatch();
|
27
31
|
const query = useSelector(selectSearch);
|
@@ -104,4 +108,50 @@ NewHostDetailsTab.defaultProps = {
|
|
104
108
|
router: {},
|
105
109
|
};
|
106
110
|
|
107
|
-
|
111
|
+
// Local Insights advisor
|
112
|
+
const scope = 'advisor';
|
113
|
+
// eslint-disable-next-line spellcheck/spell-checker
|
114
|
+
const module = './HostDetailsLightspeedTabWrapped';
|
115
|
+
|
116
|
+
const IopInsightsTab = props => (
|
117
|
+
<ScalprumComponent
|
118
|
+
scope={scope}
|
119
|
+
module={module}
|
120
|
+
IopRemediationModal={RemediationModal}
|
121
|
+
generateRuleUrl={generateRuleUrl}
|
122
|
+
{...props}
|
123
|
+
/>
|
124
|
+
);
|
125
|
+
|
126
|
+
const IopInsightsTabWrapped = props => (
|
127
|
+
<ScalprumProvider {...providerOptions}>
|
128
|
+
<IopInsightsTab {...props} />
|
129
|
+
</ScalprumProvider>
|
130
|
+
);
|
131
|
+
|
132
|
+
const LightspeedTab = props => {
|
133
|
+
const { response } = props;
|
134
|
+
const isLocalAdvisorEngine =
|
135
|
+
// eslint-disable-next-line camelcase
|
136
|
+
response?.insights_attributes?.use_local_advisor_engine;
|
137
|
+
|
138
|
+
return isLocalAdvisorEngine ? (
|
139
|
+
<IopInsightsTabWrapped {...props} />
|
140
|
+
) : (
|
141
|
+
<NewHostDetailsTab {...props} />
|
142
|
+
);
|
143
|
+
};
|
144
|
+
|
145
|
+
LightspeedTab.propTypes = {
|
146
|
+
response: PropTypes.shape({
|
147
|
+
insights_attributes: {
|
148
|
+
use_local_advisor_engine: PropTypes.bool,
|
149
|
+
},
|
150
|
+
}),
|
151
|
+
};
|
152
|
+
|
153
|
+
LightspeedTab.defaultProps = {
|
154
|
+
response: {},
|
155
|
+
};
|
156
|
+
|
157
|
+
export default LightspeedTab;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core';
|
3
|
+
import { providerOptions } from '../common/ScalprumModule/ScalprumContext';
|
4
|
+
|
5
|
+
const InsightsVulnerabilityListPage = () => {
|
6
|
+
const scope = 'vulnerability';
|
7
|
+
const module = './CveListPage';
|
8
|
+
return (
|
9
|
+
<div className="rh-cloud-insights-vulnerability-page">
|
10
|
+
<ScalprumComponent scope={scope} module={module} />
|
11
|
+
</div>
|
12
|
+
);
|
13
|
+
};
|
14
|
+
|
15
|
+
const InsightsVulnerabilityListPageWrap = () => (
|
16
|
+
<ScalprumProvider {...providerOptions}>
|
17
|
+
<InsightsVulnerabilityListPage />
|
18
|
+
</ScalprumProvider>
|
19
|
+
);
|
20
|
+
|
21
|
+
export default InsightsVulnerabilityListPageWrap;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render } from '@testing-library/react';
|
3
|
+
import '@testing-library/jest-dom';
|
4
|
+
import InsightsVulnerabilityListPage from './InsightsVulnerabilityListPage';
|
5
|
+
|
6
|
+
jest.mock('@scalprum/react-core', () => ({
|
7
|
+
ScalprumComponent: jest.fn(props => (
|
8
|
+
<div data-testid="mock-scalprum-component">{JSON.stringify(props)}</div>
|
9
|
+
)),
|
10
|
+
ScalprumProvider: jest.fn(({ children }) => <div>{children}</div>),
|
11
|
+
}));
|
12
|
+
|
13
|
+
describe('InsightsVulnerabilityListPage component', () => {
|
14
|
+
it('renders the container with correct class', () => {
|
15
|
+
const { container } = render(<InsightsVulnerabilityListPage />);
|
16
|
+
expect(
|
17
|
+
container.querySelector('.rh-cloud-insights-vulnerability-page')
|
18
|
+
).toBeTruthy();
|
19
|
+
});
|
20
|
+
});
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { UnknownIcon } from '@patternfly/react-icons';
|
4
|
+
import { Link } from 'react-router-dom';
|
5
|
+
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
|
6
|
+
|
7
|
+
import { insightsCloudUrl } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
|
8
|
+
|
9
|
+
const vulnerabilityApiPath = path =>
|
10
|
+
insightsCloudUrl(`api/vulnerability/v1/${path}`);
|
11
|
+
|
12
|
+
export const CVECountCell = ({ hostDetails }) => {
|
13
|
+
// eslint-disable-next-line camelcase
|
14
|
+
const uuid = hostDetails?.subscription_facet_attributes?.uuid;
|
15
|
+
|
16
|
+
const key = `HOST_CVE_COUNT_${uuid}`;
|
17
|
+
const response = useAPI(
|
18
|
+
uuid ? 'get' : null,
|
19
|
+
vulnerabilityApiPath(`systems?uuid=${uuid}`),
|
20
|
+
{
|
21
|
+
key,
|
22
|
+
}
|
23
|
+
);
|
24
|
+
|
25
|
+
if (uuid === undefined) {
|
26
|
+
return <UnknownIcon />;
|
27
|
+
}
|
28
|
+
|
29
|
+
// eslint-disable-next-line camelcase
|
30
|
+
const { cve_count } = (response.response?.data || [])[0]?.attributes || {};
|
31
|
+
|
32
|
+
const cveLink = (
|
33
|
+
// eslint-disable-next-line camelcase
|
34
|
+
<Link to={`hosts/${hostDetails.name}#/Vulnerabilities`}>{cve_count}</Link>
|
35
|
+
);
|
36
|
+
|
37
|
+
// eslint-disable-next-line camelcase
|
38
|
+
return cve_count === undefined ? <UnknownIcon /> : cveLink;
|
39
|
+
};
|
40
|
+
|
41
|
+
CVECountCell.propTypes = {
|
42
|
+
hostDetails: PropTypes.object.isRequired,
|
43
|
+
};
|
44
|
+
|
45
|
+
export default CVECountCell;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render, screen } from '@testing-library/react';
|
3
|
+
import { API } from 'foremanReact/redux/API';
|
4
|
+
import { CVECountCell } from '../CVECountCell';
|
5
|
+
|
6
|
+
jest.mock('foremanReact/redux/API');
|
7
|
+
API.get.mockImplementation(async () => ({
|
8
|
+
data: [
|
9
|
+
{
|
10
|
+
attributes: {
|
11
|
+
cve_count: 1,
|
12
|
+
},
|
13
|
+
},
|
14
|
+
],
|
15
|
+
}));
|
16
|
+
|
17
|
+
describe('CVECountCell', () => {
|
18
|
+
it('renders an empty cves count column', () => {
|
19
|
+
const hostDetailsMock = {
|
20
|
+
name: 'test-host.example.com',
|
21
|
+
subscription_facet_attributes: {
|
22
|
+
uuid: null, // no subscription
|
23
|
+
},
|
24
|
+
};
|
25
|
+
render(<CVECountCell hostDetails={hostDetailsMock} />);
|
26
|
+
expect(screen.getByRole('img', { hidden: true })).toBeTruthy();
|
27
|
+
});
|
28
|
+
});
|