foreman_remote_execution 0.1.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +0 -6
- data/app/assets/javascripts/template_input.js +5 -0
- data/app/assets/javascripts/template_invocation.js +44 -12
- data/app/controllers/api/v2/foreign_input_sets_controller.rb +80 -0
- data/app/controllers/api/v2/job_invocations_controller.rb +28 -14
- data/app/controllers/api/v2/job_templates_controller.rb +24 -20
- data/app/controllers/api/v2/template_inputs_controller.rb +10 -7
- data/app/controllers/job_invocations_controller.rb +18 -6
- data/app/controllers/job_templates_controller.rb +14 -4
- data/app/controllers/template_invocations_controller.rb +5 -3
- data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +1 -1
- data/app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb +19 -0
- data/app/helpers/remote_execution_helper.rb +88 -39
- data/app/lib/actions/remote_execution/run_host_job.rb +11 -8
- data/app/lib/actions/remote_execution/run_hosts_job.rb +5 -2
- data/app/lib/actions/remote_execution/run_proxy_command.rb +9 -4
- data/app/models/concerns/foreman_remote_execution/errors_flattener.rb +2 -2
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +2 -2
- data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +1 -1
- data/app/models/concerns/foreman_remote_execution/template_extensions.rb +9 -1
- data/app/models/foreign_input_set.rb +49 -0
- data/app/models/host_status/execution_status.rb +50 -5
- data/app/models/input_template_renderer.rb +52 -7
- data/app/models/job_invocation.rb +89 -32
- data/app/models/job_invocation_composer.rb +71 -55
- data/app/models/job_template.rb +43 -7
- data/app/models/remote_execution_provider.rb +1 -1
- data/app/models/setting/remote_execution.rb +7 -7
- data/app/models/ssh_execution_provider.rb +1 -1
- data/app/models/targeting.rb +1 -1
- data/app/models/template_invocation.rb +9 -4
- data/app/views/api/v2/foreign_input_sets/base.json.rabl +3 -0
- data/app/views/api/v2/foreign_input_sets/create.json.rabl +3 -0
- data/app/views/api/v2/foreign_input_sets/index.json.rabl +3 -0
- data/app/views/api/v2/foreign_input_sets/main.json.rabl +5 -0
- data/app/views/api/v2/foreign_input_sets/show.json.rabl +3 -0
- data/app/views/api/v2/job_invocations/base.json.rabl +10 -1
- data/app/views/api/v2/job_invocations/main.json.rabl +14 -1
- data/app/views/api/v2/job_templates/base.json.rabl +1 -1
- data/app/views/api/v2/job_templates/main.json.rabl +9 -1
- data/app/views/api/v2/job_templates/show.json.rabl +0 -10
- data/app/views/api/v2/template_inputs/main.json.rabl +2 -1
- data/app/views/job_invocation_task_groups/_job_invocation_task_group.html.erb +1 -1
- data/app/views/job_invocations/_description_fields.html.erb +4 -0
- data/app/views/job_invocations/_form.html.erb +73 -91
- data/app/views/job_invocations/_host_actions_td.html.erb +2 -2
- data/app/views/job_invocations/_host_name_td.html.erb +7 -0
- data/app/views/job_invocations/_tab_hosts.html.erb +6 -6
- data/app/views/job_invocations/_tab_overview.html.erb +3 -3
- data/app/views/job_invocations/index.html.erb +6 -4
- data/app/views/job_invocations/refresh.js.erb +1 -0
- data/app/views/job_invocations/show.html.erb +1 -1
- data/app/views/job_invocations/show.js.erb +6 -3
- data/app/views/job_templates/_custom_tabs.html.erb +24 -14
- data/app/views/job_templates/index.html.erb +3 -1
- data/app/views/template_inputs/_foreign_input_set_form.html.erb +12 -0
- data/app/views/template_inputs/_form.html.erb +11 -12
- data/app/views/template_invocations/show.html.erb +2 -2
- data/app/views/templates/package_action.erb +2 -2
- data/app/views/templates/puppet_run_once.erb +3 -3
- data/app/views/templates/run_command.erb +3 -3
- data/app/views/templates/service_action.erb +2 -2
- data/app/views/unattended/snippets/_remote_execution_ssh_keys.erb +1 -1
- data/config/routes.rb +5 -3
- data/db/migrate/20150616080015_create_template_input.rb +1 -1
- data/db/migrate/20150708133241_add_targeting.rb +7 -7
- data/db/migrate/20150708133242_add_invocation.rb +2 -2
- data/db/migrate/20150708133305_add_template_invocation.rb +6 -6
- data/db/migrate/20151215114631_add_host_id_to_template_invocation.rb +3 -3
- data/db/migrate/20151217092555_migrate_to_task_groups.rb +1 -1
- data/db/migrate/20160108134600_create_template_input_sets.rb +16 -0
- data/db/migrate/20160108141144_make_job_name_default_to_something.rb +9 -0
- data/db/migrate/20160111113032_upcase_ssh_feature.rb +19 -0
- data/db/migrate/20160113161916_add_run_host_job_task_id_to_template_invocation.rb +6 -0
- data/db/migrate/20160113162007_expand_all_template_invocations.rb +45 -0
- data/db/migrate/20160114120200_rename_job_categories.rb +20 -0
- data/db/migrate/20160114125628_rename_job_name_to_job_category.rb +19 -0
- data/db/seeds.d/60-ssh_proxy_feature.rb +1 -1
- data/db/seeds.d/80-provision_templates.rb +2 -2
- data/db/seeds.d/90-bookmarks.rb +19 -0
- data/doc/plugins/graphviz.rb +5 -5
- data/doc/plugins/plantuml.rb +6 -6
- data/doc/plugins/tags.rb +4 -4
- data/foreman_remote_execution.gemspec +3 -4
- data/lib/foreman_remote_execution/engine.rb +12 -9
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/factories/foreman_remote_execution_factories.rb +11 -9
- data/test/functional/api/v2/foreign_input_sets_controller_test.rb +63 -0
- data/test/functional/api/v2/job_invocations_controller_test.rb +45 -13
- data/test/functional/api/v2/job_templates_controller_test.rb +6 -6
- data/test/functional/api/v2/template_inputs_controller_test.rb +3 -3
- data/test/unit/actions/run_hosts_job_test.rb +3 -4
- data/test/unit/actions/run_proxy_command_test.rb +7 -7
- data/test/unit/concerns/host_extensions_test.rb +1 -1
- data/test/unit/execution_task_status_mapper_test.rb +93 -0
- data/test/unit/input_template_renderer_test.rb +182 -9
- data/test/unit/job_invocation_composer_test.rb +144 -168
- data/test/unit/job_invocation_test.rb +67 -15
- data/test/unit/job_template_effective_user_test.rb +2 -2
- data/test/unit/job_template_test.rb +36 -12
- data/test/unit/remote_execution_provider_test.rb +6 -6
- data/test/unit/targeting_test.rb +2 -2
- metadata +27 -21
- data/app/models/concerns/foreman_remote_execution/template_relations.rb +0 -10
- data/app/views/job_invocations/_host_provider_td.html.erb +0 -3
- data/app/views/job_templates/auto_complete_job_name.json.erb +0 -3
@@ -4,14 +4,24 @@ class JobInvocationsController < ApplicationController
|
|
4
4
|
before_filter :find_or_create_triggering, :only => [:create, :refresh]
|
5
5
|
|
6
6
|
def new
|
7
|
-
|
7
|
+
ui_params = {
|
8
8
|
:host_ids => params[:host_ids],
|
9
|
-
:job_invocation => {
|
10
|
-
},
|
11
9
|
:targeting => {
|
12
10
|
:targeting_type => Targeting::STATIC_TYPE,
|
13
11
|
:bookmark_id => params[:bookmark_id]
|
14
|
-
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
if (template = JobTemplate.find_by_id(params[:template_id]))
|
16
|
+
ui_params[:job_invocation] = {
|
17
|
+
:job_category => template.job_category,
|
18
|
+
:providers => {
|
19
|
+
template.provider_type => {:job_template_id => template.id}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
@composer = JobInvocationComposer.from_ui_params(ui_params)
|
15
25
|
end
|
16
26
|
|
17
27
|
def rerun
|
@@ -34,23 +44,25 @@ class JobInvocationsController < ApplicationController
|
|
34
44
|
@composer.triggering.trigger(::Actions::RemoteExecution::RunHostsJob, job_invocation)
|
35
45
|
redirect_to job_invocation_path(job_invocation)
|
36
46
|
else
|
47
|
+
@composer.job_invocation.description_format = nil if params[:job_invocation].key?(:description_override)
|
37
48
|
render :action => 'new'
|
38
49
|
end
|
39
50
|
end
|
40
51
|
|
41
52
|
def show
|
42
|
-
@job_invocation = resource_base.find(params[:id])
|
53
|
+
@job_invocation = resource_base.includes(:template_invocations => :run_host_job_task).find(params[:id])
|
43
54
|
@auto_refresh = @job_invocation.task.try(:pending?)
|
44
55
|
hosts_base = @job_invocation.targeting.hosts.authorized(:view_hosts, Host)
|
45
56
|
@hosts = hosts_base.search_for(params[:search], :order => params[:order] || 'name ASC').paginate(:page => params[:page])
|
46
57
|
end
|
47
58
|
|
48
59
|
def index
|
49
|
-
@job_invocations = resource_base.search_for(params[:search]).paginate(:page => params[:page]).with_task.order(
|
60
|
+
@job_invocations = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page]).with_task.order('job_invocations.id DESC')
|
50
61
|
end
|
51
62
|
|
52
63
|
# refreshes the form
|
53
64
|
def refresh
|
65
|
+
params[:job_invocation].delete :description_format if params[:job_invocation].key?(:description_override)
|
54
66
|
@composer = JobInvocationComposer.from_ui_params(params)
|
55
67
|
end
|
56
68
|
|
@@ -6,11 +6,13 @@ class JobTemplatesController < ::TemplatesController
|
|
6
6
|
@organizations = @template.organizations
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
@
|
9
|
+
def auto_complete_job_category
|
10
|
+
@job_categories = resource_base.where(['job_category LIKE ?', "%#{params[:search]}%"]).pluck(:job_category).uniq
|
11
|
+
render :json => @job_categories.map { |name| { 'completed' => '', 'part' => name, 'label' => name, 'category' => '' } }.to_json
|
11
12
|
end
|
12
13
|
|
13
14
|
def preview
|
15
|
+
find_resource unless @template.present?
|
14
16
|
base = Host.authorized(:view_hosts, Host)
|
15
17
|
host = params[:preview_host_id].present? ? base.find(params[:preview_host_id]) : base.first
|
16
18
|
@template.template = params[:template]
|
@@ -18,15 +20,23 @@ class JobTemplatesController < ::TemplatesController
|
|
18
20
|
if (output = renderer.preview)
|
19
21
|
render :text => output
|
20
22
|
else
|
21
|
-
render :status => 406, :text => renderer.error_message
|
23
|
+
render :status => 406, :text => renderer.error_message + _(', note that you must save template input changes before you try to preview it.')
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
27
|
private
|
26
28
|
|
29
|
+
def find_resource
|
30
|
+
if params[:id]
|
31
|
+
super
|
32
|
+
else
|
33
|
+
@template = resource_class.new(params[type_name_plural])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
27
37
|
def action_permission
|
28
38
|
case params[:action]
|
29
|
-
when '
|
39
|
+
when 'auto_complete_job_category'
|
30
40
|
:view_job_templates
|
31
41
|
else
|
32
42
|
super
|
@@ -6,9 +6,11 @@ class TemplateInvocationsController < ApplicationController
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def show
|
9
|
-
@
|
10
|
-
|
11
|
-
|
9
|
+
@template_invocation = TemplateInvocation.find(params[:id])
|
10
|
+
raise ActiveRecord::RecordNotFound unless User.current.can?(:view_job_invocations, @template_invocation.job_invocation)
|
11
|
+
|
12
|
+
@template_invocation_task = @template_invocation.run_host_job_task
|
13
|
+
@host = @template_invocation.host
|
12
14
|
@auto_refresh = @template_invocation_task.pending?
|
13
15
|
@since = params[:since].to_f if params[:since].present?
|
14
16
|
@line_sets = @template_invocation_task.main_action.live_output
|
@@ -15,7 +15,7 @@ module ForemanRemoteExecution
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def host_title_actions_with_run_button(*args)
|
18
|
-
title_actions(button_group(link_to(_(
|
18
|
+
title_actions(button_group(link_to(_('Run Job'), new_job_invocation_path(:host_ids => [args.first.id]), :id => :run_button)))
|
19
19
|
host_title_actions_without_run_button(*args)
|
20
20
|
end
|
21
21
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ForemanRemoteExecution
|
2
|
+
module JobTemplatesExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :permitted_actions, :run_button
|
7
|
+
end
|
8
|
+
|
9
|
+
def permitted_actions_with_run_button(template)
|
10
|
+
original = permitted_actions_without_run_button(template)
|
11
|
+
|
12
|
+
if template.is_a?(JobTemplate) && !template.snippet
|
13
|
+
original.unshift(display_link_if_authorized(_('Run'), hash_for_new_job_invocation_path(:template_id => template.id)))
|
14
|
+
end
|
15
|
+
|
16
|
+
original
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -30,15 +30,17 @@ module RemoteExecutionHelper
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def job_invocation_status(invocation)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
case invocation.status
|
34
|
+
when HostStatus::ExecutionStatus::QUEUED
|
35
|
+
_('queued')
|
36
|
+
when HostStatus::ExecutionStatus::RUNNING
|
37
|
+
_('running %s%') % invocation.progress
|
38
|
+
when HostStatus::ExecutionStatus::OK
|
39
|
+
_('succeeded')
|
40
|
+
when HostStatus::ExecutionStatus::ERROR
|
41
|
+
_('failed')
|
42
|
+
else
|
43
|
+
_('unknown status')
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
@@ -77,43 +79,48 @@ module RemoteExecutionHelper
|
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
80
|
-
def template_invocation_actions(task, host)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
82
|
+
def template_invocation_actions(task, host, job_invocation, template_invocation)
|
83
|
+
[
|
84
|
+
display_link_if_authorized(_('Host detail'), hash_for_host_path(host).merge(:auth_object => host, :permission => :view_hosts)),
|
85
|
+
display_link_if_authorized(_('Rerun on %s') % host.name, hash_for_rerun_job_invocation_path(:id => job_invocation, :host_ids => [ host.id ])),
|
86
|
+
]
|
86
87
|
end
|
87
88
|
|
88
|
-
def remote_execution_provider_for(
|
89
|
-
template_invocation = task.locks.where(:resource_type => 'TemplateInvocation').first.try(:resource) unless task.nil?
|
89
|
+
def remote_execution_provider_for(template_invocation)
|
90
90
|
template_invocation.nil? ? _('N/A') : template_invocation.template.provider.humanized_name
|
91
91
|
end
|
92
92
|
|
93
|
+
def job_invocations_buttons
|
94
|
+
[
|
95
|
+
documentation_button_rex('3.2ExecutingaJob'),
|
96
|
+
display_link_if_authorized(_('Run Job'), hash_for_new_job_invocation_path)
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
93
100
|
# rubocop:disable Metrics/AbcSize
|
94
101
|
def job_invocation_task_buttons(task)
|
95
102
|
job_invocation = task.task_groups.find { |group| group.class == JobInvocationTaskGroup }.job_invocation
|
96
103
|
buttons = []
|
97
104
|
buttons << link_to(_('Refresh'), {}, :class => 'btn btn-default', :title => _('Refresh this page'))
|
98
105
|
if authorized_for(hash_for_new_job_invocation_path)
|
99
|
-
buttons << link_to(_(
|
100
|
-
:class =>
|
106
|
+
buttons << link_to(_('Rerun'), rerun_job_invocation_path(:id => job_invocation.id),
|
107
|
+
:class => 'btn btn-default',
|
101
108
|
:title => _('Rerun the job'))
|
102
109
|
end
|
103
110
|
if authorized_for(hash_for_new_job_invocation_path)
|
104
|
-
buttons << link_to(_(
|
105
|
-
:class =>
|
111
|
+
buttons << link_to(_('Rerun failed'), rerun_job_invocation_path(:id => job_invocation.id, :failed_only => 1),
|
112
|
+
:class => 'btn btn-default',
|
106
113
|
:disabled => !task.sub_tasks.any? { |sub_task| task_failed?(sub_task) },
|
107
114
|
:title => _('Rerun on failed hosts'))
|
108
115
|
end
|
109
116
|
if authorized_for(:permission => :view_foreman_tasks, :auth_object => task)
|
110
|
-
buttons << link_to(_(
|
111
|
-
:class =>
|
117
|
+
buttons << link_to(_('Job Task'), foreman_tasks_task_path(task),
|
118
|
+
:class => 'btn btn-default',
|
112
119
|
:title => _('See the last task details'))
|
113
120
|
end
|
114
121
|
if authorized_for(:permission => :edit_foreman_tasks, :auth_object => task)
|
115
|
-
buttons << link_to(_(
|
116
|
-
:class =>
|
122
|
+
buttons << link_to(_('Cancel Job'), cancel_foreman_tasks_task_path(task),
|
123
|
+
:class => 'btn btn-danger',
|
117
124
|
:title => _('Try to cancel the job'),
|
118
125
|
:disabled => !task.cancellable?,
|
119
126
|
:method => :post)
|
@@ -125,13 +132,13 @@ module RemoteExecutionHelper
|
|
125
132
|
def template_invocation_task_buttons(task)
|
126
133
|
buttons = []
|
127
134
|
if authorized_for(:permission => :view_foreman_tasks, :auth_object => task)
|
128
|
-
buttons << link_to(_(
|
129
|
-
:class =>
|
135
|
+
buttons << link_to(_('Task Details'), foreman_tasks_task_path(task),
|
136
|
+
:class => 'btn btn-default',
|
130
137
|
:title => _('See the task details'))
|
131
138
|
end
|
132
139
|
if authorized_for(:permission => :edit_foreman_tasks, :auth_object => task)
|
133
|
-
buttons << link_to(_(
|
134
|
-
:class =>
|
140
|
+
buttons << link_to(_('Cancel Job'), cancel_foreman_tasks_task_path(task),
|
141
|
+
:class => 'btn btn-danger',
|
135
142
|
:title => _('Try to cancel the job on a host'),
|
136
143
|
:disabled => !task.cancellable?,
|
137
144
|
:method => :post)
|
@@ -140,20 +147,20 @@ module RemoteExecutionHelper
|
|
140
147
|
end
|
141
148
|
|
142
149
|
def link_to_invocation_task_if_authorized(invocation)
|
143
|
-
if invocation.
|
150
|
+
if invocation.queued?
|
151
|
+
job_invocation_status(invocation)
|
152
|
+
else
|
144
153
|
link_to_if_authorized job_invocation_status(invocation),
|
145
154
|
hash_for_foreman_tasks_task_path(invocation.task).merge(:auth_object => invocation.task, :permission => :view_foreman_tasks)
|
146
|
-
else
|
147
|
-
job_invocation_status(invocation)
|
148
155
|
end
|
149
156
|
end
|
150
157
|
|
151
158
|
def invocation_count(invocation, options = {})
|
152
159
|
options = { :unknown_string => 'N/A' }.merge(options)
|
153
|
-
if invocation.
|
154
|
-
(invocation.task.try(:output) || {}).fetch(options[:output_key], options[:unknown_string])
|
155
|
-
else
|
160
|
+
if invocation.queued?
|
156
161
|
options[:unknown_string]
|
162
|
+
else
|
163
|
+
(invocation.task.try(:output) || {}).fetch(options[:output_key], options[:unknown_string])
|
157
164
|
end
|
158
165
|
end
|
159
166
|
|
@@ -162,7 +169,7 @@ module RemoteExecutionHelper
|
|
162
169
|
if (preview = renderer.preview)
|
163
170
|
content_tag :pre, preview
|
164
171
|
else
|
165
|
-
alert :class =>
|
172
|
+
alert :class => 'alert-block alert-danger base in fade has-error',
|
166
173
|
:text => renderer.error_message.html_safe
|
167
174
|
end
|
168
175
|
end
|
@@ -178,13 +185,55 @@ module RemoteExecutionHelper
|
|
178
185
|
end
|
179
186
|
end
|
180
187
|
|
181
|
-
def
|
188
|
+
def time_in_words_span(time)
|
182
189
|
if time.nil?
|
183
|
-
_('
|
190
|
+
_('N/A')
|
184
191
|
else
|
185
|
-
content_tag :span, _(
|
192
|
+
content_tag :span, (time > Time.now ? _('in %s') : _('%s ago')) % time_ago_in_words(time),
|
186
193
|
{ :'data-original-title' => time.try(:in_time_zone), :rel => 'twipsy' }
|
187
194
|
end
|
188
195
|
end
|
189
196
|
|
197
|
+
def documentation_button_rex(section = '')
|
198
|
+
url = 'http://theforeman.org/plugins/foreman_remote_execution/' +
|
199
|
+
"#{ForemanRemoteExecution::VERSION.split('.').take(2).join('.')}/index.html#" +
|
200
|
+
section
|
201
|
+
link_to(
|
202
|
+
icon_text('help', _('Documentation'),
|
203
|
+
:class => 'icon-white', :kind => 'pficon'),
|
204
|
+
url,
|
205
|
+
:rel => 'external', :class => 'btn btn-info', :target => '_blank')
|
206
|
+
end
|
207
|
+
|
208
|
+
def template_input_header(f, template)
|
209
|
+
header = _('Template input')
|
210
|
+
header += ' ' + remove_child_link('x', f, {:rel => 'twipsy', :'data-title' => _('remove template input'), :'data-placement' => 'left',
|
211
|
+
:class => 'fr badge badge-danger'}) unless template.locked?
|
212
|
+
header.html_safe
|
213
|
+
end
|
214
|
+
|
215
|
+
def description_checkbox_f(f, job_template, disabled)
|
216
|
+
check_box_tag('description_format_override',
|
217
|
+
job_template.generate_description_format,
|
218
|
+
f.object.description_format.nil?,
|
219
|
+
:class => 'description_format_override',
|
220
|
+
:name => f.object_name + '[description_override]',
|
221
|
+
:disabled => disabled,
|
222
|
+
:onchange => 'description_override(this);') + ' ' + _('Use default description template')
|
223
|
+
end
|
224
|
+
|
225
|
+
def description_format_textarea_f(f, job_template, disabled)
|
226
|
+
textarea_f f, 'description_format',
|
227
|
+
:label => _('Description template'),
|
228
|
+
:value => f.object.description_format || job_template.generate_description_format,
|
229
|
+
:rows => 2,
|
230
|
+
:onchange => 'regenerate_description(this);',
|
231
|
+
:class => 'description_format',
|
232
|
+
:disabled => disabled,
|
233
|
+
:help_inline => popover(_('Explanation'),
|
234
|
+
_('This template is used to generate the description.
|
235
|
+
Input values can be used using the syntax %{package}.
|
236
|
+
You may also include the job category and template
|
237
|
+
name using %{job_category} and %{template_name}.'))
|
238
|
+
end
|
190
239
|
end
|
@@ -10,26 +10,29 @@ module Actions
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def plan(job_invocation, host, template_invocation, proxy)
|
13
|
-
action_subject(host, :
|
13
|
+
action_subject(host, :job_category => job_invocation.job_category, :description => job_invocation.description)
|
14
|
+
|
15
|
+
template_invocation.host_id = host.id
|
16
|
+
template_invocation.run_host_job_task_id = task.id
|
17
|
+
template_invocation.save!
|
14
18
|
|
15
|
-
template_invocation.update_attribute :host_id, host.id
|
16
19
|
link!(job_invocation)
|
17
20
|
link!(template_invocation)
|
18
21
|
|
19
22
|
verify_permissions(host, template_invocation)
|
20
23
|
hostname = find_ip_or_hostname(host)
|
21
24
|
|
22
|
-
raise _(
|
25
|
+
raise _('Could not use any template used in the job invocation') if template_invocation.blank?
|
23
26
|
|
24
27
|
settings = { :global_proxy => 'remote_execution_global_proxy',
|
25
28
|
:fallback_proxy => 'remote_execution_fallback_proxy' }
|
26
29
|
|
27
|
-
raise _(
|
28
|
-
|
30
|
+
raise _('Could not use any proxy. Consider configuring %{global_proxy} ' +
|
31
|
+
'or %{fallback_proxy} in settings') % settings if proxy.blank?
|
29
32
|
|
30
33
|
renderer = InputTemplateRenderer.new(template_invocation.template, host, template_invocation)
|
31
34
|
script = renderer.render
|
32
|
-
raise _(
|
35
|
+
raise _('Failed rendering template: %s') % renderer.error_message unless script
|
33
36
|
|
34
37
|
provider = template_invocation.template.provider
|
35
38
|
plan_action(RunProxyCommand, proxy, hostname, script, provider.proxy_command_options(template_invocation, host))
|
@@ -57,9 +60,9 @@ module Actions
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def humanized_name
|
60
|
-
_('%{description} on %{host}') % { :
|
63
|
+
_('%{description} on %{host}') % { :job_category => input[:job_category],
|
61
64
|
:host => input[:host][:name],
|
62
|
-
:description => input[:description].try(:capitalize) || input[:
|
65
|
+
:description => input[:description].try(:capitalize) || input[:job_category] }
|
63
66
|
end
|
64
67
|
|
65
68
|
def find_ip_or_hostname(host)
|
@@ -16,7 +16,7 @@ module Actions
|
|
16
16
|
task.add_missing_task_groups(job_invocation.task_group) if job_invocation.task_group
|
17
17
|
action_subject(job_invocation) unless locked
|
18
18
|
job_invocation.targeting.resolve_hosts! if job_invocation.targeting.dynamic? || !locked
|
19
|
-
input.update(:
|
19
|
+
input.update(:job_category => job_invocation.job_category)
|
20
20
|
plan_self(:job_invocation_id => job_invocation.id)
|
21
21
|
end
|
22
22
|
|
@@ -24,8 +24,11 @@ module Actions
|
|
24
24
|
job_invocation = JobInvocation.find(input[:job_invocation_id])
|
25
25
|
load_balancer = ProxyLoadBalancer.new
|
26
26
|
|
27
|
+
# composer creates just "pattern" for template_invocations because target is evaluated
|
28
|
+
# during actual run (here) so we build template invocations from these patterns
|
27
29
|
job_invocation.targeting.hosts.map do |host|
|
28
|
-
template_invocation = job_invocation.
|
30
|
+
template_invocation = job_invocation.pattern_template_invocation_for_host(host).deep_clone
|
31
|
+
template_invocation.host_id = host.id
|
29
32
|
proxy = determine_proxy(template_invocation, host, load_balancer)
|
30
33
|
trigger(RunHostJob, job_invocation, host, template_invocation, proxy)
|
31
34
|
end
|
@@ -21,7 +21,7 @@ module Actions
|
|
21
21
|
.new(data[:metadata][:exception_message]))
|
22
22
|
else
|
23
23
|
super(data)
|
24
|
-
error! _(
|
24
|
+
error! _('Script execution failed') if failed_run?
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -63,7 +63,7 @@ module Actions
|
|
63
63
|
proxy_data.fetch('output', {}).fetch('result', [])
|
64
64
|
rescue => e
|
65
65
|
::Foreman::Logging.exception("Failed to load data for task #{task.id} from proxy #{ input[:proxy_url] }", e)
|
66
|
-
[exception_to_output(_(
|
66
|
+
[exception_to_output(_('Error loading data from proxy'), e)]
|
67
67
|
end
|
68
68
|
|
69
69
|
def finalized_output
|
@@ -76,13 +76,18 @@ module Actions
|
|
76
76
|
end
|
77
77
|
|
78
78
|
if exit_status
|
79
|
-
records << format_output(_(
|
79
|
+
records << format_output(_('Exit status: %s') % exit_status, 'stdout', final_timestamp(records))
|
80
80
|
elsif run_step && run_step.error
|
81
|
-
records << format_output(_(
|
81
|
+
records << format_output(_('Job finished with error') + ": #{run_step.error.exception_class} - #{run_step.error.message}", 'debug', final_timestamp(records))
|
82
82
|
end
|
83
83
|
return records
|
84
84
|
end
|
85
85
|
|
86
|
+
def final_timestamp(records)
|
87
|
+
return task.ended_at if records.blank?
|
88
|
+
records.last.fetch('timestamp', task.ended_at) + 1
|
89
|
+
end
|
90
|
+
|
86
91
|
def proxy_result
|
87
92
|
self.output.fetch(:proxy_output, {}).fetch(:result, []) || []
|
88
93
|
end
|