foreman_remote_execution 4.4.0 → 4.5.3

Sign up to get free protection for your applications and to get access to all the features.
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