foreman_ansible 7.0.4 → 7.1.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/ansible_playbooks_controller.rb +66 -0
  3. data/app/jobs/sync_playbooks.rb +25 -0
  4. data/app/lib/proxy_api/ansible.rb +13 -0
  5. data/app/services/foreman_ansible/import_playbooks_error_notification.rb +38 -0
  6. data/app/services/foreman_ansible/import_playbooks_success_notification.rb +33 -0
  7. data/app/services/foreman_ansible/playbooks_importer.rb +73 -0
  8. data/app/services/foreman_ansible/proxy_api.rb +3 -4
  9. data/app/views/ansible_roles/index.html.erb +2 -0
  10. data/app/views/api/v2/ansible_playbooks/sync.json.rabl +5 -0
  11. data/app/views/foreman_ansible/job_templates/ansible_windows_updates.erb +160 -0
  12. data/app/views/foreman_ansible/job_templates/configure_cloud_connector_-_ansible_default.erb +37 -0
  13. data/config/routes.rb +7 -0
  14. data/db/seeds.d/90_notification_blueprints.rb +14 -0
  15. data/lib/foreman_ansible/register.rb +3 -1
  16. data/lib/foreman_ansible/remote_execution.rb +6 -0
  17. data/lib/foreman_ansible/version.rb +1 -1
  18. data/test/fixtures/playbooks_example_output.json +1 -0
  19. data/test/fixtures/sample_playbooks.json +10 -0
  20. data/test/functional/api/v2/ansible_playbooks_controller_test.rb +65 -0
  21. data/test/functional/hosts_controller_test.rb +2 -2
  22. data/test/unit/import_playbooks_test.rb +51 -0
  23. data/test/unit/lib/proxy_api/ansible_test.rb +6 -0
  24. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +58 -75
  25. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +44 -58
  26. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +32 -55
  27. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -1
  28. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +29 -42
  29. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js +27 -38
  30. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js +2 -1
  31. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesConstants.js +1 -0
  32. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesSelectors.js +6 -0
  33. data/webpack/components/AnsibleRolesAndVariables/index.js +7 -1
  34. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -2
  35. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -6
  36. data/webpack/helpers/pageParamsHelper.js +3 -3
  37. metadata +46 -31
  38. data/webpack/components/withPagination.js +0 -0
  39. data/webpack/helpers/paginationHelper.js +0 -9
@@ -20,7 +20,7 @@ class HostsControllerExtensionsTest < ActionController::TestCase
20
20
  0 => { :ansible_role_id => @role.id, :position => 0 }
21
21
  } }
22
22
  post :create, :params => { :host => host }, :session => set_session_user
23
- assert_redirected_to host_url(assigns('host'))
23
+ assert_redirected_to host_details_page_url(assigns('host'))
24
24
  assert assigns('host').ansible_roles, [@role]
25
25
  end
26
26
 
@@ -34,7 +34,7 @@ class HostsControllerExtensionsTest < ActionController::TestCase
34
34
  } }
35
35
  },
36
36
  :session => set_session_user
37
- assert_redirected_to host_url(assigns('host'))
37
+ assert_redirected_to host_details_page_url(assigns('host'))
38
38
  assert_equal assigns('host').ansible_roles, [@role]
39
39
  end
40
40
 
@@ -0,0 +1,51 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class ImportPlaybooksTest < ActiveSupport::TestCase
4
+ let(:ansible_proxy) { FactoryBot.create(:smart_proxy, :with_ansible) }
5
+ let(:proxy_api) { ::ProxyAPI::Ansible.new(url: ansible_proxy.url) }
6
+ subject { ::ForemanAnsible::PlaybooksImporter.new(ansible_proxy) }
7
+ let(:sample_playbooks) { JSON.parse(File.read(ansible_fixture_file('sample_playbooks.json'))) }
8
+ let(:playbook1_output) { sample_playbooks.first }
9
+ let(:playbook2_output) { sample_playbooks.last }
10
+ let(:first_playbook) { ['xprazak2.forklift_collection.foreman_provisioning.yml'] }
11
+ let(:second_playbook) { ['xprazak2.forklift_collection.collect_debug_draft.yml'] }
12
+ let(:playbook1_template) { JSON.parse(File.read(ansible_fixture_file('playbooks_example_output.json')))['template'] }
13
+
14
+ setup do
15
+ subject.stubs(:proxy_api).returns(proxy_api)
16
+ end
17
+
18
+ describe 'check the job templates that were created due to the import' do
19
+ test 'should just create job templates from playbooks' do
20
+ subject.expects(:playbooks).with(second_playbook).returns([playbook2_output])
21
+ actual = subject.import_playbooks(second_playbook)
22
+ assert_not_nil actual_created = actual[:created]
23
+ assert_equal 1, actual_created.count
24
+ job_template = JobTemplate.where(id: actual_created.keys.first).first
25
+ assert_equal job_template.name, actual_created.values.first
26
+ end
27
+ end
28
+
29
+ describe 'check the updated job templated due to import playbooks' do
30
+ test ' should not update an identical job template' do
31
+ FactoryBot.create(:job_template, id: 111, name: playbook1_output['name'],
32
+ template: playbook1_template)
33
+ subject.expects(:playbooks).with(first_playbook).returns([playbook1_output])
34
+ actual = subject.import_playbooks(first_playbook)
35
+ assert_not_nil actual_updated = actual[:updated]
36
+ assert_not_nil actual_created = actual[:created]
37
+ assert_equal 0, actual_updated.count
38
+ assert_equal 0, actual_created.count
39
+ end
40
+
41
+ test ' should just update a job template from playbooks' do
42
+ job_template = FactoryBot.create(:job_template, id: 112, name: playbook2_output['name'], template: 'check')
43
+ subject.expects(:playbooks).with(second_playbook).returns([playbook2_output])
44
+ actual = subject.import_playbooks(second_playbook)
45
+ assert_not_nil actual_updated = actual[:updated]
46
+ assert_equal 1, actual_updated.count
47
+ assert_equal actual_updated.keys.first, job_template.id
48
+ assert_not_nil job_template.template
49
+ end
50
+ end
51
+ end
@@ -14,6 +14,12 @@ class AnsibleTest < ActiveSupport::TestCase
14
14
  assert_equal roles, @proxy_api.roles
15
15
  end
16
16
 
17
+ test 'should get ansible playbooks from proxy' do
18
+ playbooks = ['some_playbook.some_author', 'test_playbook.test_author']
19
+ @proxy_api.expects(:get).returns(fake_rest_client_response(playbooks))
20
+ assert_equal playbooks, @proxy_api.playbooks
21
+ end
22
+
17
23
  test 'should raise error with appropriate message' do
18
24
  message = 'Connection refused'
19
25
  @proxy_api.expects(:get).raises(Errno::ECONNREFUSED, message)
@@ -4,7 +4,6 @@ import { useDispatch } from 'react-redux';
4
4
  import { useMutation } from '@apollo/client';
5
5
 
6
6
  import { sprintf, translate as __ } from 'foremanReact/common/I18n';
7
- import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
8
7
  import { openConfirmModal } from 'foremanReact/components/ConfirmModal';
9
8
  import {
10
9
  TableComposable,
@@ -14,8 +13,9 @@ import {
14
13
  Th,
15
14
  Td,
16
15
  } from '@patternfly/react-table';
17
- import { Flex, FlexItem, Pagination } from '@patternfly/react-core';
16
+ import { Flex, FlexItem } from '@patternfly/react-core';
18
17
 
18
+ import Pagination from 'foremanReact/components/Pagination';
19
19
  import deleteAnsibleVariableOverride from '../../../../graphql/mutations/deleteAnsibleVariableOverride.gql';
20
20
  import EditableAction from './EditableAction';
21
21
  import EditableValue from './EditableValue';
@@ -29,10 +29,6 @@ import {
29
29
  } from './AnsibleVariableOverridesTableHelper';
30
30
 
31
31
  import withLoading from '../../../withLoading';
32
- import {
33
- preparePerPageOptions,
34
- refreshPage,
35
- } from '../../../../helpers/paginationHelper';
36
32
 
37
33
  const reducer = (state, action) =>
38
34
  state.map((item, index) => {
@@ -58,8 +54,6 @@ const AnsibleVariableOverridesTable = ({
58
54
  hostId,
59
55
  hostGlobalId,
60
56
  totalCount,
61
- pagination,
62
- history,
63
57
  }) => {
64
58
  const columns = [
65
59
  __('Name'),
@@ -69,16 +63,6 @@ const AnsibleVariableOverridesTable = ({
69
63
  __('Source attribute'),
70
64
  ];
71
65
 
72
- const handlePerPageSelected = (event, perPage) => {
73
- refreshPage(history, { page: 1, perPage });
74
- };
75
-
76
- const handlePageSelected = (event, page) => {
77
- refreshPage(history, { ...pagination, page });
78
- };
79
-
80
- const perPageOptions = preparePerPageOptions(usePaginationOptions());
81
-
82
66
  const [editableState, innerDispatch] = useReducer(
83
67
  reducer,
84
68
  variables,
@@ -162,67 +146,68 @@ const AnsibleVariableOverridesTable = ({
162
146
 
163
147
  return (
164
148
  <React.Fragment>
165
- <Flex>
149
+ <Flex direction={{ default: 'column' }}>
150
+ <FlexItem align={{ default: 'alignRight' }}>
151
+ <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
152
+ </FlexItem>
153
+ <FlexItem>
154
+ <TableComposable variant="compact">
155
+ <Thead>
156
+ <Tr>
157
+ {columns.map(col => (
158
+ <Th key={col}>{col}</Th>
159
+ ))}
160
+ <Th />
161
+ </Tr>
162
+ </Thead>
163
+ <Tbody>
164
+ {variables.map((variable, idx) => (
165
+ <Tr key={idx}>
166
+ <Td>
167
+ <a href={variable.path}>{variable.key}</a>
168
+ </Td>
169
+ <Td>{variable.ansibleRoleName}</Td>
170
+ <Td>{variable.parameterType}</Td>
171
+ <Td>
172
+ <EditableValue
173
+ variable={variable}
174
+ editing={editableState[idx].open}
175
+ onChange={onValueChange(idx, variable)}
176
+ value={editableState[idx].value}
177
+ validation={editableState[idx].validation}
178
+ working={editableState[idx].working}
179
+ />
180
+ </Td>
181
+ <Td>{formatSourceAttr(variable)}</Td>
182
+ <Td>
183
+ <EditableAction
184
+ open={editableState[idx].open}
185
+ onClose={setEditable(idx, false)}
186
+ onOpen={setEditable(idx, true)}
187
+ toggleWorking={toggleWorking(idx)}
188
+ variable={variable}
189
+ state={editableState[idx]}
190
+ hostId={hostId}
191
+ hostName={hostAttrs.name}
192
+ hostGlobalId={hostGlobalId}
193
+ onSubmitSuccess={onSubmitSuccess(idx, variable)}
194
+ onValidationError={onValidationError(idx)}
195
+ />
196
+ </Td>
197
+ <Td actions={{ items: actionsResolver(variable, idx) }} />
198
+ </Tr>
199
+ ))}
200
+ </Tbody>
201
+ </TableComposable>
202
+ </FlexItem>
166
203
  <FlexItem align={{ default: 'alignRight' }}>
167
204
  <Pagination
205
+ updateParamsByUrl
168
206
  itemCount={totalCount}
169
- page={pagination.page}
170
- perPage={pagination.perPage}
171
- onSetPage={handlePageSelected}
172
- onPerPageSelect={handlePerPageSelected}
173
- perPageOptions={perPageOptions}
174
- variant="top"
207
+ variant="bottom"
175
208
  />
176
209
  </FlexItem>
177
210
  </Flex>
178
- <TableComposable variant="compact">
179
- <Thead>
180
- <Tr>
181
- {columns.map(col => (
182
- <Th key={col}>{col}</Th>
183
- ))}
184
- <Th />
185
- </Tr>
186
- </Thead>
187
- <Tbody>
188
- {variables.map((variable, idx) => (
189
- <Tr key={idx}>
190
- <Td>
191
- <a href={variable.path}>{variable.key}</a>
192
- </Td>
193
- <Td>{variable.ansibleRoleName}</Td>
194
- <Td>{variable.parameterType}</Td>
195
- <Td>
196
- <EditableValue
197
- variable={variable}
198
- editing={editableState[idx].open}
199
- onChange={onValueChange(idx, variable)}
200
- value={editableState[idx].value}
201
- validation={editableState[idx].validation}
202
- working={editableState[idx].working}
203
- />
204
- </Td>
205
- <Td>{formatSourceAttr(variable)}</Td>
206
- <Td>
207
- <EditableAction
208
- open={editableState[idx].open}
209
- onClose={setEditable(idx, false)}
210
- onOpen={setEditable(idx, true)}
211
- toggleWorking={toggleWorking(idx)}
212
- variable={variable}
213
- state={editableState[idx]}
214
- hostId={hostId}
215
- hostName={hostAttrs.name}
216
- hostGlobalId={hostGlobalId}
217
- onSubmitSuccess={onSubmitSuccess(idx, variable)}
218
- onValidationError={onValidationError(idx)}
219
- />
220
- </Td>
221
- <Td actions={{ items: actionsResolver(variable, idx) }} />
222
- </Tr>
223
- ))}
224
- </Tbody>
225
- </TableComposable>
226
211
  </React.Fragment>
227
212
  );
228
213
  };
@@ -233,8 +218,6 @@ AnsibleVariableOverridesTable.propTypes = {
233
218
  hostId: PropTypes.number.isRequired,
234
219
  hostGlobalId: PropTypes.string.isRequired,
235
220
  totalCount: PropTypes.number.isRequired,
236
- pagination: PropTypes.object.isRequired,
237
- history: PropTypes.object.isRequired,
238
221
  };
239
222
 
240
223
  export default withLoading(AnsibleVariableOverridesTable);
@@ -1,8 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
- import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
5
-
6
4
  import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
7
5
 
8
6
  import {
@@ -13,15 +11,12 @@ import {
13
11
  Th,
14
12
  Td,
15
13
  } from '@patternfly/react-table';
16
- import { Flex, FlexItem, Pagination } from '@patternfly/react-core';
14
+ import { Flex, FlexItem } from '@patternfly/react-core';
15
+ import Pagination from 'foremanReact/components/Pagination';
17
16
 
18
17
  import { decodeId } from '../../../../globalIdHelper';
19
18
  import withLoading from '../../../withLoading';
20
19
  import { readableCron, readablePurpose } from './JobsTabHelper';
21
- import {
22
- preparePerPageOptions,
23
- refreshPage,
24
- } from '../../../../helpers/paginationHelper';
25
20
 
26
21
  const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
27
22
  const columns = [
@@ -32,66 +27,57 @@ const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
32
27
  __('Schedule'),
33
28
  ];
34
29
 
35
- const handlePerPageSelected = (event, perPage) => {
36
- refreshPage(history, { page: 1, perPage });
37
- };
38
-
39
- const handlePageSelected = (event, page) => {
40
- refreshPage(history, { ...pagination, page });
41
- };
42
-
43
- const perPageOptions = preparePerPageOptions(usePaginationOptions());
44
-
45
30
  return (
46
31
  <React.Fragment>
47
32
  <h3>{__('Previously executed jobs')}</h3>
48
- <Flex className="pf-u-pt-md">
33
+ <Flex direction={{ default: 'column' }} className="pf-u-pt-md">
34
+ <FlexItem align={{ default: 'alignRight' }}>
35
+ <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
36
+ </FlexItem>
37
+ <FlexItem>
38
+ <TableComposable variant="compact">
39
+ <Thead>
40
+ <Tr>
41
+ {columns.map(col => (
42
+ <Th key={col}>{col}</Th>
43
+ ))}
44
+ </Tr>
45
+ </Thead>
46
+ <Tbody>
47
+ {jobs.map(job => (
48
+ <Tr key={job.id}>
49
+ <Td>
50
+ <a
51
+ onClick={() =>
52
+ window.tfm.nav.pushUrl(
53
+ `/job_invocations/${decodeId(job.id)}`
54
+ )
55
+ }
56
+ >
57
+ {job.description}
58
+ </a>
59
+ &nbsp;
60
+ {readablePurpose(job.recurringLogic.purpose)}
61
+ </Td>
62
+ <Td>{job.task.result}</Td>
63
+ <Td>{job.task.state}</Td>
64
+ <Td>
65
+ <RelativeDateTime date={job.startAt} />
66
+ </Td>
67
+ <Td>{readableCron(job.recurringLogic.cronLine)}</Td>
68
+ </Tr>
69
+ ))}
70
+ </Tbody>
71
+ </TableComposable>
72
+ </FlexItem>
49
73
  <FlexItem align={{ default: 'alignRight' }}>
50
74
  <Pagination
75
+ updateParamsByUrl
51
76
  itemCount={totalCount}
52
- page={pagination.page}
53
- perPage={pagination.perPage}
54
- onSetPage={handlePageSelected}
55
- onPerPageSelect={handlePerPageSelected}
56
- perPageOptions={perPageOptions}
57
- variant="top"
77
+ variant="bottom"
58
78
  />
59
79
  </FlexItem>
60
80
  </Flex>
61
- <TableComposable variant="compact">
62
- <Thead>
63
- <Tr>
64
- {columns.map(col => (
65
- <Th key={col}>{col}</Th>
66
- ))}
67
- </Tr>
68
- </Thead>
69
- <Tbody>
70
- {jobs.map(job => (
71
- <Tr key={job.id}>
72
- <Td>
73
- <a
74
- onClick={() =>
75
- window.tfm.nav.pushUrl(
76
- `/job_invocations/${decodeId(job.id)}`
77
- )
78
- }
79
- >
80
- {job.description}
81
- </a>
82
- &nbsp;
83
- {readablePurpose(job.recurringLogic.purpose)}
84
- </Td>
85
- <Td>{job.task.result}</Td>
86
- <Td>{job.task.state}</Td>
87
- <Td>
88
- <RelativeDateTime date={job.startAt} />
89
- </Td>
90
- <Td>{readableCron(job.recurringLogic.cronLine)}</Td>
91
- </Tr>
92
- ))}
93
- </Tbody>
94
- </TableComposable>
95
81
  </React.Fragment>
96
82
  );
97
83
  };
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
- import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
5
4
 
6
5
  import {
7
6
  TableComposable,
@@ -11,70 +10,50 @@ import {
11
10
  Th,
12
11
  Td,
13
12
  } from '@patternfly/react-table';
14
-
15
- import { Flex, FlexItem, Pagination } from '@patternfly/react-core';
13
+ import { Flex, FlexItem } from '@patternfly/react-core';
14
+ import Pagination from 'foremanReact/components/Pagination';
16
15
  import withLoading from '../../../../withLoading';
17
- import {
18
- preparePerPageOptions,
19
- refreshPage,
20
- } from '../../../../../helpers/paginationHelper';
21
16
 
22
- const AllRolesTable = ({
23
- allAnsibleRoles,
24
- totalCount,
25
- pagination,
26
- history,
27
- }) => {
17
+ const AllRolesTable = ({ allAnsibleRoles, totalCount }) => {
28
18
  const columns = [__('Name'), __('Source')];
29
19
 
30
- const handlePerPageSelected = (event, allPerPage) => {
31
- refreshPage(history, { allPage: 1, allPerPage });
32
- };
33
-
34
- const handlePageSelected = (event, allPage) => {
35
- refreshPage(history, { ...pagination, allPage });
36
- };
37
-
38
- const perPageOptions = preparePerPageOptions(usePaginationOptions());
39
-
40
20
  return (
41
21
  <React.Fragment>
42
- <Flex className="pf-u-pt-md">
22
+ <Flex direction={{ default: 'column' }} className="pf-u-pt-md">
23
+ <FlexItem align={{ default: 'alignRight' }}>
24
+ <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
25
+ </FlexItem>
26
+ <TableComposable variant="compact">
27
+ <Thead>
28
+ <Tr>
29
+ <Th />
30
+ {columns.map(col => (
31
+ <Th key={`${col}-all`}>{col}</Th>
32
+ ))}
33
+ </Tr>
34
+ </Thead>
35
+ <Tbody>
36
+ {allAnsibleRoles.map(role => (
37
+ <Tr key={`${role.id}-all`} id={role.id}>
38
+ <Td />
39
+ <Td>{role.name}</Td>
40
+ <Td>
41
+ {role.inherited
42
+ ? __('Inherited from Hostgroup')
43
+ : __('Directly assigned to Host')}
44
+ </Td>
45
+ </Tr>
46
+ ))}
47
+ </Tbody>
48
+ </TableComposable>
43
49
  <FlexItem align={{ default: 'alignRight' }}>
44
50
  <Pagination
51
+ updateParamsByUrl
45
52
  itemCount={totalCount}
46
- page={pagination.allPage}
47
- perPage={pagination.allPerPage}
48
- onSetPage={handlePageSelected}
49
- onPerPageSelect={handlePerPageSelected}
50
- perPageOptions={perPageOptions}
51
- variant="top"
53
+ variant="bottom"
52
54
  />
53
55
  </FlexItem>
54
56
  </Flex>
55
- <TableComposable variant="compact">
56
- <Thead>
57
- <Tr>
58
- <Th />
59
- {columns.map(col => (
60
- <Th key={`${col}-all`}>{col}</Th>
61
- ))}
62
- </Tr>
63
- </Thead>
64
- <Tbody>
65
- {allAnsibleRoles.map(role => (
66
- <Tr key={`${role.id}-all`} id={role.id}>
67
- <Td />
68
- <Td>{role.name}</Td>
69
- <Td>
70
- {role.inherited
71
- ? __('Inherited from Hostgroup')
72
- : __('Directly assigned to Host')}
73
- </Td>
74
- </Tr>
75
- ))}
76
- </Tbody>
77
- </TableComposable>
78
57
  </React.Fragment>
79
58
  );
80
59
  };
@@ -82,8 +61,6 @@ const AllRolesTable = ({
82
61
  AllRolesTable.propTypes = {
83
62
  allAnsibleRoles: PropTypes.array.isRequired,
84
63
  totalCount: PropTypes.number.isRequired,
85
- pagination: PropTypes.object.isRequired,
86
- history: PropTypes.object.isRequired,
87
64
  };
88
65
 
89
66
  export default withLoading(AllRolesTable);
@@ -27,7 +27,7 @@ const AllRolesModal = ({ hostGlobalId, onClose, history }) => {
27
27
  ),
28
28
  };
29
29
 
30
- const paginationKeys = { page: 'allPage', perPage: 'allPerPage' };
30
+ const paginationKeys = { page: 'page', perPage: 'per_page' };
31
31
 
32
32
  const wrapper = child => <Modal {...baseModalProps}>{child}</Modal>;
33
33
 
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { Route, Link } from 'react-router-dom';
5
- import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
5
+ import Pagination from 'foremanReact/components/Pagination';
6
6
 
7
7
  import {
8
8
  TableComposable,
@@ -12,20 +12,15 @@ import {
12
12
  Th,
13
13
  Td,
14
14
  } from '@patternfly/react-table';
15
- import { Flex, FlexItem, Button, Pagination } from '@patternfly/react-core';
15
+ import { Flex, FlexItem, Button } from '@patternfly/react-core';
16
16
 
17
17
  import EditRolesModal from './EditRolesModal';
18
18
 
19
19
  import withLoading from '../../../withLoading';
20
20
  import AllRolesModal from './AllRolesModal';
21
- import {
22
- preparePerPageOptions,
23
- refreshPage,
24
- } from '../../../../helpers/paginationHelper';
25
21
 
26
22
  const RolesTable = ({
27
23
  totalCount,
28
- pagination,
29
24
  history,
30
25
  ansibleRoles,
31
26
  hostId,
@@ -34,16 +29,6 @@ const RolesTable = ({
34
29
  }) => {
35
30
  const columns = [__('Name')];
36
31
 
37
- const handlePerPageSelected = (event, perPage) => {
38
- refreshPage(history, { page: 1, perPage });
39
- };
40
-
41
- const handlePageSelected = (event, page) => {
42
- refreshPage(history, { ...pagination, page });
43
- };
44
-
45
- const perPageOptions = preparePerPageOptions(usePaginationOptions());
46
-
47
32
  const editBtn = canEditHost ? (
48
33
  <FlexItem>
49
34
  <Link to="/Ansible/roles/edit">
@@ -67,36 +52,39 @@ const RolesTable = ({
67
52
  </Flex>
68
53
  <Flex>
69
54
  <FlexItem>{editBtn}</FlexItem>
55
+ <FlexItem align={{ default: 'alignRight' }}>
56
+ <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
57
+ </FlexItem>
58
+ </Flex>
59
+ <Flex direction={{ default: 'column' }}>
60
+ <FlexItem>
61
+ <TableComposable variant="compact">
62
+ <Thead>
63
+ <Tr>
64
+ {columns.map(col => (
65
+ <Th key={col}>{col}</Th>
66
+ ))}
67
+ </Tr>
68
+ </Thead>
69
+ <Tbody>
70
+ {ansibleRoles.map(role => (
71
+ <Tr key={role.id}>
72
+ <Td>
73
+ <a href={role.path}>{role.name}</a>
74
+ </Td>
75
+ </Tr>
76
+ ))}
77
+ </Tbody>
78
+ </TableComposable>
79
+ </FlexItem>
70
80
  <FlexItem align={{ default: 'alignRight' }}>
71
81
  <Pagination
82
+ updateParamsByUrl
72
83
  itemCount={totalCount}
73
- page={pagination.page}
74
- perPage={pagination.perPage}
75
- onSetPage={handlePageSelected}
76
- onPerPageSelect={handlePerPageSelected}
77
- perPageOptions={perPageOptions}
78
- variant="top"
84
+ variant="bottom"
79
85
  />
80
86
  </FlexItem>
81
87
  </Flex>
82
- <TableComposable variant="compact">
83
- <Thead>
84
- <Tr>
85
- {columns.map(col => (
86
- <Th key={col}>{col}</Th>
87
- ))}
88
- </Tr>
89
- </Thead>
90
- <Tbody>
91
- {ansibleRoles.map(role => (
92
- <Tr key={role.id}>
93
- <Td>
94
- <a href={role.path}>{role.name}</a>
95
- </Td>
96
- </Tr>
97
- ))}
98
- </Tbody>
99
- </TableComposable>
100
88
  <Route path="/Ansible/roles/edit">
101
89
  <EditRolesModal
102
90
  closeModal={() => history.goBack()}
@@ -123,7 +111,6 @@ RolesTable.propTypes = {
123
111
  hostId: PropTypes.number.isRequired,
124
112
  hostGlobalId: PropTypes.string.isRequired,
125
113
  history: PropTypes.object.isRequired,
126
- pagination: PropTypes.object.isRequired,
127
114
  totalCount: PropTypes.number.isRequired,
128
115
  canEditHost: PropTypes.bool.isRequired,
129
116
  };