foreman_remote_execution 0.1.2 → 0.2.1

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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.rubocop_todo.yml +0 -6
  4. data/app/assets/javascripts/template_input.js +5 -0
  5. data/app/assets/javascripts/template_invocation.js +44 -12
  6. data/app/controllers/api/v2/foreign_input_sets_controller.rb +80 -0
  7. data/app/controllers/api/v2/job_invocations_controller.rb +28 -14
  8. data/app/controllers/api/v2/job_templates_controller.rb +24 -20
  9. data/app/controllers/api/v2/template_inputs_controller.rb +10 -7
  10. data/app/controllers/job_invocations_controller.rb +18 -6
  11. data/app/controllers/job_templates_controller.rb +14 -4
  12. data/app/controllers/template_invocations_controller.rb +5 -3
  13. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +1 -1
  14. data/app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb +19 -0
  15. data/app/helpers/remote_execution_helper.rb +88 -39
  16. data/app/lib/actions/remote_execution/run_host_job.rb +11 -8
  17. data/app/lib/actions/remote_execution/run_hosts_job.rb +5 -2
  18. data/app/lib/actions/remote_execution/run_proxy_command.rb +9 -4
  19. data/app/models/concerns/foreman_remote_execution/errors_flattener.rb +2 -2
  20. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +2 -2
  21. data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +1 -1
  22. data/app/models/concerns/foreman_remote_execution/template_extensions.rb +9 -1
  23. data/app/models/foreign_input_set.rb +49 -0
  24. data/app/models/host_status/execution_status.rb +50 -5
  25. data/app/models/input_template_renderer.rb +52 -7
  26. data/app/models/job_invocation.rb +89 -32
  27. data/app/models/job_invocation_composer.rb +71 -55
  28. data/app/models/job_template.rb +43 -7
  29. data/app/models/remote_execution_provider.rb +1 -1
  30. data/app/models/setting/remote_execution.rb +7 -7
  31. data/app/models/ssh_execution_provider.rb +1 -1
  32. data/app/models/targeting.rb +1 -1
  33. data/app/models/template_invocation.rb +9 -4
  34. data/app/views/api/v2/foreign_input_sets/base.json.rabl +3 -0
  35. data/app/views/api/v2/foreign_input_sets/create.json.rabl +3 -0
  36. data/app/views/api/v2/foreign_input_sets/index.json.rabl +3 -0
  37. data/app/views/api/v2/foreign_input_sets/main.json.rabl +5 -0
  38. data/app/views/api/v2/foreign_input_sets/show.json.rabl +3 -0
  39. data/app/views/api/v2/job_invocations/base.json.rabl +10 -1
  40. data/app/views/api/v2/job_invocations/main.json.rabl +14 -1
  41. data/app/views/api/v2/job_templates/base.json.rabl +1 -1
  42. data/app/views/api/v2/job_templates/main.json.rabl +9 -1
  43. data/app/views/api/v2/job_templates/show.json.rabl +0 -10
  44. data/app/views/api/v2/template_inputs/main.json.rabl +2 -1
  45. data/app/views/job_invocation_task_groups/_job_invocation_task_group.html.erb +1 -1
  46. data/app/views/job_invocations/_description_fields.html.erb +4 -0
  47. data/app/views/job_invocations/_form.html.erb +73 -91
  48. data/app/views/job_invocations/_host_actions_td.html.erb +2 -2
  49. data/app/views/job_invocations/_host_name_td.html.erb +7 -0
  50. data/app/views/job_invocations/_tab_hosts.html.erb +6 -6
  51. data/app/views/job_invocations/_tab_overview.html.erb +3 -3
  52. data/app/views/job_invocations/index.html.erb +6 -4
  53. data/app/views/job_invocations/refresh.js.erb +1 -0
  54. data/app/views/job_invocations/show.html.erb +1 -1
  55. data/app/views/job_invocations/show.js.erb +6 -3
  56. data/app/views/job_templates/_custom_tabs.html.erb +24 -14
  57. data/app/views/job_templates/index.html.erb +3 -1
  58. data/app/views/template_inputs/_foreign_input_set_form.html.erb +12 -0
  59. data/app/views/template_inputs/_form.html.erb +11 -12
  60. data/app/views/template_invocations/show.html.erb +2 -2
  61. data/app/views/templates/package_action.erb +2 -2
  62. data/app/views/templates/puppet_run_once.erb +3 -3
  63. data/app/views/templates/run_command.erb +3 -3
  64. data/app/views/templates/service_action.erb +2 -2
  65. data/app/views/unattended/snippets/_remote_execution_ssh_keys.erb +1 -1
  66. data/config/routes.rb +5 -3
  67. data/db/migrate/20150616080015_create_template_input.rb +1 -1
  68. data/db/migrate/20150708133241_add_targeting.rb +7 -7
  69. data/db/migrate/20150708133242_add_invocation.rb +2 -2
  70. data/db/migrate/20150708133305_add_template_invocation.rb +6 -6
  71. data/db/migrate/20151215114631_add_host_id_to_template_invocation.rb +3 -3
  72. data/db/migrate/20151217092555_migrate_to_task_groups.rb +1 -1
  73. data/db/migrate/20160108134600_create_template_input_sets.rb +16 -0
  74. data/db/migrate/20160108141144_make_job_name_default_to_something.rb +9 -0
  75. data/db/migrate/20160111113032_upcase_ssh_feature.rb +19 -0
  76. data/db/migrate/20160113161916_add_run_host_job_task_id_to_template_invocation.rb +6 -0
  77. data/db/migrate/20160113162007_expand_all_template_invocations.rb +45 -0
  78. data/db/migrate/20160114120200_rename_job_categories.rb +20 -0
  79. data/db/migrate/20160114125628_rename_job_name_to_job_category.rb +19 -0
  80. data/db/seeds.d/60-ssh_proxy_feature.rb +1 -1
  81. data/db/seeds.d/80-provision_templates.rb +2 -2
  82. data/db/seeds.d/90-bookmarks.rb +19 -0
  83. data/doc/plugins/graphviz.rb +5 -5
  84. data/doc/plugins/plantuml.rb +6 -6
  85. data/doc/plugins/tags.rb +4 -4
  86. data/foreman_remote_execution.gemspec +3 -4
  87. data/lib/foreman_remote_execution/engine.rb +12 -9
  88. data/lib/foreman_remote_execution/version.rb +1 -1
  89. data/test/factories/foreman_remote_execution_factories.rb +11 -9
  90. data/test/functional/api/v2/foreign_input_sets_controller_test.rb +63 -0
  91. data/test/functional/api/v2/job_invocations_controller_test.rb +45 -13
  92. data/test/functional/api/v2/job_templates_controller_test.rb +6 -6
  93. data/test/functional/api/v2/template_inputs_controller_test.rb +3 -3
  94. data/test/unit/actions/run_hosts_job_test.rb +3 -4
  95. data/test/unit/actions/run_proxy_command_test.rb +7 -7
  96. data/test/unit/concerns/host_extensions_test.rb +1 -1
  97. data/test/unit/execution_task_status_mapper_test.rb +93 -0
  98. data/test/unit/input_template_renderer_test.rb +182 -9
  99. data/test/unit/job_invocation_composer_test.rb +144 -168
  100. data/test/unit/job_invocation_test.rb +67 -15
  101. data/test/unit/job_template_effective_user_test.rb +2 -2
  102. data/test/unit/job_template_test.rb +36 -12
  103. data/test/unit/remote_execution_provider_test.rb +6 -6
  104. data/test/unit/targeting_test.rb +2 -2
  105. metadata +27 -21
  106. data/app/models/concerns/foreman_remote_execution/template_relations.rb +0 -10
  107. data/app/views/job_invocations/_host_provider_td.html.erb +0 -3
  108. data/app/views/job_templates/auto_complete_job_name.json.erb +0 -3
@@ -0,0 +1,3 @@
1
+ object @foreign_input_set
2
+
3
+ attributes :id, :target_template_id, :target_template_name, :include_all, :include, :exclude
@@ -0,0 +1,3 @@
1
+ object @foreign_input_set
2
+
3
+ extends "api/v2/foreign_input_sets/show"
@@ -0,0 +1,3 @@
1
+ collection @foreign_input_sets
2
+
3
+ extends "api/v2/foreign_input_sets/main"
@@ -0,0 +1,5 @@
1
+ object @foreign_input_set
2
+
3
+ extends "api/v2/foreign_input_sets/base"
4
+
5
+ attributes :template_id, :target_input_id, :target_template_name, :include_all, :include, :exclude
@@ -0,0 +1,3 @@
1
+ object @foreign_input_set
2
+
3
+ extends "api/v2/foreign_input_sets/main"
@@ -1,6 +1,15 @@
1
1
  object @job_invocation
2
2
 
3
- attributes :id, :job_name, :targeting_id
3
+ attributes :id, :description, :job_category, :targeting_id, :status, :start_at, :status_label
4
+
5
+ node do |invocation|
6
+ {
7
+ :succeeded => invocation_count(invocation, :output_key => :success_count),
8
+ :failed => invocation_count(invocation, :output_key => :failed_count),
9
+ :pending => invocation_count(invocation, :output_key => :pending_count),
10
+ :total => invocation_count(invocation, :output_key => :total_count)
11
+ }
12
+ end
4
13
 
5
14
  child :task do
6
15
  attributes :id, :state
@@ -2,8 +2,21 @@ object @job_invocation
2
2
 
3
3
  extends "api/v2/job_invocations/base"
4
4
 
5
+ node do |invocation|
6
+ if invocation.triggering
7
+ case invocation.triggering.mode
8
+ when :recurring
9
+ {:mode => :recurring, :recurrence => partial('foreman_tasks/api/recurring_logics/base', :object => invocation.triggering.recurring_logic)}
10
+ when :future
11
+ {:mode => :future, :scheduling => {:start_at => invocation.triggering.start_at, :start_before => invocation.triggering.start_before }}
12
+ end
13
+ else
14
+ {:mode => :immediate}
15
+ end
16
+ end
17
+
5
18
  child :targeting do
6
- attributes :bookmark_id, :search_query, :targeting_type, :user_id
19
+ attributes :bookmark_id, :search_query, :targeting_type, :user_id, :status, :status_label
7
20
 
8
21
  child :hosts do
9
22
  extends "api/v2/hosts/base"
@@ -1,3 +1,3 @@
1
1
  object @job_template
2
2
 
3
- attributes :id, :name, :job_name, :provider_type, :snippet
3
+ attributes :id, :name, :job_category, :provider_type, :snippet, :description_format
@@ -2,8 +2,16 @@ object @job_template
2
2
 
3
3
  extends "api/v2/job_templates/base"
4
4
 
5
- attributes :audit_comment, :created_at, :updated_at
5
+ attributes :audit_comment, :description_format, :created_at, :updated_at, :template, :locked
6
6
 
7
7
  child :template_inputs do
8
8
  extends "api/v2/template_inputs/base"
9
9
  end
10
+
11
+ child :effective_user => :effective_user do
12
+ attributes :value, :current_user, :overridable
13
+ end
14
+
15
+ node do |job_template|
16
+ partial("api/v2/taxonomies/children_nodes", :object => job_template)
17
+ end
@@ -1,13 +1,3 @@
1
1
  object @job_template
2
2
 
3
3
  extends "api/v2/job_templates/main"
4
-
5
- attributes :template, :locked
6
-
7
- child :effective_user => :effective_user do
8
- attributes :value, :current_user, :overridable
9
- end
10
-
11
- node do |job_template|
12
- partial("api/v2/taxonomies/children_nodes", :object => job_template)
13
- end
@@ -2,7 +2,8 @@ object @template_input
2
2
 
3
3
  extends "api/v2/template_inputs/base"
4
4
 
5
- attributes :template_id, :fact_name, :variable_name, :puppet_parameter_name
5
+ attributes :template_id, :fact_name, :variable_name, :puppet_parameter_name, :puppet_class_name,
6
+ :description, :required
6
7
 
7
8
  node :options do |input|
8
9
  input.options.split(/\r?\n/) if input.options.present?
@@ -6,7 +6,7 @@
6
6
  </tr>
7
7
  <tr>
8
8
  <th>Job Name</th>
9
- <td><%= job_invocation.job_name %></td>
9
+ <td><%= job_invocation.job_category %></td>
10
10
  </tr>
11
11
  <tr>
12
12
  <th>Status</th>
@@ -0,0 +1,4 @@
1
+ <%= textarea_f(f, :description, :label => _('Description'), :readonly => 'true', :disabled => disabled, :class => 'description', :rows => 2, :help_inline => description_checkbox_f(f, job_template, disabled)) %>
2
+ <div class="description_format_container <%= 'hidden' if f.object.description_format.nil? %>">
3
+ <%= description_format_textarea_f(f, job_template, disabled) %>
4
+ </div>
@@ -1,119 +1,101 @@
1
1
  <script type="text/javascript">
2
2
  $(function () {
3
- regenerate_description($('#description'), true)
3
+ regenerate_description($('.description'))
4
4
  });
5
5
  </script>
6
6
 
7
7
  <%= form_for @composer.job_invocation, :html => {'data-refresh-url' => refresh_job_invocations_path, :id => 'job_invocation_form'} do |f| %>
8
8
 
9
- <ul class="nav nav-tabs" data-tabs="tabs">
10
- <li class="active"><a href="#primary" data-toggle="tab"><%= _('Job') %></a></li>
11
- <li><a href="#scheduling" data-toggle="tab">Scheduling</a></li>
12
- </ul>
9
+ <%= selectable_f f, :job_category, @composer.available_job_categories, {}, :label => _('Job category') %>
13
10
 
14
- <div class="tab-content">
15
- <div class="tab-pane active" id="primary">
16
- <%= selectable_f f, :job_name, @composer.available_job_names %>
11
+ <% selected_templates_per_provider = {} %>
12
+ <% @composer.displayed_provider_types.each do |provider_type| %>
13
+ <%= f.fields_for 'providers' do |providers_fields| %>
14
+ <%= providers_fields.fields_for provider_type do |provider_type_fields| %>
15
+ <% templates_for_provider = @composer.templates_for_provider(provider_type) %>
16
+ <% selected_templates_per_provider[provider_type] = @composer.preselected_template_for_provider(provider_type) || templates_for_provider.first %>
17
17
 
18
- <%= fields_for @composer.targeting do |targeting_fields| %>
19
- <span id="bookmark_query_map">
20
- <% @composer.available_bookmarks.each do |bookmark| %>
21
- <span id="bookmark-<%= bookmark.id %>" data-query="<%= bookmark.query %>"></span>
22
- <% end %>
23
- </span>
24
- <%= selectable_f targeting_fields, :bookmark_id, @composer.available_bookmarks.map { |b| [b.name, b.id] }, :selected => @composer.targeting.bookmark_id, :include_blank => true %>
25
- <%= textarea_f targeting_fields, :search_query, :value => @composer.displayed_search_query, :rows => 5 %>
18
+ <%= selectable_f provider_type_fields, 'job_template_id', templates_for_provider.map { |t| [t.name, t.id] },
19
+ { :selected => selected_templates_per_provider[provider_type].try(:id) },
20
+ { :class => 'job_template_selector', :label => _('Job template'),
21
+ :data => { :provider_type => provider_type }, :required => true, :onchange => "template_change(this);" }%>
22
+ <% end %>
23
+ <% end %>
24
+ <% end %>
26
25
 
27
- <div class="form-group ">
28
- <label class="col-md-2 control-label"><%= _('Resolves to') %></label>
26
+ <%= fields_for @composer.targeting do |targeting_fields| %>
27
+ <span id="bookmark_query_map">
28
+ <% @composer.available_bookmarks.each do |bookmark| %>
29
+ <span id="bookmark-<%= bookmark.id %>" data-query="<%= bookmark.query %>"></span>
30
+ <% end %>
31
+ </span>
32
+ <%= selectable_f targeting_fields, :bookmark_id, @composer.available_bookmarks.map { |b| [b.name, b.id] }, :selected => @composer.targeting.bookmark_id, :include_blank => true %>
33
+ <%= textarea_f targeting_fields, :search_query, :value => @composer.displayed_search_query, :rows => 5 %>
29
34
 
30
- <div class="col-md-4">
31
- <%= @composer.targeted_hosts_count %> <%= _('hosts') %>
32
- <%= button_tag(:type => 'button', :class => 'btn btn-default btn-sm', :title => _("Refresh"), :id => 'refresh_execution_form') do %>
33
- <%= icon_text('refresh') %>
34
- <% end %>
35
- <%= button_tag(:type => 'button', :class => 'btn btn-default btn-sm', :title => _("Preview"), :id => 'preview_hosts') do %>
36
- <%= icon_text('eye-open') %>
37
- <% end %>
38
- </div>
39
- </div>
35
+ <div class="form-group ">
36
+ <label class="col-md-2 control-label"><%= _('Resolves to') %></label>
40
37
 
41
- <div class="form-group ">
42
- <label class="col-md-2 control-label"><%= _('Type of query') %></label>
38
+ <div class="col-md-4">
39
+ <%= @composer.targeted_hosts_count %> <%= _('hosts') %>
40
+ <%= button_tag(:type => 'button', :class => 'btn btn-default btn-sm', :title => _("Refresh"), :id => 'refresh_execution_form') do %>
41
+ <%= icon_text('refresh') %>
42
+ <% end %>
43
+ <%= button_tag(:type => 'button', :class => 'btn btn-default btn-sm', :title => _("Preview"), :id => 'preview_hosts') do %>
44
+ <%= icon_text('eye-open') %>
45
+ <% end %>
46
+ </div>
47
+ </div>
43
48
 
44
- <div class="col-md-4">
45
- <%= radio_button_f targeting_fields, :targeting_type, :value => Targeting::STATIC_TYPE, :text => _(Targeting::TYPES[Targeting::STATIC_TYPE]) %>
46
- <%= radio_button_f targeting_fields, :targeting_type, :value => Targeting::DYNAMIC_TYPE, :text => _(Targeting::TYPES[Targeting::DYNAMIC_TYPE]) %>
47
- </div>
48
- <span class="help-inline"><%= popover(_('Explanation'),
49
- _("Type has impact on when is the query evaulated to hosts.<br><ul><li><b>Static</b> - evaluates just after you submit this form</li><li><b>Dynamic</b> - evaluates just before the execution is started, so if it's planed in future, targeted hosts set may change before it</li></ul>")) %></span>
50
- </div>
51
- <% end %>
49
+ <div class="form-group ">
50
+ <label class="col-md-2 control-label"><%= _('Type of query') %></label>
52
51
 
53
- <% @composer.displayed_provider_types.each do |provider_type| %>
54
- <fieldset id="provider_<%= provider_type %>" class="provider_form">
55
- <legend><%= _('Provider') + ': ' + provider_type %></legend>
56
- <%= f.fields_for 'providers' do |providers_fields| %>
57
- <%= providers_fields.fields_for provider_type do |provider_type_fields| %>
58
- <%= provider_type_fields.fields_for :job_templates do |job_templates_fields| %>
59
- <% if @composer.needs_provider_type_selection? %>
60
- <%= radio_button_f provider_type_fields, 'job_template_id', :value => '', :text => _('Disable this provider'),
61
- :class => 'job_template_selector', :checked => @composer.preselect_disabled_for_provider(provider_type) %>
62
- <span/>
63
- <% end %>
64
- <% @composer.templates_for_provider(provider_type).each do |job_template| %>
65
- <%= radio_button_f provider_type_fields, 'job_template_id',
66
- :value => job_template.id,
67
- :text => job_template.name,
68
- :onchange => "regenerate_description($(this).parent().next('fieldset'));",
69
- :class => 'job_template_selector',
70
- :checked => @composer.job_template_ids.include?(job_template.id) || @composer.only_one_template_available? %>
52
+ <div class="col-md-4">
53
+ <%= radio_button_f targeting_fields, :targeting_type, :value => Targeting::STATIC_TYPE, :text => _(Targeting::TYPES[Targeting::STATIC_TYPE]) %>
54
+ <%= radio_button_f targeting_fields, :targeting_type, :value => Targeting::DYNAMIC_TYPE, :text => _(Targeting::TYPES[Targeting::DYNAMIC_TYPE]) %>
55
+ </div>
56
+
57
+ <span class="help-inline"><%= popover(_('Explanation'),
58
+ _("Type has impact on when is the query evaulated to hosts.<br><ul><li><b>Static</b> - evaluates just after you submit this form</li><li><b>Dynamic</b> - evaluates just before the execution is started, so if it's planed in future, targeted hosts set may change before it</li></ul>")) %>
59
+ </span>
60
+ </div>
61
+ <% end %>
71
62
 
72
- <fieldset id="job_template_<%= job_template.id %>" class="job_template_form <%= 'hidden' if !@composer.job_template_ids.include?(job_template.id) && !@composer.only_one_template_available? %>">
73
- <%= job_templates_fields.fields_for job_template.id.to_s do |job_template_fields| %>
63
+ <% @composer.displayed_provider_types.each do |provider_type| %>
64
+ <fieldset id="provider_<%= provider_type %>" class="provider_form">
65
+ <%= f.fields_for 'providers' do |providers_fields| %>
66
+ <%= providers_fields.fields_for provider_type do |provider_type_fields| %>
67
+ <%= provider_type_fields.fields_for :job_templates do |job_templates_fields| %>
68
+ <% @composer.templates_for_provider(provider_type).each do |job_template| %>
69
+ <fieldset id="job_template_<%= job_template.id %>" class="job_template_form <%= 'hidden' if job_template != selected_templates_per_provider[provider_type] %>">
70
+ <%= job_templates_fields.fields_for job_template.id.to_s do |job_template_fields| %>
74
71
 
75
- <%= job_template_fields.fields_for :input_values do |input_values_fields| %>
76
- <% job_template.template_inputs.where(:input_type => 'user').each do |input| %>
77
- <%= input_values_fields.fields_for input.id.to_s, @composer.template_invocation_input_value_for(input) do |input_fields| %>
78
- <% unless input.options.blank? %>
79
- <%= selectable_f input_fields, :value, input.options_array, {:include_blank => !input.required}, :require => input.required, :label => input.name, :help_inline => input.description, :id => input.name, :onchange => "regenerate_description(this);" %>
80
- <% else %>
81
- <%= textarea_f input_fields, :value, :label => input.name, :help_inline => input.description, :required => input.required, :rows => 2, :onchange => "regenerate_description(this);", :id => input.name %>
82
- <% end %>
83
- <% end %>
72
+ <%= job_template_fields.fields_for :input_values do |input_values_fields| %>
73
+ <% job_template.template_inputs_with_foreign.select { |input| input.input_type == 'user' }.each do |input| %>
74
+ <%= input_values_fields.fields_for input.id.to_s, @composer.template_invocation_input_value_for(job_template, input) do |input_fields| %>
75
+ <% unless input.options.blank? %>
76
+ <%= selectable_f input_fields, :value, input.options_array, {:include_blank => !input.required}, :require => input.required, :label => input.name, :help_inline => input.description, :id => input.name, :onchange => "regenerate_description(this);" %>
77
+ <% else %>
78
+ <%= textarea_f input_fields, :value, :label => input.name, :help_inline => input.description, :required => input.required, :rows => 2, :onchange => "regenerate_description(this);", :id => input.name %>
84
79
  <% end %>
85
80
  <% end %>
86
- <% if job_template.effective_user.overridable? %>
87
- <%= text_f job_template_fields, :effective_user, :label => _('Effective user'), :help_inline => N_("A user to be used for executing the script. If it differs from the SSH user, su or sudo is used to switch the accounts.") %>
88
- <% end %>
89
-
90
81
  <% end %>
91
- <%= textarea_f f, :description, :label => _("Description"), :readonly => "true", :id => "description", :rows => 2, :help_inline => content_tag(:span, check_box_tag('description_format_override', job_template.generate_description_format, true, :onchange => "description_override(this);") + ' ' + _("Use default description template")) %>
92
- <div id="description_format_container" class="hidden">
93
- <%= textarea_f f, :description_format,
94
- :label => _("Description template"),
95
- :value => job_template.generate_description_format,
96
- :rows => 2,
97
- :onchange => "regenerate_description(this);",
98
- :id => "description_format",
99
- :help_inline => popover(_('Explanation'), _('Description template determines the job name once it is submitted. Input values can become part of the name
100
- if they are specified using interpolation syntax, e.g. %{fqdn} where fqdn is the name of interpolated input.')) %>
101
- </div>
102
- </fieldset>
82
+ <% end %>
83
+ <% if job_template.effective_user.overridable? %>
84
+ <%= text_f job_template_fields, :effective_user, :label => _('Effective user'), :help_inline => N_("A user to be used for executing the script. If it differs from the SSH user, su or sudo is used to switch the accounts.") %>
85
+ <% end %>
86
+ <%= render :partial => 'description_fields', :locals => { :f => f, :job_template => job_template, :disabled => job_template != selected_templates_per_provider[provider_type] } %>
103
87
  <% end %>
104
- <% end %>
88
+ </fieldset>
105
89
  <% end %>
106
90
  <% end %>
107
- </fieldset>
91
+ <% end %>
108
92
  <% end %>
93
+ </fieldset>
94
+ <% end %>
109
95
 
110
- <%= render :partial => 'preview_hosts_modal' %>
111
- </div>
96
+ <%= trigger_selector f, @composer.triggering %>
97
+ <%= render :partial => 'preview_hosts_modal' %>
112
98
 
113
- <div class="tab-pane" id="scheduling">
114
- <%= trigger_selector f, @composer.triggering %>
115
- </div>
116
- </div>
117
99
 
118
100
  <%= submit_or_cancel f %>
119
101
  <% end %>
@@ -1,3 +1,3 @@
1
- <td class="host_actions" id="<%= dom_id(host) %>-actions" data-refresh_required="<%= task.nil? ? 'true' : '' %>" data-id="<%= host.id %>">
2
- <%= action_buttons(template_invocation_actions(task, host)) %>
1
+ <td class="host_actions" id="<%= dom_id(host) %>-actions" data-refresh_required="" data-id="<%= host.id %>">
2
+ <%= action_buttons(template_invocation_actions(task, host, job_invocation, template_invocation)) %>
3
3
  </td>
@@ -0,0 +1,7 @@
1
+ <td class="host_name" id="<%= dom_id(host) %>-name" data-refresh_required="<%= task.nil? ? 'true' : '' %>" data-id="<%= host.id %>">
2
+ <% if task %>
3
+ <%= link_to_if_authorized host.name, hash_for_template_invocation_path(:id => template_invocation).merge(:auth_object => host, :permission => :view_hosts) %>
4
+ <% else %>
5
+ <%= host.name %>
6
+ <% end %>
7
+ </td>
@@ -19,7 +19,6 @@
19
19
  <thead>
20
20
  <tr>
21
21
  <th><%= sort :name, :as => _('Host') %></th>
22
- <th><%= _('Provider') %></th>
23
22
  <th><%= _('Status') %></th>
24
23
  <th><%= _('Actions') %></th>
25
24
  </tr>
@@ -27,12 +26,13 @@
27
26
 
28
27
  <tbody>
29
28
  <% hosts.each do |host| %>
30
- <% task = job_invocation.sub_task_for_host(host) %>
29
+ <% template_invocation = job_invocation.template_invocations.find { |template_invocation| template_invocation.host_id == host.id } %>
30
+ <% task = template_invocation.try(:run_host_job_task) %>
31
31
  <tr>
32
- <td><%= link_to_if_authorized host.name, hash_for_host_path(host).merge(:auth_object => host, :permission => :view_hosts) %></td>
33
- <%= render('host_provider_td', :host => host, :task => task) %>
34
- <%= render('host_status_td', :host => host, :task => task) %>
35
- <%= render('host_actions_td', :host => host, :task => task) %>
32
+ <% options = { :host => host, :task => task, :job_invocation => job_invocation, :template_invocation => template_invocation } %>
33
+ <%= render 'host_name_td', options %>
34
+ <%= render 'host_status_td', options %>
35
+ <%= render 'host_actions_td', options %>
36
36
  </tr>
37
37
  <% end %>
38
38
  </tbody>
@@ -13,8 +13,8 @@
13
13
  <pre><%= job_invocation.targeting.search_query %></pre>
14
14
 
15
15
  <%= _('Evaluated at:') %> <%= job_invocation.targeting.resolved_at %><br>
16
- <% if job_invocation.template_invocations.size > 1 %>
17
- <% job_invocation.template_invocations.each do |template_invocation| %>
16
+ <% if job_invocation.pattern_template_invocations.size > 1 %>
17
+ <% job_invocation.pattern_template_invocations.each do |template_invocation| %>
18
18
  <%= host_counter template_invocation.template.provider.humanized_name, ForemanTasks::Task::DynflowTask.for_action(Actions::RemoteExecution::RunHostJob).for_resource(template_invocation).uniq.size %>
19
19
  <% end %>
20
20
  <% end %>
@@ -23,7 +23,7 @@
23
23
 
24
24
  <div class="col-md-6 infoblock">
25
25
  <h4><%= _('Providers and templates') %></h4>
26
- <% job_invocation.template_invocations.each do |template_invocation| %>
26
+ <% job_invocation.pattern_template_invocations.each do |template_invocation| %>
27
27
  <h5>
28
28
  <b><%= template_invocation.template.name %></b> <%= 'through' %> <%= template_invocation.template.provider.humanized_name %>
29
29
  </h5>
@@ -1,28 +1,30 @@
1
1
  <% title _('Job invocations') %>
2
2
 
3
+ <% title_actions(job_invocations_buttons) %>
4
+
3
5
  <table class="table table-bordered table-striped table-condensed">
4
6
  <thead>
5
7
  <tr>
6
- <th><%= sort :job_name, :as => _('Job name') %></th>
8
+ <th><%= sort :description, :as => _('Description') %></th>
7
9
  <th><%= _('Status') %></th>
8
10
  <th><%= _('Succeeded') %></th>
9
11
  <th><%= _('Failed') %></th>
10
12
  <th><%= _('Pending') %></th>
11
13
  <th><%= _('Total hosts') %></th>
12
- <th><%= sort :started_at, :as => _('Started') %></th>
14
+ <th><%= sort :start_at, :as => _('Start') %></th>
13
15
  </tr>
14
16
  </thead>
15
17
 
16
18
  <tbody>
17
19
  <% @job_invocations.each do |invocation| %>
18
20
  <tr>
19
- <td><%= link_to_if_authorized "#{invocation.description.try(:capitalize) || invocation.job_name}", hash_for_job_invocation_path(invocation).merge(:auth_object => invocation, :permission => :view_job_invocation) %></td>
21
+ <td><%= link_to_if_authorized "#{invocation.description.try(:capitalize) || invocation.job_category}", hash_for_job_invocation_path(invocation).merge(:auth_object => invocation, :permission => :view_job_invocations) %></td>
20
22
  <td><%= link_to_invocation_task_if_authorized(invocation) %></td>
21
23
  <td><%= invocation_count(invocation, :output_key => :success_count) %></td>
22
24
  <td><%= invocation_count(invocation, :output_key => :failed_count) %></td>
23
25
  <td><%= invocation_count(invocation, :output_key => :pending_count) %></td>
24
26
  <td><%= invocation_count(invocation, :output_key => :total_count) %></td>
25
- <td><%= time_ago(invocation.task.try(:started_at)) %></td>
27
+ <td><%= time_in_words_span(invocation.start_at) %></td>
26
28
  </tr>
27
29
  <% end %>
28
30
  </tbody>
@@ -1,2 +1,3 @@
1
1
  $('form#job_invocation_form').replaceWith("<%=j render :partial => 'form' %>");
2
2
  $('#job_invocation_form').find('a[rel="popover"]').popover();
3
+ $('#job_invocation_form select:not(.without_select2)').select2({ allowClear: true });
@@ -1,4 +1,4 @@
1
- <% title @job_invocation.job_name %>
1
+ <% title @job_invocation.description %>
2
2
  <% stylesheet 'job_invocations' %>
3
3
  <% javascript 'template_invocation' %>
4
4
 
@@ -1,4 +1,4 @@
1
- $('div.btn-group').html('<%= button_group(job_invocation_task_buttons(@job_invocation.task)).html_safe %>');
1
+ $('div#title_action div.btn-group').html('<%= button_group(job_invocation_task_buttons(@job_invocation.task)).html_safe %>');
2
2
  $('div#status_chart').html('<%=j job_invocation_chart(@job_invocation) %>');
3
3
  $('div#status').flot_pie();
4
4
 
@@ -8,12 +8,15 @@ $('div#status').flot_pie();
8
8
  hosts_tab.data('refresh_required', '');
9
9
  <% end %>
10
10
 
11
- <% ['status', 'actions', 'provider'].each do |attribute| %>
11
+ <% ['name', 'status', 'actions', 'provider'].each do |attribute| %>
12
12
  <% if params["host_ids_needing_#{attribute}_update"].present? %>
13
13
  var td_element;
14
14
  <% Host.authorized(:view_hosts, Host).where(:id => params["host_ids_needing_#{attribute}_update"]).each do |host| %>
15
+ <% template_invocation = @job_invocation.template_invocations.find { |template_invocation| template_invocation.host_id == host.id } %>
16
+ <% task = template_invocation.try(:run_host_job_task) %>
17
+ <% options = { :host => host, :task => task, :job_invocation => @job_invocation, :template_invocation => template_invocation } %>
15
18
  td_element= $('#<%= dom_id(host) %>-<%= attribute %>');
16
- td_element.replaceWith('<%=j render("host_#{attribute}_td", :host => host, :task => @job_invocation.sub_task_for_host(host)) %>');
19
+ td_element.replaceWith('<%=j render("host_#{attribute}_td", options) %>');
17
20
  <% end %>
18
21
  <% end %>
19
22
  <% end %>