foreman_remote_execution 0.0.1
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.
- checksums.yaml +15 -0
- data/LICENSE +619 -0
- data/README.md +54 -0
- data/Rakefile +47 -0
- data/app/assets/javascripts/template_input.js +9 -0
- data/app/assets/javascripts/template_invocation.js +32 -0
- data/app/assets/stylesheets/job_invocations.css.scss +35 -0
- data/app/assets/stylesheets/template_invocation.css.scss +16 -0
- data/app/controllers/api/v2/job_templates_controller.rb +108 -0
- data/app/controllers/job_invocations_controller.rb +35 -0
- data/app/controllers/job_templates_controller.rb +35 -0
- data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +40 -0
- data/app/helpers/remote_execution_helper.rb +88 -0
- data/app/lib/actions/remote_execution/run_host_job.rb +93 -0
- data/app/lib/actions/remote_execution/run_hosts_job.rb +35 -0
- data/app/lib/actions/remote_execution/run_proxy_command.rb +34 -0
- data/app/models/concerns/foreman_remote_execution/bookmark_extensions.rb +9 -0
- data/app/models/concerns/foreman_remote_execution/foreman_tasks_task_extensions.rb +9 -0
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +19 -0
- data/app/models/concerns/foreman_remote_execution/template_extensions.rb +20 -0
- data/app/models/concerns/foreman_remote_execution/template_relations.rb +10 -0
- data/app/models/concerns/foreman_remote_execution/user_extensions.rb +9 -0
- data/app/models/input_template_renderer.rb +42 -0
- data/app/models/job_invocation.rb +21 -0
- data/app/models/job_invocation_composer.rb +210 -0
- data/app/models/job_template.rb +52 -0
- data/app/models/remote_execution_provider.rb +17 -0
- data/app/models/setting/remote_execution.rb +19 -0
- data/app/models/ssh_execution_provider.rb +2 -0
- data/app/models/targeting.rb +56 -0
- data/app/models/targeting_host.rb +9 -0
- data/app/models/template_input.rb +154 -0
- data/app/models/template_invocation.rb +13 -0
- data/app/models/template_invocation_input_value.rb +8 -0
- data/app/views/api/v2/job_templates/base.json.rabl +3 -0
- data/app/views/api/v2/job_templates/create.json.rabl +3 -0
- data/app/views/api/v2/job_templates/index.json.rabl +3 -0
- data/app/views/api/v2/job_templates/main.json.rabl +5 -0
- data/app/views/api/v2/job_templates/show.json.rabl +9 -0
- data/app/views/job_invocations/_form.html.erb +67 -0
- data/app/views/job_invocations/_tab_hosts.html.erb +33 -0
- data/app/views/job_invocations/_tab_overview.html.erb +41 -0
- data/app/views/job_invocations/index.html.erb +30 -0
- data/app/views/job_invocations/new.html.erb +8 -0
- data/app/views/job_invocations/refresh.js.erb +1 -0
- data/app/views/job_invocations/show.html.erb +21 -0
- data/app/views/job_templates/_custom_tab_headers.html.erb +2 -0
- data/app/views/job_templates/_custom_tabs.html.erb +28 -0
- data/app/views/job_templates/auto_complete_job_name.json.erb +3 -0
- data/app/views/job_templates/edit.html.erb +6 -0
- data/app/views/job_templates/index.html.erb +33 -0
- data/app/views/job_templates/new.html.erb +6 -0
- data/app/views/template_inputs/_form.html.erb +22 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20150612121541_add_job_template_to_template.rb +6 -0
- data/db/migrate/20150616080015_create_template_input.rb +19 -0
- data/db/migrate/20150708133241_add_targeting.rb +25 -0
- data/db/migrate/20150708133242_add_invocation.rb +11 -0
- data/db/migrate/20150708133305_add_template_invocation.rb +22 -0
- data/db/migrate/20150812110800_add_resolved_at_to_targeting.rb +5 -0
- data/db/migrate/20150812145900_add_last_task_id_to_job_invocation.rb +6 -0
- data/db/seeds.d/60-ssh_proxy_feature.rb +2 -0
- data/lib/foreman_remote_execution/engine.rb +119 -0
- data/lib/foreman_remote_execution/version.rb +3 -0
- data/lib/foreman_remote_execution.rb +6 -0
- data/lib/tasks/foreman_remote_execution_tasks.rake +49 -0
- data/locale/Makefile +62 -0
- data/locale/en/foreman_remote_execution.po +19 -0
- data/locale/foreman_remote_execution.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/test/factories/foreman_remote_execution_factories.rb +48 -0
- data/test/functional/api/v2/job_templates_controller_test.rb +74 -0
- data/test/test_plugin_helper.rb +8 -0
- data/test/unit/actions/run_hosts_job_test.rb +40 -0
- data/test/unit/actions/run_proxy_command_test.rb +30 -0
- data/test/unit/input_template_renderer_test.rb +366 -0
- data/test/unit/job_invocation_composer_test.rb +415 -0
- data/test/unit/job_invocation_test.rb +31 -0
- data/test/unit/job_template_test.rb +5 -0
- data/test/unit/remote_execution_provider_test.rb +51 -0
- data/test/unit/targeting_test.rb +107 -0
- data/test/unit/template_input_test.rb +25 -0
- metadata +195 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
|
|
3
|
+
describe InputTemplateRenderer do
|
|
4
|
+
context "renderer for simple template without inputs" do
|
|
5
|
+
let(:renderer) { InputTemplateRenderer.new(FactoryGirl.build(:job_template, :template => 'id')) }
|
|
6
|
+
|
|
7
|
+
it 'should render the content' do
|
|
8
|
+
renderer.render.must_equal 'id'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should render preview' do
|
|
12
|
+
renderer.preview.must_equal 'id'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "renderer for template with user input used" do
|
|
17
|
+
let(:template) { FactoryGirl.build(:job_template, :template => 'service restart <%= input("service_name") -%>') }
|
|
18
|
+
let(:renderer) { InputTemplateRenderer.new(template) }
|
|
19
|
+
|
|
20
|
+
context 'but without input defined' do
|
|
21
|
+
describe 'rendering' do
|
|
22
|
+
let(:result) { renderer.render }
|
|
23
|
+
it { result.must_equal false }
|
|
24
|
+
|
|
25
|
+
it 'registers an error' do
|
|
26
|
+
result # let is lazy
|
|
27
|
+
renderer.error_message.wont_be_nil
|
|
28
|
+
renderer.error_message.wont_be_empty
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'preview' do
|
|
33
|
+
let(:result) { renderer.preview }
|
|
34
|
+
it { result.must_equal false }
|
|
35
|
+
|
|
36
|
+
it 'registers an error' do
|
|
37
|
+
result # let is lazy
|
|
38
|
+
renderer.error_message.wont_be_nil
|
|
39
|
+
renderer.error_message.wont_be_empty
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'with matching input defined' do
|
|
45
|
+
|
|
46
|
+
let(:job_invocation) { FactoryGirl.create(:job_invocation) }
|
|
47
|
+
let(:template_invocation) { FactoryGirl.build(:template_invocation, :template => template) }
|
|
48
|
+
let(:result) { renderer.render }
|
|
49
|
+
|
|
50
|
+
before do
|
|
51
|
+
template.template_inputs << FactoryGirl.build(:template_input, :name => 'service_name', :input_type => 'user')
|
|
52
|
+
job_invocation.template_invocations << template_invocation
|
|
53
|
+
renderer.invocation = template_invocation
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe 'rendering' do
|
|
57
|
+
it 'can\'t render the content without job invocation since we don\'t have values' do
|
|
58
|
+
refute result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'registers an error' do
|
|
62
|
+
result # let is lazy
|
|
63
|
+
renderer.error_message.wont_be_nil
|
|
64
|
+
renderer.error_message.wont_be_empty
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'with invocation specified' do
|
|
68
|
+
before do
|
|
69
|
+
FactoryGirl.create(:template_invocation_input_value,
|
|
70
|
+
:template_invocation => template_invocation,
|
|
71
|
+
:template_input => template.template_inputs.first,
|
|
72
|
+
:value => 'foreman')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'can render with job invocation with corresponding value' do
|
|
76
|
+
renderer.render.must_equal 'service restart foreman'
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe 'preview' do
|
|
82
|
+
it 'should render preview' do
|
|
83
|
+
renderer.preview.must_equal 'service restart $USER_INPUT[service_name]'
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "renderer for template with fact input used" do
|
|
90
|
+
let(:template) { FactoryGirl.build(:job_template, :template => 'echo <%= input("issue") -%> > /etc/issue') }
|
|
91
|
+
let(:renderer) { InputTemplateRenderer.new(template) }
|
|
92
|
+
|
|
93
|
+
context 'with matching input defined' do
|
|
94
|
+
before { renderer.template.template_inputs<< FactoryGirl.build(:template_input, :name => 'issue', :input_type => 'fact', :fact_name => 'issue') }
|
|
95
|
+
let(:result) { renderer.render }
|
|
96
|
+
|
|
97
|
+
describe 'rendering' do
|
|
98
|
+
it 'can\'t render the content without host since we don\'t have facts' do
|
|
99
|
+
refute result
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'registers an error' do
|
|
103
|
+
result # let is lazy
|
|
104
|
+
renderer.error_message.wont_be_nil
|
|
105
|
+
renderer.error_message.wont_be_empty
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'with host specified' do
|
|
109
|
+
before { renderer.host = FactoryGirl.create(:host) }
|
|
110
|
+
|
|
111
|
+
describe 'rendering' do
|
|
112
|
+
it 'can\'t render the content without host since we don\'t have fact value' do
|
|
113
|
+
refute result
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'registers an error' do
|
|
117
|
+
result # let is lazy
|
|
118
|
+
renderer.error_message.wont_be_nil
|
|
119
|
+
renderer.error_message.wont_be_empty
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe 'preview' do
|
|
124
|
+
it 'should render preview' do
|
|
125
|
+
renderer.preview.must_equal 'echo $FACT_INPUT[issue] > /etc/issue'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context 'with existing fact' do
|
|
130
|
+
let(:fact) { FactoryGirl.create(:fact_name, :name => 'issue') }
|
|
131
|
+
|
|
132
|
+
describe 'rendering' do
|
|
133
|
+
it 'can\'t render the content without host since we don\'t have fact value' do
|
|
134
|
+
fact # let is lazy
|
|
135
|
+
refute result
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'registers an error' do
|
|
139
|
+
result # let is lazy
|
|
140
|
+
renderer.error_message.wont_be_nil
|
|
141
|
+
renderer.error_message.wont_be_empty
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe 'preview' do
|
|
146
|
+
it 'should render preview' do
|
|
147
|
+
renderer.preview.must_equal 'echo $FACT_INPUT[issue] > /etc/issue'
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context 'with fact issue value' do
|
|
152
|
+
before { FactoryGirl.create(:fact_value, :host => renderer.host, :fact_name => fact, :value => 'banner') }
|
|
153
|
+
|
|
154
|
+
let(:result) { renderer.render }
|
|
155
|
+
|
|
156
|
+
it 'can render with job invocation with corresponding value' do
|
|
157
|
+
result.must_equal 'echo banner > /etc/issue'
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
describe 'preview' do
|
|
165
|
+
it 'should render preview' do
|
|
166
|
+
renderer.preview.must_equal 'echo $FACT_INPUT[issue] > /etc/issue'
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context 'with host specified' do
|
|
170
|
+
before do
|
|
171
|
+
host = FactoryGirl.create(:host)
|
|
172
|
+
fact = FactoryGirl.create(:fact_name, :name => 'issue')
|
|
173
|
+
FactoryGirl.create(:fact_value, :host => host, :fact_name => fact, :value => 'banner')
|
|
174
|
+
renderer.host = host
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
let(:result) { renderer.render }
|
|
178
|
+
|
|
179
|
+
it 'uses the value even in preview' do
|
|
180
|
+
result.must_equal 'echo banner > /etc/issue'
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context "renderer for template with variable input used" do
|
|
188
|
+
let(:template) { FactoryGirl.build(:job_template, :template => 'echo <%= input("client_key") -%> > /etc/chef/client.pem') }
|
|
189
|
+
let(:renderer) { InputTemplateRenderer.new(template) }
|
|
190
|
+
|
|
191
|
+
context 'with matching input defined' do
|
|
192
|
+
before { renderer.template.template_inputs<< FactoryGirl.build(:template_input, :name => 'client_key', :input_type => 'variable', :variable_name => 'client_key') }
|
|
193
|
+
let(:result) { renderer.render }
|
|
194
|
+
|
|
195
|
+
describe 'rendering' do
|
|
196
|
+
it 'can\'t render the content without host since we don\'t have host so no classification' do
|
|
197
|
+
refute result
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it 'registers an error' do
|
|
201
|
+
result # let is lazy
|
|
202
|
+
renderer.error_message.wont_be_nil
|
|
203
|
+
renderer.error_message.wont_be_empty
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context 'with host specified' do
|
|
207
|
+
let(:environment) { FactoryGirl.create(:environment) }
|
|
208
|
+
before { renderer.host = FactoryGirl.create(:host, :environment => environment) }
|
|
209
|
+
|
|
210
|
+
describe 'rendering' do
|
|
211
|
+
it 'can\'t render the content without host since we don\'t have variable value in classification' do
|
|
212
|
+
refute result
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'registers an error' do
|
|
216
|
+
result # let is lazy
|
|
217
|
+
renderer.error_message.wont_be_nil
|
|
218
|
+
renderer.error_message.wont_be_empty
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
describe 'preview' do
|
|
223
|
+
it 'should render preview' do
|
|
224
|
+
renderer.preview.must_equal 'echo $VARIABLE_INPUT[client_key] > /etc/chef/client.pem'
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
context 'with existing variable implemented as host parameter' do
|
|
230
|
+
let(:parameter) { FactoryGirl.create(:host_parameter, :host => renderer.host, :name => 'client_key', :value => 'RSA KEY') }
|
|
231
|
+
|
|
232
|
+
describe 'rendering' do
|
|
233
|
+
it 'renders the value from host parameter' do
|
|
234
|
+
parameter
|
|
235
|
+
renderer.host.reload
|
|
236
|
+
result.must_equal 'echo RSA KEY > /etc/chef/client.pem'
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
describe 'preview' do
|
|
241
|
+
it 'should render preview' do
|
|
242
|
+
parameter
|
|
243
|
+
renderer.host.reload
|
|
244
|
+
renderer.preview.must_equal 'echo RSA KEY > /etc/chef/client.pem'
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
context 'with existing variable implemented as smart variable' do
|
|
250
|
+
let(:puppet_class) { FactoryGirl.create(:puppetclass, :environments => [environment], :hosts => [renderer.host]) }
|
|
251
|
+
let(:lookup_key) do
|
|
252
|
+
FactoryGirl.create(:lookup_key,
|
|
253
|
+
:key => 'client_key',
|
|
254
|
+
:puppetclass => puppet_class,
|
|
255
|
+
:overrides => {"fqdn=#{renderer.host.fqdn}" => "RSA KEY"})
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe 'rendering' do
|
|
259
|
+
it 'renders the value from host parameter' do
|
|
260
|
+
lookup_key
|
|
261
|
+
result.must_equal 'echo RSA KEY > /etc/chef/client.pem'
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
describe 'preview' do
|
|
266
|
+
it 'should render preview' do
|
|
267
|
+
lookup_key
|
|
268
|
+
renderer.preview.must_equal 'echo RSA KEY > /etc/chef/client.pem'
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe 'preview' do
|
|
275
|
+
it 'should render preview' do
|
|
276
|
+
renderer.preview.must_equal 'echo $VARIABLE_INPUT[client_key] > /etc/chef/client.pem'
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
context "renderer for template with puppet parameter input used" do
|
|
284
|
+
let(:template) { FactoryGirl.build(:job_template, :template => 'echo "This is WebServer with nginx <%= input("nginx_version") -%>" > /etc/motd') }
|
|
285
|
+
let(:renderer) { InputTemplateRenderer.new(template) }
|
|
286
|
+
|
|
287
|
+
context 'with matching input defined' do
|
|
288
|
+
before do
|
|
289
|
+
renderer.template.template_inputs<< FactoryGirl.build(:template_input,
|
|
290
|
+
:name => 'nginx_version',
|
|
291
|
+
:input_type => 'puppet_parameter',
|
|
292
|
+
:puppet_parameter_name => 'version',
|
|
293
|
+
:puppet_class_name => 'nginx')
|
|
294
|
+
end
|
|
295
|
+
let(:result) { renderer.render }
|
|
296
|
+
|
|
297
|
+
describe 'rendering' do
|
|
298
|
+
it 'can\'t render the content without host since we don\'t have host so no classification' do
|
|
299
|
+
refute result
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
it 'registers an error' do
|
|
303
|
+
result # let is lazy
|
|
304
|
+
renderer.error_message.wont_be_nil
|
|
305
|
+
renderer.error_message.wont_be_empty
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
context 'with host specified' do
|
|
309
|
+
let(:environment) { FactoryGirl.create(:environment) }
|
|
310
|
+
before { renderer.host = FactoryGirl.create(:host, :environment => environment) }
|
|
311
|
+
|
|
312
|
+
describe 'rendering' do
|
|
313
|
+
it 'can\'t render the content without host since we don\'t have puppet parameter in classification' do
|
|
314
|
+
refute result
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it 'registers an error' do
|
|
318
|
+
result # let is lazy
|
|
319
|
+
renderer.error_message.wont_be_nil
|
|
320
|
+
renderer.error_message.wont_be_empty
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
describe 'preview' do
|
|
325
|
+
it 'should render preview' do
|
|
326
|
+
renderer.preview.must_equal 'echo "This is WebServer with nginx $PUPPET_PARAMETER_INPUT[nginx_version]" > /etc/motd'
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context 'with existing puppet parameter with matching override' do
|
|
331
|
+
let(:puppet_class) do
|
|
332
|
+
FactoryGirl.create(:puppetclass, :environments => [environment], :hosts => [renderer.host], :name => 'nginx')
|
|
333
|
+
end
|
|
334
|
+
let(:lookup_key) do
|
|
335
|
+
FactoryGirl.create(:lookup_key, :as_smart_class_param, :with_override,
|
|
336
|
+
:key => 'version',
|
|
337
|
+
:puppetclass => puppet_class,
|
|
338
|
+
:path => 'fqdn',
|
|
339
|
+
:overrides => {"fqdn=#{renderer.host.fqdn}" => "1.4.7"})
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
describe 'rendering' do
|
|
343
|
+
it 'renders the value from puppet parameter' do
|
|
344
|
+
lookup_key
|
|
345
|
+
result.must_equal 'echo "This is WebServer with nginx 1.4.7" > /etc/motd'
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
describe 'preview' do
|
|
350
|
+
it 'should render preview' do
|
|
351
|
+
lookup_key
|
|
352
|
+
renderer.preview.must_equal 'echo "This is WebServer with nginx 1.4.7" > /etc/motd'
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
describe 'preview' do
|
|
359
|
+
it 'should render preview' do
|
|
360
|
+
renderer.preview.must_equal 'echo "This is WebServer with nginx $PUPPET_PARAMETER_INPUT[nginx_version]" > /etc/motd'
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
end
|