foreman_remote_execution 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/helpers/job_invocations_chart_helper.rb +2 -0
- data/app/helpers/remote_execution_helper.rb +6 -2
- data/app/lib/proxy_api/remote_execution_ssh.rb +6 -0
- data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +58 -0
- data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +4 -0
- data/app/models/host_status/execution_status.rb +9 -1
- data/app/views/job_invocations/_card_results.html.erb +1 -0
- data/app/views/job_invocations/_host_status_td.html.erb +1 -1
- data/app/views/job_invocations/_tab_overview.html.erb +1 -1
- data/app/views/job_invocations/show.html.erb +1 -1
- data/config/routes.rb +2 -1
- data/foreman_remote_execution.gemspec +1 -1
- data/lib/foreman_remote_execution/engine.rb +2 -0
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/functional/job_invocations_controller_test.rb +12 -0
- data/test/models/orchestration/ssh_test.rb +24 -0
- data/test/unit/remote_execution_provider_test.rb +4 -1
- data/webpack/index.js +0 -15
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9821a3370ca6a9a1fa582ab4412d5adea5bbfc125b4102c3bc2a2c92724aaf48
|
4
|
+
data.tar.gz: 6464d913e62d09c6e7318d887f4680a5f7a996a7f537e015a07abd366bda01c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66f0fe8d87d3b70fd5f23d2892abbe6f7b525e27635bc480eaf6517ae33a3510b81a1f2732373cac7b66f54333e5731f0a457a5d63bda16f233d2615a07efbb0
|
7
|
+
data.tar.gz: 6390c063f681c358200e91b6702bcc235ff953428052ab8b39f13821e26d14b30409ad87df431af468eaf57e6a39437438422016fd817da41ccb1dfaa607b090
|
@@ -37,6 +37,8 @@ module JobInvocationsChartHelper
|
|
37
37
|
_('running %{percent}%%') % {:percent => percent}
|
38
38
|
when HostStatus::ExecutionStatus::OK
|
39
39
|
_('succeeded')
|
40
|
+
when HostStatus::ExecutionStatus::CANCELLED
|
41
|
+
_('cancelled')
|
40
42
|
when HostStatus::ExecutionStatus::ERROR
|
41
43
|
_('failed')
|
42
44
|
else
|
@@ -13,9 +13,13 @@ module RemoteExecutionHelper
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def template_invocation_status(task)
|
16
|
+
def template_invocation_status(task, parent_task)
|
17
17
|
if task.nil?
|
18
|
-
|
18
|
+
if parent_task.result == 'cancelled'
|
19
|
+
icon_text('warning-triangle-o', _('cancelled'), :kind => 'pficon')
|
20
|
+
else
|
21
|
+
icon_text('question', 'N/A', :kind => 'fa')
|
22
|
+
end
|
19
23
|
elsif task.state == 'running'
|
20
24
|
icon_text('running', _('running'), :kind => 'pficon')
|
21
25
|
elsif task.state == 'planned'
|
@@ -10,5 +10,11 @@ module ::ProxyAPI
|
|
10
10
|
rescue => e
|
11
11
|
raise ProxyException.new(url, e, N_('Unable to fetch public key'))
|
12
12
|
end
|
13
|
+
|
14
|
+
def drop_from_known_hosts(hostname)
|
15
|
+
delete('known_hosts/' + hostname)
|
16
|
+
rescue => e
|
17
|
+
raise ProxyException.new(url, e, N_('Unable to remove host from known hosts'))
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ForemanRemoteExecution
|
2
|
+
module Orchestration::SSH
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
before_destroy :ssh_destroy
|
7
|
+
after_validation :queue_ssh_destroy
|
8
|
+
register_rebuild(:queue_ssh_destroy, N_("SSH_#{self.to_s.split('::').first}"))
|
9
|
+
end
|
10
|
+
|
11
|
+
def drop_from_known_hosts(args)
|
12
|
+
proxy_id, target = args
|
13
|
+
proxy = ::SmartProxy.find(proxy_id)
|
14
|
+
begin
|
15
|
+
proxy.drop_host_from_known_hosts(target)
|
16
|
+
rescue => e
|
17
|
+
Rails.logger.warn e.message
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def ssh_destroy
|
24
|
+
logger.debug "Scheduling SSH known_hosts cleanup"
|
25
|
+
|
26
|
+
host, _kind, target = host_kind_target
|
27
|
+
proxies = host.remote_execution_proxies('SSH').values
|
28
|
+
proxies.flatten.uniq.each do |proxy|
|
29
|
+
queue.create(id: queue_id(proxy.id), name: _("Remove SSH known hosts for %s") % self,
|
30
|
+
priority: 200, action: [self, :drop_from_known_hosts, [proxy.id, target]])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def queue_ssh_destroy
|
35
|
+
should_drop_from_known_hosts? && ssh_destroy
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_drop_from_known_hosts?
|
39
|
+
host, = host_kind_target
|
40
|
+
host&.build && host&.changes&.key?('build')
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def host_kind_target
|
46
|
+
if self.is_a?(::Host::Base)
|
47
|
+
[self, 'host', name]
|
48
|
+
else
|
49
|
+
[self.host, 'interface', ip]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def queue_id(proxy_id)
|
54
|
+
_, kind, id = host_kind_target
|
55
|
+
"ssh_remove_known_hosts_#{kind}_#{id}_#{proxy_id}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -7,8 +7,10 @@ class HostStatus::ExecutionStatus < HostStatus::Status
|
|
7
7
|
QUEUED = 2
|
8
8
|
# execution is in progress, dynflow task was created
|
9
9
|
RUNNING = 3
|
10
|
+
# execution has been cancelled
|
11
|
+
CANCELLED = 4
|
10
12
|
# mapping to string representation
|
11
|
-
STATUS_NAMES = { OK => 'succeeded', ERROR => 'failed', QUEUED => 'queued', RUNNING => 'running' }.freeze
|
13
|
+
STATUS_NAMES = { OK => 'succeeded', ERROR => 'failed', QUEUED => 'queued', RUNNING => 'running', CANCELLED => 'cancelled' }.freeze
|
12
14
|
|
13
15
|
def relevant?(*args)
|
14
16
|
execution_tasks.present?
|
@@ -38,6 +40,8 @@ class HostStatus::ExecutionStatus < HostStatus::Status
|
|
38
40
|
case to_status(options)
|
39
41
|
when OK
|
40
42
|
execution_tasks.present? ? N_('Last execution succeeded') : N_('No execution finished yet')
|
43
|
+
when CANCELLED
|
44
|
+
N_('Last execution cancelled')
|
41
45
|
when ERROR
|
42
46
|
N_('Last execution failed')
|
43
47
|
else
|
@@ -54,6 +58,8 @@ class HostStatus::ExecutionStatus < HostStatus::Status
|
|
54
58
|
case status
|
55
59
|
when OK
|
56
60
|
[ "state = 'stopped' AND result = 'success'" ]
|
61
|
+
when CANCELLED
|
62
|
+
[ "state = 'stopped' AND result = 'cancelled'" ]
|
57
63
|
when ERROR
|
58
64
|
[ "state = 'stopped' AND (result = 'error' OR result = 'warning')" ]
|
59
65
|
when QUEUED
|
@@ -74,6 +80,8 @@ class HostStatus::ExecutionStatus < HostStatus::Status
|
|
74
80
|
QUEUED
|
75
81
|
elsif task.state == 'stopped' && task.result == 'success'
|
76
82
|
OK
|
83
|
+
elsif task.state == 'stopped' && task.result == 'cancelled'
|
84
|
+
CANCELLED
|
77
85
|
elsif task.pending?
|
78
86
|
RUNNING
|
79
87
|
else
|
@@ -1 +1 @@
|
|
1
|
-
<td class="host_status" id="<%= dom_id(host) %>-status" data-refresh_required="<%= task.nil? || task.pending? ? 'true' : '' %>" data-id="<%= host.id %>"><%= template_invocation_status(task) %></td>
|
1
|
+
<td class="host_status" id="<%= dom_id(host) %>-status" data-refresh_required="<%= task.nil? || task.pending? ? 'true' : '' %>" data-id="<%= host.id %>"><%= template_invocation_status(task, job_invocation.task) %></td>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% template_invocations = job_invocation.pattern_template_invocations %>
|
2
2
|
<div class='row'>
|
3
3
|
<div class="col-xs-6 col-sm-6 col-md-6">
|
4
|
-
<%= render :partial => 'card_results' %>
|
4
|
+
<%= render :partial => 'card_results', :locals => { :job_invocation => job_invocation } %>
|
5
5
|
<%= render :partial => 'card_schedule', :locals => { :job_invocation => job_invocation } %>
|
6
6
|
</div>
|
7
7
|
<div class='col-xs-12 col-sm-6 col-md-6'>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% title @job_invocation.description %>
|
2
2
|
<% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
|
3
3
|
<% javascript 'charts', 'foreman_remote_execution/template_invocation' %>
|
4
|
-
|
4
|
+
<% javascript *webpack_asset_paths('foreman_remote_execution', :extension => 'js') %>
|
5
5
|
|
6
6
|
<%= breadcrumbs name_field: 'description' %>
|
7
7
|
|
data/config/routes.rb
CHANGED
@@ -16,7 +16,8 @@ Rails.application.routes.draw do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
match 'job_invocations/new', to: 'job_invocations#new', via: [:get, :post], as: 'new_job_invocation'
|
20
|
+
resources :job_invocations, :only => [:create, :show, :index] do
|
20
21
|
collection do
|
21
22
|
post 'refresh'
|
22
23
|
get 'chart'
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.extra_rdoc_files = Dir['README*', 'LICENSE']
|
26
26
|
|
27
27
|
s.add_dependency 'deface'
|
28
|
-
s.add_dependency 'dynflow', '>= 1.0.
|
28
|
+
s.add_dependency 'dynflow', '>= 1.0.2', '< 2.0.0'
|
29
29
|
s.add_dependency 'foreman_remote_execution_core'
|
30
30
|
s.add_dependency 'foreman-tasks', '>= 0.15.1'
|
31
31
|
|
@@ -166,10 +166,12 @@ module ForemanRemoteExecution
|
|
166
166
|
|
167
167
|
Host::Managed.prepend ForemanRemoteExecution::HostExtensions
|
168
168
|
Host::Managed.include ForemanTasks::Concerns::HostActionSubject
|
169
|
+
Host::Managed.include ForemanRemoteExecution::Orchestration::SSH
|
169
170
|
|
170
171
|
(Nic::Base.descendants + [Nic::Base]).each do |klass|
|
171
172
|
klass.send(:include, ForemanRemoteExecution::NicExtensions)
|
172
173
|
end
|
174
|
+
Nic::Managed.include ForemanRemoteExecution::Orchestration::SSH
|
173
175
|
|
174
176
|
Bookmark.include ForemanRemoteExecution::BookmarkExtensions
|
175
177
|
HostsHelper.prepend ForemanRemoteExecution::HostsHelperExtensions
|
@@ -46,4 +46,16 @@ class JobInvocationsControllerTest < ActionController::TestCase
|
|
46
46
|
assert_equal(template_invocation_params,
|
47
47
|
assigns(:composer).params['template_invocations'])
|
48
48
|
end
|
49
|
+
|
50
|
+
test 'new via GET and POST' do
|
51
|
+
template = FactoryBot.create(:job_template, :with_input)
|
52
|
+
feature = FactoryBot.create(:remote_execution_feature, job_template: template)
|
53
|
+
params = { feature: feature.label, inputs: { template.template_inputs.first.name => 'foobar' } }
|
54
|
+
|
55
|
+
get :new, params: params, session: set_session_user
|
56
|
+
assert_response :success
|
57
|
+
|
58
|
+
post :new, params: params, session: set_session_user
|
59
|
+
assert_response :success
|
60
|
+
end
|
49
61
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class SSHOrchestrationTest < ActiveSupport::TestCase
|
4
|
+
let(:host) { FactoryBot.create(:host, :managed, :with_subnet) }
|
5
|
+
let(:proxy) { FactoryBot.create(:smart_proxy, :ssh) }
|
6
|
+
let(:interface) { host.interfaces.first }
|
7
|
+
|
8
|
+
before { interface.subnet.remote_execution_proxies = [proxy] }
|
9
|
+
|
10
|
+
it 'attempts to drop IP address and hostname from smart proxies on destroy' do
|
11
|
+
host.stubs(:skip_orchestration?).returns false
|
12
|
+
SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(interface.ip)
|
13
|
+
SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(host.name)
|
14
|
+
host.destroy
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'attempts to drop IP address and hostname from smart proxies on rebuild' do
|
18
|
+
host.build = true
|
19
|
+
host.save!
|
20
|
+
ids = ["ssh_remove_known_hosts_interface_#{interface.ip}_#{proxy.id}",
|
21
|
+
"ssh_remove_known_hosts_host_#{host.name}_#{proxy.id}"]
|
22
|
+
_(host.queue.task_ids).must_equal ids
|
23
|
+
end
|
24
|
+
end
|
@@ -149,7 +149,10 @@ class RemoteExecutionProviderTest < ActiveSupport::TestCase
|
|
149
149
|
FactoryBot.create(:host) do |host|
|
150
150
|
host.interfaces = [FactoryBot.build(:nic_managed, flags.merge(:ip => nil, :name => 'somehost.somedomain.org', :primary => true)),
|
151
151
|
FactoryBot.build(:nic_managed, flags.merge(:ip => '127.0.0.1'))]
|
152
|
-
end
|
152
|
+
end.reload
|
153
|
+
# Reassigning the interfaces triggers the on-deletion ssh key removal for the interface which is being replaced
|
154
|
+
# This has an undesired side effect of caching the original interface as execution one which made the tests
|
155
|
+
# give wrong results. Reloading the host wipes the cache
|
153
156
|
end
|
154
157
|
|
155
158
|
let(:flags) do
|
data/webpack/index.js
CHANGED
@@ -12,18 +12,3 @@ componentRegistry.register({
|
|
12
12
|
});
|
13
13
|
|
14
14
|
registerReducer('foremanRemoteExecutionReducers', rootReducer);
|
15
|
-
|
16
|
-
if (window.location.href.match(/job_invocations/)) {
|
17
|
-
const jobInvocationId = parseInt(
|
18
|
-
new URI(window.location.href).filename(),
|
19
|
-
10,
|
20
|
-
);
|
21
|
-
|
22
|
-
const mountJobInvocationContainer = () => {
|
23
|
-
mount('JobInvocationContainer', '#status_chart', {
|
24
|
-
url: `/job_invocations/chart?id=${jobInvocationId}`,
|
25
|
-
});
|
26
|
-
};
|
27
|
-
|
28
|
-
document.addEventListener('page:change', mountJobInvocationContainer);
|
29
|
-
}
|
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: 3.
|
4
|
+
version: 3.2.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: 2020-
|
11
|
+
date: 2020-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0.
|
33
|
+
version: 1.0.2
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: 2.0.0
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 1.0.
|
43
|
+
version: 1.0.2
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 2.0.0
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- app/models/concerns/foreman_remote_execution/foreman_tasks_triggering_extensions.rb
|
179
179
|
- app/models/concerns/foreman_remote_execution/host_extensions.rb
|
180
180
|
- app/models/concerns/foreman_remote_execution/nic_extensions.rb
|
181
|
+
- app/models/concerns/foreman_remote_execution/orchestration/ssh.rb
|
181
182
|
- app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb
|
182
183
|
- app/models/concerns/foreman_remote_execution/subnet_extensions.rb
|
183
184
|
- app/models/concerns/foreman_remote_execution/taxonomy_extensions.rb
|
@@ -377,6 +378,7 @@ files:
|
|
377
378
|
- test/functional/job_invocations_controller_test.rb
|
378
379
|
- test/functional/job_templates_controller_test.rb
|
379
380
|
- test/helpers/remote_execution_helper_test.rb
|
381
|
+
- test/models/orchestration/ssh_test.rb
|
380
382
|
- test/test_plugin_helper.rb
|
381
383
|
- test/unit/actions/run_host_job_test.rb
|
382
384
|
- test/unit/actions/run_hosts_job_test.rb
|
@@ -442,6 +444,7 @@ test_files:
|
|
442
444
|
- test/functional/job_invocations_controller_test.rb
|
443
445
|
- test/functional/job_templates_controller_test.rb
|
444
446
|
- test/helpers/remote_execution_helper_test.rb
|
447
|
+
- test/models/orchestration/ssh_test.rb
|
445
448
|
- test/test_plugin_helper.rb
|
446
449
|
- test/unit/actions/run_host_job_test.rb
|
447
450
|
- test/unit/actions/run_hosts_job_test.rb
|