foreman_remote_execution 8.0.0 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
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