foreman_remote_execution 3.0.3 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +2 -1
- data/.rubocop.yml +80 -50
- data/.rubocop_todo.yml +113 -73
- data/Gemfile +4 -0
- data/app/controllers/api/v2/foreign_input_sets_controller.rb +3 -2
- data/app/controllers/api/v2/job_invocations_controller.rb +7 -6
- data/app/controllers/api/v2/job_templates_controller.rb +3 -2
- data/app/controllers/api/v2/remote_execution_features_controller.rb +3 -2
- data/app/controllers/api/v2/template_invocations_controller.rb +1 -1
- data/app/controllers/cockpit_controller.rb +1 -0
- data/app/controllers/concerns/foreman/controller/parameters/foreign_input_set.rb +1 -1
- data/app/controllers/concerns/foreman/controller/parameters/job_template.rb +4 -4
- data/app/controllers/job_invocations_controller.rb +10 -6
- data/app/controllers/job_templates_controller.rb +1 -1
- data/app/controllers/remote_execution_features_controller.rb +3 -2
- data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +16 -5
- data/app/helpers/job_invocations_chart_helper.rb +11 -10
- data/app/helpers/job_invocations_helper.rb +13 -5
- data/app/helpers/remote_execution_helper.rb +43 -46
- data/app/lib/actions/remote_execution/run_host_job.rb +5 -6
- data/app/lib/actions/remote_execution/run_hosts_job.rb +2 -2
- data/app/lib/foreman_remote_execution/renderer/scope/input.rb +1 -0
- data/app/models/concerns/foreman_remote_execution/errors_flattener.rb +0 -2
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +3 -5
- data/app/models/concerns/foreman_remote_execution/nic_extensions.rb +1 -0
- data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +1 -0
- data/app/models/foreign_input_set.rb +3 -2
- data/app/models/input_template_renderer.rb +1 -1
- data/app/models/job_invocation.rb +10 -12
- data/app/models/job_invocation_composer.rb +20 -14
- data/app/models/job_invocation_task_group.rb +1 -1
- data/app/models/job_template.rb +3 -3
- data/app/models/remote_execution_feature.rb +0 -2
- data/app/models/remote_execution_provider.rb +4 -2
- data/app/models/setting/remote_execution.rb +54 -56
- data/app/models/ssh_execution_provider.rb +2 -2
- data/app/models/targeting.rb +1 -0
- data/app/models/template_invocation.rb +2 -3
- data/app/views/api/v2/job_invocations/base.json.rabl +1 -1
- data/app/views/api/v2/job_invocations/main.json.rabl +5 -2
- data/app/views/job_invocations/_card_target_hosts.html.erb +12 -0
- data/app/views/job_invocations/_card_user_input.html.erb +1 -1
- data/app/views/job_invocations/_form.html.erb +3 -2
- data/app/views/job_invocations/_rerun_taxonomies.html.erb +22 -0
- data/app/views/job_invocations/_user_input.html.erb +1 -1
- data/app/views/job_invocations/show.html.erb +2 -0
- data/db/migrate/20151215114631_add_host_id_to_template_invocation.rb +1 -0
- data/db/migrate/20180110104432_rename_template_invocation_permission.rb +1 -0
- data/db/seeds.d/50-notification_blueprints.rb +4 -4
- data/db/seeds.d/90-bookmarks.rb +1 -0
- data/extra/cockpit/foreman-cockpit-session +7 -2
- data/lib/foreman_remote_execution/engine.rb +18 -17
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/benchmark/run_hosts_job_benchmark.rb +1 -1
- data/test/factories/foreman_remote_execution_factories.rb +1 -1
- data/test/functional/api/v2/job_invocations_controller_test.rb +9 -9
- data/test/functional/api/v2/job_templates_controller_test.rb +1 -1
- data/test/functional/api/v2/remote_execution_features_controller_test.rb +2 -2
- data/test/functional/api/v2/template_invocations_controller_test.rb +4 -4
- data/test/functional/job_invocations_controller_test.rb +11 -11
- data/test/functional/job_templates_controller_test.rb +1 -1
- data/test/unit/actions/run_hosts_job_test.rb +8 -8
- data/test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb +3 -3
- data/test/unit/concerns/host_extensions_test.rb +19 -19
- data/test/unit/concerns/nic_extensions_test.rb +1 -1
- data/test/unit/execution_task_status_mapper_test.rb +10 -10
- data/test/unit/input_template_renderer_test.rb +77 -77
- data/test/unit/job_invocation_composer_test.rb +100 -96
- data/test/unit/job_invocation_test.rb +29 -29
- data/test/unit/job_template_effective_user_test.rb +3 -3
- data/test/unit/job_template_test.rb +31 -31
- data/test/unit/remote_execution_feature_test.rb +19 -19
- data/test/unit/remote_execution_provider_test.rb +29 -29
- data/test/unit/renderer_scope_input.rb +6 -6
- data/test/unit/targeting_test.rb +6 -6
- data/test/unit/template_invocation_input_value_test.rb +3 -3
- metadata +3 -2
@@ -42,7 +42,8 @@ module Actions
|
|
42
42
|
:script => script,
|
43
43
|
:execution_timeout_interval => job_invocation.execution_timeout_interval,
|
44
44
|
:secrets => secrets(host, job_invocation, provider),
|
45
|
-
:use_batch_triggering => true
|
45
|
+
:use_batch_triggering => true,
|
46
|
+
:use_concurrency_control => options[:use_concurrency_control]}
|
46
47
|
action_options = provider.proxy_command_options(template_invocation, host)
|
47
48
|
.merge(additional_options)
|
48
49
|
|
@@ -94,7 +95,6 @@ module Actions
|
|
94
95
|
super << self
|
95
96
|
end
|
96
97
|
|
97
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
98
98
|
def fill_continuous_output(continuous_output)
|
99
99
|
delegated_output.fetch('result', []).each do |raw_output|
|
100
100
|
continuous_output.add_raw_output(raw_output)
|
@@ -109,13 +109,12 @@ module Actions
|
|
109
109
|
end
|
110
110
|
if exit_status
|
111
111
|
continuous_output.add_output(_('Exit status: %s') % exit_status, 'stdout', final_timestamp)
|
112
|
-
elsif run_step
|
112
|
+
elsif run_step&.error
|
113
113
|
continuous_output.add_output(_('Job finished with error') + ": #{run_step.error.exception_class} - #{run_step.error.message}", 'debug', final_timestamp)
|
114
114
|
end
|
115
115
|
rescue => e
|
116
116
|
continuous_output.add_exception(_('Error loading data from proxy'), e)
|
117
117
|
end
|
118
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
119
118
|
|
120
119
|
def exit_status
|
121
120
|
delegated_output[:exit_status]
|
@@ -162,8 +161,8 @@ module Actions
|
|
162
161
|
offline_proxies = proxy_selector.offline
|
163
162
|
settings = { :count => offline_proxies.count, :proxy_names => offline_proxies.map(&:name).join(', ') }
|
164
163
|
raise n_('The only applicable proxy %{proxy_names} is down',
|
165
|
-
|
166
|
-
|
164
|
+
'All %{count} applicable proxies are down. Tried %{proxy_names}',
|
165
|
+
offline_proxies.count) % settings
|
167
166
|
elsif proxy == :not_defined
|
168
167
|
settings = { :global_proxy => 'remote_execution_global_proxy',
|
169
168
|
:fallback_proxy => 'remote_execution_fallback_proxy' }
|
@@ -42,7 +42,7 @@ module Actions
|
|
42
42
|
# during actual run (here) so we build template invocations from these patterns
|
43
43
|
template_invocation = job_invocation.pattern_template_invocation_for_host(host).deep_clone
|
44
44
|
template_invocation.host_id = host.id
|
45
|
-
trigger(RunHostJob, job_invocation, host, template_invocation, proxy_selector)
|
45
|
+
trigger(RunHostJob, job_invocation, host, template_invocation, proxy_selector, { :use_concurrency_control => uses_concurrency_control })
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -76,7 +76,7 @@ module Actions
|
|
76
76
|
limit_concurrency_level invocation.concurrency_level unless invocation.concurrency_level.nil?
|
77
77
|
unless invocation.time_span.nil?
|
78
78
|
distribute_over_time(invocation.time_span,
|
79
|
-
|
79
|
+
invocation.targeting.hosts.count)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -61,6 +61,7 @@ module ForemanRemoteExecution
|
|
61
61
|
|
62
62
|
def input(name)
|
63
63
|
return template_input_values[name.to_s] if template_input_values.key?(name.to_s)
|
64
|
+
|
64
65
|
input = find_by_name(template.template_inputs_with_foreign, name) # rubocop:disable Rails/DynamicFindBy
|
65
66
|
if input
|
66
67
|
@preview ? input.preview(self) : input.value(self)
|
@@ -7,7 +7,6 @@ module ForemanRemoteExecution
|
|
7
7
|
def flattened_errors
|
8
8
|
errors = Hash.new { |h, k| h[k] = [] }
|
9
9
|
# self.errors is ActiveModel::Errors, not Hash and doesn't have the #each_key method
|
10
|
-
# rubocop:disable Performance/HashEachMethods
|
11
10
|
self.errors.keys.each do |key|
|
12
11
|
messages = self.errors[key]
|
13
12
|
invalid_objects = invalid_objects_for_attribute(key)
|
@@ -19,7 +18,6 @@ module ForemanRemoteExecution
|
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
22
|
-
# rubocop:enable Performance/HashEachMethods
|
23
21
|
errors.map { |key, messages| self.errors.full_message(key, messages.join(', ')) }
|
24
22
|
end
|
25
23
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module ForemanRemoteExecution
|
2
2
|
module HostExtensions
|
3
|
-
# rubocop:disable Metrics/BlockLength
|
4
3
|
def self.prepended(base)
|
5
4
|
base.instance_eval do
|
6
5
|
has_many :targeting_hosts, :dependent => :destroy, :foreign_key => 'host_id'
|
@@ -27,11 +26,11 @@ module ForemanRemoteExecution
|
|
27
26
|
|
28
27
|
mapping = {
|
29
28
|
'job_invocation.id' => %(#{TemplateInvocation.table_name}.job_invocation_id #{operator} ?),
|
30
|
-
'job_invocation.result' => %(#{ForemanTasks::Task.table_name}.result #{operator} (?))
|
29
|
+
'job_invocation.result' => %(#{ForemanTasks::Task.table_name}.result #{operator} (?)),
|
31
30
|
}
|
32
31
|
{
|
33
32
|
:conditions => sanitize_sql_for_conditions([mapping[key], value_to_sql(operator, value)]),
|
34
|
-
:joins => { :template_invocations => [:run_host_job_task] }
|
33
|
+
:joins => { :template_invocations => [:run_host_job_task] },
|
35
34
|
}
|
36
35
|
end
|
37
36
|
end
|
@@ -65,10 +64,9 @@ module ForemanRemoteExecution
|
|
65
64
|
get_interface_by_flag(:execution)
|
66
65
|
end
|
67
66
|
|
68
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
69
67
|
def remote_execution_proxies(provider, authorized = true)
|
70
68
|
proxies = {}
|
71
|
-
proxies[:subnet] = execution_interface.subnet.remote_execution_proxies.with_features(provider) if execution_interface
|
69
|
+
proxies[:subnet] = execution_interface.subnet.remote_execution_proxies.with_features(provider) if execution_interface&.subnet
|
72
70
|
proxies[:fallback] = smart_proxies.with_features(provider) if Setting[:remote_execution_fallback_proxy]
|
73
71
|
|
74
72
|
if Setting[:remote_execution_global_proxy]
|
@@ -16,9 +16,10 @@ class ForeignInputSet < ApplicationRecord
|
|
16
16
|
|
17
17
|
def inputs(templates_stack = [])
|
18
18
|
return [] unless target_template
|
19
|
-
|
19
|
+
|
20
|
+
if templates_stack.include?(target_template) || template&.id == target_template&.id
|
20
21
|
raise CircularDependencyError.new(N_("Circular dependency detected in foreign input set '%{template}' -> '%{target_template}'. Templates stack: %{templates_stack}"),
|
21
|
-
|
22
|
+
:template => template.name, :target_template => target_template.name, :templates_stack => templates_stack.map(&:name).inspect)
|
22
23
|
end
|
23
24
|
inputs = target_template.template_inputs_with_foreign(templates_stack + [target_template])
|
24
25
|
unless self.include_all?
|
@@ -43,7 +43,7 @@ class InputTemplateRenderer
|
|
43
43
|
input_values: @template_input_values,
|
44
44
|
templates_stack: templates_stack,
|
45
45
|
input_template_instance: self,
|
46
|
-
current_user: User.current.try(:login)
|
46
|
+
current_user: User.current.try(:login),
|
47
47
|
}
|
48
48
|
)
|
49
49
|
Foreman::Renderer.render(source, @scope)
|
@@ -10,7 +10,7 @@ class JobInvocation < ApplicationRecord
|
|
10
10
|
FLATTENED_ERRORS_MAPPING = {
|
11
11
|
:pattern_template_invocations => lambda do |template_invocation|
|
12
12
|
_('template') + " #{template_invocation.template.name}"
|
13
|
-
end
|
13
|
+
end,
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
belongs_to :targeting, :dependent => :destroy
|
@@ -198,23 +198,21 @@ class JobInvocation < ApplicationRecord
|
|
198
198
|
|
199
199
|
def output(host)
|
200
200
|
return unless (task = sub_task_for_host(host)) && task.main_action && task.main_action.live_output.any?
|
201
|
+
|
201
202
|
task.main_action.live_output.first['output']
|
202
203
|
end
|
203
204
|
|
204
205
|
def generate_description
|
205
|
-
key_re = /%\{([^\}]+)\}/
|
206
206
|
template_invocation = pattern_template_invocations.first
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
input_hash.update(:job_category => job_category)
|
212
|
-
input_hash.update(:template_name => template_invocation.template.name)
|
213
|
-
description_format.scan(key_re) { |key| input_hash[key.first] }
|
214
|
-
self.description = description_format
|
215
|
-
input_hash.each do |k, v|
|
216
|
-
self.description.gsub!(Regexp.new("%\{#{k}\}"), v || '')
|
207
|
+
input_hash = template_invocation.input_values.reduce({}) do |h, v|
|
208
|
+
value = v.value
|
209
|
+
value = '*' * 3 if v.template_input.respond_to?(:hidden_value) && v.template_input.hidden_value?
|
210
|
+
h.update("%{#{v.template_input.name}}" => value)
|
217
211
|
end
|
212
|
+
input_hash.update("%{job_category}" => job_category)
|
213
|
+
input_hash.update("%{template_name}" => template_invocation.template.name)
|
214
|
+
input_hash.default = "''"
|
215
|
+
self.description = description_format.gsub(/%{[^}]+}/) { |key| input_hash[key] }
|
218
216
|
self.description = self.description[0..(JobInvocation.columns_hash['description'].limit - 1)]
|
219
217
|
end
|
220
218
|
|
@@ -37,7 +37,7 @@ class JobInvocationComposer
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def blank_to_nil(thing)
|
40
|
-
thing.
|
40
|
+
thing.presence
|
41
41
|
end
|
42
42
|
|
43
43
|
# TODO: Fix this comment
|
@@ -71,16 +71,19 @@ class JobInvocationComposer
|
|
71
71
|
def concurrency_control_params
|
72
72
|
{
|
73
73
|
:time_span => job_invocation_base[:time_span],
|
74
|
-
:level => job_invocation_base[:concurrency_level]
|
74
|
+
:level => job_invocation_base[:concurrency_level],
|
75
75
|
}
|
76
76
|
end
|
77
77
|
|
78
78
|
def triggering
|
79
79
|
return {} unless ui_params.key?(:triggering)
|
80
|
+
|
80
81
|
trig = ui_params[:triggering]
|
81
82
|
keys = (1..5).map { |i| "end_time(#{i}i)" }
|
82
|
-
|
83
|
-
trig
|
83
|
+
values = trig.fetch(:end_time, {}).values_at(*keys)
|
84
|
+
return trig if values.any?(&:nil?)
|
85
|
+
|
86
|
+
trig.merge(:end_time => Time.local(*values))
|
84
87
|
end
|
85
88
|
|
86
89
|
def targeting(targeting_params)
|
@@ -108,6 +111,7 @@ class JobInvocationComposer
|
|
108
111
|
|
109
112
|
def targeting_params
|
110
113
|
raise ::Foreman::Exception, _('Cannot specify both bookmark_id and search_query') if api_params[:bookmark_id] && api_params[:search_query]
|
114
|
+
|
111
115
|
api_params.slice(:targeting_type, :bookmark_id, :search_query, :randomized_ordering).merge(:user_id => User.current.id)
|
112
116
|
end
|
113
117
|
|
@@ -120,14 +124,14 @@ class JobInvocationComposer
|
|
120
124
|
:cronline => api_params[:recurrence][:cron_line],
|
121
125
|
:end_time => format_datetime(api_params[:recurrence][:end_time]),
|
122
126
|
:input_type => :cronline,
|
123
|
-
:max_iteration => api_params[:recurrence][:max_iteration]
|
127
|
+
:max_iteration => api_params[:recurrence][:max_iteration],
|
124
128
|
}
|
125
129
|
elsif api_params[:scheduling].present?
|
126
130
|
{
|
127
131
|
:mode => :future,
|
128
132
|
:start_at_raw => format_datetime(api_params[:scheduling][:start_at]),
|
129
133
|
:start_before_raw => format_datetime(api_params[:scheduling][:start_before]),
|
130
|
-
:end_time_limited => api_params[:scheduling][:start_before] ? true : false
|
134
|
+
:end_time_limited => api_params[:scheduling][:start_before] ? true : false,
|
131
135
|
}
|
132
136
|
else
|
133
137
|
{}
|
@@ -137,7 +141,7 @@ class JobInvocationComposer
|
|
137
141
|
def concurrency_control_params
|
138
142
|
{
|
139
143
|
:level => api_params.fetch(:concurrency_control, {})[:concurrency_level],
|
140
|
-
:time_span => api_params.fetch(:concurrency_control, {})[:time_span]
|
144
|
+
:time_span => api_params.fetch(:concurrency_control, {})[:time_span],
|
141
145
|
}
|
142
146
|
end
|
143
147
|
|
@@ -162,6 +166,7 @@ class JobInvocationComposer
|
|
162
166
|
|
163
167
|
def format_datetime(datetime)
|
164
168
|
return datetime if datetime.blank?
|
169
|
+
|
165
170
|
Time.parse(datetime).strftime('%Y-%m-%d %H:%M')
|
166
171
|
end
|
167
172
|
end
|
@@ -195,7 +200,7 @@ class JobInvocationComposer
|
|
195
200
|
def concurrency_control_params
|
196
201
|
{
|
197
202
|
:level => job_invocation.concurrency_level,
|
198
|
-
:time_span => job_invocation.time_span
|
203
|
+
:time_span => job_invocation.time_span,
|
199
204
|
}
|
200
205
|
end
|
201
206
|
|
@@ -271,11 +276,12 @@ class JobInvocationComposer
|
|
271
276
|
|
272
277
|
def input_values_params
|
273
278
|
return {} if @provided_inputs.blank?
|
279
|
+
|
274
280
|
@provided_inputs.map do |key, value|
|
275
281
|
input = job_template.template_inputs_with_foreign.find { |i| i.name == key.to_s }
|
276
282
|
unless input
|
277
283
|
raise Foreman::Exception.new(N_('Feature input %{input_name} not defined in template %{template_name}'),
|
278
|
-
|
284
|
+
:input_name => key, :template_name => job_template.name)
|
279
285
|
end
|
280
286
|
{ 'template_input_id' => input.id, 'value' => value }
|
281
287
|
end
|
@@ -284,14 +290,14 @@ class JobInvocationComposer
|
|
284
290
|
def job_template
|
285
291
|
unless feature.job_template
|
286
292
|
raise Foreman::Exception.new(N_('No template mapped to feature %{feature_name}'),
|
287
|
-
|
293
|
+
:feature_name => feature.name)
|
288
294
|
end
|
289
295
|
template = JobTemplate.authorized(:view_job_templates).find_by(id: feature.job_template_id)
|
290
296
|
|
291
297
|
unless template
|
292
298
|
raise Foreman::Exception.new(N_('The template %{template_name} mapped to feature %{feature_name} is not accessible by the user'),
|
293
|
-
|
294
|
-
|
299
|
+
:template_name => template.name,
|
300
|
+
:feature_name => feature.name)
|
295
301
|
end
|
296
302
|
template
|
297
303
|
end
|
@@ -329,7 +335,6 @@ class JobInvocationComposer
|
|
329
335
|
self.new(ParamsForFeature.new(feature_label, hosts, provided_inputs).params)
|
330
336
|
end
|
331
337
|
|
332
|
-
# rubocop:disable Metrics/AbcSize
|
333
338
|
def compose
|
334
339
|
job_invocation.job_category = validate_job_category(params[:job_category])
|
335
340
|
job_invocation.job_category ||= resolve_job_category(available_job_categories.first) { |tempate| template.job_category } if @set_defaults
|
@@ -354,7 +359,6 @@ class JobInvocationComposer
|
|
354
359
|
|
355
360
|
self
|
356
361
|
end
|
357
|
-
# rubocop:enable Metrics/AbcSize
|
358
362
|
|
359
363
|
def trigger(raise_on_error = false)
|
360
364
|
generate_description
|
@@ -576,8 +580,10 @@ class JobInvocationComposer
|
|
576
580
|
def resolve_for_composer(default_value, &block)
|
577
581
|
setting_value = Setting['remote_execution_form_job_template']
|
578
582
|
return default_value unless setting_value
|
583
|
+
|
579
584
|
form_template = JobTemplate.find_by :name => setting_value
|
580
585
|
return default_value unless form_template
|
586
|
+
|
581
587
|
if block_given?
|
582
588
|
yield form_template
|
583
589
|
else
|
data/app/models/job_template.rb
CHANGED
@@ -7,8 +7,8 @@ class JobTemplate < ::Template
|
|
7
7
|
end
|
8
8
|
|
9
9
|
attr_exportable :job_category, :description_format,
|
10
|
-
|
11
|
-
|
10
|
+
:foreign_input_sets, :provider_type,
|
11
|
+
{ :kind => ->(template) { template.class.name.underscore } }.merge(taxonomy_exportable)
|
12
12
|
|
13
13
|
include Authorizable
|
14
14
|
extend FriendlyId
|
@@ -65,7 +65,7 @@ class JobTemplate < ::Template
|
|
65
65
|
|
66
66
|
def import_raw!(contents, options = {})
|
67
67
|
template = import_raw(contents, options)
|
68
|
-
template
|
68
|
+
template&.save!
|
69
69
|
template
|
70
70
|
end
|
71
71
|
|
@@ -23,7 +23,6 @@ class RemoteExecutionFeature < ApplicationRecord
|
|
23
23
|
self.find_by(label: label) || raise(::Foreman::Exception.new(N_('Unknown remote execution feature %s'), label))
|
24
24
|
end
|
25
25
|
|
26
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
27
26
|
def self.register(label, name, options = {})
|
28
27
|
begin
|
29
28
|
return false unless RemoteExecutionFeature.table_exists?
|
@@ -61,5 +60,4 @@ class RemoteExecutionFeature < ApplicationRecord
|
|
61
60
|
return feature
|
62
61
|
end
|
63
62
|
end
|
64
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
65
63
|
end
|
@@ -89,9 +89,11 @@ class RemoteExecutionProvider
|
|
89
89
|
host.host_param(setting.to_s) || Setting[setting]
|
90
90
|
end
|
91
91
|
|
92
|
-
def ssh_password(_host)
|
92
|
+
def ssh_password(_host)
|
93
|
+
end
|
93
94
|
|
94
|
-
def ssh_key_passphrase(_host)
|
95
|
+
def ssh_key_passphrase(_host)
|
96
|
+
end
|
95
97
|
|
96
98
|
def proxy_action_class
|
97
99
|
ForemanRemoteExecutionCore::Actions::RunScript
|
@@ -2,79 +2,77 @@ class Setting::RemoteExecution < Setting
|
|
2
2
|
|
3
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}
|
4
4
|
|
5
|
-
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
6
5
|
def self.default_settings
|
7
6
|
[
|
8
7
|
self.set('remote_execution_fallback_proxy',
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
N_('Search the host for any proxy with Remote Execution, useful when the host has no subnet or the subnet does not have an execution proxy'),
|
9
|
+
false,
|
10
|
+
N_('Fallback to Any Proxy')),
|
12
11
|
self.set('remote_execution_global_proxy',
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
N_('Search for remote execution proxy outside of the proxies assigned to the host. ' +
|
13
|
+
"The search will be limited to the host's organization and location."),
|
14
|
+
true,
|
15
|
+
N_('Enable Global Proxy')),
|
17
16
|
self.set('remote_execution_ssh_user',
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
N_('Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user.'),
|
18
|
+
'root',
|
19
|
+
N_('SSH User')),
|
21
20
|
self.set('remote_execution_effective_user',
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
N_('Default user to use for executing the script. If the user differs from the SSH user, su or sudo is used to switch the user.'),
|
22
|
+
'root',
|
23
|
+
N_('Effective User')),
|
25
24
|
self.set('remote_execution_effective_user_method',
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
N_('What command should be used to switch to the effective user. One of %s') % SSHExecutionProvider::EFFECTIVE_USER_METHODS.inspect,
|
26
|
+
'sudo',
|
27
|
+
N_('Effective User Method'),
|
28
|
+
nil,
|
29
|
+
{ :collection => proc { Hash[SSHExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] } }),
|
31
30
|
self.set('remote_execution_sudo_password', N_("Sudo password"), '', N_("Sudo password"), nil, {:encrypted => true}),
|
32
31
|
self.set('remote_execution_sync_templates',
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
N_('Whether we should sync templates from disk when running db:seed.'),
|
33
|
+
true,
|
34
|
+
N_('Sync Job Templates')),
|
36
35
|
self.set('remote_execution_ssh_port',
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
N_('Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port.'),
|
37
|
+
'22',
|
38
|
+
N_('SSH Port')),
|
40
39
|
self.set('remote_execution_connect_by_ip',
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
N_('Should the ip addresses on host interfaces be preferred over the fqdn? '\
|
41
|
+
'It is useful when DNS not resolving the fqdns properly. You may override this per host by setting a parameter called remote_execution_connect_by_ip. '\
|
42
|
+
'This setting only applies to IPv4. When the host has only an IPv6 address on the interface used for remote execution, hostname will be used even if this setting is set to true.'),
|
43
|
+
false,
|
44
|
+
N_('Connect by IP')),
|
45
45
|
self.set('remote_execution_ssh_password',
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
N_('Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password'),
|
47
|
+
nil,
|
48
|
+
N_('Default SSH password'),
|
49
|
+
nil,
|
50
|
+
{ :encrypted => true }),
|
51
51
|
self.set('remote_execution_ssh_key_passphrase',
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
N_('Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase'),
|
53
|
+
nil,
|
54
|
+
N_('Default SSH key passphrase'),
|
55
|
+
nil,
|
56
|
+
{ :encrypted => true }),
|
57
57
|
self.set('remote_execution_workers_pool_size',
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
N_('Amount of workers in the pool to handle the execution of the remote execution jobs. Restart of the dynflowd/foreman-tasks service is required.'),
|
59
|
+
5,
|
60
|
+
N_('Workers pool size')),
|
61
61
|
self.set('remote_execution_cleanup_working_dirs',
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
N_('When enabled, working directories will be removed after task completion. You may override this per host by setting a parameter called remote_execution_cleanup_working_dirs.'),
|
63
|
+
true,
|
64
|
+
N_('Cleanup working directories')),
|
65
65
|
self.set('remote_execution_cockpit_url',
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
N_('Where to find the Cockpit instance for the Web Console button. By default, no button is shown.'),
|
67
|
+
nil,
|
68
|
+
N_('Cockpit URL'),
|
69
|
+
nil),
|
70
70
|
self.set('remote_execution_form_job_template',
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
N_('Choose a job template that is pre-selected in job invocation form'),
|
72
|
+
'Run Command - SSH Default',
|
73
|
+
_('Form Job Template'),
|
74
|
+
nil,
|
75
|
+
{ :collection => proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] } }),
|
76
76
|
]
|
77
77
|
end
|
78
|
-
# rubocop:enable AbcSize
|
79
|
-
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize
|
80
78
|
end
|