foreman_puppet 11.0.0 → 11.2.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/foreman_puppet/locale/ca/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/cs_CZ/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/de/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/en/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/en_GB/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/es/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/fr/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/gl/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/it/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/ja/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/ka/foreman_puppet.js +192 -12
- data/app/assets/javascripts/foreman_puppet/locale/ko/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/nl_NL/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/pl/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/pt_BR/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/ru/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/sv_SE/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/zh_CN/foreman_puppet.js +181 -1
- data/app/assets/javascripts/foreman_puppet/locale/zh_TW/foreman_puppet.js +181 -1
- data/app/controllers/concerns/foreman_puppet/extensions/hosts_controller_extensions.rb +1 -1
- data/app/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller.rb +75 -1
- data/app/models/foreman_puppet/config_group.rb +3 -1
- data/app/models/foreman_puppet/host_config_group.rb +12 -0
- data/app/models/foreman_puppet/puppetclass.rb +14 -3
- data/app/services/concerns/foreman_puppet/extensions/bulk_hosts_manager.rb +18 -0
- data/config/api_routes.rb +1 -0
- data/db/seeds.d/111_puppet_proxy_feature.rb +1 -1
- data/lib/foreman_puppet/register.rb +1 -0
- data/lib/foreman_puppet/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/ca/foreman_puppet.po +187 -1
- data/locale/cs_CZ/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/cs_CZ/foreman_puppet.po +187 -1
- data/locale/de/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/de/foreman_puppet.po +188 -2
- data/locale/en/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/en/foreman_puppet.po +187 -1
- data/locale/en_GB/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/en_GB/foreman_puppet.po +187 -1
- data/locale/es/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/es/foreman_puppet.po +187 -1
- data/locale/foreman_puppet.pot +312 -13
- data/locale/fr/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/fr/foreman_puppet.po +187 -1
- data/locale/gl/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/gl/foreman_puppet.po +187 -1
- data/locale/it/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/it/foreman_puppet.po +187 -1
- data/locale/ja/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/ja/foreman_puppet.po +187 -1
- data/locale/ka/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/ka/foreman_puppet.po +199 -13
- data/locale/ko/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/ko/foreman_puppet.po +187 -1
- data/locale/nl_NL/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/nl_NL/foreman_puppet.po +187 -1
- data/locale/pl/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/pl/foreman_puppet.po +187 -1
- data/locale/pt_BR/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/pt_BR/foreman_puppet.po +187 -1
- data/locale/ru/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/ru/foreman_puppet.po +187 -1
- data/locale/sv_SE/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/sv_SE/foreman_puppet.po +187 -1
- data/locale/zh_CN/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/zh_CN/foreman_puppet.po +187 -1
- data/locale/zh_TW/LC_MESSAGES/foreman_puppet.mo +0 -0
- data/locale/zh_TW/foreman_puppet.po +187 -1
- data/test/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller_test.rb +93 -0
- data/test/models/foreman_puppet/host_test.rb +50 -0
- data/test/models/foreman_puppet/hostgroup_test.rb +50 -0
- data/test/services/foreman_puppet/bulk_hosts_manager_test.rb +45 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +8 -0
- data/webpack/global_index.js +18 -1
- data/webpack/src/Extends/Hosts/ActionsBar/index.js +20 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/__tests__/actions.test.js +0 -7
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/BulkChangePuppetEnvironmentModal.js +239 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/BulkChangePuppetEnvironmentModal.test.js +155 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/actions.test.js +49 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/actions.js +37 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/__tests__/index.test.js +160 -47
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/__tests__/actions.test.js +0 -6
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/__tests__/index.test.js +136 -39
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/BulkRemovePuppetEnvironmentModal.js +148 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/BulkRemovePuppetEnvironmentModal.test.js +80 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/__tests__/index.test.js +123 -34
- data/webpack/src/Router/routes.fixtures.js +13 -0
- data/webpack/src/Router/routes.test.js +68 -8
- data/webpack/src/foreman_puppet_host_form.test.js +3 -1
- data/webpack/test_setup.js +1 -0
- metadata +14 -3
- data/webpack/src/Router/__snapshots__/routes.test.js.snap +0 -3
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
5
|
+
import {
|
|
6
|
+
Modal,
|
|
7
|
+
Button,
|
|
8
|
+
TextContent,
|
|
9
|
+
Text,
|
|
10
|
+
Select,
|
|
11
|
+
SelectOption,
|
|
12
|
+
SelectList,
|
|
13
|
+
MenuToggle,
|
|
14
|
+
} from '@patternfly/react-core';
|
|
15
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
16
|
+
import { addToast } from 'foremanReact/components/ToastsList/slice';
|
|
17
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
|
18
|
+
import {
|
|
19
|
+
selectAPIStatus,
|
|
20
|
+
selectAPIResponse,
|
|
21
|
+
} from 'foremanReact/redux/API/APISelectors';
|
|
22
|
+
import { STATUS } from 'foremanReact/constants';
|
|
23
|
+
import { bulkActionErrorToastParams } from '../toastHelpers';
|
|
24
|
+
import {
|
|
25
|
+
fetchEnvironments,
|
|
26
|
+
bulkChangePuppetEnvironment,
|
|
27
|
+
PUPPET_ENVIRONMENTS_KEY,
|
|
28
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
29
|
+
INHERIT_ENVIRONMENT,
|
|
30
|
+
} from './actions';
|
|
31
|
+
|
|
32
|
+
const BulkChangePuppetEnvironmentModal = ({
|
|
33
|
+
isOpen,
|
|
34
|
+
closeModal,
|
|
35
|
+
selectAllHostsMode,
|
|
36
|
+
selectedCount,
|
|
37
|
+
fetchBulkParams,
|
|
38
|
+
onSuccess: onSuccessCallback,
|
|
39
|
+
}) => {
|
|
40
|
+
const dispatch = useDispatch();
|
|
41
|
+
const [environmentId, setEnvironmentId] = useState(null);
|
|
42
|
+
const [environmentSelectOpen, setEnvironmentSelectOpen] = useState(false);
|
|
43
|
+
const currentOrganization = useForemanOrganization();
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
dispatch(fetchEnvironments(currentOrganization?.id));
|
|
47
|
+
}, [dispatch, currentOrganization?.id]);
|
|
48
|
+
|
|
49
|
+
const environments = useSelector(state =>
|
|
50
|
+
selectAPIResponse(state, PUPPET_ENVIRONMENTS_KEY)
|
|
51
|
+
);
|
|
52
|
+
const environmentsStatus = useSelector(state =>
|
|
53
|
+
selectAPIStatus(state, PUPPET_ENVIRONMENTS_KEY)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const onToggleClick = () => {
|
|
57
|
+
setEnvironmentSelectOpen(!environmentSelectOpen);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleEnvironmentSelect = (event, selection) => {
|
|
61
|
+
setEnvironmentId(selection);
|
|
62
|
+
setEnvironmentSelectOpen(false);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getEnvironmentLabel = value => {
|
|
66
|
+
if (value === INHERIT_ENVIRONMENT) return __('*Inherit from host group*');
|
|
67
|
+
|
|
68
|
+
const selectedEnvironment = environments?.results?.find(
|
|
69
|
+
environment => `${environment.id}` === value
|
|
70
|
+
);
|
|
71
|
+
return selectedEnvironment?.name || __('Select an Environment');
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const toggle = toggleRef => (
|
|
75
|
+
<MenuToggle
|
|
76
|
+
ouiaId="bulk-change-env-common-select-toggle"
|
|
77
|
+
ref={toggleRef}
|
|
78
|
+
onClick={onToggleClick}
|
|
79
|
+
isExpanded={environmentSelectOpen}
|
|
80
|
+
style={{ width: '500px' }}
|
|
81
|
+
>
|
|
82
|
+
{environmentId
|
|
83
|
+
? getEnvironmentLabel(environmentId)
|
|
84
|
+
: __('Select an Environment')}
|
|
85
|
+
</MenuToggle>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const handleModalClose = () => {
|
|
89
|
+
setEnvironmentId(null);
|
|
90
|
+
closeModal();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleError = response => {
|
|
94
|
+
handleModalClose();
|
|
95
|
+
dispatch(
|
|
96
|
+
addToast(
|
|
97
|
+
bulkActionErrorToastParams(
|
|
98
|
+
response,
|
|
99
|
+
__('Failed to change Puppet Environment'),
|
|
100
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handleSuccess = response => {
|
|
107
|
+
dispatch(
|
|
108
|
+
addToast({
|
|
109
|
+
type: 'success',
|
|
110
|
+
message: response.data.message,
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
try {
|
|
114
|
+
if (onSuccessCallback) onSuccessCallback();
|
|
115
|
+
} finally {
|
|
116
|
+
handleModalClose();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const handleConfirm = () => {
|
|
121
|
+
const requestBody = {
|
|
122
|
+
included: {
|
|
123
|
+
search: fetchBulkParams(),
|
|
124
|
+
},
|
|
125
|
+
environment_id: environmentId,
|
|
126
|
+
organization_id: currentOrganization?.id,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
dispatch(
|
|
130
|
+
bulkChangePuppetEnvironment(requestBody, handleSuccess, handleError)
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const modalActions = [
|
|
135
|
+
<Button
|
|
136
|
+
key="add"
|
|
137
|
+
ouiaId="bulk-change-environment-modal-add-button"
|
|
138
|
+
variant="primary"
|
|
139
|
+
onClick={handleConfirm}
|
|
140
|
+
isDisabled={environmentId === null}
|
|
141
|
+
isLoading={environmentsStatus === STATUS.PENDING}
|
|
142
|
+
>
|
|
143
|
+
{__('Change Puppet Environment')}
|
|
144
|
+
</Button>,
|
|
145
|
+
<Button
|
|
146
|
+
key="cancel"
|
|
147
|
+
ouiaId="bulk-change-environment-modal-cancel-button"
|
|
148
|
+
variant="link"
|
|
149
|
+
onClick={handleModalClose}
|
|
150
|
+
>
|
|
151
|
+
{__('Cancel')}
|
|
152
|
+
</Button>,
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<Modal
|
|
157
|
+
isOpen={isOpen}
|
|
158
|
+
onClose={handleModalClose}
|
|
159
|
+
onEscapePress={handleModalClose}
|
|
160
|
+
title={__('Change Puppet Environment')}
|
|
161
|
+
width="50%"
|
|
162
|
+
position="top"
|
|
163
|
+
actions={modalActions}
|
|
164
|
+
id="bulk-change-puppet-environment"
|
|
165
|
+
key="bulk-change-puppet-environment"
|
|
166
|
+
ouiaId="bulk-change-puppet-environment"
|
|
167
|
+
>
|
|
168
|
+
<TextContent>
|
|
169
|
+
<Text ouiaId="bulk-change-puppet-environment-options">
|
|
170
|
+
{selectAllHostsMode ? (
|
|
171
|
+
<FormattedMessage
|
|
172
|
+
id="bulk-change-puppet-environment-warning-message-all"
|
|
173
|
+
defaultMessage={__(
|
|
174
|
+
'Changing the Puppet environment will affect {boldCount} selected hosts. Some hosts may already have been associated with the selected environment.'
|
|
175
|
+
)}
|
|
176
|
+
values={{
|
|
177
|
+
boldCount: <strong>{__('All')}</strong>,
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
) : (
|
|
181
|
+
<FormattedMessage
|
|
182
|
+
id="bulk-change-puppet-environment-warning-message"
|
|
183
|
+
defaultMessage={__(
|
|
184
|
+
'Changing the Puppet environment will affect {boldCount} selected {count, plural, one {host} other {hosts}}. Some hosts may already have been associated with the selected environment.'
|
|
185
|
+
)}
|
|
186
|
+
values={{
|
|
187
|
+
count: selectedCount,
|
|
188
|
+
boldCount: <strong>{selectedCount}</strong>,
|
|
189
|
+
}}
|
|
190
|
+
/>
|
|
191
|
+
)}
|
|
192
|
+
</Text>
|
|
193
|
+
</TextContent>
|
|
194
|
+
{environmentsStatus === STATUS.RESOLVED && (
|
|
195
|
+
<Select
|
|
196
|
+
id="bulk-change-puppet-environment-select"
|
|
197
|
+
isOpen={environmentSelectOpen}
|
|
198
|
+
selected={environmentId}
|
|
199
|
+
onSelect={handleEnvironmentSelect}
|
|
200
|
+
onOpenChange={isSelectOpen => setEnvironmentSelectOpen(isSelectOpen)}
|
|
201
|
+
toggle={toggle}
|
|
202
|
+
shouldFocusToggleOnSelect
|
|
203
|
+
ouiaId="bulk-change-puppet-environment-select"
|
|
204
|
+
>
|
|
205
|
+
<SelectList>
|
|
206
|
+
<SelectOption value={INHERIT_ENVIRONMENT}>
|
|
207
|
+
{__('*Inherit from host group*')}
|
|
208
|
+
</SelectOption>
|
|
209
|
+
{environments?.results?.map(environment => (
|
|
210
|
+
<SelectOption
|
|
211
|
+
key={`${environment.id}`}
|
|
212
|
+
value={`${environment.id}`}
|
|
213
|
+
>
|
|
214
|
+
{environment.name}
|
|
215
|
+
</SelectOption>
|
|
216
|
+
))}
|
|
217
|
+
</SelectList>
|
|
218
|
+
</Select>
|
|
219
|
+
)}
|
|
220
|
+
</Modal>
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
BulkChangePuppetEnvironmentModal.propTypes = {
|
|
225
|
+
isOpen: PropTypes.bool,
|
|
226
|
+
closeModal: PropTypes.func,
|
|
227
|
+
fetchBulkParams: PropTypes.func.isRequired,
|
|
228
|
+
onSuccess: PropTypes.func,
|
|
229
|
+
selectedCount: PropTypes.number.isRequired,
|
|
230
|
+
selectAllHostsMode: PropTypes.bool.isRequired,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
BulkChangePuppetEnvironmentModal.defaultProps = {
|
|
234
|
+
isOpen: false,
|
|
235
|
+
closeModal: () => {},
|
|
236
|
+
onSuccess: undefined,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export default BulkChangePuppetEnvironmentModal;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import { IntlProvider } from 'react-intl';
|
|
5
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
6
|
+
|
|
7
|
+
import BulkChangePuppetEnvironmentModal from '../BulkChangePuppetEnvironmentModal';
|
|
8
|
+
import { fetchEnvironments, bulkChangePuppetEnvironment } from '../actions';
|
|
9
|
+
import {
|
|
10
|
+
selectAPIResponse,
|
|
11
|
+
selectAPIStatus,
|
|
12
|
+
} from 'foremanReact/redux/API/APISelectors';
|
|
13
|
+
|
|
14
|
+
jest.mock('@patternfly/react-core', () => {
|
|
15
|
+
const React = require('react');
|
|
16
|
+
const actual = jest.requireActual('@patternfly/react-core');
|
|
17
|
+
|
|
18
|
+
const MenuToggle = React.forwardRef(({ children, onClick }, ref) => (
|
|
19
|
+
<button type="button" ref={ref} onClick={onClick}>
|
|
20
|
+
{children}
|
|
21
|
+
</button>
|
|
22
|
+
));
|
|
23
|
+
|
|
24
|
+
const SelectOption = ({ children, value, onSelect }) => (
|
|
25
|
+
<button type="button" onClick={event => onSelect(event, value)}>
|
|
26
|
+
{children}
|
|
27
|
+
</button>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const SelectList = ({ children, onSelect }) => (
|
|
31
|
+
<div>
|
|
32
|
+
{React.Children.map(children, child =>
|
|
33
|
+
React.isValidElement(child)
|
|
34
|
+
? React.cloneElement(child, { onSelect })
|
|
35
|
+
: child
|
|
36
|
+
)}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const Select = ({ children, isOpen, toggle, onSelect }) => (
|
|
41
|
+
<div>
|
|
42
|
+
{toggle()}
|
|
43
|
+
{isOpen &&
|
|
44
|
+
React.Children.map(children, child =>
|
|
45
|
+
React.isValidElement(child)
|
|
46
|
+
? React.cloneElement(child, { onSelect })
|
|
47
|
+
: child
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
...actual,
|
|
54
|
+
MenuToggle,
|
|
55
|
+
Select,
|
|
56
|
+
SelectList,
|
|
57
|
+
SelectOption,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
jest.mock('react-redux', () => ({
|
|
62
|
+
...jest.requireActual('react-redux'),
|
|
63
|
+
useDispatch: jest.fn(),
|
|
64
|
+
useSelector: jest.fn(),
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
jest.mock('foremanReact/Root/Context/ForemanContext', () => ({
|
|
68
|
+
useForemanOrganization: jest.fn(() => ({ id: 23 })),
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
jest.mock('foremanReact/redux/API/APISelectors', () => ({
|
|
72
|
+
selectAPIResponse: jest.fn(),
|
|
73
|
+
selectAPIStatus: jest.fn(),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
jest.mock('../actions', () => ({
|
|
77
|
+
fetchEnvironments: jest.fn(() => ({ type: 'FETCH_ENVIRONMENTS' })),
|
|
78
|
+
bulkChangePuppetEnvironment: jest.fn(() => ({
|
|
79
|
+
type: 'BULK_CHANGE_PUPPET_ENVIRONMENT',
|
|
80
|
+
})),
|
|
81
|
+
PUPPET_ENVIRONMENTS_KEY: 'PUPPET_ENVIRONMENTS_KEY',
|
|
82
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY: 'BULK_CHANGE_PUPPET_ENVIRONMENT',
|
|
83
|
+
INHERIT_ENVIRONMENT: 'inherit',
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
describe('BulkChangePuppetEnvironmentModal', () => {
|
|
87
|
+
const dispatch = jest.fn();
|
|
88
|
+
const fetchBulkParams = jest.fn(
|
|
89
|
+
() => 'organization = "Default Organization"'
|
|
90
|
+
);
|
|
91
|
+
const environmentsResponse = {
|
|
92
|
+
results: [{ id: 1, name: 'production' }],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const renderComponent = () =>
|
|
96
|
+
render(
|
|
97
|
+
<IntlProvider locale="en">
|
|
98
|
+
<BulkChangePuppetEnvironmentModal
|
|
99
|
+
isOpen
|
|
100
|
+
closeModal={jest.fn()}
|
|
101
|
+
fetchBulkParams={fetchBulkParams}
|
|
102
|
+
selectedCount={2}
|
|
103
|
+
selectAllHostsMode={false}
|
|
104
|
+
/>
|
|
105
|
+
</IntlProvider>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
beforeEach(() => {
|
|
109
|
+
jest.clearAllMocks();
|
|
110
|
+
useDispatch.mockReturnValue(dispatch);
|
|
111
|
+
selectAPIResponse.mockReturnValue(environmentsResponse);
|
|
112
|
+
selectAPIStatus.mockReturnValue('RESOLVED');
|
|
113
|
+
useSelector.mockImplementation(selector => selector({}));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('renders the environment options', () => {
|
|
117
|
+
renderComponent();
|
|
118
|
+
|
|
119
|
+
expect(fetchEnvironments).toHaveBeenCalledWith(23);
|
|
120
|
+
expect(
|
|
121
|
+
screen.getAllByText('Change Puppet Environment')[0]
|
|
122
|
+
).toBeInTheDocument();
|
|
123
|
+
expect(
|
|
124
|
+
screen.getByRole('button', { name: 'Select an Environment' })
|
|
125
|
+
).toBeInTheDocument();
|
|
126
|
+
expect(
|
|
127
|
+
screen.getByText(/Changing the Puppet environment will affect/)
|
|
128
|
+
).toBeInTheDocument();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('submits organization scope with the bulk change request', () => {
|
|
132
|
+
renderComponent();
|
|
133
|
+
|
|
134
|
+
fireEvent.click(
|
|
135
|
+
screen.getByRole('button', { name: 'Select an Environment' })
|
|
136
|
+
);
|
|
137
|
+
expect(screen.getByText('*Inherit from host group*')).toBeInTheDocument();
|
|
138
|
+
fireEvent.click(screen.getByText('production'));
|
|
139
|
+
fireEvent.click(
|
|
140
|
+
screen.getByRole('button', { name: 'Change Puppet Environment' })
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
expect(bulkChangePuppetEnvironment).toHaveBeenCalledWith(
|
|
144
|
+
{
|
|
145
|
+
included: {
|
|
146
|
+
search: 'organization = "Default Organization"',
|
|
147
|
+
},
|
|
148
|
+
environment_id: '1',
|
|
149
|
+
organization_id: 23,
|
|
150
|
+
},
|
|
151
|
+
expect.any(Function),
|
|
152
|
+
expect.any(Function)
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
});
|
data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/actions.test.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { APIActions } from 'foremanReact/redux/API';
|
|
2
|
+
import {
|
|
3
|
+
fetchEnvironments,
|
|
4
|
+
PUPPET_ENVIRONMENTS_KEY,
|
|
5
|
+
bulkChangePuppetEnvironment,
|
|
6
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
7
|
+
} from '../actions';
|
|
8
|
+
|
|
9
|
+
jest.mock('foremanReact/redux/API', () => ({
|
|
10
|
+
APIActions: {
|
|
11
|
+
get: jest.fn(),
|
|
12
|
+
put: jest.fn(),
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
describe('BulkChangePuppetEnvironment actions', () => {
|
|
17
|
+
const environmentsUrl = '/foreman_puppet/api/v2/environments';
|
|
18
|
+
const bulkChangeUrl = '/api/v2/hosts/bulk/change_puppet_environment';
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
jest.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('fetches environments', () => {
|
|
25
|
+
fetchEnvironments(23);
|
|
26
|
+
|
|
27
|
+
expect(APIActions.get).toHaveBeenCalledWith({
|
|
28
|
+
key: PUPPET_ENVIRONMENTS_KEY,
|
|
29
|
+
url: environmentsUrl,
|
|
30
|
+
params: { per_page: 'all', organization_id: 23 },
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('calls bulk change puppet environment endpoint', () => {
|
|
35
|
+
const params = { included: { ids: [1] }, environment_id: '1' };
|
|
36
|
+
const handleSuccess = jest.fn();
|
|
37
|
+
const handleError = jest.fn();
|
|
38
|
+
|
|
39
|
+
bulkChangePuppetEnvironment(params, handleSuccess, handleError);
|
|
40
|
+
|
|
41
|
+
expect(APIActions.put).toHaveBeenCalledWith({
|
|
42
|
+
key: BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
43
|
+
url: bulkChangeUrl,
|
|
44
|
+
handleSuccess,
|
|
45
|
+
handleError,
|
|
46
|
+
params,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/index.test.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
|
|
4
|
+
import { useBulkModalOpen } from 'foremanReact/common/BulkModalStateHelper';
|
|
5
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
|
6
|
+
|
|
7
|
+
import BulkChangePuppetEnvironmentScene from '../index';
|
|
8
|
+
import BulkChangePuppetEnvironmentModal from '../BulkChangePuppetEnvironmentModal';
|
|
9
|
+
|
|
10
|
+
jest.mock('foremanReact/common/BulkModalStateHelper', () => ({
|
|
11
|
+
useBulkModalOpen: jest.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
jest.mock('../BulkChangePuppetEnvironmentModal', () => ({
|
|
15
|
+
__esModule: true,
|
|
16
|
+
default: jest.fn(() => null),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
describe('BulkChangePuppetEnvironmentScene', () => {
|
|
20
|
+
const fetchBulkParams = jest.fn();
|
|
21
|
+
const refreshTableData = jest.fn();
|
|
22
|
+
const contextValue = {
|
|
23
|
+
selectAllHostsMode: false,
|
|
24
|
+
selectedCount: 2,
|
|
25
|
+
selectedResults: [1, 2],
|
|
26
|
+
fetchBulkParams,
|
|
27
|
+
refreshTableData,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
useBulkModalOpen.mockReturnValue({
|
|
33
|
+
isOpen: true,
|
|
34
|
+
close: jest.fn(),
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('opens with bulk modal state and passes expected props', () => {
|
|
39
|
+
let component;
|
|
40
|
+
act(() => {
|
|
41
|
+
component = renderer.create(
|
|
42
|
+
<ForemanActionsBarContext.Provider value={contextValue}>
|
|
43
|
+
<BulkChangePuppetEnvironmentScene />
|
|
44
|
+
</ForemanActionsBarContext.Provider>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const componentType =
|
|
49
|
+
BulkChangePuppetEnvironmentModal.default ||
|
|
50
|
+
BulkChangePuppetEnvironmentModal;
|
|
51
|
+
const { props } = component.root.findByType(componentType);
|
|
52
|
+
|
|
53
|
+
expect(props).toEqual(
|
|
54
|
+
expect.objectContaining({
|
|
55
|
+
fetchBulkParams,
|
|
56
|
+
selectedCount: 2,
|
|
57
|
+
selectAllHostsMode: false,
|
|
58
|
+
isOpen: true,
|
|
59
|
+
closeModal: expect.any(Function),
|
|
60
|
+
onSuccess: refreshTableData,
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
component.unmount();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { APIActions } from 'foremanReact/redux/API';
|
|
2
|
+
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
3
|
+
|
|
4
|
+
export const PUPPET_ENVIRONMENTS_KEY = 'PUPPET_ENVIRONMENTS_KEY';
|
|
5
|
+
export const BULK_CHANGE_PUPPET_ENVIRONMENT_KEY =
|
|
6
|
+
'BULK_CHANGE_PUPPET_ENVIRONMENT';
|
|
7
|
+
|
|
8
|
+
export const INHERIT_ENVIRONMENT = 'inherit';
|
|
9
|
+
|
|
10
|
+
export const fetchEnvironments = organizationId => {
|
|
11
|
+
const url = foremanUrl('/foreman_puppet/api/v2/environments');
|
|
12
|
+
return APIActions.get({
|
|
13
|
+
key: PUPPET_ENVIRONMENTS_KEY,
|
|
14
|
+
url,
|
|
15
|
+
params: {
|
|
16
|
+
per_page: 'all',
|
|
17
|
+
...(organizationId ? { organization_id: organizationId } : {}),
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const bulkChangePuppetEnvironment = (
|
|
23
|
+
params,
|
|
24
|
+
handleSuccess,
|
|
25
|
+
handleError
|
|
26
|
+
) => {
|
|
27
|
+
const url = foremanUrl('/api/v2/hosts/bulk/change_puppet_environment');
|
|
28
|
+
return APIActions.put({
|
|
29
|
+
key: BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
30
|
+
url,
|
|
31
|
+
handleSuccess,
|
|
32
|
+
handleError,
|
|
33
|
+
params,
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default fetchEnvironments;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
|
3
|
+
import { useBulkModalOpen } from 'foremanReact/common/BulkModalStateHelper';
|
|
4
|
+
import BulkChangePuppetEnvironmentModal from './BulkChangePuppetEnvironmentModal';
|
|
5
|
+
|
|
6
|
+
const BulkChangePuppetEnvironmentScene = () => {
|
|
7
|
+
const {
|
|
8
|
+
selectAllHostsMode,
|
|
9
|
+
selectedCount,
|
|
10
|
+
fetchBulkParams,
|
|
11
|
+
refreshTableData,
|
|
12
|
+
} = useContext(ForemanActionsBarContext);
|
|
13
|
+
const { isOpen, close: closeModal } = useBulkModalOpen(
|
|
14
|
+
'bulk-change-puppet-environment'
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<BulkChangePuppetEnvironmentModal
|
|
19
|
+
fetchBulkParams={fetchBulkParams}
|
|
20
|
+
selectedCount={selectedCount}
|
|
21
|
+
selectAllHostsMode={selectAllHostsMode}
|
|
22
|
+
isOpen={isOpen}
|
|
23
|
+
closeModal={closeModal}
|
|
24
|
+
onSuccess={refreshTableData}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { BulkChangePuppetEnvironmentModal };
|
|
30
|
+
export default BulkChangePuppetEnvironmentScene;
|