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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/job_invocations_controller.rb +1 -1
  3. data/app/controllers/ui_job_wizard_controller.rb +0 -7
  4. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +1 -5
  5. data/app/helpers/remote_execution_helper.rb +3 -9
  6. data/app/lib/actions/remote_execution/run_host_job.rb +1 -5
  7. data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
  8. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +0 -2
  9. data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +70 -0
  10. data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +0 -6
  11. data/app/models/host_status/execution_status.rb +3 -3
  12. data/app/models/job_invocation.rb +6 -9
  13. data/app/models/job_invocation_composer.rb +4 -4
  14. data/app/models/remote_execution_feature.rb +1 -5
  15. data/app/models/remote_execution_provider.rb +2 -3
  16. data/app/models/setting/remote_execution.rb +2 -2
  17. data/app/models/targeting.rb +1 -5
  18. data/app/views/job_invocations/index.html.erb +1 -1
  19. data/app/views/templates/ssh/module_action.erb +0 -1
  20. data/app/views/templates/ssh/power_action.erb +0 -2
  21. data/app/views/templates/ssh/puppet_run_once.erb +0 -1
  22. data/foreman_remote_execution.gemspec +0 -1
  23. data/lib/foreman_remote_execution/engine.rb +2 -0
  24. data/lib/foreman_remote_execution/version.rb +1 -1
  25. data/test/models/orchestration/ssh_test.rb +56 -0
  26. data/test/unit/job_invocation_composer_test.rb +1 -14
  27. data/test/unit/job_invocation_test.rb +1 -1
  28. data/test/unit/remote_execution_provider_test.rb +0 -12
  29. data/webpack/JobWizard/JobWizard.js +16 -59
  30. data/webpack/JobWizard/JobWizard.scss +0 -58
  31. data/webpack/JobWizard/JobWizardConstants.js +0 -18
  32. data/webpack/JobWizard/JobWizardSelectors.js +0 -9
  33. data/webpack/JobWizard/__tests__/JobWizard.test.js +13 -0
  34. data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +32 -0
  35. data/webpack/JobWizard/__tests__/fixtures.js +2 -112
  36. data/webpack/JobWizard/__tests__/integration.test.js +92 -16
  37. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +9 -37
  38. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +55 -116
  39. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +16 -150
  40. data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +249 -0
  41. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +2 -4
  42. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +51 -123
  43. data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +113 -0
  44. data/webpack/JobWizard/steps/form/FormHelpers.js +0 -1
  45. data/webpack/JobWizard/steps/form/SelectField.js +2 -14
  46. data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +38 -0
  47. data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +23 -0
  48. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +37 -0
  49. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +23 -0
  50. data/webpack/__mocks__/foremanReact/components/SearchBar.js +1 -18
  51. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +0 -1
  52. metadata +13 -35
  53. data/app/models/host_proxy_invocation.rb +0 -4
  54. data/db/migrate/2021051713291621250977_add_host_proxy_invocations.rb +0 -12
  55. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +0 -67
  56. data/webpack/JobWizard/steps/AdvancedFields/__tests__/DescriptionField.test.js +0 -23
  57. data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +0 -25
  58. data/webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js +0 -23
  59. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/SelectedChips.test.js +0 -37
  60. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +0 -50
  61. data/webpack/JobWizard/steps/HostsAndInputs/index.js +0 -66
  62. data/webpack/JobWizard/steps/Schedule/QueryType.js +0 -48
  63. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +0 -61
  64. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +0 -25
  65. data/webpack/JobWizard/steps/Schedule/StartEndDates.js +0 -51
  66. data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +0 -22
  67. data/webpack/JobWizard/steps/Schedule/index.js +0 -44
  68. data/webpack/JobWizard/steps/form/Formatter.js +0 -150
  69. data/webpack/JobWizard/steps/form/NumberInput.js +0 -35
  70. data/webpack/JobWizard/steps/form/WizardTitle.js +0 -14
  71. data/webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example +0 -76
@@ -1,150 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import { useSelector } from 'react-redux';
3
- import { FormGroup, TextInput, TextArea } from '@patternfly/react-core';
4
- import PropTypes from 'prop-types';
5
- import SearchBar from 'foremanReact/components/SearchBar';
6
- import { helpLabel } from './FormHelpers';
7
- import { SelectField } from './SelectField';
8
-
9
- const TemplateSearchField = ({
10
- name,
11
- controller,
12
- labelText,
13
- required,
14
- defaultValue,
15
- setValue,
16
- values,
17
- }) => {
18
- const searchQuery = useSelector(
19
- state => state.autocomplete?.[name]?.searchQuery
20
- );
21
- useEffect(() => {
22
- setValue({ ...values, [name]: searchQuery });
23
- // eslint-disable-next-line react-hooks/exhaustive-deps
24
- }, [searchQuery]);
25
- const id = name.replace(/ /g, '-');
26
- return (
27
- <FormGroup
28
- label={name}
29
- labelIcon={helpLabel(labelText, name)}
30
- fieldId={id}
31
- isRequired={required}
32
- className="foreman-search-field"
33
- >
34
- <SearchBar
35
- initialQuery={defaultValue}
36
- data={{
37
- controller,
38
- autocomplete: {
39
- id: name,
40
- url: `/${controller}/auto_complete_search`,
41
- useKeyShortcuts: true,
42
- },
43
- }}
44
- onSearch={() => null}
45
- />
46
- </FormGroup>
47
- );
48
- };
49
-
50
- export const formatter = (input, values, setValue) => {
51
- const isSelectType = !!input?.options;
52
- const inputType = input.value_type;
53
- const isTextType = inputType === 'plain' || !inputType; // null defaults to plain
54
-
55
- const { name, required, hidden_value: hidden } = input;
56
- const labelText = input.description;
57
- const value = values[name];
58
- const id = name.replace(/ /g, '-');
59
- if (isSelectType) {
60
- const options = input.options.split(/\r?\n/).map(option => option.trim());
61
- return (
62
- <SelectField
63
- aria-label={name}
64
- key={id}
65
- isRequired={required}
66
- label={name}
67
- fieldId={id}
68
- options={options}
69
- labelIcon={helpLabel(labelText, name)}
70
- value={value}
71
- setValue={newValue => setValue({ ...values, [name]: newValue })}
72
- />
73
- );
74
- }
75
- if (isTextType) {
76
- return (
77
- <FormGroup
78
- key={name}
79
- label={name}
80
- labelIcon={helpLabel(labelText, name)}
81
- fieldId={id}
82
- isRequired={required}
83
- >
84
- <TextArea
85
- aria-label={name}
86
- className={hidden ? 'masked-input' : null}
87
- required={required}
88
- rows={2}
89
- id={id}
90
- value={value}
91
- onChange={newValue => setValue({ ...values, [name]: newValue })}
92
- />
93
- </FormGroup>
94
- );
95
- }
96
- if (inputType === 'date') {
97
- return (
98
- <FormGroup
99
- key={name}
100
- label={name}
101
- labelIcon={helpLabel(labelText, name)}
102
- fieldId={id}
103
- isRequired={required}
104
- >
105
- <TextInput
106
- aria-label={name}
107
- placeholder="YYYY-mm-dd HH:MM"
108
- className={hidden ? 'masked-input' : null}
109
- required={required}
110
- id={id}
111
- type="text"
112
- value={value}
113
- onChange={newValue => setValue({ ...values, [name]: newValue })}
114
- />
115
- </FormGroup>
116
- );
117
- }
118
- if (inputType === 'search') {
119
- const controller = input.resource_type;
120
- // TODO: get text from redux autocomplete
121
- return (
122
- <TemplateSearchField
123
- key={id}
124
- name={name}
125
- defaultValue={value}
126
- controller={controller}
127
- labelText={labelText}
128
- required={required}
129
- setValue={setValue}
130
- values={values}
131
- />
132
- );
133
- }
134
-
135
- return null;
136
- };
137
-
138
- TemplateSearchField.propTypes = {
139
- name: PropTypes.string.isRequired,
140
- controller: PropTypes.string.isRequired,
141
- labelText: PropTypes.string,
142
- required: PropTypes.bool.isRequired,
143
- defaultValue: PropTypes.string,
144
- setValue: PropTypes.func.isRequired,
145
- values: PropTypes.object.isRequired,
146
- };
147
- TemplateSearchField.defaultProps = {
148
- labelText: null,
149
- defaultValue: '',
150
- };
@@ -1,35 +0,0 @@
1
- import React, { useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormGroup, TextInput, ValidatedOptions } from '@patternfly/react-core';
4
- import { translate as __ } from 'foremanReact/common/I18n';
5
-
6
- export const NumberInput = ({ formProps, inputProps }) => {
7
- const [validated, setValidated] = useState();
8
- const name = inputProps.id.replace(/-/g, ' ');
9
- return (
10
- <FormGroup
11
- {...formProps}
12
- helperTextInvalid={__('Has to be a number')}
13
- validated={validated}
14
- >
15
- <TextInput
16
- aria-label={name}
17
- type="text"
18
- {...inputProps}
19
- onChange={newValue => {
20
- setValidated(
21
- /^\d+$/.test(newValue) || newValue === ''
22
- ? ValidatedOptions.noval
23
- : ValidatedOptions.error
24
- );
25
- inputProps.onChange(newValue);
26
- }}
27
- />
28
- </FormGroup>
29
- );
30
- };
31
-
32
- NumberInput.propTypes = {
33
- formProps: PropTypes.object.isRequired,
34
- inputProps: PropTypes.object.isRequired,
35
- };
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { Title } from '@patternfly/react-core';
4
-
5
- export const WizardTitle = ({ title, ...props }) => (
6
- <Title headingLevel="h2" className="wizard-title" {...props}>
7
- {title}
8
- </Title>
9
- );
10
-
11
- WizardTitle.propTypes = {
12
- title: PropTypes.string.isRequired,
13
- };
14
- export default WizardTitle;
@@ -1,76 +0,0 @@
1
- import React from 'react';
2
- import { Provider } from 'react-redux';
3
- import configureMockStore from 'redux-mock-store';
4
- import * as patternfly from '@patternfly/react-core';
5
- import { mount, shallow } from '@theforeman/test';
6
- import { formatter } from '../Formatter';
7
-
8
- jest.spyOn(patternfly, 'Select');
9
- jest.spyOn(patternfly, 'SelectOption');
10
- jest.spyOn(patternfly, 'FormGroup');
11
- patternfly.Select.mockImplementation(props => <div props={props} />);
12
- patternfly.SelectOption.mockImplementation(props => <div props={props} />);
13
- patternfly.FormGroup.mockImplementation(props => <div props={props} />);
14
- const mockStore = configureMockStore([]);
15
- const store = mockStore({});
16
-
17
- describe('formatter', () => {
18
- it('render date input', () => {
19
- const props = {
20
- name: 'date adv',
21
- required: false,
22
- options: '',
23
- advanced: true,
24
- value_type: 'date',
25
- resource_type: 'ansible_roles',
26
- default: '',
27
- hidden_value: false,
28
- };
29
- expect(shallow(formatter(props, {}, jest.fn()))).toMatchSnapshot();
30
- });
31
- it('render text input', () => {
32
- const props = {
33
- name: 'plain adv hidden',
34
- required: true,
35
- description: 'some Description',
36
- options: '',
37
- advanced: true,
38
- value_type: 'plain',
39
- resource_type: 'ansible_roles',
40
- default: 'Default val',
41
- hidden_value: true,
42
- };
43
- expect(shallow(formatter(props, {}, jest.fn()))).toMatchSnapshot();
44
- });
45
- it('render select input', () => {
46
- const props = {
47
- name: 'adv plain search',
48
- required: false,
49
- input_type: 'user',
50
- options: 'option 1\r\noption 2\r\noption 3\r\noption 4',
51
- advanced: true,
52
- value_type: 'plain',
53
- resource_type: 'ansible_roles',
54
- default: '',
55
- hidden_value: false,
56
- };
57
- expect(shallow(formatter(props, {}, jest.fn()))).toMatchSnapshot();
58
- });
59
- it('render search input', () => {
60
- const props = {
61
- name: 'search adv',
62
- required: false,
63
- options: '',
64
- advanced: true,
65
- value_type: 'search',
66
- resource_type: 'foreman_tasks/tasks',
67
- default: '',
68
- hidden_value: false,
69
- };
70
- expect(
71
- mount(
72
- <Provider store={store}>{formatter(props, {}, jest.fn())}</Provider>
73
- )
74
- ).toMatchSnapshot();
75
- });
76
- });