foreman_remote_execution 16.0.4 → 16.0.5

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/job_invocations_controller.rb +28 -1
  3. data/app/controllers/template_invocations_controller.rb +1 -1
  4. data/config/routes.rb +1 -0
  5. data/lib/foreman_remote_execution/engine.rb +9 -256
  6. data/lib/foreman_remote_execution/plugin.rb +246 -0
  7. data/lib/foreman_remote_execution/version.rb +1 -1
  8. data/test/functional/api/v2/job_invocations_controller_test.rb +1 -1
  9. data/test/unit/job_invocation_report_template_test.rb +6 -6
  10. data/webpack/JobInvocationDetail/CheckboxesActions.js +196 -0
  11. data/webpack/JobInvocationDetail/{JobInvocationHostTableToolbar.js → DropdownFilter.js} +3 -6
  12. data/webpack/JobInvocationDetail/JobInvocationConstants.js +6 -6
  13. data/webpack/JobInvocationDetail/JobInvocationDetail.scss +18 -0
  14. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +205 -89
  15. data/webpack/JobInvocationDetail/JobInvocationSelectors.js +30 -3
  16. data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +20 -27
  17. data/webpack/JobInvocationDetail/OpenAllInvocationsModal.js +118 -0
  18. data/webpack/JobInvocationDetail/TemplateInvocation.js +54 -24
  19. data/webpack/JobInvocationDetail/TemplateInvocationComponents/TemplateActionButtons.js +8 -10
  20. data/webpack/JobInvocationDetail/TemplateInvocationPage.js +1 -1
  21. data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +1 -1
  22. data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +202 -0
  23. data/webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js +34 -28
  24. data/webpack/JobInvocationDetail/index.js +61 -30
  25. data/webpack/JobWizard/steps/HostsAndInputs/buildHostQuery.js +26 -7
  26. data/webpack/react_app/components/TargetingHosts/TargetingHostsLabelsRow.scss +1 -1
  27. metadata +8 -6
  28. data/webpack/JobInvocationDetail/OpenAlInvocations.js +0 -111
  29. data/webpack/JobInvocationDetail/__tests__/OpenAlInvocations.test.js +0 -110
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 263ac53880d0a4d4673659013457388598c58706f452a8f6db7c94df017ac634
4
- data.tar.gz: c7806ab71384b036d0ce50e2f8b55c0f9c13095fcfc455dd8057d28fabc74682
3
+ metadata.gz: f0af6a4d6d568edd8bf5d878940d19f72d3f2b2ad2c67e767cd7764e2287ba3f
4
+ data.tar.gz: 5b7f5b64a90c38b6b65df711be7bf93c586c73400386c96c6ae280285b4a9349
5
5
  SHA512:
6
- metadata.gz: 8c20ef4f8c84e5b57e3b1562dba4191d3552269d327de0ce51e7dd9d737db87a3e15a390abb60003568035e168adf2e3f3053fdbaf3f36a3f0e3282941081008
7
- data.tar.gz: 33c31c42d97a26a67331097c545e731c3b44a4430e6c8a2ce26f516b4296db78908639ab410b5959128f182d58d05681d4fc46e495c95c6cce120b2a2ff25e80
6
+ metadata.gz: 408d5714fba95e7213fa42c2510021231cd2d5c61b7ecc502a0d76c96ca80f97758e03928da5a1c1acc9547fe4fcbfbe2f836991954b78a09cbe7b6ef0644e95
7
+ data.tar.gz: c0468bdebd334affe636a1aa34dff3689707084a0d0f141b05c0a09428f6700aa48b1a43b2e9e61262d8bd8968ab4c22b3d1ab68ad48cf8527b930989fac8994
@@ -149,6 +149,33 @@ class JobInvocationsController < ApplicationController
149
149
  render :json => {:job_invocations => job_invocations}
150
150
  end
151
151
 
152
+ def list_jobs_hosts
153
+ @job_invocation = resource_base.find(params[:id])
154
+ hosts = @job_invocation.targeting.hosts.authorized(:view_hosts, Host)
155
+ hosts = hosts.search_for(params[:search])
156
+ template_invocations_task_by_hosts = {}
157
+ hosts.each do |host|
158
+ template_invocation = @job_invocation.template_invocations.find { |template_inv| template_inv.host_id == host.id }
159
+ next unless template_invocation
160
+ template_invocation_task = template_invocation.run_host_job_task
161
+ template_invocations_task_by_hosts[host.id] =
162
+ {
163
+ :host_name => host.name,
164
+ :id => host.id,
165
+ :task => template_invocation_task.attributes.merge({cancellable: template_invocation_task.cancellable? }),
166
+ :permissions => {
167
+ :view_foreman_tasks => authorized_for(:permission => :view_foreman_tasks, :auth_object => template_invocation_task),
168
+ :cancel_job_invocations => authorized_for(:permission => :cancel_job_invocations, :auth_object => @job_invocation),
169
+ :execute_jobs => authorized_for(controller: :job_invocations, action: :create) && (!host.infrastructure_host? || User.current.can?(:execute_jobs_on_infrastructure_hosts)),
170
+ },
171
+ }
172
+ end
173
+
174
+ render json: {
175
+ :template_invocations_task_by_hosts => template_invocations_task_by_hosts,
176
+ }
177
+ end
178
+
152
179
  private
153
180
 
154
181
  def action_permission
@@ -159,7 +186,7 @@ class JobInvocationsController < ApplicationController
159
186
  'create'
160
187
  when 'cancel'
161
188
  'cancel'
162
- when 'chart', 'preview_job_invocations_per_host'
189
+ when 'chart', 'preview_job_invocations_per_host', 'list_jobs_hosts'
163
190
  'view'
164
191
  else
165
192
  super
@@ -48,7 +48,7 @@ class TemplateInvocationsController < ApplicationController
48
48
 
49
49
  auto_refresh = @job_invocation.task.try(:pending?)
50
50
  finished = @job_invocation.status_label == 'failed' || @job_invocation.status_label == 'succeeded' || @job_invocation.status_label == 'cancelled'
51
- render :json => { :output => lines, :preview => template_invocation_preview(@template_invocation, @host), :proxy => proxy, :input_values => transformed_input_values, :job_invocation_description => @job_invocation.description, :task_id => @template_invocation_task.id, :task_cancellable => @template_invocation_task.cancellable?, :host_name => @host.name, :permissions => {
51
+ render :json => { :output => lines, :preview => template_invocation_preview(@template_invocation, @host), :proxy => proxy, :input_values => transformed_input_values, :job_invocation_description => @job_invocation.description, :task => @template_invocation_task.attributes.merge({cancellable: @template_invocation_task.cancellable? }), :host_name => @host.name, :permissions => {
52
52
  :view_foreman_tasks => User.current.allowed_to?(:view_foreman_tasks),
53
53
  :cancel_job_invocations => User.current.allowed_to?(:cancel_job_invocations),
54
54
  :execute_jobs => User.current.allowed_to?(:create_job_invocations) && (!@host.infrastructure_host? || User.current.can?(:execute_jobs_on_infrastructure_hosts)),
data/config/routes.rb CHANGED
@@ -35,6 +35,7 @@ Rails.application.routes.draw do
35
35
  get 'auto_complete_search'
36
36
  end
37
37
  member do
38
+ get 'hosts', to: 'job_invocations#list_jobs_hosts'
38
39
  post 'cancel'
39
40
  end
40
41
  end
@@ -7,13 +7,14 @@ module ForemanRemoteExecution
7
7
  # Precompile any JS or CSS files under app/assets/
8
8
  # If requiring files from each other, list them explicitly here to avoid precompiling the same
9
9
  # content twice.
10
- assets_to_precompile =
11
- Dir.chdir(root) do
10
+ def self.assets_to_precompile
11
+ assets = Dir.chdir(root) do
12
12
  Dir['app/assets/javascripts/**/*'].map do |f|
13
13
  f.split(File::SEPARATOR, 4).last
14
14
  end
15
15
  end
16
- assets_to_precompile += %w(foreman_remote_execution/foreman_remote_execution.css)
16
+ assets << 'foreman_remote_execution/foreman_remote_execution.css'
17
+ end
17
18
 
18
19
  # Add any db migrations
19
20
  initializer 'foreman_remote_execution.load_app_instance_data' do |app|
@@ -34,260 +35,16 @@ module ForemanRemoteExecution
34
35
 
35
36
  initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |app|
36
37
  app.reloader.to_prepare do
37
- Foreman::Plugin.register :foreman_remote_execution do
38
- requires_foreman '>= 3.15'
39
- register_global_js_file 'global'
40
- register_gettext
41
-
42
- apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
43
- ApipieDSL.configuration.dsl_classes_matchers += [
44
- "#{ForemanRemoteExecution::Engine.root}/app/lib/foreman_remote_execution/renderer/**/*.rb",
45
- ]
46
- automatic_assets(false)
47
- precompile_assets(*assets_to_precompile)
48
-
49
- # Add settings to a Remote Execution category
50
- settings do
51
- category :remote_execution, N_('Remote Execution') do
52
- setting 'remote_execution_fallback_proxy',
53
- type: :boolean,
54
- description: 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'),
55
- default: false,
56
- full_name: N_('Fallback to Any Proxy')
57
- setting 'remote_execution_global_proxy',
58
- type: :boolean,
59
- description: N_('Search for remote execution proxy outside of the proxies assigned to the host. The search will be limited to the host\'s organization and location.'),
60
- default: true,
61
- full_name: N_('Enable Global Proxy')
62
- setting 'remote_execution_ssh_user',
63
- type: :string,
64
- description: N_('Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user.'),
65
- default: 'root',
66
- full_name: N_('SSH User')
67
- setting 'remote_execution_effective_user',
68
- type: :string,
69
- description: 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.'),
70
- default: 'root',
71
- full_name: N_('Effective User')
72
- setting 'remote_execution_effective_user_method',
73
- type: :string,
74
- description: N_('What command should be used to switch to the effective user. One of %s') % ::ScriptExecutionProvider::EFFECTIVE_USER_METHODS.inspect,
75
- default: 'sudo',
76
- full_name: N_('Effective User Method'),
77
- collection: proc { Hash[::ScriptExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] }
78
- setting 'remote_execution_effective_user_password',
79
- type: :string,
80
- description: N_('Effective user password'),
81
- default: '',
82
- full_name: N_('Effective user password'),
83
- encrypted: true
84
- setting 'remote_execution_sync_templates',
85
- type: :boolean,
86
- description: N_('Whether we should sync templates from disk when running db:seed.'),
87
- default: true,
88
- full_name: N_('Sync Job Templates')
89
- setting 'remote_execution_ssh_port',
90
- type: :integer,
91
- description: N_('Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port.'),
92
- default: 22,
93
- full_name: N_('SSH Port')
94
- setting 'remote_execution_connect_by_ip',
95
- type: :boolean,
96
- description: N_('Should the ip addresses on host interfaces be preferred over the fqdn? '\
97
- '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. '\
98
- 'For dual-stacked hosts you should consider the remote_execution_connect_by_ip_prefer_ipv6 setting'),
99
- default: false,
100
- full_name: N_('Connect by IP')
101
- setting 'remote_execution_connect_by_ip_prefer_ipv6',
102
- type: :boolean,
103
- description: N_('When connecting using ip address, should the IPv6 addresses be preferred? '\
104
- 'If no IPv6 address is set, it falls back to IPv4 automatically. You may override this per host by setting a parameter called remote_execution_connect_by_ip_prefer_ipv6. '\
105
- 'By default and for compatibility, IPv4 will be preferred over IPv6 by default'),
106
- default: false,
107
- full_name: N_('Prefer IPv6 over IPv4')
108
- setting 'remote_execution_ssh_password',
109
- type: :string,
110
- description: N_('Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password'),
111
- default: nil,
112
- full_name: N_('Default SSH password'),
113
- encrypted: true
114
- setting 'remote_execution_ssh_key_passphrase',
115
- type: :string,
116
- description: N_('Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase'),
117
- default: nil,
118
- full_name: N_('Default SSH key passphrase'),
119
- encrypted: true
120
- setting 'remote_execution_cleanup_working_dirs',
121
- type: :boolean,
122
- description: 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.'),
123
- default: true,
124
- full_name: N_('Cleanup working directories')
125
- setting 'remote_execution_cockpit_url',
126
- type: :string,
127
- description: N_('Where to find the Cockpit instance for the Web Console button. By default, no button is shown.'),
128
- default: nil,
129
- full_name: N_('Cockpit URL')
130
- setting 'remote_execution_form_job_template',
131
- type: :string,
132
- description: N_('Choose a job template that is pre-selected in job invocation form'),
133
- default: 'Run Command - Script Default',
134
- full_name: N_('Form Job Template'),
135
- collection: proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] }
136
- setting 'remote_execution_job_invocation_report_template',
137
- type: :string,
138
- description: N_('Select a report template used for generating a report for a particular remote execution job'),
139
- default: 'Job - Invocation Report',
140
- full_name: N_('Job Invocation Report Template'),
141
- collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
142
- setting 'remote_execution_time_to_pickup',
143
- type: :integer,
144
- description: N_('Time in seconds within which the host has to pick up a job. If the job is not picked up within this limit, the job will be cancelled. Defaults to 1 day. Applies only to pull-mqtt based jobs.'),
145
- default: 24 * 60 * 60,
146
- full_name: N_('Time to pickup')
147
- end
148
- end
149
-
150
- # Add permissions
151
- security_block :foreman_remote_execution do
152
- permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview, :export],
153
- :'api/v2/job_templates' => [:index, :show, :revision, :export],
154
- :'api/v2/template_inputs' => [:index, :show],
155
- :'api/v2/foreign_input_sets' => [:index, :show],
156
- :ui_job_wizard => [:categories, :template, :resources, :job_invocation]}, :resource_type => 'JobTemplate'
157
- permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
158
- :'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
159
- permission :edit_job_templates, { :job_templates => [:edit, :update],
160
- :'api/v2/job_templates' => [:update],
161
- :'api/v2/template_inputs' => [:create, :update, :destroy],
162
- :'api/v2/foreign_input_sets' => [:create, :update, :destroy]}, :resource_type => 'JobTemplate'
163
- permission :view_remote_execution_features, { :remote_execution_features => [:index, :show],
164
- :'api/v2/remote_execution_features' => [:index, :show, :available_remote_execution_features]},
165
- :resource_type => 'RemoteExecutionFeature'
166
- permission :edit_remote_execution_features, { :remote_execution_features => [:update],
167
- :'api/v2/remote_execution_features' => [:update ]}, :resource_type => 'RemoteExecutionFeature'
168
- permission :destroy_job_templates, { :job_templates => [:destroy],
169
- :'api/v2/job_templates' => [:destroy] }, :resource_type => 'JobTemplate'
170
- permission :lock_job_templates, { :job_templates => [:lock, :unlock] }, :resource_type => 'JobTemplate'
171
- permission :create_job_invocations, { :job_invocations => [:new, :create, :legacy_create, :refresh, :rerun, :preview_hosts],
172
- 'api/v2/job_invocations' => [:create, :rerun] }, :resource_type => 'JobInvocation'
173
- permission :view_job_invocations, { :job_invocations => [:index, :chart, :show, :auto_complete_search, :preview_job_invocations_per_host], :template_invocations => [:show, :show_template_invocation_by_host],
174
- 'api/v2/job_invocations' => [:index, :show, :output, :raw_output, :outputs, :hosts] }, :resource_type => 'JobInvocation'
175
- permission :view_template_invocations, { :template_invocations => [:show, :template_invocation_preview, :show_template_invocation_by_host],
176
- 'api/v2/template_invocations' => [:template_invocations], :ui_job_wizard => [:job_invocation] }, :resource_type => 'TemplateInvocation'
177
- permission :create_template_invocations, {}, :resource_type => 'TemplateInvocation'
178
- permission :execute_jobs_on_infrastructure_hosts, {}, :resource_type => 'JobInvocation'
179
- permission :cancel_job_invocations, { :job_invocations => [:cancel], 'api/v2/job_invocations' => [:cancel] }, :resource_type => 'JobInvocation'
180
- # this permissions grants user to get auto completion hints when setting up filters
181
- permission :filter_autocompletion_for_template_invocation, { :template_invocations => [ :auto_complete_search, :index ] },
182
- :resource_type => 'TemplateInvocation'
183
- permission :cockpit_hosts, { 'cockpit' => [:redirect, :host_ssh_params] }, :resource_type => 'Host'
184
- end
185
-
186
- USER_PERMISSIONS = [
187
- :view_job_templates,
188
- :view_job_invocations,
189
- :create_job_invocations,
190
- :create_template_invocations,
191
- :view_hosts,
192
- :view_smart_proxies,
193
- :view_remote_execution_features,
194
- ].freeze
195
- MANAGER_PERMISSIONS = USER_PERMISSIONS + [
196
- :cancel_job_invocations,
197
- :destroy_job_templates,
198
- :edit_job_templates,
199
- :create_job_templates,
200
- :lock_job_templates,
201
- :view_audit_logs,
202
- :filter_autocompletion_for_template_invocation,
203
- :edit_remote_execution_features,
204
- ]
205
-
206
- # Add a new role called 'Remote Execution User ' if it doesn't exist
207
- role 'Remote Execution User', USER_PERMISSIONS, 'Role with permissions to run remote execution jobs against hosts'
208
- role 'Remote Execution Manager', MANAGER_PERMISSIONS, 'Role with permissions to manage job templates, remote execution features, cancel jobs and view audit logs'
209
-
210
- add_all_permissions_to_default_roles(except: [:execute_jobs_on_infrastructure_hosts])
211
- add_permissions_to_default_roles({
212
- Role::MANAGER => [:execute_jobs_on_infrastructure_hosts],
213
- Role::SITE_MANAGER => USER_PERMISSIONS + [:execute_jobs_on_infrastructure_hosts],
214
- })
215
-
216
- # add menu entry
217
- menu :top_menu, :job_templates,
218
- url_hash: { controller: :job_templates, action: :index },
219
- caption: N_('Job Templates'),
220
- parent: :hosts_menu,
221
- after: :provisioning_templates
222
- menu :admin_menu, :remote_execution_features,
223
- url_hash: { controller: :remote_execution_features, action: :index },
224
- caption: N_('Remote Execution Features'),
225
- parent: :administer_menu,
226
- after: :bookmarks
227
-
228
- menu :top_menu, :job_invocations,
229
- url_hash: { controller: :job_invocations, action: :index },
230
- caption: N_('Jobs'),
231
- parent: :monitor_menu,
232
- after: :audits
233
-
234
- menu :labs_menu, :job_invocations_detail,
235
- url_hash: { controller: :job_invocations, action: :show },
236
- caption: N_('Job invocations detail'),
237
- parent: :lab_features_menu,
238
- url: '/experimental/job_invocations_detail/1'
239
-
240
- register_custom_status HostStatus::ExecutionStatus
241
- # add dashboard widget
242
- # widget 'foreman_remote_execution_widget', name: N_('Foreman plugin template widget'), sizex: 4, sizey: 1
243
- widget 'dashboard/latest-jobs', :name => N_('Latest Jobs'), :sizex => 6, :sizey => 1
244
-
245
- parameter_filter Subnet, :remote_execution_proxies, :remote_execution_proxy_ids => []
246
- parameter_filter Nic::Interface do |ctx|
247
- ctx.permit :execution
248
- end
249
-
250
- register_graphql_query_field :job_invocations, '::Types::JobInvocation', :collection_field
251
- register_graphql_query_field :job_invocation, '::Types::JobInvocation', :record_field
252
-
253
- register_graphql_mutation_field :create_job_invocation, ::Mutations::JobInvocations::Create
254
-
255
- extend_template_helpers ForemanRemoteExecution::RendererMethods
256
-
257
- extend_rabl_template 'api/v2/smart_proxies/main', 'api/v2/smart_proxies/pubkey'
258
- extend_rabl_template 'api/v2/interfaces/main', 'api/v2/interfaces/execution_flag'
259
- extend_rabl_template 'api/v2/subnets/show', 'api/v2/subnets/remote_execution_proxies'
260
- extend_rabl_template 'api/v2/hosts/main', 'api/v2/host/main'
261
- parameter_filter ::Subnet, :remote_execution_proxy_ids
262
-
263
- describe_host do
264
- multiple_actions_provider :rex_hosts_multiple_actions
265
- overview_buttons_provider :rex_host_overview_buttons
266
- end
267
-
268
- # Extend Registration module
269
- extend_allowed_registration_vars :remote_execution_interface
270
- extend_allowed_registration_vars :setup_remote_execution_pull
271
- ForemanTasks.dynflow.eager_load_actions!
272
- extend_observable_events(
273
- ::Dynflow::Action.descendants.select do |klass|
274
- klass <= ::Actions::ObservableAction
275
- end.map(&:namespaced_event_names) +
276
- RemoteExecutionFeature.all.pluck(:label).flat_map do |label|
277
- [::Actions::RemoteExecution::RunHostJob, ::Actions::RemoteExecution::RunHostsJob].map do |klass|
278
- klass.feature_job_event_names(label)
279
- end
280
- end
281
- )
282
- end
38
+ # Allow plugin registration to call application code once on boot
39
+ require_relative 'plugin'
283
40
  end
284
41
  end
285
42
 
286
43
  initializer 'foreman_remote_execution.assets.precompile' do |app|
287
- app.config.assets.precompile += assets_to_precompile
44
+ app.config.assets.precompile += Engine.assets_to_precompile
288
45
  end
289
46
  initializer 'foreman_remote_execution.configure_assets', group: :assets do
290
- SETTINGS[:foreman_remote_execution] = { assets: { precompile: assets_to_precompile } }
47
+ SETTINGS[:foreman_remote_execution] = { assets: { precompile: Engine.assets_to_precompile } }
291
48
  end
292
49
 
293
50
  # Include concerns in this config.to_prepare block
@@ -300,8 +57,7 @@ module ForemanRemoteExecution
300
57
  # e.g. having ProvisioningTemplate < Template, adding has_many :template_inputs to Template from concern
301
58
  # Template.reflect_on_association :template_inputs # => <#Association...
302
59
  # ProvisioningTemplate.reflect_on_association :template_inputs # => nil
303
- require_dependency 'job_template'
304
- (Template.descendants + [Template]).each { |klass| klass.send(:include, ForemanRemoteExecution::TemplateExtensions) }
60
+ (Template.descendants + [JobTemplate, Template]).each { |klass| klass.send(:include, ForemanRemoteExecution::TemplateExtensions) }
305
61
  Template.prepend ForemanRemoteExecution::TemplateOverrides
306
62
 
307
63
  (Taxonomy.descendants + [Taxonomy]).each { |klass| klass.send(:include, ForemanRemoteExecution::TaxonomyExtensions) }
@@ -323,9 +79,6 @@ module ForemanRemoteExecution
323
79
  Subnet.include ForemanRemoteExecution::SubnetExtensions
324
80
 
325
81
  ::Api::V2::InterfacesController.include Api::V2::InterfacesControllerExtensions
326
- # We need to explicitly force to load the Task model due to Rails loader
327
- # having issues with resolving it to Rake::Task otherwise
328
- require_dependency 'foreman_tasks/task'
329
82
  ForemanTasks::Task.include ForemanRemoteExecution::ForemanTasksTaskExtensions
330
83
  ForemanTasks::Cleaner.include ForemanRemoteExecution::ForemanTasksCleanerExtensions
331
84
  RemoteExecutionProvider.register(:SSH, ::ScriptExecutionProvider)
@@ -0,0 +1,246 @@
1
+ Foreman::Plugin.register :foreman_remote_execution do
2
+ requires_foreman '>= 3.15'
3
+ register_global_js_file 'global'
4
+ register_gettext
5
+
6
+ apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
7
+ ApipieDSL.configuration.dsl_classes_matchers += [
8
+ "#{ForemanRemoteExecution::Engine.root}/app/lib/foreman_remote_execution/renderer/**/*.rb",
9
+ ]
10
+ automatic_assets(false)
11
+ precompile_assets(ForemanRemoteExecution::Engine.assets_to_precompile)
12
+
13
+ # Add settings to a Remote Execution category
14
+ settings do
15
+ category :remote_execution, N_('Remote Execution') do
16
+ setting 'remote_execution_fallback_proxy',
17
+ type: :boolean,
18
+ description: 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'),
19
+ default: false,
20
+ full_name: N_('Fallback to Any Proxy')
21
+ setting 'remote_execution_global_proxy',
22
+ type: :boolean,
23
+ description: N_('Search for remote execution proxy outside of the proxies assigned to the host. The search will be limited to the host\'s organization and location.'),
24
+ default: true,
25
+ full_name: N_('Enable Global Proxy')
26
+ setting 'remote_execution_ssh_user',
27
+ type: :string,
28
+ description: N_('Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user.'),
29
+ default: 'root',
30
+ full_name: N_('SSH User')
31
+ setting 'remote_execution_effective_user',
32
+ type: :string,
33
+ description: 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.'),
34
+ default: 'root',
35
+ full_name: N_('Effective User')
36
+ setting 'remote_execution_effective_user_method',
37
+ type: :string,
38
+ description: N_('What command should be used to switch to the effective user. One of %s') % ::ScriptExecutionProvider::EFFECTIVE_USER_METHODS.inspect,
39
+ default: 'sudo',
40
+ full_name: N_('Effective User Method'),
41
+ collection: proc { Hash[::ScriptExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] }
42
+ setting 'remote_execution_effective_user_password',
43
+ type: :string,
44
+ description: N_('Effective user password'),
45
+ default: '',
46
+ full_name: N_('Effective user password'),
47
+ encrypted: true
48
+ setting 'remote_execution_sync_templates',
49
+ type: :boolean,
50
+ description: N_('Whether we should sync templates from disk when running db:seed.'),
51
+ default: true,
52
+ full_name: N_('Sync Job Templates')
53
+ setting 'remote_execution_ssh_port',
54
+ type: :integer,
55
+ description: N_('Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port.'),
56
+ default: 22,
57
+ full_name: N_('SSH Port')
58
+ setting 'remote_execution_connect_by_ip',
59
+ type: :boolean,
60
+ description: N_('Should the ip addresses on host interfaces be preferred over the fqdn? '\
61
+ '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. '\
62
+ 'For dual-stacked hosts you should consider the remote_execution_connect_by_ip_prefer_ipv6 setting'),
63
+ default: false,
64
+ full_name: N_('Connect by IP')
65
+ setting 'remote_execution_connect_by_ip_prefer_ipv6',
66
+ type: :boolean,
67
+ description: N_('When connecting using ip address, should the IPv6 addresses be preferred? '\
68
+ 'If no IPv6 address is set, it falls back to IPv4 automatically. You may override this per host by setting a parameter called remote_execution_connect_by_ip_prefer_ipv6. '\
69
+ 'By default and for compatibility, IPv4 will be preferred over IPv6 by default'),
70
+ default: false,
71
+ full_name: N_('Prefer IPv6 over IPv4')
72
+ setting 'remote_execution_ssh_password',
73
+ type: :string,
74
+ description: N_('Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password'),
75
+ default: nil,
76
+ full_name: N_('Default SSH password'),
77
+ encrypted: true
78
+ setting 'remote_execution_ssh_key_passphrase',
79
+ type: :string,
80
+ description: N_('Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase'),
81
+ default: nil,
82
+ full_name: N_('Default SSH key passphrase'),
83
+ encrypted: true
84
+ setting 'remote_execution_cleanup_working_dirs',
85
+ type: :boolean,
86
+ description: 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.'),
87
+ default: true,
88
+ full_name: N_('Cleanup working directories')
89
+ setting 'remote_execution_cockpit_url',
90
+ type: :string,
91
+ description: N_('Where to find the Cockpit instance for the Web Console button. By default, no button is shown.'),
92
+ default: nil,
93
+ full_name: N_('Cockpit URL')
94
+ setting 'remote_execution_form_job_template',
95
+ type: :string,
96
+ description: N_('Choose a job template that is pre-selected in job invocation form'),
97
+ default: 'Run Command - Script Default',
98
+ full_name: N_('Form Job Template'),
99
+ collection: proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] }
100
+ setting 'remote_execution_job_invocation_report_template',
101
+ type: :string,
102
+ description: N_('Select a report template used for generating a report for a particular remote execution job'),
103
+ default: 'Job - Invocation Report',
104
+ full_name: N_('Job Invocation Report Template'),
105
+ collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
106
+ setting 'remote_execution_time_to_pickup',
107
+ type: :integer,
108
+ description: N_('Time in seconds within which the host has to pick up a job. If the job is not picked up within this limit, the job will be cancelled. Defaults to 1 day. Applies only to pull-mqtt based jobs.'),
109
+ default: 24 * 60 * 60,
110
+ full_name: N_('Time to pickup')
111
+ end
112
+ end
113
+
114
+ # Add permissions
115
+ security_block :foreman_remote_execution do
116
+ permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview, :export],
117
+ :'api/v2/job_templates' => [:index, :show, :revision, :export],
118
+ :'api/v2/template_inputs' => [:index, :show],
119
+ :'api/v2/foreign_input_sets' => [:index, :show],
120
+ :ui_job_wizard => [:categories, :template, :resources, :job_invocation]}, :resource_type => 'JobTemplate'
121
+ permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
122
+ :'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
123
+ permission :edit_job_templates, { :job_templates => [:edit, :update],
124
+ :'api/v2/job_templates' => [:update],
125
+ :'api/v2/template_inputs' => [:create, :update, :destroy],
126
+ :'api/v2/foreign_input_sets' => [:create, :update, :destroy]}, :resource_type => 'JobTemplate'
127
+ permission :view_remote_execution_features, { :remote_execution_features => [:index, :show],
128
+ :'api/v2/remote_execution_features' => [:index, :show, :available_remote_execution_features]},
129
+ :resource_type => 'RemoteExecutionFeature'
130
+ permission :edit_remote_execution_features, { :remote_execution_features => [:update],
131
+ :'api/v2/remote_execution_features' => [:update]}, :resource_type => 'RemoteExecutionFeature'
132
+ permission :destroy_job_templates, { :job_templates => [:destroy],
133
+ :'api/v2/job_templates' => [:destroy] }, :resource_type => 'JobTemplate'
134
+ permission :lock_job_templates, { :job_templates => [:lock, :unlock] }, :resource_type => 'JobTemplate'
135
+ permission :create_job_invocations, { :job_invocations => [:new, :create, :legacy_create, :refresh, :rerun, :preview_hosts],
136
+ 'api/v2/job_invocations' => [:create, :rerun] }, :resource_type => 'JobInvocation'
137
+ permission :view_job_invocations, { :job_invocations => [:index, :chart, :show, :auto_complete_search, :preview_job_invocations_per_host, :list_jobs_hosts], :template_invocations => [:show, :show_template_invocation_by_host],
138
+ 'api/v2/job_invocations' => [:index, :show, :output, :raw_output, :outputs, :hosts] }, :resource_type => 'JobInvocation'
139
+ permission :view_template_invocations, { :template_invocations => [:show, :template_invocation_preview, :show_template_invocation_by_host], :job_invocations => [:list_jobs_hosts],
140
+ 'api/v2/template_invocations' => [:template_invocations], :ui_job_wizard => [:job_invocation] }, :resource_type => 'TemplateInvocation'
141
+ permission :create_template_invocations, {}, :resource_type => 'TemplateInvocation'
142
+ permission :execute_jobs_on_infrastructure_hosts, {}, :resource_type => 'JobInvocation'
143
+ permission :cancel_job_invocations, { :job_invocations => [:cancel], 'api/v2/job_invocations' => [:cancel] }, :resource_type => 'JobInvocation'
144
+ # this permissions grants user to get auto completion hints when setting up filters
145
+ permission :filter_autocompletion_for_template_invocation, { :template_invocations => [:auto_complete_search, :index] },
146
+ :resource_type => 'TemplateInvocation'
147
+ permission :cockpit_hosts, { 'cockpit' => [:redirect, :host_ssh_params] }, :resource_type => 'Host'
148
+ end
149
+
150
+ user_permissions = [
151
+ :view_job_templates,
152
+ :view_job_invocations,
153
+ :create_job_invocations,
154
+ :create_template_invocations,
155
+ :view_hosts,
156
+ :view_smart_proxies,
157
+ :view_remote_execution_features,
158
+ ].freeze
159
+ manager_permissions = user_permissions + [
160
+ :cancel_job_invocations,
161
+ :destroy_job_templates,
162
+ :edit_job_templates,
163
+ :create_job_templates,
164
+ :lock_job_templates,
165
+ :view_audit_logs,
166
+ :filter_autocompletion_for_template_invocation,
167
+ :edit_remote_execution_features,
168
+ ]
169
+
170
+ # Add a new role called 'Remote Execution User ' if it doesn't exist
171
+ role 'Remote Execution User', user_permissions, 'Role with permissions to run remote execution jobs against hosts'
172
+ role 'Remote Execution Manager', manager_permissions, 'Role with permissions to manage job templates, remote execution features, cancel jobs and view audit logs'
173
+
174
+ add_all_permissions_to_default_roles(except: [:execute_jobs_on_infrastructure_hosts])
175
+ add_permissions_to_default_roles({
176
+ Role::MANAGER => [:execute_jobs_on_infrastructure_hosts],
177
+ Role::SITE_MANAGER => user_permissions + [:execute_jobs_on_infrastructure_hosts],
178
+ })
179
+
180
+ # add menu entry
181
+ menu :top_menu, :job_templates,
182
+ url_hash: { controller: :job_templates, action: :index },
183
+ caption: N_('Job Templates'),
184
+ parent: :hosts_menu,
185
+ after: :provisioning_templates
186
+ menu :admin_menu, :remote_execution_features,
187
+ url_hash: { controller: :remote_execution_features, action: :index },
188
+ caption: N_('Remote Execution Features'),
189
+ parent: :administer_menu,
190
+ after: :bookmarks
191
+
192
+ menu :top_menu, :job_invocations,
193
+ url_hash: { controller: :job_invocations, action: :index },
194
+ caption: N_('Jobs'),
195
+ parent: :monitor_menu,
196
+ after: :audits
197
+
198
+ menu :labs_menu, :job_invocations_detail,
199
+ url_hash: { controller: :job_invocations, action: :show },
200
+ caption: N_('Job invocations detail'),
201
+ parent: :lab_features_menu,
202
+ url: '/experimental/job_invocations_detail/1'
203
+
204
+ register_custom_status HostStatus::ExecutionStatus
205
+ # add dashboard widget
206
+ # widget 'foreman_remote_execution_widget', name: N_('Foreman plugin template widget'), sizex: 4, sizey: 1
207
+ widget 'dashboard/latest-jobs', :name => N_('Latest Jobs'), :sizex => 6, :sizey => 1
208
+
209
+ parameter_filter Subnet, :remote_execution_proxies, :remote_execution_proxy_ids => []
210
+ parameter_filter Nic::Interface do |ctx|
211
+ ctx.permit :execution
212
+ end
213
+
214
+ register_graphql_query_field :job_invocations, '::Types::JobInvocation', :collection_field
215
+ register_graphql_query_field :job_invocation, '::Types::JobInvocation', :record_field
216
+
217
+ register_graphql_mutation_field :create_job_invocation, ::Mutations::JobInvocations::Create
218
+
219
+ extend_template_helpers ForemanRemoteExecution::RendererMethods
220
+
221
+ extend_rabl_template 'api/v2/smart_proxies/main', 'api/v2/smart_proxies/pubkey'
222
+ extend_rabl_template 'api/v2/interfaces/main', 'api/v2/interfaces/execution_flag'
223
+ extend_rabl_template 'api/v2/subnets/show', 'api/v2/subnets/remote_execution_proxies'
224
+ extend_rabl_template 'api/v2/hosts/main', 'api/v2/host/main'
225
+ parameter_filter ::Subnet, :remote_execution_proxy_ids
226
+
227
+ describe_host do
228
+ multiple_actions_provider :rex_hosts_multiple_actions
229
+ overview_buttons_provider :rex_host_overview_buttons
230
+ end
231
+
232
+ # Extend Registration module
233
+ extend_allowed_registration_vars :remote_execution_interface
234
+ extend_allowed_registration_vars :setup_remote_execution_pull
235
+ ForemanTasks.dynflow.eager_load_actions!
236
+ extend_observable_events(
237
+ ::Dynflow::Action.descendants.select do |klass|
238
+ klass <= ::Actions::ObservableAction
239
+ end.map(&:namespaced_event_names) +
240
+ RemoteExecutionFeature.all.pluck(:label).flat_map do |label|
241
+ [::Actions::RemoteExecution::RunHostJob, ::Actions::RemoteExecution::RunHostsJob].map do |klass|
242
+ klass.feature_job_event_names(label)
243
+ end
244
+ end
245
+ )
246
+ end
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '16.0.4'.freeze
2
+ VERSION = '16.0.5'.freeze
3
3
  end
@@ -91,7 +91,7 @@ module Api
91
91
  end
92
92
 
93
93
  test 'should create with schedule' do
94
- @attrs[:scheduling] = { start_at: Time.now.to_s }
94
+ @attrs[:scheduling] = { start_at: (Time.now + 1.hour).to_s }
95
95
  post :create, params: { job_invocation: @attrs }
96
96
  invocation = ActiveSupport::JSON.decode(@response.body)
97
97
  assert_equal invocation['mode'], 'future'