foreman_remote_execution 4.6.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby_ci.yml +7 -0
  3. data/app/controllers/job_invocations_controller.rb +1 -1
  4. data/app/controllers/ui_job_wizard_controller.rb +7 -0
  5. data/app/graphql/types/job_invocation.rb +16 -0
  6. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +5 -1
  7. data/app/helpers/remote_execution_helper.rb +9 -3
  8. data/app/lib/actions/remote_execution/run_host_job.rb +5 -1
  9. data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
  10. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +2 -0
  11. data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +6 -0
  12. data/app/models/host_proxy_invocation.rb +4 -0
  13. data/app/models/host_status/execution_status.rb +3 -3
  14. data/app/models/job_invocation.rb +9 -6
  15. data/app/models/job_invocation_composer.rb +4 -4
  16. data/app/models/job_template.rb +1 -1
  17. data/app/models/remote_execution_feature.rb +5 -1
  18. data/app/models/setting/remote_execution.rb +2 -2
  19. data/app/models/targeting.rb +5 -1
  20. data/app/views/job_invocations/index.html.erb +1 -1
  21. data/app/views/templates/ssh/module_action.erb +1 -0
  22. data/app/views/templates/ssh/power_action.erb +2 -0
  23. data/app/views/templates/ssh/puppet_run_once.erb +1 -0
  24. data/db/migrate/2021051713291621250977_add_host_proxy_invocations.rb +12 -0
  25. data/foreman_remote_execution.gemspec +2 -3
  26. data/lib/foreman_remote_execution/engine.rb +3 -2
  27. data/lib/foreman_remote_execution/version.rb +1 -1
  28. data/test/graphql/queries/job_invocation_query_test.rb +31 -0
  29. data/test/graphql/queries/job_invocations_query_test.rb +35 -0
  30. data/test/unit/concerns/host_extensions_test.rb +4 -4
  31. data/test/unit/input_template_renderer_test.rb +1 -89
  32. data/test/unit/job_invocation_composer_test.rb +15 -13
  33. data/test/unit/job_invocation_test.rb +1 -1
  34. data/webpack/JobWizard/JobWizard.js +28 -8
  35. data/webpack/JobWizard/JobWizard.scss +39 -0
  36. data/webpack/JobWizard/JobWizardConstants.js +10 -0
  37. data/webpack/JobWizard/JobWizardSelectors.js +9 -0
  38. data/webpack/JobWizard/__tests__/fixtures.js +104 -2
  39. data/webpack/JobWizard/__tests__/integration.test.js +13 -85
  40. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +21 -4
  41. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +67 -0
  42. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +73 -59
  43. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +135 -16
  44. data/webpack/JobWizard/steps/AdvancedFields/__tests__/DescriptionField.test.js +23 -0
  45. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +122 -51
  46. data/webpack/JobWizard/steps/Schedule/QueryType.js +48 -0
  47. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +61 -0
  48. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +25 -0
  49. data/webpack/JobWizard/steps/Schedule/StartEndDates.js +51 -0
  50. data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +22 -0
  51. data/webpack/JobWizard/steps/Schedule/index.js +41 -0
  52. data/webpack/JobWizard/steps/form/FormHelpers.js +1 -0
  53. data/webpack/JobWizard/steps/form/Formatter.js +149 -0
  54. data/webpack/JobWizard/steps/form/NumberInput.js +33 -0
  55. data/webpack/JobWizard/steps/form/SelectField.js +14 -2
  56. data/webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example +76 -0
  57. data/webpack/__mocks__/foremanReact/components/SearchBar.js +18 -1
  58. data/webpack/react_app/components/RecentJobsCard/JobStatusIcon.js +43 -0
  59. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +72 -66
  60. data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +98 -0
  61. data/webpack/react_app/components/RecentJobsCard/constants.js +11 -0
  62. data/webpack/react_app/components/RecentJobsCard/styles.scss +11 -0
  63. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +1 -0
  64. data/webpack/react_app/extend/fillRecentJobsCard.js +1 -1
  65. metadata +25 -16
  66. data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +0 -70
  67. data/test/models/orchestration/ssh_test.rb +0 -56
  68. data/webpack/JobWizard/__tests__/JobWizard.test.js +0 -13
  69. data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +0 -32
  70. data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +0 -249
  71. data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +0 -113
  72. data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +0 -38
  73. data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +0 -23
  74. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +0 -37
  75. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +0 -23
  76. data/webpack/react_app/components/RecentJobsCard/styles.css +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14dc89216ec220750d38149b86e0ecded26e13d99678505302a5a157b0c7c9e2
4
- data.tar.gz: b2091af78be3ed0fec0d5acea056a49e601e6d1ef96954c49976fd1c0da39ecb
3
+ metadata.gz: 742978171c8d62de9fdf9e14b2be742235dc1cce90c0c522871d65a90ee1f612
4
+ data.tar.gz: caae67492773457e26461ae6e39addec2cc1b105bf387a9cf0dbfc667ad25102
5
5
  SHA512:
6
- metadata.gz: 10d901fec16519db44d05d9b9ecb2b15923e1a2e439f1e0032778b9272ed4c48a446436b4ef7375bb5113f8067d5596035b5a7fa593a522fc37e56a472d51c31
7
- data.tar.gz: cb7686bf72b55bf65bbd35cee82910925f12b9dd29ec573dc96bb340fb1cc629833a80239e96317dcef2163d17d00ba93db92f5f50a10c5a4f4363d77647f729
6
+ metadata.gz: e40d5600dbe09f3ea875179a3ac44a4046ffd8615efe5c88f364828e7bd21b24d2d2a7f5f8ea09954f2f00056bc6d867efc22f7b82b0189de766f225101ae896
7
+ data.tar.gz: 6875df7248f14be5a915f7b3001cd6d4a50476f84824b0118747d4ba7b2993b977cf85cfe5f9cdde8706b2d2cb4fea20c1770988405adebf09683cc966ba9e70
@@ -71,3 +71,10 @@ jobs:
71
71
  run: |
72
72
  bundle exec rake test:foreman_remote_execution
73
73
  bundle exec rake test TEST="test/unit/foreman/access_permissions_test.rb"
74
+ - name: 'Upload logs'
75
+ uses: actions/upload-artifact@v2
76
+ if: failure()
77
+ with:
78
+ name: logs
79
+ path: log/*.log
80
+ retention-days: 5
@@ -67,7 +67,7 @@ class JobInvocationsController < ApplicationController
67
67
  end
68
68
 
69
69
  def index
70
- @job_invocations = resource_base_search_and_page.with_task.order('job_invocations.id DESC')
70
+ @job_invocations = resource_base_search_and_page.preload(:task, :targeting).order('job_invocations.id DESC')
71
71
  end
72
72
 
73
73
  # refreshes the form
@@ -10,9 +10,12 @@ class UiJobWizardController < ::Api::V2::BaseController
10
10
 
11
11
  def template
12
12
  job_template = JobTemplate.authorized.find(params[:id])
13
+ advanced_template_inputs, template_inputs = map_template_inputs(job_template.template_inputs_with_foreign).partition { |x| x["advanced"] }
13
14
  render :json => {
14
15
  :job_template => job_template,
15
16
  :effective_user => job_template.effective_user,
17
+ :template_inputs => template_inputs,
18
+ :advanced_template_inputs => advanced_template_inputs,
16
19
  }
17
20
  end
18
21
 
@@ -20,6 +23,10 @@ class UiJobWizardController < ::Api::V2::BaseController
20
23
  nested_resource || 'job_template'
21
24
  end
22
25
 
26
+ def map_template_inputs(template_inputs_with_foreign)
27
+ template_inputs_with_foreign.map { |input| input.attributes.merge({:resource_type => input.resource_type&.tableize }) }
28
+ end
29
+
23
30
  def resource_class
24
31
  JobTemplate
25
32
  end
@@ -0,0 +1,16 @@
1
+ module Types
2
+ class JobInvocation < BaseObject
3
+ description 'A Job Invocation'
4
+
5
+ global_id_field :id
6
+ field :job_category, String
7
+ field :description, String
8
+ field :time_span, Integer
9
+ field :start_at, GraphQL::Types::ISO8601DateTime
10
+ field :status_label, String
11
+
12
+ belongs_to :triggering, Types::Triggering
13
+ belongs_to :task, Types::Task
14
+ field :recurring_logic, Types::RecurringLogic
15
+ end
16
+ end
@@ -7,7 +7,9 @@ module ForemanRemoteExecution
7
7
  end
8
8
 
9
9
  def multiple_actions
10
- super + [ [_('Schedule Remote Job'), new_job_invocation_path, false] ]
10
+ res = super
11
+ res += [ [_('Schedule Remote Job'), new_job_invocation_path, false] ] if authorized_for(controller: :job_invocations, action: :new)
12
+ res
11
13
  end
12
14
 
13
15
  def schedule_job_multi_button(*args)
@@ -21,12 +23,14 @@ module ForemanRemoteExecution
21
23
  end
22
24
 
23
25
  def rex_host_features(*args)
26
+ return unless authorized_for(controller: :job_invocations, action: :create)
24
27
  RemoteExecutionFeature.with_host_action_button.order(:label).map do |feature|
25
28
  link_to(_('%s') % feature.name, job_invocations_path(:host_ids => [args.first.id], :feature => feature.label), :method => :post)
26
29
  end
27
30
  end
28
31
 
29
32
  def schedule_job_button(*args)
33
+ return unless authorized_for(controller: :job_invocations, action: :new)
30
34
  link_to(_('Schedule Remote Job'), new_job_invocation_path(:host_ids => [args.first.id]), :id => :run_button, :class => 'btn btn-default')
31
35
  end
32
36
 
@@ -7,6 +7,10 @@ module RemoteExecutionHelper
7
7
  @job_hosts_authorizer ||= Authorizer.new(User.current, :collection => @hosts)
8
8
  end
9
9
 
10
+ def host_tasks_authorizer
11
+ @host_tasks_authorizer ||= Authorizer.new(User.current, :collection => @job_invocation.sub_tasks)
12
+ end
13
+
10
14
  def host_counter(label, count)
11
15
  content_tag(:div, :class => 'host_counter') do
12
16
  content_tag(:div, label, :class => 'header') + content_tag(:div, count.to_s, :class => 'count')
@@ -36,7 +40,7 @@ module RemoteExecutionHelper
36
40
  'data-method': 'get', id: "#{host.name}-actions-rerun" } }
37
41
  end
38
42
 
39
- if host_task.present? && authorized_for(hash_for_foreman_tasks_task_path(host_task).merge(auth_object: host_task, permission: :view_foreman_tasks))
43
+ if host_task.present? && authorized_for(hash_for_foreman_tasks_task_path(host_task).merge(auth_object: host_task, permission: :view_foreman_tasks, authorizer: host_tasks_authorizer))
40
44
  links << { title: _('Host task'),
41
45
  action: { href: foreman_tasks_task_path(host_task),
42
46
  'data-method': 'get', id: "#{host.name}-actions-task" } }
@@ -109,12 +113,14 @@ module RemoteExecutionHelper
109
113
  :class => 'btn btn-danger',
110
114
  :title => _('Try to cancel the job on a host'),
111
115
  :disabled => !task.cancellable?,
112
- :method => :post)
116
+ :method => :post,
117
+ :remote => true)
113
118
  buttons << link_to(_('Abort Job'), abort_foreman_tasks_task_path(task),
114
119
  :class => 'btn btn-danger',
115
120
  :title => _('Try to abort the job on a host without waiting for its result'),
116
121
  :disabled => !task.cancellable?,
117
- :method => :post)
122
+ :method => :post,
123
+ :remote => true)
118
124
  end
119
125
  buttons
120
126
  end
@@ -47,12 +47,16 @@ module Actions
47
47
  script = renderer.render
48
48
  raise _('Failed rendering template: %s') % renderer.error_message unless script
49
49
 
50
+ first_execution = host.executed_through_proxies.where(:id => proxy.id).none?
51
+ host.executed_through_proxies << proxy if first_execution
52
+
50
53
  additional_options = { :hostname => provider.find_ip_or_hostname(host),
51
54
  :script => script,
52
55
  :execution_timeout_interval => job_invocation.execution_timeout_interval,
53
56
  :secrets => secrets(host, job_invocation, provider),
54
57
  :use_batch_triggering => true,
55
- :use_concurrency_control => options[:use_concurrency_control]}
58
+ :use_concurrency_control => options[:use_concurrency_control],
59
+ :first_execution => first_execution }
56
60
  action_options = provider.proxy_command_options(template_invocation, host)
57
61
  .merge(additional_options)
58
62
 
@@ -72,7 +72,7 @@ module Actions
72
72
 
73
73
  def total_count
74
74
  # For compatibility with already existing tasks
75
- return output[:total_count] unless output.has_key?(:host_count) || task.pending?
75
+ return output[:total_count] || hosts.count unless output.has_key?(:host_count) || task.pending?
76
76
 
77
77
  output[:host_count] || hosts.count
78
78
  end
@@ -6,6 +6,8 @@ module ForemanRemoteExecution
6
6
  has_many :template_invocations, :dependent => :destroy, :foreign_key => 'host_id'
7
7
  has_one :execution_status_object, :class_name => 'HostStatus::ExecutionStatus', :foreign_key => 'host_id', :dependent => :destroy
8
8
  has_many :run_host_job_tasks, :through => :template_invocations
9
+ has_many :host_proxy_invocations, :foreign_key => 'host_id', :dependent => :destroy
10
+ has_many :executed_through_proxies, :through => :host_proxy_invocations, :source => 'smart_proxy'
9
11
 
10
12
  scoped_search :relation => :run_host_job_tasks, :on => :result, :rename => 'job_invocation.result',
11
13
  :ext_method => :search_by_job_invocation,
@@ -1,5 +1,11 @@
1
1
  module ForemanRemoteExecution
2
2
  module SmartProxyExtensions
3
+ def self.prepended(base)
4
+ base.instance_eval do
5
+ has_many :host_proxy_invocations, :dependent => :destroy
6
+ end
7
+ end
8
+
3
9
  def pubkey
4
10
  self[:pubkey] || update_pubkey
5
11
  end
@@ -0,0 +1,4 @@
1
+ class HostProxyInvocation < ApplicationRecord
2
+ belongs_to :host, :class_name => 'Host::Managed', :inverse_of => :host_proxy_invocations
3
+ belongs_to :smart_proxy
4
+ end
@@ -64,11 +64,11 @@ class HostStatus::ExecutionStatus < HostStatus::Status
64
64
 
65
65
  case status
66
66
  when OK
67
- [ "foreman_tasks_tasks.state = 'stopped' AND result = 'success'" ]
67
+ [ "foreman_tasks_tasks.state = 'stopped' AND foreman_tasks_tasks.result = 'success'" ]
68
68
  when CANCELLED
69
- [ "foreman_tasks_tasks.state = 'stopped' AND result = 'cancelled'" ]
69
+ [ "foreman_tasks_tasks.state = 'stopped' AND foreman_tasks_tasks.result = 'cancelled'" ]
70
70
  when ERROR
71
- [ "foreman_tasks_tasks.state = 'stopped' AND (result = 'error' OR result = 'warning')" ]
71
+ [ "foreman_tasks_tasks.state = 'stopped' AND (foreman_tasks_tasks.result = 'error' OR foreman_tasks_tasks.result = 'warning')" ]
72
72
  when QUEUED
73
73
  [ "foreman_tasks_tasks.state = 'scheduled' OR foreman_tasks_tasks.state IS NULL" ]
74
74
  when RUNNING
@@ -65,8 +65,6 @@ class JobInvocation < ApplicationRecord
65
65
  scoped_search :on => 'pattern_template_name', :rename => 'pattern_template_name', :operators => ['= '],
66
66
  :complete_value => false, :only_explicit => true, :ext_method => :search_by_pattern_template
67
67
 
68
- scope :with_task, -> { references(:task) }
69
-
70
68
  scoped_search :relation => :recurring_logic, :on => 'id', :rename => 'recurring_logic.id'
71
69
 
72
70
  scoped_search :relation => :recurring_logic, :on => 'id', :rename => 'recurring',
@@ -99,7 +97,7 @@ class JobInvocation < ApplicationRecord
99
97
  def self.search_by_status(key, operator, value)
100
98
  conditions = HostStatus::ExecutionStatus::ExecutionTaskStatusMapper.sql_conditions_for(value)
101
99
  conditions[0] = "NOT (#{conditions[0]})" if operator == '<>'
102
- { :conditions => sanitize_sql_for_conditions(conditions), :include => :task }
100
+ { :conditions => sanitize_sql_for_conditions(conditions), :joins => :task }
103
101
  end
104
102
 
105
103
  def self.search_by_recurring_logic(key, operator, value)
@@ -193,11 +191,16 @@ class JobInvocation < ApplicationRecord
193
191
  end
194
192
 
195
193
  def total_hosts_count
194
+ count = _('N/A')
195
+
196
196
  if targeting.resolved?
197
- task&.main_action&.total_count || targeting.hosts.count
198
- else
199
- _('N/A')
197
+ count = if task&.main_action.respond_to?(:total_count)
198
+ task.main_action.total_count
199
+ else
200
+ targeting.hosts.count
201
+ end
200
202
  end
203
+ count
201
204
  end
202
205
 
203
206
  def pattern_template_invocation_for_host(host)
@@ -209,7 +209,7 @@ class JobInvocationComposer
209
209
  def format_datetime(datetime)
210
210
  return datetime if datetime.blank?
211
211
 
212
- Time.parse(datetime).strftime('%Y-%m-%d %H:%M')
212
+ Time.parse(datetime).utc.strftime('%Y-%m-%d %H:%M')
213
213
  end
214
214
  end
215
215
 
@@ -296,7 +296,7 @@ class JobInvocationComposer
296
296
  attr_reader :feature_label, :feature, :provided_inputs
297
297
 
298
298
  def initialize(feature_label, hosts, provided_inputs = {})
299
- @feature = RemoteExecutionFeature.feature(feature_label)
299
+ @feature = RemoteExecutionFeature.feature!(feature_label)
300
300
  @provided_inputs = provided_inputs
301
301
  translator = HostIdsTranslator.new(hosts)
302
302
  @host_bookmark = translator.bookmark
@@ -405,7 +405,7 @@ class JobInvocationComposer
405
405
  job_invocation.effective_user_password = params[:effective_user_password]
406
406
 
407
407
  if @reruns && job_invocation.targeting.static?
408
- job_invocation.targeting.host_ids = JobInvocation.find(@reruns).targeting.host_ids
408
+ job_invocation.targeting.assign_host_ids(JobInvocation.find(@reruns).targeting.host_ids)
409
409
  job_invocation.targeting.mark_resolved!
410
410
  end
411
411
 
@@ -513,7 +513,7 @@ class JobInvocationComposer
513
513
  end
514
514
 
515
515
  def available_bookmarks
516
- Bookmark.authorized(:view_bookmarks).my_bookmarks.where(:controller => ['hosts', 'dashboard'])
516
+ Bookmark.my_bookmarks.where(:controller => ['hosts', 'dashboard'])
517
517
  end
518
518
 
519
519
  def targeted_hosts
@@ -83,7 +83,7 @@ class JobTemplate < ::Template
83
83
  end
84
84
 
85
85
  def acceptable_template_input_types
86
- [ :user, :fact, :variable, :puppet_parameter ]
86
+ [ :user, :fact, :variable ]
87
87
  end
88
88
 
89
89
  def default_render_scope_class
@@ -20,7 +20,11 @@ class RemoteExecutionFeature < ApplicationRecord
20
20
  end
21
21
 
22
22
  def self.feature(label)
23
- self.find_by(label: label) || raise(::Foreman::Exception.new(N_('Unknown remote execution feature %s'), label))
23
+ self.find_by(label: label)
24
+ end
25
+
26
+ def self.feature!(label)
27
+ feature(label) || raise(::Foreman::Exception.new(N_('Unknown remote execution feature %s'), label))
24
28
  end
25
29
 
26
30
  def self.register(label, name, options = {})
@@ -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
  ]
@@ -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?
@@ -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
  <%
@@ -13,6 +13,8 @@ template_inputs:
13
13
  required: true
14
14
  %>
15
15
 
16
+ PATH="$PATH:/usr/sbin:/sbin"
17
+
16
18
  echo <%= input('action') %> host && sleep 3
17
19
  <%= case input('action')
18
20
  when 'restart'
@@ -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
@@ -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
@@ -16,8 +16,7 @@ Gem::Specification.new do |s|
16
16
  'management functionality with remote management functionality.'
17
17
 
18
18
  s.files = `git ls-files`.split("\n").reject do |file|
19
- file.start_with?('scripts', 'lib/foreman_remote_execution_core') ||
20
- file == 'foreman_remote_execution_core.gemspec'
19
+ file.start_with?('scripts')
21
20
  end
22
21
 
23
22
  s.test_files = `git ls-files test`.split("\n")
@@ -25,7 +24,7 @@ Gem::Specification.new do |s|
25
24
 
26
25
  s.add_dependency 'deface'
27
26
  s.add_dependency 'dynflow', '>= 1.0.2', '< 2.0.0'
28
- s.add_dependency 'foreman-tasks', '>= 4.1.0'
27
+ s.add_dependency 'foreman-tasks', '>= 5.0.0'
29
28
 
30
29
  s.add_development_dependency 'factory_bot_rails', '~> 4.8.0'
31
30
  s.add_development_dependency 'rdoc'
@@ -152,6 +152,9 @@ module ForemanRemoteExecution
152
152
  ctx.permit :execution
153
153
  end
154
154
 
155
+ register_graphql_query_field :job_invocations, '::Types::JobInvocation', :collection_field
156
+ register_graphql_query_field :job_invocation, '::Types::JobInvocation', :record_field
157
+
155
158
  extend_template_helpers ForemanRemoteExecution::RendererMethods
156
159
 
157
160
  extend_rabl_template 'api/v2/smart_proxies/main', 'api/v2/smart_proxies/pubkey'
@@ -201,12 +204,10 @@ module ForemanRemoteExecution
201
204
 
202
205
  Host::Managed.prepend ForemanRemoteExecution::HostExtensions
203
206
  Host::Managed.include ForemanTasks::Concerns::HostActionSubject
204
- Host::Managed.include ForemanRemoteExecution::Orchestration::SSH
205
207
 
206
208
  (Nic::Base.descendants + [Nic::Base]).each do |klass|
207
209
  klass.send(:include, ForemanRemoteExecution::NicExtensions)
208
210
  end
209
- Nic::Managed.include ForemanRemoteExecution::Orchestration::SSH
210
211
 
211
212
  Bookmark.include ForemanRemoteExecution::BookmarkExtensions
212
213
  HostsHelper.prepend ForemanRemoteExecution::HostsHelperExtensions
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '4.6.0'.freeze
2
+ VERSION = '4.7.0'.freeze
3
3
  end