foreman_rh_cloud 12.1.1 → 12.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/config/routes.rb CHANGED
@@ -37,6 +37,7 @@ Rails.application.routes.draw do
37
37
  get 'inventory_upload', to: '/react#index'
38
38
  end
39
39
  get 'insights_cloud', to: '/react#index' # Uses foreman's react controller
40
+ get 'insights_vulnerability', to: '/react#index'
40
41
  end
41
42
 
42
43
  scope :module => :'insights_cloud/api', :path => :redhat_access do
@@ -44,12 +44,12 @@ module ForemanRhCloud
44
44
  setting('allow_auto_inventory_upload', type: :boolean, description: N_('Enable automatic upload of your host inventory to the Red Hat cloud'), default: true, full_name: N_('Automatic inventory upload'))
45
45
  setting('allow_auto_insights_sync', type: :boolean, description: N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), default: true, full_name: N_('Synchronize recommendations Automatically'))
46
46
  setting('allow_auto_insights_mismatch_delete', type: :boolean, description: N_('Enable automatic deletion of mismatched host records from the Red Hat cloud'), default: false, full_name: N_('Automatic mismatch deletion'))
47
- setting('obfuscate_inventory_hostnames', type: :boolean, description: N_('Obfuscate host names sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored and host names are always obfuscated.)'), default: false, full_name: N_('Obfuscate host names'))
48
- setting('obfuscate_inventory_ips', type: :boolean, description: N_('Obfuscate ipv4 addresses sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored and host ipv4 addresses are always obfuscated.)'), default: false, full_name: N_('Obfuscate host ipv4 addresses.'))
47
+ setting('obfuscate_inventory_hostnames', type: :boolean, description: N_('Obfuscate host names sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host names are not included in the report.)'), default: false, full_name: N_('Obfuscate host names'))
48
+ setting('obfuscate_inventory_ips', type: :boolean, description: N_('Obfuscate ipv4 addresses sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host IPv4 addresses are not included in the report.)'), default: false, full_name: N_('Obfuscate host ipv4 addresses.'))
49
49
  setting('exclude_installed_packages', type: :boolean, description: N_('Exclude installed packages from being uploaded to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored and installed packages are always excluded.)'), default: false, full_name: N_("Exclude installed packages"))
50
50
  setting('include_parameter_tags', type: :boolean, description: N_('Should import include parameter tags from Foreman?'), default: false, full_name: N_('Include parameters in insights-client reports'))
51
51
  setting('rhc_instance_id', type: :string, description: N_('RHC daemon id'), default: nil, full_name: N_('ID of the RHC(Yggdrasil) daemon'))
52
- setting('insights_minimal_data_collection', type: :boolean, default: false, full_name: N_('Minimal data collection'), description: N_('Only send the minimum required data to Red Hat cloud, and obfuscate wherever possible. When this is true, hostnames and IPv4 addresses are always obfuscated and installed packages are excluded, regardless of those settings.'))
52
+ setting('insights_minimal_data_collection', type: :boolean, default: false, full_name: N_('Minimal data collection'), description: N_('Only include the minimum required data in inventory reports for uploading to Red Hat cloud. When this is true, installed packages are excluded from the report regardless of the exclude_installed_packages setting, and host names and IPv4 addresses are excluded from the report regardless of obfuscation settings.'))
53
53
  end
54
54
  end
55
55
 
@@ -117,11 +117,18 @@ module ForemanRhCloud
117
117
  parent: :insights_menu,
118
118
  if: -> { !ForemanRhCloud.with_local_advisor_engine? }
119
119
  menu :top_menu, :insights_hits, caption: N_('Recommendations'), url: '/foreman_rh_cloud/insights_cloud', url_hash: { controller: :react, action: :index }, parent: :insights_menu
120
+ menu :top_menu,
121
+ :insights_vulnerability,
122
+ caption: N_('Vulnerability'),
123
+ url: '/foreman_rh_cloud/insights_vulnerability',
124
+ url_hash: { controller: :react, action: :index },
125
+ parent: :insights_menu,
126
+ if: -> { ForemanRhCloud.with_local_advisor_engine? }
120
127
  end
121
128
 
122
129
  register_facet InsightsFacet, :insights do
123
130
  configure_host do
124
- api_view :list => 'api/v2/hosts/insights/insights'
131
+ api_view :list => 'api/v2/hosts/insights/insights', :single => 'api/v2/hosts/insights/single'
125
132
  set_dependent_action :destroy
126
133
  end
127
134
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '12.1.1'.freeze
2
+ VERSION = '12.1.2'.freeze
3
3
  end
@@ -0,0 +1,2 @@
1
+ module InsightsVulnerability
2
+ end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "12.1.1",
3
+ "version": "12.1.2",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ const CVEsHostDetailsTab = ({ hostName }) => (
6
+ <div>
7
+ <h1>
8
+ {__('CVEs tab for host:')} {hostName}
9
+ </h1>
10
+ </div>
11
+ );
12
+
13
+ CVEsHostDetailsTab.propTypes = {
14
+ hostName: PropTypes.string.isRequired,
15
+ };
16
+
17
+ export default CVEsHostDetailsTab;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import CVEsHostDetailsTab from '../CVEsHostDetailsTab';
4
+
5
+ describe('CVEsHostDetailsTab', () => {
6
+ it('renders without crashing', () => {
7
+ render(<CVEsHostDetailsTab hostName="test-host.example.com" />);
8
+ expect(
9
+ screen.getByText('CVEs tab for host: test-host.example.com')
10
+ ).toBeTruthy();
11
+ });
12
+
13
+ it('renders the host name', () => {
14
+ const hostName = 'test-host.example.com';
15
+ render(<CVEsHostDetailsTab hostName={hostName} />);
16
+ expect(screen.getByText(`CVEs tab for host: ${hostName}`)).toBeTruthy();
17
+ });
18
+ });
@@ -0,0 +1,3 @@
1
+ import CVEsHostDetailsTab from './CVEsHostDetailsTab';
2
+
3
+ export default CVEsHostDetailsTab;
@@ -25,7 +25,7 @@ const MinimalInventoryDropdown = ({ setChosenValue }) => {
25
25
  ),
26
26
  },
27
27
  optional: {
28
- title: __('Optional data collection'),
28
+ title: __('Analytics data collection'),
29
29
  description: __(
30
30
  'Send additional data to enhance Insights services, as per the settings'
31
31
  ),
@@ -3,7 +3,8 @@ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
3
3
  import InventoryAutoUploadSwitcher from './ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload';
4
4
  import NewHostDetailsTab from './InsightsHostDetailsTab/NewHostDetailsTab';
5
5
  import { InsightsTotalRiskChartWrapper } from './InsightsHostDetailsTab/InsightsTotalRiskChartWrapper';
6
- import { isNotRhelHost } from './ForemanRhCloudHelpers';
6
+ import { isNotRhelHost, vulnerabilityDisabled } from './ForemanRhCloudHelpers';
7
+ import CVEsHostDetailsTab from './CVEsHostDetailsTab/CVEsHostDetailsTab';
7
8
 
8
9
  const fills = [
9
10
  {
@@ -27,6 +28,15 @@ const fills = [
27
28
  component: props => <InsightsTotalRiskChartWrapper {...props} />,
28
29
  weight: 2800,
29
30
  },
31
+ {
32
+ slot: 'host-details-page-tabs',
33
+ name: 'CVEs',
34
+ component: props => <CVEsHostDetailsTab {...props} />,
35
+ weight: 300,
36
+ metadata: {
37
+ hideTab: vulnerabilityDisabled,
38
+ },
39
+ },
30
40
  ];
31
41
 
32
42
  export const registerFills = () => {
@@ -11,3 +11,6 @@ export const isNotRhelHost = ({ hostDetails }) =>
11
11
  // eslint-disable-next-line camelcase
12
12
  hostDetails?.operatingsystem_name
13
13
  );
14
+
15
+ export const vulnerabilityDisabled = ({ hostDetails }) =>
16
+ isNotRhelHost({ hostDetails }) || !hostDetails?.vulnerability?.enabled;
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import componentRegistry from 'foremanReact/components/componentRegistry';
3
3
  import { registerRoutes as foremanRegisterRoutes } from 'foremanReact/routes/RoutingService';
4
4
  import ForemanInventoryUpload from './ForemanInventoryUpload';
5
+ import InsightsVulnerability from './InsightsVulnerability/InsightsVulnerability';
5
6
  import InsightsCloudSync from './InsightsCloudSync';
6
7
  import InsightsHostDetailsTab from './InsightsHostDetailsTab';
7
8
 
@@ -9,6 +10,7 @@ const pages = [
9
10
  { name: 'ForemanInventoryUpload', type: ForemanInventoryUpload },
10
11
  { name: 'InsightsCloudSync', type: InsightsCloudSync },
11
12
  { name: 'InsightsHostDetailsTab', type: InsightsHostDetailsTab },
13
+ { name: 'InsightsVulnerability', type: InsightsVulnerability },
12
14
  ];
13
15
 
14
16
  export const registerPages = () => {
@@ -26,6 +28,11 @@ export const routes = [
26
28
  exact: true,
27
29
  render: props => <ForemanInventoryUpload {...props} />,
28
30
  },
31
+ {
32
+ path: '/foreman_rh_cloud/insights_vulnerability',
33
+ exact: true,
34
+ render: props => <InsightsVulnerability {...props} />,
35
+ },
29
36
  ];
30
37
 
31
38
  export const registerRoutes = () => {
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import {
3
+ AngleDoubleDownIcon,
4
+ AngleDoubleUpIcon,
5
+ CriticalRiskIcon,
6
+ EqualsIcon,
7
+ } from '@patternfly/react-icons';
8
+ import { Label } from '@patternfly/react-core';
9
+ import PropTypes from 'prop-types';
10
+
11
+ const VALUE_TO_STATE = {
12
+ 1: { icon: <AngleDoubleDownIcon />, text: 'Low', color: 'blue' },
13
+ 2: { icon: <EqualsIcon />, text: 'Moderate', color: 'yellow' },
14
+ 3: { icon: <AngleDoubleUpIcon />, text: 'Important', color: 'orange' },
15
+ 4: { icon: <CriticalRiskIcon />, text: 'Critical', color: 'red' },
16
+ };
17
+
18
+ const InsightsLabel = ({ value = 1, text, hideIcon, ...props }) => (
19
+ <Label
20
+ {...props}
21
+ color={VALUE_TO_STATE[value].color}
22
+ icon={!hideIcon && VALUE_TO_STATE[value].icon}
23
+ >
24
+ {text || VALUE_TO_STATE[value].text}
25
+ </Label>
26
+ );
27
+
28
+ InsightsLabel.propTypes = {
29
+ value: PropTypes.oneOf([1, 2, 3, 4]),
30
+ text: PropTypes.string,
31
+ hideIcon: PropTypes.bool,
32
+ };
33
+
34
+ InsightsLabel.defaultProps = {
35
+ value: 1,
36
+ text: '',
37
+ hideIcon: false,
38
+ };
39
+
40
+ export default InsightsLabel;
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import './InsightsSection.scss';
5
+
6
+ const InsightsSection = ({ type, children, className, ...props }) => {
7
+ let sectionClasses = className || '';
8
+ if (type !== undefined) {
9
+ sectionClasses = `${sectionClasses} ins-l-${type}`.trim();
10
+ }
11
+
12
+ return (
13
+ <section {...props} className={sectionClasses}>
14
+ {children}
15
+ </section>
16
+ );
17
+ };
18
+
19
+ InsightsSection.propTypes = {
20
+ type: PropTypes.string,
21
+ children: PropTypes.node,
22
+ className: PropTypes.string,
23
+ };
24
+ InsightsSection.defaultProps = {
25
+ type: undefined,
26
+ children: null,
27
+ className: '',
28
+ };
29
+
30
+ export default InsightsSection;
@@ -0,0 +1,25 @@
1
+ section.ins-l-content {
2
+ padding: var(--pf-t--global--spacer--lg);
3
+ }
4
+
5
+ section.ins-l-button-group {
6
+ > * { display: inline; }
7
+ * + * { margin-left: 0.3125rem; } // 5px = 0.3125rem
8
+ margin: 1.5rem 0; // 24px = 1.5rem
9
+ }
10
+
11
+ section.ins-l-icon-group {
12
+ * + * { margin-left: 0.625rem; } // 10px = 0.625rem
13
+ }
14
+
15
+ section.ins-l-icon-group__with-major {
16
+ * + * { margin-left: 0.46875rem; } // 7.5px = 0.46875rem
17
+ .ins-battery:last-of-type {
18
+ padding-left: 0.9375rem; // 15px = 0.9375rem
19
+ border-left: 2px solid #eaeaea;
20
+ span.label{
21
+ font-weight: 500;
22
+ margin: 0 0.625rem; // 10px = 0.625rem
23
+ }
24
+ }
25
+ }
@@ -1,21 +1,19 @@
1
1
  /* eslint-disable camelcase */
2
2
  import React from 'react';
3
- import {
4
- InsightsLabel,
5
- Section,
6
- } from '@redhat-cloud-services/frontend-components';
7
3
  import { DropdownItem } from '@patternfly/react-core/deprecated';
8
4
  import { sortable, cellWidth } from '@patternfly/react-table';
9
5
  import { AnsibeTowerIcon, ExternalLinkAltIcon } from '@patternfly/react-icons';
10
6
  import { translate as __ } from 'foremanReact/common/I18n';
11
7
  import { foremanUrl } from '../../../ForemanRhCloudHelpers';
12
8
  import DropdownToggle from '../../../common/DropdownToggle';
9
+ import InsightsSection from './InsightsSection';
10
+ import InsightsLabel from './InsightsLabel';
13
11
 
14
12
  export const totalRiskFormatter = ({ title: totalRisk }) => ({
15
13
  children: (
16
- <Section className="insights-total-risk" type="icon-group">
14
+ <InsightsSection className="insights-total-risk" type="icon-group">
17
15
  <InsightsLabel value={totalRisk} />
18
- </Section>
16
+ </InsightsSection>
19
17
  ),
20
18
  });
21
19
 
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ const InsightsVulnerability = () => (
6
+ <PageLayout searchable={false} header={__('Vulnerability')}>
7
+ <div className="insights-vulnerability">
8
+ <p>This page is under development. Please check back soon for updates.</p>
9
+ </div>
10
+ </PageLayout>
11
+ );
12
+
13
+ export default InsightsVulnerability;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import InsightsVulnerability from './InsightsVulnerability';
5
+
6
+ describe('InsightsVulnerability component', () => {
7
+ it('renders the "under development" message', () => {
8
+ render(<InsightsVulnerability />);
9
+ expect(
10
+ screen.getByText(/this page is under development/i)
11
+ ).toBeInTheDocument();
12
+ });
13
+
14
+ it('renders the container with correct class', () => {
15
+ const { container } = render(<InsightsVulnerability />);
16
+ expect(container.querySelector('.insights-vulnerability')).toBeTruthy();
17
+ });
18
+ });
@@ -1,10 +1,39 @@
1
1
  import { testSelectorsSnapshotWithFixtures } from '@theforeman/test';
2
- import { foremanUrl } from '../ForemanRhCloudHelpers';
2
+ import { foremanUrl, vulnerabilityDisabled } from '../ForemanRhCloudHelpers';
3
3
 
4
4
  global.URL_PREFIX = 'MY_TEST_URL_PREFIX.example.com';
5
5
 
6
6
  const fixtures = {
7
7
  'should return foreman Url': () => foremanUrl('/test_path'),
8
+ 'vulnerabilityDisabled returns false for RHEL host with vulnerability enabled': () =>
9
+ vulnerabilityDisabled({
10
+ hostDetails: {
11
+ operatingsystem_name: 'Red Hat Enterprise Linux',
12
+ vulnerability: { enabled: true },
13
+ },
14
+ }),
15
+ 'vulnerabilityDisabled returns true for non-RHEL host': () =>
16
+ vulnerabilityDisabled({
17
+ hostDetails: {
18
+ operatingsystem_name: 'Ubuntu',
19
+ vulnerability: { enabled: true },
20
+ },
21
+ }),
22
+ 'vulnerabilityDisabled returns true for RHEL host with vulnerability disabled': () =>
23
+ vulnerabilityDisabled({
24
+ hostDetails: {
25
+ operatingsystem_name: 'Red Hat Enterprise Linux',
26
+ vulnerability: { enabled: false },
27
+ },
28
+ }),
29
+ 'vulnerabilityDisabled returns true for missing vulnerability object': () =>
30
+ vulnerabilityDisabled({
31
+ hostDetails: {
32
+ operatingsystem_name: 'Red Hat Enterprise Linux',
33
+ },
34
+ }),
35
+ 'vulnerabilityDisabled returns true for missing hostDetails': () =>
36
+ vulnerabilityDisabled({}),
8
37
  };
9
38
 
10
39
  describe('ForemanRhCloud helpers', () =>
@@ -1,3 +1,13 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`ForemanRhCloud helpers should return foreman Url 1`] = `"MY_TEST_URL_PREFIX.example.com/test_path"`;
4
+
5
+ exports[`ForemanRhCloud helpers vulnerabilityDisabled returns false for RHEL host with vulnerability enabled 1`] = `false`;
6
+
7
+ exports[`ForemanRhCloud helpers vulnerabilityDisabled returns true for RHEL host with vulnerability disabled 1`] = `true`;
8
+
9
+ exports[`ForemanRhCloud helpers vulnerabilityDisabled returns true for missing hostDetails 1`] = `true`;
10
+
11
+ exports[`ForemanRhCloud helpers vulnerabilityDisabled returns true for missing vulnerability object 1`] = `true`;
12
+
13
+ exports[`ForemanRhCloud helpers vulnerabilityDisabled returns true for non-RHEL host 1`] = `true`;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_rh_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.1.1
4
+ version: 12.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
@@ -144,6 +144,7 @@ files:
144
144
  - app/views/api/v2/advisor_engine/host_details.json.rabl
145
145
  - app/views/api/v2/hosts/insights/base.rabl
146
146
  - app/views/api/v2/hosts/insights/insights.rabl
147
+ - app/views/api/v2/hosts/insights/single.rabl
147
148
  - app/views/hosts/_insights_tab.html.erb
148
149
  - app/views/job_templates/cloud_connector.erb
149
150
  - app/views/job_templates/rh_cloud_download_playbook.erb
@@ -207,6 +208,7 @@ files:
207
208
  - lib/insights_cloud/async/insights_scheduled_sync.rb
208
209
  - lib/insights_cloud/async/rules_result.rb
209
210
  - lib/insights_cloud/generators/playbook_progress_generator.rb
211
+ - lib/insights_vulnerability.rb
210
212
  - lib/inventory_sync/async/host_result.rb
211
213
  - lib/inventory_sync/async/inventory_full_sync.rb
212
214
  - lib/inventory_sync/async/inventory_hosts_sync.rb
@@ -278,6 +280,9 @@ files:
278
280
  - test/unit/shell_process_job_test.rb
279
281
  - test/unit/slice_generator_test.rb
280
282
  - test/unit/tags_generator_test.rb
283
+ - webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js
284
+ - webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js
285
+ - webpack/CVEsHostDetailsTab/index.js
281
286
  - webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js
282
287
  - webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js
283
288
  - webpack/ForemanInventoryUpload/Components/AccountList/AccountList.stories.js
@@ -538,6 +543,9 @@ files:
538
543
  - webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsSelectors.test.js.snap
539
544
  - webpack/InsightsCloudSync/Components/InsightsSettings/index.js
540
545
  - webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss
546
+ - webpack/InsightsCloudSync/Components/InsightsTable/InsightsLabel.js
547
+ - webpack/InsightsCloudSync/Components/InsightsTable/InsightsSection.js
548
+ - webpack/InsightsCloudSync/Components/InsightsTable/InsightsSection.scss
541
549
  - webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js
542
550
  - webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableActions.js
543
551
  - webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js
@@ -599,6 +607,8 @@ files:
599
607
  - webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js
600
608
  - webpack/InsightsHostDetailsTab/components/ListItem/index.js
601
609
  - webpack/InsightsHostDetailsTab/index.js
610
+ - webpack/InsightsVulnerability/InsightsVulnerability.js
611
+ - webpack/InsightsVulnerability/InsightsVulnerability.test.js
602
612
  - webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js
603
613
  - webpack/__mocks__/foremanReact/common/I18n.js
604
614
  - webpack/__mocks__/foremanReact/common/MountingService.js