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
@@ -7,7 +7,7 @@ describe JobInvocationComposer do
|
|
7
7
|
permission1 = FactoryGirl.create(:permission, :name => 'view_job_templates', :resource_type => 'JobTemplate')
|
8
8
|
permission2 = Permission.find_by_name('view_bookmarks')
|
9
9
|
permission3 = Permission.find_by_name('view_hosts')
|
10
|
-
filter1 = FactoryGirl.build(:filter, :permissions => [permission1], :search => 'name ~
|
10
|
+
filter1 = FactoryGirl.build(:filter, :permissions => [permission1], :search => 'name ~ trying*')
|
11
11
|
filter2 = FactoryGirl.build(:filter, :permissions => [permission2])
|
12
12
|
filter3 = FactoryGirl.build(:filter, :permissions => [permission3])
|
13
13
|
filter1.save
|
@@ -21,16 +21,16 @@ describe JobInvocationComposer do
|
|
21
21
|
User.current.save
|
22
22
|
end
|
23
23
|
|
24
|
-
let(:
|
25
|
-
let(:
|
26
|
-
let(:
|
27
|
-
let(:unauthorized_job_template_1) { FactoryGirl.create(:job_template, :
|
28
|
-
let(:unauthorized_job_template_2) { FactoryGirl.create(:job_template, :
|
24
|
+
let(:trying_job_template_1) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying1', :provider_type => 'SSH') }
|
25
|
+
let(:trying_job_template_2) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_2', :name => 'trying2', :provider_type => 'Mcollective') }
|
26
|
+
let(:trying_job_template_3) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying3', :provider_type => 'SSH') }
|
27
|
+
let(:unauthorized_job_template_1) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'unauth1', :provider_type => 'SSH') }
|
28
|
+
let(:unauthorized_job_template_2) { FactoryGirl.create(:job_template, :job_category => 'unauthorized_job_template_2', :name => 'unauth2', :provider_type => 'Ansible') }
|
29
29
|
|
30
30
|
|
31
|
-
let(:input1) { FactoryGirl.create(:template_input, :template =>
|
32
|
-
let(:input2) { FactoryGirl.create(:template_input, :template =>
|
33
|
-
let(:input3) { FactoryGirl.create(:template_input, :template =>
|
31
|
+
let(:input1) { FactoryGirl.create(:template_input, :template => trying_job_template_1, :input_type => 'user') }
|
32
|
+
let(:input2) { FactoryGirl.create(:template_input, :template => trying_job_template_3, :input_type => 'user') }
|
33
|
+
let(:input3) { FactoryGirl.create(:template_input, :template => trying_job_template_1, :input_type => 'user', :required => true) }
|
34
34
|
let(:unauthorized_input1) { FactoryGirl.create(:template_input, :template => unauthorized_job_template_1, :input_type => 'user') }
|
35
35
|
|
36
36
|
let(:ansible_params) { { } }
|
@@ -45,44 +45,44 @@ describe JobInvocationComposer do
|
|
45
45
|
describe '#available_templates' do
|
46
46
|
it 'obeys authorization' do
|
47
47
|
composer # lazy load composer before stubbing
|
48
|
-
JobTemplate.expects(:authorized).with(:view_job_templates).returns(JobTemplate.
|
48
|
+
JobTemplate.expects(:authorized).with(:view_job_templates).returns(JobTemplate.where({}))
|
49
49
|
composer.available_templates
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
context 'job templates exist' do
|
54
54
|
before do
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
trying_job_template_1
|
56
|
+
trying_job_template_2
|
57
|
+
trying_job_template_3
|
58
58
|
unauthorized_job_template_1
|
59
59
|
unauthorized_job_template_2
|
60
60
|
end
|
61
61
|
|
62
|
-
describe '#available_templates_for(
|
62
|
+
describe '#available_templates_for(job_category)' do
|
63
63
|
it 'find the templates only for a given job name' do
|
64
|
-
results = composer.available_templates_for(
|
65
|
-
results.must_include
|
66
|
-
results.wont_include
|
64
|
+
results = composer.available_templates_for(trying_job_template_1.job_category)
|
65
|
+
results.must_include trying_job_template_1
|
66
|
+
results.wont_include trying_job_template_2
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'it respects view permissions' do
|
70
|
-
results = composer.available_templates_for(
|
70
|
+
results = composer.available_templates_for(trying_job_template_1.job_category)
|
71
71
|
results.wont_include unauthorized_job_template_1
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
describe '#
|
76
|
-
let(:
|
75
|
+
describe '#available_job_categories' do
|
76
|
+
let(:job_categories) { composer.available_job_categories }
|
77
77
|
|
78
78
|
it 'find only job names that user is granted to view' do
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
job_categories.must_include trying_job_template_1.job_category
|
80
|
+
job_categories.must_include trying_job_template_2.job_category
|
81
|
+
job_categories.wont_include unauthorized_job_template_2.job_category
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'every job name is listed just once' do
|
85
|
-
|
85
|
+
job_categories.uniq.must_equal job_categories
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
@@ -90,8 +90,8 @@ describe JobInvocationComposer do
|
|
90
90
|
let(:provider_types) { composer.available_provider_types }
|
91
91
|
|
92
92
|
it 'finds only providers which user is granted to view' do
|
93
|
-
composer.job_invocation.
|
94
|
-
provider_types.must_include '
|
93
|
+
composer.job_invocation.job_category = 'trying_job_template_1'
|
94
|
+
provider_types.must_include 'SSH'
|
95
95
|
provider_types.wont_include 'Mcollective'
|
96
96
|
provider_types.wont_include 'Ansible'
|
97
97
|
end
|
@@ -115,7 +115,7 @@ describe JobInvocationComposer do
|
|
115
115
|
end
|
116
116
|
|
117
117
|
context 'params contains job template ids' do
|
118
|
-
let(:ssh_params) { { :job_template_id =>
|
118
|
+
let(:ssh_params) { { :job_template_id => trying_job_template_1.id.to_s } }
|
119
119
|
let(:ansible_params) { { :job_template_id => '' } }
|
120
120
|
let(:mcollective_params) { { :job_template_id => '' } }
|
121
121
|
let(:params) { { :job_invocation => providers_params }.with_indifferent_access }
|
@@ -130,58 +130,34 @@ describe JobInvocationComposer do
|
|
130
130
|
|
131
131
|
describe '#needs_provider_type_selection?' do
|
132
132
|
it 'returns true if there are more than one providers respecting authorization' do
|
133
|
-
composer.stubs(:available_provider_types => [ '
|
133
|
+
composer.stubs(:available_provider_types => [ 'SSH', 'Ansible' ])
|
134
134
|
assert composer.needs_provider_type_selection?
|
135
135
|
end
|
136
136
|
|
137
137
|
it 'returns false if there is one provider' do
|
138
|
-
composer.stubs(:available_provider_types => [ '
|
138
|
+
composer.stubs(:available_provider_types => [ 'SSH' ])
|
139
139
|
refute composer.needs_provider_type_selection?
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
-
describe '#only_one_template_available?' do
|
144
|
-
context 'composer needs provider type selection' do
|
145
|
-
before { composer.stubs(:needs_provider_type_selection? => true) }
|
146
|
-
|
147
|
-
it 'returns false because it means we have at least two providers so we need to be able to disable it per provider' do
|
148
|
-
refute composer.only_one_template_available?
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
context 'composer does not need provider type selection' do
|
153
|
-
before { composer.stubs(:needs_provider_type_selection? => false) }
|
154
|
-
|
155
|
-
it 'returns true if there is only one template for the provider' do
|
156
|
-
composer.stubs(:templates_for_provider => [ testing_job_template_1 ])
|
157
|
-
assert composer.only_one_template_available?
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'returns false if there is more than one template for the provider' do
|
161
|
-
composer.stubs(:templates_for_provider => [ testing_job_template_1, testing_job_template_3 ])
|
162
|
-
refute composer.only_one_template_available?
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
143
|
describe '#displayed_provider_types' do
|
168
144
|
# nothing to test yet
|
169
145
|
end
|
170
146
|
|
171
147
|
describe '#templates_for_provider(provider_type)' do
|
172
148
|
it 'returns all templates for a given provider respecting template permissions' do
|
173
|
-
|
174
|
-
result = composer.templates_for_provider('
|
175
|
-
result.must_include
|
176
|
-
result.must_include
|
149
|
+
trying_job_template_4 = FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying4', :provider_type => 'Ansible')
|
150
|
+
result = composer.templates_for_provider('SSH')
|
151
|
+
result.must_include trying_job_template_1
|
152
|
+
result.must_include trying_job_template_3
|
177
153
|
result.wont_include unauthorized_job_template_1
|
178
|
-
result.wont_include
|
154
|
+
result.wont_include trying_job_template_4
|
179
155
|
|
180
156
|
result = composer.templates_for_provider('Ansible')
|
181
|
-
result.wont_include
|
182
|
-
result.wont_include
|
157
|
+
result.wont_include trying_job_template_1
|
158
|
+
result.wont_include trying_job_template_3
|
183
159
|
result.wont_include unauthorized_job_template_2
|
184
|
-
result.must_include
|
160
|
+
result.must_include trying_job_template_4
|
185
161
|
end
|
186
162
|
end
|
187
163
|
|
@@ -191,9 +167,9 @@ describe JobInvocationComposer do
|
|
191
167
|
end
|
192
168
|
|
193
169
|
context 'extra unavailable templates id were selected' do
|
194
|
-
let(:unauthorized) { FactoryGirl.create(:job_template, :
|
195
|
-
let(:mcollective_authorized) { FactoryGirl.create(:job_template, :
|
196
|
-
let(:ssh_params) { { :job_template_id =>
|
170
|
+
let(:unauthorized) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'unauth3', :provider_type => 'Ansible') }
|
171
|
+
let(:mcollective_authorized) { FactoryGirl.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying4', :provider_type => 'Mcollective') }
|
172
|
+
let(:ssh_params) { { :job_template_id => trying_job_template_1.id.to_s } }
|
197
173
|
let(:ansible_params) { { :job_template_id => unauthorized.id.to_s } }
|
198
174
|
let(:mcollective_params) { { :job_template_id => mcollective_authorized.id.to_s } }
|
199
175
|
let(:params) { { :job_invocation => providers_params }.with_indifferent_access }
|
@@ -205,44 +181,44 @@ describe JobInvocationComposer do
|
|
205
181
|
|
206
182
|
it 'contains only authorized template specified in params' do
|
207
183
|
mcollective_authorized # make sure mcollective_authorized exists
|
208
|
-
composer.selected_job_templates.must_include
|
184
|
+
composer.selected_job_templates.must_include trying_job_template_1
|
209
185
|
composer.selected_job_templates.must_include mcollective_authorized
|
210
|
-
composer.selected_job_templates.wont_include
|
186
|
+
composer.selected_job_templates.wont_include trying_job_template_3
|
211
187
|
end
|
212
188
|
end
|
213
189
|
end
|
214
190
|
|
215
|
-
describe '#
|
191
|
+
describe '#preselected_template_for_provider(provider_type)' do
|
216
192
|
context 'none template was selected through params' do
|
217
|
-
it 'returns
|
218
|
-
|
193
|
+
it 'returns nil' do
|
194
|
+
composer.preselected_template_for_provider('SSH').must_be_nil
|
219
195
|
end
|
220
196
|
end
|
221
197
|
|
222
198
|
context 'available template was selected for a specified provider through params' do
|
223
|
-
let(:ssh_params) { { :job_template_id =>
|
199
|
+
let(:ssh_params) { { :job_template_id => trying_job_template_1.id.to_s } }
|
224
200
|
let(:params) { { :job_invocation => providers_params }.with_indifferent_access }
|
225
201
|
|
226
|
-
it 'returns
|
227
|
-
|
202
|
+
it 'returns the selected template because it is available for provider' do
|
203
|
+
composer.preselected_template_for_provider('SSH').must_equal trying_job_template_1
|
228
204
|
end
|
229
205
|
end
|
230
206
|
end
|
231
207
|
|
232
|
-
describe '#template_invocations' do
|
208
|
+
describe '#pattern template_invocations' do
|
233
209
|
let(:ssh_params) do
|
234
|
-
{ :job_template_id =>
|
210
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
235
211
|
:job_templates => {
|
236
|
-
|
212
|
+
trying_job_template_1.id.to_s => {
|
237
213
|
:input_values => { input1.id.to_s => { :value => 'value1' }, unauthorized_input1.id.to_s => { :value => 'dropped' } }
|
238
214
|
}
|
239
215
|
}
|
240
216
|
}
|
241
217
|
end
|
242
218
|
let(:params) { { :job_invocation => { :providers => { :ssh => ssh_params } } }.with_indifferent_access }
|
243
|
-
let(:invocations) { composer.
|
219
|
+
let(:invocations) { composer.pattern_template_invocations }
|
244
220
|
|
245
|
-
it 'builds template invocations based on passed params and it filters out wrong inputs' do
|
221
|
+
it 'builds pattern template invocations based on passed params and it filters out wrong inputs' do
|
246
222
|
invocations.size.must_equal 1
|
247
223
|
invocations.first.input_values.size.must_equal 1
|
248
224
|
invocations.first.input_values.first.value.must_equal 'value1'
|
@@ -251,9 +227,9 @@ describe JobInvocationComposer do
|
|
251
227
|
|
252
228
|
describe '#effective_user' do
|
253
229
|
let(:ssh_params) do
|
254
|
-
{ :job_template_id =>
|
230
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
255
231
|
:job_templates => {
|
256
|
-
|
232
|
+
trying_job_template_1.id.to_s => {
|
257
233
|
:effective_user => invocation_effective_user
|
258
234
|
}
|
259
235
|
}
|
@@ -261,8 +237,8 @@ describe JobInvocationComposer do
|
|
261
237
|
end
|
262
238
|
let(:params) { { :job_invocation => { :providers => { :ssh => ssh_params } } }.with_indifferent_access }
|
263
239
|
let(:template_invocation) do
|
264
|
-
|
265
|
-
composer.
|
240
|
+
trying_job_template_1.effective_user.update_attributes(:overridable => overridable, :value => 'template user')
|
241
|
+
composer.pattern_template_invocations.first
|
266
242
|
end
|
267
243
|
|
268
244
|
before do
|
@@ -280,7 +256,7 @@ describe JobInvocationComposer do
|
|
280
256
|
|
281
257
|
context 'when overridable and not provided' do
|
282
258
|
let(:overridable) { true }
|
283
|
-
let(:invocation_effective_user) {
|
259
|
+
let(:invocation_effective_user) { '' }
|
284
260
|
|
285
261
|
it 'takes the value from the job template' do
|
286
262
|
template_invocation.effective_user.must_equal 'template user'
|
@@ -289,7 +265,7 @@ describe JobInvocationComposer do
|
|
289
265
|
|
290
266
|
context 'when not overridable and provided' do
|
291
267
|
let(:overridable) { false }
|
292
|
-
let(:invocation_effective_user) {
|
268
|
+
let(:invocation_effective_user) { 'invocation user' }
|
293
269
|
|
294
270
|
it 'takes the value from the job template' do
|
295
271
|
template_invocation.effective_user.must_equal 'template user'
|
@@ -347,7 +323,7 @@ describe JobInvocationComposer do
|
|
347
323
|
describe '#available_bookmarks' do
|
348
324
|
it 'obeys authorization' do
|
349
325
|
composer
|
350
|
-
Bookmark.expects(:authorized).with(:view_bookmarks).returns(Bookmark.
|
326
|
+
Bookmark.expects(:authorized).with(:view_bookmarks).returns(Bookmark.where({}))
|
351
327
|
composer.available_bookmarks
|
352
328
|
end
|
353
329
|
|
@@ -372,7 +348,7 @@ describe JobInvocationComposer do
|
|
372
348
|
|
373
349
|
it 'obeys authorization' do
|
374
350
|
composer.stubs(:displayed_search_query => "name = #{host.name}")
|
375
|
-
Host.expects(:authorized).with(:view_hosts, Host).returns(Host.
|
351
|
+
Host.expects(:authorized).with(:view_hosts, Host).returns(Host.where({}))
|
376
352
|
composer.targeted_hosts_count
|
377
353
|
end
|
378
354
|
|
@@ -382,7 +358,7 @@ describe JobInvocationComposer do
|
|
382
358
|
end
|
383
359
|
|
384
360
|
it 'returns 0 for queries with syntax errors' do
|
385
|
-
composer.stubs(:displayed_search_query =>
|
361
|
+
composer.stubs(:displayed_search_query => 'name = ')
|
386
362
|
composer.targeted_hosts_count.must_equal 0
|
387
363
|
end
|
388
364
|
|
@@ -393,7 +369,7 @@ describe JobInvocationComposer do
|
|
393
369
|
end
|
394
370
|
|
395
371
|
describe '#template_invocation_input_value_for(input)' do
|
396
|
-
let(:value1) { composer.template_invocation_input_value_for(input1) }
|
372
|
+
let(:value1) { composer.template_invocation_input_value_for(trying_job_template_1, input1) }
|
397
373
|
it 'returns new empty input value if there is no invocation' do
|
398
374
|
assert value1.new_record?
|
399
375
|
value1.value.must_be_empty
|
@@ -401,9 +377,9 @@ describe JobInvocationComposer do
|
|
401
377
|
|
402
378
|
context 'there are invocations without input values for a given input' do
|
403
379
|
let(:ssh_params) do
|
404
|
-
{ :job_template_id =>
|
380
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
405
381
|
:job_templates => {
|
406
|
-
|
382
|
+
trying_job_template_1.id.to_s => {
|
407
383
|
:input_values => { }
|
408
384
|
} } }
|
409
385
|
end
|
@@ -417,9 +393,9 @@ describe JobInvocationComposer do
|
|
417
393
|
|
418
394
|
context 'there are invocations with input values for a given input' do
|
419
395
|
let(:ssh_params) do
|
420
|
-
{ :job_template_id =>
|
396
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
421
397
|
:job_templates => {
|
422
|
-
|
398
|
+
trying_job_template_1.id.to_s => {
|
423
399
|
:input_values => { input1.id.to_s => { :value => 'value1' } }
|
424
400
|
} } }
|
425
401
|
end
|
@@ -434,9 +410,9 @@ describe JobInvocationComposer do
|
|
434
410
|
describe '#valid?' do
|
435
411
|
let(:host) { FactoryGirl.create(:host) }
|
436
412
|
let(:ssh_params) do
|
437
|
-
{ :job_template_id =>
|
413
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
438
414
|
:job_templates => {
|
439
|
-
|
415
|
+
trying_job_template_1.id.to_s => {
|
440
416
|
:input_values => { input1.id.to_s => { :value => 'value1' } }
|
441
417
|
} } }
|
442
418
|
end
|
@@ -448,7 +424,7 @@ describe JobInvocationComposer do
|
|
448
424
|
composer
|
449
425
|
composer.job_invocation.expects(:valid?).returns(false)
|
450
426
|
composer.targeting.expects(:valid?).returns(false)
|
451
|
-
composer.
|
427
|
+
composer.pattern_template_invocations.each { |invocation| invocation.expects(:valid?).returns(false) }
|
452
428
|
refute composer.valid?
|
453
429
|
end
|
454
430
|
end
|
@@ -477,11 +453,11 @@ describe JobInvocationComposer do
|
|
477
453
|
end
|
478
454
|
end
|
479
455
|
|
480
|
-
describe '#
|
481
|
-
it 'triggers
|
456
|
+
describe '#job_category' do
|
457
|
+
it 'triggers job_category on job_invocation' do
|
482
458
|
composer
|
483
|
-
composer.job_invocation.expects(:
|
484
|
-
composer.
|
459
|
+
composer.job_invocation.expects(:job_category)
|
460
|
+
composer.job_category
|
485
461
|
end
|
486
462
|
end
|
487
463
|
|
@@ -496,9 +472,9 @@ describe JobInvocationComposer do
|
|
496
472
|
describe '#compose_from_invocation(existing_invocation)' do
|
497
473
|
let(:host) { FactoryGirl.create(:host) }
|
498
474
|
let(:ssh_params) do
|
499
|
-
{ :job_template_id =>
|
475
|
+
{ :job_template_id => trying_job_template_1.id.to_s,
|
500
476
|
:job_templates => {
|
501
|
-
|
477
|
+
trying_job_template_1.id.to_s => {
|
502
478
|
:input_values => { input1.id.to_s => { :value => 'value1' } }
|
503
479
|
} } }
|
504
480
|
end
|
@@ -522,7 +498,7 @@ describe JobInvocationComposer do
|
|
522
498
|
end
|
523
499
|
|
524
500
|
it 'sets the same job name' do
|
525
|
-
new_composer.
|
501
|
+
new_composer.job_category.must_equal existing.job_category
|
526
502
|
end
|
527
503
|
|
528
504
|
it 'builds new targeting object which keeps search query' do
|
@@ -531,11 +507,11 @@ describe JobInvocationComposer do
|
|
531
507
|
end
|
532
508
|
|
533
509
|
it 'keeps job template ids' do
|
534
|
-
new_composer.job_template_ids.must_equal existing.
|
510
|
+
new_composer.job_template_ids.must_equal existing.pattern_template_invocations.map(&:template_id)
|
535
511
|
end
|
536
512
|
|
537
513
|
it 'keeps template invocations and their values' do
|
538
|
-
new_composer.
|
514
|
+
new_composer.pattern_template_invocations.size.must_equal existing.pattern_template_invocations.size
|
539
515
|
end
|
540
516
|
|
541
517
|
end
|
@@ -549,153 +525,153 @@ describe JobInvocationComposer do
|
|
549
525
|
context 'with targeting from bookmark' do
|
550
526
|
|
551
527
|
before do
|
552
|
-
[
|
528
|
+
[trying_job_template_1, trying_job_template_3] # mentioning templates we want to have initialized in the test
|
553
529
|
end
|
554
530
|
|
555
531
|
let(:params) do
|
556
|
-
{ :
|
557
|
-
:job_template_id =>
|
558
|
-
:targeting_type =>
|
532
|
+
{ :job_category => trying_job_template_1.job_category,
|
533
|
+
:job_template_id => trying_job_template_1.id,
|
534
|
+
:targeting_type => 'static_query',
|
559
535
|
:bookmark_id => bookmark.id }
|
560
536
|
end
|
561
537
|
|
562
|
-
it
|
538
|
+
it 'creates invocation with a bookmark' do
|
563
539
|
assert composer.save!
|
564
540
|
assert_equal bookmark, composer.job_invocation.targeting.bookmark
|
565
541
|
assert_equal composer.job_invocation.targeting.user, User.current
|
566
|
-
refute_empty composer.job_invocation.
|
542
|
+
refute_empty composer.job_invocation.pattern_template_invocations
|
567
543
|
end
|
568
544
|
end
|
569
545
|
|
570
|
-
context
|
546
|
+
context 'with targeting from search query' do
|
571
547
|
let(:params) do
|
572
|
-
{ :
|
573
|
-
:job_template_id =>
|
574
|
-
:targeting_type =>
|
575
|
-
:search_query =>
|
548
|
+
{ :job_category => trying_job_template_1.job_category,
|
549
|
+
:job_template_id => trying_job_template_1.id,
|
550
|
+
:targeting_type => 'static_query',
|
551
|
+
:search_query => 'some hosts' }
|
576
552
|
end
|
577
553
|
|
578
|
-
it
|
554
|
+
it 'creates invocation with a search query' do
|
579
555
|
assert composer.save!
|
580
|
-
assert_equal
|
581
|
-
refute_empty composer.job_invocation.
|
556
|
+
assert_equal 'some hosts', composer.job_invocation.targeting.search_query
|
557
|
+
refute_empty composer.job_invocation.pattern_template_invocations
|
582
558
|
end
|
583
559
|
end
|
584
560
|
|
585
|
-
context
|
561
|
+
context 'with with inputs' do
|
586
562
|
let(:params) do
|
587
|
-
{ :
|
588
|
-
:job_template_id =>
|
589
|
-
:targeting_type =>
|
590
|
-
:search_query =>
|
591
|
-
:inputs => {input1.name =>
|
563
|
+
{ :job_category => trying_job_template_1.job_category,
|
564
|
+
:job_template_id => trying_job_template_1.id,
|
565
|
+
:targeting_type => 'static_query',
|
566
|
+
:search_query => 'some hosts',
|
567
|
+
:inputs => {input1.name => 'some_value'}}
|
592
568
|
end
|
593
569
|
|
594
|
-
it
|
570
|
+
it 'finds the inputs by name' do
|
595
571
|
assert composer.save!
|
596
|
-
assert_equal 1, composer.
|
572
|
+
assert_equal 1, composer.pattern_template_invocations.first.input_values.count
|
597
573
|
end
|
598
574
|
end
|
599
575
|
|
600
|
-
context
|
576
|
+
context 'with effective user' do
|
601
577
|
let(:params) do
|
602
|
-
{ :
|
603
|
-
:job_template_id =>
|
578
|
+
{ :job_category => trying_job_template_1.job_category,
|
579
|
+
:job_template_id => trying_job_template_1.id,
|
604
580
|
:effective_user => 'invocation user',
|
605
|
-
:targeting_type =>
|
606
|
-
:search_query =>
|
607
|
-
:inputs => {input1.name =>
|
581
|
+
:targeting_type => 'static_query',
|
582
|
+
:search_query => 'some hosts',
|
583
|
+
:inputs => {input1.name => 'some_value'}}
|
608
584
|
end
|
609
585
|
|
610
|
-
let(:template_invocation) { composer.job_invocation.
|
586
|
+
let(:template_invocation) { composer.job_invocation.pattern_template_invocations.first }
|
611
587
|
|
612
|
-
it
|
588
|
+
it 'sets the effective user based on the input' do
|
613
589
|
assert composer.save!
|
614
590
|
template_invocation.effective_user.must_equal 'invocation user'
|
615
591
|
end
|
616
592
|
end
|
617
593
|
|
618
|
-
context
|
594
|
+
context 'with invalid targeting' do
|
619
595
|
let(:params) do
|
620
|
-
{ :
|
621
|
-
:job_template_id =>
|
622
|
-
:search_query =>
|
623
|
-
:inputs => {input1.name =>
|
596
|
+
{ :job_category => trying_job_template_1.job_category,
|
597
|
+
:job_template_id => trying_job_template_1.id,
|
598
|
+
:search_query => 'some hosts',
|
599
|
+
:inputs => {input1.name => 'some_value'}}
|
624
600
|
end
|
625
601
|
|
626
|
-
it
|
602
|
+
it 'handles errors' do
|
627
603
|
assert_raises(ActiveRecord::RecordNotSaved) do
|
628
604
|
composer.save!
|
629
605
|
end
|
630
606
|
end
|
631
607
|
end
|
632
608
|
|
633
|
-
context
|
609
|
+
context 'with invalid bookmark and search query' do
|
634
610
|
let(:params) do
|
635
|
-
{ :
|
636
|
-
:job_template_id =>
|
637
|
-
:targeting_type =>
|
638
|
-
:search_query =>
|
611
|
+
{ :job_category => trying_job_template_1.job_category,
|
612
|
+
:job_template_id => trying_job_template_1.id,
|
613
|
+
:targeting_type => 'static_query',
|
614
|
+
:search_query => 'some hosts',
|
639
615
|
:bookmark_id => bookmark.id,
|
640
|
-
:inputs => {input1.name =>
|
616
|
+
:inputs => {input1.name => 'some_value'}}
|
641
617
|
end
|
642
618
|
|
643
|
-
it
|
619
|
+
it 'handles errors' do
|
644
620
|
assert_raises(Foreman::Exception) do
|
645
621
|
JobInvocationComposer.from_api_params(params)
|
646
622
|
end
|
647
623
|
end
|
648
624
|
end
|
649
625
|
|
650
|
-
context
|
626
|
+
context 'with invalid inputs' do
|
651
627
|
let(:params) do
|
652
|
-
{ :
|
653
|
-
:job_template_id =>
|
654
|
-
:targeting_type =>
|
655
|
-
:search_query =>
|
628
|
+
{ :job_category => trying_job_template_1.job_category,
|
629
|
+
:job_template_id => trying_job_template_1.id,
|
630
|
+
:targeting_type => 'static_query',
|
631
|
+
:search_query => 'some hosts',
|
656
632
|
:inputs => {input3.name => nil}}
|
657
633
|
end
|
658
634
|
|
659
|
-
it
|
635
|
+
it 'handles errors' do
|
660
636
|
error = assert_raises(ActiveRecord::RecordNotSaved) do
|
661
637
|
composer.save!
|
662
638
|
end
|
663
|
-
error.message.must_include "Template #{
|
639
|
+
error.message.must_include "Template #{trying_job_template_1.name}: Input #{input3.name.downcase}: Value can't be blank"
|
664
640
|
end
|
665
641
|
end
|
666
642
|
|
667
|
-
context
|
643
|
+
context 'with empty values for non-required inputs' do
|
668
644
|
let(:params) do
|
669
|
-
{ :
|
670
|
-
:job_template_id =>
|
671
|
-
:targeting_type =>
|
672
|
-
:search_query =>
|
673
|
-
:inputs => {input3.name =>
|
645
|
+
{ :job_category => trying_job_template_1.job_category,
|
646
|
+
:job_template_id => trying_job_template_1.id,
|
647
|
+
:targeting_type => 'static_query',
|
648
|
+
:search_query => 'some hosts',
|
649
|
+
:inputs => {input3.name => 'some value'}}
|
674
650
|
end
|
675
651
|
|
676
|
-
it
|
652
|
+
it 'accepts the params' do
|
677
653
|
composer.save!
|
678
654
|
refute composer.job_invocation.new_record?
|
679
655
|
end
|
680
656
|
end
|
681
657
|
|
682
|
-
context
|
658
|
+
context 'with missing required inputs' do
|
683
659
|
let(:params) do
|
684
|
-
{ :
|
685
|
-
:job_template_id =>
|
686
|
-
:targeting_type =>
|
687
|
-
:search_query =>
|
688
|
-
:inputs => {input1.name =>
|
660
|
+
{ :job_category => trying_job_template_1.job_category,
|
661
|
+
:job_template_id => trying_job_template_1.id,
|
662
|
+
:targeting_type => 'static_query',
|
663
|
+
:search_query => 'some hosts',
|
664
|
+
:inputs => {input1.name => 'some_value'}}
|
689
665
|
end
|
690
666
|
|
691
|
-
it
|
667
|
+
it 'handles errors' do
|
692
668
|
input3.must_be :required
|
693
669
|
|
694
670
|
error = assert_raises(ActiveRecord::RecordNotSaved) do
|
695
671
|
composer.save!
|
696
672
|
end
|
697
673
|
|
698
|
-
error.message.must_include "Template #{
|
674
|
+
error.message.must_include "Template #{trying_job_template_1.name}: Not all required inputs have values. Missing inputs: #{input3.name}"
|
699
675
|
end
|
700
676
|
end
|
701
677
|
end
|