foreman_remote_execution 9.0.0 → 9.1.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/job_invocations_controller.rb +1 -0
  3. data/app/controllers/job_invocations_controller.rb +10 -0
  4. data/app/controllers/ui_job_wizard_controller.rb +6 -1
  5. data/app/helpers/remote_execution_helper.rb +1 -1
  6. data/app/lib/actions/remote_execution/run_hosts_job.rb +28 -2
  7. data/app/models/remote_execution_feature.rb +11 -8
  8. data/app/views/api/v2/job_invocations/base.json.rabl +1 -1
  9. data/app/views/job_invocations/show.html.erb +1 -1
  10. data/app/views/job_invocations/welcome.html.erb +1 -1
  11. data/config/routes.rb +1 -0
  12. data/db/migrate/20210816100932_rex_setting_category_to_dsl.rb +1 -1
  13. data/db/migrate/20220426145007_add_unique_feature_label_index.rb +14 -0
  14. data/lib/foreman_remote_execution/engine.rb +1 -1
  15. data/lib/foreman_remote_execution/version.rb +1 -1
  16. data/locale/action_names.rb +2 -2
  17. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  18. data/locale/de/foreman_remote_execution.po +266 -154
  19. data/locale/en/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  20. data/locale/en/foreman_remote_execution.po +132 -24
  21. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  22. data/locale/en_GB/foreman_remote_execution.po +149 -41
  23. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  24. data/locale/es/foreman_remote_execution.po +320 -210
  25. data/locale/foreman_remote_execution.pot +394 -211
  26. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  27. data/locale/fr/foreman_remote_execution.po +353 -241
  28. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  29. data/locale/ja/foreman_remote_execution.po +368 -261
  30. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  31. data/locale/ko/foreman_remote_execution.po +161 -53
  32. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  33. data/locale/pt_BR/foreman_remote_execution.po +335 -225
  34. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  35. data/locale/ru/foreman_remote_execution.po +161 -53
  36. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  37. data/locale/zh_CN/foreman_remote_execution.po +465 -359
  38. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  39. data/locale/zh_TW/foreman_remote_execution.po +162 -54
  40. data/package.json +6 -6
  41. data/webpack/JobWizard/JobWizard.js +97 -32
  42. data/webpack/JobWizard/StartsBeforeErrorAlert.js +17 -0
  43. data/webpack/JobWizard/__tests__/__snapshots__/integration.test.js.snap +8 -0
  44. data/webpack/JobWizard/__tests__/fixtures.js +5 -0
  45. data/webpack/JobWizard/__tests__/integration.test.js +15 -0
  46. data/webpack/JobWizard/__tests__/validation.test.js +27 -0
  47. data/webpack/JobWizard/autofill.js +1 -0
  48. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +29 -10
  49. data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +8 -0
  50. data/webpack/JobWizard/steps/HostsAndInputs/HostPreviewModal.js +3 -0
  51. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js +38 -1
  52. data/webpack/JobWizard/steps/HostsAndInputs/buildHostQuery.js +16 -10
  53. data/webpack/JobWizard/steps/HostsAndInputs/index.js +51 -3
  54. data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +33 -13
  55. data/webpack/JobWizard/steps/form/DateTimePicker.js +1 -1
  56. data/webpack/JobWizard/submit.js +14 -3
  57. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4f0a9c455ec484caac7631cec3d1ed8eff22263c96036d7837fdbb86f3faab8
4
- data.tar.gz: a73788ec230b20cfd6050733d40f27a59d7bf26d334ce51f0b422aae1a64a68e
3
+ metadata.gz: 81407b69460f3a75ba7c4c49d66c499af7075afd1546222ff2e02c56bc4e459e
4
+ data.tar.gz: c3b6c06eb6ba6a44d1e827e5a3507787a974264c30e58d93170d5d66e4eaa3b2
5
5
  SHA512:
6
- metadata.gz: cb1ef923190e046bc4f9c688ac1040f26e521e7a96a7a154fd461a650d25b04875572e26b75f57dfb425401ae2bf8e82447eb01c635006eb9b51b36df168b999
7
- data.tar.gz: 3e47f08ded8554ff2b38c50f7d16b8705441ece2753df227181d7782426c7c320476220f5b12dee496216cda119467ff3a0348f7821811dda702e8a9d852c1f3
6
+ metadata.gz: 23980086920902efd40d77912e472e0ebd9421c5429dfec561d96c4d7fdfc5cabdde3ff4a999b9ee50227c1163af1a4cffb676b939352d464ab5a6af29899027
7
+ data.tar.gz: 121f36e745fb79d7364cf42f9de7d875d5da1b1af91ef5138688241f8c520d9c14f0de3b8e584b6d50d0cb7ada113b0c3aa666cba5482214fee978d522c87fe4
@@ -71,6 +71,7 @@ module Api
71
71
  param :description_format, String, :required => false, :desc => N_('Override the description format from the template for this invocation only')
72
72
  param :execution_timeout_interval, Integer, :required => false, :desc => N_('Override the timeout interval from the template for this invocation only')
73
73
  param :feature, String, :required => false, :desc => N_('Remote execution feature label that should be triggered, job template assigned to this feature will be used')
74
+ param :time_to_pickup, Integer, :required => false, :desc => N_('Override the global time to pickup interval for this invocation only')
74
75
 
75
76
  RemoteExecutionProvider.providers.each_value do |provider|
76
77
  next if !provider.respond_to?(:provider_inputs_doc) || provider.provider_inputs_doc.empty?
@@ -40,6 +40,16 @@ class JobInvocationsController < ApplicationController
40
40
  render :action => 'new'
41
41
  end
42
42
 
43
+ def legacy_create
44
+ @composer = prepare_composer
45
+ if @composer.trigger
46
+ redirect_to job_invocation_path(@composer.job_invocation)
47
+ else
48
+ @composer.job_invocation.description_format = nil if params.fetch(:job_invocation, {}).key?(:description_override)
49
+ render :action => 'new'
50
+ end
51
+ end
52
+
43
53
  def create
44
54
  @composer = prepare_composer
45
55
  if @composer.trigger
@@ -13,11 +13,13 @@ class UiJobWizardController < ApplicationController
13
13
  def template
14
14
  job_template = JobTemplate.authorized.find(params[:id])
15
15
  advanced_template_inputs, template_inputs = map_template_inputs(job_template.template_inputs_with_foreign).partition { |x| x["advanced"] }
16
+ provider_inputs = job_template.provider.provider_inputs.map { |input| input.instance_values.merge({:provider_input => true, default: input.value }) }
16
17
  render :json => {
17
18
  :job_template => job_template,
18
19
  :effective_user => job_template.effective_user,
19
20
  :template_inputs => template_inputs,
20
- :advanced_template_inputs => advanced_template_inputs,
21
+ :provider_name => job_template.provider.provider_input_namespace,
22
+ :advanced_template_inputs => advanced_template_inputs+provider_inputs,
21
23
  }
22
24
  end
23
25
 
@@ -66,6 +68,9 @@ class UiJobWizardController < ApplicationController
66
68
  job_organization = Taxonomy.find_by(id: job.task.input[:current_organization_id])
67
69
  job_location = Taxonomy.find_by(id: job.task.input[:current_location_id])
68
70
  render :json => {
71
+ :provider_input_values => composer[:template_invocations][0][:provider_input_values],
72
+ :provider_input_values1 => job[:provider_input_values],
73
+ :job2 => composer[:template_invocations][0],
69
74
  :job => composer,
70
75
  :job_organization => job_organization,
71
76
  :job_location => job_location,
@@ -238,7 +238,7 @@ module RemoteExecutionHelper
238
238
 
239
239
  def load_template_from_task(template_invocation, target)
240
240
  task = template_invocation.job_invocation.sub_task_for_host(target)
241
- return if task.nil?
241
+ return if [nil, 'scheduled', 'planning'].include?(task&.state)
242
242
 
243
243
  task.execution_plan.actions[1].try(:input).try(:[], 'script')
244
244
  end
@@ -5,6 +5,7 @@ module Actions
5
5
  include Dynflow::Action::WithBulkSubPlans
6
6
  include Dynflow::Action::WithPollingSubPlans
7
7
  include Actions::RecurringAction
8
+ include Actions::ObservableAction
8
9
 
9
10
  middleware.use Actions::Middleware::BindJobInvocation
10
11
  middleware.use Actions::Middleware::RecurringLogic
@@ -12,6 +13,7 @@ module Actions
12
13
 
13
14
  execution_plan_hooks.use :notify_on_success, :on => :success
14
15
  execution_plan_hooks.use :notify_on_failure, :on => :failure
16
+ execution_plan_hooks.use :emit_event_running, :on => :running
15
17
 
16
18
  class CheckOnProxyActions; end
17
19
 
@@ -94,9 +96,12 @@ module Actions
94
96
  end
95
97
  end
96
98
 
99
+ def job_invocation_id
100
+ input[:job_invocation_id] || input.fetch(:job_invocation, {})[:id]
101
+ end
102
+
97
103
  def job_invocation
98
- id = input[:job_invocation_id] || input.fetch(:job_invocation, {})[:id]
99
- @job_invocation ||= JobInvocation.find(id)
104
+ @job_invocation ||= JobInvocation.find(job_invocation_id)
100
105
  end
101
106
 
102
107
  def batch(from, size)
@@ -152,6 +157,14 @@ module Actions
152
157
  input[:proxy_batch_size]
153
158
  end
154
159
 
160
+ def self.event_names
161
+ super + [event_name_base + '_' + event_name_suffix('running')]
162
+ end
163
+
164
+ def emit_event_running(plan)
165
+ emit_event(plan, :running)
166
+ end
167
+
155
168
  private
156
169
 
157
170
  def mail_notification_preference
@@ -163,6 +176,19 @@ module Actions
163
176
 
164
177
  /\A#{JobInvocation::CACHE_PREFIX}_#{job_invocation_id}/
165
178
  end
179
+
180
+ extend ApipieDSL::Class
181
+ apipie :class, "An action representing execution of a job against a set of hosts" do
182
+ name 'Actions::RemoteExecution::RunHostsJob'
183
+ refs 'Actions::RemoteExecution::RunHostsJob'
184
+ sections only: %w[all webhooks]
185
+ property :task, object_of: 'Task', desc: 'Returns the task to which this action belongs'
186
+ property :job_invocation_id, Integer, desc: "Returns the id of the job invocation"
187
+ property :job_invocation, object_of: 'JobInvocation', desc: "Returns the job invocation"
188
+ end
189
+ class Jail < ::Actions::ObservableAction::Jail
190
+ allow :job_invocation_id, :job_invocation
191
+ end
166
192
  end
167
193
  end
168
194
  end
@@ -43,8 +43,12 @@ class RemoteExecutionFeature < ApplicationRecord
43
43
  feature = self.find_by(label: label)
44
44
  builder = options[:notification_builder] ? options[:notification_builder].to_s : nil
45
45
 
46
+ if options[:provided_inputs]
47
+ provided_inputs = Array(options[:provided_inputs]).join(',')
48
+ end
49
+
46
50
  attributes = { :name => name,
47
- :provided_input_names => options[:provided_inputs],
51
+ :provided_inputs => provided_inputs,
48
52
  :description => options[:description],
49
53
  :host_action_button => options[:host_action_button],
50
54
  :proxy_selector_override => options[:proxy_selector_override],
@@ -58,13 +62,12 @@ class RemoteExecutionFeature < ApplicationRecord
58
62
  end
59
63
 
60
64
  self.without_auditing do
61
- if feature.nil?
62
- feature = self.create!({ :label => label }.merge(attributes))
63
- else
64
- feature.attributes = attributes
65
- feature.save if feature.changed?
66
- end
67
- return feature
65
+ # The only validation we currently have is uniqueness validation, which
66
+ # the upsert will enforce
67
+ # rubocop:disable Rails/SkipsModelValidations
68
+ result = self.upsert({ label: label }.merge(attributes), unique_by: :label)
69
+ self.find(result.first.to_h['id'])
70
+ # rubocop:enable Rails/SkipsModelValidations
68
71
  end
69
72
  end
70
73
  end
@@ -1,6 +1,6 @@
1
1
  object @job_invocation
2
2
 
3
- attributes :id, :description, :job_category, :targeting_id, :status, :start_at, :status_label, :ssh_user
3
+ attributes :id, :description, :job_category, :targeting_id, :status, :start_at, :status_label, :ssh_user, :time_to_pickup
4
4
 
5
5
  node do |invocation|
6
6
  {
@@ -1,6 +1,6 @@
1
1
  <% title @job_invocation.description %>
2
2
  <% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
3
- <% javascript 'charts', 'foreman_remote_execution/template_invocation' %>
3
+ <% javascript 'foreman_remote_execution/template_invocation' %>
4
4
  <% javascript *webpack_asset_paths('foreman_remote_execution', :extension => 'js') %>
5
5
  <% content_for(:stylesheets) do %>
6
6
  <%= webpacked_plugins_css_for :foreman_remote_execution %>
@@ -9,6 +9,6 @@
9
9
  <p><%= link_to _('Learn more about this in the documentation.'),
10
10
  documentation_url('1.ForemanRemoteExecution1.3Manual', :root_url => 'https://www.theforeman.org/plugins/foreman_remote_execution/1.3/index.html#'), :rel => 'external' %></p>
11
11
  <div class="blank-slate-pf-main-action">
12
- <%= new_link(_("Run Job"), {}, { :class => "btn-lg" }) %>
12
+ <%= display_link_if_authorized(_("Run Job"), { :action => :create }, { :class => "btn btn-primary btn-lg" }) %>
13
13
  </div>
14
14
  </div>
data/config/routes.rb CHANGED
@@ -18,6 +18,7 @@ Rails.application.routes.draw do
18
18
 
19
19
  match 'job_invocations/new', to: 'react#index', :via => [:get], as: 'new_job_invocation'
20
20
  match 'job_invocations/new', to: 'job_invocations#create', via: [:post], as: 'create_job_invocation'
21
+ match 'job_invocations/', to: 'job_invocations#legacy_create', via: [:post], as: 'legacy_create_job_invocation'
21
22
  match 'job_invocations/:id/rerun', to: 'react#index', :via => [:get], as: 'rerun_job_invocation'
22
23
  match 'old/job_invocations/new', to: 'job_invocations#new', via: [:get], as: 'form_new_job_invocation'
23
24
  match 'old/job_invocations/:id/rerun', to: 'job_invocations#rerun', via: [:get, :post], as: 'form_rerun_job_invocation'
@@ -1,5 +1,5 @@
1
1
  class RexSettingCategoryToDsl < ActiveRecord::Migration[6.0]
2
2
  def up
3
- Setting.where(category: 'Setting::RemoteExecution').update_all(category: 'Setting')
3
+ Setting.where(category: 'Setting::RemoteExecution').update_all(category: 'Setting') if column_exists?(:settings, :category)
4
4
  end
5
5
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddUniqueFeatureLabelIndex < ActiveRecord::Migration[6.0]
4
+ def change
5
+ remove_index :remote_execution_features, :label
6
+
7
+ counts = RemoteExecutionFeature.group(:label).count
8
+ counts.select { |_, count| count > 1 }.each do |label, count|
9
+ RemoteExecutionFeature.where(label: label).limit(count - 1).delete_all
10
+ end
11
+
12
+ add_index :remote_execution_features, :label, unique: true
13
+ end
14
+ end
@@ -181,7 +181,7 @@ module ForemanRemoteExecution
181
181
  permission :destroy_job_templates, { :job_templates => [:destroy],
182
182
  :'api/v2/job_templates' => [:destroy] }, :resource_type => 'JobTemplate'
183
183
  permission :lock_job_templates, { :job_templates => [:lock, :unlock] }, :resource_type => 'JobTemplate'
184
- permission :create_job_invocations, { :job_invocations => [:new, :create, :refresh, :rerun, :preview_hosts],
184
+ permission :create_job_invocations, { :job_invocations => [:new, :create, :legacy_create, :refresh, :rerun, :preview_hosts],
185
185
  'api/v2/job_invocations' => [:create, :rerun] }, :resource_type => 'JobInvocation'
186
186
  permission :view_job_invocations, { :job_invocations => [:index, :chart, :show, :auto_complete_search], :template_invocations => [:show],
187
187
  'api/v2/job_invocations' => [:index, :show, :output, :raw_output, :outputs] }, :resource_type => 'JobInvocation'
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '9.0.0'.freeze
2
+ VERSION = '9.1.0'.freeze
3
3
  end
@@ -1,5 +1,5 @@
1
1
  # Autogenerated!
2
- _("Remote action:")
2
+ _("Action with sub plans")
3
3
  _("Import Puppet classes")
4
4
  _("Import facts")
5
- _("Action with sub plans")
5
+ _("Remote action:")