foreman_remote_execution 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/foreman_remote_execution/foreman_remote_execution.css +4 -0
- data/app/assets/stylesheets/foreman_remote_execution/{job_invocations.css.scss → job_invocations.scss} +0 -0
- data/app/assets/stylesheets/foreman_remote_execution/{modal_window.css.scss → modal_window.scss} +1 -1
- data/app/assets/stylesheets/foreman_remote_execution/{template_invocation.css.scss → template_invocation.scss} +0 -0
- data/app/models/job_invocation_composer.rb +24 -2
- data/app/models/setting/remote_execution.rb +8 -2
- data/app/views/job_invocations/_form.html.erb +2 -2
- data/app/views/job_invocations/_preview_hosts_modal.html.erb +1 -1
- data/app/views/job_invocations/new.html.erb +1 -1
- data/app/views/job_invocations/show.html.erb +1 -1
- data/app/views/job_templates/_import_job_template_modal.html.erb +1 -1
- data/app/views/template_invocations/show.html.erb +1 -1
- data/lib/foreman_remote_execution/engine.rb +6 -2
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/unit/job_invocation_composer_test.rb +50 -0
- data/webpack/react_app/components/jobInvocations/index.js +5 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9ac5ddf16b74dec2deb0b11e6235c5074efd9ff22c69df60095998965785eb6
|
4
|
+
data.tar.gz: d3a6b6783e5dfe9905e6267b36289c3f2a56274dfc9500cec2947241ad8968da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39cb455b52d5d6290a6a79d3cd0f48fa9c52f9666a3f8f07b3d4e36c996bc2b16cf4657535f6b80d6be502a3a4c9a4f858821fd0ed94ea54bc4990c0efe430e7
|
7
|
+
data.tar.gz: 6c052042b3e9e3d829018dc78967e94aedfbd59db2745c9fe93048404729c9e01e14224c44064f7c294cf8fbb471be9dd9a455681339e4de69f378ddab9e3b3f
|
File without changes
|
File without changes
|
@@ -203,7 +203,7 @@ class JobInvocationComposer
|
|
203
203
|
base = { :user_id => User.current.id }
|
204
204
|
if @host_ids
|
205
205
|
search_query = @host_ids.empty? ? 'name ^ ()' : Targeting.build_query_from_hosts(@host_ids)
|
206
|
-
base.merge(:search_query => search_query
|
206
|
+
base.merge(:search_query => search_query).merge(job_invocation.targeting.attributes.slice('targeting_type', 'randomized_ordering'))
|
207
207
|
else
|
208
208
|
base.merge job_invocation.targeting.attributes.slice('search_query', 'bookmark_id', 'targeting_type', 'randomized_ordering')
|
209
209
|
end
|
@@ -332,7 +332,7 @@ class JobInvocationComposer
|
|
332
332
|
# rubocop:disable Metrics/AbcSize
|
333
333
|
def compose
|
334
334
|
job_invocation.job_category = validate_job_category(params[:job_category])
|
335
|
-
job_invocation.job_category ||= available_job_categories.first if @set_defaults
|
335
|
+
job_invocation.job_category ||= resolve_job_category(available_job_categories.first) { |tempate| template.job_category } if @set_defaults
|
336
336
|
job_invocation.remote_execution_feature_id = params[:remote_execution_feature_id]
|
337
337
|
job_invocation.targeting = build_targeting
|
338
338
|
job_invocation.triggering = build_triggering
|
@@ -428,6 +428,16 @@ class JobInvocationComposer
|
|
428
428
|
(templates_for_provider(provider_type) & selected_job_templates).first
|
429
429
|
end
|
430
430
|
|
431
|
+
def resolve_job_category(default_category)
|
432
|
+
resolve_for_composer(default_category) { |form_template| form_template.job_category }
|
433
|
+
end
|
434
|
+
|
435
|
+
def resolve_job_template(provider_templates)
|
436
|
+
resolve_for_composer(provider_templates.first) do |form_template|
|
437
|
+
provider_templates.include?(form_template) ? form_template : provider_templates.first
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
431
441
|
def displayed_search_query
|
432
442
|
if @search_query.present?
|
433
443
|
@search_query
|
@@ -562,4 +572,16 @@ class JobInvocationComposer
|
|
562
572
|
def validate_host_ids(ids)
|
563
573
|
Host.authorized(Targeting::RESOLVE_PERMISSION, Host).where(:id => ids).pluck(:id)
|
564
574
|
end
|
575
|
+
|
576
|
+
def resolve_for_composer(default_value, &block)
|
577
|
+
setting_value = Setting['remote_execution_form_job_template']
|
578
|
+
return default_value unless setting_value
|
579
|
+
form_template = JobTemplate.find_by :name => setting_value
|
580
|
+
return default_value unless form_template
|
581
|
+
if block_given?
|
582
|
+
yield form_template
|
583
|
+
else
|
584
|
+
form_template
|
585
|
+
end
|
586
|
+
end
|
565
587
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Setting::RemoteExecution < Setting
|
2
2
|
|
3
|
-
::Setting::BLANK_ATTRS.concat %w{remote_execution_ssh_password remote_execution_ssh_key_passphrase remote_execution_sudo_password remote_execution_cockpit_url}
|
3
|
+
::Setting::BLANK_ATTRS.concat %w{remote_execution_ssh_password remote_execution_ssh_key_passphrase remote_execution_sudo_password remote_execution_cockpit_url remote_execution_form_job_template}
|
4
4
|
|
5
5
|
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
6
6
|
def self.default_settings
|
@@ -66,7 +66,13 @@ class Setting::RemoteExecution < Setting
|
|
66
66
|
N_('Where to find the Cockpit instance for the Web Console button. By default, no button is shown.'),
|
67
67
|
nil,
|
68
68
|
N_('Cockpit URL'),
|
69
|
-
nil)
|
69
|
+
nil),
|
70
|
+
self.set('remote_execution_form_job_template',
|
71
|
+
N_('Choose a job template that is pre-selected in job invocation form'),
|
72
|
+
'Run Command - SSH Default',
|
73
|
+
_('Form Job Template'),
|
74
|
+
nil,
|
75
|
+
{ :collection => proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] } })
|
70
76
|
]
|
71
77
|
end
|
72
78
|
# rubocop:enable AbcSize
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<%= f.fields_for 'providers' do |providers_fields| %>
|
17
17
|
<%= providers_fields.fields_for provider_type do |provider_type_fields| %>
|
18
18
|
<% templates_for_provider = @composer.templates_for_provider(provider_type) %>
|
19
|
-
<% selected_templates_per_provider[provider_type] = @composer.preselected_template_for_provider(provider_type) || templates_for_provider
|
19
|
+
<% selected_templates_per_provider[provider_type] = @composer.preselected_template_for_provider(provider_type) || @composer.resolve_job_template(templates_for_provider) %>
|
20
20
|
|
21
21
|
<%= selectable_f provider_type_fields, 'job_template_id', templates_for_provider.map { |t| [t.name, t.id] },
|
22
22
|
{ :selected => selected_templates_per_provider[provider_type].try(:id) },
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<% end %>
|
34
34
|
</span>
|
35
35
|
<%= selectable_f targeting_fields, :bookmark_id, @composer.available_bookmarks.map { |b| [b.name, b.id] }, :selected => @composer.targeting.bookmark_id, :include_blank => true %>
|
36
|
-
<%= textarea_f targeting_fields, :search_query, :value => @composer.displayed_search_query, :rows => 5 %>
|
36
|
+
<%= textarea_f targeting_fields, :search_query, :value => @composer.displayed_search_query, :rows => 5, :class => 'autocomplete-input form-control', :'data-url' => auto_complete_search_hosts_path %>
|
37
37
|
|
38
38
|
<div class="form-group ">
|
39
39
|
<label class="col-md-2 control-label"><%= _('Resolves to') %></label>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% stylesheet 'foreman_remote_execution/
|
1
|
+
<% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
|
2
2
|
|
3
3
|
<!-- modal window -->
|
4
4
|
<div class="modal fade" id="previewHostsModal" role="dialog" aria-hidden="true" data-url="<%= preview_hosts_job_invocations_path %>">
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% title @job_invocation.description %>
|
2
|
-
<% stylesheet 'foreman_remote_execution/
|
2
|
+
<% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
|
3
3
|
<% javascript 'charts', 'foreman_remote_execution/template_invocation' %>
|
4
4
|
<%= javascript_include_tag *webpack_asset_paths('foreman_remote_execution', :extension => 'js'), "data-turbolinks-track" => true, 'defer' => 'defer' %>
|
5
5
|
|
@@ -9,7 +9,7 @@
|
|
9
9
|
:items => items)
|
10
10
|
%>
|
11
11
|
|
12
|
-
<% stylesheet 'foreman_remote_execution/
|
12
|
+
<% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
|
13
13
|
<% javascript 'foreman_remote_execution/template_invocation' %>
|
14
14
|
|
15
15
|
<div id="title_action">
|
@@ -38,6 +38,8 @@ module ForemanRemoteExecution
|
|
38
38
|
|
39
39
|
apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
|
40
40
|
|
41
|
+
automatic_assets(false)
|
42
|
+
|
41
43
|
# Add permissions
|
42
44
|
security_block :foreman_remote_execution do
|
43
45
|
permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview, :export],
|
@@ -130,10 +132,12 @@ module ForemanRemoteExecution
|
|
130
132
|
# content twice.
|
131
133
|
assets_to_precompile =
|
132
134
|
Dir.chdir(root) do
|
133
|
-
Dir['app/assets/javascripts/**/*'
|
134
|
-
f.split(File::SEPARATOR, 4).last
|
135
|
+
Dir['app/assets/javascripts/**/*'].map do |f|
|
136
|
+
f.split(File::SEPARATOR, 4).last
|
135
137
|
end
|
136
138
|
end
|
139
|
+
assets_to_precompile += %w(foreman_remote_execution/foreman_remote_execution.css)
|
140
|
+
|
137
141
|
initializer 'foreman_remote_execution.assets.precompile' do |app|
|
138
142
|
app.config.assets.precompile += assets_to_precompile
|
139
143
|
end
|
@@ -811,5 +811,55 @@ class JobInvocationComposerTest < ActiveSupport::TestCase
|
|
811
811
|
assert created.targeting.resolved?
|
812
812
|
assert_equal job_invocation.template_invocations_host_ids, created.targeting.host_ids
|
813
813
|
end
|
814
|
+
|
815
|
+
it 'takes randomized_ordering from the original job invocation when rerunning failed' do
|
816
|
+
job_invocation.targeting.randomized_ordering = true
|
817
|
+
job_invocation.targeting.save!
|
818
|
+
host_ids = job_invocation.targeting.hosts.pluck(:id)
|
819
|
+
composer = JobInvocationComposer.from_job_invocation(job_invocation, :host_ids => host_ids)
|
820
|
+
assert composer.job_invocation.targeting.randomized_ordering
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
describe '#resolve_job_category and #resolve job_templates' do
|
825
|
+
let(:setting_template) { as_admin { FactoryBot.create(:job_template, :name => 'trying setting', :job_category => 'fluff') } }
|
826
|
+
let(:other_template) { as_admin { FactoryBot.create(:job_template, :name => 'trying something', :job_category => 'fluff') } }
|
827
|
+
let(:second_template) { as_admin { FactoryBot.create(:job_template, :name => 'second template', :job_category => 'fluff') } }
|
828
|
+
let(:params) { { :host_ids => nil, :targeting => { :targeting_type => "static_query", :bookmark_id => nil }, :job_template_id => setting_template.id } }
|
829
|
+
let(:composer) { JobInvocationComposer.from_api_params(params) }
|
830
|
+
|
831
|
+
context 'with template in setting present' do
|
832
|
+
before do
|
833
|
+
FactoryBot.create(
|
834
|
+
:setting,
|
835
|
+
:name => 'remote_execution_form_job_template',
|
836
|
+
:category => 'Setting::RemoteExecution',
|
837
|
+
:value => setting_template.name
|
838
|
+
)
|
839
|
+
end
|
840
|
+
|
841
|
+
it 'should resolve category to the setting value' do
|
842
|
+
assert_equal setting_template.job_category, composer.resolve_job_category('foo')
|
843
|
+
end
|
844
|
+
|
845
|
+
it 'should resolve template to the setting value' do
|
846
|
+
assert_equal setting_template, composer.resolve_job_template([other_template, setting_template])
|
847
|
+
end
|
848
|
+
|
849
|
+
it 'should respect provider templates when resolving templates' do
|
850
|
+
assert_equal other_template, composer.resolve_job_template([other_template])
|
851
|
+
end
|
852
|
+
end
|
853
|
+
|
854
|
+
context 'with template in setting absent' do
|
855
|
+
it 'should resolve category to the default value' do
|
856
|
+
category = 'foo'
|
857
|
+
assert_equal category, composer.resolve_job_category(category)
|
858
|
+
end
|
859
|
+
|
860
|
+
it 'should resolve template to the first in category' do
|
861
|
+
assert_equal other_template, composer.resolve_job_template([other_template, second_template])
|
862
|
+
end
|
863
|
+
end
|
814
864
|
end
|
815
865
|
end
|
@@ -7,6 +7,8 @@ import DonutChart from 'foremanReact/components/common/charts/DonutChart';
|
|
7
7
|
import AggregateStatus from './AggregateStatus/index.js';
|
8
8
|
import * as JobInvocationActions from '../../redux/actions/jobInvocations';
|
9
9
|
|
10
|
+
const colIndexOfMaxValue = columns => columns.reduce((iMax, x, i, arr) => (x[1] > arr[iMax][1] ? i : iMax), 0);
|
11
|
+
|
10
12
|
class JobInvocationContainer extends React.Component {
|
11
13
|
componentDidMount() {
|
12
14
|
const { startJobInvocationsPolling, data: { url } } = this.props;
|
@@ -16,10 +18,12 @@ class JobInvocationContainer extends React.Component {
|
|
16
18
|
|
17
19
|
render() {
|
18
20
|
const { jobInvocations, statuses } = this.props;
|
21
|
+
const iMax = colIndexOfMaxValue(jobInvocations);
|
19
22
|
|
20
23
|
return (
|
21
24
|
<div id="job_invocations_chart_container">
|
22
|
-
<DonutChart data={Immutable.asMutable(jobInvocations)}
|
25
|
+
<DonutChart data={Immutable.asMutable(jobInvocations)}
|
26
|
+
title={{type: 'percent', secondary: (jobInvocations[iMax] || [])[0]}}/>
|
23
27
|
<AggregateStatus statuses={statuses} />
|
24
28
|
</div>
|
25
29
|
);
|
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: 2.0.
|
4
|
+
version: 2.0.3
|
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: 2019-
|
11
|
+
date: 2019-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -147,9 +147,10 @@ files:
|
|
147
147
|
- app/assets/javascripts/foreman_remote_execution/job_templates.js
|
148
148
|
- app/assets/javascripts/foreman_remote_execution/template_input.js
|
149
149
|
- app/assets/javascripts/foreman_remote_execution/template_invocation.js
|
150
|
-
- app/assets/stylesheets/foreman_remote_execution/
|
151
|
-
- app/assets/stylesheets/foreman_remote_execution/
|
152
|
-
- app/assets/stylesheets/foreman_remote_execution/
|
150
|
+
- app/assets/stylesheets/foreman_remote_execution/foreman_remote_execution.css
|
151
|
+
- app/assets/stylesheets/foreman_remote_execution/job_invocations.scss
|
152
|
+
- app/assets/stylesheets/foreman_remote_execution/modal_window.scss
|
153
|
+
- app/assets/stylesheets/foreman_remote_execution/template_invocation.scss
|
153
154
|
- app/controllers/api/v2/foreign_input_sets_controller.rb
|
154
155
|
- app/controllers/api/v2/job_invocations_controller.rb
|
155
156
|
- app/controllers/api/v2/job_templates_controller.rb
|