foreman_remote_execution 1.5.6 → 1.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: e46050a5990faad87a961e071259349d70484bd1a3a5dc591f2dc2d99a8ed5fd
4
- data.tar.gz: 2024c485f96831c771299629dee1eae498fbc078cd9a97fded7db60a66c88b4f
2
+ SHA1:
3
+ metadata.gz: d32b2841ada7024991eaaa445876b288bdb7e659
4
+ data.tar.gz: ac0e476c16619599050ed2ee18fe8a36c6676612
5
5
  SHA512:
6
- metadata.gz: fc474783987a76f8fa74304887f7a54aba2d1a4a64619087d891266916cff2f9c4527e2a53fff719bf8736f10d9fbf8542da2d99cd78d87d946f1048965c24a8
7
- data.tar.gz: af6e2aa4211743d8e210f2dfc823f81110ff6100ba4cb046b90ab85ca8a13048e6087eaaeebe9d856112cd525b2ae957e5d112a5734d96754fc77013b51b4cd7
6
+ metadata.gz: b359f35fd8d49fb8648cf9e166bde983c7559b7137b76704018ebd8998ac5d3d45600934dc459edf20b75982ccc9d7622e3872c6d75570c845f7378e149ca5d1
7
+ data.tar.gz: a35c2128ec33e5c54aff10a860d7515356a44bca013295e5066b916e89fc116e5384716904c4b30fd4808fde9eb67bbdefbd1e2240df8d6237625a858387f062
@@ -111,14 +111,9 @@ module Api
111
111
  param :failed_only, :bool
112
112
  def rerun
113
113
  composer = JobInvocationComposer.from_job_invocation(@job_invocation, params)
114
- if composer.rerun_possible?
115
- composer.trigger!
116
- @job_invocation = composer.job_invocation
117
- process_response @job_invocation
118
- else
119
- render :json => { :error => _('Could not rerun job %{id} because its template could not be found') % { :id => composer.reruns } },
120
- :status => 404
121
- end
114
+ composer.trigger!
115
+ @job_invocation = composer.job_invocation
116
+ process_response @job_invocation
122
117
  end
123
118
 
124
119
  private
@@ -161,7 +161,7 @@ module RemoteExecutionHelper
161
161
 
162
162
  def preview_box(template_invocation, target)
163
163
  renderer = InputTemplateRenderer.new(template_invocation.template, target, template_invocation)
164
- if (preview = (load_template_from_task(template_invocation, target) || renderer.preview))
164
+ if (preview = renderer.preview)
165
165
  content_tag :pre, preview
166
166
  elsif target.nil?
167
167
  alert :text => _('Could not render the preview because no host matches the search query.'),
@@ -234,10 +234,4 @@ module RemoteExecutionHelper
234
234
  end
235
235
  end
236
236
  end
237
-
238
- def load_template_from_task(template_invocation, target)
239
- task = template_invocation.job_invocation.sub_task_for_host(target)
240
- return if task.nil?
241
- task.execution_plan.actions[1].try(:input) { |input| input['script'] }
242
- end
243
237
  end
@@ -49,8 +49,6 @@ module Actions
49
49
  job_invocation.password = job_invocation.key_passphrase = job_invocation.sudo_password = nil
50
50
  job_invocation.save!
51
51
 
52
- Rails.logger.debug "cleaning cache for keys that begin with 'job_invocation_#{job_invocation.id}'"
53
- Rails.cache.delete_matched(/\A#{JobInvocation::CACHE_PREFIX}_#{job_invocation.id}/)
54
52
  # creating the success notification should be the very last thing this tasks do
55
53
  job_invocation.build_notification.deliver!
56
54
  end
@@ -0,0 +1,57 @@
1
+ module ForemanRemoteExecution
2
+ module Renderer
3
+ module Scope
4
+ class Input < ::Foreman::Renderer::Scope::Base
5
+ include Foreman::Renderer::Scope::Macros::HostTemplate
6
+
7
+ attr_reader :template, :host, :invocation, :input_values, :input_template_instance
8
+ delegate :input, to: :input_template_instance
9
+
10
+ def render_error(message)
11
+ raise ::InputTemplateRenderer::RenderError.new(message)
12
+ end
13
+
14
+ def preview?
15
+ !!@preview
16
+ end
17
+
18
+ def render_template(template_name, input_values = {}, options = {})
19
+ options.assert_valid_keys(:with_foreign_input_set)
20
+ with_foreign_input_set = options.fetch(:with_foreign_input_set, true)
21
+ template = @template.class.authorized("view_#{@template.class.to_s.underscore.pluralize}").find_by(name: template_name)
22
+ unless template
23
+ self.error_message = _('included template \'%s\' not found') % template_name
24
+ raise error_message
25
+ end
26
+ if with_foreign_input_set
27
+ input_values = foreign_input_set_values(template, input_values)
28
+ end
29
+ included_renderer = InputTemplateRenderer.new(template, host, invocation, input_values.with_indifferent_access, @preview, @templates_stack)
30
+ out = included_renderer.render
31
+ if included_renderer.error_message
32
+ @input_template_instance.error_message = included_renderer.error_message
33
+ raise error_message
34
+ else
35
+ out
36
+ end
37
+ end
38
+
39
+ def foreign_input_set_values(target_template, overrides = {})
40
+ input_set = @template.foreign_input_sets.find_by(:target_template_id => target_template)
41
+ return overrides if input_set.nil?
42
+
43
+ inputs_to_generate = input_set.inputs.map(&:name) - overrides.keys.map(&:to_s)
44
+ included_renderer = InputTemplateRenderer.new(input_set.target_template, host, invocation, nil, @preview, @templates_stack)
45
+ input_values = inputs_to_generate.inject(HashWithIndifferentAccess.new) do |hash, input_name|
46
+ hash.merge(input_name => included_renderer.input(input_name))
47
+ end
48
+ input_values.merge(overrides)
49
+ end
50
+
51
+ def allowed_helpers
52
+ super + [:input, :render_template, :preview?, :render_error]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -5,9 +5,9 @@ class InputTemplateRenderer
5
5
  class RenderError < ::Foreman::Exception
6
6
  end
7
7
 
8
- include UnattendedHelper
8
+ delegate :logger, to: Rails
9
9
 
10
- attr_accessor :template, :host, :invocation, :input_values, :error_message
10
+ attr_accessor :template, :host, :invocation, :input_values, :error_message, :templates_stack
11
11
 
12
12
  # takes template object that should be rendered
13
13
  # host and template invocation arguments are optional
@@ -16,8 +16,8 @@ class InputTemplateRenderer
16
16
  raise Foreman::Exception, N_('Recursive rendering of templates detected') if templates_stack.include?(template)
17
17
 
18
18
  @host = host
19
- @invocation = invocation
20
19
  @template = template
20
+ @invocation = invocation
21
21
  @input_values = input_values
22
22
  @preview = preview
23
23
  @templates_stack = templates_stack + [template]
@@ -25,82 +25,53 @@ class InputTemplateRenderer
25
25
 
26
26
  def render
27
27
  @template.validate_unique_inputs!
28
- render_safe(@template.template, ::Foreman::Renderer::ALLOWED_HELPERS + [ :input, :render_template, :preview?, :render_error, :cached ], :host => @host)
28
+ source = Foreman::Renderer.get_source(
29
+ template: template,
30
+ host: host
31
+ )
32
+ scope = Foreman::Renderer.get_scope(
33
+ host: host,
34
+ klass: renderer_scope,
35
+ variables: {
36
+ host: host,
37
+ template: template,
38
+ preview: @preview,
39
+ invocation: invocation,
40
+ input_values: input_values,
41
+ templates_stack: templates_stack,
42
+ input_template_instance: self
43
+ }
44
+ )
45
+ Foreman::Renderer.render(source, scope)
29
46
  rescue => e
30
47
  self.error_message ||= _('error during rendering: %s') % e.message
31
- Rails.logger.debug e.to_s + "\n" + e.backtrace.join("\n")
32
- return false
33
- end
34
-
35
- def preview
36
- old_preview = @preview
37
- @preview = true
38
- render
39
- ensure
40
- @preview = old_preview
41
- end
42
-
43
- def cached(key, &block)
44
- return yield if preview?
45
- cache_key = "#{JobInvocation::CACHE_PREFIX}_#{invocation.job_invocation_id}_#{key}"
46
- Rails.logger.debug "cache hit for #{cache_key}" if Rails.cache.exist?(cache_key)
47
- Rails.cache.fetch(cache_key, &block)
48
+ Foreman::Logging.exception('Error during rendering of a job template', e)
49
+ false
48
50
  end
49
51
 
50
52
  def input(name)
51
53
  return @input_values[name.to_s] if @input_values
52
- input = find_by_name(@template.template_inputs_with_foreign, name) # rubocop:disable Rails/DynamicFindBy
54
+ input = find_by_name(template.template_inputs_with_foreign, name) # rubocop:disable Rails/DynamicFindBy
53
55
  if input
54
56
  @preview ? input.preview(self) : input.value(self)
55
57
  else
56
- self.error_message = _('input macro with name \'%s\' used, but no input with such name defined for this template') % name
58
+ error_message = _('input macro with name \'%s\' used, but no input with such name defined for this template') % name
57
59
  raise UndefinedInput, "Rendering failed, no input with name #{name} for input macro found"
58
60
  end
59
61
  end
60
62
 
61
- def render_error(message)
62
- raise RenderError.new(message)
63
- end
64
-
65
- def render_template(template_name, input_values = {}, options = {})
66
- options.assert_valid_keys(:with_foreign_input_set)
67
- with_foreign_input_set = options.fetch(:with_foreign_input_set, true)
68
- template = @template.class.authorized("view_#{@template.class.to_s.underscore.pluralize}").find_by(:name => template_name)
69
- unless template
70
- self.error_message = _('included template \'%s\' not found') % template_name
71
- raise error_message
72
- end
73
- if with_foreign_input_set
74
- input_values = foreign_input_set_values(template, input_values)
75
- end
76
- included_renderer = self.class.new(template, host, invocation, input_values.with_indifferent_access, @preview, @templates_stack)
77
- out = included_renderer.render
78
- if included_renderer.error_message
79
- self.error_message = included_renderer.error_message
80
- raise error_message
81
- else
82
- out
83
- end
84
- end
85
-
86
- def preview?
87
- !!@preview
63
+ def preview
64
+ old_preview = @preview
65
+ @preview = true
66
+ render
67
+ ensure
68
+ @preview = old_preview
88
69
  end
89
70
 
90
- def foreign_input_set_values(target_template, overrides = {})
91
- input_set = @template.foreign_input_sets.find_by(:target_template_id => target_template)
92
- return overrides if input_set.nil?
93
-
94
- inputs_to_generate = input_set.inputs.map(&:name) - overrides.keys.map(&:to_s)
95
- included_renderer = self.class.new(input_set.target_template, host, invocation, nil, @preview, @templates_stack)
96
- input_values = inputs_to_generate.inject(HashWithIndifferentAccess.new) do |hash, input_name|
97
- hash.merge(input_name => included_renderer.input(input_name))
98
- end
99
- input_values.merge(overrides)
100
- end
71
+ private
101
72
 
102
- def logger
103
- Rails.logger
73
+ def renderer_scope
74
+ ForemanRemoteExecution::Renderer::Scope::Input
104
75
  end
105
76
 
106
77
  def find_by_name(collection, name)
@@ -1,6 +1,4 @@
1
1
  class JobInvocation < ApplicationRecord
2
- CACHE_PREFIX = "job_invocation".freeze
3
-
4
2
  audited :except => [:task_id, :targeting_id, :task_group_id, :triggering_id]
5
3
 
6
4
  include Authorizable
@@ -186,8 +186,7 @@ class JobInvocationComposer
186
186
  :concurrency_control => concurrency_control_params,
187
187
  :execution_timeout_interval => job_invocation.execution_timeout_interval,
188
188
  :remote_execution_feature_id => job_invocation.remote_execution_feature_id,
189
- :template_invocations => template_invocations_params,
190
- :reruns => job_invocation.id }.with_indifferent_access
189
+ :template_invocations => template_invocations_params }.with_indifferent_access
191
190
  end
192
191
 
193
192
  private
@@ -298,7 +297,6 @@ class JobInvocationComposer
298
297
  end
299
298
 
300
299
  attr_accessor :params, :job_invocation, :host_ids, :search_query
301
- attr_reader :reruns
302
300
  delegate :job_category, :remote_execution_feature_id, :pattern_template_invocations, :template_invocations, :targeting, :triggering, :to => :job_invocation
303
301
 
304
302
  def initialize(params, set_defaults = false)
@@ -306,7 +304,6 @@ class JobInvocationComposer
306
304
  @set_defaults = set_defaults
307
305
  @job_invocation = JobInvocation.new
308
306
  @job_invocation.task_group = JobInvocationTaskGroup.new
309
- @reruns = params[:reruns]
310
307
  compose
311
308
 
312
309
  @host_ids = validate_host_ids(params[:host_ids])
@@ -345,8 +342,6 @@ class JobInvocationComposer
345
342
  job_invocation.key_passphrase = params[:key_passphrase]
346
343
  job_invocation.sudo_password = params[:sudo_password]
347
344
 
348
- job_invocation.job_category = nil unless rerun_possible?
349
-
350
345
  self
351
346
  end
352
347
  # rubocop:enable Metrics/AbcSize
@@ -475,10 +470,6 @@ class JobInvocationComposer
475
470
  job_invocation.pattern_template_invocations.map(&:template_id)
476
471
  end
477
472
 
478
- def rerun_possible?
479
- !(reruns && job_invocation.pattern_template_invocations.empty?)
480
- end
481
-
482
473
  private
483
474
 
484
475
  # builds input values for a given templates id based on params
@@ -136,7 +136,7 @@ class JobTemplate < ::Template
136
136
 
137
137
  def generate_description_format
138
138
  if description_format.blank?
139
- generated_description = '%{template_name}'
139
+ generated_description = '%{job_category}'
140
140
  unless template_inputs_with_foreign.empty?
141
141
  inputs = template_inputs_with_foreign.map(&:name).map { |name| %{#{name}="%{#{name}}"} }.join(' ')
142
142
  generated_description << " with inputs #{inputs}"
@@ -173,11 +173,7 @@ class TemplateInput < ApplicationRecord
173
173
  private
174
174
 
175
175
  def get_enc
176
- @enc ||= if SETTINGS[:version].short <= '1.15'
177
- Classification::ClassParam.new(:host => @renderer.host).enc
178
- else
179
- HostInfoProviders::PuppetInfo.new(@renderer.host).puppetclass_parameters
180
- end
176
+ @enc ||= HostInfoProviders::PuppetInfo.new(@renderer.host).puppetclass_parameters
181
177
  end
182
178
  end
183
179
  end
@@ -6,15 +6,7 @@
6
6
 
7
7
  <%= form_for @composer.job_invocation, :html => {'data-refresh-url' => refresh_job_invocations_path, :id => 'job_invocation_form'} do |f| %>
8
8
 
9
- <% unless @composer.rerun_possible? %>
10
- <%= alert :text => _('Could not rerun job %{id} because its template could not be found') % { :id => @composer.reruns },
11
- :class => 'alert alert-block alert-danger has-error',
12
- :close => false %>
13
- <% end %>
14
-
15
- <%= selectable_f f, :job_category, @composer.available_job_categories,
16
- { :selected => @composer.job_invocation.job_category, :include_blank => @composer.job_invocation.job_category.nil? },
17
- :label => _('Job category') %>
9
+ <%= selectable_f f, :job_category, @composer.available_job_categories, {}, :label => _('Job category') %>
18
10
  <%= f.hidden_field(:remote_execution_feature_id, :value => @composer.remote_execution_feature_id) %>
19
11
 
20
12
  <% selected_templates_per_provider = {} %>
@@ -124,5 +116,5 @@
124
116
 
125
117
  <%= render :partial => 'preview_hosts_modal' %>
126
118
 
127
- <%= submit_or_cancel f, false, :cancel_path => job_invocations_path, :disabled => !@composer.rerun_possible? %>
119
+ <%= submit_or_cancel f, false, :cancel_path => job_invocations_path %>
128
120
  <% end %>
@@ -34,7 +34,7 @@ module ForemanRemoteExecution
34
34
 
35
35
  initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |_app|
36
36
  Foreman::Plugin.register :foreman_remote_execution do
37
- requires_foreman '>= 1.18'
37
+ requires_foreman '>= 1.20'
38
38
 
39
39
  apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
40
40
 
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '1.5.6'.freeze
2
+ VERSION = '1.6.0'.freeze
3
3
  end
@@ -1,7 +1,7 @@
1
1
  FactoryBot.define do
2
2
  factory :job_template do
3
3
  sequence(:name) { |n| "Job template #{n}" }
4
- sequence(:job_category) { |n| "Job name #{n}" }
4
+ sequence(:job_category) { |n| "job name #{n}" }
5
5
  template 'id'
6
6
  provider_type 'SSH'
7
7
  organizations { [Organization.find_by(name: 'Organization 1')] } if SETTINGS[:organizations_enabled]
@@ -6,11 +6,6 @@ module Api
6
6
  setup do
7
7
  @invocation = FactoryBot.create(:job_invocation, :with_template, :with_task)
8
8
  @template = FactoryBot.create(:job_template, :with_input)
9
-
10
- # Without this the template in template_invocations and in pattern_template_invocations
11
- # would belong to different job_categories, causing trouble when trying to rerun
12
- @invocation.job_category = @invocation.pattern_template_invocations.first.template.job_category
13
- @invocation.save!
14
9
  end
15
10
 
16
11
  test 'should get index' do
@@ -183,8 +178,6 @@ module Api
183
178
 
184
179
  test 'should rerun failed only' do
185
180
  @invocation = FactoryBot.create(:job_invocation, :with_template, :with_failed_task)
186
- @invocation.job_category = @invocation.pattern_template_invocations.first.template.job_category
187
- @invocation.save!
188
181
  JobInvocation.any_instance.expects(:generate_description)
189
182
  JobInvocationComposer.any_instance
190
183
  .expects(:validate_job_category)
@@ -198,13 +191,6 @@ module Api
198
191
  targeting.user_id.must_equal users(:admin).id
199
192
  targeting.search_query.must_equal "name ^ (#{hostnames.join(',')})"
200
193
  end
201
-
202
- test 'should return 404 if template is not found' do
203
- @invocation.job_category = 'Missing category'
204
- @invocation.save!
205
- post :rerun, params: { :id => @invocation.id }
206
- assert_response 404
207
- end
208
194
  end
209
195
  end
210
196
  end
@@ -39,36 +39,6 @@ class InputTemplateRendererTest < ActiveSupport::TestCase
39
39
  renderer.error_message.wont_be_empty
40
40
  end
41
41
  end
42
-
43
- describe 'caching helper' do
44
- it 'caches the value under given key in real mode' do
45
- renderer.stubs(:invocation => OpenStruct.new(:job_invocation_id => 1))
46
-
47
- i = 1
48
- result = renderer.cached('some_key') { i }
49
- result.must_equal 1
50
- i += 1
51
- result = renderer.cached('some_key') { i }
52
- result.must_equal 1
53
- i += 1
54
- result = renderer.cached('different_key') { i }
55
- result.must_equal 3
56
- end
57
-
58
- it 'does not cache the value in preview mode' do
59
- renderer.stubs(:invocation => OpenStruct.new(:job_invocation_id => 1), :preview? => true)
60
-
61
- i = 1
62
- result = renderer.cached('some_key') { i }
63
- result.must_equal 1
64
- i += 1
65
- result = renderer.cached('some_key') { i }
66
- result.must_equal 2
67
- i += 1
68
- result = renderer.cached('different_key') { i }
69
- result.must_equal 3
70
- end
71
- end
72
42
  end
73
43
 
74
44
  context 'with matching input defined' do
@@ -156,24 +156,6 @@ class JobInvocationComposerTest < ActiveSupport::TestCase
156
156
  end
157
157
  end
158
158
 
159
- describe '#rerun_possible?' do
160
- it 'is true when not rerunning' do
161
- composer.must_be :rerun_possible?
162
- end
163
-
164
- it 'is true when rerunning with pattern tempalte invocations' do
165
- composer.expects(:reruns).returns(1)
166
- composer.job_invocation.expects(:pattern_template_invocations).returns([1])
167
- composer.must_be :rerun_possible?
168
- end
169
-
170
- it 'is false when rerunning without pattern template invocations' do
171
- composer.expects(:reruns).returns(1)
172
- composer.job_invocation.expects(:pattern_template_invocations).returns([])
173
- composer.wont_be :rerun_possible?
174
- end
175
- end
176
-
177
159
  describe '#selected_job_templates' do
178
160
  it 'returns no template if none was selected through params' do
179
161
  composer.selected_job_templates.must_be_empty
@@ -44,14 +44,14 @@ class JobTemplateTest < ActiveSupport::TestCase
44
44
  end
45
45
 
46
46
  it 'uses the job name as description_format if not set or blank and has no inputs' do
47
- minimal_template.generate_description_format.must_equal '%{template_name}'
47
+ minimal_template.generate_description_format.must_equal '%{job_category}'
48
48
  minimal_template.description_format = ''
49
- minimal_template.generate_description_format.must_equal '%{template_name}'
49
+ minimal_template.generate_description_format.must_equal '%{job_category}'
50
50
  end
51
51
 
52
52
  it 'generates the description_format if not set or blank and has inputs' do
53
53
  input_name = template.template_inputs.first.name
54
- expected_result = %(%{template_name} with inputs #{input_name}="%{#{input_name}}")
54
+ expected_result = %(%{job_category} with inputs #{input_name}="%{#{input_name}}")
55
55
  template.generate_description_format.must_equal expected_result
56
56
  template.description_format = ''
57
57
  template.generate_description_format.must_equal expected_result
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: 1.5.6
4
+ version: 1.6.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: 2018-09-13 00:00:00.000000000 Z
11
+ date: 2018-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -168,6 +168,7 @@ files:
168
168
  - app/lib/actions/middleware/bind_job_invocation.rb
169
169
  - app/lib/actions/remote_execution/run_host_job.rb
170
170
  - app/lib/actions/remote_execution/run_hosts_job.rb
171
+ - app/lib/foreman_remote_execution/renderer/scope/input.rb
171
172
  - app/lib/proxy_api/remote_execution_ssh.rb
172
173
  - app/mailers/.gitkeep
173
174
  - app/models/concerns/foreman_remote_execution/bookmark_extensions.rb
@@ -417,7 +418,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
417
418
  version: '0'
418
419
  requirements: []
419
420
  rubyforge_project:
420
- rubygems_version: 2.7.3
421
+ rubygems_version: 2.6.12
421
422
  signing_key:
422
423
  specification_version: 4
423
424
  summary: A plugin bringing remote execution to the Foreman, completing the config