foreman_rh_cloud 12.2.1 → 12.2.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/rh_cloud/advisor_engine_config_controller.rb +1 -1
  3. data/app/controllers/api/v2/rh_cloud/cloud_request_controller.rb +3 -0
  4. data/app/controllers/api/v2/rh_cloud/inventory_controller.rb +3 -0
  5. data/app/controllers/concerns/foreman_rh_cloud/iop_smart_proxy_access.rb +28 -0
  6. data/app/controllers/concerns/insights_cloud/package_profile_upload_extensions.rb +1 -1
  7. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +3 -0
  8. data/app/controllers/foreman_rh_cloud/foreman_rh_cloud_controller.rb +22 -0
  9. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +19 -5
  10. data/app/models/foreman_rh_cloud/ping.rb +90 -0
  11. data/app/services/foreman_rh_cloud/cert_auth.rb +1 -1
  12. data/app/services/foreman_rh_cloud/cloud_request.rb +1 -1
  13. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +1 -1
  14. data/app/services/foreman_rh_cloud/hit_remediations_retriever.rb +27 -10
  15. data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +14 -12
  16. data/app/services/foreman_rh_cloud/tags_auth.rb +3 -2
  17. data/app/views/api/v2/hosts/insights/base.rabl +2 -2
  18. data/app/views/api/v2/hosts/insights/single.rabl +1 -1
  19. data/config/routes.rb +6 -14
  20. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +2 -2
  21. data/lib/foreman_inventory_upload/async/upload_report_job.rb +1 -1
  22. data/lib/foreman_inventory_upload/generators/slice.rb +24 -0
  23. data/lib/foreman_rh_cloud/engine.rb +6 -2
  24. data/lib/foreman_rh_cloud/plugin.rb +18 -2
  25. data/lib/foreman_rh_cloud/version.rb +1 -1
  26. data/lib/foreman_rh_cloud.rb +5 -6
  27. data/lib/insights_cloud/async/insights_scheduled_sync.rb +2 -2
  28. data/lib/inventory_sync/async/inventory_hosts_sync.rb +1 -1
  29. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +2 -2
  30. data/lib/tasks/insights.rake +1 -1
  31. data/lib/tasks/rh_cloud_inventory.rake +20 -2
  32. data/package.json +1 -1
  33. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +20 -3
  34. data/test/controllers/insights_sync/settings_controller_test.rb +1 -1
  35. data/test/factories/inventory_upload_factories.rb +4 -112
  36. data/test/jobs/inventory_scheduled_sync_test.rb +3 -3
  37. data/test/test_plugin_helper.rb +8 -2
  38. data/test/unit/rh_cloud_http_proxy_test.rb +3 -3
  39. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +4 -1
  40. data/test/unit/services/foreman_rh_cloud/insights_api_forwarder_test.rb +43 -2
  41. data/test/unit/services/foreman_rh_cloud/tags_auth_test.rb +15 -1
  42. data/test/unit/slice_generator_test.rb +33 -0
  43. data/test/unit/tags_generator_test.rb +4 -1
  44. data/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js +1 -1
  45. data/webpack/CveDetailsPage/CveDetailsPage.js +1 -1
  46. data/webpack/CveDetailsPage/CveDetailsPage.test.js +1 -3
  47. data/webpack/ForemanColumnExtensions/index.js +1 -1
  48. data/webpack/ForemanRhCloudPages.js +1 -0
  49. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationHelpers.js +26 -4
  50. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +85 -11
  51. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +39 -5
  52. data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +13 -0
  53. data/webpack/InsightsCloudSync/InsightsCloudSync.js +9 -7
  54. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +12 -10
  55. data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js +1 -1
  56. data/webpack/IopRecommendationDetails/IopRecommendationDetails.js +1 -1
  57. data/webpack/common/Hooks/ConfigHooks.js +1 -2
  58. data/webpack/common/styles.scss +7 -0
  59. metadata +5 -1
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable react-hooks/exhaustive-deps */
2
2
  import React, { useEffect } from 'react';
3
+ import Immutable from 'seamless-immutable';
3
4
  import PropTypes from 'prop-types';
4
5
  import {
5
6
  Table,
@@ -7,7 +8,7 @@ import {
7
8
  TableBody,
8
9
  } from '@patternfly/react-table/deprecated';
9
10
  import { Modal, ModalVariant, Button } from '@patternfly/react-core';
10
- import { isEmpty } from 'lodash';
11
+ import { isEmpty, noop } from 'lodash';
11
12
  import { STATUS } from 'foremanReact/constants';
12
13
  import { translate as __ } from 'foremanReact/common/I18n';
13
14
  import { columns } from './RemediationTableConstants';
@@ -15,8 +16,48 @@ import { modifyRows } from './RemediationHelpers';
15
16
  import ModalFooter from './RemediationModalFooter';
16
17
  import TableEmptyState from '../../../common/table/EmptyState';
17
18
  import './RemediationModal.scss';
19
+ import { useAdvisorEngineConfig } from '../../../common/Hooks/ConfigHooks';
20
+
21
+ /* eslint-disable spellcheck/spell-checker */
22
+
23
+ // Sample iopData:
24
+ // const iopTestData = Immutable([
25
+ // {
26
+ // hostid: 'c7c6727e-2966-4f7c-87f1-20ef14db7a2d',
27
+ // host_name: 'advisor-test.local',
28
+ // rulename: 'hardening_cryptopol_krb5|NO_CPOL_KRB5',
29
+ // resolutions: [
30
+ // {
31
+ // description: 'Remove manual crypto-policies',
32
+ // id: 'fix',
33
+ // needs_reboot: true,
34
+ // resolution_risk: 1,
35
+ // },
36
+ // ],
37
+ // rebootable: true,
38
+ // description: 'Decreased security: krb5 crypto-policies overridden',
39
+ // },
40
+ // {
41
+ // hostid: 'c7c6727e-2966-4f7c-87f1-20ef14db7a2d',
42
+ // host_name: 'advisor-test.local',
43
+ // rulename: 'hardening_logging_auditd|HARDENING_LOGGING_5_AUDITD',
44
+ // resolutions: [
45
+ // {
46
+ // description: 'Install and enable auditd',
47
+ // id: 'fix',
48
+ // needs_reboot: false,
49
+ // resolution_risk: 1,
50
+ // },
51
+ // ],
52
+ // rebootable: false,
53
+ // description: 'Decreased security: auditd not running',
54
+ // },
55
+ // ]);
56
+
57
+ /* eslint-enable spellcheck/spell-checker */
18
58
 
19
59
  const RemediationModal = ({
60
+ iopData,
20
61
  selectedIds,
21
62
  fetchRemediations,
22
63
  remediations,
@@ -24,31 +65,49 @@ const RemediationModal = ({
24
65
  error,
25
66
  isAllSelected,
26
67
  query,
68
+ isDisabled,
27
69
  }) => {
28
- const [rows, setRows] = React.useState([]);
70
+ const iopRows = Immutable(iopData ?? []).map(recommendation => ({
71
+ id: recommendation.rulename,
72
+ host_id: recommendation.hostid,
73
+ hostname: recommendation.host_name,
74
+ title: recommendation.description,
75
+ resolutions: recommendation.resolutions ?? [],
76
+ reboot: recommendation.rebootable,
77
+ }));
78
+
29
79
  const [open, setOpen] = React.useState(false);
30
80
  const [resolutions, setResolutions] = React.useState([]);
31
81
  const [hostsIds, setHostsIds] = React.useState([]);
82
+ const [rows, setRows] = React.useState([]);
32
83
  const toggleModal = () => setOpen(prevValue => !prevValue);
33
84
 
85
+ const isIop = useAdvisorEngineConfig();
34
86
  useEffect(() => {
35
- if (open) fetchRemediations({ selectedIds, isAllSelected, query });
87
+ // only fetch for Hosted. IoP provides via props.
88
+ if (!isIop && open)
89
+ fetchRemediations({ selectedIds, isAllSelected, query });
36
90
  }, [open]);
37
91
 
38
92
  useEffect(() => {
39
- const modifiedRows =
40
- status === STATUS.PENDING
41
- ? []
42
- : modifyRows(remediations, setResolutions, setHostsIds);
93
+ let modifiedRows;
94
+ if (isIop) {
95
+ modifiedRows = modifyRows(iopRows, setResolutions, setHostsIds, true);
96
+ } else {
97
+ modifiedRows =
98
+ status === STATUS.PENDING
99
+ ? []
100
+ : modifyRows(remediations, setResolutions, setHostsIds, false);
101
+ }
43
102
  setRows(modifiedRows);
44
- }, [remediations, status]);
103
+ }, [remediations, status, iopData, isIop]);
45
104
 
46
105
  return (
47
106
  <React.Fragment>
48
107
  <Button
49
108
  ouiaId="button-remediate"
50
109
  variant="primary"
51
- isDisabled={isEmpty(selectedIds)}
110
+ isDisabled={isDisabled || isEmpty(selectedIds)}
52
111
  onClick={() => {
53
112
  toggleModal();
54
113
  }}
@@ -68,6 +127,7 @@ const RemediationModal = ({
68
127
  toggleModal={toggleModal}
69
128
  resolutions={resolutions}
70
129
  hostsIds={hostsIds}
130
+ isIop={isIop}
71
131
  />
72
132
  }
73
133
  >
@@ -92,22 +152,36 @@ const RemediationModal = ({
92
152
  };
93
153
 
94
154
  RemediationModal.propTypes = {
95
- selectedIds: PropTypes.object,
96
- fetchRemediations: PropTypes.func.isRequired,
155
+ iopData: PropTypes.arrayOf(
156
+ PropTypes.shape({
157
+ hostid: PropTypes.string,
158
+ host_name: PropTypes.string,
159
+ rulename: PropTypes.string,
160
+ resolutions: PropTypes.array,
161
+ rebootable: PropTypes.bool,
162
+ description: PropTypes.string,
163
+ })
164
+ ),
165
+ selectedIds: PropTypes.shape({}),
166
+ fetchRemediations: PropTypes.func,
97
167
  remediations: PropTypes.array,
98
168
  status: PropTypes.string,
99
169
  error: PropTypes.string,
100
170
  isAllSelected: PropTypes.bool,
101
171
  query: PropTypes.string,
172
+ isDisabled: PropTypes.bool,
102
173
  };
103
174
 
104
175
  RemediationModal.defaultProps = {
176
+ iopData: null,
105
177
  selectedIds: {},
178
+ fetchRemediations: noop,
106
179
  remediations: [],
107
180
  status: null,
108
181
  error: null,
109
182
  isAllSelected: false,
110
183
  query: null,
184
+ isDisabled: false,
111
185
  };
112
186
 
113
187
  export default RemediationModal;
@@ -2,18 +2,44 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Button } from '@patternfly/react-core';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
+ import { useBulkSelect } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
5
6
  import { JOB_INVOCATION_PATH } from './RemediationTableConstants';
6
7
 
7
- const ModalFooter = ({ toggleModal, resolutions, hostsIds }) => {
8
+ const ModalFooter = ({ toggleModal, resolutions, hostsIds, isIop }) => {
8
9
  let token = document.querySelector('meta[name="csrf-token"]');
9
10
  token = token?.content || '';
11
+
12
+ const [jobInProgress, setJobInProgress] = React.useState(false);
13
+ const formRef = React.useRef(null);
14
+
15
+ const { fetchBulkParams } = useBulkSelect({
16
+ initialArry: hostsIds,
17
+ idColumn: 'insights_uuid',
18
+ });
19
+
20
+ const handleSubmit = e => {
21
+ e.preventDefault();
22
+ setJobInProgress(true);
23
+
24
+ setTimeout(() => {
25
+ // eslint-disable-next-line no-unused-expressions
26
+ formRef.current?.submit?.();
27
+ }, 100);
28
+ };
10
29
  return (
11
- <form action={JOB_INVOCATION_PATH} method="post">
30
+ <form
31
+ action={JOB_INVOCATION_PATH}
32
+ method="post"
33
+ ref={formRef}
34
+ onSubmit={handleSubmit}
35
+ >
12
36
  <Button
13
37
  type="submit"
14
38
  ouiaId="button-confirm"
15
39
  key="confirm"
16
40
  variant="primary"
41
+ isDisabled={jobInProgress}
42
+ isLoading={jobInProgress}
17
43
  >
18
44
  {__('Remediate')}
19
45
  </Button>
@@ -32,9 +58,15 @@ const ModalFooter = ({ toggleModal, resolutions, hostsIds }) => {
32
58
  name="inputs[hit_remediation_pairs]"
33
59
  value={JSON.stringify(resolutions)}
34
60
  />
35
- {hostsIds.map(id => (
36
- <input type="hidden" name="host_ids[]" key={id} value={id} />
37
- ))}
61
+ {!isIop &&
62
+ hostsIds.map(id => (
63
+ <input type="hidden" name="host_ids[]" key={id} value={id} />
64
+ ))}
65
+ {isIop && (
66
+ <>
67
+ <input type="hidden" name="search" value={fetchBulkParams()} />
68
+ </>
69
+ )}
38
70
  </form>
39
71
  );
40
72
  };
@@ -43,11 +75,13 @@ ModalFooter.propTypes = {
43
75
  toggleModal: PropTypes.func.isRequired,
44
76
  resolutions: PropTypes.array,
45
77
  hostsIds: PropTypes.array,
78
+ isIop: PropTypes.bool,
46
79
  };
47
80
 
48
81
  ModalFooter.defaultProps = {
49
82
  resolutions: [],
50
83
  hostsIds: [],
84
+ isIop: false,
51
85
  };
52
86
 
53
87
  export default ModalFooter;
@@ -2,12 +2,14 @@
2
2
  import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Radio } from '@patternfly/react-core';
5
+ import { getResolutionId } from './RemediationHelpers';
5
6
 
6
7
  const Resolutions = ({
7
8
  resolutions,
8
9
  setResolutions,
9
10
  selectedResolution,
10
11
  hit_id,
12
+ isIop,
11
13
  }) => {
12
14
  const [checkedID, setCheckedID] = React.useState(selectedResolution);
13
15
 
@@ -27,6 +29,15 @@ const Resolutions = ({
27
29
  stateRes.map(res => {
28
30
  if (hit_id === res.hit_id) {
29
31
  setCheckedID(resolution_id);
32
+ if (isIop)
33
+ return {
34
+ ...res,
35
+ resolution_id: getResolutionId(
36
+ resolution_id,
37
+ res.rule_id
38
+ ),
39
+ resolution_type: resolution_id,
40
+ };
30
41
  return { ...res, resolution_id };
31
42
  }
32
43
  return res;
@@ -45,12 +56,14 @@ Resolutions.propTypes = {
45
56
  resolutions: PropTypes.array,
46
57
  hit_id: PropTypes.number,
47
58
  selectedResolution: PropTypes.number,
59
+ isIop: PropTypes.bool,
48
60
  };
49
61
 
50
62
  Resolutions.defaultProps = {
51
63
  resolutions: [],
52
64
  hit_id: null,
53
65
  selectedResolution: null,
66
+ isIop: false,
54
67
  };
55
68
 
56
69
  export default Resolutions;
@@ -67,13 +67,15 @@ export const generateRuleUrl = ruleId =>
67
67
  foremanUrl(`/foreman_rh_cloud/recommendations/${ruleId}`);
68
68
 
69
69
  const IopRecommendationsPage = props => (
70
- <ScalprumComponent
71
- scope={scope}
72
- module={module}
73
- IopRemediationModal={RemediationModal}
74
- generateRuleUrl={generateRuleUrl}
75
- {...props}
76
- />
70
+ <div className="advisor">
71
+ <ScalprumComponent
72
+ scope={scope}
73
+ module={module}
74
+ IopRemediationModal={RemediationModal}
75
+ generateRuleUrl={generateRuleUrl}
76
+ {...props}
77
+ />
78
+ </div>
77
79
  );
78
80
 
79
81
  const IopRecommendationsPageWrapped = props => (
@@ -110,16 +110,18 @@ NewHostDetailsTab.defaultProps = {
110
110
 
111
111
  // Local Insights advisor
112
112
  const scope = 'advisor';
113
- const module = './SystemDetailsWrapped';
113
+ const module = './SystemDetailWrapped';
114
114
 
115
115
  const IopInsightsTab = props => (
116
- <ScalprumComponent
117
- scope={scope}
118
- module={module}
119
- IopRemediationModal={RemediationModal}
120
- generateRuleUrl={generateRuleUrl}
121
- {...props}
122
- />
116
+ <div className="advisor">
117
+ <ScalprumComponent
118
+ scope={scope}
119
+ module={module}
120
+ IopRemediationModal={RemediationModal}
121
+ generateRuleUrl={generateRuleUrl}
122
+ {...props}
123
+ />
124
+ </div>
123
125
  );
124
126
 
125
127
  const IopInsightsTabWrapped = props => (
@@ -132,7 +134,7 @@ const InsightsTab = props => {
132
134
  const { response } = props;
133
135
  const isLocalAdvisorEngine =
134
136
  // eslint-disable-next-line camelcase
135
- response?.insights_attributes?.use_local_advisor_engine;
137
+ response?.insights_attributes?.use_iop_mode;
136
138
 
137
139
  return isLocalAdvisorEngine ? (
138
140
  <IopInsightsTabWrapped {...props} />
@@ -144,7 +146,7 @@ const InsightsTab = props => {
144
146
  InsightsTab.propTypes = {
145
147
  response: PropTypes.shape({
146
148
  insights_attributes: {
147
- use_local_advisor_engine: PropTypes.bool,
149
+ use_iop_mode: PropTypes.bool,
148
150
  },
149
151
  }),
150
152
  };
@@ -6,7 +6,7 @@ const InsightsVulnerabilityListPage = () => {
6
6
  const scope = 'vulnerability';
7
7
  const module = './CveListPage';
8
8
  return (
9
- <div className="rh-cloud-insights-vulnerability-page">
9
+ <div className="rh-cloud-insights-vulnerability-page vulnerability">
10
10
  <ScalprumComponent scope={scope} module={module} />
11
11
  </div>
12
12
  );
@@ -13,7 +13,7 @@ const IopRecommendationDetails = props => {
13
13
  // eslint-disable-next-line camelcase
14
14
  const ruleId = urlParams?.params?.rule_id;
15
15
  return (
16
- <div className="iop-recommendation-details-scalprum">
16
+ <div className="iop-recommendation-details-scalprum advisor">
17
17
  <ScalprumComponent
18
18
  scope={scope}
19
19
  module={module}
@@ -14,6 +14,5 @@ export const useAdvisorEngineConfig = () => {
14
14
  );
15
15
 
16
16
  // eslint-disable-next-line camelcase
17
- const isLocalAdvisorEngine = advisorEngineConfig?.use_local_advisor_engine;
18
- return isLocalAdvisorEngine;
17
+ return advisorEngineConfig?.use_iop_mode;
19
18
  };
@@ -0,0 +1,7 @@
1
+ // overwrite bootstrap style which added unintended bottom margins to chips
2
+ // and dropdowns in Advisor and Vulnerability
3
+ .vulnerability, .advisor {
4
+ ul, ol {
5
+ margin-bottom: 0px;
6
+ }
7
+ }
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.2.1
4
+ version: 12.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
@@ -98,6 +98,7 @@ files:
98
98
  - app/controllers/api/v2/rh_cloud/advisor_engine_config_controller.rb
99
99
  - app/controllers/api/v2/rh_cloud/cloud_request_controller.rb
100
100
  - app/controllers/api/v2/rh_cloud/inventory_controller.rb
101
+ - app/controllers/concerns/foreman_rh_cloud/iop_smart_proxy_access.rb
101
102
  - app/controllers/concerns/insights_cloud/candlepin_cache.rb
102
103
  - app/controllers/concerns/insights_cloud/client_authentication.rb
103
104
  - app/controllers/concerns/insights_cloud/package_profile_upload_extensions.rb
@@ -110,6 +111,7 @@ files:
110
111
  - app/controllers/foreman_inventory_upload/tasks_controller.rb
111
112
  - app/controllers/foreman_inventory_upload/uploads_controller.rb
112
113
  - app/controllers/foreman_inventory_upload/uploads_settings_controller.rb
114
+ - app/controllers/foreman_rh_cloud/foreman_rh_cloud_controller.rb
113
115
  - app/controllers/insights_cloud/api/machine_telemetries_controller.rb
114
116
  - app/controllers/insights_cloud/hits_controller.rb
115
117
  - app/controllers/insights_cloud/settings_controller.rb
@@ -119,6 +121,7 @@ files:
119
121
  - app/helpers/foreman_inventory_upload_helper.rb
120
122
  - app/helpers/foreman_inventory_upload_host_helper.rb
121
123
  - app/models/concerns/rh_cloud_host.rb
124
+ - app/models/foreman_rh_cloud/ping.rb
122
125
  - app/models/insights_client_report_status.rb
123
126
  - app/models/insights_facet.rb
124
127
  - app/models/insights_hit.rb
@@ -662,6 +665,7 @@ files:
662
665
  - webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap
663
666
  - webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap
664
667
  - webpack/common/Switcher/index.js
668
+ - webpack/common/styles.scss
665
669
  - webpack/common/table/EmptyState.js
666
670
  - webpack/common/table/helpers.js
667
671
  - webpack/global_index.js