foreman_remote_execution 0.3.0 → 0.3.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 -5
- data/.rubocop_todo.yml +90 -92
- data/app/assets/javascripts/job_templates.js +10 -0
- data/app/assets/stylesheets/modal_window.css.scss +4 -0
- data/app/controllers/api/v2/job_templates_controller.rb +22 -1
- data/app/controllers/job_templates_controller.rb +21 -1
- data/app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb +3 -2
- data/app/helpers/remote_execution_helper.rb +5 -3
- data/app/lib/actions/middleware/bind_job_invocation.rb +1 -1
- data/app/lib/actions/remote_execution/run_host_job.rb +15 -8
- data/app/lib/actions/remote_execution/run_hosts_job.rb +2 -1
- data/app/models/concerns/foreman_remote_execution/exportable.rb +71 -0
- data/app/models/foreign_input_set.rb +3 -0
- data/app/models/job_invocation.rb +6 -4
- data/app/models/job_invocation_composer.rb +1 -1
- data/app/models/job_template.rb +22 -6
- data/app/models/template_input.rb +4 -0
- data/app/models/template_invocation.rb +1 -1
- data/app/services/proxy_load_balancer.rb +3 -0
- data/app/views/job_invocations/_preview_hosts_modal.html.erb +3 -1
- data/app/views/job_templates/_import_job_template_modal.html.erb +20 -0
- data/app/views/job_templates/index.html.erb +5 -1
- data/config/routes.rb +4 -0
- data/lib/foreman_remote_execution/engine.rb +4 -4
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/locale/Makefile +18 -19
- data/locale/action_names.rb +2 -2
- data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/de/foreman_remote_execution.po +823 -0
- data/locale/en/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/en/foreman_remote_execution.po +332 -283
- data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/en_GB/foreman_remote_execution.po +824 -0
- data/locale/foreman_remote_execution.pot +277 -131
- data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/fr/foreman_remote_execution.po +823 -0
- data/test/functional/api/v2/job_templates_controller_test.rb +15 -0
- data/test/unit/actions/run_host_job_test.rb +50 -0
- data/test/unit/concerns/exportable_test.rb +88 -0
- data/test/unit/job_invocation_composer_test.rb +1 -1
- data/test/unit/job_invocation_test.rb +3 -6
- data/test/unit/job_template_test.rb +34 -2
- data/test/unit/proxy_load_balancer_test.rb +8 -6
- data/test/unit/template_input_test.rb +15 -0
- metadata +17 -2
@@ -69,6 +69,21 @@ module Api
|
|
69
69
|
:job_template => {:name => ''}
|
70
70
|
assert_response :unprocessable_entity
|
71
71
|
end
|
72
|
+
|
73
|
+
test 'should export template' do
|
74
|
+
get :export, :id => @template.to_param
|
75
|
+
assert_equal @response.body, @template.to_erb
|
76
|
+
assert_response :success
|
77
|
+
end
|
78
|
+
|
79
|
+
test 'should import template' do
|
80
|
+
new_name = @template.name = "#{@template.name}_renamed"
|
81
|
+
erb_data = @template.to_erb
|
82
|
+
post :import, :template => erb_data
|
83
|
+
assert_response :success
|
84
|
+
assert JobTemplate.find_by_name(new_name)
|
85
|
+
end
|
72
86
|
end
|
87
|
+
|
73
88
|
end
|
74
89
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module ForemanRemoteExecution
|
4
|
+
class RunHostJobTest < ActiveSupport::TestCase
|
5
|
+
include Dynflow::Testing
|
6
|
+
|
7
|
+
let(:action) do
|
8
|
+
create_action(Actions::RemoteExecution::RunHostJob)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#find_ip_or_hostname' do
|
12
|
+
let(:host) { FactoryGirl.create(:host) }
|
13
|
+
let(:flags) do
|
14
|
+
{ :primary => false, :provision => false, :execution => false }
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'finds hostname' do
|
18
|
+
host.expects(:fqdn).returns('somehost.somedomain.org')
|
19
|
+
action.send(:find_ip_or_hostname, host).must_equal 'somehost.somedomain.org'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets ip from unflagged interfaces' do
|
23
|
+
ip = '127.0.0.1'
|
24
|
+
host.interfaces = [FactoryGirl.build(:nic_managed, flags.merge(:ip => nil)),
|
25
|
+
FactoryGirl.build(:nic_managed, flags.merge(:ip => ip))]
|
26
|
+
action.send(:find_ip_or_hostname, host).must_equal ip
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'gets ip from flagged interfaces' do
|
30
|
+
unflagged_interface = FactoryGirl.build(:nic_managed, flags)
|
31
|
+
host.interfaces = [unflagged_interface]
|
32
|
+
action.send(:find_ip_or_hostname, host).must_equal unflagged_interface.ip
|
33
|
+
|
34
|
+
provision_interface = FactoryGirl.build(:nic_managed, flags.merge(:provision => true))
|
35
|
+
host.interfaces << provision_interface
|
36
|
+
action.send(:find_ip_or_hostname, host).must_equal provision_interface.ip
|
37
|
+
|
38
|
+
primary_interface = FactoryGirl.build(:nic_managed, flags.merge(:primary => true))
|
39
|
+
host.interfaces << primary_interface
|
40
|
+
# Workaround, execution flag got enabled when adding the interface to the host
|
41
|
+
host.interfaces.last.execution = false
|
42
|
+
action.send(:find_ip_or_hostname, host).must_equal primary_interface.ip
|
43
|
+
|
44
|
+
execution_interface = FactoryGirl.build(:nic_managed, flags.merge(:execution => true))
|
45
|
+
host.interfaces << execution_interface
|
46
|
+
action.send(:find_ip_or_hostname, host).must_equal execution_interface.ip
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module ForemanRemoteExecution
|
4
|
+
class ExportableTest < ActiveSupport::TestCase
|
5
|
+
class SampleModel
|
6
|
+
include ::ForemanRemoteExecution::Exportable
|
7
|
+
|
8
|
+
attr_accessor :name, :attrs, :subnet, :mac, :password, :subnet
|
9
|
+
attr_exportable :name, :attrs, :mac, :subnet, :mac => ->(m) { m.mac.upcase if m.mac },
|
10
|
+
:custom_attr => ->(m) { 'hello world' }
|
11
|
+
|
12
|
+
def attributes
|
13
|
+
{
|
14
|
+
'name' => name,
|
15
|
+
'attrs' => attrs,
|
16
|
+
'mac' => mac,
|
17
|
+
'password' => password,
|
18
|
+
'subnet' => subnet
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class SampleSubnet
|
24
|
+
include ::ForemanRemoteExecution::Exportable
|
25
|
+
|
26
|
+
attr_accessor :name, :network
|
27
|
+
attr_exportable :name, :network
|
28
|
+
|
29
|
+
def attributes
|
30
|
+
{
|
31
|
+
'name' => name,
|
32
|
+
'network' => network
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def setup
|
38
|
+
@subnet = SampleSubnet.new
|
39
|
+
@subnet.name = 'pxe'
|
40
|
+
@subnet.network = '192.168.122.0'
|
41
|
+
|
42
|
+
@sample = SampleModel.new
|
43
|
+
@sample.name = 'name'
|
44
|
+
@sample.attrs = {'nested' => 'hash'}
|
45
|
+
@sample.subnet = @subnet
|
46
|
+
@sample.mac = 'aa:bb:cc:dd:ee:ff'
|
47
|
+
@sample.password = 'password'
|
48
|
+
end
|
49
|
+
|
50
|
+
test '#to_export includes all specified attributes' do
|
51
|
+
assert_equal %w(name attrs mac subnet custom_attr), @sample.to_export.keys
|
52
|
+
end
|
53
|
+
|
54
|
+
test '#to_export does not include all attributes' do
|
55
|
+
assert_not_include @sample.to_export.keys, 'password'
|
56
|
+
end
|
57
|
+
|
58
|
+
test '#to_export calls the lambda' do
|
59
|
+
export = @sample.to_export
|
60
|
+
assert_equal('AA:BB:CC:DD:EE:FF', export['mac'])
|
61
|
+
assert_equal(export['custom_attr'], 'hello world')
|
62
|
+
end
|
63
|
+
|
64
|
+
test '#to_export values are exported recursively' do
|
65
|
+
export = @sample.to_export
|
66
|
+
assert_equal('pxe', export['subnet']['name'])
|
67
|
+
assert_equal('192.168.122.0', export['subnet']['network'])
|
68
|
+
end
|
69
|
+
|
70
|
+
test '#to_export nested hashes are primitive' do
|
71
|
+
@sample.attrs = {:foo => 'bar', :baz => 'qux'}.with_indifferent_access
|
72
|
+
export = @sample.to_export
|
73
|
+
assert_instance_of Hash, export['attrs']
|
74
|
+
end
|
75
|
+
|
76
|
+
test '#to_export includes blank values' do
|
77
|
+
@sample.attrs = {}
|
78
|
+
export = @sample.to_export
|
79
|
+
assert_instance_of Hash, export['attrs']
|
80
|
+
end
|
81
|
+
|
82
|
+
test '#to_export(false) does not include blank values' do
|
83
|
+
@sample.attrs = {}
|
84
|
+
export = @sample.to_export(false)
|
85
|
+
assert_nil export['attrs']
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -433,7 +433,7 @@ describe JobInvocationComposer do
|
|
433
433
|
|
434
434
|
describe 'with concurrency control set' do
|
435
435
|
let(:params) do
|
436
|
-
{ :job_invocation => { :providers => { :ssh => ssh_params }, :concurrency_level =>
|
436
|
+
{ :job_invocation => { :providers => { :ssh => ssh_params }, :concurrency_level => '5', :time_span => '60' } }.with_indifferent_access
|
437
437
|
end
|
438
438
|
|
439
439
|
it 'accepts the concurrency options' do
|
@@ -63,16 +63,14 @@ describe JobInvocation do
|
|
63
63
|
|
64
64
|
describe 'descriptions' do
|
65
65
|
it 'generates description from input values' do
|
66
|
-
job_invocation.expects(:save!)
|
67
66
|
job_invocation.description_format = '%{job_category} - %{foo}'
|
68
|
-
job_invocation.generate_description
|
67
|
+
job_invocation.generate_description
|
69
68
|
job_invocation.description.must_equal "#{job_invocation.job_category} - #{@input_value.value}"
|
70
69
|
end
|
71
70
|
|
72
71
|
it 'handles missing keys correctly' do
|
73
|
-
job_invocation.expects(:save!)
|
74
72
|
job_invocation.description_format = '%{job_category} - %{missing_key}'
|
75
|
-
job_invocation.generate_description
|
73
|
+
job_invocation.generate_description
|
76
74
|
job_invocation.description.must_equal "#{job_invocation.job_category} - %{missing_key}"
|
77
75
|
end
|
78
76
|
|
@@ -80,10 +78,9 @@ describe JobInvocation do
|
|
80
78
|
column_limit = 255
|
81
79
|
expected_result = 'a' * column_limit
|
82
80
|
JobInvocation.columns_hash['description'].expects(:limit).returns(column_limit)
|
83
|
-
job_invocation.expects(:save!)
|
84
81
|
job_invocation.description_format = '%{job_category}'
|
85
82
|
job_invocation.job_category = 'a' * 1000
|
86
|
-
job_invocation.generate_description
|
83
|
+
job_invocation.generate_description
|
87
84
|
job_invocation.description.must_equal expected_result
|
88
85
|
end
|
89
86
|
end
|
@@ -217,12 +217,44 @@ describe JobTemplate do
|
|
217
217
|
end
|
218
218
|
|
219
219
|
it 'syncs content' do
|
220
|
-
synced_template.template.must_match(
|
220
|
+
synced_template.template.must_match(/ping -c <%= input\('count'\) %> <%= input\('hostname'\) %>/m)
|
221
221
|
end
|
222
222
|
|
223
223
|
it 'syncs input sets' do
|
224
224
|
synced_template.foreign_input_sets.first.target_template.must_equal included
|
225
|
-
synced_template.template_inputs_with_foreign.map(&:name).must_equal [
|
225
|
+
synced_template.template_inputs_with_foreign.map(&:name).must_equal ['hostname', 'count']
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'template export' do
|
230
|
+
let(:exportable_template) do
|
231
|
+
FactoryGirl.create(:job_template, :with_input)
|
232
|
+
end
|
233
|
+
|
234
|
+
let(:erb) do
|
235
|
+
exportable_template.to_erb
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'exports name' do
|
239
|
+
erb.must_match(/^name: #{exportable_template.name}$/)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'includes template inputs' do
|
243
|
+
erb.must_match(/^template_inputs:$/)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'includes template contents' do
|
247
|
+
erb.must_include exportable_template.template
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'is importable' do
|
251
|
+
erb
|
252
|
+
old_name = exportable_template.name
|
253
|
+
exportable_template.update_attributes(:name => "#{old_name}_renamed")
|
254
|
+
|
255
|
+
imported = JobTemplate.import!(erb)
|
256
|
+
imported.name.must_equal old_name
|
257
|
+
imported.template_inputs.first.to_export.must_equal exportable_template.template_inputs.first.to_export
|
226
258
|
end
|
227
259
|
end
|
228
260
|
|
@@ -8,15 +8,17 @@ describe ProxyLoadBalancer do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'load balances' do
|
11
|
-
|
12
|
-
|
11
|
+
count = 3
|
12
|
+
ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.expects(:tasks_count).raises.then.times(count - 1).returns(0)
|
13
|
+
proxies = FactoryGirl.create_list(:smart_proxy, count, :ssh)
|
13
14
|
|
14
|
-
|
15
|
-
found
|
16
|
-
not_yet_seen.delete(found)
|
15
|
+
available = proxies.reduce([]) do |found, _|
|
16
|
+
found << load_balancer.next(proxies)
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
available.count.must_equal count
|
20
|
+
available.uniq.count.must_equal count - 1
|
21
|
+
load_balancer.offline.count.must_equal 1
|
20
22
|
end
|
21
23
|
|
22
24
|
it 'returns nil for if no proxy is available' do
|
@@ -3,6 +3,21 @@ require 'test_plugin_helper'
|
|
3
3
|
describe TemplateInput do
|
4
4
|
let(:template_input) { FactoryGirl.build(:template_input) }
|
5
5
|
|
6
|
+
context 'export' do
|
7
|
+
before do
|
8
|
+
template_input.input_type = 'user'
|
9
|
+
template_input.options = "foo\nbar\nbaz"
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'exports type' do
|
13
|
+
template_input.to_export['input_type'].must_equal template_input.input_type
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'exports options' do
|
17
|
+
template_input.to_export['options'].must_equal template_input.options
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
6
21
|
context 'user input' do
|
7
22
|
before { template_input.input_type = 'user' }
|
8
23
|
it { assert template_input.user_template_input? }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_remote_execution
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Foreman Remote Execution team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -136,9 +136,11 @@ files:
|
|
136
136
|
- README.md
|
137
137
|
- Rakefile
|
138
138
|
- app/assets/javascripts/execution_interface.js
|
139
|
+
- app/assets/javascripts/job_templates.js
|
139
140
|
- app/assets/javascripts/template_input.js
|
140
141
|
- app/assets/javascripts/template_invocation.js
|
141
142
|
- app/assets/stylesheets/job_invocations.css.scss
|
143
|
+
- app/assets/stylesheets/modal_window.css.scss
|
142
144
|
- app/assets/stylesheets/template_invocation.css.scss
|
143
145
|
- app/controllers/api/v2/foreign_input_sets_controller.rb
|
144
146
|
- app/controllers/api/v2/job_invocations_controller.rb
|
@@ -161,6 +163,7 @@ files:
|
|
161
163
|
- app/mailers/.gitkeep
|
162
164
|
- app/models/concerns/foreman_remote_execution/bookmark_extensions.rb
|
163
165
|
- app/models/concerns/foreman_remote_execution/errors_flattener.rb
|
166
|
+
- app/models/concerns/foreman_remote_execution/exportable.rb
|
164
167
|
- app/models/concerns/foreman_remote_execution/foreman_tasks_task_extensions.rb
|
165
168
|
- app/models/concerns/foreman_remote_execution/foreman_tasks_triggering_extensions.rb
|
166
169
|
- app/models/concerns/foreman_remote_execution/host_extensions.rb
|
@@ -234,6 +237,7 @@ files:
|
|
234
237
|
- app/views/job_invocations/show.js.erb
|
235
238
|
- app/views/job_templates/_custom_tab_headers.html.erb
|
236
239
|
- app/views/job_templates/_custom_tabs.html.erb
|
240
|
+
- app/views/job_templates/_import_job_template_modal.html.erb
|
237
241
|
- app/views/job_templates/edit.html.erb
|
238
242
|
- app/views/job_templates/index.html.erb
|
239
243
|
- app/views/job_templates/new.html.erb
|
@@ -335,8 +339,15 @@ files:
|
|
335
339
|
- lib/tasks/foreman_remote_execution_tasks.rake
|
336
340
|
- locale/Makefile
|
337
341
|
- locale/action_names.rb
|
342
|
+
- locale/de/LC_MESSAGES/foreman_remote_execution.mo
|
343
|
+
- locale/de/foreman_remote_execution.po
|
344
|
+
- locale/en/LC_MESSAGES/foreman_remote_execution.mo
|
338
345
|
- locale/en/foreman_remote_execution.po
|
346
|
+
- locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo
|
347
|
+
- locale/en_GB/foreman_remote_execution.po
|
339
348
|
- locale/foreman_remote_execution.pot
|
349
|
+
- locale/fr/LC_MESSAGES/foreman_remote_execution.mo
|
350
|
+
- locale/fr/foreman_remote_execution.po
|
340
351
|
- locale/gemspec.rb
|
341
352
|
- test/factories/foreman_remote_execution_factories.rb
|
342
353
|
- test/functional/api/v2/foreign_input_sets_controller_test.rb
|
@@ -345,8 +356,10 @@ files:
|
|
345
356
|
- test/functional/api/v2/remote_execution_features_controller_test.rb
|
346
357
|
- test/functional/api/v2/template_inputs_controller_test.rb
|
347
358
|
- test/test_plugin_helper.rb
|
359
|
+
- test/unit/actions/run_host_job_test.rb
|
348
360
|
- test/unit/actions/run_hosts_job_test.rb
|
349
361
|
- test/unit/actions/run_proxy_command_test.rb
|
362
|
+
- test/unit/concerns/exportable_test.rb
|
350
363
|
- test/unit/concerns/host_extensions_test.rb
|
351
364
|
- test/unit/concerns/nic_extensions_test.rb
|
352
365
|
- test/unit/execution_task_status_mapper_test.rb
|
@@ -393,8 +406,10 @@ test_files:
|
|
393
406
|
- test/functional/api/v2/remote_execution_features_controller_test.rb
|
394
407
|
- test/functional/api/v2/template_inputs_controller_test.rb
|
395
408
|
- test/test_plugin_helper.rb
|
409
|
+
- test/unit/actions/run_host_job_test.rb
|
396
410
|
- test/unit/actions/run_hosts_job_test.rb
|
397
411
|
- test/unit/actions/run_proxy_command_test.rb
|
412
|
+
- test/unit/concerns/exportable_test.rb
|
398
413
|
- test/unit/concerns/host_extensions_test.rb
|
399
414
|
- test/unit/concerns/nic_extensions_test.rb
|
400
415
|
- test/unit/execution_task_status_mapper_test.rb
|