foreman_remote_execution 8.0.0 → 8.1.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/job_invocations_controller.rb +1 -2
  3. data/app/controllers/job_templates_controller.rb +1 -1
  4. data/app/controllers/ui_job_wizard_controller.rb +1 -1
  5. data/app/helpers/job_invocations_helper.rb +0 -7
  6. data/app/helpers/remote_execution_helper.rb +1 -1
  7. data/app/lib/actions/remote_execution/proxy_action.rb +46 -0
  8. data/app/lib/actions/remote_execution/run_host_job.rb +38 -11
  9. data/app/lib/actions/remote_execution/run_hosts_job.rb +7 -6
  10. data/app/lib/actions/remote_execution/template_invocation_progress_logging.rb +27 -0
  11. data/app/models/job_invocation.rb +5 -9
  12. data/app/models/job_invocation_composer.rb +4 -0
  13. data/app/models/remote_execution_provider.rb +10 -2
  14. data/app/models/ssh_execution_provider.rb +1 -0
  15. data/app/models/template_invocation.rb +1 -0
  16. data/app/models/template_invocation_event.rb +11 -0
  17. data/app/views/job_invocations/_form.html.erb +4 -0
  18. data/app/views/job_invocations/new.html.erb +5 -0
  19. data/app/views/templates/script/package_action.erb +1 -1
  20. data/config/routes.rb +5 -5
  21. data/db/migrate/20220713095705_create_template_invocation_events.rb +17 -0
  22. data/db/migrate/20220822155946_add_time_to_pickup_to_job_invocation.rb +5 -0
  23. data/extra/cockpit/foreman-cockpit-session +303 -230
  24. data/extra/cockpit/foreman-cockpit.service +1 -0
  25. data/foreman_remote_execution.gemspec +1 -1
  26. data/lib/foreman_remote_execution/engine.rb +12 -7
  27. data/lib/foreman_remote_execution/tasks/explain_proxy_selection.rake +131 -0
  28. data/lib/foreman_remote_execution/version.rb +1 -1
  29. data/test/unit/remote_execution_provider_test.rb +22 -0
  30. data/webpack/JobWizard/JobWizard.js +53 -18
  31. data/webpack/JobWizard/JobWizard.scss +3 -0
  32. data/webpack/JobWizard/JobWizardConstants.js +1 -1
  33. data/webpack/JobWizard/JobWizardHelpers.js +15 -0
  34. data/webpack/JobWizard/JobWizardPageRerun.js +29 -5
  35. data/webpack/JobWizard/JobWizardSelectors.js +8 -2
  36. data/webpack/JobWizard/__tests__/JobWizardPageRerun.test.js +5 -0
  37. data/webpack/JobWizard/__tests__/fixtures.js +26 -2
  38. data/webpack/JobWizard/autofill.js +32 -10
  39. data/webpack/JobWizard/index.js +25 -6
  40. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +25 -0
  41. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +12 -1
  42. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +41 -6
  43. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +1 -1
  44. data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +1 -1
  45. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +4 -2
  46. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +6 -2
  47. data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +28 -20
  48. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +32 -0
  49. data/webpack/JobWizard/steps/HostsAndInputs/index.js +2 -2
  50. data/webpack/JobWizard/steps/ReviewDetails/index.js +1 -0
  51. data/webpack/JobWizard/steps/form/FormHelpers.js +21 -1
  52. data/webpack/JobWizard/steps/form/Formatter.js +22 -6
  53. data/webpack/JobWizard/steps/form/ResourceSelect.js +97 -10
  54. data/webpack/JobWizard/steps/form/SearchSelect.js +2 -2
  55. data/webpack/JobWizard/steps/form/SelectField.js +4 -0
  56. data/webpack/JobWizard/submit.js +3 -1
  57. data/webpack/JobWizard/validation.js +1 -0
  58. data/webpack/Routes/routes.js +3 -3
  59. data/webpack/react_app/components/FeaturesDropdown/actions.js +23 -2
  60. data/webpack/react_app/components/FeaturesDropdown/index.js +2 -0
  61. data/webpack/react_app/components/HostKebab/KebabItems.js +1 -0
  62. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +5 -0
  63. data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +51 -59
  64. data/webpack/react_app/extend/Fills.js +3 -3
  65. metadata +12 -5
@@ -1,29 +1,116 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
4
+ import Immutable from 'seamless-immutable';
5
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
2
6
  import { useSelector, useDispatch } from 'react-redux';
3
7
  import URI from 'urijs';
4
8
  import { get } from 'foremanReact/redux/API';
5
9
  import { selectResponse, selectIsLoading } from '../../JobWizardSelectors';
6
- import { SearchSelect } from '../form/SearchSelect';
10
+ import { DEBOUNCE_API } from '../../JobWizardConstants';
7
11
 
8
- export const useNameSearchAPI = (apiKey, url) => {
12
+ export const ResourceSelect = ({
13
+ name,
14
+ selected,
15
+ setSelected,
16
+ placeholderText,
17
+ apiKey,
18
+ url,
19
+ }) => {
20
+ const maxResults = 100;
9
21
  const dispatch = useDispatch();
10
22
  const uri = new URI(url);
11
23
  const onSearch = search => {
12
24
  dispatch(
13
25
  get({
14
26
  key: apiKey,
15
- url: uri.addSearch({
16
- name: search,
17
- }),
27
+ url: uri.addSearch(search),
18
28
  })
19
29
  );
20
30
  };
21
31
 
22
32
  const response = useSelector(state => selectResponse(state, apiKey));
23
33
  const isLoading = useSelector(state => selectIsLoading(state, apiKey));
24
- return [onSearch, response, isLoading];
34
+ const [isOpen, setIsOpen] = useState(false);
35
+ const [typingTimeout, setTypingTimeout] = useState(null);
36
+ useEffect(() => {
37
+ onSearch(selected ? { id: selected } : {});
38
+ if (typingTimeout) {
39
+ return () => clearTimeout(typingTimeout);
40
+ }
41
+ return undefined;
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+ let selectOptions = [];
45
+ if (response.subtotal > maxResults) {
46
+ selectOptions = [
47
+ <SelectOption
48
+ isDisabled
49
+ key={0}
50
+ description={__('Please refine your search.')}
51
+ >
52
+ {sprintf(
53
+ __('You have %s results to display. Showing first %s results'),
54
+ response.subtotal,
55
+ maxResults
56
+ )}
57
+ </SelectOption>,
58
+ ];
59
+ }
60
+ selectOptions = [
61
+ ...selectOptions,
62
+ ...Immutable.asMutable(response?.results || [])?.map((result, index) => (
63
+ <SelectOption key={index + 1} value={result.id}>
64
+ {result.name}
65
+ </SelectOption>
66
+ )),
67
+ ];
68
+
69
+ const onSelect = (event, selection) => {
70
+ setSelected(selection);
71
+ setIsOpen(false);
72
+ };
73
+ const autoSearch = searchTerm => {
74
+ if (typingTimeout) clearTimeout(typingTimeout);
75
+ setTypingTimeout(
76
+ setTimeout(() => onSearch({ name: searchTerm }), DEBOUNCE_API)
77
+ );
78
+ };
79
+ return (
80
+ <Select
81
+ toggleAriaLabel={`${name} toggle`}
82
+ chipGroupComponent={<></>}
83
+ variant={SelectVariant.typeahead}
84
+ selections={selected}
85
+ loadingVariant={isLoading ? 'spinner' : null}
86
+ onSelect={onSelect}
87
+ onToggle={setIsOpen}
88
+ isOpen={isOpen}
89
+ className="without_select2"
90
+ maxHeight="45vh"
91
+ onTypeaheadInputChanged={value => {
92
+ autoSearch(value || '');
93
+ }}
94
+ placeholderText={placeholderText}
95
+ typeAheadAriaLabel={`${name} typeahead input`}
96
+ >
97
+ {selectOptions}
98
+ </Select>
99
+ );
25
100
  };
26
101
 
27
- export const ResourceSelectAPI = props => (
28
- <SearchSelect {...props} useNameSearch={useNameSearchAPI} />
29
- );
102
+ ResourceSelect.propTypes = {
103
+ name: PropTypes.string,
104
+ selected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
105
+ setSelected: PropTypes.func.isRequired,
106
+ placeholderText: PropTypes.string,
107
+ apiKey: PropTypes.string.isRequired,
108
+ url: PropTypes.string,
109
+ };
110
+
111
+ ResourceSelect.defaultProps = {
112
+ name: 'typeahead select',
113
+ selected: {},
114
+ placeholderText: '',
115
+ url: '',
116
+ };
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
4
4
  import Immutable from 'seamless-immutable';
5
5
  import { sprintf, translate as __ } from 'foremanReact/common/I18n';
6
+ import { DEBOUNCE_API } from '../../JobWizardConstants';
6
7
 
7
8
  export const maxResults = 100;
8
9
 
@@ -19,7 +20,6 @@ export const SearchSelect = ({
19
20
  const [onSearch, response, isLoading] = useNameSearch(apiKey, url);
20
21
  const [isOpen, setIsOpen] = useState(false);
21
22
  const [typingTimeout, setTypingTimeout] = useState(null);
22
- const autoSearchDelay = 500;
23
23
  useEffect(() => {
24
24
  onSearch(selected.name || '');
25
25
  if (typingTimeout) {
@@ -71,7 +71,7 @@ export const SearchSelect = ({
71
71
  };
72
72
  const autoSearch = searchTerm => {
73
73
  if (typingTimeout) clearTimeout(typingTimeout);
74
- setTypingTimeout(setTimeout(() => onSearch(searchTerm), autoSearchDelay));
74
+ setTypingTimeout(setTimeout(() => onSearch(searchTerm), DEBOUNCE_API));
75
75
  };
76
76
  return (
77
77
  <Select
@@ -3,6 +3,7 @@ import { FormGroup, Select, SelectOption } from '@patternfly/react-core';
3
3
  import PropTypes from 'prop-types';
4
4
 
5
5
  export const SelectField = ({
6
+ labelInfo,
6
7
  label,
7
8
  fieldId,
8
9
  options,
@@ -29,6 +30,7 @@ export const SelectField = ({
29
30
  ];
30
31
  return (
31
32
  <FormGroup
33
+ labelInfo={labelInfo}
32
34
  label={label}
33
35
  fieldId={fieldId}
34
36
  labelIcon={labelIcon}
@@ -54,6 +56,7 @@ export const SelectField = ({
54
56
  };
55
57
  SelectField.propTypes = {
56
58
  label: PropTypes.string,
59
+ labelInfo: PropTypes.node,
57
60
  fieldId: PropTypes.string.isRequired,
58
61
  options: PropTypes.array,
59
62
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@@ -64,6 +67,7 @@ SelectField.propTypes = {
64
67
 
65
68
  SelectField.defaultProps = {
66
69
  label: null,
70
+ labelInfo: null,
67
71
  options: [],
68
72
  labelIcon: null,
69
73
  value: null,
@@ -34,6 +34,7 @@ export const submit = ({
34
34
  templateValues: advancedTemplateValues,
35
35
  password,
36
36
  keyPassphrase,
37
+ timeToPickup,
37
38
  } = advancedValues;
38
39
  const getCronLine = () => {
39
40
  const [hour, minute] = repeatData.at
@@ -70,7 +71,7 @@ export const submit = ({
70
71
  : 'dynamic_query',
71
72
  randomized_ordering: isRandomizedOrdering,
72
73
  inputs: { ...templateValues, ...advancedTemplateValues },
73
- ssh_user: sshUser,
74
+ ssh_user: sshUser || null,
74
75
  ssh: {
75
76
  effective_user: effectiveUserValue,
76
77
  effective_user_password: effectiveUserPassword,
@@ -107,6 +108,7 @@ export const submit = ({
107
108
  description_format: description,
108
109
  execution_timeout_interval: timeoutToKill,
109
110
  feature: '', // TODO add value after https://github.com/theforeman/foreman_remote_execution/pull/629
111
+ time_to_pickup: timeToPickup,
110
112
  },
111
113
  };
112
114
 
@@ -39,6 +39,7 @@ export const useValidation = ({ advancedValues, templateValues }) => {
39
39
  );
40
40
  [
41
41
  advancedValues.timeoutToKill,
42
+ advancedValues.timeToPickup,
42
43
  advancedValues.concurrencyLevel,
43
44
  advancedValues.timeSpan,
44
45
  ].forEach(value => {
@@ -4,12 +4,12 @@ import JobWizardPageRerun from '../JobWizard/JobWizardPageRerun';
4
4
 
5
5
  const ForemanREXRoutes = [
6
6
  {
7
- path: '/experimental/job_wizard/new',
7
+ path: '/job_invocations/new',
8
8
  exact: true,
9
- render: () => <JobWizardPage />,
9
+ render: props => <JobWizardPage {...props} />,
10
10
  },
11
11
  {
12
- path: '/experimental/job_wizard/:id/rerun',
12
+ path: '/job_invocations/:id/rerun',
13
13
  exact: true,
14
14
  render: props => <JobWizardPageRerun {...props} />,
15
15
  },
@@ -7,7 +7,28 @@ export const runFeature = (hostId, feature, label) => dispatch => {
7
7
  `/job_invocations?feature=${feature}&host_ids%5B%5D=${hostId}`
8
8
  );
9
9
 
10
- const successToast = () => sprintf(__('%s job has been invoked'), label);
10
+ const successToast = ({ request }) => {
11
+ if (request.responseURL.includes('job_invocations?')) {
12
+ return __('Opening job invocation form');
13
+ }
14
+ return sprintf(__('%s job has been invoked'), label);
15
+ };
11
16
  const errorToast = ({ message }) => message;
12
- dispatch(post({ key: feature.toUpperCase(), url, successToast, errorToast }));
17
+ dispatch(
18
+ post({
19
+ key: feature.toUpperCase(),
20
+ url,
21
+ successToast,
22
+ errorToast,
23
+ handleSuccess: ({ request }) => {
24
+ if (request.responseURL.includes('job_invocations?')) {
25
+ // checking if user should be redicted to finish setting up the job
26
+ window.location.href = request.responseURL.replace(
27
+ 'job_invocations?',
28
+ 'job_invocations/new?'
29
+ );
30
+ }
31
+ },
32
+ })
33
+ );
13
34
  };
@@ -47,10 +47,12 @@ const FeaturesDropdown = ({ hostId }) => {
47
47
 
48
48
  return (
49
49
  <Dropdown
50
+ ouiaId="schedule-a-job-dropdown"
50
51
  alignments={{ default: 'right' }}
51
52
  onSelect={() => setIsOpen(false)}
52
53
  toggle={
53
54
  <DropdownToggle
55
+ ouiaId="schedule-a-job-dropdown-toggle"
54
56
  splitButtonItems={scheduleJob}
55
57
  toggleVariant="secondary"
56
58
  onToggle={() => setIsOpen(prev => !prev)}
@@ -14,6 +14,7 @@ const HostKebabItems = () => {
14
14
  if (!consoleUrl) return null;
15
15
  return (
16
16
  <DropdownItem
17
+ ouiaId="web-console-dropdown-item"
17
18
  icon={<CodeIcon />}
18
19
  href={consoleUrl}
19
20
  target="_blank"
@@ -27,6 +27,7 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
27
27
  <DropdownItem
28
28
  href={foremanUrl(`${JOB_BASE_URL}${name}`)}
29
29
  key="link-to-all"
30
+ ouiaId="link-to-all-dropdown-item"
30
31
  >
31
32
  {__('View all jobs')}
32
33
  </DropdownItem>,
@@ -35,24 +36,28 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
35
36
  `${JOB_BASE_URL}${name}+and+status+%3D+failed+or+status%3D+succeeded`
36
37
  )}
37
38
  key="link-to-finished"
39
+ ouiaId="link-to-finished-dropdown-item"
38
40
  >
39
41
  {__('View finished jobs')}
40
42
  </DropdownItem>,
41
43
  <DropdownItem
42
44
  href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+running`)}
43
45
  key="link-to-running"
46
+ ouiaId="link-to-running-dropdown-item"
44
47
  >
45
48
  {__('View running jobs')}
46
49
  </DropdownItem>,
47
50
  <DropdownItem
48
51
  href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+queued`)}
49
52
  key="link-to-scheduled"
53
+ ouiaId="link-to-scheduled-dropdown-item"
50
54
  >
51
55
  {__('View scheduled jobs')}
52
56
  </DropdownItem>,
53
57
  ]}
54
58
  >
55
59
  <Tabs
60
+ ouiaId="tabs"
56
61
  mountOnEnter
57
62
  unmountOnExit
58
63
  activeKey={activeTab}
@@ -1,15 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import {
4
- DataList,
5
- DataListItem,
6
- DataListItemRow,
7
- DataListItemCells,
8
- DataListCell,
9
- DataListWrapModifier,
10
- Text,
11
- Bullseye,
12
- } from '@patternfly/react-core';
3
+ import { Text, Bullseye } from '@patternfly/react-core';
4
+ import { TableComposable, Tr, Tbody, Td } from '@patternfly/react-table';
13
5
  import { STATUS } from 'foremanReact/constants';
14
6
 
15
7
  import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
@@ -33,55 +25,55 @@ const RecentJobsTable = ({ status, hostId }) => {
33
25
  } = useAPI('get', jobsUrl, RECENT_JOBS_KEY);
34
26
 
35
27
  return (
36
- <DataList aria-label="recent-jobs-table" isCompact>
37
- <SkeletonLoader
38
- skeletonProps={{ count: 3 }}
39
- status={responseStatus || STATUS.PENDING}
40
- emptyState={
41
- <Bullseye>
42
- <Text style={{ marginTop: '20px' }} component="p">
43
- {__('No results found')}
44
- </Text>
45
- </Bullseye>
46
- }
47
- >
48
- {jobs?.length &&
49
- jobs.map(
50
- ({
51
- status: jobStatus,
52
- status_label: label,
53
- id,
54
- start_at: startAt,
55
- description,
56
- }) => (
57
- <DataListItem key={id}>
58
- <DataListItemRow>
59
- <DataListItemCells
60
- dataListCells={[
61
- <DataListCell
62
- wrapModifier={DataListWrapModifier.truncate}
63
- key={`name-${id}`}
64
- >
65
- <a href={foremanUrl(`/job_invocations/${id}`)}>
66
- {description}
67
- </a>
68
- </DataListCell>,
69
- <DataListCell key={`date-${id}`}>
70
- <RelativeDateTime date={startAt} />
71
- </DataListCell>,
72
- <DataListCell key={`status-${id}`}>
73
- <JobStatusIcon status={jobStatus}>
74
- {label}
75
- </JobStatusIcon>
76
- </DataListCell>,
77
- ]}
78
- />
79
- </DataListItemRow>
80
- </DataListItem>
81
- )
82
- )}
83
- </SkeletonLoader>
84
- </DataList>
28
+ <SkeletonLoader
29
+ skeletonProps={{ count: 3 }}
30
+ status={responseStatus || STATUS.PENDING}
31
+ emptyState={
32
+ <Bullseye>
33
+ <Text
34
+ ouiaId="no-results-text"
35
+ style={{ marginTop: '20px' }}
36
+ component="p"
37
+ >
38
+ {__('No results found')}
39
+ </Text>
40
+ </Bullseye>
41
+ }
42
+ >
43
+ {!!jobs?.length && (
44
+ <TableComposable
45
+ aria-label="recent-jobs-table"
46
+ variant="compact"
47
+ borders="compactBorderless"
48
+ >
49
+ <Tbody>
50
+ {jobs.map(
51
+ ({
52
+ status: jobStatus,
53
+ status_label: label,
54
+ id,
55
+ start_at: startAt,
56
+ description,
57
+ }) => (
58
+ <Tr key={id}>
59
+ <Td modifier="truncate" key={`name-${id}`}>
60
+ <a href={foremanUrl(`/job_invocations/${id}`)}>
61
+ {description}
62
+ </a>
63
+ </Td>
64
+ <Td modifier="truncate" key={`date-${id}`}>
65
+ <RelativeDateTime date={startAt} />
66
+ </Td>
67
+ <Td modifier="truncate" key={`status-${id}`}>
68
+ <JobStatusIcon status={jobStatus}>{label}</JobStatusIcon>
69
+ </Td>
70
+ </Tr>
71
+ )
72
+ )}
73
+ </Tbody>
74
+ </TableComposable>
75
+ )}
76
+ </SkeletonLoader>
85
77
  );
86
78
  };
87
79
 
@@ -41,11 +41,11 @@ const fills = [
41
41
  ];
42
42
 
43
43
  const registerFills = () => {
44
- fills.forEach(({ slot, id, component: Component, weight, metadata }) =>
44
+ fills.forEach(({ slot, name, component: Component, weight, metadata }) =>
45
45
  addGlobalFill(
46
46
  slot,
47
- id,
48
- <Component key={`rex-fill-${id}`} />,
47
+ `rex-${name}`,
48
+ <Component key={`rex-${name}`} />,
49
49
  weight,
50
50
  metadata
51
51
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0
4
+ version: 8.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-03 00:00:00.000000000 Z
11
+ date: 2022-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 5.1.0
53
+ version: 7.1.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 5.1.0
60
+ version: 7.1.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: factory_bot_rails
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -149,8 +149,10 @@ files:
149
149
  - app/helpers/job_invocations_helper.rb
150
150
  - app/helpers/remote_execution_helper.rb
151
151
  - app/lib/actions/middleware/bind_job_invocation.rb
152
+ - app/lib/actions/remote_execution/proxy_action.rb
152
153
  - app/lib/actions/remote_execution/run_host_job.rb
153
154
  - app/lib/actions/remote_execution/run_hosts_job.rb
155
+ - app/lib/actions/remote_execution/template_invocation_progress_logging.rb
154
156
  - app/lib/foreman_remote_execution/provider_input.rb
155
157
  - app/lib/foreman_remote_execution/renderer/scope/input.rb
156
158
  - app/lib/proxy_api/remote_execution_ssh.rb
@@ -189,6 +191,7 @@ files:
189
191
  - app/models/targeting.rb
190
192
  - app/models/targeting_host.rb
191
193
  - app/models/template_invocation.rb
194
+ - app/models/template_invocation_event.rb
192
195
  - app/models/template_invocation_input_value.rb
193
196
  - app/overrides/execution_interface.rb
194
197
  - app/overrides/subnet_proxies.rb
@@ -324,6 +327,8 @@ files:
324
327
  - db/migrate/20210816100932_rex_setting_category_to_dsl.rb
325
328
  - db/migrate/20220321101835_rename_ssh_provider_to_script.rb
326
329
  - db/migrate/20220331112719_add_ssh_user_to_job_invocation.rb
330
+ - db/migrate/20220713095705_create_template_invocation_events.rb
331
+ - db/migrate/20220822155946_add_time_to_pickup_to_job_invocation.rb
327
332
  - db/seeds.d/100-assign_features_with_templates.rb
328
333
  - db/seeds.d/20-permissions.rb
329
334
  - db/seeds.d/50-notification_blueprints.rb
@@ -339,6 +344,7 @@ files:
339
344
  - jsconfig.json
340
345
  - lib/foreman_remote_execution.rb
341
346
  - lib/foreman_remote_execution/engine.rb
347
+ - lib/foreman_remote_execution/tasks/explain_proxy_selection.rake
342
348
  - lib/foreman_remote_execution/version.rb
343
349
  - lib/tasks/foreman_remote_execution_tasks.rake
344
350
  - locale/Makefile
@@ -408,6 +414,7 @@ files:
408
414
  - webpack/JobWizard/JobWizard.js
409
415
  - webpack/JobWizard/JobWizard.scss
410
416
  - webpack/JobWizard/JobWizardConstants.js
417
+ - webpack/JobWizard/JobWizardHelpers.js
411
418
  - webpack/JobWizard/JobWizardPageRerun.js
412
419
  - webpack/JobWizard/JobWizardSelectors.js
413
420
  - webpack/JobWizard/__tests__/JobWizardPageRerun.test.js
@@ -548,7 +555,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
548
555
  - !ruby/object:Gem::Version
549
556
  version: '0'
550
557
  requirements: []
551
- rubygems_version: 3.2.26
558
+ rubygems_version: 3.3.20
552
559
  signing_key:
553
560
  specification_version: 4
554
561
  summary: A plugin bringing remote execution to the Foreman, completing the config