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.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/ansible_playbooks_controller.rb +66 -0
- data/app/controllers/foreman_ansible/api/v2/hostgroups_controller_extensions.rb +5 -1
- data/app/controllers/foreman_ansible/api/v2/hosts_controller_extensions.rb +3 -1
- data/app/graphql/presenters/ansible_role_presenter.rb +4 -0
- data/app/graphql/types/ansible_role.rb +1 -0
- data/app/graphql/types/inherited_ansible_role.rb +4 -0
- data/app/helpers/foreman_ansible/hosts_helper.rb +19 -0
- data/app/jobs/sync_playbooks.rb +25 -0
- data/app/lib/proxy_api/ansible.rb +13 -0
- data/app/services/foreman_ansible/import_playbooks_error_notification.rb +38 -0
- data/app/services/foreman_ansible/import_playbooks_success_notification.rb +33 -0
- data/app/services/foreman_ansible/playbooks_importer.rb +73 -0
- data/app/services/foreman_ansible/proxy_api.rb +3 -4
- data/app/services/foreman_ansible/variables_importer.rb +9 -9
- data/app/views/ansible_roles/index.html.erb +2 -0
- data/app/views/api/v2/ansible_playbooks/sync.json.rabl +5 -0
- data/app/views/api/v2/hostgroups/ansible_roles.json.rabl +9 -1
- data/app/views/api/v2/hosts/ansible_roles.json.rabl +9 -1
- data/app/views/foreman_ansible/job_templates/ansible_roles_-_install_from_git.erb +4 -1
- data/app/views/foreman_ansible/job_templates/ansible_windows_updates.erb +160 -0
- data/config/routes.rb +10 -3
- data/db/migrate/20200421201839_update_ansible_inv_template_name.rb +1 -5
- data/db/seeds.d/90_notification_blueprints.rb +14 -0
- data/lib/foreman_ansible/engine.rb +0 -1
- data/lib/foreman_ansible/register.rb +9 -3
- data/lib/foreman_ansible/version.rb +1 -1
- data/locale/action_names.rb +4 -3
- data/locale/ca/foreman_ansible.edit.po +1162 -0
- data/locale/ca/foreman_ansible.po +360 -45
- data/{webpack/components/withPagination.js → locale/ca/foreman_ansible.po.time_stamp} +0 -0
- data/locale/cs_CZ/foreman_ansible.edit.po +1207 -0
- data/locale/cs_CZ/foreman_ansible.po +372 -57
- data/locale/cs_CZ/foreman_ansible.po.time_stamp +0 -0
- data/locale/de/foreman_ansible.edit.po +1148 -0
- data/locale/de/foreman_ansible.po +355 -40
- data/locale/de/foreman_ansible.po.time_stamp +0 -0
- data/locale/en/foreman_ansible.edit.po +1146 -0
- data/locale/en/foreman_ansible.po +355 -40
- data/locale/en/foreman_ansible.po.time_stamp +0 -0
- data/locale/en_GB/foreman_ansible.edit.po +1155 -0
- data/locale/en_GB/foreman_ansible.po +357 -42
- data/locale/en_GB/foreman_ansible.po.time_stamp +0 -0
- data/locale/es/foreman_ansible.edit.po +1148 -0
- data/locale/es/foreman_ansible.po +355 -40
- data/locale/es/foreman_ansible.po.time_stamp +0 -0
- data/locale/foreman_ansible.pot +767 -263
- data/locale/fr/foreman_ansible.edit.po +1148 -0
- data/locale/fr/foreman_ansible.po +355 -40
- data/locale/fr/foreman_ansible.po.time_stamp +0 -0
- data/locale/gl/foreman_ansible.edit.po +1156 -0
- data/locale/gl/foreman_ansible.po +358 -43
- data/locale/gl/foreman_ansible.po.time_stamp +0 -0
- data/locale/it/foreman_ansible.edit.po +1148 -0
- data/locale/it/foreman_ansible.po +355 -40
- data/locale/it/foreman_ansible.po.time_stamp +0 -0
- data/locale/ja/foreman_ansible.edit.po +1148 -0
- data/locale/ja/foreman_ansible.po +355 -40
- data/locale/ja/foreman_ansible.po.time_stamp +0 -0
- data/locale/ko/foreman_ansible.edit.po +1148 -0
- data/locale/ko/foreman_ansible.po +355 -40
- data/locale/ko/foreman_ansible.po.time_stamp +0 -0
- data/locale/nl_NL/foreman_ansible.edit.po +1168 -0
- data/locale/nl_NL/foreman_ansible.po +359 -44
- data/locale/nl_NL/foreman_ansible.po.time_stamp +0 -0
- data/locale/pl/foreman_ansible.edit.po +1180 -0
- data/locale/pl/foreman_ansible.po +363 -48
- data/locale/pl/foreman_ansible.po.time_stamp +0 -0
- data/locale/pt_BR/foreman_ansible.edit.po +1148 -0
- data/locale/pt_BR/foreman_ansible.po +355 -40
- data/locale/pt_BR/foreman_ansible.po.time_stamp +0 -0
- data/locale/ru/foreman_ansible.edit.po +1149 -0
- data/locale/ru/foreman_ansible.po +355 -40
- data/locale/ru/foreman_ansible.po.time_stamp +0 -0
- data/locale/sv_SE/foreman_ansible.edit.po +1180 -0
- data/locale/sv_SE/foreman_ansible.po +363 -48
- data/locale/sv_SE/foreman_ansible.po.time_stamp +0 -0
- data/locale/zh_CN/foreman_ansible.edit.po +1148 -0
- data/locale/zh_CN/foreman_ansible.po +355 -40
- data/locale/zh_CN/foreman_ansible.po.time_stamp +0 -0
- data/locale/zh_TW/foreman_ansible.edit.po +1148 -0
- data/locale/zh_TW/foreman_ansible.po +355 -40
- data/locale/zh_TW/foreman_ansible.po.time_stamp +0 -0
- data/test/fixtures/playbooks_example_output.json +1 -0
- data/test/fixtures/sample_playbooks.json +10 -0
- data/test/functional/api/v2/ansible_playbooks_controller_test.rb +65 -0
- data/test/functional/hosts_controller_test.rb +2 -2
- data/test/graphql/queries/host_ansible_roles_query_test.rb +61 -0
- data/test/unit/import_playbooks_test.rb +51 -0
- data/test/unit/lib/proxy_api/ansible_test.rb +6 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +58 -75
- data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +44 -58
- data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js.orig +151 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +43 -56
- data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -1
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +26 -24
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +3 -2
- data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +39 -43
- data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +30 -0
- data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js +27 -38
- data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js +2 -1
- data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesConstants.js +1 -0
- data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesSelectors.js +6 -0
- data/webpack/components/AnsibleRolesAndVariables/index.js +7 -1
- data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcher.test.js +0 -2
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +3 -12
- data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -2
- data/webpack/components/AnsibleRolesSwitcher/components/OrderedRolesTooltip.js +11 -12
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +6 -20
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -6
- data/webpack/components/withLoading.js +7 -12
- data/webpack/graphql/queries/allAnsibleRoles.gql +3 -0
- data/webpack/graphql/queries/hostAnsibleRoles.gql +3 -0
- data/webpack/helpers/pageParamsHelper.js +3 -3
- metadata +87 -34
- data/app/helpers/foreman_ansible/hosts_helper_extensions.rb +0 -30
- 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
|
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
|
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
|
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
|
-
|
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
|
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
|
+
|
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
|
-
|
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
|
-
|
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
|
};
|