foreman_remote_execution 4.4.0 → 4.5.3

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/job_invocations_controller.rb +13 -24
  3. data/app/controllers/job_invocations_controller.rb +1 -1
  4. data/app/controllers/job_templates_controller.rb +4 -4
  5. data/app/controllers/ui_job_wizard_controller.rb +19 -0
  6. data/app/helpers/job_invocations_helper.rb +2 -2
  7. data/app/helpers/remote_execution_helper.rb +13 -9
  8. data/app/lib/actions/remote_execution/run_host_job.rb +36 -6
  9. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +7 -5
  10. data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +6 -0
  11. data/app/models/host_proxy_invocation.rb +4 -0
  12. data/app/models/host_status/execution_status.rb +5 -5
  13. data/app/models/job_invocation.rb +31 -12
  14. data/app/models/job_invocation_composer.rb +61 -19
  15. data/app/models/remote_execution_provider.rb +1 -1
  16. data/app/models/setting/remote_execution.rb +2 -2
  17. data/app/models/ssh_execution_provider.rb +4 -4
  18. data/app/models/targeting.rb +5 -1
  19. data/app/overrides/execution_interface.rb +8 -8
  20. data/app/overrides/subnet_proxies.rb +6 -6
  21. data/app/views/job_invocations/index.html.erb +1 -1
  22. data/app/views/templates/ssh/module_action.erb +1 -0
  23. data/app/views/templates/ssh/puppet_run_once.erb +1 -0
  24. data/config/routes.rb +1 -0
  25. data/db/migrate/20180110104432_rename_template_invocation_permission.rb +1 -1
  26. data/db/migrate/20190111153330_remove_remote_execution_without_proxy_setting.rb +4 -4
  27. data/db/migrate/2021051713291621250977_add_host_proxy_invocations.rb +12 -0
  28. data/extra/cockpit/foreman-cockpit-session +6 -6
  29. data/lib/foreman_remote_execution/engine.rb +11 -8
  30. data/lib/foreman_remote_execution/version.rb +1 -1
  31. data/package.json +2 -1
  32. data/test/functional/api/v2/job_invocations_controller_test.rb +14 -1
  33. data/test/unit/job_invocation_composer_test.rb +59 -2
  34. data/test/unit/job_invocation_test.rb +1 -1
  35. data/webpack/JobWizard/JobWizard.js +80 -19
  36. data/webpack/JobWizard/JobWizard.scss +42 -1
  37. data/webpack/JobWizard/JobWizardConstants.js +11 -0
  38. data/webpack/JobWizard/JobWizardSelectors.js +27 -1
  39. data/webpack/JobWizard/__tests__/__snapshots__/integration.test.js.snap +43 -0
  40. data/webpack/JobWizard/__tests__/fixtures.js +128 -0
  41. data/webpack/JobWizard/__tests__/integration.test.js +84 -0
  42. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +110 -0
  43. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +67 -0
  44. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +195 -0
  45. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +144 -0
  46. data/webpack/JobWizard/steps/AdvancedFields/__tests__/DescriptionField.test.js +23 -0
  47. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +34 -2
  48. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +122 -44
  49. data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +9 -1
  50. data/webpack/JobWizard/steps/Schedule/QueryType.js +48 -0
  51. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +61 -0
  52. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +25 -0
  53. data/webpack/JobWizard/steps/Schedule/StartEndDates.js +51 -0
  54. data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +22 -0
  55. data/webpack/JobWizard/steps/Schedule/index.js +41 -0
  56. data/webpack/JobWizard/steps/form/FormHelpers.js +20 -0
  57. data/webpack/JobWizard/steps/form/Formatter.js +149 -0
  58. data/webpack/JobWizard/steps/form/GroupedSelectField.js +3 -0
  59. data/webpack/JobWizard/steps/form/NumberInput.js +33 -0
  60. data/webpack/JobWizard/steps/form/SelectField.js +24 -3
  61. data/webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example +76 -0
  62. data/webpack/__mocks__/foremanReact/components/SearchBar.js +18 -1
  63. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +21 -2
  64. data/webpack/global_index.js +5 -3
  65. data/webpack/index.js +3 -0
  66. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +1 -5
  67. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js +8 -3
  68. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +1 -0
  69. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap +7 -2
  70. data/webpack/react_app/extend/{fills.js → fillRecentJobsCard.js} +7 -6
  71. data/webpack/react_app/extend/fillregistrationAdvanced.js +11 -0
  72. data/webpack/react_app/extend/reducers.js +2 -1
  73. metadata +24 -14
  74. data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +0 -70
  75. data/test/models/orchestration/ssh_test.rb +0 -56
  76. data/webpack/JobWizard/__tests__/JobWizard.test.js +0 -20
  77. data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +0 -83
  78. data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +0 -64
  79. data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +0 -38
  80. data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +0 -23
  81. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +0 -36
  82. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +0 -22
  83. data/webpack/fills_index.js +0 -11
@@ -1,4 +1,7 @@
1
1
  class JobInvocationComposer
2
+ class JobTemplateNotFound < StandardError; end
3
+
4
+ class FeatureNotFound < StandardError; end
2
5
 
3
6
  class UiParams
4
7
  attr_reader :ui_params
@@ -100,6 +103,17 @@ class JobInvocationComposer
100
103
 
101
104
  def initialize(api_params)
102
105
  @api_params = api_params
106
+
107
+ if api_params[:feature]
108
+ # set a default targeting type for backward compatibility
109
+ # when `for_feature` was used by the API it automatically set a default
110
+ api_params[:targeting_type] = Targeting::STATIC_TYPE
111
+ end
112
+
113
+ if api_params[:search_query].blank? && api_params[:host_ids].present?
114
+ translator = HostIdsTranslator.new(api_params[:host_ids])
115
+ api_params[:search_query] = translator.scoped_search
116
+ end
103
117
  end
104
118
 
105
119
  def params
@@ -107,12 +121,16 @@ class JobInvocationComposer
107
121
  :targeting => targeting_params,
108
122
  :triggering => triggering_params,
109
123
  :description_format => api_params[:description_format],
110
- :remote_execution_feature_id => api_params[:remote_execution_feature_id],
124
+ :remote_execution_feature_id => remote_execution_feature_id,
111
125
  :concurrency_control => concurrency_control_params,
112
126
  :execution_timeout_interval => api_params[:execution_timeout_interval] || template.execution_timeout_interval,
113
127
  :template_invocations => template_invocations_params }.with_indifferent_access
114
128
  end
115
129
 
130
+ def remote_execution_feature_id
131
+ feature&.id || api_params[:remote_execution_feature_id]
132
+ end
133
+
116
134
  def targeting_params
117
135
  raise ::Foreman::Exception, _('Cannot specify both bookmark_id and search_query') if api_params[:bookmark_id] && api_params[:search_query]
118
136
 
@@ -156,7 +174,7 @@ class JobInvocationComposer
156
174
  input = template.template_inputs_with_foreign.find { |i| i.name == name }
157
175
  unless input
158
176
  raise ::Foreman::Exception, _('Unknown input %{input_name} for template %{template_name}') %
159
- { :input_name => name, :template_name => template.name }
177
+ { :input_name => name, :template_name => template.name }
160
178
  end
161
179
  { :template_input_id => input.id, :value => value }
162
180
  end
@@ -170,8 +188,20 @@ class JobInvocationComposer
170
188
  inputs.select { |key, value| provider_input_names.include? key }.map { |key, value| { :name => key, :value => value } }
171
189
  end
172
190
 
191
+ def feature
192
+ @feature ||= RemoteExecutionFeature.feature(api_params[:feature]) if api_params[:feature]
193
+ rescue => e
194
+ raise(FeatureNotFound, e.message)
195
+ end
196
+
197
+ def job_template_id
198
+ feature&.job_template_id || api_params[:job_template_id]
199
+ end
200
+
173
201
  def template
174
- @template ||= JobTemplate.authorized(:view_job_templates).find(api_params[:job_template_id])
202
+ @template ||= JobTemplate.authorized(:view_job_templates).find(job_template_id)
203
+ rescue ActiveRecord::RecordNotFound
204
+ raise(JobTemplateNotFound, _("Template with id '%{id}' was not found") % { id: job_template_id })
175
205
  end
176
206
 
177
207
  private
@@ -239,25 +269,38 @@ class JobInvocationComposer
239
269
  end
240
270
  end
241
271
 
272
+ class HostIdsTranslator
273
+ attr_reader :bookmark, :hosts, :scoped_search, :host_ids
274
+
275
+ def initialize(input)
276
+ case input
277
+ when Bookmark
278
+ @bookmark = input
279
+ when Host::Base
280
+ @hosts = [input]
281
+ when Array
282
+ @hosts = input.map do |id|
283
+ Host::Managed.authorized.friendly.find(id)
284
+ end
285
+ when String
286
+ @scoped_search = input
287
+ else
288
+ @hosts = input
289
+ end
290
+
291
+ @scoped_search ||= Targeting.build_query_from_hosts(hosts.map(&:id)) if @hosts
292
+ end
293
+ end
294
+
242
295
  class ParamsForFeature
243
296
  attr_reader :feature_label, :feature, :provided_inputs
244
297
 
245
298
  def initialize(feature_label, hosts, provided_inputs = {})
246
299
  @feature = RemoteExecutionFeature.feature(feature_label)
247
300
  @provided_inputs = provided_inputs
248
- if hosts.is_a? Bookmark
249
- @host_bookmark = hosts
250
- elsif hosts.is_a? Host::Base
251
- @host_objects = [hosts]
252
- elsif hosts.is_a? Array
253
- @host_objects = hosts.map do |id|
254
- Host::Managed.authorized.friendly.find(id)
255
- end
256
- elsif hosts.is_a? String
257
- @host_scoped_search = hosts
258
- else
259
- @host_objects = hosts
260
- end
301
+ translator = HostIdsTranslator.new(hosts)
302
+ @host_bookmark = translator.bookmark
303
+ @host_scoped_search = translator.scoped_search
261
304
  end
262
305
 
263
306
  def params
@@ -275,7 +318,6 @@ class JobInvocationComposer
275
318
  ret = {}
276
319
  ret['targeting_type'] = Targeting::STATIC_TYPE
277
320
  ret['search_query'] = @host_scoped_search if @host_scoped_search
278
- ret['search_query'] = Targeting.build_query_from_hosts(@host_objects) if @host_objects
279
321
  ret['bookmark_id'] = @host_bookmark.id if @host_bookmark
280
322
  ret['user_id'] = User.current.id
281
323
  ret
@@ -363,7 +405,7 @@ class JobInvocationComposer
363
405
  job_invocation.effective_user_password = params[:effective_user_password]
364
406
 
365
407
  if @reruns && job_invocation.targeting.static?
366
- job_invocation.targeting.host_ids = JobInvocation.find(@reruns).targeting.host_ids
408
+ job_invocation.targeting.assign_host_ids(JobInvocation.find(@reruns).targeting.host_ids)
367
409
  job_invocation.targeting.mark_resolved!
368
410
  end
369
411
 
@@ -553,7 +595,7 @@ class JobInvocationComposer
553
595
 
554
596
  params[:template_invocations].select { |t| valid_template_ids.include?(t[:template_id].to_i) }.map do |template_invocation_params|
555
597
  template_invocation = job_invocation.pattern_template_invocations.build(:template_id => template_invocation_params[:template_id],
556
- :effective_user => build_effective_user(template_invocation_params))
598
+ :effective_user => build_effective_user(template_invocation_params))
557
599
  build_input_values_for(template_invocation, template_invocation_params)
558
600
  template_invocation
559
601
  end
@@ -50,7 +50,7 @@ class RemoteExecutionProvider
50
50
  method = host_setting(host, :remote_execution_effective_user_method)
51
51
  unless EFFECTIVE_USER_METHODS.include?(method)
52
52
  raise _('Effective user method "%{current_value}" is not one of %{valid_methods}') %
53
- { :current_value => method, :valid_methods => EFFECTIVE_USER_METHODS}
53
+ { :current_value => method, :valid_methods => EFFECTIVE_USER_METHODS}
54
54
  end
55
55
  method
56
56
  end
@@ -70,13 +70,13 @@ class Setting::RemoteExecution < Setting
70
70
  self.set('remote_execution_form_job_template',
71
71
  N_('Choose a job template that is pre-selected in job invocation form'),
72
72
  'Run Command - SSH Default',
73
- _('Form Job Template'),
73
+ N_('Form Job Template'),
74
74
  nil,
75
75
  { :collection => proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] } }),
76
76
  self.set('remote_execution_job_invocation_report_template',
77
77
  N_('Select a report template used for generating a report for a particular remote execution job'),
78
78
  'Jobs - Invocation report template',
79
- _('Job Invocation Report Template'),
79
+ N_('Job Invocation Report Template'),
80
80
  nil,
81
81
  { :collection => proc { self.job_invocation_report_templates_select } }),
82
82
  ]
@@ -2,10 +2,10 @@ class SSHExecutionProvider < RemoteExecutionProvider
2
2
  class << self
3
3
  def proxy_command_options(template_invocation, host)
4
4
  super.merge(:ssh_user => ssh_user(host),
5
- :effective_user => effective_user(template_invocation),
6
- :effective_user_method => effective_user_method(host),
7
- :cleanup_working_dirs => cleanup_working_dirs?(host),
8
- :ssh_port => ssh_port(host))
5
+ :effective_user => effective_user(template_invocation),
6
+ :effective_user_method => effective_user_method(host),
7
+ :cleanup_working_dirs => cleanup_working_dirs?(host),
8
+ :ssh_port => ssh_port(host))
9
9
  end
10
10
 
11
11
  def humanized_name
@@ -46,9 +46,13 @@ class Targeting < ApplicationRecord
46
46
  # pluck(:id) returns duplicate results for HostCollections
47
47
  host_ids = User.as(user.login) { Host.authorized(RESOLVE_PERMISSION, Host).search_for(search_query).order(:name, :id).pluck(:id).uniq }
48
48
  host_ids.shuffle!(random: Random.new) if randomized_ordering
49
+ self.assign_host_ids(host_ids)
50
+ self.save(:validate => false)
51
+ end
52
+
53
+ def assign_host_ids(host_ids)
49
54
  # this can be optimized even more, by introducing bulk insert
50
55
  self.targeting_hosts.build(host_ids.map { |id| { :host_id => id } })
51
- self.save(:validate => false)
52
56
  end
53
57
 
54
58
  def dynamic?
@@ -1,9 +1,9 @@
1
- Deface::Override.new(:virtual_path => 'hosts/_form',
2
- :name => 'add_execution_interface_js',
3
- :insert_before => 'div#primary',
4
- :text => '<%= javascript "foreman_remote_execution/execution_interface" %>')
1
+ Deface::Override.new(:virtual_path => 'hosts/_form',
2
+ :name => 'add_execution_interface_js',
3
+ :insert_before => 'div#primary',
4
+ :text => '<%= javascript "foreman_remote_execution/execution_interface" %>')
5
5
 
6
- Deface::Override.new(:virtual_path => 'nic/_base_form',
7
- :name => 'add_execution_interface',
8
- :insert_after => 'erb[loud]:contains("interface_provision")',
9
- :partial => 'overrides/nics/execution_interface')
6
+ Deface::Override.new(:virtual_path => 'nic/_base_form',
7
+ :name => 'add_execution_interface',
8
+ :insert_after => 'erb[loud]:contains("interface_provision")',
9
+ :partial => 'overrides/nics/execution_interface')
@@ -1,9 +1,9 @@
1
1
  Deface::Override.new(:virtual_path => 'subnets/_form',
2
- :name => 'add_remote_execution_proxies_tab',
3
- :insert_after => 'li.active',
4
- :partial => 'overrides/subnets/rex_tab')
2
+ :name => 'add_remote_execution_proxies_tab',
3
+ :insert_after => 'li.active',
4
+ :partial => 'overrides/subnets/rex_tab')
5
5
 
6
6
  Deface::Override.new(:virtual_path => 'subnets/_form',
7
- :name => 'add_remote_execution_proxies_tab_pane',
8
- :insert_after => 'div#proxies',
9
- :partial => 'overrides/subnets/rex_tab_pane')
7
+ :name => 'add_remote_execution_proxies_tab_pane',
8
+ :insert_after => 'div#proxies',
9
+ :partial => 'overrides/subnets/rex_tab_pane')
@@ -21,7 +21,7 @@
21
21
  <% @job_invocations.each do |invocation| %>
22
22
  <tr>
23
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>
24
- <td><%= trunc_with_tooltip(invocation&.targeting&.search_query, 15) %></td>
24
+ <td><%= trunc_with_tooltip(invocation.targeting.search_query, 15) %></td>
25
25
  <td><%= link_to_invocation_task_if_authorized(invocation) %></td>
26
26
  <td><%= invocation_result(invocation, :success_count) %></td>
27
27
  <td><%= invocation_result(invocation, :failed_count) %></td>
@@ -29,6 +29,7 @@ template_inputs:
29
29
  input_type: user
30
30
  required: false
31
31
  advanced: true
32
+ feature: katello_module_stream_action
32
33
  %>
33
34
 
34
35
  <%
@@ -10,6 +10,7 @@ template_inputs:
10
10
  description: Additional options to pass to puppet
11
11
  input_type: user
12
12
  required: false
13
+ feature: puppet_run_host
13
14
  %>
14
15
  <% if @host.operatingsystem.family == 'Debian' -%>
15
16
  export PATH=/opt/puppetlabs/bin:$PATH
data/config/routes.rb CHANGED
@@ -44,6 +44,7 @@ Rails.application.routes.draw do
44
44
  end
45
45
  get 'cockpit/redirect', to: 'cockpit#redirect'
46
46
  get 'ui_job_wizard/categories', to: 'ui_job_wizard#categories'
47
+ get 'ui_job_wizard/template/:id', to: 'ui_job_wizard#template'
47
48
 
48
49
  match '/experimental/job_wizard', to: 'react#index', :via => [:get]
49
50
 
@@ -16,7 +16,7 @@ class RenameTemplateInvocationPermission < ActiveRecord::Migration[4.2]
16
16
  return if old_permission.nil?
17
17
 
18
18
  new_permission = Permission.find_or_create_by(:name => new,
19
- :resource_type => 'TemplateInvocation')
19
+ :resource_type => 'TemplateInvocation')
20
20
  old_permission.filterings.each do |filtering|
21
21
  filtering.permission_id = new_permission.id
22
22
  filtering.save!
@@ -5,9 +5,9 @@ class RemoveRemoteExecutionWithoutProxySetting < ActiveRecord::Migration[5.2]
5
5
 
6
6
  def down
7
7
  Setting.create!(:name => 'remote_execution_without_proxy',
8
- :description => N_('When enabled, the remote execution will try to run '\
9
- 'the commands directly, when no proxy with remote execution '\
10
- 'feature is configured for the host.'),
11
- :default => false, :full_name => N_('Fallback Without Proxy'))
8
+ :description => N_('When enabled, the remote execution will try to run '\
9
+ 'the commands directly, when no proxy with remote execution '\
10
+ 'feature is configured for the host.'),
11
+ :default => false, :full_name => N_('Fallback Without Proxy'))
12
12
  end
13
13
  end
@@ -0,0 +1,12 @@
1
+ class AddHostProxyInvocations < ActiveRecord::Migration[6.0]
2
+ def change
3
+ # rubocop:disable Rails/CreateTableWithTimestamps
4
+ create_table :host_proxy_invocations do |t|
5
+ t.references :host, :null => false
6
+ t.references :smart_proxy, :null => false
7
+ end
8
+ # rubocop:enable Rails/CreateTableWithTimestamps
9
+
10
+ add_index :host_proxy_invocations, [:host_id, :smart_proxy_id], unique: true
11
+ end
12
+ end
@@ -56,13 +56,13 @@ end
56
56
 
57
57
  def send_auth_challenge(challenge)
58
58
  send_control({ "command" => "authorize",
59
- "cookie" => "1234", # must be present, but value doesn't matter
60
- "challenge" => challenge})
59
+ "cookie" => "1234", # must be present, but value doesn't matter
60
+ "challenge" => challenge})
61
61
  end
62
62
 
63
63
  def send_auth_response(response)
64
64
  send_control({ "command" => "authorize",
65
- "response" => response})
65
+ "response" => response})
66
66
  end
67
67
 
68
68
  def read_auth_reply
@@ -76,9 +76,9 @@ end
76
76
  def exit_with_problem(problem, message, auth_methods)
77
77
  LOG.error("#{problem} - #{message}")
78
78
  send_control({ "command" => "init",
79
- "problem" => problem,
80
- "message" => message,
81
- "auth-method-results" => auth_methods})
79
+ "problem" => problem,
80
+ "message" => message,
81
+ "auth-method-results" => auth_methods})
82
82
  exit 1
83
83
  end
84
84
 
@@ -51,14 +51,13 @@ module ForemanRemoteExecution
51
51
 
52
52
  initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |_app|
53
53
  Foreman::Plugin.register :foreman_remote_execution do
54
- register_global_js_file 'global'
55
54
  requires_foreman '>= 2.2'
55
+ register_global_js_file 'global'
56
56
 
57
57
  apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
58
58
  ApipieDSL.configuration.dsl_classes_matchers += [
59
59
  "#{ForemanRemoteExecution::Engine.root}/app/lib/foreman_remote_execution/renderer/**/*.rb",
60
60
  ]
61
- register_global_js_file 'global'
62
61
  automatic_assets(false)
63
62
  precompile_assets(*assets_to_precompile)
64
63
 
@@ -68,7 +67,7 @@ module ForemanRemoteExecution
68
67
  :'api/v2/job_templates' => [:index, :show, :revision, :export],
69
68
  :'api/v2/template_inputs' => [:index, :show],
70
69
  :'api/v2/foreign_input_sets' => [:index, :show],
71
- :ui_job_wizard => [:categories]}, :resource_type => 'JobTemplate'
70
+ :ui_job_wizard => [:categories, :template]}, :resource_type => 'JobTemplate'
72
71
  permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
73
72
  :'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
74
73
  permission :edit_job_templates, { :job_templates => [:edit, :update],
@@ -141,7 +140,7 @@ module ForemanRemoteExecution
141
140
  url_hash: { controller: 'job_wizard', action: :index },
142
141
  caption: N_('Job wizard'),
143
142
  parent: :lab_features_menu,
144
- url: 'experimental/job_wizard',
143
+ url: '/experimental/job_wizard',
145
144
  after: :host_wizard
146
145
 
147
146
  register_custom_status HostStatus::ExecutionStatus
@@ -163,9 +162,15 @@ module ForemanRemoteExecution
163
162
 
164
163
  # Extend Registration module
165
164
  extend_allowed_registration_vars :remote_execution_interface
166
- register_global_js_file 'fills'
167
165
  ForemanTasks.dynflow.eager_load_actions!
168
- extend_observable_events(::Dynflow::Action.descendants.select { |klass| klass <= ::Actions::ObservableAction }.map(&:namespaced_event_names))
166
+ extend_observable_events(
167
+ ::Dynflow::Action.descendants.select do |klass|
168
+ klass <= ::Actions::ObservableAction
169
+ end.map(&:namespaced_event_names) +
170
+ RemoteExecutionFeature.all.pluck(:label).map do |label|
171
+ ::Actions::RemoteExecution::RunHostJob.feature_job_event_name(label)
172
+ end
173
+ )
169
174
  end
170
175
  end
171
176
 
@@ -196,12 +201,10 @@ module ForemanRemoteExecution
196
201
 
197
202
  Host::Managed.prepend ForemanRemoteExecution::HostExtensions
198
203
  Host::Managed.include ForemanTasks::Concerns::HostActionSubject
199
- Host::Managed.include ForemanRemoteExecution::Orchestration::SSH
200
204
 
201
205
  (Nic::Base.descendants + [Nic::Base]).each do |klass|
202
206
  klass.send(:include, ForemanRemoteExecution::NicExtensions)
203
207
  end
204
- Nic::Managed.include ForemanRemoteExecution::Orchestration::SSH
205
208
 
206
209
  Bookmark.include ForemanRemoteExecution::BookmarkExtensions
207
210
  HostsHelper.prepend ForemanRemoteExecution::HostsHelperExtensions
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '4.4.0'.freeze
2
+ VERSION = '4.5.3'.freeze
3
3
  end
data/package.json CHANGED
@@ -29,7 +29,8 @@
29
29
  "babel-eslint": "^10.0.0",
30
30
  "eslint": "^6.8.0",
31
31
  "prettier": "^1.19.1",
32
- "@patternfly/react-catalog-view-extension": "^4.8.126"
32
+ "@patternfly/react-catalog-view-extension": "^4.8.126",
33
+ "redux-mock-store": "^1.2.2"
33
34
  },
34
35
  "peerDependencies": {
35
36
  "@theforeman/vendor": "^8.3.0"
@@ -114,11 +114,24 @@ module Api
114
114
  assert_response :success
115
115
  end
116
116
 
117
- test 'search_query' do
117
+ test 'host ids as search_query' do
118
118
  @attrs[:host_ids] = 'name = testfqdn'
119
119
  post :create, params: { job_invocation: @attrs }
120
120
  assert_response :success
121
121
  end
122
+
123
+ test 'with search_query param' do
124
+ @attrs[:targeting_type] = 'static_query'
125
+ @attrs[:search_query] = 'name = testfqdn'
126
+ post :create, params: { job_invocation: @attrs }
127
+ assert_response :success
128
+ end
129
+
130
+ test 'with job_template_id param' do
131
+ @attrs[:job_template_id] = 12_345
132
+ post :create, params: { job_invocation: @attrs }
133
+ assert_response :error
134
+ end
122
135
  end
123
136
  end
124
137