foreman_remote_execution 5.0.0 → 6.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +7 -0
  4. data/app/controllers/ui_job_wizard_controller.rb +12 -1
  5. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +20 -9
  6. data/app/helpers/remote_execution_helper.rb +1 -1
  7. data/app/lib/actions/remote_execution/run_host_job.rb +2 -0
  8. data/app/lib/foreman_remote_execution/renderer/scope/input.rb +1 -1
  9. data/app/mailers/rex_job_mailer.rb +1 -1
  10. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +4 -0
  11. data/app/models/job_invocation.rb +2 -0
  12. data/app/models/job_template.rb +3 -1
  13. data/app/models/targeting.rb +1 -1
  14. data/app/views/job_invocations/_preview_hosts_list.html.erb +1 -1
  15. data/app/views/job_templates/_custom_tabs.html.erb +4 -9
  16. data/app/views/template_invocations/show.html.erb +7 -1
  17. data/lib/foreman_remote_execution/engine.rb +7 -3
  18. data/lib/foreman_remote_execution/version.rb +1 -1
  19. data/locale/action_names.rb +3 -4
  20. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  21. data/locale/de/foreman_remote_execution.po +356 -20
  22. data/locale/en/foreman_remote_execution.po +356 -20
  23. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  24. data/locale/en_GB/foreman_remote_execution.po +356 -20
  25. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  26. data/locale/es/foreman_remote_execution.po +357 -21
  27. data/locale/foreman_remote_execution.pot +808 -296
  28. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  29. data/locale/fr/foreman_remote_execution.po +357 -21
  30. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  31. data/locale/ja/foreman_remote_execution.po +357 -21
  32. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  33. data/locale/ko/foreman_remote_execution.po +356 -20
  34. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  35. data/locale/pt_BR/foreman_remote_execution.po +357 -21
  36. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  37. data/locale/ru/foreman_remote_execution.po +356 -20
  38. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  39. data/locale/zh_CN/foreman_remote_execution.po +357 -21
  40. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  41. data/locale/zh_TW/foreman_remote_execution.po +356 -20
  42. data/package.json +3 -1
  43. data/test/unit/job_invocation_report_template_test.rb +1 -1
  44. data/test/unit/targeting_test.rb +1 -1
  45. data/webpack/JobWizard/JobWizard.js +22 -5
  46. data/webpack/JobWizard/JobWizard.scss +5 -0
  47. data/webpack/JobWizard/JobWizardConstants.js +2 -1
  48. data/webpack/JobWizard/__tests__/fixtures.js +13 -2
  49. data/webpack/JobWizard/__tests__/integration.test.js +6 -1
  50. data/webpack/JobWizard/autofill.js +34 -9
  51. data/webpack/JobWizard/index.js +0 -7
  52. data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +25 -7
  53. data/webpack/JobWizard/steps/HostsAndInputs/HostSearch.js +1 -1
  54. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js +28 -0
  55. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +1 -1
  56. data/webpack/JobWizard/steps/form/Formatter.js +18 -3
  57. data/webpack/__mocks__/foremanReact/components/Pagination.js +2 -0
  58. data/webpack/__mocks__/foremanReact/constants.js +1 -0
  59. data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +1 -1
  60. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +1 -6
  61. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +1 -9
  62. data/webpack/react_app/components/TargetingHosts/index.js +2 -3
  63. metadata +3 -4
  64. data/app/views/templates/README.md +0 -6
  65. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66efbd042b1d607eeaa4e72b07452ac00a4e68d28bf09e1fc496f26cae25f1e4
4
- data.tar.gz: 124621a113adab399e259ece92caad11fdf35da117da77dc512fc9e31e6ec66a
3
+ metadata.gz: 61d64bd14e3ce43367e26ad39ec10408baf8ec7920f45aa4ea1353340d3cf742
4
+ data.tar.gz: 0ab68114a29368fa4c2a269287b875368cdcc31db63dd481df223a1f91a36cef
5
5
  SHA512:
6
- metadata.gz: 04ed33fb87e3b0830501f97b95ab62c129897e8510909b47163559854bb0b2b792ccab4035c5fc606a6a8d8e5ff8c084fcfd2109331dff8b4e7a6eac23c86825
7
- data.tar.gz: bca23be551bd1d8169c28a5a4e2d71079ea42cae3a11d6d289f40c9c862a2e7307b6c6e569ba79be7e743f729ef58a3ef72b027ee8735e9c448e4672a105db4b
6
+ metadata.gz: 5d908f4f766c2b55bf6814035058b5faea29ba1ae3c61729275d2492e62b5f5aba2f60838d0b8383b9075f75daed15788d34ae1b2b9e091fea3ec26f812c670a
7
+ data.tar.gz: 05d63bba759d31d2b85030bc8cb4e39faeb9af50e784374e016edb4637d84906f6527b533efd5600da969a1b2315f34392f5f994d1ae17bbc840f5a2dfdf04a9
data/Gemfile CHANGED
@@ -2,4 +2,4 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec :name => 'foreman_remote_execution'
4
4
 
5
- gem 'theforeman-rubocop', '~> 0.1.0.pre'
5
+ gem 'theforeman-rubocop', '~> 0.1.1'
data/README.md CHANGED
@@ -24,6 +24,13 @@ management functionality with remote management functionality.
24
24
 
25
25
  Check the Foreman manual [remote execution section](http://theforeman.org/plugins/foreman_remote_execution/)
26
26
 
27
+ ## Compatibility
28
+
29
+ | Foreman Version | Plugin Version |
30
+ | --------------- | -------------- |
31
+ | >= 3.1 | ~> 5.0.0 |
32
+ | >= 3.2 | >= 6.0.0 |
33
+
27
34
  ## Simulated runs
28
35
  There is an option to use an alternative `ScriptRunner` implementation. Instead of doing ssh connections it discards any input its given and gives back fake output.
29
36
 
@@ -3,10 +3,11 @@ class UiJobWizardController < ApplicationController
3
3
  def categories
4
4
  job_categories = resource_scope
5
5
  .search_for("job_category ~ \"#{params[:search]}\"")
6
+ .where(:snippet => false)
6
7
  .select(:job_category).distinct
7
8
  .reorder(:job_category)
8
9
  .pluck(:job_category)
9
- render :json => {:job_categories =>job_categories, :with_katello => with_katello}
10
+ render :json => {:job_categories => job_categories, :with_katello => with_katello, default_category: default_category, default_template: default_template&.id}
10
11
  end
11
12
 
12
13
  def template
@@ -24,6 +25,16 @@ class UiJobWizardController < ApplicationController
24
25
  template_inputs_with_foreign.map { |input| input.attributes.merge({:resource_type_tableize => input.resource_type&.tableize }) }
25
26
  end
26
27
 
28
+ def default_category
29
+ default_template&.job_category
30
+ end
31
+
32
+ def default_template
33
+ if (setting_value = Setting['remote_execution_form_job_template'])
34
+ JobTemplate.authorized(:view_job_templates).find_by :name => setting_value
35
+ end
36
+ end
37
+
27
38
  def resource_name(nested_resource = nil)
28
39
  nested_resource || 'job_template'
29
40
  end
@@ -8,7 +8,7 @@ module ForemanRemoteExecution
8
8
 
9
9
  def multiple_actions
10
10
  res = super
11
- res += [ [_('Schedule Remote Job'), new_job_invocation_path, false] ] if authorized_for(controller: :job_invocations, action: :new)
11
+ res += [ [_('Schedule Remote Job'), new_job_invocation_path, false] ] if can_schedule_jobs?
12
12
  res
13
13
  end
14
14
 
@@ -22,20 +22,20 @@ module ForemanRemoteExecution
22
22
  end
23
23
  end
24
24
 
25
- def rex_host_features(*args)
26
- return unless authorized_for(controller: :job_invocations, action: :create)
25
+ def rex_host_features(host, *_rest)
26
+ return [] unless can_execute_on_host?(host)
27
27
  RemoteExecutionFeature.with_host_action_button.order(:label).map do |feature|
28
- link_to(_('%s') % feature.name, job_invocations_path(:host_ids => [args.first.id], :feature => feature.label), :method => :post)
28
+ link_to(_('%s') % feature.name, job_invocations_path(:host_ids => [host.id], :feature => feature.label), :method => :post)
29
29
  end
30
30
  end
31
31
 
32
- def schedule_job_button(*args)
33
- return unless authorized_for(controller: :job_invocations, action: :new)
34
- link_to(_('Schedule Remote Job'), new_job_invocation_path(:host_ids => [args.first.id]), :id => :run_button, :class => 'btn btn-default')
32
+ def schedule_job_button(host, *_rest)
33
+ return unless can_execute_on_host?(host)
34
+ link_to(_('Schedule Remote Job'), new_job_invocation_path(:host_ids => [host.id]), :id => :run_button, :class => 'btn btn-default')
35
35
  end
36
36
 
37
37
  def web_console_button(host, *args)
38
- return unless authorized_for(permission: 'cockpit_hosts', auth_object: host)
38
+ return if !authorized_for(permission: 'cockpit_hosts', auth_object: host) || !can_execute_on_infrastructure_host?(host)
39
39
 
40
40
  url = SSHExecutionProvider.cockpit_url_for_host(host.name)
41
41
  url ? link_to(_('Web Console'), url, :class => 'btn btn-default', :id => :'web-console-button', :target => '_new') : nil
@@ -46,6 +46,17 @@ module ForemanRemoteExecution
46
46
  button_group(web_console_button(*args)))
47
47
  super(*args)
48
48
  end
49
- end
50
49
 
50
+ def can_schedule_jobs?
51
+ authorized_for(controller: :job_invocations, action: :create)
52
+ end
53
+
54
+ def can_execute_on_host?(host)
55
+ can_schedule_jobs? && can_execute_on_infrastructure_host?(host)
56
+ end
57
+
58
+ def can_execute_on_infrastructure_host?(host)
59
+ !host.infrastructure_host? || User.current.can?(:execute_jobs_on_infrastructure_hosts)
60
+ end
61
+ end
51
62
  end
@@ -31,7 +31,7 @@ module RemoteExecutionHelper
31
31
 
32
32
  if authorized_for(hash_for_host_path(host).merge(auth_object: host, permission: :view_hosts, authorizer: job_hosts_authorizer))
33
33
  links << { title: _('Host detail'),
34
- action: { href: host_path(host), 'data-method': 'get', id: "#{host.name}-actions-detail" } }
34
+ action: { href: current_host_details_path(host), 'data-method': 'get', id: "#{host.name}-actions-detail" } }
35
35
  end
36
36
 
37
37
  if authorized_for(hash_for_rerun_job_invocation_path(id: job_invocation, host_ids: [ host.id ], authorizer: job_hosts_authorizer))
@@ -42,6 +42,8 @@ module Actions
42
42
 
43
43
  provider_type = template_invocation.template.provider_type.to_s
44
44
  proxy = determine_proxy!(proxy_selector, provider_type, host)
45
+ link!(proxy)
46
+ input[:proxy_id] = proxy.id
45
47
 
46
48
  renderer = InputTemplateRenderer.new(template_invocation.template, host, template_invocation)
47
49
  script = renderer.render
@@ -98,7 +98,7 @@ module ForemanRemoteExecution
98
98
  def input(name)
99
99
  return template_input_values[name.to_s] if template_input_values.key?(name.to_s)
100
100
 
101
- input = find_by_name(template.template_inputs_with_foreign, name) # rubocop:disable Rails/DynamicFindBy
101
+ input = find_by_name(template.template_inputs_with_foreign, name)
102
102
  if input
103
103
  @preview ? input.preview(self) : input.value(self)
104
104
  else
@@ -1,5 +1,5 @@
1
1
  class RexJobMailer < ApplicationMailer
2
- add_template_helper(ApplicationHelper)
2
+ helper ApplicationHelper
3
3
 
4
4
  def job_finished(job, opts = {})
5
5
  @job = job
@@ -121,6 +121,10 @@ module ForemanRemoteExecution
121
121
  @cached_rex_host_params_hash = nil
122
122
  end
123
123
 
124
+ def infrastructure_host?
125
+ infrastructure_facet&.foreman_instance || infrastructure_facet&.smart_proxy_id
126
+ end
127
+
124
128
  private
125
129
 
126
130
  def extend_host_params_hash(params)
@@ -15,8 +15,10 @@ class JobInvocation < ApplicationRecord
15
15
 
16
16
  belongs_to :targeting, :dependent => :destroy
17
17
  has_many :all_template_invocations, :inverse_of => :job_invocation, :dependent => :destroy, :class_name => 'TemplateInvocation'
18
+ # rubocop:disable Rails/HasManyOrHasOneDependent
18
19
  has_many :template_invocations, -> { where('template_invocations.host_id IS NOT NULL') }, :inverse_of => :job_invocation
19
20
  has_many :pattern_template_invocations, -> { where('template_invocations.host_id IS NULL') }, :inverse_of => :job_invocation, :class_name => 'TemplateInvocation'
21
+ # rubocop:enable Rails/HasManyOrHasOneDependent
20
22
  has_many :pattern_templates, :through => :pattern_template_invocations, :source => :template
21
23
 
22
24
  validates :targeting, :presence => true
@@ -17,8 +17,10 @@ class JobTemplate < ::Template
17
17
 
18
18
  has_many :audits, :as => :auditable, :class_name => Audited.audit_class.name, :dependent => :nullify
19
19
  has_many :all_template_invocations, :dependent => :destroy, :foreign_key => 'template_id', :class_name => 'TemplateInvocation'
20
+ # rubocop:disable Rails/HasManyOrHasOneDependent
20
21
  has_many :template_invocations, -> { where('host_id IS NOT NULL') }, :foreign_key => 'template_id'
21
22
  has_many :pattern_template_invocations, -> { where('host_id IS NULL') }, :foreign_key => 'template_id', :class_name => 'TemplateInvocation'
23
+ # rubocop:enable Rails/HasManyOrHasOneDependent
22
24
  has_many :remote_execution_features, :dependent => :nullify
23
25
 
24
26
  # these can't be shared in parent class, scoped search can't handle STI properly
@@ -192,7 +194,7 @@ class JobTemplate < ::Template
192
194
  end
193
195
 
194
196
  def default_input_values(ignore_keys)
195
- result = self.template_inputs_with_foreign.select { |ti| !ti.required? && ti.user_template_input? }.map { |ti| ti.name.to_s }
197
+ result = self.template_inputs_with_foreign.select { |ti| !ti.required? && ti.input_type == 'user' }.map { |ti| ti.name.to_s }
196
198
  result -= ignore_keys.map(&:to_s)
197
199
  Hash[result.map { |k| [ k, nil ] }]
198
200
  end
@@ -67,7 +67,7 @@ class Targeting < ApplicationRecord
67
67
  return '' if ids.empty?
68
68
 
69
69
  hosts = Host.execution_scope.where(:id => ids).distinct.pluck(:name)
70
- "name ^ (#{hosts.join(', ')})"
70
+ hosts.any? ? "name ^ (#{hosts.join(', ')})" : ''
71
71
  end
72
72
 
73
73
  def resolved?
@@ -7,7 +7,7 @@
7
7
  <% if @hosts.any? -%>
8
8
  <ul>
9
9
  <% @hosts.each do |host| -%>
10
- <li><%= link_to h(host.name), host_path(host), :target => '_blank' %></li>
10
+ <li><%= link_to h(host.name), current_host_details_path(host), :target => '_blank' %></li>
11
11
  <% end -%>
12
12
 
13
13
  <% if @additional > 0 -%>
@@ -1,14 +1,9 @@
1
1
  <div class="tab-pane" id="template_job">
2
2
 
3
- <%= field(f, :job_category, :label => _('Job category')) do %>
4
- <%= auto_complete_search(:job_category,
5
- f.object.job_category,
6
- :placeholder => _("Job category") + ' ...',
7
- :name => 'job_template[job_category]',
8
- :id => 'search',
9
- :disabled => @template.locked?) %>
10
- <% end %>
11
-
3
+ <%= autocomplete_f(f, :job_category,
4
+ :search_query => '',
5
+ :placeholder => _("Job category") + ' ...',
6
+ :disabled => @template.locked?) %>
12
7
  <%= text_f f, :description_format,
13
8
  :disabled => @template.locked?,
14
9
  :label_help => description_format_help %>
@@ -28,7 +28,13 @@ end
28
28
  </div>
29
29
  </div>
30
30
  <% if @host %>
31
- <h3><%= _('Target: ') %><%= link_to(@host.name, host_path(@host)) %></h3>
31
+ <% proxy_id = @template_invocation_task.input[:proxy_id] %>
32
+ <h3>
33
+ <%= _('Target: ') %><%= link_to(@host.name, current_host_details_path(@host)) %>
34
+ <% if proxy_id && proxy = SmartProxy.find_by(id: proxy_id) %>
35
+ <%= _('using Smart Proxy') %> <%= link_to(proxy.name, smart_proxy_path(proxy)) %>
36
+ <% end %>
37
+ </h3>
32
38
 
33
39
  <div class="preview hidden">
34
40
  <%= preview_box(@template_invocation, @host) %>
@@ -47,7 +47,7 @@ module ForemanRemoteExecution
47
47
 
48
48
  initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |_app|
49
49
  Foreman::Plugin.register :foreman_remote_execution do
50
- requires_foreman '>= 3.1'
50
+ requires_foreman '>= 3.2'
51
51
  register_global_js_file 'global'
52
52
 
53
53
  apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
@@ -152,7 +152,7 @@ module ForemanRemoteExecution
152
152
  setting 'remote_execution_job_invocation_report_template',
153
153
  type: :string,
154
154
  description: N_('Select a report template used for generating a report for a particular remote execution job'),
155
- default: 'Jobs - Invocation report template',
155
+ default: 'Job invocation - report template',
156
156
  full_name: N_('Job Invocation Report Template'),
157
157
  collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
158
158
  end
@@ -214,7 +214,11 @@ module ForemanRemoteExecution
214
214
  role 'Remote Execution User', USER_PERMISSIONS, 'Role with permissions to run remote execution jobs against hosts'
215
215
  role 'Remote Execution Manager', MANAGER_PERMISSIONS, 'Role with permissions to manage job templates, remote execution features, cancel jobs and view audit logs'
216
216
 
217
- add_all_permissions_to_default_roles
217
+ add_all_permissions_to_default_roles(except: [:execute_jobs_on_infrastructure_hosts])
218
+ add_permissions_to_default_roles({
219
+ Role::MANAGER => [:execute_jobs_on_infrastructure_hosts],
220
+ Role::SITE_MANAGER => USER_PERMISSIONS + [:execute_jobs_on_infrastructure_hosts],
221
+ })
218
222
 
219
223
  # add menu entry
220
224
  menu :top_menu, :job_templates,
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '5.0.0'.freeze
2
+ VERSION = '6.0.0'.freeze
3
3
  end
@@ -1,6 +1,5 @@
1
1
  # Autogenerated!
2
- _("Preupgrade job")
3
- _("Action with sub plans")
4
- _("Import facts")
5
- _("Import Puppet classes")
6
2
  _("Remote action:")
3
+ _("»Import facts«")
4
+ _("»Import Puppet classes«")
5
+ _("»Action with sub plans«")