foreman_leapp 0.0.5 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -20
  3. data/app/controllers/api/v2/concerns/api_authorizer.rb +27 -0
  4. data/app/controllers/api/v2/preupgrade_reports_controller.rb +21 -2
  5. data/app/controllers/preupgrade_reports_controller.rb +11 -1
  6. data/app/lib/actions/preupgrade_job.rb +2 -1
  7. data/app/lib/helpers/job_helper.rb +3 -4
  8. data/app/models/preupgrade_report.rb +1 -0
  9. data/app/models/preupgrade_report_entry.rb +1 -0
  10. data/app/views/api/v2/preupgrade_report_entries/base.json.rabl +1 -1
  11. data/app/views/api/v2/preupgrade_reports/job_invocation.json.rabl +3 -0
  12. data/app/views/foreman_leapp/job_templates/leapp_check.erb +15 -0
  13. data/app/views/foreman_leapp/job_templates/{preupgrade.erb → leapp_preupgrade.erb} +5 -2
  14. data/app/views/foreman_leapp/job_templates/leapp_remediation.erb +29 -0
  15. data/app/views/foreman_leapp/job_templates/leapp_upgrade.erb +26 -0
  16. data/app/views/job_invocations/_leapp_preupgrade_report.html.erb +2 -1
  17. data/config/routes.rb +2 -1
  18. data/db/migrate/20200429080939_report_entries_flags.rb +5 -0
  19. data/db/seeds.d/10_leapp_preupgrade.rb +1 -1
  20. data/lib/foreman_leapp/engine.rb +7 -6
  21. data/lib/foreman_leapp/version.rb +1 -1
  22. data/package.json +3 -2
  23. data/test/functional/api/v2/preupgrade_reports_controller_test.rb +89 -6
  24. data/test/functional/preupgrade_reports_controller_test.rb +27 -4
  25. data/test/unit/actions/preupgrade_job_test.rb +1 -1
  26. data/test/unit/helpers/job_helper_test.rb +3 -10
  27. data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +4 -0
  28. data/webpack/__mocks__/foremanReact/common/I18n.js +1 -1
  29. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
  30. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +1 -0
  31. data/webpack/components/PreupgradeReports/PreupgradeReports.js +119 -8
  32. data/webpack/components/PreupgradeReports/PreupgradeReportsActions.js +1 -1
  33. data/webpack/components/PreupgradeReports/PreupgradeReportsHelpers.js +152 -0
  34. data/webpack/components/PreupgradeReports/PreupgradeReportsReducer.js +2 -0
  35. data/webpack/components/PreupgradeReports/PreupgradeReportsSelectors.js +11 -0
  36. data/webpack/components/PreupgradeReports/__tests__/PreupgradeReports.fixtures.js +72 -2
  37. data/webpack/components/PreupgradeReports/__tests__/PreupgradeReports.test.js +26 -1
  38. data/webpack/components/PreupgradeReports/__tests__/PreupgradeReportsHelpers.test.js +78 -0
  39. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReports.test.js.snap +60 -5
  40. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReportsHelpers.test.js.snap +489 -0
  41. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReportsReducer.test.js.snap +40 -1
  42. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReportsSelectors.test.js.snap +36 -1
  43. data/webpack/components/PreupgradeReports/components/EntriesFilter.js +121 -0
  44. data/webpack/components/PreupgradeReports/components/EntriesFilter.scss +3 -0
  45. data/webpack/components/PreupgradeReports/components/EntriesFilter.test.js +30 -0
  46. data/webpack/components/PreupgradeReports/components/FixSelectedButton.js +35 -0
  47. data/webpack/components/PreupgradeReports/components/FixSelectedButton.test.js +15 -0
  48. data/webpack/components/PreupgradeReports/components/NoReports.js +35 -0
  49. data/webpack/components/PreupgradeReports/components/NoReports.test.js +15 -0
  50. data/webpack/components/PreupgradeReports/components/UpgradeAllButton.js +29 -0
  51. data/webpack/components/PreupgradeReports/components/UpgradeAllButton.test.js +17 -0
  52. data/webpack/components/PreupgradeReports/components/__snapshots__/EntriesFilter.test.js.snap +330 -0
  53. data/webpack/components/PreupgradeReports/components/__snapshots__/FixSelectedButton.test.js.snap +40 -0
  54. data/webpack/components/PreupgradeReports/components/__snapshots__/NoReports.test.js.snap +19 -0
  55. data/webpack/components/PreupgradeReports/components/__snapshots__/UpgradeAllButton.test.js.snap +29 -0
  56. data/webpack/components/PreupgradeReports/index.js +28 -5
  57. data/webpack/components/PreupgradeReportsList/PreupgradeReportList.scss +37 -0
  58. data/webpack/components/PreupgradeReportsList/__tests__/PreupgradeReportsList.test.js +28 -2
  59. data/webpack/components/PreupgradeReportsList/__tests__/__snapshots__/PreupgradeReportsList.test.js.snap +119 -0
  60. data/webpack/components/PreupgradeReportsList/components/InfoItem.js +1 -1
  61. data/webpack/components/PreupgradeReportsList/components/InhibitorInfoItem.js +33 -0
  62. data/webpack/components/PreupgradeReportsList/components/PreupgradeReportEntry.js +50 -6
  63. data/webpack/components/PreupgradeReportsList/components/PreupgradeReportsListHeader.js +56 -0
  64. data/webpack/components/PreupgradeReportsList/components/SortableHeaderItem.js +50 -0
  65. data/webpack/components/PreupgradeReportsList/components/__tests__/InhibitorInfoItem.test.js +27 -0
  66. data/webpack/components/PreupgradeReportsList/components/__tests__/PreupgradeReportEntry.fixtures.js +38 -0
  67. data/webpack/components/PreupgradeReportsList/components/__tests__/PreupgradeReportEntry.test.js +2 -0
  68. data/webpack/components/PreupgradeReportsList/components/__tests__/PreupgradeReportsListHeader.test.js +14 -0
  69. data/webpack/components/PreupgradeReportsList/components/__tests__/SortableHeaderItem.test.js +29 -0
  70. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/InhibitorInfoItem.test.js.snap +32 -0
  71. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/PreupgradeReportEntry.test.js.snap +95 -14
  72. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/PreupgradeReportsListHeader.test.js.snap +113 -0
  73. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/SortableHeaderItem.test.js.snap +36 -0
  74. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/helpers.test.js.snap +191 -29
  75. data/webpack/components/PreupgradeReportsList/components/__tests__/helpers.test.js +19 -8
  76. data/webpack/components/PreupgradeReportsList/components/foreman_leapp.scss +15 -0
  77. data/webpack/components/PreupgradeReportsList/components/helpers.js +177 -21
  78. data/webpack/components/PreupgradeReportsList/components/images/i_severity-critical.svg +61 -0
  79. data/webpack/components/PreupgradeReportsList/components/images/i_severity-high.svg +61 -0
  80. data/webpack/components/PreupgradeReportsList/components/images/i_severity-low.svg +62 -0
  81. data/webpack/components/PreupgradeReportsList/components/images/i_severity-med.svg +62 -0
  82. data/webpack/components/PreupgradeReportsList/index.js +48 -10
  83. data/webpack/csrf.js +4 -0
  84. metadata +61 -10
  85. data/app/views/foreman_leapp/job_templates/remediation.erb +0 -17
  86. data/app/views/foreman_leapp/job_templates/upgrade.erb +0 -16
  87. data/webpack/components/PreupgradeReportsList/components/StringInfoItem.js +0 -49
  88. data/webpack/components/PreupgradeReportsList/components/__tests__/StringInfoItem.test.js +0 -13
  89. data/webpack/components/PreupgradeReportsList/components/__tests__/__snapshots__/StringInfoItem.test.js.snap +0 -12
@@ -0,0 +1,37 @@
1
+ @import '~@theforeman/vendor/scss/variables';
2
+
3
+ #preupgrade-report-entries-list-view {
4
+ .sortable-header {
5
+ &.active {
6
+ color: $color-pf-blue-400;
7
+ }
8
+
9
+ &:hover {
10
+ cursor: pointer;
11
+ }
12
+
13
+ .fa-angle-up, .fa-angle-down {
14
+ margin-right: 10px;
15
+ }
16
+ }
17
+
18
+ .list-view-pf-additional-info-item {
19
+ flex: 1;
20
+ }
21
+
22
+ .list-view-header {
23
+ border-top: 0px;
24
+ background-color: $color-pf-white;
25
+ border-left-color: $color-pf-white;
26
+ border-right-color: $color-pf-white;
27
+
28
+ .list-view-pf-description {
29
+ font-size: 16px;
30
+ font-weight: 600;
31
+ }
32
+
33
+ .list-view-pf-checkbox {
34
+ margin-left: 17px;
35
+ }
36
+ }
37
+ }
@@ -2,11 +2,37 @@ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
 
3
3
  import PreupgradeReportsList from '../index';
4
4
 
5
- import { preupgradeReports } from '../../PreupgradeReports/__tests__/PreupgradeReports.fixtures';
5
+ const allEntries = [
6
+ { title: 'Fix me!', severity: 'Too severe to talk about' },
7
+ { title: 'I am broken too', severity: 'medium' },
8
+ { title: 'Octocat is not happy', severity: 'high' },
9
+ { title: 'Not enough credits', severity: 'low' },
10
+ ];
11
+
12
+ const isSelected = () => false;
13
+ const toggleSelected = () => {};
14
+ const sort = { attribute: '', order: 'asc' };
15
+ const changeSort = () => {};
16
+ const toggleSelectAll = () => {};
6
17
 
7
18
  const fixtures = {
8
19
  'should render': {
9
- preupgradeReports,
20
+ allEntries,
21
+ fixAllWorking: false,
22
+ isSelected,
23
+ toggleSelected,
24
+ sort,
25
+ changeSort,
26
+ toggleSelectAll,
27
+ },
28
+ 'should render when working': {
29
+ allEntries,
30
+ fixAllWorking: true,
31
+ isSelected,
32
+ toggleSelected,
33
+ sort,
34
+ changeSort,
35
+ toggleSelectAll,
10
36
  },
11
37
  };
12
38
 
@@ -3,7 +3,99 @@
3
3
  exports[`PreupgradeReportsList should render 1`] = `
4
4
  <ListView
5
5
  className=""
6
+ id="preupgrade-report-entries-list-view"
6
7
  >
8
+ <PreupgradeReportsListHeader
9
+ changeSort={[Function]}
10
+ sort={
11
+ Object {
12
+ "attribute": "",
13
+ "order": "asc",
14
+ }
15
+ }
16
+ toggleSelectAll={[Function]}
17
+ />
18
+ <PreupgradeReportEntry
19
+ entry={
20
+ Object {
21
+ "severity": "Too severe to talk about",
22
+ "title": "Fix me!",
23
+ }
24
+ }
25
+ isEntrySelected={false}
26
+ key="0"
27
+ toggleSelected={[Function]}
28
+ />
29
+ <PreupgradeReportEntry
30
+ entry={
31
+ Object {
32
+ "severity": "medium",
33
+ "title": "I am broken too",
34
+ }
35
+ }
36
+ isEntrySelected={false}
37
+ key="1"
38
+ toggleSelected={[Function]}
39
+ />
40
+ <PreupgradeReportEntry
41
+ entry={
42
+ Object {
43
+ "severity": "high",
44
+ "title": "Octocat is not happy",
45
+ }
46
+ }
47
+ isEntrySelected={false}
48
+ key="2"
49
+ toggleSelected={[Function]}
50
+ />
51
+ <PreupgradeReportEntry
52
+ entry={
53
+ Object {
54
+ "severity": "low",
55
+ "title": "Not enough credits",
56
+ }
57
+ }
58
+ isEntrySelected={false}
59
+ key="3"
60
+ toggleSelected={[Function]}
61
+ />
62
+ <PaginationWrapper
63
+ dropdownButtonId="preupgrade-report-entries-pagination-dropdown"
64
+ itemCount={4}
65
+ onChange={[Function]}
66
+ pagination={
67
+ Object {
68
+ "page": 1,
69
+ "perPage": 20,
70
+ "perPageOptions": Array [
71
+ 5,
72
+ 10,
73
+ 20,
74
+ 30,
75
+ 50,
76
+ ],
77
+ }
78
+ }
79
+ viewType="list"
80
+ />
81
+ </ListView>
82
+ `;
83
+
84
+ exports[`PreupgradeReportsList should render when working 1`] = `
85
+ <ListView
86
+ className=""
87
+ id="preupgrade-report-entries-list-view"
88
+ >
89
+ <PreupgradeReportsListHeader
90
+ changeSort={[Function]}
91
+ sort={
92
+ Object {
93
+ "attribute": "",
94
+ "order": "asc",
95
+ }
96
+ }
97
+ toggleSelectAll={[Function]}
98
+ />
7
99
  <PreupgradeReportEntry
8
100
  entry={
9
101
  Object {
@@ -11,7 +103,9 @@ exports[`PreupgradeReportsList should render 1`] = `
11
103
  "title": "Fix me!",
12
104
  }
13
105
  }
106
+ isEntrySelected={false}
14
107
  key="0"
108
+ toggleSelected={[Function]}
15
109
  />
16
110
  <PreupgradeReportEntry
17
111
  entry={
@@ -20,7 +114,9 @@ exports[`PreupgradeReportsList should render 1`] = `
20
114
  "title": "I am broken too",
21
115
  }
22
116
  }
117
+ isEntrySelected={false}
23
118
  key="1"
119
+ toggleSelected={[Function]}
24
120
  />
25
121
  <PreupgradeReportEntry
26
122
  entry={
@@ -29,7 +125,9 @@ exports[`PreupgradeReportsList should render 1`] = `
29
125
  "title": "Octocat is not happy",
30
126
  }
31
127
  }
128
+ isEntrySelected={false}
32
129
  key="2"
130
+ toggleSelected={[Function]}
33
131
  />
34
132
  <PreupgradeReportEntry
35
133
  entry={
@@ -38,7 +136,28 @@ exports[`PreupgradeReportsList should render 1`] = `
38
136
  "title": "Not enough credits",
39
137
  }
40
138
  }
139
+ isEntrySelected={false}
41
140
  key="3"
141
+ toggleSelected={[Function]}
142
+ />
143
+ <PaginationWrapper
144
+ dropdownButtonId="preupgrade-report-entries-pagination-dropdown"
145
+ itemCount={4}
146
+ onChange={[Function]}
147
+ pagination={
148
+ Object {
149
+ "page": 1,
150
+ "perPage": 20,
151
+ "perPageOptions": Array [
152
+ 5,
153
+ 10,
154
+ 20,
155
+ 30,
156
+ 50,
157
+ ],
158
+ }
159
+ }
160
+ viewType="list"
42
161
  />
43
162
  </ListView>
44
163
  `;
@@ -14,7 +14,7 @@ const InfoItem = ({ itemId, children, tooltipText }) => {
14
14
  </OverlayTrigger>
15
15
  );
16
16
  return (
17
- <ListView.InfoItem key={itemId} className="additional-info-wide">
17
+ <ListView.InfoItem key={itemId}>
18
18
  {tooltipText ? overlay : children}
19
19
  </ListView.InfoItem>
20
20
  );
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Icon } from 'patternfly-react';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+
6
+ import { isInhibitor } from '../../PreupgradeReports/PreupgradeReportsHelpers';
7
+ import InfoItem from './InfoItem';
8
+ import EmptyInfoItem from './EmptyInfoItem';
9
+
10
+ const InhibitorInfoItem = ({ entry }) => {
11
+ const key = `inhibitor-${entry.id}`;
12
+
13
+ if (isInhibitor(entry)) {
14
+ return (
15
+ <InfoItem
16
+ itemId={key}
17
+ tooltipText={__('This issue inhibits the upgrade.')}
18
+ >
19
+ <span>
20
+ <Icon type="pf" name="security" className="severity-high" />
21
+ {__('Inhibitor')}
22
+ </span>
23
+ </InfoItem>
24
+ );
25
+ }
26
+ return <EmptyInfoItem entry={entry} attr="inhibitor" />;
27
+ };
28
+
29
+ InhibitorInfoItem.propTypes = {
30
+ entry: PropTypes.object.isRequired,
31
+ };
32
+
33
+ export default InhibitorInfoItem;
@@ -1,20 +1,64 @@
1
1
  import React from 'react';
2
- import { ListView } from 'patternfly-react';
2
+ import { ListView, Grid, Icon } from 'patternfly-react';
3
3
  import PropTypes from 'prop-types';
4
+ import './foreman_leapp.scss';
4
5
 
5
- import { additionalInfo } from './helpers';
6
+ import InhibitorInfoItem from './InhibitorInfoItem';
6
7
 
7
- const PreupgradeReportEntry = ({ entry }) => (
8
+ import {
9
+ itemIteratorId,
10
+ hasRemediations,
11
+ getExternals,
12
+ getRemediations,
13
+ getTitle,
14
+ getSeverity,
15
+ getSummary,
16
+ getTags,
17
+ getSeverityImg,
18
+ } from './helpers';
19
+
20
+ import { entryFixable } from '../../PreupgradeReports/PreupgradeReportsHelpers';
21
+
22
+ const PreupgradeReportEntry = ({ entry, isEntrySelected, toggleSelected }) => (
8
23
  <ListView.Item
9
24
  key={entry.id}
10
- className="listViewItem--listItemVariants"
11
25
  stacked
12
- additionalInfo={additionalInfo(entry)}
13
- />
26
+ checkboxInput={
27
+ <input
28
+ type="checkbox"
29
+ value={isEntrySelected}
30
+ checked={isEntrySelected}
31
+ disabled={!entryFixable(entry)}
32
+ onChange={() => toggleSelected(entry, isEntrySelected)}
33
+ />
34
+ }
35
+ description={entry.title}
36
+ additionalInfo={[
37
+ <ListView.InfoItem key={itemIteratorId(entry, entry.hostname)}>
38
+ <Icon type="pf" name="cluster" /> {entry.hostname}
39
+ </ListView.InfoItem>,
40
+ <ListView.InfoItem key={itemIteratorId(entry, entry.severity)}>
41
+ {getSeverityImg(entry)}
42
+ </ListView.InfoItem>,
43
+ hasRemediations(entry),
44
+ <InhibitorInfoItem key={itemIteratorId(entry, 'flags')} entry={entry} />,
45
+ ]}
46
+ >
47
+ <Grid fluid>
48
+ {getTitle(entry)}
49
+ {getSeverity(entry)}
50
+ {getSummary(entry)}
51
+ {getTags(entry)}
52
+ {getExternals(entry)}
53
+ {getRemediations(entry)}
54
+ </Grid>
55
+ </ListView.Item>
14
56
  );
15
57
 
16
58
  PreupgradeReportEntry.propTypes = {
17
59
  entry: PropTypes.object.isRequired,
60
+ isEntrySelected: PropTypes.bool.isRequired,
61
+ toggleSelected: PropTypes.func.isRequired,
18
62
  };
19
63
 
20
64
  export default PreupgradeReportEntry;
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { ListView } from 'patternfly-react';
3
+ import PropTypes from 'prop-types';
4
+
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+
7
+ import InfoItem from './InfoItem';
8
+ import SortableHeaderItem from './SortableHeaderItem';
9
+
10
+ const PreupgradeReportsListHeader = ({ sort, changeSort, toggleSelectAll }) => {
11
+ const additionalInfoColumns = [
12
+ { label: __('Host'), value: 'hostname' },
13
+ { label: __('Risk Factor'), value: 'severity' },
14
+ { label: __('Has Remediation?'), value: 'fix' },
15
+ { label: __('Inhibitor?'), value: 'inhibitor' },
16
+ ];
17
+
18
+ const additionalInfo = additionalInfoColumns.map((col, idx) => (
19
+ <InfoItem itemId={idx.toString()} key={idx}>
20
+ <strong>
21
+ <SortableHeaderItem
22
+ title={col.label}
23
+ sort={sort}
24
+ value={col.value}
25
+ changeSort={changeSort}
26
+ />
27
+ </strong>
28
+ </InfoItem>
29
+ ));
30
+
31
+ return (
32
+ <ListView.Item
33
+ additionalInfo={additionalInfo}
34
+ className="list-view-header"
35
+ checkboxInput={<input type="checkbox" onClick={toggleSelectAll} />}
36
+ description={
37
+ <SortableHeaderItem
38
+ title={__('Title')}
39
+ sort={sort}
40
+ value="title"
41
+ changeSort={changeSort}
42
+ />
43
+ }
44
+ hideCloseIcon
45
+ stacked
46
+ />
47
+ );
48
+ };
49
+
50
+ PreupgradeReportsListHeader.propTypes = {
51
+ sort: PropTypes.object.isRequired,
52
+ changeSort: PropTypes.func.isRequired,
53
+ toggleSelectAll: PropTypes.func.isRequired,
54
+ };
55
+
56
+ export default PreupgradeReportsListHeader;
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import { Icon } from 'patternfly-react';
3
+ import classNames from 'classnames';
4
+ import PropTypes from 'prop-types';
5
+
6
+ const SortableHeaderItem = ({ value, title, sort, changeSort }) => {
7
+ const chooseChevron = (active, order) => {
8
+ if (!active) {
9
+ return null;
10
+ }
11
+
12
+ const direction = order === 'asc' ? 'angle-up' : 'angle-down';
13
+
14
+ return <Icon type="fa" name={direction} />;
15
+ };
16
+
17
+ const active = sort.attribute === value;
18
+
19
+ const clickHandler = () => {
20
+ let direction = 'asc';
21
+
22
+ if (active) {
23
+ direction = sort.order === 'asc' ? 'desc' : 'asc';
24
+ }
25
+
26
+ changeSort({
27
+ attribute: value,
28
+ order: direction,
29
+ });
30
+ };
31
+
32
+ return (
33
+ <span
34
+ className={`sortable-header ${classNames({ active })}`}
35
+ onClick={clickHandler}
36
+ >
37
+ {chooseChevron(active, sort.order)}
38
+ {title}
39
+ </span>
40
+ );
41
+ };
42
+
43
+ SortableHeaderItem.propTypes = {
44
+ sort: PropTypes.object.isRequired,
45
+ changeSort: PropTypes.func.isRequired,
46
+ value: PropTypes.string.isRequired,
47
+ title: PropTypes.string.isRequired,
48
+ };
49
+
50
+ export default SortableHeaderItem;