foreman_ansible 7.0.4 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/ansible_playbooks_controller.rb +66 -0
  3. data/app/controllers/foreman_ansible/api/v2/hostgroups_controller_extensions.rb +5 -1
  4. data/app/controllers/foreman_ansible/api/v2/hosts_controller_extensions.rb +3 -1
  5. data/app/graphql/presenters/ansible_role_presenter.rb +4 -0
  6. data/app/graphql/types/ansible_role.rb +1 -0
  7. data/app/graphql/types/inherited_ansible_role.rb +4 -0
  8. data/app/helpers/foreman_ansible/hosts_helper.rb +19 -0
  9. data/app/jobs/sync_playbooks.rb +25 -0
  10. data/app/lib/proxy_api/ansible.rb +13 -0
  11. data/app/services/foreman_ansible/import_playbooks_error_notification.rb +38 -0
  12. data/app/services/foreman_ansible/import_playbooks_success_notification.rb +33 -0
  13. data/app/services/foreman_ansible/playbooks_importer.rb +73 -0
  14. data/app/services/foreman_ansible/proxy_api.rb +3 -4
  15. data/app/services/foreman_ansible/variables_importer.rb +9 -9
  16. data/app/views/ansible_roles/index.html.erb +2 -0
  17. data/app/views/api/v2/ansible_playbooks/sync.json.rabl +5 -0
  18. data/app/views/api/v2/hostgroups/ansible_roles.json.rabl +9 -1
  19. data/app/views/api/v2/hosts/ansible_roles.json.rabl +9 -1
  20. data/app/views/foreman_ansible/job_templates/ansible_roles_-_install_from_git.erb +4 -1
  21. data/app/views/foreman_ansible/job_templates/ansible_windows_updates.erb +160 -0
  22. data/config/routes.rb +10 -3
  23. data/db/migrate/20200421201839_update_ansible_inv_template_name.rb +1 -5
  24. data/db/seeds.d/90_notification_blueprints.rb +14 -0
  25. data/lib/foreman_ansible/engine.rb +0 -1
  26. data/lib/foreman_ansible/register.rb +9 -3
  27. data/lib/foreman_ansible/version.rb +1 -1
  28. data/locale/action_names.rb +4 -3
  29. data/locale/ca/foreman_ansible.edit.po +1162 -0
  30. data/locale/ca/foreman_ansible.po +360 -45
  31. data/{webpack/components/withPagination.js → locale/ca/foreman_ansible.po.time_stamp} +0 -0
  32. data/locale/cs_CZ/foreman_ansible.edit.po +1207 -0
  33. data/locale/cs_CZ/foreman_ansible.po +372 -57
  34. data/locale/cs_CZ/foreman_ansible.po.time_stamp +0 -0
  35. data/locale/de/foreman_ansible.edit.po +1148 -0
  36. data/locale/de/foreman_ansible.po +355 -40
  37. data/locale/de/foreman_ansible.po.time_stamp +0 -0
  38. data/locale/en/foreman_ansible.edit.po +1146 -0
  39. data/locale/en/foreman_ansible.po +355 -40
  40. data/locale/en/foreman_ansible.po.time_stamp +0 -0
  41. data/locale/en_GB/foreman_ansible.edit.po +1155 -0
  42. data/locale/en_GB/foreman_ansible.po +357 -42
  43. data/locale/en_GB/foreman_ansible.po.time_stamp +0 -0
  44. data/locale/es/foreman_ansible.edit.po +1148 -0
  45. data/locale/es/foreman_ansible.po +355 -40
  46. data/locale/es/foreman_ansible.po.time_stamp +0 -0
  47. data/locale/foreman_ansible.pot +767 -263
  48. data/locale/fr/foreman_ansible.edit.po +1148 -0
  49. data/locale/fr/foreman_ansible.po +355 -40
  50. data/locale/fr/foreman_ansible.po.time_stamp +0 -0
  51. data/locale/gl/foreman_ansible.edit.po +1156 -0
  52. data/locale/gl/foreman_ansible.po +358 -43
  53. data/locale/gl/foreman_ansible.po.time_stamp +0 -0
  54. data/locale/it/foreman_ansible.edit.po +1148 -0
  55. data/locale/it/foreman_ansible.po +355 -40
  56. data/locale/it/foreman_ansible.po.time_stamp +0 -0
  57. data/locale/ja/foreman_ansible.edit.po +1148 -0
  58. data/locale/ja/foreman_ansible.po +355 -40
  59. data/locale/ja/foreman_ansible.po.time_stamp +0 -0
  60. data/locale/ko/foreman_ansible.edit.po +1148 -0
  61. data/locale/ko/foreman_ansible.po +355 -40
  62. data/locale/ko/foreman_ansible.po.time_stamp +0 -0
  63. data/locale/nl_NL/foreman_ansible.edit.po +1168 -0
  64. data/locale/nl_NL/foreman_ansible.po +359 -44
  65. data/locale/nl_NL/foreman_ansible.po.time_stamp +0 -0
  66. data/locale/pl/foreman_ansible.edit.po +1180 -0
  67. data/locale/pl/foreman_ansible.po +363 -48
  68. data/locale/pl/foreman_ansible.po.time_stamp +0 -0
  69. data/locale/pt_BR/foreman_ansible.edit.po +1148 -0
  70. data/locale/pt_BR/foreman_ansible.po +355 -40
  71. data/locale/pt_BR/foreman_ansible.po.time_stamp +0 -0
  72. data/locale/ru/foreman_ansible.edit.po +1149 -0
  73. data/locale/ru/foreman_ansible.po +355 -40
  74. data/locale/ru/foreman_ansible.po.time_stamp +0 -0
  75. data/locale/sv_SE/foreman_ansible.edit.po +1180 -0
  76. data/locale/sv_SE/foreman_ansible.po +363 -48
  77. data/locale/sv_SE/foreman_ansible.po.time_stamp +0 -0
  78. data/locale/zh_CN/foreman_ansible.edit.po +1148 -0
  79. data/locale/zh_CN/foreman_ansible.po +355 -40
  80. data/locale/zh_CN/foreman_ansible.po.time_stamp +0 -0
  81. data/locale/zh_TW/foreman_ansible.edit.po +1148 -0
  82. data/locale/zh_TW/foreman_ansible.po +355 -40
  83. data/locale/zh_TW/foreman_ansible.po.time_stamp +0 -0
  84. data/test/fixtures/playbooks_example_output.json +1 -0
  85. data/test/fixtures/sample_playbooks.json +10 -0
  86. data/test/functional/api/v2/ansible_playbooks_controller_test.rb +65 -0
  87. data/test/functional/hosts_controller_test.rb +2 -2
  88. data/test/graphql/queries/host_ansible_roles_query_test.rb +61 -0
  89. data/test/unit/import_playbooks_test.rb +51 -0
  90. data/test/unit/lib/proxy_api/ansible_test.rb +6 -0
  91. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +58 -75
  92. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +44 -58
  93. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js.orig +151 -0
  94. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +43 -56
  95. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -1
  96. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +26 -24
  97. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +3 -2
  98. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +39 -43
  99. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +30 -0
  100. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js +27 -38
  101. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js +2 -1
  102. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesConstants.js +1 -0
  103. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesSelectors.js +6 -0
  104. data/webpack/components/AnsibleRolesAndVariables/index.js +7 -1
  105. data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcher.test.js +0 -2
  106. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +3 -12
  107. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -2
  108. data/webpack/components/AnsibleRolesSwitcher/components/OrderedRolesTooltip.js +11 -12
  109. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +6 -20
  110. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -6
  111. data/webpack/components/withLoading.js +7 -12
  112. data/webpack/graphql/queries/allAnsibleRoles.gql +3 -0
  113. data/webpack/graphql/queries/hostAnsibleRoles.gql +3 -0
  114. data/webpack/helpers/pageParamsHelper.js +3 -3
  115. metadata +87 -34
  116. data/app/helpers/foreman_ansible/hosts_helper_extensions.rb +0 -30
  117. data/webpack/helpers/paginationHelper.js +0 -9
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "name": "xprazak2.forklift_collection.foreman_provisioning.yml",
4
+ "playbooks_content": "- hosts: all\n become: true\n vars:\n libvirt_tftp: true\n roles:\n - foreman\n - libvirt\n - foreman_provisioning\n"
5
+ },
6
+ {
7
+ "name": "xprazak2.forklift_collection.collect_debug_draft.yml",
8
+ "playbooks_content": "---\n- hosts: all\n become: true\n vars:\n bats_output_dir: '/root/bats_results'\n remote_dir: \"/tmp/debug-{{ pipeline_type | default('foreman') }}-{{ pipeline_version | default('nightly') }}-{{ pipeline_os | default('el7') }}\"\n roles:\n - sos_report\n tasks:\n - name: \"Find bats files\"\n find:\n paths: \"{{ bats_output_dir }}\"\n patterns: \"*.tap\"\n register: bats_results\n\n - name: \"Copy bats results\"\n fetch:\n src: \"{{ item.path }}\"\n dest: \"{{ remote_dir }}\"\n with_items: \"{{ bats_results.files }}\"\n\n - name: \"Find smoker files\"\n find:\n paths: \"{{ smoker_output_dir }}\"\n patterns: \"*.xml\"\n register: smoker_results\n\n - name: \"Copy smoker results\"\n fetch:\n src: \"{{ item.path }}\"\n dest: \"{{ remote_dir }}\"\n with_items: \"{{ smoker_results.files }}\"\n"
9
+ }
10
+ ]
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module Api
6
+ module V2
7
+ # Tests for the ansible playbooks controller
8
+ class AnsiblePlaybooksControllerTest < ActionController::TestCase
9
+ let(:ansible_proxy) { FactoryBot.create(:smart_proxy, :with_ansible) }
10
+ let(:proxy_api) { ::ProxyAPI::Ansible.new(url: ansible_proxy.url) }
11
+ let(:playbooks_names) { %w[xprazak2.forklift_collection.foreman_provisioning.yml xprazak2.forklift_collection.collect_debug_draft.yml] }
12
+ let(:importer_test) { mock('PlaybooksImporter') }
13
+
14
+ test 'should fetch with nil' do
15
+ AnsiblePlaybooksController.any_instance.stubs(:fetch_playbooks_names).returns(nil)
16
+
17
+ get :fetch, :params => {
18
+ :proxy_id => ansible_proxy.id
19
+ }, :session => set_session_user
20
+ response = JSON.parse(@response.body)
21
+ assert_empty response['results']['playbooks_names']
22
+ assert_response :success
23
+ end
24
+
25
+ test 'should fetch playbooks names' do
26
+ AnsiblePlaybooksController.any_instance.stubs(:fetch_playbooks_names).returns(playbooks_names)
27
+
28
+ get :fetch, :params => {
29
+ :proxy_id => ansible_proxy.id
30
+ }, :session => set_session_user
31
+ response = JSON.parse(@response.body)
32
+ assert_not_empty response['results']
33
+ assert_equal response['results']['playbooks_names'], playbooks_names
34
+ end
35
+
36
+ test 'should use correct proxy' do
37
+ AnsiblePlaybooksController.any_instance.expects(:find_proxy_api).with(ansible_proxy).returns(proxy_api)
38
+ proxy_api.expects(:playbooks_names).returns(playbooks_names)
39
+
40
+ get :fetch, :params => {
41
+ :proxy_id => ansible_proxy.id
42
+ }, :session => set_session_user
43
+ response = JSON.parse(@response.body)
44
+ assert_not_empty response['results']
45
+ assert_not_empty playbooks_names = response['results']['playbooks_names']
46
+ assert_equal 2, playbooks_names.count
47
+ end
48
+
49
+ test 'check plan and sync' do
50
+ task = mock('Foreman Task')
51
+ AnsiblePlaybooksController.any_instance.expects(:plan_ansible_sync).with(ansible_proxy.id, playbooks_names).returns(task)
52
+ task.stubs(:id).returns('123')
53
+ task.stubs(:action).returns('Import Playbooks')
54
+
55
+ put :sync, :params => {
56
+ :proxy_id => ansible_proxy.id,
57
+ :playbooks_names => playbooks_names
58
+ }, :session => set_session_user
59
+ response = JSON.parse(@response.body)
60
+ assert_equal '123', response['id']
61
+ assert_equal 'Import Playbooks', response['action']
62
+ end
63
+ end
64
+ end
65
+ end
@@ -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,61 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module Queries
4
+ class HostAnsibleRolesQueryTest < GraphQLQueryTestCase
5
+ let(:role1) { FactoryBot.create(:ansible_role) }
6
+ let(:role2) { FactoryBot.create(:ansible_role) }
7
+ let(:hostgroup) { FactoryBot.create(:hostgroup, ansible_roles: [role1]) }
8
+ let(:host) { FactoryBot.create(:host, hostgroup: hostgroup, ansible_roles: [role2]) }
9
+ let(:variables) { { id: Foreman::GlobalId.for(host) } }
10
+ let(:query) do
11
+ <<-GRAPHQL
12
+ query ($id: String!) {
13
+ host(id: $id) {
14
+ id
15
+ allAnsibleRoles {
16
+ totalCount
17
+ nodes {
18
+ id
19
+ name
20
+ inherited
21
+ ansibleVariables {
22
+ totalCount
23
+ nodes {
24
+ key
25
+ override
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ GRAPHQL
33
+ end
34
+
35
+ context 'with admin permissions' do
36
+ let(:context_user) { FactoryBot.create(:user, :admin) }
37
+ let(:data) { result['data']['host']['allAnsibleRoles'] }
38
+
39
+ it 'allows to fetch inherited roles' do
40
+ value(data['totalCount']).must_equal(2)
41
+ r1_data = data['nodes'].first
42
+ r2_data = data['nodes'].second
43
+ value(r1_data['name']).must_equal(role1.name)
44
+ value(r1_data['inherited']).must_equal(true)
45
+ value(r2_data['name']).must_equal(role2.name)
46
+ value(r2_data['inherited']).must_equal(false)
47
+ end
48
+
49
+ it 'allow fetching variables' do
50
+ var1 = FactoryBot.create(:ansible_variable, ansible_role: role1, override: true)
51
+ FactoryBot.create(:ansible_variable, ansible_role: role1)
52
+ FactoryBot.create(:ansible_variable, ansible_role: role2, override: true)
53
+ r1_vars = data['nodes'].first['ansibleVariables']
54
+ r2_vars = data['nodes'].second['ansibleVariables']
55
+ value(r1_vars['totalCount']).must_equal(2)
56
+ value(r2_vars['totalCount']).must_equal(1)
57
+ value(r1_vars['nodes'].first['key']).must_equal(var1.key)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -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
  };