foreman_remote_execution 13.2.3 → 13.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e86e40030829ea1e82f832a45615c93e2c77ff50ef2d2998f2ee933ef4526252
4
- data.tar.gz: c1e97626289a621bea70337993e65d05736ed839844cd0762f40d6b77ef91241
3
+ metadata.gz: f9049b84ffeb17c5603ee539e395f8de3180211896386064769bdec137a55aa2
4
+ data.tar.gz: 819932602c95357b78f56a1b04ed837c6f10ada81d653e0c621f832f594c6749
5
5
  SHA512:
6
- metadata.gz: 076f55dc40c9a0a82e4d69347128063c11c15299966b8ba5b96bdf59755e170473d58acdf32cb937b06aef6277c8fc9a43c842ba59fb250001c691f1cba95439
7
- data.tar.gz: def9eff7af10885ecbaa2e88f2773108a17ae1683301f0b5312fef964a640a61fabf96bd275c56928fcca2db6171a2fb6447b4e7043a329e8c9daae9446ea5cc
6
+ metadata.gz: bd6873c9f48b728cb4d7627c57bade8f1693355ef87d1ec2e7ece5af689fff10b2990edf8da0ae24a438afc0effab6de27be4db0c28908e340ea51dd1cc2bb4a
7
+ data.tar.gz: 6f56b251e5678619ae91cc0627096a468c04f3c28ad87e0f76adb3978d213d75bf7889d71e4f1228810f52f25a913f6e026e3828f5b5f45d721bd588de0c566e
@@ -73,12 +73,14 @@ module RemoteExecutionHelper
73
73
  buttons << link_to(_('Rerun'), rerun_job_invocation_path(:id => job_invocation.id),
74
74
  :class => 'btn btn-default',
75
75
  :title => _('Rerun the job'))
76
- end
77
- if authorized_for(controller: :job_invocations, action: :create)
78
76
  buttons << link_to(_('Rerun failed'), rerun_job_invocation_path(:id => job_invocation.id, :failed_only => 1),
79
77
  :class => 'btn btn-default',
80
78
  :disabled => job_invocation.failed_hosts.none?,
81
79
  :title => _('Rerun on failed hosts'))
80
+ buttons << link_to(_('Rerun succeeded'), rerun_job_invocation_path(:id => job_invocation.id, :succeeded_only => 1),
81
+ :class => 'btn btn-default',
82
+ :disabled => job_invocation.succeeded_hosts.none?,
83
+ :title => _('Rerun on succeeded hosts'))
82
84
  end
83
85
  if authorized_for(:permission => :view_foreman_tasks, :auth_object => task, :authorizer => task_authorizer)
84
86
  buttons << link_to(_('Job Task'), foreman_tasks_task_path(task),
@@ -44,13 +44,13 @@ end
44
44
  <% if @error %>
45
45
  <div class="line error"><%= @error %></div>
46
46
  <% else %>
47
- <%= link_to_function(_('Scroll to bottom'), '$("html, body").animate({ scrollTop: $(document).height() }, "slow");', :class => 'pull-right scroll-link-bottom') %>
47
+ <%= link_to_function(_('Scroll to bottom'), '$("#rails-app-content").scrollTop($("#rails-app-content").prop("scrollHeight"));', :class => 'pull-right scroll-link-bottom') %>
48
48
 
49
49
  <div class="printable">
50
50
  <%= render :partial => 'output_line_set', :collection => normalize_line_sets(@line_sets) %>
51
51
  </div>
52
52
 
53
- <%= link_to_function(_('Scroll to top'), '$("html, body").animate({ scrollTop: 0 }, "slow");', :class => 'pull-right scroll-link-top') %>
53
+ <%= link_to_function(_('Scroll to top'), '$("#rails-app-content").scrollTop(0);', :class => 'pull-right scroll-link-top') %>
54
54
  <% end %>
55
55
  </div>
56
56
 
@@ -0,0 +1,15 @@
1
+ <%#
2
+ kind: job_template
3
+ name: Download and run a script
4
+ model: JobTemplate
5
+ job_category: Commands
6
+ description_format: "Download the script from %{url} and run it locally"
7
+ provider_type: script
8
+ template_inputs:
9
+ - name: url
10
+ description: URL of the script to download and execute
11
+ input_type: user
12
+ required: true
13
+ %>
14
+
15
+ set -o pipefail && curl -sS '<%= input("url") %>' | bash
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '13.2.3'.freeze
2
+ VERSION = '13.2.5'.freeze
3
3
  end
@@ -8,8 +8,8 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: foreman_remote_execution 1.0.0\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2024-07-10 20:01+0200\n"
12
- "PO-Revision-Date: 2024-07-10 20:01+0200\n"
11
+ "POT-Creation-Date: 2024-07-17 17:11+0200\n"
12
+ "PO-Revision-Date: 2024-07-17 17:11+0200\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
15
  "Language: \n"
@@ -1,16 +1,33 @@
1
+ import React, { useState, useEffect } from 'react';
1
2
  import PropTypes from 'prop-types';
2
- import React from 'react';
3
3
  import URI from 'urijs';
4
- import { Alert, Button, Divider, Skeleton } from '@patternfly/react-core';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import {
6
+ Alert,
7
+ Divider,
8
+ Skeleton,
9
+ Button,
10
+ Title,
11
+ EmptyState,
12
+ EmptyStateVariant,
13
+ EmptyStateIcon,
14
+ EmptyStateBody,
15
+ } from '@patternfly/react-core';
16
+ import { ExclamationCircleIcon } from '@patternfly/react-icons';
17
+ import { global_palette_red_200 as exclamationColor } from '@patternfly/react-tokens';
18
+ import { get } from 'foremanReact/redux/API';
19
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
20
+ import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
21
+ import { STATUS } from 'foremanReact/constants';
5
22
  import {
6
23
  useForemanLocation,
7
24
  useForemanOrganization,
8
25
  } from 'foremanReact/Root/Context/ForemanContext';
9
- import { translate as __, sprintf } from 'foremanReact/common/I18n';
10
- import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
11
- import { STATUS } from 'foremanReact/constants';
12
- import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
13
26
  import { JobWizard } from './JobWizard';
27
+ import {
28
+ selectRerunJobInvocationResponse,
29
+ selectRerunJobInvocationStatus,
30
+ } from './JobWizardSelectors';
14
31
  import { JOB_API_KEY } from './JobWizardConstants';
15
32
 
16
33
  const JobWizardPageRerun = ({
@@ -19,6 +36,7 @@ const JobWizardPageRerun = ({
19
36
  },
20
37
  location: { search },
21
38
  }) => {
39
+ const dispatch = useDispatch();
22
40
  const uri = new URI(search);
23
41
  const { failed_only: failedOnly } = uri.search(true);
24
42
  const { succeeded_only: succeededOnly } = uri.search(true);
@@ -28,11 +46,6 @@ const JobWizardPageRerun = ({
28
46
  } else if (succeededOnly) {
29
47
  queryParams = '&succeeded_only=1';
30
48
  }
31
- const { response, status } = useAPI(
32
- 'get',
33
- `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
34
- JOB_API_KEY
35
- );
36
49
  const title = __('Run job');
37
50
  const breadcrumbOptions = {
38
51
  breadcrumbItems: [
@@ -41,11 +54,55 @@ const JobWizardPageRerun = ({
41
54
  ],
42
55
  };
43
56
 
44
- const jobOrganization = response.job_organization;
45
- const jobLocation = response.job_location;
57
+ const [errorMessage, setErrorMessage] = useState('');
58
+ const jobInvocationResponse = useSelector(selectRerunJobInvocationResponse);
59
+ const jobInvocationStatus = useSelector(selectRerunJobInvocationStatus);
60
+ const jobOrganization = jobInvocationResponse.job_organization;
61
+ const jobLocation = jobInvocationResponse.job_location;
46
62
  const currentOrganization = useForemanOrganization();
47
63
  const currentLocation = useForemanLocation();
48
64
 
65
+ const emptyStateLarge = (
66
+ <EmptyState variant={EmptyStateVariant.large}>
67
+ <EmptyStateIcon
68
+ icon={ExclamationCircleIcon}
69
+ color={exclamationColor.value}
70
+ />
71
+ <Title ouiaId="job-wizard-empty-state-header" headingLevel="h4" size="lg">
72
+ {__('Unable to run job')}
73
+ </Title>
74
+ <EmptyStateBody>{sprintf(errorMessage)}</EmptyStateBody>
75
+ <Button
76
+ ouiaId="job-wizard-run-job-button"
77
+ component="a"
78
+ href="/job_invocations/new"
79
+ variant="primary"
80
+ >
81
+ {__('Create job')}
82
+ </Button>
83
+ </EmptyState>
84
+ );
85
+
86
+ useEffect(() => {
87
+ let isMounted = true;
88
+ if (id !== undefined) {
89
+ dispatch(
90
+ get({
91
+ key: JOB_API_KEY,
92
+ url: `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
93
+ handleError: ({ response }) => {
94
+ if (isMounted) {
95
+ setErrorMessage(response?.data?.error?.message);
96
+ }
97
+ },
98
+ })
99
+ );
100
+ }
101
+ return () => {
102
+ isMounted = false;
103
+ };
104
+ }, [dispatch, id, failedOnly, queryParams]);
105
+
49
106
  return (
50
107
  <PageLayout
51
108
  header={title}
@@ -66,14 +123,16 @@ const JobWizardPageRerun = ({
66
123
  <React.Fragment>
67
124
  <Divider component="div" />
68
125
  </React.Fragment>
69
- {!status || status === STATUS.PENDING ? (
126
+ {jobInvocationStatus === STATUS.ERROR && emptyStateLarge}
127
+ {(!jobInvocationStatus || jobInvocationStatus === STATUS.PENDING) && (
70
128
  <div style={{ height: '400px' }}>
71
129
  <Skeleton
72
130
  height="100%"
73
131
  screenreaderText="Loading large rectangle contents"
74
132
  />
75
133
  </div>
76
- ) : (
134
+ )}
135
+ {jobInvocationStatus === STATUS.RESOLVED && (
77
136
  <React.Fragment>
78
137
  {jobOrganization?.id !== currentOrganization?.id && (
79
138
  <Alert
@@ -107,7 +166,12 @@ const JobWizardPageRerun = ({
107
166
  )}
108
167
  <Divider component="div" />
109
168
  <JobWizard
110
- rerunData={{ ...response?.job, inputs: response?.inputs } || null}
169
+ rerunData={
170
+ {
171
+ ...jobInvocationResponse?.job,
172
+ inputs: jobInvocationResponse?.inputs,
173
+ } || null
174
+ }
111
175
  />
112
176
  </React.Fragment>
113
177
  )}
@@ -14,8 +14,15 @@ import {
14
14
  JOB_TEMPLATE,
15
15
  HOSTS_API,
16
16
  JOB_INVOCATION,
17
+ JOB_API_KEY,
17
18
  } from './JobWizardConstants';
18
19
 
20
+ export const selectRerunJobInvocationResponse = state =>
21
+ selectAPIResponse(state, JOB_API_KEY) || {};
22
+
23
+ export const selectRerunJobInvocationStatus = state =>
24
+ selectAPIStatus(state, JOB_API_KEY);
25
+
19
26
  export const selectJobTemplatesStatus = state =>
20
27
  selectAPIStatus(state, JOB_TEMPLATES);
21
28
 
@@ -114,6 +114,8 @@ export const jobCategories = ['Services', 'Ansible Commands', 'Puppet'];
114
114
 
115
115
  export const testSetup = (selectors, api) => {
116
116
  jest.spyOn(api, 'get');
117
+ jest.spyOn(selectors, 'selectRerunJobInvocationResponse');
118
+ jest.spyOn(selectors, 'selectRerunJobInvocationStatus');
117
119
  jest.spyOn(selectors, 'selectJobTemplate');
118
120
  jest.spyOn(selectors, 'selectJobTemplates');
119
121
  jest.spyOn(selectors, 'selectJobCategories');
@@ -123,6 +125,10 @@ export const testSetup = (selectors, api) => {
123
125
 
124
126
  jest.spyOn(selectors, 'selectTemplateInputs');
125
127
  jest.spyOn(selectors, 'selectAdvancedTemplateInputs');
128
+ selectors.selectRerunJobInvocationResponse.mockImplementation(
129
+ () => jobInvocation
130
+ );
131
+ selectors.selectRerunJobInvocationStatus.mockImplementation(() => 'RESOLVED');
126
132
  selectors.selectWithKatello.mockImplementation(() => true);
127
133
  selectors.selectTemplateInputs.mockImplementation(
128
134
  () => jobTemplateResponse.template_inputs
@@ -14,16 +14,17 @@ import {
14
14
  jobInvocation,
15
15
  } from '../../__tests__/fixtures';
16
16
 
17
+ jest.useFakeTimers();
17
18
  const store = testSetup(selectors, api);
18
19
  mockApi(api);
19
20
  jest.spyOn(APIHooks, 'useAPI');
21
+ store.dispatch = jest.fn();
20
22
  APIHooks.useAPI.mockImplementation((action, url) => {
21
23
  if (url === '/ui_job_wizard/job_invocation?id=57') {
22
24
  return { response: jobInvocation, status: 'RESOLVED' };
23
25
  }
24
26
  return {};
25
27
  });
26
- jest.useFakeTimers();
27
28
 
28
29
  describe('ReviewDetails', () => {
29
30
  it('should call goToStepByName function when StepButton is clicked', async () => {
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: 13.2.3
4
+ version: 13.2.5
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: 2024-07-17 00:00:00.000000000 Z
11
+ date: 2024-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -295,6 +295,7 @@ files:
295
295
  - app/views/templates/script/puppet_install_modules_from_git.erb
296
296
  - app/views/templates/script/puppet_run_once.erb
297
297
  - app/views/templates/script/run_command.erb
298
+ - app/views/templates/script/run_downloaded_script.erb
298
299
  - app/views/templates/script/service_action.erb
299
300
  - config/routes.rb
300
301
  - db/migrate/20150612121541_add_job_template_to_template.rb