foreman_remote_execution 4.5.6 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/job_invocations_controller.rb +1 -1
- data/app/controllers/ui_job_wizard_controller.rb +0 -7
- data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +1 -5
- data/app/helpers/remote_execution_helper.rb +3 -9
- data/app/lib/actions/remote_execution/run_host_job.rb +1 -5
- data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +0 -2
- data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +70 -0
- data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +0 -6
- data/app/models/host_status/execution_status.rb +3 -3
- data/app/models/job_invocation.rb +6 -9
- data/app/models/job_invocation_composer.rb +4 -4
- data/app/models/remote_execution_feature.rb +1 -5
- data/app/models/remote_execution_provider.rb +2 -3
- data/app/models/setting/remote_execution.rb +2 -2
- data/app/models/targeting.rb +1 -5
- data/app/views/job_invocations/index.html.erb +1 -1
- data/app/views/templates/ssh/module_action.erb +0 -1
- data/app/views/templates/ssh/power_action.erb +0 -2
- data/app/views/templates/ssh/puppet_run_once.erb +0 -1
- data/foreman_remote_execution.gemspec +0 -1
- data/lib/foreman_remote_execution/engine.rb +2 -0
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/models/orchestration/ssh_test.rb +56 -0
- data/test/unit/job_invocation_composer_test.rb +1 -14
- data/test/unit/job_invocation_test.rb +1 -1
- data/test/unit/remote_execution_provider_test.rb +0 -12
- data/webpack/JobWizard/JobWizard.js +16 -59
- data/webpack/JobWizard/JobWizard.scss +0 -58
- data/webpack/JobWizard/JobWizardConstants.js +0 -18
- data/webpack/JobWizard/JobWizardSelectors.js +0 -9
- data/webpack/JobWizard/__tests__/JobWizard.test.js +13 -0
- data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +32 -0
- data/webpack/JobWizard/__tests__/fixtures.js +2 -112
- data/webpack/JobWizard/__tests__/integration.test.js +92 -16
- data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +9 -37
- data/webpack/JobWizard/steps/AdvancedFields/Fields.js +55 -116
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +16 -150
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +249 -0
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +2 -4
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +51 -123
- data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +113 -0
- data/webpack/JobWizard/steps/form/FormHelpers.js +0 -1
- data/webpack/JobWizard/steps/form/SelectField.js +2 -14
- data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +38 -0
- data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +23 -0
- data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +37 -0
- data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +23 -0
- data/webpack/__mocks__/foremanReact/components/SearchBar.js +1 -18
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +0 -1
- metadata +13 -35
- data/app/models/host_proxy_invocation.rb +0 -4
- data/db/migrate/2021051713291621250977_add_host_proxy_invocations.rb +0 -12
- data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +0 -67
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/DescriptionField.test.js +0 -23
- data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +0 -25
- data/webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js +0 -23
- data/webpack/JobWizard/steps/HostsAndInputs/__tests__/SelectedChips.test.js +0 -37
- data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +0 -50
- data/webpack/JobWizard/steps/HostsAndInputs/index.js +0 -66
- data/webpack/JobWizard/steps/Schedule/QueryType.js +0 -48
- data/webpack/JobWizard/steps/Schedule/RepeatOn.js +0 -61
- data/webpack/JobWizard/steps/Schedule/ScheduleType.js +0 -25
- data/webpack/JobWizard/steps/Schedule/StartEndDates.js +0 -51
- data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +0 -22
- data/webpack/JobWizard/steps/Schedule/index.js +0 -44
- data/webpack/JobWizard/steps/form/Formatter.js +0 -150
- data/webpack/JobWizard/steps/form/NumberInput.js +0 -35
- data/webpack/JobWizard/steps/form/WizardTitle.js +0 -14
- data/webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example +0 -76
@@ -1,10 +1,8 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
|
-
import { FormGroup, TextInput
|
3
|
+
import { FormGroup, TextInput } from '@patternfly/react-core';
|
4
4
|
import { translate as __ } from 'foremanReact/common/I18n';
|
5
5
|
import { helpLabel } from '../form/FormHelpers';
|
6
|
-
import { formatter } from '../form/Formatter';
|
7
|
-
import { NumberInput } from '../form/NumberInput';
|
8
6
|
|
9
7
|
export const EffectiveUserField = ({ value, setValue }) => (
|
10
8
|
<FormGroup
|
@@ -18,7 +16,6 @@ export const EffectiveUserField = ({ value, setValue }) => (
|
|
18
16
|
fieldId="effective-user"
|
19
17
|
>
|
20
18
|
<TextInput
|
21
|
-
aria-label="effective user"
|
22
19
|
autoComplete="effective-user"
|
23
20
|
id="effective-user"
|
24
21
|
type="text"
|
@@ -29,25 +26,25 @@ export const EffectiveUserField = ({ value, setValue }) => (
|
|
29
26
|
);
|
30
27
|
|
31
28
|
export const TimeoutToKillField = ({ value, setValue }) => (
|
32
|
-
<
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
'Time in seconds from the start on the remote host after which the job should be killed.'
|
38
|
-
),
|
39
|
-
'timeout-to-kill'
|
29
|
+
<FormGroup
|
30
|
+
label={__('Timeout to kill')}
|
31
|
+
labelIcon={helpLabel(
|
32
|
+
__(
|
33
|
+
'Time in seconds from the start on the remote host after which the job should be killed.'
|
40
34
|
),
|
41
|
-
|
42
|
-
}
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
35
|
+
'timeout-to-kill'
|
36
|
+
)}
|
37
|
+
fieldId="timeout-to-kill"
|
38
|
+
>
|
39
|
+
<TextInput
|
40
|
+
type="number"
|
41
|
+
value={value}
|
42
|
+
placeholder={__('For example: 1, 2, 3, 4, 5...')}
|
43
|
+
autoComplete="timeout-to-kill"
|
44
|
+
id="timeout-to-kill"
|
45
|
+
onChange={newValue => setValue(newValue)}
|
46
|
+
/>
|
47
|
+
</FormGroup>
|
51
48
|
);
|
52
49
|
|
53
50
|
export const PasswordField = ({ value, setValue }) => (
|
@@ -59,12 +56,11 @@ export const PasswordField = ({ value, setValue }) => (
|
|
59
56
|
),
|
60
57
|
'password'
|
61
58
|
)}
|
62
|
-
fieldId="
|
59
|
+
fieldId="password"
|
63
60
|
>
|
64
61
|
<TextInput
|
65
|
-
|
66
|
-
|
67
|
-
id="job-password"
|
62
|
+
autoComplete="password"
|
63
|
+
id="password"
|
68
64
|
type="password"
|
69
65
|
placeholder="*****"
|
70
66
|
value={value}
|
@@ -85,7 +81,6 @@ export const KeyPassphraseField = ({ value, setValue }) => (
|
|
85
81
|
fieldId="key-passphrase"
|
86
82
|
>
|
87
83
|
<TextInput
|
88
|
-
aria-label="key passphrase"
|
89
84
|
autoComplete="key-passphrase"
|
90
85
|
id="key-passphrase"
|
91
86
|
type="password"
|
@@ -108,7 +103,6 @@ export const EffectiveUserPasswordField = ({ value, setValue }) => (
|
|
108
103
|
fieldId="effective-user-password"
|
109
104
|
>
|
110
105
|
<TextInput
|
111
|
-
aria-label="effective userpassword"
|
112
106
|
autoComplete="effective-user-password"
|
113
107
|
id="effective-user-password"
|
114
108
|
type="password"
|
@@ -120,89 +114,51 @@ export const EffectiveUserPasswordField = ({ value, setValue }) => (
|
|
120
114
|
);
|
121
115
|
|
122
116
|
export const ConcurrencyLevelField = ({ value, setValue }) => (
|
123
|
-
<
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
'Run at most N tasks at a time. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1.'
|
129
|
-
),
|
130
|
-
'concurrency-level'
|
117
|
+
<FormGroup
|
118
|
+
label={__('Concurrency level')}
|
119
|
+
labelIcon={helpLabel(
|
120
|
+
__(
|
121
|
+
'Run at most N tasks at a time. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1.'
|
131
122
|
),
|
132
|
-
|
133
|
-
}
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
123
|
+
'concurrency-level'
|
124
|
+
)}
|
125
|
+
fieldId="concurrency-level"
|
126
|
+
>
|
127
|
+
<TextInput
|
128
|
+
min={1}
|
129
|
+
type="number"
|
130
|
+
autoComplete="concurrency-level"
|
131
|
+
id="concurrency-level"
|
132
|
+
placeholder={__('For example: 1, 2, 3, 4, 5...')}
|
133
|
+
value={value}
|
134
|
+
onChange={newValue => setValue(newValue)}
|
135
|
+
/>
|
136
|
+
</FormGroup>
|
143
137
|
);
|
144
138
|
|
145
139
|
export const TimeSpanLevelField = ({ value, setValue }) => (
|
146
|
-
<NumberInput
|
147
|
-
formProps={{
|
148
|
-
label: __('Time span'),
|
149
|
-
labelIcon: helpLabel(
|
150
|
-
__(
|
151
|
-
'Distribute execution over N seconds. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1.'
|
152
|
-
),
|
153
|
-
'time-span'
|
154
|
-
),
|
155
|
-
fieldId: 'time-span',
|
156
|
-
}}
|
157
|
-
inputProps={{
|
158
|
-
min: 1,
|
159
|
-
autoComplete: 'time-span',
|
160
|
-
id: 'time-span',
|
161
|
-
placeholder: __('For example: 1, 2, 3, 4, 5...'),
|
162
|
-
value,
|
163
|
-
onChange: newValue => setValue(newValue),
|
164
|
-
}}
|
165
|
-
/>
|
166
|
-
);
|
167
|
-
|
168
|
-
export const ExecutionOrderingField = ({ isRandomizedOrdering, setValue }) => (
|
169
140
|
<FormGroup
|
170
|
-
label={__('
|
171
|
-
fieldId="schedule-type"
|
141
|
+
label={__('Time span')}
|
172
142
|
labelIcon={helpLabel(
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
),
|
178
|
-
}}
|
179
|
-
/>,
|
180
|
-
'effective-user-password'
|
143
|
+
__(
|
144
|
+
'Distribute execution over N seconds. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1.'
|
145
|
+
),
|
146
|
+
'time-span'
|
181
147
|
)}
|
182
|
-
|
148
|
+
fieldId="time-span"
|
183
149
|
>
|
184
|
-
<
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
<Radio
|
193
|
-
aria-label="execution order randomized"
|
194
|
-
isChecked={isRandomizedOrdering}
|
195
|
-
name="execution-order"
|
196
|
-
onChange={() => setValue(true)}
|
197
|
-
id="execution-order-randomized"
|
198
|
-
label={__('Randomized')}
|
150
|
+
<TextInput
|
151
|
+
min={1}
|
152
|
+
type="number"
|
153
|
+
autoComplete="time-span"
|
154
|
+
id="time-span"
|
155
|
+
placeholder={__('For example: 1, 2, 3, 4, 5...')}
|
156
|
+
value={value}
|
157
|
+
onChange={newValue => setValue(newValue)}
|
199
158
|
/>
|
200
159
|
</FormGroup>
|
201
160
|
);
|
202
161
|
|
203
|
-
export const TemplateInputsFields = ({ inputs, value, setValue }) => (
|
204
|
-
<>{inputs?.map(input => formatter(input, value, setValue))}</>
|
205
|
-
);
|
206
162
|
EffectiveUserField.propTypes = {
|
207
163
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
208
164
|
setValue: PropTypes.func.isRequired,
|
@@ -223,20 +179,3 @@ ConcurrencyLevelField.propTypes = EffectiveUserField.propTypes;
|
|
223
179
|
ConcurrencyLevelField.defaultProps = EffectiveUserField.defaultProps;
|
224
180
|
TimeSpanLevelField.propTypes = EffectiveUserField.propTypes;
|
225
181
|
TimeSpanLevelField.defaultProps = EffectiveUserField.defaultProps;
|
226
|
-
ExecutionOrderingField.propTypes = {
|
227
|
-
isRandomizedOrdering: PropTypes.bool,
|
228
|
-
setValue: PropTypes.func.isRequired,
|
229
|
-
};
|
230
|
-
ExecutionOrderingField.defaultProps = {
|
231
|
-
isRandomizedOrdering: false,
|
232
|
-
};
|
233
|
-
|
234
|
-
TemplateInputsFields.propTypes = {
|
235
|
-
inputs: PropTypes.array.isRequired,
|
236
|
-
value: PropTypes.object,
|
237
|
-
setValue: PropTypes.func.isRequired,
|
238
|
-
};
|
239
|
-
|
240
|
-
TemplateInputsFields.defaultProps = {
|
241
|
-
value: {},
|
242
|
-
};
|
@@ -1,159 +1,25 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { Provider } from 'react-redux';
|
3
|
+
import configureMockStore from 'redux-mock-store';
|
4
|
+
import * as patternfly from '@patternfly/react-core';
|
3
5
|
import { mount } from '@theforeman/test';
|
4
|
-
import {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
13
|
-
|
14
|
-
|
15
|
-
const store = testSetup(selectors, api);
|
16
|
-
mockApi(api);
|
17
|
-
|
18
|
-
jest.spyOn(selectors, 'selectEffectiveUser');
|
19
|
-
|
20
|
-
selectors.selectEffectiveUser.mockImplementation(
|
21
|
-
() => jobTemplate.effective_user
|
22
|
-
);
|
6
|
+
import { AdvancedFields } from '../AdvancedFields';
|
7
|
+
|
8
|
+
jest.spyOn(patternfly, 'FormGroup');
|
9
|
+
patternfly.FormGroup.mockImplementation(props => (
|
10
|
+
<div>{props.navAriaLabel}</div>
|
11
|
+
));
|
12
|
+
const mockStore = configureMockStore([]);
|
13
|
+
const store = mockStore({
|
14
|
+
JOB_TEMPLATE: { response: { effective_user: { overridable: true } } },
|
15
|
+
});
|
23
16
|
describe('AdvancedFields', () => {
|
24
|
-
it('
|
25
|
-
const
|
26
|
-
<Provider store={store}>
|
27
|
-
<JobWizard advancedValues={{}} setAdvancedValues={jest.fn()} />
|
28
|
-
</Provider>
|
29
|
-
);
|
30
|
-
// setup
|
31
|
-
wrapper.find('.pf-c-button.pf-c-select__toggle-button').simulate('click');
|
32
|
-
wrapper
|
33
|
-
.find('.pf-c-select__menu-item')
|
34
|
-
.first()
|
35
|
-
.simulate('click');
|
36
|
-
|
37
|
-
// test
|
38
|
-
expect(wrapper.find('.pf-c-wizard__nav-link.pf-m-disabled')).toHaveLength(
|
39
|
-
0
|
40
|
-
);
|
41
|
-
wrapper
|
42
|
-
.find('.pf-c-wizard__nav-link')
|
43
|
-
.at(2)
|
44
|
-
.simulate('click'); // Advanced step
|
45
|
-
const effectiveUserInput = () => wrapper.find('input#effective-user');
|
46
|
-
const advancedTemplateInput = () =>
|
47
|
-
wrapper.find('.pf-c-form__group-control textarea');
|
48
|
-
const effectiveUesrValue = 'effective user new value';
|
49
|
-
const advancedTemplateInputValue = 'advanced input new value';
|
50
|
-
effectiveUserInput().getDOMNode().value = effectiveUesrValue;
|
51
|
-
|
52
|
-
effectiveUserInput().simulate('change');
|
53
|
-
wrapper.update();
|
54
|
-
advancedTemplateInput().getDOMNode().value = advancedTemplateInputValue;
|
55
|
-
advancedTemplateInput().simulate('change');
|
56
|
-
expect(effectiveUserInput().prop('value')).toEqual(effectiveUesrValue);
|
57
|
-
expect(advancedTemplateInput().prop('value')).toEqual(
|
58
|
-
advancedTemplateInputValue
|
59
|
-
);
|
60
|
-
|
61
|
-
wrapper
|
62
|
-
.find('.pf-c-wizard__nav-link')
|
63
|
-
.at(1)
|
64
|
-
.simulate('click');
|
65
|
-
|
66
|
-
expect(wrapper.find('.pf-c-wizard__nav-link.pf-m-current').text()).toEqual(
|
67
|
-
'Target hosts and inputs'
|
68
|
-
);
|
69
|
-
wrapper
|
70
|
-
.find('.pf-c-wizard__nav-link')
|
71
|
-
.at(2)
|
72
|
-
.simulate('click'); // Advanced step
|
73
|
-
|
74
|
-
expect(effectiveUserInput().prop('value')).toEqual(effectiveUesrValue);
|
75
|
-
expect(advancedTemplateInput().prop('value')).toEqual(
|
76
|
-
advancedTemplateInputValue
|
77
|
-
);
|
78
|
-
});
|
79
|
-
it('fill template fields', async () => {
|
80
|
-
render(
|
17
|
+
it('rendring', () => {
|
18
|
+
const component = mount(
|
81
19
|
<Provider store={store}>
|
82
|
-
<
|
20
|
+
<AdvancedFields advancedValues={{}} setAdvancedValues={jest.fn()} />
|
83
21
|
</Provider>
|
84
22
|
);
|
85
|
-
|
86
|
-
fireEvent.click(screen.getByText(WIZARD_TITLES.advanced));
|
87
|
-
});
|
88
|
-
const searchValue = 'search test';
|
89
|
-
const textValue = 'I am a text';
|
90
|
-
const dateValue = '08/07/2021';
|
91
|
-
const textField = screen.getByLabelText('adv plain hidden', {
|
92
|
-
selector: 'textarea',
|
93
|
-
});
|
94
|
-
const selectField = screen.getByText('option 1');
|
95
|
-
const searchField = screen.getByPlaceholderText('Filter...');
|
96
|
-
const dateField = screen.getByLabelText('adv date', {
|
97
|
-
selector: 'input',
|
98
|
-
});
|
99
|
-
|
100
|
-
fireEvent.click(selectField);
|
101
|
-
await act(async () => {
|
102
|
-
await fireEvent.click(screen.getByText('option 2'));
|
103
|
-
fireEvent.click(screen.getAllByText(WIZARD_TITLES.advanced)[0]); // to remove focus
|
104
|
-
await fireEvent.change(textField, {
|
105
|
-
target: { value: textValue },
|
106
|
-
});
|
107
|
-
|
108
|
-
await fireEvent.change(searchField, {
|
109
|
-
target: { value: searchValue },
|
110
|
-
});
|
111
|
-
await fireEvent.change(dateField, {
|
112
|
-
target: { value: dateValue },
|
113
|
-
});
|
114
|
-
});
|
115
|
-
expect(
|
116
|
-
screen.getByLabelText('adv plain hidden', {
|
117
|
-
selector: 'textarea',
|
118
|
-
}).value
|
119
|
-
).toBe(textValue);
|
120
|
-
expect(searchField.value).toBe(searchValue);
|
121
|
-
expect(dateField.value).toBe(dateValue);
|
122
|
-
await act(async () => {
|
123
|
-
fireEvent.click(screen.getByText(WIZARD_TITLES.categoryAndTemplate));
|
124
|
-
});
|
125
|
-
expect(screen.getAllByText(WIZARD_TITLES.categoryAndTemplate)).toHaveLength(
|
126
|
-
3
|
127
|
-
);
|
128
|
-
|
129
|
-
await act(async () => {
|
130
|
-
fireEvent.click(screen.getByText('Advanced Fields'));
|
131
|
-
});
|
132
|
-
expect(textField.value).toBe(textValue);
|
133
|
-
expect(searchField.value).toBe(searchValue);
|
134
|
-
expect(dateField.value).toBe(dateValue);
|
135
|
-
expect(screen.queryAllByText('option 1')).toHaveLength(0);
|
136
|
-
expect(screen.queryAllByText('option 2')).toHaveLength(1);
|
137
|
-
});
|
138
|
-
it('fill defaults into fields', async () => {
|
139
|
-
render(
|
140
|
-
<Provider store={store}>
|
141
|
-
<JobWizard />
|
142
|
-
</Provider>
|
143
|
-
);
|
144
|
-
await act(async () => {
|
145
|
-
fireEvent.click(screen.getByText('Advanced Fields'));
|
146
|
-
});
|
147
|
-
|
148
|
-
expect(
|
149
|
-
screen.getByLabelText('effective user', {
|
150
|
-
selector: 'input',
|
151
|
-
}).value
|
152
|
-
).toBe('default effective user');
|
153
|
-
expect(
|
154
|
-
screen.getByLabelText('timeout to kill', {
|
155
|
-
selector: 'input',
|
156
|
-
}).value
|
157
|
-
).toBe('2');
|
23
|
+
expect(component).toMatchSnapshot();
|
158
24
|
});
|
159
25
|
});
|
data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`AdvancedFields rendring 1`] = `
|
4
|
+
<Provider
|
5
|
+
store={
|
6
|
+
Object {
|
7
|
+
"clearActions": [Function],
|
8
|
+
"dispatch": [Function],
|
9
|
+
"getActions": [Function],
|
10
|
+
"getState": [Function],
|
11
|
+
"replaceReducer": [Function],
|
12
|
+
"subscribe": [Function],
|
13
|
+
}
|
14
|
+
}
|
15
|
+
>
|
16
|
+
<AdvancedFields
|
17
|
+
advancedValues={Object {}}
|
18
|
+
setAdvancedValues={[MockFunction]}
|
19
|
+
>
|
20
|
+
<Title
|
21
|
+
className="advanced-fields-title"
|
22
|
+
headingLevel="h2"
|
23
|
+
>
|
24
|
+
<h2
|
25
|
+
className="pf-c-title pf-m-xl advanced-fields-title"
|
26
|
+
>
|
27
|
+
Advanced Fields
|
28
|
+
</h2>
|
29
|
+
</Title>
|
30
|
+
<Form>
|
31
|
+
<form
|
32
|
+
className="pf-c-form"
|
33
|
+
noValidate={true}
|
34
|
+
>
|
35
|
+
<EffectiveUserField
|
36
|
+
setValue={[Function]}
|
37
|
+
value=""
|
38
|
+
>
|
39
|
+
<mockConstructor
|
40
|
+
fieldId="effective-user"
|
41
|
+
label="Effective user"
|
42
|
+
labelIcon={
|
43
|
+
<Popover
|
44
|
+
aria-label="help-text"
|
45
|
+
bodyContent="A user to be used for executing the script. If it differs from the SSH user, su or sudo is used to switch the accounts."
|
46
|
+
id="effective-user-help"
|
47
|
+
>
|
48
|
+
<button
|
49
|
+
aria-label="open-help-tooltip-button"
|
50
|
+
className="pf-c-form__group-label-help"
|
51
|
+
onClick={[Function]}
|
52
|
+
>
|
53
|
+
<HelpIcon
|
54
|
+
color="currentColor"
|
55
|
+
noVerticalAlign={true}
|
56
|
+
size="sm"
|
57
|
+
/>
|
58
|
+
</button>
|
59
|
+
</Popover>
|
60
|
+
}
|
61
|
+
>
|
62
|
+
<div />
|
63
|
+
</mockConstructor>
|
64
|
+
</EffectiveUserField>
|
65
|
+
<TimeoutToKillField
|
66
|
+
setValue={[Function]}
|
67
|
+
value=""
|
68
|
+
>
|
69
|
+
<mockConstructor
|
70
|
+
fieldId="timeout-to-kill"
|
71
|
+
label="Timeout to kill"
|
72
|
+
labelIcon={
|
73
|
+
<Popover
|
74
|
+
aria-label="help-text"
|
75
|
+
bodyContent="Time in seconds from the start on the remote host after which the job should be killed."
|
76
|
+
id="timeout-to-kill-help"
|
77
|
+
>
|
78
|
+
<button
|
79
|
+
aria-label="open-help-tooltip-button"
|
80
|
+
className="pf-c-form__group-label-help"
|
81
|
+
onClick={[Function]}
|
82
|
+
>
|
83
|
+
<HelpIcon
|
84
|
+
color="currentColor"
|
85
|
+
noVerticalAlign={true}
|
86
|
+
size="sm"
|
87
|
+
/>
|
88
|
+
</button>
|
89
|
+
</Popover>
|
90
|
+
}
|
91
|
+
>
|
92
|
+
<div />
|
93
|
+
</mockConstructor>
|
94
|
+
</TimeoutToKillField>
|
95
|
+
<PasswordField
|
96
|
+
setValue={[Function]}
|
97
|
+
value=""
|
98
|
+
>
|
99
|
+
<mockConstructor
|
100
|
+
fieldId="password"
|
101
|
+
label="Password"
|
102
|
+
labelIcon={
|
103
|
+
<Popover
|
104
|
+
aria-label="help-text"
|
105
|
+
bodyContent="Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution."
|
106
|
+
id="password-help"
|
107
|
+
>
|
108
|
+
<button
|
109
|
+
aria-label="open-help-tooltip-button"
|
110
|
+
className="pf-c-form__group-label-help"
|
111
|
+
onClick={[Function]}
|
112
|
+
>
|
113
|
+
<HelpIcon
|
114
|
+
color="currentColor"
|
115
|
+
noVerticalAlign={true}
|
116
|
+
size="sm"
|
117
|
+
/>
|
118
|
+
</button>
|
119
|
+
</Popover>
|
120
|
+
}
|
121
|
+
>
|
122
|
+
<div />
|
123
|
+
</mockConstructor>
|
124
|
+
</PasswordField>
|
125
|
+
<KeyPassphraseField
|
126
|
+
setValue={[Function]}
|
127
|
+
value=""
|
128
|
+
>
|
129
|
+
<mockConstructor
|
130
|
+
fieldId="key-passphrase"
|
131
|
+
label="Private key passphrase"
|
132
|
+
labelIcon={
|
133
|
+
<Popover
|
134
|
+
aria-label="help-text"
|
135
|
+
bodyContent="Key passphrase is only applicable for SSH provider. Other providers ignore this field. Passphrase is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution."
|
136
|
+
id="key-passphrase-help"
|
137
|
+
>
|
138
|
+
<button
|
139
|
+
aria-label="open-help-tooltip-button"
|
140
|
+
className="pf-c-form__group-label-help"
|
141
|
+
onClick={[Function]}
|
142
|
+
>
|
143
|
+
<HelpIcon
|
144
|
+
color="currentColor"
|
145
|
+
noVerticalAlign={true}
|
146
|
+
size="sm"
|
147
|
+
/>
|
148
|
+
</button>
|
149
|
+
</Popover>
|
150
|
+
}
|
151
|
+
>
|
152
|
+
<div />
|
153
|
+
</mockConstructor>
|
154
|
+
</KeyPassphraseField>
|
155
|
+
<EffectiveUserPasswordField
|
156
|
+
setValue={[Function]}
|
157
|
+
value=""
|
158
|
+
>
|
159
|
+
<mockConstructor
|
160
|
+
fieldId="effective-user-password"
|
161
|
+
label="Effective user password"
|
162
|
+
labelIcon={
|
163
|
+
<Popover
|
164
|
+
aria-label="help-text"
|
165
|
+
bodyContent="Effective user password is only applicable for SSH provider. Other providers ignore this field. Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution."
|
166
|
+
id="effective-user-password-help"
|
167
|
+
>
|
168
|
+
<button
|
169
|
+
aria-label="open-help-tooltip-button"
|
170
|
+
className="pf-c-form__group-label-help"
|
171
|
+
onClick={[Function]}
|
172
|
+
>
|
173
|
+
<HelpIcon
|
174
|
+
color="currentColor"
|
175
|
+
noVerticalAlign={true}
|
176
|
+
size="sm"
|
177
|
+
/>
|
178
|
+
</button>
|
179
|
+
</Popover>
|
180
|
+
}
|
181
|
+
>
|
182
|
+
<div />
|
183
|
+
</mockConstructor>
|
184
|
+
</EffectiveUserPasswordField>
|
185
|
+
<ConcurrencyLevelField
|
186
|
+
setValue={[Function]}
|
187
|
+
value=""
|
188
|
+
>
|
189
|
+
<mockConstructor
|
190
|
+
fieldId="concurrency-level"
|
191
|
+
label="Concurrency level"
|
192
|
+
labelIcon={
|
193
|
+
<Popover
|
194
|
+
aria-label="help-text"
|
195
|
+
bodyContent="Run at most N tasks at a time. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1."
|
196
|
+
id="concurrency-level-help"
|
197
|
+
>
|
198
|
+
<button
|
199
|
+
aria-label="open-help-tooltip-button"
|
200
|
+
className="pf-c-form__group-label-help"
|
201
|
+
onClick={[Function]}
|
202
|
+
>
|
203
|
+
<HelpIcon
|
204
|
+
color="currentColor"
|
205
|
+
noVerticalAlign={true}
|
206
|
+
size="sm"
|
207
|
+
/>
|
208
|
+
</button>
|
209
|
+
</Popover>
|
210
|
+
}
|
211
|
+
>
|
212
|
+
<div />
|
213
|
+
</mockConstructor>
|
214
|
+
</ConcurrencyLevelField>
|
215
|
+
<TimeSpanLevelField
|
216
|
+
setValue={[Function]}
|
217
|
+
value=""
|
218
|
+
>
|
219
|
+
<mockConstructor
|
220
|
+
fieldId="time-span"
|
221
|
+
label="Time span"
|
222
|
+
labelIcon={
|
223
|
+
<Popover
|
224
|
+
aria-label="help-text"
|
225
|
+
bodyContent="Distribute execution over N seconds. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1."
|
226
|
+
id="time-span-help"
|
227
|
+
>
|
228
|
+
<button
|
229
|
+
aria-label="open-help-tooltip-button"
|
230
|
+
className="pf-c-form__group-label-help"
|
231
|
+
onClick={[Function]}
|
232
|
+
>
|
233
|
+
<HelpIcon
|
234
|
+
color="currentColor"
|
235
|
+
noVerticalAlign={true}
|
236
|
+
size="sm"
|
237
|
+
/>
|
238
|
+
</button>
|
239
|
+
</Popover>
|
240
|
+
}
|
241
|
+
>
|
242
|
+
<div />
|
243
|
+
</mockConstructor>
|
244
|
+
</TimeSpanLevelField>
|
245
|
+
</form>
|
246
|
+
</Form>
|
247
|
+
</AdvancedFields>
|
248
|
+
</Provider>
|
249
|
+
`;
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
|
-
import { Text, TextVariants, Form, Alert } from '@patternfly/react-core';
|
3
|
+
import { Title, Text, TextVariants, Form, Alert } from '@patternfly/react-core';
|
4
4
|
import { translate as __ } from 'foremanReact/common/I18n';
|
5
5
|
import { SelectField } from '../form/SelectField';
|
6
6
|
import { GroupedSelectField } from '../form/GroupedSelectField';
|
7
|
-
import { WizardTitle } from '../form/WizardTitle';
|
8
|
-
import { WIZARD_TITLES } from '../../JobWizardConstants';
|
9
7
|
|
10
8
|
export const CategoryAndTemplate = ({
|
11
9
|
jobCategories,
|
@@ -42,7 +40,7 @@ export const CategoryAndTemplate = ({
|
|
42
40
|
const isError = !!(categoryError || allTemplatesError || templateError);
|
43
41
|
return (
|
44
42
|
<>
|
45
|
-
<
|
43
|
+
<Title headingLevel="h2">{__('Category and Template')}</Title>
|
46
44
|
<Text component={TextVariants.p}>{__('All fields are required.')}</Text>
|
47
45
|
<Form>
|
48
46
|
<SelectField
|