foreman_remote_execution 7.0.0 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby_ci.yml +4 -2
- data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_commands_controller_extensions.rb +1 -0
- data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_controller_extensions.rb +8 -0
- data/app/controllers/ui_job_wizard_controller.rb +15 -0
- data/app/helpers/remote_execution_helper.rb +1 -1
- data/app/models/concerns/foreman_remote_execution/foreman_tasks_task_extensions.rb +6 -0
- data/app/models/host_status/execution_status.rb +2 -1
- data/app/models/job_invocation.rb +1 -1
- data/app/models/job_invocation_composer.rb +6 -3
- data/app/models/job_template.rb +2 -0
- data/app/models/remote_execution_provider.rb +4 -0
- data/app/models/template_invocation.rb +2 -0
- data/app/services/remote_execution_proxy_selector.rb +1 -1
- data/app/views/overrides/subnets/_rex_tab_pane.html.erb +1 -1
- data/app/views/templates/script/package_action.erb +8 -3
- data/config/routes.rb +3 -1
- data/lib/foreman_remote_execution/engine.rb +6 -5
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/functional/api/v2/job_invocations_controller_test.rb +8 -0
- data/test/helpers/remote_execution_helper_test.rb +4 -0
- data/test/unit/api_params_test.rb +33 -0
- data/test/unit/job_invocation_report_template_test.rb +1 -1
- data/test/unit/job_invocation_test.rb +1 -2
- data/test/unit/remote_execution_provider_test.rb +26 -0
- data/webpack/JobWizard/JobWizard.js +154 -20
- data/webpack/JobWizard/JobWizard.scss +43 -1
- data/webpack/JobWizard/JobWizardConstants.js +11 -1
- data/webpack/JobWizard/JobWizardPageRerun.js +112 -0
- data/webpack/JobWizard/__tests__/JobWizardPageRerun.test.js +79 -0
- data/webpack/JobWizard/__tests__/fixtures.js +73 -0
- data/webpack/JobWizard/__tests__/integration.test.js +17 -3
- data/webpack/JobWizard/autofill.js +8 -1
- data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +9 -0
- data/webpack/JobWizard/steps/AdvancedFields/Fields.js +21 -0
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +41 -17
- data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +3 -3
- data/webpack/JobWizard/steps/ReviewDetails/index.js +2 -3
- data/webpack/JobWizard/steps/Schedule/PurposeField.js +1 -3
- data/webpack/JobWizard/steps/Schedule/QueryType.js +33 -40
- data/webpack/JobWizard/steps/Schedule/RepeatHour.js +55 -16
- data/webpack/JobWizard/steps/Schedule/RepeatOn.js +19 -56
- data/webpack/JobWizard/steps/Schedule/RepeatWeek.js +1 -1
- data/webpack/JobWizard/steps/Schedule/ScheduleFuture.js +126 -0
- data/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js +287 -0
- data/webpack/JobWizard/steps/Schedule/ScheduleType.js +88 -20
- data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +206 -186
- data/webpack/JobWizard/steps/form/DateTimePicker.js +23 -6
- data/webpack/JobWizard/steps/form/Formatter.js +7 -8
- data/webpack/JobWizard/submit.js +10 -3
- data/webpack/Routes/routes.js +8 -2
- data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +1 -0
- data/webpack/react_app/components/FeaturesDropdown/index.js +1 -1
- data/webpack/react_app/components/RegistrationExtension/RexPull.js +73 -0
- data/webpack/react_app/extend/Fills.js +8 -1
- metadata +11 -6
- data/webpack/JobWizard/steps/Schedule/StartEndDates.js +0 -106
- data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +0 -32
- data/webpack/JobWizard/steps/Schedule/index.js +0 -178
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa3c6d67549990da3bbd1d7cbf55408bd4a1dc4d7fc5cbcec8db99eded747964
|
4
|
+
data.tar.gz: ca4e519773be6b0493341fd25ba55e8d4345367c88e0b068183ebe66d020e22e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbeb56766cc65ed9fcd587f260fb29fca965b961b0787230f0510166702351cb5ff0c78387b3f818b9741f281519f33931bc8d0aa36a923d92e0d50f620d113e
|
7
|
+
data.tar.gz: 3238dc8bc7cdbaa361a6c077e5d611839cb549424ad98daea9e68ac81a932dd6c8de2f233b31f019cc7a1d037b6fea4a656ca3d7e789eb9a794170fb26ac1f68
|
@@ -16,8 +16,10 @@ jobs:
|
|
16
16
|
- name: Setup Ruby
|
17
17
|
uses: ruby/setup-ruby@v1
|
18
18
|
with:
|
19
|
-
ruby-version: 2.
|
19
|
+
ruby-version: 2.7
|
20
20
|
bundler-cache: true
|
21
|
+
cache-version: 1
|
22
|
+
rubygems: 3.0.0
|
21
23
|
- name: Run rubocop
|
22
24
|
if: github.event_name != 'push'
|
23
25
|
run: bundle exec rubocop --format github
|
@@ -36,7 +38,7 @@ jobs:
|
|
36
38
|
fail-fast: false
|
37
39
|
matrix:
|
38
40
|
foreman-core-branch: [develop]
|
39
|
-
ruby-version: [2.
|
41
|
+
ruby-version: [2.7]
|
40
42
|
node-version: [12]
|
41
43
|
steps:
|
42
44
|
- run: sudo apt-get update
|
@@ -9,6 +9,7 @@ module ForemanRemoteExecution
|
|
9
9
|
update_api(:create) do
|
10
10
|
param :registration_command, Hash do
|
11
11
|
param :remote_execution_interface, String, desc: N_("Identifier of the Host interface for Remote execution")
|
12
|
+
param :setup_remote_execution_pull, :bool, desc: N_("Set 'host_registration_remote_execution_pull' parameter for the host. If it is set to true, pull provider client will be deployed on the host")
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_controller_extensions.rb
CHANGED
@@ -6,6 +6,7 @@ module ForemanRemoteExecution
|
|
6
6
|
|
7
7
|
update_api(:global, :host) do
|
8
8
|
param :remote_execution_interface, String, desc: N_("Identifier of the Host interface for Remote execution")
|
9
|
+
param :setup_remote_execution_pull, :bool, desc: N_("Set 'host_registration_remote_execution_pull' parameter for the host. If it is set to true, pull provider client will be deployed on the host")
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -13,10 +14,17 @@ module ForemanRemoteExecution
|
|
13
14
|
|
14
15
|
def host_setup_extension
|
15
16
|
remote_execution_interface
|
17
|
+
remote_execution_pull
|
16
18
|
reset_host_known_keys! unless @host.new_record?
|
17
19
|
super
|
18
20
|
end
|
19
21
|
|
22
|
+
def remote_execution_pull
|
23
|
+
HostParameter.where(host: @host, name: 'host_registration_remote_execution_pull').destroy_all
|
24
|
+
|
25
|
+
setup_host_param('host_registration_remote_execution_pull', ActiveRecord::Type::Boolean.new.deserialize(params['setup_remote_execution_pull']))
|
26
|
+
end
|
27
|
+
|
20
28
|
def remote_execution_interface
|
21
29
|
return unless params['remote_execution_interface'].present?
|
22
30
|
|
@@ -57,4 +57,19 @@ class UiJobWizardController < ApplicationController
|
|
57
57
|
render :json => { :results =>
|
58
58
|
resource_list.sort_by { |r| r[:name] }.take(100), :subtotal => resource_list.count}
|
59
59
|
end
|
60
|
+
|
61
|
+
def job_invocation
|
62
|
+
job = JobInvocation.authorized.find(params[:id])
|
63
|
+
composer = JobInvocationComposer.from_job_invocation(job, params).params
|
64
|
+
job_template_inputs = JobTemplate.authorized.find(composer[:template_invocations][0][:template_id]).template_inputs_with_foreign
|
65
|
+
inputs = Hash[job_template_inputs.map { |input| ["inputs[#{input[:name]}]", (composer[:template_invocations][0][:input_values].find { |value| value[:template_input_id] == input[:id] })[:value]] }]
|
66
|
+
job_organization = Taxonomy.find_by(id: job.task.input[:current_organization_id])
|
67
|
+
job_location = Taxonomy.find_by(id: job.task.input[:current_location_id])
|
68
|
+
render :json => {
|
69
|
+
:job => composer,
|
70
|
+
:job_organization => job_organization,
|
71
|
+
:job_location => job_location,
|
72
|
+
:inputs => inputs,
|
73
|
+
}
|
74
|
+
end
|
60
75
|
end
|
@@ -246,7 +246,7 @@ module RemoteExecutionHelper
|
|
246
246
|
def job_report_template
|
247
247
|
template = ReportTemplate.where(name: Setting['remote_execution_job_invocation_report_template']).first
|
248
248
|
|
249
|
-
template if template.template_inputs.where(name: 'job_id').exists?
|
249
|
+
template if template && template.template_inputs.where(name: 'job_id').exists?
|
250
250
|
end
|
251
251
|
|
252
252
|
def job_report_template_parameters(job_invocation, template)
|
@@ -4,6 +4,12 @@ module ForemanRemoteExecution
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
has_many :job_invocations, :dependent => :destroy, :foreign_key => 'task_id'
|
7
|
+
has_one :template_invocation, :inverse_of => :run_host_job_task, :foreign_key => 'run_host_job_task_id', :dependent => :nullify
|
8
|
+
has_one :template, :through => :template_invocation
|
9
|
+
has_many :remote_execution_features, :through => :template
|
10
|
+
|
11
|
+
scoped_search :relation => :remote_execution_features, :on => :name, :rename => 'remote_execution_feature.name'
|
12
|
+
scoped_search :relation => :remote_execution_features, :on => :label, :rename => 'remote_execution_feature.label'
|
7
13
|
end
|
8
14
|
end
|
9
15
|
end
|
@@ -50,7 +50,8 @@ class HostStatus::ExecutionStatus < HostStatus::Status
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def status_link
|
53
|
-
job_invocation = last_stopped_task
|
53
|
+
job_invocation = last_stopped_task&.parent_task&.job_invocations&.first
|
54
|
+
return unless job_invocation
|
54
55
|
return nil unless User.current.can?(:view_job_invocations, job_invocation)
|
55
56
|
|
56
57
|
Rails.application.routes.url_helpers.job_invocation_path(job_invocation)
|
@@ -25,7 +25,7 @@ class JobInvocation < ApplicationRecord
|
|
25
25
|
validates :job_category, :presence => true
|
26
26
|
validates_associated :targeting, :all_template_invocations
|
27
27
|
|
28
|
-
scoped_search :on => :id, :complete_value => true
|
28
|
+
scoped_search :on => :id, :complete_value => true, :validator => ScopedSearch::Validators::INTEGER
|
29
29
|
scoped_search :on => :job_category, :complete_value => true
|
30
30
|
scoped_search :on => :description, :complete_value => true
|
31
31
|
|
@@ -219,7 +219,7 @@ class JobInvocationComposer
|
|
219
219
|
def format_datetime(datetime)
|
220
220
|
return datetime if datetime.blank?
|
221
221
|
|
222
|
-
Time.parse(datetime).
|
222
|
+
Time.zone.parse(datetime).strftime('%Y-%m-%d %H:%M')
|
223
223
|
end
|
224
224
|
end
|
225
225
|
|
@@ -441,8 +441,11 @@ class JobInvocationComposer
|
|
441
441
|
end
|
442
442
|
|
443
443
|
def valid?
|
444
|
-
|
445
|
-
triggering
|
444
|
+
unless triggering.valid?
|
445
|
+
job_invocation.errors.add(:triggering, 'is invalid')
|
446
|
+
return false
|
447
|
+
end
|
448
|
+
targeting.valid? & job_invocation.valid? & !pattern_template_invocations.map(&:valid?).include?(false)
|
446
449
|
end
|
447
450
|
|
448
451
|
def save
|
data/app/models/job_template.rb
CHANGED
@@ -32,6 +32,8 @@ class JobTemplate < ::Template
|
|
32
32
|
scoped_search :on => :snippet, :complete_value => {:true => true, :false => false}
|
33
33
|
scoped_search :on => :provider_type, :complete_value => true
|
34
34
|
scoped_search :on => :template
|
35
|
+
scoped_search :relation => :remote_execution_features, :on => :name, :rename => 'feature.name'
|
36
|
+
scoped_search :relation => :remote_execution_features, :on => :label, :rename => 'feature.label'
|
35
37
|
|
36
38
|
# with proc support, default_scope can no longer be chained
|
37
39
|
# include all default scoping here
|
@@ -28,6 +28,10 @@ class RemoteExecutionProvider
|
|
28
28
|
providers.keys.map(&:to_s)
|
29
29
|
end
|
30
30
|
|
31
|
+
def provider_proxy_features
|
32
|
+
providers.values.map(&:proxy_feature).flatten.uniq.compact
|
33
|
+
end
|
34
|
+
|
31
35
|
def proxy_command_options(template_invocation, host)
|
32
36
|
{:proxy_operation_name => proxy_operation_name}.merge(proxy_command_provider_inputs(template_invocation))
|
33
37
|
end
|
@@ -16,6 +16,7 @@ class TemplateInvocation < ApplicationRecord
|
|
16
16
|
belongs_to :host, :class_name => 'Host::Managed', :foreign_key => :host_id
|
17
17
|
has_one :host_group, :through => :host, :source => :hostgroup
|
18
18
|
belongs_to :run_host_job_task, :class_name => 'ForemanTasks::Task'
|
19
|
+
has_many :remote_execution_features, :through => :template
|
19
20
|
|
20
21
|
validates_associated :input_values
|
21
22
|
validate :provides_required_input_values
|
@@ -25,6 +26,7 @@ class TemplateInvocation < ApplicationRecord
|
|
25
26
|
scoped_search :relation => :host_group, :on => :name, :rename => 'host_group.name', :complete_value => true
|
26
27
|
scoped_search :relation => :template, :on => :job_category, :complete_value => true
|
27
28
|
scoped_search :relation => :template, :on => :name, :complete_value => true
|
29
|
+
scoped_search :relation => :remote_execution_features, :on => :name, :rename => 'feature'
|
28
30
|
|
29
31
|
class TaskResultMap
|
30
32
|
MAP = {
|
@@ -7,7 +7,7 @@ class RemoteExecutionProxySelector < ::ForemanTasks::ProxySelector
|
|
7
7
|
return proxies if capability.nil?
|
8
8
|
|
9
9
|
proxies.reduce({}) do |acc, (strategy, possible_proxies)|
|
10
|
-
acc.merge(strategy => possible_proxies.select { |proxy| proxy.has_capability?(capability) })
|
10
|
+
acc.merge(strategy => possible_proxies.select { |proxy| proxy.has_capability?(provider, capability) })
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="tab-pane" id="rex_proxies">
|
2
2
|
<%= fields_for :subnet do |f| %>
|
3
|
-
<%= multiple_selects f, :remote_execution_proxies, SmartProxy.authorized.with_features(*RemoteExecutionProvider.
|
3
|
+
<%= multiple_selects f, :remote_execution_proxies, SmartProxy.authorized.with_features(*RemoteExecutionProvider.provider_proxy_features).distinct, @subnet.remote_execution_proxy_ids, {:label => _("Proxies"), :help_inline => _("Select as many remote execution proxies as applicable for this subnet. When multiple proxies with the same provider are added, actions will be load balanced among them.")} %>
|
4
4
|
<% end %>
|
5
5
|
</div>
|
@@ -16,6 +16,11 @@ template_inputs:
|
|
16
16
|
input_type: user
|
17
17
|
required: true
|
18
18
|
options: "install\nupdate\nremove\ngroup install\ngroup remove"
|
19
|
+
- name: options
|
20
|
+
description: Additional options for the package manager
|
21
|
+
input_type: user
|
22
|
+
required: false
|
23
|
+
advanced: true
|
19
24
|
- name: package
|
20
25
|
description: The name of the package, if any
|
21
26
|
input_type: user
|
@@ -87,7 +92,7 @@ handle_zypp_res_codes () {
|
|
87
92
|
|
88
93
|
# Action
|
89
94
|
<% if package_manager == 'yum' -%>
|
90
|
-
yum -y <%= action %> <%= input("package") %>
|
95
|
+
yum -y <%= input("options") %> <%= action %> <%= input("package") %>
|
91
96
|
<% elsif package_manager == 'apt' -%>
|
92
97
|
<%-
|
93
98
|
action = 'install' if action == 'group install'
|
@@ -103,7 +108,7 @@ handle_zypp_res_codes () {
|
|
103
108
|
[ -x "$(command -v subscription-manager)" ] && subscription-manager refresh
|
104
109
|
export DEBIAN_FRONTEND=noninteractive
|
105
110
|
apt-get -y update
|
106
|
-
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y <%= action %> <%= input("package") %>
|
111
|
+
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y <%= input("options") %> <%= action %> <%= input("package") %>
|
107
112
|
<% elsif package_manager == 'zypper' -%>
|
108
113
|
<%-
|
109
114
|
if action == "group install"
|
@@ -113,7 +118,7 @@ handle_zypp_res_codes () {
|
|
113
118
|
end
|
114
119
|
-%>
|
115
120
|
zypper refresh
|
116
|
-
zypper -n <%= action %> <%= input("package") %>
|
121
|
+
zypper -n <%= action %> <%= input("options") %> <%= input("package") %>
|
117
122
|
handle_zypp_res_codes $?
|
118
123
|
<% end -%>
|
119
124
|
RETVAL=$?
|
data/config/routes.rb
CHANGED
@@ -46,8 +46,10 @@ Rails.application.routes.draw do
|
|
46
46
|
get 'ui_job_wizard/categories', to: 'ui_job_wizard#categories'
|
47
47
|
get 'ui_job_wizard/template/:id', to: 'ui_job_wizard#template'
|
48
48
|
get 'ui_job_wizard/resources', to: 'ui_job_wizard#resources'
|
49
|
+
get 'ui_job_wizard/job_invocation', to: 'ui_job_wizard#job_invocation'
|
49
50
|
|
50
|
-
match '/experimental/job_wizard', to: 'react#index', :via => [:get]
|
51
|
+
match '/experimental/job_wizard/new', to: 'react#index', :via => [:get]
|
52
|
+
match '/experimental/job_wizard/:id/rerun', to: 'react#index', :via => [:get]
|
51
53
|
|
52
54
|
namespace :api, :defaults => {:format => 'json'} do
|
53
55
|
scope '(:apiv)', :module => :v2, :defaults => {:apiv => 'v2'}, :apiv => /v1|v2/, :constraints => ApiConstraints.new(:version => 2, :default => true) do
|
@@ -47,7 +47,7 @@ module ForemanRemoteExecution
|
|
47
47
|
|
48
48
|
initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |_app|
|
49
49
|
Foreman::Plugin.register :foreman_remote_execution do
|
50
|
-
requires_foreman '>= 3.
|
50
|
+
requires_foreman '>= 3.4'
|
51
51
|
register_global_js_file 'global'
|
52
52
|
|
53
53
|
apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
|
@@ -152,7 +152,7 @@ module ForemanRemoteExecution
|
|
152
152
|
setting 'remote_execution_job_invocation_report_template',
|
153
153
|
type: :string,
|
154
154
|
description: N_('Select a report template used for generating a report for a particular remote execution job'),
|
155
|
-
default: 'Job
|
155
|
+
default: 'Job - Invocation Report',
|
156
156
|
full_name: N_('Job Invocation Report Template'),
|
157
157
|
collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
|
158
158
|
end
|
@@ -164,7 +164,7 @@ module ForemanRemoteExecution
|
|
164
164
|
:'api/v2/job_templates' => [:index, :show, :revision, :export],
|
165
165
|
:'api/v2/template_inputs' => [:index, :show],
|
166
166
|
:'api/v2/foreign_input_sets' => [:index, :show],
|
167
|
-
:ui_job_wizard => [:categories, :template, :resources]}, :resource_type => 'JobTemplate'
|
167
|
+
:ui_job_wizard => [:categories, :template, :resources, :job_invocation]}, :resource_type => 'JobTemplate'
|
168
168
|
permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
|
169
169
|
:'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
|
170
170
|
permission :edit_job_templates, { :job_templates => [:edit, :update],
|
@@ -181,7 +181,7 @@ module ForemanRemoteExecution
|
|
181
181
|
permission :view_job_invocations, { :job_invocations => [:index, :chart, :show, :auto_complete_search], :template_invocations => [:show],
|
182
182
|
'api/v2/job_invocations' => [:index, :show, :output, :raw_output, :outputs] }, :resource_type => 'JobInvocation'
|
183
183
|
permission :view_template_invocations, { :template_invocations => [:show],
|
184
|
-
'api/v2/template_invocations' => [:template_invocations] }, :resource_type => 'TemplateInvocation'
|
184
|
+
'api/v2/template_invocations' => [:template_invocations], :ui_job_wizard => [:job_invocation] }, :resource_type => 'TemplateInvocation'
|
185
185
|
permission :create_template_invocations, {}, :resource_type => 'TemplateInvocation'
|
186
186
|
permission :execute_jobs_on_infrastructure_hosts, {}, :resource_type => 'JobInvocation'
|
187
187
|
permission :cancel_job_invocations, { :job_invocations => [:cancel], 'api/v2/job_invocations' => [:cancel] }, :resource_type => 'JobInvocation'
|
@@ -242,7 +242,7 @@ module ForemanRemoteExecution
|
|
242
242
|
url_hash: { controller: 'job_wizard', action: :index },
|
243
243
|
caption: N_('Job wizard'),
|
244
244
|
parent: :lab_features_menu,
|
245
|
-
url: '/experimental/job_wizard',
|
245
|
+
url: '/experimental/job_wizard/new',
|
246
246
|
after: :host_wizard
|
247
247
|
|
248
248
|
register_custom_status HostStatus::ExecutionStatus
|
@@ -275,6 +275,7 @@ module ForemanRemoteExecution
|
|
275
275
|
|
276
276
|
# Extend Registration module
|
277
277
|
extend_allowed_registration_vars :remote_execution_interface
|
278
|
+
extend_allowed_registration_vars :setup_remote_execution_pull
|
278
279
|
ForemanTasks.dynflow.eager_load_actions!
|
279
280
|
extend_observable_events(
|
280
281
|
::Dynflow::Action.descendants.select do |klass|
|
@@ -82,6 +82,14 @@ module Api
|
|
82
82
|
assert_response :success
|
83
83
|
end
|
84
84
|
|
85
|
+
test 'should propagate errors from triggering' do
|
86
|
+
@attrs[:recurrence] = { cron_line: 'foo' }
|
87
|
+
post :create, params: { job_invocation: @attrs }
|
88
|
+
invocation = ActiveSupport::JSON.decode(@response.body)
|
89
|
+
assert_match(/foo is not valid format of cron line/, invocation['error']['message'])
|
90
|
+
assert_response 500
|
91
|
+
end
|
92
|
+
|
85
93
|
test 'should create with schedule' do
|
86
94
|
@attrs[:scheduling] = { start_at: Time.now.to_s }
|
87
95
|
post :create, params: { job_invocation: @attrs }
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
|
5
|
+
class ApiParamsTest < ActiveSupport::TestCase
|
6
|
+
describe '#format_datetime' do
|
7
|
+
let(:params) { JobInvocationComposer::ApiParams.allocate }
|
8
|
+
|
9
|
+
it 'leaves empty string as is' do
|
10
|
+
assert_equal params.send(:format_datetime, ''), ''
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'honors explicitly supplied time zone' do
|
14
|
+
in_time_zone(ActiveSupport::TimeZone['America/New_York']) do
|
15
|
+
assert_equal '2022-07-08 08:53', params.send(:format_datetime, '2022-07-08 12:53:20 UTC')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'implicitly honors current user\'s time zone' do
|
20
|
+
in_time_zone(ActiveSupport::TimeZone['America/New_York']) do
|
21
|
+
assert_equal '2022-07-08 12:53', params.send(:format_datetime, '2022-07-08 12:53:20')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def in_time_zone(zone)
|
27
|
+
old_tz = Time.zone
|
28
|
+
Time.zone = zone
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
Time.zone = old_tz
|
32
|
+
end
|
33
|
+
end
|
@@ -9,7 +9,7 @@ class JobReportTemplateTest < ActiveSupport::TestCase
|
|
9
9
|
|
10
10
|
context 'with valid job invocation report template' do
|
11
11
|
let(:job_invocation_template) do
|
12
|
-
file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/
|
12
|
+
file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/job_-_invocation_report.erb"))
|
13
13
|
template = ReportTemplate.import_without_save("Job Invocation Report Template", file_path)
|
14
14
|
template.save!
|
15
15
|
template
|
@@ -95,9 +95,8 @@ class JobInvocationTest < ActiveSupport::TestCase
|
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'truncates generated description to 255 characters' do
|
98
|
-
column_limit = 255
|
98
|
+
column_limit = 255 # There is a 255 character limit on the database level
|
99
99
|
expected_result = 'a' * column_limit
|
100
|
-
JobInvocation.columns_hash['description'].expects(:limit).returns(column_limit)
|
101
100
|
job_invocation.description_format = '%{job_category}'
|
102
101
|
job_invocation.job_category = 'a' * 1000
|
103
102
|
job_invocation.generate_description
|
@@ -33,6 +33,10 @@ class RemoteExecutionProviderTest < ActiveSupport::TestCase
|
|
33
33
|
it 'accepts strings' do
|
34
34
|
RemoteExecutionProvider.provider_for('SSH').must_equal SSHExecutionProvider
|
35
35
|
end
|
36
|
+
|
37
|
+
it 'returns a default one if unknown value is provided' do
|
38
|
+
RemoteExecutionProvider.provider_for('WinRM').must_equal ScriptExecutionProvider
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
describe '.provider_names' do
|
@@ -52,6 +56,28 @@ class RemoteExecutionProviderTest < ActiveSupport::TestCase
|
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
59
|
+
describe '.provider_proxy_features' do
|
60
|
+
it 'returns correct values' do
|
61
|
+
RemoteExecutionProvider.stubs(:providers).returns(
|
62
|
+
:SSH => SSHExecutionProvider,
|
63
|
+
:script => ScriptExecutionProvider
|
64
|
+
)
|
65
|
+
|
66
|
+
features = RemoteExecutionProvider.provider_proxy_features
|
67
|
+
_(features).must_include 'SSH'
|
68
|
+
_(features).must_include 'Script'
|
69
|
+
RemoteExecutionProvider.unstub(:providers)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'can deal with non-arrays' do
|
73
|
+
provider = OpenStruct.new(proxy_feature: 'Testing')
|
74
|
+
RemoteExecutionProvider.stubs(:providers).returns(:testing => provider)
|
75
|
+
features = RemoteExecutionProvider.provider_proxy_features
|
76
|
+
_(features).must_include 'Testing'
|
77
|
+
RemoteExecutionProvider.unstub(:providers)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
55
81
|
describe '.host_setting' do
|
56
82
|
let(:host) { FactoryBot.create(:host) }
|
57
83
|
|