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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36a15d0142caa911a59ff7d9797ceab5dabb0e601f605c0fee3d547d1be168f5
4
- data.tar.gz: d41aba8d661cae6ef74cfee2bd9e007a37f218c3056e9d9b8ae3a1de5f243bc6
3
+ metadata.gz: 9821a3370ca6a9a1fa582ab4412d5adea5bbfc125b4102c3bc2a2c92724aaf48
4
+ data.tar.gz: 6464d913e62d09c6e7318d887f4680a5f7a996a7f537e015a07abd366bda01c8
5
5
  SHA512:
6
- metadata.gz: 20d61e7658cda93e3f24340ae6caa65c1c7868f37e699d7e6a9da524f2acaef9cccdf86cd47a7d2a1386037ad5aac0900935f3c3b2b4706926f16e60245f1b64
7
- data.tar.gz: 66e0c4b3af2d1feab711fe90b2af6a5ce08d4159501a1725a98243647a022431d871081bf2d1e82d46f8490c41589a1df6f15f2ee6f13391fb10df240bd41fe4
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
- icon_text('question', 'N/A', :kind => 'fa')
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
@@ -12,6 +12,10 @@ module ForemanRemoteExecution
12
12
  key
13
13
  end
14
14
 
15
+ def drop_host_from_known_hosts(host)
16
+ ::ProxyAPI::RemoteExecutionSSH.new(:url => url).drop_from_known_hosts(host)
17
+ end
18
+
15
19
  def refresh
16
20
  errors = super
17
21
  update_pubkey
@@ -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
@@ -5,6 +5,7 @@
5
5
  </h2>
6
6
  <div class="card-pf-body">
7
7
  <div id='status_chart'>
8
+ <%= react_component('JobInvocationContainer', data: { url: "/job_invocations/chart?id=#{job_invocation.id}" }) %>
8
9
  </div>
9
10
  </div>
10
11
  </div>
@@ -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
- <%= javascript_include_tag *webpack_asset_paths('foreman_remote_execution', :extension => 'js'), "data-turbolinks-track" => true, 'defer' => 'defer' %>
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
- resources :job_invocations, :only => [:new, :create, :show, :index] do
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.1', '< 2.0.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
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '3.1.0'.freeze
2
+ VERSION = '3.2.0'.freeze
3
3
  end
@@ -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.1.0
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-04-07 00:00:00.000000000 Z
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.1
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.1
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