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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 837b065cbfe503343d7eedfb734f5a8d83ca1b5d358f990cc9741d9658b1f4dd
4
- data.tar.gz: 4ff9c2ad68f54faf3cca998b8cb54f74e75dfc3408dbbbfc527a82e88eaa7226
3
+ metadata.gz: a9ac5ddf16b74dec2deb0b11e6235c5074efd9ff22c69df60095998965785eb6
4
+ data.tar.gz: d3a6b6783e5dfe9905e6267b36289c3f2a56274dfc9500cec2947241ad8968da
5
5
  SHA512:
6
- metadata.gz: 9ccb9cd8c75c9e92d69fb22c6024ee242d2917f1410448f781aa0a561505a4e63faa72b9908355ed3672af55a1c4a0bbbeee928e8281388f873bd555093d72ed
7
- data.tar.gz: afadfd61e5a6bc01c1c60496e6a26b5fd5e0e2fd7a4ecaa21895480bbc9455924d0ac12109ed7a71106a7536759d0eaa69033f1f695f34399f3f9bbb862b51f0
6
+ metadata.gz: 39cb455b52d5d6290a6a79d3cd0f48fa9c52f9666a3f8f07b3d4e36c996bc2b16cf4657535f6b80d6be502a3a4c9a4f858821fd0ed94ea54bc4990c0efe430e7
7
+ data.tar.gz: 6c052042b3e9e3d829018dc78967e94aedfbd59db2745c9fe93048404729c9e01e14224c44064f7c294cf8fbb471be9dd9a455681339e4de69f378ddab9e3b3f
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require_self
3
+ *= require_tree .
4
+ */
@@ -1,4 +1,4 @@
1
- div.modal-body {
1
+ #previewHostsModal div.modal-body {
2
2
  overflow-y: auto;
3
3
  max-height: 500px;
4
4
  }
@@ -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, :targeting_type => job_invocation.targeting.targeting_type)
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.first %>
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/modal_window' %>
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,4 +1,4 @@
1
1
  <% javascript 'foreman_remote_execution/template_invocation' %>
2
- <% stylesheet 'foreman_remote_execution/template_invocation' %>
2
+ <% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
3
3
  <% title _('Job invocation') %>
4
4
  <%= render :partial => 'form' %>
@@ -1,5 +1,5 @@
1
1
  <% title @job_invocation.description %>
2
- <% stylesheet 'foreman_remote_execution/job_invocations' %>
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
 
@@ -1,4 +1,4 @@
1
- <% stylesheet 'foreman_remote_execution/modal_window' %>
1
+ <% stylesheet 'foreman_remote_execution/foreman_remote_execution' %>
2
2
 
3
3
  <!-- modal window -->
4
4
  <div class="modal fade" id="importJobTemplateModal" role="dialog" aria-hidden="true">
@@ -9,7 +9,7 @@
9
9
  :items => items)
10
10
  %>
11
11
 
12
- <% stylesheet 'foreman_remote_execution/template_invocation' %>
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/**/*', 'app/assets/stylesheets/**/*'].map do |f|
134
- f.split(File::SEPARATOR, 4).last.gsub(/\.scss\Z/, '')
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
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '2.0.3'.freeze
3
3
  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.2
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-10-29 00:00:00.000000000 Z
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/job_invocations.css.scss
151
- - app/assets/stylesheets/foreman_remote_execution/modal_window.css.scss
152
- - app/assets/stylesheets/foreman_remote_execution/template_invocation.css.scss
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