foreman_remote_execution 2.0.2 → 2.0.3
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 +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
|