foreman_remote_execution 3.3.2 → 4.0.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/.github/workflows/ci.yml +2 -1
- data/app/assets/stylesheets/foreman_remote_execution/job_invocations.scss +6 -5
- data/app/controllers/api/v2/job_invocations_controller.rb +3 -2
- data/app/controllers/job_invocations_controller.rb +22 -8
- data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
- data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
- data/app/lib/foreman_remote_execution/renderer/scope/input.rb +35 -0
- data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +11 -4
- data/app/models/job_invocation.rb +6 -3
- data/app/models/job_invocation_composer.rb +2 -2
- data/app/models/remote_execution_provider.rb +2 -2
- data/app/models/setting/remote_execution.rb +2 -2
- data/app/models/ssh_execution_provider.rb +1 -1
- data/app/services/default_proxy_proxy_selector.rb +3 -1
- data/app/views/api/v2/job_invocations/main.json.rabl +2 -2
- data/app/views/job_invocations/_card_target_hosts.html.erb +1 -1
- data/app/views/job_invocations/_form.html.erb +1 -1
- data/app/views/job_invocations/_tab_hosts.html.erb +1 -20
- data/app/views/job_invocations/index.html.erb +2 -1
- data/app/views/job_invocations/show.html.erb +9 -0
- data/app/views/job_invocations/show.js.erb +5 -0
- data/app/views/job_invocations/show.json.erb +2 -1
- data/app/views/templates/ssh/package_action.erb +1 -0
- data/app/views/templates/ssh/puppet_agent_disable.erb +3 -0
- data/app/views/templates/ssh/puppet_agent_enable.erb +3 -0
- data/app/views/templates/ssh/puppet_install_modules_from_forge.erb +3 -0
- data/app/views/templates/ssh/puppet_run_once.erb +3 -0
- data/db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb +34 -0
- data/db/seeds.d/20-permissions.rb +9 -0
- data/lib/foreman_remote_execution/engine.rb +4 -1
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/functional/api/v2/job_invocations_controller_test.rb +65 -2
- data/test/functional/job_invocations_controller_test.rb +71 -0
- data/test/models/orchestration/ssh_test.rb +1 -1
- data/test/support/remote_execution_helper.rb +5 -0
- data/test/unit/actions/run_host_job_test.rb +3 -3
- data/test/unit/actions/run_hosts_job_test.rb +1 -1
- data/test/unit/job_invocation_composer_test.rb +5 -5
- data/test/unit/remote_execution_provider_test.rb +6 -6
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
- data/webpack/__mocks__/foremanReact/components/SearchBar.js +2 -0
- data/webpack/__mocks__/foremanReact/constants.js +21 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +2 -0
- data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js +1 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHosts.js +21 -15
- data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +10 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +62 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss +6 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js +10 -2
- data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js +9 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js +26 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap +16 -1
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +68 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap +11 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +35 -19
- data/webpack/react_app/components/TargetingHosts/index.js +73 -13
- metadata +18 -3
- data/webpack/react_app/components/TargetingHosts/TargetingHostsActions.js +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93860edb8974a0691383b3a199a1a2d079d10401d7780b99aa6275b75125eb58
|
4
|
+
data.tar.gz: d333f8eb85a42b36694dee932447d4364b57ed2c095ad5a055d1e7adf69a9866
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70c300e719d6587639719a4d95aa23da2d3f3a16d51692392c789b70cd381b31320789db0f45b57c129e4b90d36bd1a8ddadd29db4f38f2d9e40a39219b1d130
|
7
|
+
data.tar.gz: 1feab0c5cfd3fee6054a004eba812b7257df80a2dce50aa200d15dd20797f24f8a614d802668ac6daf043c189b7caa8e8d5f0d4a997726764c80c91173d9437b
|
data/.github/workflows/ci.yml
CHANGED
@@ -30,10 +30,11 @@ jobs:
|
|
30
30
|
strategy:
|
31
31
|
fail-fast: false
|
32
32
|
matrix:
|
33
|
-
foreman-core-branch: [
|
33
|
+
foreman-core-branch: [develop]
|
34
34
|
ruby-version: [2.5, 2.6]
|
35
35
|
node-version: [12]
|
36
36
|
steps:
|
37
|
+
- run: sudo apt-get update
|
37
38
|
- run: sudo apt-get install build-essential libcurl4-openssl-dev zlib1g-dev libpq-dev
|
38
39
|
- uses: actions/checkout@v2
|
39
40
|
with:
|
@@ -18,14 +18,14 @@ module Api
|
|
18
18
|
|
19
19
|
api :GET, '/job_invocations/:id', N_('Show job invocation')
|
20
20
|
param :id, :identifier, :required => true
|
21
|
-
param :host_status,
|
21
|
+
param :host_status, :bool, required: false, desc: N_('Show Job status for the hosts')
|
22
22
|
def show
|
23
23
|
@hosts = @job_invocation.targeting.hosts.authorized(:view_hosts, Host)
|
24
24
|
@template_invocations = @job_invocation.template_invocations
|
25
25
|
.where(host: @hosts)
|
26
26
|
.includes(:input_values)
|
27
27
|
|
28
|
-
if params[:host_status]
|
28
|
+
if params[:host_status] == 'true'
|
29
29
|
template_invocations = @template_invocations.includes(:run_host_job_task).to_a
|
30
30
|
@host_statuses = Hash[template_invocations.map { |ti| [ti.host_id, template_invocation_status(ti)] }]
|
31
31
|
end
|
@@ -80,6 +80,7 @@ module Api
|
|
80
80
|
end
|
81
81
|
composer.trigger!
|
82
82
|
@job_invocation = composer.job_invocation
|
83
|
+
@hosts = @job_invocation.targeting.hosts
|
83
84
|
process_response @job_invocation
|
84
85
|
end
|
85
86
|
|
@@ -52,16 +52,18 @@ class JobInvocationsController < ApplicationController
|
|
52
52
|
|
53
53
|
def show
|
54
54
|
@job_invocation = resource_base.includes(:template_invocations => :run_host_job_task).find(params[:id])
|
55
|
-
@auto_refresh = @job_invocation.task.try(:pending?)
|
56
|
-
@resource_base = @job_invocation.targeting.hosts.authorized(:view_hosts, Host)
|
57
|
-
# There's no need to do the joining if we're not filtering
|
58
|
-
unless params[:search].nil?
|
59
|
-
@resource_base = @resource_base.joins(:template_invocations)
|
60
|
-
.where(:template_invocations => { :job_invocation_id => @job_invocation.id})
|
61
|
-
end
|
62
|
-
@hosts = resource_base_search_and_page
|
63
55
|
@job_organization = Taxonomy.find_by(id: @job_invocation.task.input[:current_organization_id])
|
64
56
|
@job_location = Taxonomy.find_by(id: @job_invocation.task.input[:current_location_id])
|
57
|
+
@auto_refresh = @job_invocation.task.try(:pending?)
|
58
|
+
|
59
|
+
respond_to do |format|
|
60
|
+
format.json do
|
61
|
+
targeting_hosts_resources
|
62
|
+
end
|
63
|
+
|
64
|
+
format.html
|
65
|
+
format.js
|
66
|
+
end
|
65
67
|
end
|
66
68
|
|
67
69
|
def index
|
@@ -153,4 +155,16 @@ class JobInvocationsController < ApplicationController
|
|
153
155
|
JobInvocationComposer.from_ui_params(with_triggering)
|
154
156
|
end
|
155
157
|
end
|
158
|
+
|
159
|
+
def targeting_hosts_resources
|
160
|
+
@auto_refresh = @job_invocation.task.try(:pending?)
|
161
|
+
@resource_base = @job_invocation.targeting.hosts.authorized(:view_hosts, Host)
|
162
|
+
|
163
|
+
unless params[:search].nil?
|
164
|
+
@resource_base = @resource_base.joins(:template_invocations)
|
165
|
+
.where(:template_invocations => { :job_invocation_id => @job_invocation.id})
|
166
|
+
end
|
167
|
+
@hosts = resource_base_search_and_page
|
168
|
+
@total_hosts = resource_base_with_search.size
|
169
|
+
end
|
156
170
|
end
|
@@ -60,7 +60,7 @@ module Actions
|
|
60
60
|
def secrets(host, job_invocation, provider)
|
61
61
|
job_secrets = { :ssh_password => job_invocation.password,
|
62
62
|
:key_passphrase => job_invocation.key_passphrase,
|
63
|
-
:
|
63
|
+
:effective_user_password => job_invocation.effective_user_password }
|
64
64
|
|
65
65
|
job_secrets.merge(provider.secrets(host)) { |_key, job_secret, provider_secret| job_secret || provider_secret }
|
66
66
|
end
|
@@ -47,7 +47,7 @@ module Actions
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def finalize
|
50
|
-
job_invocation.password = job_invocation.key_passphrase = job_invocation.
|
50
|
+
job_invocation.password = job_invocation.key_passphrase = job_invocation.effective_user_password = nil
|
51
51
|
job_invocation.save!
|
52
52
|
|
53
53
|
Rails.logger.debug "cleaning cache for keys that begin with 'job_invocation_#{job_invocation.id}'"
|
@@ -3,14 +3,33 @@ module ForemanRemoteExecution
|
|
3
3
|
module Scope
|
4
4
|
class Input < ::Foreman::Renderer::Scope::Template
|
5
5
|
include Foreman::Renderer::Scope::Macros::HostTemplate
|
6
|
+
extend ApipieDSL::Class
|
6
7
|
|
7
8
|
attr_reader :template, :host, :invocation, :input_template_instance, :current_user
|
8
9
|
delegate :input, to: :input_template_instance
|
9
10
|
|
11
|
+
apipie :class, 'Macros related to template rendering' do
|
12
|
+
name 'Template Input Render'
|
13
|
+
sections only: %w[all jobs]
|
14
|
+
end
|
15
|
+
|
16
|
+
apipie :method, 'Always raises an error with a description provided as an argument' do
|
17
|
+
desc 'This method is useful for aborting script execution if some of the conditions are not met'
|
18
|
+
required :message, String, desc: 'Description for the error'
|
19
|
+
raises error: ::InputTemplateRenderer::RenderError, desc: 'The error is always being raised'
|
20
|
+
returns nil, desc: "Doesn't return anything"
|
21
|
+
example "<%
|
22
|
+
@host.operatingsystem #=> nil
|
23
|
+
render_error(N_('Unsupported or no operating system found for this host.')) unless @host.operatingsystem #=> InputTemplateRenderer::RenderError is raised and the execution of the script is aborted
|
24
|
+
%>"
|
25
|
+
end
|
10
26
|
def render_error(message)
|
11
27
|
raise ::InputTemplateRenderer::RenderError.new(message)
|
12
28
|
end
|
13
29
|
|
30
|
+
apipie :method, 'Check whether the template in preview mode or not' do
|
31
|
+
returns one_of: [true, false], desc: 'Returns true if the template in preview mode, false otherwise'
|
32
|
+
end
|
14
33
|
def preview?
|
15
34
|
!!@preview
|
16
35
|
end
|
@@ -23,6 +42,16 @@ module ForemanRemoteExecution
|
|
23
42
|
Rails.cache.fetch(cache_key, &block)
|
24
43
|
end
|
25
44
|
|
45
|
+
# rubocop:disable Lint/InterpolationCheck
|
46
|
+
apipie :method, 'Render template by given name' do
|
47
|
+
required :template_name, String, desc: 'name of the template to render'
|
48
|
+
optional :input_values, Hash, desc: 'key:value list of input values for the template'
|
49
|
+
optional :options, Hash, desc: 'Additional options such as :with_foreign_input_set. Set to true if a foreign input set should be considered when rendering the template'
|
50
|
+
raises error: StandardError, desc: 'raises an error if there is no template or template input with such name'
|
51
|
+
returns String, desc: 'Rendered template'
|
52
|
+
example '<%= render_template("Run Command - Ansible Default", command: "yum -y group install #{input("package")}") %>'
|
53
|
+
end
|
54
|
+
# rubocop:enable Lint/InterpolationCheck
|
26
55
|
def render_template(template_name, input_values = {}, options = {})
|
27
56
|
options.assert_valid_keys(:with_foreign_input_set)
|
28
57
|
with_foreign_input_set = options.fetch(:with_foreign_input_set, true)
|
@@ -59,6 +88,12 @@ module ForemanRemoteExecution
|
|
59
88
|
input_values.merge(overrides).with_indifferent_access
|
60
89
|
end
|
61
90
|
|
91
|
+
apipie :method, 'Returns the value of template input' do
|
92
|
+
required :name, String, desc: 'name of the template input'
|
93
|
+
raises error: UndefinedInput, desc: 'when there is no input with such name defined for the current template'
|
94
|
+
returns Object, desc: 'The value of template input'
|
95
|
+
example 'input("Include Facts") #=> "yes"'
|
96
|
+
end
|
62
97
|
def input(name)
|
63
98
|
return template_input_values[name.to_s] if template_input_values.key?(name.to_s)
|
64
99
|
|
@@ -15,9 +15,13 @@ module ForemanRemoteExecution
|
|
15
15
|
proxy = ::SmartProxy.find(proxy_id)
|
16
16
|
begin
|
17
17
|
proxy.drop_host_from_known_hosts(target)
|
18
|
-
rescue
|
19
|
-
|
20
|
-
|
18
|
+
rescue ::ProxyAPI::ProxyException => e
|
19
|
+
if e.wrapped_exception.is_a?(RestClient::NotFound)
|
20
|
+
# ignore 404 when known_hosts entry is missing or the module was not enabled
|
21
|
+
Foreman::Logging.exception "Proxy failed to delete SSH known_hosts for #{name}, #{ip}", e, :level => :error
|
22
|
+
else
|
23
|
+
raise e
|
24
|
+
end
|
21
25
|
rescue => e
|
22
26
|
Rails.logger.warn e.message
|
23
27
|
return false
|
@@ -29,7 +33,10 @@ module ForemanRemoteExecution
|
|
29
33
|
logger.debug "Scheduling SSH known_hosts cleanup"
|
30
34
|
|
31
35
|
host, _kind, _target = host_kind_target
|
32
|
-
|
36
|
+
# #remote_execution_proxies may not be defined on the host object in some case
|
37
|
+
# for example Host::Discovered does not have it defined, even though these hosts
|
38
|
+
# have Nic::Managed interfaces associated with them
|
39
|
+
proxies = (host.try(:remote_execution_proxies, 'SSH') || {}).values
|
33
40
|
proxies.flatten.uniq.each do |proxy|
|
34
41
|
queue.create(id: queue_id(proxy.id), name: _("Remove SSH known hosts for %s") % self,
|
35
42
|
priority: 200, action: [self, :drop_from_known_hosts, proxy.id])
|
@@ -41,7 +41,10 @@ class JobInvocation < ApplicationRecord
|
|
41
41
|
has_many :template_invocation_tasks, :through => :template_invocations,
|
42
42
|
:class_name => 'ForemanTasks::Task',
|
43
43
|
:source => 'run_host_job_task'
|
44
|
-
|
44
|
+
has_one :user, through: :task
|
45
|
+
scoped_search relation: :user, on: :login, rename: 'user', complete_value: true,
|
46
|
+
value_translation: ->(value) { value == 'current_user' ? User.current.login : value },
|
47
|
+
special_values: [:current_user], aliases: ['owner'], :only_explicit => true
|
45
48
|
scoped_search :relation => :task, :on => :started_at, :rename => 'started_at', :complete_value => true
|
46
49
|
scoped_search :relation => :task, :on => :start_at, :rename => 'start_at', :complete_value => true
|
47
50
|
scoped_search :relation => :task, :on => :ended_at, :rename => 'ended_at', :complete_value => true
|
@@ -70,7 +73,7 @@ class JobInvocation < ApplicationRecord
|
|
70
73
|
|
71
74
|
delegate :start_at, :to => :task, :allow_nil => true
|
72
75
|
|
73
|
-
encrypts :password, :key_passphrase, :
|
76
|
+
encrypts :password, :key_passphrase, :effective_user_password
|
74
77
|
|
75
78
|
def self.search_by_status(key, operator, value)
|
76
79
|
conditions = HostStatus::ExecutionStatus::ExecutionTaskStatusMapper.sql_conditions_for(value)
|
@@ -139,7 +142,7 @@ class JobInvocation < ApplicationRecord
|
|
139
142
|
invocation.pattern_template_invocations = self.pattern_template_invocations.map(&:deep_clone)
|
140
143
|
invocation.password = self.password
|
141
144
|
invocation.key_passphrase = self.key_passphrase
|
142
|
-
invocation.
|
145
|
+
invocation.effective_user_password = self.effective_user_password
|
143
146
|
end
|
144
147
|
end
|
145
148
|
|
@@ -15,7 +15,7 @@ class JobInvocationComposer
|
|
15
15
|
:description_format => job_invocation_base[:description_format],
|
16
16
|
:password => blank_to_nil(job_invocation_base[:password]),
|
17
17
|
:key_passphrase => blank_to_nil(job_invocation_base[:key_passphrase]),
|
18
|
-
:
|
18
|
+
:effective_user_password => blank_to_nil(job_invocation_base[:effective_user_password]),
|
19
19
|
:concurrency_control => concurrency_control_params,
|
20
20
|
:execution_timeout_interval => execution_timeout_interval,
|
21
21
|
:template_invocations => template_invocations_params }.with_indifferent_access
|
@@ -348,7 +348,7 @@ class JobInvocationComposer
|
|
348
348
|
job_invocation.execution_timeout_interval = params[:execution_timeout_interval]
|
349
349
|
job_invocation.password = params[:password]
|
350
350
|
job_invocation.key_passphrase = params[:key_passphrase]
|
351
|
-
job_invocation.
|
351
|
+
job_invocation.effective_user_password = params[:effective_user_password]
|
352
352
|
|
353
353
|
if @reruns && job_invocation.targeting.static?
|
354
354
|
job_invocation.targeting.host_ids = JobInvocation.find(@reruns).targeting.host_ids
|
@@ -57,8 +57,8 @@ class RemoteExecutionProvider
|
|
57
57
|
[true, 'true', 'True', 'TRUE', '1'].include?(setting)
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
host_setting(host, :
|
60
|
+
def effective_user_password(host)
|
61
|
+
host_setting(host, :remote_execution_effective_user_password)
|
62
62
|
end
|
63
63
|
|
64
64
|
def effective_interfaces(host)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Setting::RemoteExecution < Setting
|
2
2
|
|
3
|
-
::Setting::BLANK_ATTRS.concat %w{remote_execution_ssh_password remote_execution_ssh_key_passphrase remote_execution_sudo_password remote_execution_cockpit_url remote_execution_form_job_template}
|
3
|
+
::Setting::BLANK_ATTRS.concat %w{remote_execution_ssh_password remote_execution_ssh_key_passphrase remote_execution_sudo_password remote_execution_effective_user_password remote_execution_cockpit_url remote_execution_form_job_template}
|
4
4
|
|
5
5
|
def self.default_settings
|
6
6
|
[
|
@@ -27,7 +27,7 @@ class Setting::RemoteExecution < Setting
|
|
27
27
|
N_('Effective User Method'),
|
28
28
|
nil,
|
29
29
|
{ :collection => proc { Hash[SSHExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] } }),
|
30
|
-
self.set('
|
30
|
+
self.set('remote_execution_effective_user_password', N_("Effective user password"), '', N_("Effective user password"), nil, {:encrypted => true}),
|
31
31
|
self.set('remote_execution_sync_templates',
|
32
32
|
N_('Whether we should sync templates from disk when running db:seed.'),
|
33
33
|
true,
|
@@ -32,7 +32,7 @@ class SSHExecutionProvider < RemoteExecutionProvider
|
|
32
32
|
{
|
33
33
|
:ssh_password => ssh_password(host),
|
34
34
|
:key_passphrase => ssh_key_passphrase(host),
|
35
|
-
:
|
35
|
+
:effective_user_password => effective_user_password(host),
|
36
36
|
}
|
37
37
|
end
|
38
38
|
|
@@ -10,7 +10,9 @@ class DefaultProxyProxySelector < ::RemoteExecutionProxySelector
|
|
10
10
|
def available_proxies(host, provider)
|
11
11
|
# TODO: Once we have a internal proxy marker/feature on the proxy, we can
|
12
12
|
# swap the implementation
|
13
|
-
|
13
|
+
raise _('default_capsule method missing from SmartProxy') unless ::SmartProxy.respond_to?(:default_capsule)
|
14
|
+
|
15
|
+
internal_proxy = ::SmartProxy.default_capsule
|
14
16
|
super.reduce({}) do |acc, (key, proxies)|
|
15
17
|
acc.merge(key => proxies.select { |proxy| proxy == internal_proxy })
|
16
18
|
end
|
@@ -19,10 +19,10 @@ child :targeting do
|
|
19
19
|
attributes :bookmark_id, :search_query, :targeting_type, :user_id, :status, :status_label,
|
20
20
|
:randomized_ordering
|
21
21
|
|
22
|
-
child @hosts do
|
22
|
+
child @hosts => :hosts do
|
23
23
|
extends 'api/v2/hosts/base'
|
24
24
|
|
25
|
-
if params[:host_status]
|
25
|
+
if params[:host_status] == 'true'
|
26
26
|
node :job_status do |host|
|
27
27
|
@host_statuses[host.id]
|
28
28
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% template_invocations = job_invocation.pattern_template_invocations %>
|
2
|
-
<div class="card-pf card-pf-accented">
|
2
|
+
<div class="card-pf card-pf-accented target-hosts-card">
|
3
3
|
<div class="card-pf-title">
|
4
4
|
<h2 style="height: 18px;" class="card-pf-title">
|
5
5
|
<%= _('Target hosts') %>
|
@@ -95,7 +95,7 @@
|
|
95
95
|
<div class="advanced hidden">
|
96
96
|
<%= password_f f, :password, :placeholder => '*****', :label => _('Password'), :label_help => N_('Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution.') %>
|
97
97
|
<%= password_f f, :key_passphrase, :placeholder => '*****', :label => _('Private key passphrase'), :label_help => N_('Key passhprase is only applicable for SSH provider. Other providers ignore this field. <br> Passphrase is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution.') %>
|
98
|
-
<%= password_f f, :
|
98
|
+
<%= password_f f, :effective_user_password, :placeholder => '*****', :label => _('Effective user password'), :label_help => N_('Effective user password is only applicable for SSH provider. Other providers ignore this field. <br> Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution.') %>
|
99
99
|
</div>
|
100
100
|
|
101
101
|
<div class="advanced hidden">
|
@@ -1,24 +1,5 @@
|
|
1
1
|
<% if job_invocation.resolved? %>
|
2
|
-
<%=
|
3
|
-
<div class="row">
|
4
|
-
<div class="title_filter col-md-6">
|
5
|
-
<div class="input-group">
|
6
|
-
<%= autocomplete_f(f, :search, value: params[:search].try(:squeeze, " "), placeholder: _("Filter") + ' ...', path: hosts_path, only_input: true) %>
|
7
|
-
<span class="input-group-btn">
|
8
|
-
<button class="btn btn-default" type="submit">
|
9
|
-
<%= icon_text('search', content_tag(:span, _('Search'), :class => 'hidden-xs', :kind => 'fa')) %>
|
10
|
-
</button>
|
11
|
-
</span>
|
12
|
-
</div>
|
13
|
-
</div>
|
14
|
-
</div>
|
15
|
-
<% end %>
|
16
|
-
<br>
|
17
|
-
|
18
|
-
<div id="targeting_hosts">
|
19
|
-
<%= mount_react_component('TargetingHosts', '#targeting_hosts') %>
|
20
|
-
</div>
|
21
|
-
<%= will_paginate_with_info @hosts, :container => true %>
|
2
|
+
<%= react_component('TargetingHosts' ) %>
|
22
3
|
<% else %>
|
23
4
|
<div class="alert alert-warning">
|
24
5
|
<%=
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
|
1
2
|
<% title _('Job invocations') %>
|
2
3
|
|
3
4
|
<% title_actions(job_invocations_buttons) %>
|
@@ -19,7 +20,7 @@
|
|
19
20
|
<tbody>
|
20
21
|
<% @job_invocations.each do |invocation| %>
|
21
22
|
<tr>
|
22
|
-
<td><%= link_to_if_authorized invocation_description(invocation), hash_for_job_invocation_path(invocation).merge(:auth_object => invocation, :permission => :view_job_invocations, :authorizer => authorizer) %></td>
|
23
|
+
<td class="text_warp"><%= link_to_if_authorized invocation_description(invocation), hash_for_job_invocation_path(invocation).merge(:auth_object => invocation, :permission => :view_job_invocations, :authorizer => authorizer) %></td>
|
23
24
|
<td><%= trunc_with_tooltip(invocation&.targeting&.search_query, 15) %></td>
|
24
25
|
<td><%= link_to_invocation_task_if_authorized(invocation) %></td>
|
25
26
|
<td><%= invocation_result(invocation, :success_count) %></td>
|
@@ -2,6 +2,9 @@
|
|
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
|
+
<% content_for(:stylesheets) do %>
|
6
|
+
<%= webpacked_plugins_css_for :foreman_remote_execution %>
|
7
|
+
<% end %>
|
5
8
|
|
6
9
|
<%= breadcrumbs name_field: 'description' %>
|
7
10
|
|
@@ -41,3 +44,9 @@
|
|
41
44
|
<% end %>
|
42
45
|
<%= render_tab_content_for(:main_tabs, subject: @job_invocation) %>
|
43
46
|
</div>
|
47
|
+
|
48
|
+
<script id="job_invocation_refresh" data-refresh-url="<%= job_invocation_path(@job_invocation) %>">
|
49
|
+
<% if @auto_refresh %>
|
50
|
+
delayed_refresh($('script#job_invocation_refresh').data('refresh-url'), {});
|
51
|
+
<% end %>
|
52
|
+
</script>
|
@@ -97,6 +97,7 @@ handle_zypp_res_codes () {
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
-%>
|
100
|
+
[ -x "$(command -v subscription-manager)" ] && subscription-manager refresh
|
100
101
|
apt-get -y update
|
101
102
|
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y <%= action %> <%= input("package") %>
|
102
103
|
<% elsif package_manager == 'zypper' -%>
|
@@ -13,4 +13,7 @@ template_inputs:
|
|
13
13
|
provider_type: SSH
|
14
14
|
kind: job_template
|
15
15
|
-%>
|
16
|
+
<% if @host.operatingsystem.family == 'Debian' -%>
|
17
|
+
export PATH=/opt/puppetlabs/bin:$PATH
|
18
|
+
<% end -%>
|
16
19
|
puppet agent --disable "<%= input("comment").present? ? input("comment") : "Disabled using Foreman Remote Execution" %> - <%= current_user %> - $(date "+%d/%m/%Y %H:%M")"
|