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.
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 %>