foreman_remote_execution 5.0.8 → 5.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_controller_extensions.rb +0 -5
- data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +9 -20
- data/app/helpers/remote_execution_helper.rb +3 -4
- data/app/lib/actions/remote_execution/run_host_job.rb +2 -0
- data/app/lib/foreman_remote_execution/renderer/scope/input.rb +1 -1
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +0 -8
- data/app/models/concerns/foreman_remote_execution/nic_extensions.rb +4 -6
- data/app/models/job_invocation.rb +2 -0
- data/app/models/job_invocation_composer.rb +1 -1
- data/app/models/job_template.rb +3 -1
- data/app/models/targeting.rb +1 -1
- data/app/views/dashboard/_latest-jobs.html.erb +1 -1
- data/app/views/job_invocations/_preview_hosts_list.html.erb +1 -1
- data/app/views/job_templates/_custom_tabs.html.erb +4 -9
- data/app/views/template_invocations/show.html.erb +7 -1
- data/app/views/templates/ssh/package_action.erb +0 -3
- data/lib/foreman_remote_execution/engine.rb +2 -7
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/package.json +7 -6
- data/test/unit/concerns/host_extensions_test.rb +1 -2
- data/test/unit/job_invocation_report_template_test.rb +1 -1
- data/test/unit/targeting_test.rb +1 -1
- data/webpack/JobWizard/steps/form/GroupedSelectField.js +0 -2
- data/webpack/global_index.js +0 -4
- data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +1 -6
- data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +2 -2
- data/webpack/react_app/components/RecentJobsCard/constants.js +0 -1
- metadata +3 -13
- data/app/views/api/v2/host/main.rabl +0 -1
- data/jsconfig.json +0 -8
- data/test/unit/api_params_test.rb +0 -33
- data/webpack/react_app/components/FeaturesDropdown/actions.js +0 -13
- data/webpack/react_app/components/FeaturesDropdown/constant.js +0 -2
- data/webpack/react_app/components/FeaturesDropdown/index.js +0 -74
- data/webpack/react_app/components/HostKebab/KebabItems.js +0 -27
- data/webpack/react_app/extend/fillKebabItems.js +0 -11
- data/webpack/react_app/extend/fillRexFeaturesDropdown.js +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 831ec5aca2ec4aaa3df1229f7addd9a968c7c49b0fc49a15253e33d2ab0f5689
|
4
|
+
data.tar.gz: 07a4f17f0d4d694c4b927291ee8e55dafd839cf902a9ef06c79b227fdf65760f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75fd11cfe45b5223a2427561c0859c39f19923535283fa919927af9b4ffd67ea56a4c9b791632e73c72c4dff1946f2e1046cb10a1f84ed7dae0e686daff2d90d
|
7
|
+
data.tar.gz: 03557c309e25a902c0def6e7575ad74a02e724482da823b4580f4bbe9b80358eadb2e0781b832f45a2e9101196447edf887476fa79782a3d6ee125640dccd92a
|
data/Gemfile
CHANGED
data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_controller_extensions.rb
CHANGED
@@ -13,7 +13,6 @@ module ForemanRemoteExecution
|
|
13
13
|
|
14
14
|
def host_setup_extension
|
15
15
|
remote_execution_interface
|
16
|
-
reset_host_known_keys! unless @host.new_record?
|
17
16
|
super
|
18
17
|
end
|
19
18
|
|
@@ -22,10 +21,6 @@ module ForemanRemoteExecution
|
|
22
21
|
|
23
22
|
@host.set_execution_interface(params['remote_execution_interface'])
|
24
23
|
end
|
25
|
-
|
26
|
-
def reset_host_known_keys!
|
27
|
-
@host.host_proxy_invocations.destroy_all
|
28
|
-
end
|
29
24
|
end
|
30
25
|
end
|
31
26
|
end
|
@@ -8,7 +8,7 @@ module ForemanRemoteExecution
|
|
8
8
|
|
9
9
|
def multiple_actions
|
10
10
|
res = super
|
11
|
-
res += [ [_('Schedule Remote Job'), new_job_invocation_path, false] ] if
|
11
|
+
res += [ [_('Schedule Remote Job'), new_job_invocation_path, false] ] if authorized_for(controller: :job_invocations, action: :new)
|
12
12
|
res
|
13
13
|
end
|
14
14
|
|
@@ -22,20 +22,20 @@ module ForemanRemoteExecution
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def rex_host_features(
|
26
|
-
return
|
25
|
+
def rex_host_features(*args)
|
26
|
+
return unless authorized_for(controller: :job_invocations, action: :create)
|
27
27
|
RemoteExecutionFeature.with_host_action_button.order(:label).map do |feature|
|
28
|
-
link_to(_('%s') % feature.name, job_invocations_path(:host_ids => [
|
28
|
+
link_to(_('%s') % feature.name, job_invocations_path(:host_ids => [args.first.id], :feature => feature.label), :method => :post)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def schedule_job_button(
|
33
|
-
return unless
|
34
|
-
link_to(_('Schedule Remote Job'), new_job_invocation_path(:host_ids => [
|
32
|
+
def schedule_job_button(*args)
|
33
|
+
return unless authorized_for(controller: :job_invocations, action: :new)
|
34
|
+
link_to(_('Schedule Remote Job'), new_job_invocation_path(:host_ids => [args.first.id]), :id => :run_button, :class => 'btn btn-default')
|
35
35
|
end
|
36
36
|
|
37
37
|
def web_console_button(host, *args)
|
38
|
-
return
|
38
|
+
return unless authorized_for(permission: 'cockpit_hosts', auth_object: host)
|
39
39
|
|
40
40
|
url = SSHExecutionProvider.cockpit_url_for_host(host.name)
|
41
41
|
url ? link_to(_('Web Console'), url, :class => 'btn btn-default', :id => :'web-console-button', :target => '_new') : nil
|
@@ -46,17 +46,6 @@ module ForemanRemoteExecution
|
|
46
46
|
button_group(web_console_button(*args)))
|
47
47
|
super(*args)
|
48
48
|
end
|
49
|
-
|
50
|
-
def can_schedule_jobs?
|
51
|
-
authorized_for(controller: :job_invocations, action: :create)
|
52
|
-
end
|
53
|
-
|
54
|
-
def can_execute_on_host?(host)
|
55
|
-
can_schedule_jobs? && can_execute_on_infrastructure_host?(host)
|
56
|
-
end
|
57
|
-
|
58
|
-
def can_execute_on_infrastructure_host?(host)
|
59
|
-
!host.infrastructure_host? || User.current.can?(:execute_jobs_on_infrastructure_hosts)
|
60
|
-
end
|
61
49
|
end
|
50
|
+
|
62
51
|
end
|
@@ -31,7 +31,7 @@ module RemoteExecutionHelper
|
|
31
31
|
|
32
32
|
if authorized_for(hash_for_host_path(host).merge(auth_object: host, permission: :view_hosts, authorizer: job_hosts_authorizer))
|
33
33
|
links << { title: _('Host detail'),
|
34
|
-
action: { href:
|
34
|
+
action: { href: host_path(host), 'data-method': 'get', id: "#{host.name}-actions-detail" } }
|
35
35
|
end
|
36
36
|
|
37
37
|
if authorized_for(hash_for_rerun_job_invocation_path(id: job_invocation, host_ids: [ host.id ], authorizer: job_hosts_authorizer))
|
@@ -147,10 +147,9 @@ module RemoteExecutionHelper
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
-
def invocation_description(invocation
|
150
|
+
def invocation_description(invocation)
|
151
151
|
description = invocation.description.try(:capitalize) || invocation.job_category
|
152
|
-
|
153
|
-
description
|
152
|
+
trunc_with_tooltip(description, 80)
|
154
153
|
end
|
155
154
|
|
156
155
|
def invocation_result(invocation, key)
|
@@ -42,6 +42,8 @@ module Actions
|
|
42
42
|
|
43
43
|
provider_type = template_invocation.template.provider_type.to_s
|
44
44
|
proxy = determine_proxy!(proxy_selector, provider_type, host)
|
45
|
+
link!(proxy)
|
46
|
+
input[:proxy_id] = proxy.id
|
45
47
|
|
46
48
|
renderer = InputTemplateRenderer.new(template_invocation.template, host, template_invocation)
|
47
49
|
script = renderer.render
|
@@ -98,7 +98,7 @@ module ForemanRemoteExecution
|
|
98
98
|
def input(name)
|
99
99
|
return template_input_values[name.to_s] if template_input_values.key?(name.to_s)
|
100
100
|
|
101
|
-
input = find_by_name(template.template_inputs_with_foreign, name)
|
101
|
+
input = find_by_name(template.template_inputs_with_foreign, name)
|
102
102
|
if input
|
103
103
|
@preview ? input.preview(self) : input.value(self)
|
104
104
|
else
|
@@ -46,10 +46,6 @@ module ForemanRemoteExecution
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def cockpit_url
|
50
|
-
SSHExecutionProvider.cockpit_url_for_host(self.name)
|
51
|
-
end
|
52
|
-
|
53
49
|
def execution_status(options = {})
|
54
50
|
@execution_status ||= get_status(HostStatus::ExecutionStatus).to_status(options)
|
55
51
|
end
|
@@ -125,10 +121,6 @@ module ForemanRemoteExecution
|
|
125
121
|
@cached_rex_host_params_hash = nil
|
126
122
|
end
|
127
123
|
|
128
|
-
def infrastructure_host?
|
129
|
-
infrastructure_facet&.foreman_instance || infrastructure_facet&.smart_proxy_id
|
130
|
-
end
|
131
|
-
|
132
124
|
private
|
133
125
|
|
134
126
|
def extend_host_params_hash(params)
|
@@ -3,18 +3,16 @@ module ForemanRemoteExecution
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
before_validation :set_execution_flag
|
6
7
|
validate :exclusive_execution_interface
|
7
|
-
before_validation :move_execution_flag
|
8
8
|
end
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
-
def
|
13
|
-
return unless
|
12
|
+
def set_execution_flag
|
13
|
+
return unless primary? && host.present?
|
14
14
|
|
15
|
-
host.interfaces
|
16
|
-
.select { |i| i.execution? && i != self }
|
17
|
-
.each { |i| i.execution = false }
|
15
|
+
self.execution = true if host.interfaces.detect(&:execution).nil?
|
18
16
|
end
|
19
17
|
|
20
18
|
def exclusive_execution_interface
|
@@ -15,8 +15,10 @@ class JobInvocation < ApplicationRecord
|
|
15
15
|
|
16
16
|
belongs_to :targeting, :dependent => :destroy
|
17
17
|
has_many :all_template_invocations, :inverse_of => :job_invocation, :dependent => :destroy, :class_name => 'TemplateInvocation'
|
18
|
+
# rubocop:disable Rails/HasManyOrHasOneDependent
|
18
19
|
has_many :template_invocations, -> { where('template_invocations.host_id IS NOT NULL') }, :inverse_of => :job_invocation
|
19
20
|
has_many :pattern_template_invocations, -> { where('template_invocations.host_id IS NULL') }, :inverse_of => :job_invocation, :class_name => 'TemplateInvocation'
|
21
|
+
# rubocop:enable Rails/HasManyOrHasOneDependent
|
20
22
|
has_many :pattern_templates, :through => :pattern_template_invocations, :source => :template
|
21
23
|
|
22
24
|
validates :targeting, :presence => true
|
data/app/models/job_template.rb
CHANGED
@@ -17,8 +17,10 @@ class JobTemplate < ::Template
|
|
17
17
|
|
18
18
|
has_many :audits, :as => :auditable, :class_name => Audited.audit_class.name, :dependent => :nullify
|
19
19
|
has_many :all_template_invocations, :dependent => :destroy, :foreign_key => 'template_id', :class_name => 'TemplateInvocation'
|
20
|
+
# rubocop:disable Rails/HasManyOrHasOneDependent
|
20
21
|
has_many :template_invocations, -> { where('host_id IS NOT NULL') }, :foreign_key => 'template_id'
|
21
22
|
has_many :pattern_template_invocations, -> { where('host_id IS NULL') }, :foreign_key => 'template_id', :class_name => 'TemplateInvocation'
|
23
|
+
# rubocop:enable Rails/HasManyOrHasOneDependent
|
22
24
|
has_many :remote_execution_features, :dependent => :nullify
|
23
25
|
|
24
26
|
# these can't be shared in parent class, scoped search can't handle STI properly
|
@@ -192,7 +194,7 @@ class JobTemplate < ::Template
|
|
192
194
|
end
|
193
195
|
|
194
196
|
def default_input_values(ignore_keys)
|
195
|
-
result = self.template_inputs_with_foreign.select { |ti| !ti.required? && ti.
|
197
|
+
result = self.template_inputs_with_foreign.select { |ti| !ti.required? && ti.input_type == 'user' }.map { |ti| ti.name.to_s }
|
196
198
|
result -= ignore_keys.map(&:to_s)
|
197
199
|
Hash[result.map { |k| [ k, nil ] }]
|
198
200
|
end
|
data/app/models/targeting.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
</tr>
|
11
11
|
<% JobInvocation.latest_jobs.each do |invocation| %>
|
12
12
|
<tr>
|
13
|
-
<td class="ellipsis"><%= link_to_if_authorized invocation_description(invocation
|
13
|
+
<td class="ellipsis"><%= link_to_if_authorized invocation_description(invocation), hash_for_job_invocation_path(invocation).merge(:auth_object => invocation, :permission => :view_job_invocations, :authorizer => authorizer) %></td>
|
14
14
|
<td><%= link_to_invocation_task_if_authorized(invocation) %></td>
|
15
15
|
<td><%= time_in_words_span(invocation.start_at) %></td>
|
16
16
|
</tr>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<% if @hosts.any? -%>
|
8
8
|
<ul>
|
9
9
|
<% @hosts.each do |host| -%>
|
10
|
-
<li><%= link_to h(host.name),
|
10
|
+
<li><%= link_to h(host.name), host_path(host), :target => '_blank' %></li>
|
11
11
|
<% end -%>
|
12
12
|
|
13
13
|
<% if @additional > 0 -%>
|
@@ -1,14 +1,9 @@
|
|
1
1
|
<div class="tab-pane" id="template_job">
|
2
2
|
|
3
|
-
<%=
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
:name => 'job_template[job_category]',
|
8
|
-
:id => 'search',
|
9
|
-
:disabled => @template.locked?) %>
|
10
|
-
<% end %>
|
11
|
-
|
3
|
+
<%= autocomplete_f(f, :job_category,
|
4
|
+
:search_query => '',
|
5
|
+
:placeholder => _("Job category") + ' ...',
|
6
|
+
:disabled => @template.locked?) %>
|
12
7
|
<%= text_f f, :description_format,
|
13
8
|
:disabled => @template.locked?,
|
14
9
|
:label_help => description_format_help %>
|
@@ -28,7 +28,13 @@ end
|
|
28
28
|
</div>
|
29
29
|
</div>
|
30
30
|
<% if @host %>
|
31
|
-
|
31
|
+
<% proxy_id = @template_invocation_task.input[:proxy_id] %>
|
32
|
+
<h3>
|
33
|
+
<%= _('Target: ') %><%= link_to(@host.name, host_path(@host)) %>
|
34
|
+
<% if proxy_id && proxy = SmartProxy.find_by(id: proxy_id) %>
|
35
|
+
<%= _('using Smart Proxy') %> <%= link_to(proxy.name, smart_proxy_path(proxy)) %>
|
36
|
+
<% end %>
|
37
|
+
</h3>
|
32
38
|
|
33
39
|
<div class="preview hidden">
|
34
40
|
<%= preview_box(@template_invocation, @host) %>
|
@@ -152,7 +152,7 @@ module ForemanRemoteExecution
|
|
152
152
|
setting 'remote_execution_job_invocation_report_template',
|
153
153
|
type: :string,
|
154
154
|
description: N_('Select a report template used for generating a report for a particular remote execution job'),
|
155
|
-
default: '
|
155
|
+
default: 'Job invocation - report template',
|
156
156
|
full_name: N_('Job Invocation Report Template'),
|
157
157
|
collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
|
158
158
|
end
|
@@ -214,11 +214,7 @@ module ForemanRemoteExecution
|
|
214
214
|
role 'Remote Execution User', USER_PERMISSIONS, 'Role with permissions to run remote execution jobs against hosts'
|
215
215
|
role 'Remote Execution Manager', MANAGER_PERMISSIONS, 'Role with permissions to manage job templates, remote execution features, cancel jobs and view audit logs'
|
216
216
|
|
217
|
-
add_all_permissions_to_default_roles
|
218
|
-
add_permissions_to_default_roles({
|
219
|
-
Role::MANAGER => [:execute_jobs_on_infrastructure_hosts],
|
220
|
-
Role::SITE_MANAGER => USER_PERMISSIONS + [:execute_jobs_on_infrastructure_hosts],
|
221
|
-
})
|
217
|
+
add_all_permissions_to_default_roles
|
222
218
|
|
223
219
|
# add menu entry
|
224
220
|
menu :top_menu, :job_templates,
|
@@ -265,7 +261,6 @@ module ForemanRemoteExecution
|
|
265
261
|
extend_rabl_template 'api/v2/smart_proxies/main', 'api/v2/smart_proxies/pubkey'
|
266
262
|
extend_rabl_template 'api/v2/interfaces/main', 'api/v2/interfaces/execution_flag'
|
267
263
|
extend_rabl_template 'api/v2/subnets/show', 'api/v2/subnets/remote_execution_proxies'
|
268
|
-
extend_rabl_template 'api/v2/hosts/main', 'api/v2/host/main'
|
269
264
|
parameter_filter ::Subnet, :remote_execution_proxy_ids
|
270
265
|
describe_host { overview_buttons_provider :host_overview_buttons }
|
271
266
|
|
data/package.json
CHANGED
@@ -21,19 +21,20 @@
|
|
21
21
|
},
|
22
22
|
"devDependencies": {
|
23
23
|
"@babel/core": "^7.7.0",
|
24
|
-
"@theforeman/builder": "^
|
25
|
-
"@theforeman/eslint-plugin-foreman": "^
|
26
|
-
"@theforeman/stories": "^
|
27
|
-
"@theforeman/test": "^
|
28
|
-
"@theforeman/vendor-dev": "^
|
24
|
+
"@theforeman/builder": "^8.16.0",
|
25
|
+
"@theforeman/eslint-plugin-foreman": "^8.16.0",
|
26
|
+
"@theforeman/stories": "^8.16.0",
|
27
|
+
"@theforeman/test": "^8.16.0",
|
28
|
+
"@theforeman/vendor-dev": "^8.16.0",
|
29
29
|
"babel-eslint": "^10.0.0",
|
30
30
|
"eslint": "^6.8.0",
|
31
31
|
"prettier": "^1.19.1",
|
32
|
+
"@patternfly/react-catalog-view-extension": "^4.8.126",
|
32
33
|
"redux-mock-store": "^1.2.2",
|
33
34
|
"graphql-tag": "^2.11.0",
|
34
35
|
"graphql": "^15.5.0"
|
35
36
|
},
|
36
37
|
"peerDependencies": {
|
37
|
-
"@theforeman/vendor": "^
|
38
|
+
"@theforeman/vendor": "^8.16.0"
|
38
39
|
}
|
39
40
|
}
|
@@ -67,8 +67,7 @@ class ForemanRemoteExecutionHostExtensionsTest < ActiveSupport::TestCase
|
|
67
67
|
it 'should only have one execution interface' do
|
68
68
|
host.interfaces << FactoryBot.build(:nic_managed)
|
69
69
|
host.interfaces.each { |interface| interface.execution = true }
|
70
|
-
_(host).
|
71
|
-
_(host.interfaces.count(&:execution?)).must_equal 1
|
70
|
+
_(host).wont_be :valid?
|
72
71
|
end
|
73
72
|
|
74
73
|
it 'returns the execution interface' do
|
@@ -9,7 +9,7 @@ class JobReportTemplateTest < ActiveSupport::TestCase
|
|
9
9
|
|
10
10
|
context 'with valid job invocation report template' do
|
11
11
|
let(:job_invocation_template) do
|
12
|
-
file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/
|
12
|
+
file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/job_invocation_-_report_template.erb"))
|
13
13
|
template = ReportTemplate.import_without_save("Job Invocation Report Template", file_path)
|
14
14
|
template.save!
|
15
15
|
template
|
data/test/unit/targeting_test.rb
CHANGED
data/webpack/global_index.js
CHANGED
@@ -2,13 +2,9 @@ import { registerRoutes } from 'foremanReact/routes/RoutingService';
|
|
2
2
|
import routes from './Routes/routes';
|
3
3
|
import fillregistrationAdvanced from './react_app/extend/fillregistrationAdvanced';
|
4
4
|
import fillRecentJobsCard from './react_app/extend/fillRecentJobsCard';
|
5
|
-
import fillFeaturesDropdown from './react_app/extend/fillRexFeaturesDropdown';
|
6
|
-
import fillKebabItems from './react_app/extend/fillKebabItems';
|
7
5
|
import registerReducers from './react_app/extend/reducers';
|
8
6
|
|
9
7
|
registerReducers();
|
10
8
|
registerRoutes('foreman_remote_execution', routes);
|
11
|
-
fillFeaturesDropdown();
|
12
9
|
fillRecentJobsCard();
|
13
10
|
fillregistrationAdvanced();
|
14
|
-
fillKebabItems();
|
@@ -52,12 +52,7 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
|
|
52
52
|
</DropdownItem>,
|
53
53
|
]}
|
54
54
|
>
|
55
|
-
<Tabs
|
56
|
-
mountOnEnter
|
57
|
-
unmountOnExit
|
58
|
-
activeKey={activeTab}
|
59
|
-
onSelect={handleTabClick}
|
60
|
-
>
|
55
|
+
<Tabs mountOnEnter activeKey={activeTab} onSelect={handleTabClick}>
|
61
56
|
<Tab
|
62
57
|
eventKey={FINISHED_TAB}
|
63
58
|
title={<TabTitleText>{__('Finished')}</TabTitleText>}
|
@@ -19,7 +19,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
|
|
19
19
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
20
20
|
|
21
21
|
import JobStatusIcon from './JobStatusIcon';
|
22
|
-
import { JOB_API_URL, JOBS_IN_CARD
|
22
|
+
import { JOB_API_URL, JOBS_IN_CARD } from './constants';
|
23
23
|
|
24
24
|
const RecentJobsTable = ({ status, hostId }) => {
|
25
25
|
const jobsUrl =
|
@@ -30,7 +30,7 @@ const RecentJobsTable = ({ status, hostId }) => {
|
|
30
30
|
const {
|
31
31
|
response: { results: jobs },
|
32
32
|
status: responseStatus,
|
33
|
-
} = useAPI('get', jobsUrl
|
33
|
+
} = useAPI('get', jobsUrl);
|
34
34
|
|
35
35
|
return (
|
36
36
|
<DataList aria-label="recent-jobs-table" isCompact>
|
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: 5.0
|
4
|
+
version: 5.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:
|
11
|
+
date: 2021-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -201,7 +201,6 @@ files:
|
|
201
201
|
- app/views/api/v2/foreign_input_sets/index.json.rabl
|
202
202
|
- app/views/api/v2/foreign_input_sets/main.json.rabl
|
203
203
|
- app/views/api/v2/foreign_input_sets/show.json.rabl
|
204
|
-
- app/views/api/v2/host/main.rabl
|
205
204
|
- app/views/api/v2/interfaces/execution_flag.json.rabl
|
206
205
|
- app/views/api/v2/job_invocations/base.json.rabl
|
207
206
|
- app/views/api/v2/job_invocations/create.json.rabl
|
@@ -335,7 +334,6 @@ files:
|
|
335
334
|
- extra/cockpit/foreman-cockpit.service
|
336
335
|
- extra/cockpit/settings.yml.example
|
337
336
|
- foreman_remote_execution.gemspec
|
338
|
-
- jsconfig.json
|
339
337
|
- lib/foreman_remote_execution.rb
|
340
338
|
- lib/foreman_remote_execution/engine.rb
|
341
339
|
- lib/foreman_remote_execution/version.rb
|
@@ -388,7 +386,6 @@ files:
|
|
388
386
|
- test/test_plugin_helper.rb
|
389
387
|
- test/unit/actions/run_host_job_test.rb
|
390
388
|
- test/unit/actions/run_hosts_job_test.rb
|
391
|
-
- test/unit/api_params_test.rb
|
392
389
|
- test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb
|
393
390
|
- test/unit/concerns/host_extensions_test.rb
|
394
391
|
- test/unit/concerns/nic_extensions_test.rb
|
@@ -479,10 +476,6 @@ files:
|
|
479
476
|
- webpack/global_index.js
|
480
477
|
- webpack/helpers.js
|
481
478
|
- webpack/index.js
|
482
|
-
- webpack/react_app/components/FeaturesDropdown/actions.js
|
483
|
-
- webpack/react_app/components/FeaturesDropdown/constant.js
|
484
|
-
- webpack/react_app/components/FeaturesDropdown/index.js
|
485
|
-
- webpack/react_app/components/HostKebab/KebabItems.js
|
486
479
|
- webpack/react_app/components/RecentJobsCard/JobStatusIcon.js
|
487
480
|
- webpack/react_app/components/RecentJobsCard/RecentJobsCard.js
|
488
481
|
- webpack/react_app/components/RecentJobsCard/RecentJobsTable.js
|
@@ -515,9 +508,7 @@ files:
|
|
515
508
|
- webpack/react_app/components/jobInvocations/AggregateStatus/index.js
|
516
509
|
- webpack/react_app/components/jobInvocations/AggregateStatus/index.test.js
|
517
510
|
- webpack/react_app/components/jobInvocations/index.js
|
518
|
-
- webpack/react_app/extend/fillKebabItems.js
|
519
511
|
- webpack/react_app/extend/fillRecentJobsCard.js
|
520
|
-
- webpack/react_app/extend/fillRexFeaturesDropdown.js
|
521
512
|
- webpack/react_app/extend/fillregistrationAdvanced.js
|
522
513
|
- webpack/react_app/extend/reducers.js
|
523
514
|
- webpack/react_app/redux/actions/jobInvocations/index.js
|
@@ -546,7 +537,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
546
537
|
- !ruby/object:Gem::Version
|
547
538
|
version: '0'
|
548
539
|
requirements: []
|
549
|
-
rubygems_version: 3.2
|
540
|
+
rubygems_version: 3.1.2
|
550
541
|
signing_key:
|
551
542
|
specification_version: 4
|
552
543
|
summary: A plugin bringing remote execution to the Foreman, completing the config
|
@@ -573,7 +564,6 @@ test_files:
|
|
573
564
|
- test/test_plugin_helper.rb
|
574
565
|
- test/unit/actions/run_host_job_test.rb
|
575
566
|
- test/unit/actions/run_hosts_job_test.rb
|
576
|
-
- test/unit/api_params_test.rb
|
577
567
|
- test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb
|
578
568
|
- test/unit/concerns/host_extensions_test.rb
|
579
569
|
- test/unit/concerns/nic_extensions_test.rb
|
@@ -1 +0,0 @@
|
|
1
|
-
attributes :cockpit_url
|
data/jsconfig.json
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_plugin_helper'
|
4
|
-
|
5
|
-
class ApiParamsTest < ActiveSupport::TestCase
|
6
|
-
describe '#format_datetime' do
|
7
|
-
let(:params) { JobInvocationComposer::ApiParams.allocate }
|
8
|
-
|
9
|
-
it 'leaves empty string as is' do
|
10
|
-
assert_equal params.send(:format_datetime, ''), ''
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'honors explicitly supplied time zone' do
|
14
|
-
in_time_zone(ActiveSupport::TimeZone['America/New_York']) do
|
15
|
-
assert_equal '2022-07-08 08:53', params.send(:format_datetime, '2022-07-08 12:53:20 UTC')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'implicitly honors current user\'s time zone' do
|
20
|
-
in_time_zone(ActiveSupport::TimeZone['America/New_York']) do
|
21
|
-
assert_equal '2022-07-08 12:53', params.send(:format_datetime, '2022-07-08 12:53:20')
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def in_time_zone(zone)
|
27
|
-
old_tz = Time.zone
|
28
|
-
Time.zone = zone
|
29
|
-
yield
|
30
|
-
ensure
|
31
|
-
Time.zone = old_tz
|
32
|
-
end
|
33
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { foremanUrl } from 'foremanReact/common/helpers';
|
2
|
-
import { sprintf, translate as __ } from 'foremanReact/common/I18n';
|
3
|
-
import { post } from 'foremanReact/redux/API';
|
4
|
-
|
5
|
-
export const runFeature = (hostId, feature, label) => dispatch => {
|
6
|
-
const url = foremanUrl(
|
7
|
-
`/job_invocations?feature=${feature}&host_ids%5B%5D=${hostId}`
|
8
|
-
);
|
9
|
-
|
10
|
-
const successToast = () => sprintf(__('%s job has been invoked'), label);
|
11
|
-
const errorToast = ({ message }) => message;
|
12
|
-
dispatch(post({ key: feature.toUpperCase(), url, successToast, errorToast }));
|
13
|
-
};
|
@@ -1,74 +0,0 @@
|
|
1
|
-
import PropTypes from 'prop-types';
|
2
|
-
import React, { useState } from 'react';
|
3
|
-
import { useDispatch } from 'react-redux';
|
4
|
-
import {
|
5
|
-
DropdownItem,
|
6
|
-
Dropdown,
|
7
|
-
DropdownToggle,
|
8
|
-
DropdownToggleAction,
|
9
|
-
} from '@patternfly/react-core';
|
10
|
-
import { push } from 'connected-react-router';
|
11
|
-
|
12
|
-
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
|
13
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
14
|
-
import { foremanUrl } from 'foremanReact/common/helpers';
|
15
|
-
import { STATUS } from 'foremanReact/constants';
|
16
|
-
|
17
|
-
import { REX_FEATURES_API, NEW_JOB_PAGE } from './constant';
|
18
|
-
import { runFeature } from './actions';
|
19
|
-
|
20
|
-
const FeaturesDropdown = ({ hostId }) => {
|
21
|
-
const [isOpen, setIsOpen] = useState(false);
|
22
|
-
const {
|
23
|
-
response: { results: features },
|
24
|
-
status,
|
25
|
-
} = useAPI('get', foremanUrl(REX_FEATURES_API));
|
26
|
-
|
27
|
-
const dispatch = useDispatch();
|
28
|
-
const dropdownItems = features
|
29
|
-
?.filter(feature => feature.host_action_button)
|
30
|
-
?.map(({ name, label, id, description }) => (
|
31
|
-
<DropdownItem
|
32
|
-
onClick={() => dispatch(runFeature(hostId, label, name))}
|
33
|
-
key={id}
|
34
|
-
description={description}
|
35
|
-
>
|
36
|
-
{name}
|
37
|
-
</DropdownItem>
|
38
|
-
));
|
39
|
-
const scheduleJob = [
|
40
|
-
<DropdownToggleAction
|
41
|
-
onClick={() => dispatch(push(`${NEW_JOB_PAGE}=${hostId}`))}
|
42
|
-
key="schedule-job-action"
|
43
|
-
>
|
44
|
-
{__('Schedule a job')}
|
45
|
-
</DropdownToggleAction>,
|
46
|
-
];
|
47
|
-
|
48
|
-
return (
|
49
|
-
<Dropdown
|
50
|
-
alignments={{ default: 'right' }}
|
51
|
-
onSelect={() => setIsOpen(false)}
|
52
|
-
toggle={
|
53
|
-
<DropdownToggle
|
54
|
-
splitButtonItems={scheduleJob}
|
55
|
-
toggleVariant="primary"
|
56
|
-
onToggle={() => setIsOpen(prev => !prev)}
|
57
|
-
isDisabled={status === STATUS.PENDING}
|
58
|
-
splitButtonVariant="action"
|
59
|
-
/>
|
60
|
-
}
|
61
|
-
isOpen={isOpen}
|
62
|
-
dropdownItems={dropdownItems}
|
63
|
-
/>
|
64
|
-
);
|
65
|
-
};
|
66
|
-
|
67
|
-
FeaturesDropdown.propTypes = {
|
68
|
-
hostId: PropTypes.number,
|
69
|
-
};
|
70
|
-
FeaturesDropdown.defaultProps = {
|
71
|
-
hostId: undefined,
|
72
|
-
};
|
73
|
-
|
74
|
-
export default FeaturesDropdown;
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { useSelector } from 'react-redux';
|
3
|
-
import { DropdownItem } from '@patternfly/react-core';
|
4
|
-
import { CodeIcon } from '@patternfly/react-icons';
|
5
|
-
import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
|
6
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
7
|
-
import { HOST_DETAILS_KEY } from 'foremanReact/components/HostDetails/consts';
|
8
|
-
|
9
|
-
const HostKebabItems = () => {
|
10
|
-
const { cockpit_url: consoleUrl } = useSelector(state =>
|
11
|
-
selectAPIResponse(state, HOST_DETAILS_KEY)
|
12
|
-
);
|
13
|
-
|
14
|
-
if (!consoleUrl) return null;
|
15
|
-
return (
|
16
|
-
<DropdownItem
|
17
|
-
icon={<CodeIcon />}
|
18
|
-
href={consoleUrl}
|
19
|
-
target="_blank"
|
20
|
-
rel="noreferrer"
|
21
|
-
>
|
22
|
-
{__('Web Console')}
|
23
|
-
</DropdownItem>
|
24
|
-
);
|
25
|
-
};
|
26
|
-
|
27
|
-
export default HostKebabItems;
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
3
|
-
import KebabItems from '../components/HostKebab/KebabItems';
|
4
|
-
|
5
|
-
export default () =>
|
6
|
-
addGlobalFill(
|
7
|
-
'host-details-kebab',
|
8
|
-
'rex-host-details-kebab-job',
|
9
|
-
<KebabItems key="rex-host-details-kebab-job" />,
|
10
|
-
100
|
11
|
-
);
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
3
|
-
import FeaturesDropdown from '../components/FeaturesDropdown';
|
4
|
-
|
5
|
-
export default () =>
|
6
|
-
addGlobalFill(
|
7
|
-
'_rex-host-features',
|
8
|
-
'_rex-host-features',
|
9
|
-
<FeaturesDropdown key="_rex-host-features" />,
|
10
|
-
1000
|
11
|
-
);
|