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,151 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
|
5
|
+
|
6
|
+
import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
|
7
|
+
|
8
|
+
import {
|
9
|
+
TableComposable,
|
10
|
+
Thead,
|
11
|
+
Tbody,
|
12
|
+
Tr,
|
13
|
+
Th,
|
14
|
+
Td,
|
15
|
+
} from '@patternfly/react-table';
|
16
|
+
import { Flex, FlexItem, Pagination } from '@patternfly/react-core';
|
17
|
+
|
18
|
+
import { decodeId } from '../../../../globalIdHelper';
|
19
|
+
import withLoading from '../../../withLoading';
|
20
|
+
<<<<<<< HEAD
|
21
|
+
import { readableCron } from './JobsTabHelper';
|
22
|
+
import {
|
23
|
+
preparePerPageOptions,
|
24
|
+
refreshPage,
|
25
|
+
} from '../../../../helpers/paginationHelper';
|
26
|
+
=======
|
27
|
+
import { readableCron, readablePurpose } from './JobsTabHelper';
|
28
|
+
>>>>>>> 5b01704 (Fixes #34458 - Show Hostgroup jobs on the Host Detail page)
|
29
|
+
|
30
|
+
const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
|
31
|
+
const columns = [
|
32
|
+
__('Description'),
|
33
|
+
__('Result'),
|
34
|
+
__('State'),
|
35
|
+
__('Executed at'),
|
36
|
+
__('Schedule'),
|
37
|
+
];
|
38
|
+
|
39
|
+
const handlePerPageSelected = (event, perPage) => {
|
40
|
+
refreshPage(history, { page: 1, perPage });
|
41
|
+
};
|
42
|
+
|
43
|
+
const handlePageSelected = (event, page) => {
|
44
|
+
refreshPage(history, { ...pagination, page });
|
45
|
+
};
|
46
|
+
|
47
|
+
const perPageOptions = preparePerPageOptions(usePaginationOptions());
|
48
|
+
|
49
|
+
return (
|
50
|
+
<React.Fragment>
|
51
|
+
<h3>{__('Previously executed jobs')}</h3>
|
52
|
+
<<<<<<< HEAD
|
53
|
+
<Flex className="pf-u-pt-md">
|
54
|
+
=======
|
55
|
+
<Flex direction={{ default: 'column' }} className="pf-u-pt-md">
|
56
|
+
<FlexItem align={{ default: 'alignRight' }}>
|
57
|
+
<Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
|
58
|
+
</FlexItem>
|
59
|
+
<FlexItem>
|
60
|
+
<TableComposable variant="compact">
|
61
|
+
<Thead>
|
62
|
+
<Tr>
|
63
|
+
{columns.map(col => (
|
64
|
+
<Th key={col}>{col}</Th>
|
65
|
+
))}
|
66
|
+
</Tr>
|
67
|
+
</Thead>
|
68
|
+
<Tbody>
|
69
|
+
{jobs.map(job => (
|
70
|
+
<Tr key={job.id}>
|
71
|
+
<Td>
|
72
|
+
<a
|
73
|
+
onClick={() =>
|
74
|
+
window.tfm.nav.pushUrl(
|
75
|
+
`/job_invocations/${decodeId(job.id)}`
|
76
|
+
)
|
77
|
+
}
|
78
|
+
>
|
79
|
+
{job.description}
|
80
|
+
</a>
|
81
|
+
|
82
|
+
{readablePurpose(job.recurringLogic.purpose)}
|
83
|
+
</Td>
|
84
|
+
<Td>{job.task.result}</Td>
|
85
|
+
<Td>{job.task.state}</Td>
|
86
|
+
<Td>
|
87
|
+
<RelativeDateTime date={job.startAt} />
|
88
|
+
</Td>
|
89
|
+
<Td>{readableCron(job.recurringLogic.cronLine)}</Td>
|
90
|
+
</Tr>
|
91
|
+
))}
|
92
|
+
</Tbody>
|
93
|
+
</TableComposable>
|
94
|
+
</FlexItem>
|
95
|
+
>>>>>>> 5b01704 (Fixes #34458 - Show Hostgroup jobs on the Host Detail page)
|
96
|
+
<FlexItem align={{ default: 'alignRight' }}>
|
97
|
+
<Pagination
|
98
|
+
itemCount={totalCount}
|
99
|
+
page={pagination.page}
|
100
|
+
perPage={pagination.perPage}
|
101
|
+
onSetPage={handlePageSelected}
|
102
|
+
onPerPageSelect={handlePerPageSelected}
|
103
|
+
perPageOptions={perPageOptions}
|
104
|
+
variant="top"
|
105
|
+
/>
|
106
|
+
</FlexItem>
|
107
|
+
</Flex>
|
108
|
+
<TableComposable variant="compact">
|
109
|
+
<Thead>
|
110
|
+
<Tr>
|
111
|
+
{columns.map(col => (
|
112
|
+
<Th key={col}>{col}</Th>
|
113
|
+
))}
|
114
|
+
</Tr>
|
115
|
+
</Thead>
|
116
|
+
<Tbody>
|
117
|
+
{jobs.map(job => (
|
118
|
+
<Tr key={job.id}>
|
119
|
+
<Td>
|
120
|
+
<a
|
121
|
+
onClick={() =>
|
122
|
+
window.tfm.nav.pushUrl(
|
123
|
+
`/job_invocations/${decodeId(job.id)}`
|
124
|
+
)
|
125
|
+
}
|
126
|
+
>
|
127
|
+
{job.description}
|
128
|
+
</a>
|
129
|
+
</Td>
|
130
|
+
<Td>{job.task.result}</Td>
|
131
|
+
<Td>{job.task.state}</Td>
|
132
|
+
<Td>
|
133
|
+
<RelativeDateTime date={job.startAt} />
|
134
|
+
</Td>
|
135
|
+
<Td>{readableCron(job.recurringLogic.cronLine)}</Td>
|
136
|
+
</Tr>
|
137
|
+
))}
|
138
|
+
</Tbody>
|
139
|
+
</TableComposable>
|
140
|
+
</React.Fragment>
|
141
|
+
);
|
142
|
+
};
|
143
|
+
|
144
|
+
PreviousJobsTable.propTypes = {
|
145
|
+
jobs: PropTypes.array.isRequired,
|
146
|
+
history: PropTypes.object.isRequired,
|
147
|
+
totalCount: PropTypes.number.isRequired,
|
148
|
+
pagination: PropTypes.object.isRequired,
|
149
|
+
};
|
150
|
+
|
151
|
+
export default withLoading(PreviousJobsTable);
|
data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js
CHANGED
@@ -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,60 @@ import {
|
|
11
10
|
Th,
|
12
11
|
Td,
|
13
12
|
} from '@patternfly/react-table';
|
14
|
-
|
15
|
-
import
|
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
|
-
|
22
|
-
const AllRolesTable = ({
|
23
|
-
allAnsibleRoles,
|
24
|
-
totalCount,
|
25
|
-
pagination,
|
26
|
-
history,
|
27
|
-
}) => {
|
28
|
-
const columns = [__('Name'), __('Source')];
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
};
|
33
|
-
|
34
|
-
const handlePageSelected = (event, allPage) => {
|
35
|
-
refreshPage(history, { ...pagination, allPage });
|
36
|
-
};
|
37
|
-
|
38
|
-
const perPageOptions = preparePerPageOptions(usePaginationOptions());
|
17
|
+
const AllRolesTable = ({ allAnsibleRoles, totalCount }) => {
|
18
|
+
const columns = [__('Name'), __('Variables'), __('Source')];
|
39
19
|
|
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
|
+
<a
|
42
|
+
href={`/ansible/ansible_variables?search=ansible_role=${role.name}`}
|
43
|
+
target="_blank"
|
44
|
+
rel="noreferrer"
|
45
|
+
>
|
46
|
+
{role.ansibleVariables.totalCount}
|
47
|
+
</a>
|
48
|
+
</Td>
|
49
|
+
|
50
|
+
<Td>
|
51
|
+
{role.inherited
|
52
|
+
? __('Inherited from Hostgroup')
|
53
|
+
: __('Directly assigned to Host')}
|
54
|
+
</Td>
|
55
|
+
</Tr>
|
56
|
+
))}
|
57
|
+
</Tbody>
|
58
|
+
</TableComposable>
|
43
59
|
<FlexItem align={{ default: 'alignRight' }}>
|
44
60
|
<Pagination
|
61
|
+
updateParamsByUrl
|
45
62
|
itemCount={totalCount}
|
46
|
-
|
47
|
-
perPage={pagination.allPerPage}
|
48
|
-
onSetPage={handlePageSelected}
|
49
|
-
onPerPageSelect={handlePerPageSelected}
|
50
|
-
perPageOptions={perPageOptions}
|
51
|
-
variant="top"
|
63
|
+
variant="bottom"
|
52
64
|
/>
|
53
65
|
</FlexItem>
|
54
66
|
</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
67
|
</React.Fragment>
|
79
68
|
);
|
80
69
|
};
|
@@ -82,8 +71,6 @@ const AllRolesTable = ({
|
|
82
71
|
AllRolesTable.propTypes = {
|
83
72
|
allAnsibleRoles: PropTypes.array.isRequired,
|
84
73
|
totalCount: PropTypes.number.isRequired,
|
85
|
-
pagination: PropTypes.object.isRequired,
|
86
|
-
history: PropTypes.object.isRequired,
|
87
74
|
};
|
88
75
|
|
89
76
|
export default withLoading(AllRolesTable);
|
@@ -27,7 +27,7 @@ const AllRolesModal = ({ hostGlobalId, onClose, history }) => {
|
|
27
27
|
),
|
28
28
|
};
|
29
29
|
|
30
|
-
const paginationKeys = { page: '
|
30
|
+
const paginationKeys = { page: 'page', perPage: 'per_page' };
|
31
31
|
|
32
32
|
const wrapper = child => <Modal {...baseModalProps}>{child}</Modal>;
|
33
33
|
|
data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
import React, { useState
|
1
|
+
import React, { useState } from 'react';
|
2
2
|
import { translate as __ } from 'foremanReact/common/I18n';
|
3
3
|
import PropTypes from 'prop-types';
|
4
|
-
|
4
|
+
import { isEqual } from 'lodash';
|
5
5
|
import { useMutation } from '@apollo/client';
|
6
6
|
|
7
7
|
import { Button, Modal, Spinner } from '@patternfly/react-core';
|
@@ -21,17 +21,15 @@ const EditRolesForm = props => {
|
|
21
21
|
actions,
|
22
22
|
} = props;
|
23
23
|
|
24
|
-
const
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
const initAvailableOpt = availableRoles.map(item => item.name);
|
25
|
+
const initChosenOpt = assignedRoles.map(item => item.name);
|
26
|
+
const [availableOptions, setAvailableOptions] = useState(initAvailableOpt);
|
27
|
+
const [chosenOptions, setChosenOptions] = useState(initChosenOpt);
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
});
|
34
|
-
}, [availableRoles, assignedRoles]);
|
29
|
+
const onListChange = (nextAvailable, nextChosen) => {
|
30
|
+
setAvailableOptions(nextAvailable);
|
31
|
+
setChosenOptions(nextChosen);
|
32
|
+
};
|
35
33
|
|
36
34
|
const [callMutation, { loading }] = useMutation(assignAnsibleRoles, {
|
37
35
|
onCompleted: onCompleted(closeModal),
|
@@ -42,15 +40,19 @@ const EditRolesForm = props => {
|
|
42
40
|
|
43
41
|
const variables = {
|
44
42
|
id: encodeId('Host', hostId),
|
45
|
-
ansibleRoleIds: roleNamesToIds(allRoles,
|
43
|
+
ansibleRoleIds: roleNamesToIds(allRoles, chosenOptions),
|
46
44
|
};
|
47
45
|
|
46
|
+
const didNotModifyOptions = () =>
|
47
|
+
isEqual(initAvailableOpt.sort(), availableOptions.sort()) &&
|
48
|
+
isEqual(initChosenOpt, chosenOptions); // The order of the chosen options is important.
|
49
|
+
|
48
50
|
const formActions = [
|
49
51
|
<Button
|
50
52
|
key="confirm"
|
51
53
|
variant="primary"
|
52
54
|
onClick={() => callMutation({ variables })}
|
53
|
-
isDisabled={loading}
|
55
|
+
isDisabled={loading || didNotModifyOptions()}
|
54
56
|
aria-label="submit ansible roles"
|
55
57
|
>
|
56
58
|
{__('Confirm')}
|
@@ -65,14 +67,9 @@ const EditRolesForm = props => {
|
|
65
67
|
return (
|
66
68
|
<Modal {...baseModalProps} actions={formActions}>
|
67
69
|
<DualList
|
68
|
-
availableOptions={
|
69
|
-
chosenOptions={
|
70
|
-
onListChange={
|
71
|
-
setFormState({
|
72
|
-
availableOptions: newAvailable,
|
73
|
-
chosenOptions: newChosen,
|
74
|
-
})
|
75
|
-
}
|
70
|
+
availableOptions={availableOptions}
|
71
|
+
chosenOptions={chosenOptions}
|
72
|
+
onListChange={onListChange}
|
76
73
|
/>
|
77
74
|
</Modal>
|
78
75
|
);
|
@@ -80,11 +77,16 @@ const EditRolesForm = props => {
|
|
80
77
|
|
81
78
|
EditRolesForm.propTypes = {
|
82
79
|
closeModal: PropTypes.func.isRequired,
|
83
|
-
assignedRoles: PropTypes.array
|
84
|
-
availableRoles: PropTypes.array
|
80
|
+
assignedRoles: PropTypes.array,
|
81
|
+
availableRoles: PropTypes.array,
|
85
82
|
actions: PropTypes.array.isRequired,
|
86
83
|
hostId: PropTypes.number.isRequired,
|
87
84
|
baseModalProps: PropTypes.object.isRequired,
|
88
85
|
};
|
89
86
|
|
87
|
+
EditRolesForm.defaultProps = {
|
88
|
+
assignedRoles: [],
|
89
|
+
availableRoles: [],
|
90
|
+
};
|
91
|
+
|
90
92
|
export default withLoading(EditRolesForm);
|
@@ -20,7 +20,7 @@ const EditRolesModal = ({
|
|
20
20
|
canEditHost,
|
21
21
|
}) => {
|
22
22
|
const baseModalProps = {
|
23
|
-
width: '
|
23
|
+
width: '50%',
|
24
24
|
isOpen,
|
25
25
|
className: 'foreman-modal',
|
26
26
|
showClose: false,
|
@@ -54,6 +54,7 @@ const EditRolesModal = ({
|
|
54
54
|
|
55
55
|
const renameData = data => ({
|
56
56
|
availableRoles: data.host.availableAnsibleRoles.nodes,
|
57
|
+
assignedRoles,
|
57
58
|
});
|
58
59
|
|
59
60
|
return (
|
@@ -64,7 +65,7 @@ const EditRolesModal = ({
|
|
64
65
|
baseModalProps={baseModalProps}
|
65
66
|
fetchFn={useFetchFn}
|
66
67
|
renameData={renameData}
|
67
|
-
renamedDataPath="availableRoles"
|
68
|
+
renamedDataPath="availableRoles.assignedRoles"
|
68
69
|
assignedRoles={assignedRoles}
|
69
70
|
closeModal={closeModal}
|
70
71
|
hostId={hostId}
|
@@ -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
|
5
|
+
import Pagination from 'foremanReact/components/Pagination';
|
6
6
|
|
7
7
|
import {
|
8
8
|
TableComposable,
|
@@ -12,37 +12,22 @@ import {
|
|
12
12
|
Th,
|
13
13
|
Td,
|
14
14
|
} from '@patternfly/react-table';
|
15
|
-
import { Flex, FlexItem, Button
|
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,
|
32
27
|
hostGlobalId,
|
33
28
|
canEditHost,
|
34
29
|
}) => {
|
35
|
-
const columns = [__('Name')];
|
36
|
-
|
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());
|
30
|
+
const columns = [__('Name'), __('Variables')];
|
46
31
|
|
47
32
|
const editBtn = canEditHost ? (
|
48
33
|
<FlexItem>
|
@@ -67,36 +52,48 @@ 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
|
+
<Td>
|
76
|
+
<a
|
77
|
+
href={`/ansible/ansible_variables?search=ansible_role=${role.name}`}
|
78
|
+
target="_blank"
|
79
|
+
rel="noreferrer"
|
80
|
+
>
|
81
|
+
{role.ansibleVariables.totalCount}
|
82
|
+
</a>
|
83
|
+
</Td>
|
84
|
+
</Tr>
|
85
|
+
))}
|
86
|
+
</Tbody>
|
87
|
+
</TableComposable>
|
88
|
+
</FlexItem>
|
70
89
|
<FlexItem align={{ default: 'alignRight' }}>
|
71
90
|
<Pagination
|
91
|
+
updateParamsByUrl
|
72
92
|
itemCount={totalCount}
|
73
|
-
|
74
|
-
perPage={pagination.perPage}
|
75
|
-
onSetPage={handlePageSelected}
|
76
|
-
onPerPageSelect={handlePerPageSelected}
|
77
|
-
perPageOptions={perPageOptions}
|
78
|
-
variant="top"
|
93
|
+
variant="bottom"
|
79
94
|
/>
|
80
95
|
</FlexItem>
|
81
96
|
</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
97
|
<Route path="/Ansible/roles/edit">
|
101
98
|
<EditRolesModal
|
102
99
|
closeModal={() => history.goBack()}
|
@@ -123,7 +120,6 @@ RolesTable.propTypes = {
|
|
123
120
|
hostId: PropTypes.number.isRequired,
|
124
121
|
hostGlobalId: PropTypes.string.isRequired,
|
125
122
|
history: PropTypes.object.isRequired,
|
126
|
-
pagination: PropTypes.object.isRequired,
|
127
123
|
totalCount: PropTypes.number.isRequired,
|
128
124
|
canEditHost: PropTypes.bool.isRequired,
|
129
125
|
};
|
@@ -35,6 +35,9 @@ const role1 = {
|
|
35
35
|
id: 'MDE6QW5zaWJsZVJvbGUtMw==',
|
36
36
|
name: 'aardvaark.cube',
|
37
37
|
path: '/ansible/ansible_roles/search="name = aardvaark.cube"',
|
38
|
+
ansibleVariables: {
|
39
|
+
totalCount: 1,
|
40
|
+
},
|
38
41
|
};
|
39
42
|
|
40
43
|
const role2 = {
|
@@ -42,6 +45,9 @@ const role2 = {
|
|
42
45
|
id: 'MDE6QW5zaWJsZVJvbGUtNQ==',
|
43
46
|
name: 'aardvaark.sphere',
|
44
47
|
path: '/ansible/ansible_roles/search="name = aardvaark.sphere"',
|
48
|
+
ansibleVariables: {
|
49
|
+
totalCount: 2,
|
50
|
+
},
|
45
51
|
};
|
46
52
|
|
47
53
|
const role3 = {
|
@@ -49,6 +55,9 @@ const role3 = {
|
|
49
55
|
id: 'MDE6QW5zaWJsZVJvbGUtMzA=',
|
50
56
|
name: 'another.role',
|
51
57
|
path: '/ansible/ansible_roles/search="name = another.role"',
|
58
|
+
ansibleVariables: {
|
59
|
+
totalCount: 3,
|
60
|
+
},
|
52
61
|
};
|
53
62
|
|
54
63
|
const role4 = {
|
@@ -56,6 +65,9 @@ const role4 = {
|
|
56
65
|
id: 'MDE6QW5zaWJsZVJvbGUtMzk=',
|
57
66
|
name: 'geerlingguy.ceylon',
|
58
67
|
path: '/ansible/ansible_roles/search="name = geerlingguy.ceylon"',
|
68
|
+
ansibleVariables: {
|
69
|
+
totalCount: 4,
|
70
|
+
},
|
59
71
|
};
|
60
72
|
|
61
73
|
const ansibleRolesMock = {
|
@@ -77,30 +89,45 @@ const availableRoles = {
|
|
77
89
|
name: 'theforeman.foreman_scap_client',
|
78
90
|
path:
|
79
91
|
'/ansible/ansible_roles/search="name = theforeman.foreman_scap_client"',
|
92
|
+
ansibleVariables: {
|
93
|
+
totalCount: 23,
|
94
|
+
},
|
80
95
|
},
|
81
96
|
{
|
82
97
|
__typename: 'AnsibleRole',
|
83
98
|
id: 'MDE6QW5zaWJsZVJvbGUtMg==',
|
84
99
|
name: 'adriagalin.motd',
|
85
100
|
path: '/ansible/ansible_roles/search="name = adriagalin.motd"',
|
101
|
+
ansibleVariables: {
|
102
|
+
totalCount: 23,
|
103
|
+
},
|
86
104
|
},
|
87
105
|
{
|
88
106
|
__typename: 'AnsibleRole',
|
89
107
|
id: 'MDE6QW5zaWJsZVJvbGUtMjI=',
|
90
108
|
name: 'geerlingguy.php',
|
91
109
|
path: '/ansible/ansible_roles/search="name = geerlingguy.php"',
|
110
|
+
ansibleVariables: {
|
111
|
+
totalCount: 23,
|
112
|
+
},
|
92
113
|
},
|
93
114
|
{
|
94
115
|
__typename: 'AnsibleRole',
|
95
116
|
id: 'MDE6QW5zaWJsZVJvbGUtNTc=',
|
96
117
|
name: 'robertdebock.epel',
|
97
118
|
path: '/ansible/ansible_roles/search="name = robertdebock.epel"',
|
119
|
+
ansibleVariables: {
|
120
|
+
totalCount: 23,
|
121
|
+
},
|
98
122
|
},
|
99
123
|
{
|
100
124
|
__typename: 'AnsibleRole',
|
101
125
|
id: 'MDE6QW5zaWJsZVJvbGUtNTg=',
|
102
126
|
name: 'geerlingguy.nfs',
|
103
127
|
path: '/ansible/ansible_roles/search="name = geerlingguy.nfs"',
|
128
|
+
ansibleVariables: {
|
129
|
+
totalCount: 23,
|
130
|
+
},
|
104
131
|
},
|
105
132
|
],
|
106
133
|
};
|
@@ -118,6 +145,9 @@ export const allRolesMocks = allAnsibleRolesMockFactory(
|
|
118
145
|
name: 'adriagalin.motd',
|
119
146
|
path: '/ansible/ansible_roles/search="name = adriagalin.motd"',
|
120
147
|
inherited: true,
|
148
|
+
ansibleVariables: {
|
149
|
+
totalCount: 23,
|
150
|
+
},
|
121
151
|
},
|
122
152
|
{ ...role1, inherited: false },
|
123
153
|
{ ...role2, inherited: false },
|