foreman_remote_execution 4.3.1 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/job_invocations_controller.rb +16 -0
- data/app/controllers/foreman_remote_execution/concerns/api/v2/registration_commands_controller_extensions.rb +19 -0
- data/app/helpers/remote_execution_helper.rb +27 -0
- data/app/lib/foreman_remote_execution/provider_input.rb +29 -0
- data/app/models/invocation_provider_input_value.rb +12 -0
- data/app/models/job_invocation.rb +4 -0
- data/app/models/job_invocation_composer.rb +13 -0
- data/app/models/remote_execution_provider.rb +17 -2
- data/app/models/setting/remote_execution.rb +10 -0
- data/app/models/template_invocation.rb +2 -0
- data/app/services/renderer_methods.rb +12 -0
- data/app/views/job_invocations/_form.html.erb +8 -0
- data/db/migrate/20210312074713_add_provider_inputs.rb +10 -0
- data/foreman_remote_execution.gemspec +1 -1
- data/lib/foreman_remote_execution/engine.rb +5 -6
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/locale/action_names.rb +1 -0
- data/locale/de/foreman_remote_execution.po +77 -27
- data/locale/en/foreman_remote_execution.po +77 -27
- data/locale/en_GB/foreman_remote_execution.po +77 -27
- data/locale/es/foreman_remote_execution.po +77 -27
- data/locale/foreman_remote_execution.pot +241 -163
- data/locale/fr/foreman_remote_execution.po +77 -27
- data/locale/ja/foreman_remote_execution.po +77 -27
- data/locale/ko/foreman_remote_execution.po +77 -27
- data/locale/pt_BR/foreman_remote_execution.po +77 -27
- data/locale/ru/foreman_remote_execution.po +77 -27
- data/locale/zh_CN/foreman_remote_execution.po +77 -27
- data/locale/zh_TW/foreman_remote_execution.po +77 -27
- data/package.json +3 -2
- data/test/helpers/remote_execution_helper_test.rb +16 -0
- data/test/unit/job_invocation_composer_test.rb +41 -1
- data/test/unit/job_invocation_report_template_test.rb +57 -0
- data/webpack/JobWizard/JobWizard.js +30 -7
- data/webpack/JobWizard/JobWizard.scss +12 -0
- data/webpack/JobWizard/JobWizardConstants.js +5 -0
- data/webpack/JobWizard/JobWizardSelectors.js +21 -0
- data/webpack/JobWizard/__tests__/JobWizard.test.js +20 -0
- data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +83 -0
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +77 -0
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +45 -0
- data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +64 -0
- data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +86 -0
- data/webpack/JobWizard/steps/form/GroupedSelectField.js +88 -0
- data/webpack/JobWizard/steps/form/SelectField.js +39 -0
- data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +38 -0
- data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +23 -0
- data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +36 -0
- data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +22 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +1 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +5 -0
- data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +10 -0
- data/webpack/fills_index.js +11 -0
- data/webpack/global_index.js +4 -0
- data/webpack/index.js +0 -4
- data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +87 -0
- data/webpack/react_app/components/RecentJobsCard/constants.js +1 -0
- data/webpack/react_app/components/RecentJobsCard/index.js +1 -0
- data/webpack/react_app/components/RecentJobsCard/styles.css +15 -0
- data/webpack/react_app/components/RegistrationExtension/RexInterface.js +50 -0
- data/webpack/react_app/components/RegistrationExtension/__tests__/RexInterface.test.js +9 -0
- data/webpack/react_app/components/RegistrationExtension/__tests__/__snapshots__/RexInterface.test.js.snap +35 -0
- data/webpack/react_app/extend/fills.js +10 -0
- data/webpack/react_app/extend/reducers.js +4 -0
- metadata +39 -5
- data/app/views/api/v2/registration/_form.html.erb +0 -12
@@ -26,6 +26,11 @@ msgstr "%s 之前"
|
|
26
26
|
msgid "%{description} on %{host}"
|
27
27
|
msgstr "%{description} 於 %{host} 之上"
|
28
28
|
|
29
|
+
msgid "...and %{count} more"
|
30
|
+
msgid_plural "...and %{count} more"
|
31
|
+
msgstr[0] ""
|
32
|
+
msgstr[1] ""
|
33
|
+
|
29
34
|
msgid "A comma separated list of input names to be excluded from the foreign template."
|
30
35
|
msgstr "從外部範本排除的輸入名稱清單,以逗號隔開。"
|
31
36
|
|
@@ -53,6 +58,12 @@ msgstr "動作"
|
|
53
58
|
msgid "Add Foreign Input Set"
|
54
59
|
msgstr "新增外部輸入集"
|
55
60
|
|
61
|
+
msgid "Advanced fields"
|
62
|
+
msgstr ""
|
63
|
+
|
64
|
+
msgid "All fields are required."
|
65
|
+
msgstr ""
|
66
|
+
|
56
67
|
msgid "Alphabetical"
|
57
68
|
msgstr ""
|
58
69
|
|
@@ -95,6 +106,12 @@ msgstr "無法指定 bookmark_id 和 search_query"
|
|
95
106
|
msgid "Cannot specify both recurrence and scheduling"
|
96
107
|
msgstr "無法指定 recurrence 和 scheduling"
|
97
108
|
|
109
|
+
msgid "Category And Template"
|
110
|
+
msgstr ""
|
111
|
+
|
112
|
+
msgid "Category and template"
|
113
|
+
msgstr ""
|
114
|
+
|
98
115
|
msgid "Choose a job template that is pre-selected in job invocation form"
|
99
116
|
msgstr ""
|
100
117
|
|
@@ -125,6 +142,9 @@ msgstr ""
|
|
125
142
|
msgid "Control concurrency level and distribution over time"
|
126
143
|
msgstr "隨時間控制週期等級並散佈"
|
127
144
|
|
145
|
+
msgid "Could not display data for job invocation."
|
146
|
+
msgstr ""
|
147
|
+
|
128
148
|
msgid "Could not find any suitable interface for execution"
|
129
149
|
msgstr ""
|
130
150
|
|
@@ -227,6 +247,12 @@ msgstr "有效使用者方法 \"%{current_value}\" 並非 %{valid_methods} 之
|
|
227
247
|
msgid "Effective user options"
|
228
248
|
msgstr "有效的使用者選項"
|
229
249
|
|
250
|
+
msgid "Effective user password"
|
251
|
+
msgstr ""
|
252
|
+
|
253
|
+
msgid "Effective user password is only applicable for SSH provider. Other providers ignore this field. <br> Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution."
|
254
|
+
msgstr ""
|
255
|
+
|
230
256
|
msgid "Enable Global Proxy"
|
231
257
|
msgstr ""
|
232
258
|
|
@@ -263,18 +289,12 @@ msgstr "已失敗"
|
|
263
289
|
msgid "Failed rendering template: %s"
|
264
290
|
msgstr "無法生成範本:%s"
|
265
291
|
|
266
|
-
msgid "Fallback Without Proxy"
|
267
|
-
msgstr ""
|
268
|
-
|
269
292
|
msgid "Fallback to Any Proxy"
|
270
293
|
msgstr ""
|
271
294
|
|
272
295
|
msgid "Feature input %{input_name} not defined in template %{template_name}"
|
273
296
|
msgstr "未知的輸入 %{input_name} 未定義於範本 %{template_name}"
|
274
297
|
|
275
|
-
msgid "Filter"
|
276
|
-
msgstr "篩選器"
|
277
|
-
|
278
298
|
msgid "Foreign input set"
|
279
299
|
msgstr "外部輸入集"
|
280
300
|
|
@@ -287,6 +307,9 @@ msgstr ""
|
|
287
307
|
msgid "Get output for a host"
|
288
308
|
msgstr "取得主機輸出"
|
289
309
|
|
310
|
+
msgid "Get outputs of hosts in a job"
|
311
|
+
msgstr ""
|
312
|
+
|
290
313
|
msgid "Get raw output for a host"
|
291
314
|
msgstr ""
|
292
315
|
|
@@ -305,9 +328,15 @@ msgstr ""
|
|
305
328
|
msgid "Host with id '%{id}' was not found"
|
306
329
|
msgstr "找不到 ID 為 '%{id}' 的主機"
|
307
330
|
|
331
|
+
msgid "Hosts gone missing"
|
332
|
+
msgstr ""
|
333
|
+
|
308
334
|
msgid "How often the job should occur, in the cron format"
|
309
335
|
msgstr "工作多常發生,格式同 cron"
|
310
336
|
|
337
|
+
msgid "Identifier of the Host interface for Remote execution"
|
338
|
+
msgstr ""
|
339
|
+
|
311
340
|
msgid "Import"
|
312
341
|
msgstr "匯入"
|
313
342
|
|
@@ -335,6 +364,12 @@ msgstr "輸入集的描述"
|
|
335
364
|
msgid "Inputs to use"
|
336
365
|
msgstr "要使用的輸入"
|
337
366
|
|
367
|
+
msgid "Interface with the '%s' identifier was specified as a remote execution interface, however the interface was not found on the host. If the interface exists, it needs to be created in Foreman during the registration."
|
368
|
+
msgstr ""
|
369
|
+
|
370
|
+
msgid "Internal proxy selector can only be used if Katello is enabled"
|
371
|
+
msgstr ""
|
372
|
+
|
338
373
|
msgid "Invocation type, one of %s"
|
339
374
|
msgstr "祈願類型,%s 之一"
|
340
375
|
|
@@ -386,6 +421,9 @@ msgstr ""
|
|
386
421
|
msgid "Job templates"
|
387
422
|
msgstr "工作範本"
|
388
423
|
|
424
|
+
msgid "Job wizard"
|
425
|
+
msgstr ""
|
426
|
+
|
389
427
|
msgid "JobTemplate|Locked"
|
390
428
|
msgstr "JobTemplate|Locked"
|
391
429
|
|
@@ -431,6 +469,9 @@ msgstr "列出各個位置上的工作範本"
|
|
431
469
|
msgid "List job templates per organization"
|
432
470
|
msgstr "列出各個組織的工作範本"
|
433
471
|
|
472
|
+
msgid "List of proxy IDs to be used for remote execution"
|
473
|
+
msgstr ""
|
474
|
+
|
434
475
|
msgid "List remote execution features"
|
435
476
|
msgstr "列出遠端執行功能"
|
436
477
|
|
@@ -458,6 +499,9 @@ msgstr "新工作範本"
|
|
458
499
|
msgid "No execution finished yet"
|
459
500
|
msgstr "尚無執行完成"
|
460
501
|
|
502
|
+
msgid "No hosts found."
|
503
|
+
msgstr ""
|
504
|
+
|
461
505
|
msgid "No template mapped to feature %{feature_name}"
|
462
506
|
msgstr "沒有範本定義至功能 %{feature_name}"
|
463
507
|
|
@@ -500,6 +544,9 @@ msgstr "此時間之後不再進行任何執行"
|
|
500
544
|
msgid "Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port."
|
501
545
|
msgstr ""
|
502
546
|
|
547
|
+
msgid "Preupgrade job"
|
548
|
+
msgstr ""
|
549
|
+
|
503
550
|
msgid "Preview"
|
504
551
|
msgstr "預覽"
|
505
552
|
|
@@ -539,6 +586,9 @@ msgstr "遠端執行"
|
|
539
586
|
msgid "Remote Execution Features"
|
540
587
|
msgstr "遠端執行功能"
|
541
588
|
|
589
|
+
msgid "Remote Execution Interface"
|
590
|
+
msgstr ""
|
591
|
+
|
542
592
|
msgid "Remote action:"
|
543
593
|
msgstr "遠端動作:"
|
544
594
|
|
@@ -578,6 +628,9 @@ msgstr "解析至"
|
|
578
628
|
msgid "Results"
|
579
629
|
msgstr ""
|
580
630
|
|
631
|
+
msgid "Review details"
|
632
|
+
msgstr ""
|
633
|
+
|
581
634
|
msgid "Run"
|
582
635
|
msgstr "執行"
|
583
636
|
|
@@ -593,6 +646,9 @@ msgstr "一次最多執行 N 個任務"
|
|
593
646
|
msgid "Run at most N tasks at a time. If this is set and proxy batch triggering is enabled, then tasks are triggered on the smart proxy in batches of size 1."
|
594
647
|
msgstr ""
|
595
648
|
|
649
|
+
msgid "Run job"
|
650
|
+
msgstr ""
|
651
|
+
|
596
652
|
msgid "SSH"
|
597
653
|
msgstr "SSH"
|
598
654
|
|
@@ -629,9 +685,6 @@ msgstr "捲動至底端"
|
|
629
685
|
msgid "Scroll to top"
|
630
686
|
msgstr "捲動至頂端"
|
631
687
|
|
632
|
-
msgid "Search"
|
633
|
-
msgstr "搜尋"
|
634
|
-
|
635
688
|
msgid "Search Query"
|
636
689
|
msgstr ""
|
637
690
|
|
@@ -659,6 +712,12 @@ msgstr ""
|
|
659
712
|
msgid "Should the ip addresses on host interfaces be preferred over the fqdn? It is useful when DNS not resolving the fqdns properly. You may override this per host by setting a parameter called remote_execution_connect_by_ip. This setting only applies to IPv4. When the host has only an IPv6 address on the interface used for remote execution, hostname will be used even if this setting is set to true."
|
660
713
|
msgstr ""
|
661
714
|
|
715
|
+
msgid "Should this interface be used for remote execution?"
|
716
|
+
msgstr ""
|
717
|
+
|
718
|
+
msgid "Show Job status for the hosts"
|
719
|
+
msgstr ""
|
720
|
+
|
662
721
|
msgid "Show foreign input set details"
|
663
722
|
msgstr "顯示外部輸入集的詳細資料"
|
664
723
|
|
@@ -689,12 +748,6 @@ msgstr "已成功"
|
|
689
748
|
msgid "Success"
|
690
749
|
msgstr "成功"
|
691
750
|
|
692
|
-
msgid "Sudo password"
|
693
|
-
msgstr ""
|
694
|
-
|
695
|
-
msgid "Sudo password is only applicable for SSH provider. Other providers ignore this field. <br> Password is stored encrypted in DB until the job finishes. For future or recurring executions, it is removed after the last execution."
|
696
|
-
msgstr ""
|
697
|
-
|
698
751
|
msgid "Sync Job Templates"
|
699
752
|
msgstr ""
|
700
753
|
|
@@ -760,6 +813,9 @@ msgstr "使用者無法存取範本 %{template_name} 對應至功能 %{feature_n
|
|
760
813
|
msgid "There was an error while updating the status, try refreshing the page."
|
761
814
|
msgstr "更新狀態時發生錯誤,請更新此頁面。"
|
762
815
|
|
816
|
+
msgid "This can happen if the host is removed or moved to another organization or location after the job was started"
|
817
|
+
msgstr ""
|
818
|
+
|
763
819
|
msgid "This template is locked for editing."
|
764
820
|
msgstr "此範本已鎖定,因此無法編輯。"
|
765
821
|
|
@@ -886,9 +942,6 @@ msgstr "哪位使用者該用來執行此 script(使用類似 sudo 機制)"
|
|
886
942
|
msgid "What user should be used to run the script (using sudo-like mechanisms). Defaults to a template parameter or global setting."
|
887
943
|
msgstr "哪位使用者該用來執行此 script(使用類似 sudo 機制)。預設值設為範本參數或全域設定。"
|
888
944
|
|
889
|
-
msgid "When enabled, the remote execution will try to run the commands directly, when no proxy with remote execution feature is configured for the host."
|
890
|
-
msgstr ""
|
891
|
-
|
892
945
|
msgid "When enabled, working directories will be removed after task completion. You may override this per host by setting a parameter called remote_execution_cleanup_working_dirs."
|
893
946
|
msgstr ""
|
894
947
|
|
@@ -922,9 +975,15 @@ msgstr "為此範本新增輸入集,以參照至不同的範本輸入"
|
|
922
975
|
msgid "cancelled"
|
923
976
|
msgstr "已取消"
|
924
977
|
|
978
|
+
msgid "default_capsule method missing from SmartProxy"
|
979
|
+
msgstr ""
|
980
|
+
|
925
981
|
msgid "effective user"
|
926
982
|
msgstr ""
|
927
983
|
|
984
|
+
msgid "error"
|
985
|
+
msgstr ""
|
986
|
+
|
928
987
|
msgid "error during rendering: %s"
|
929
988
|
msgstr "處理時發生錯誤:%s"
|
930
989
|
|
@@ -949,9 +1008,6 @@ msgstr "找不到包含的範本 '%s'"
|
|
949
1008
|
msgid "input macro with name '%s' used, but no input with such name defined for this template"
|
950
1009
|
msgstr "使用了名為 '%s' 的輸入巨集,但此範本並未輸入這樣的名稱"
|
951
1010
|
|
952
|
-
msgid "planned"
|
953
|
-
msgstr ""
|
954
|
-
|
955
1011
|
msgid "queued"
|
956
1012
|
msgstr "已排程"
|
957
1013
|
|
@@ -961,9 +1017,6 @@ msgstr ""
|
|
961
1017
|
msgid "remove template input set"
|
962
1018
|
msgstr "移除範本輸入集"
|
963
1019
|
|
964
|
-
msgid "running"
|
965
|
-
msgstr "執行中"
|
966
|
-
|
967
1020
|
msgid "running %{percent}%%"
|
968
1021
|
msgstr ""
|
969
1022
|
|
@@ -973,9 +1026,6 @@ msgstr "秒"
|
|
973
1026
|
msgid "succeeded"
|
974
1027
|
msgstr "已成功"
|
975
1028
|
|
976
|
-
msgid "success"
|
977
|
-
msgstr "成功"
|
978
|
-
|
979
1029
|
msgid "tasks at a time"
|
980
1030
|
msgstr ""
|
981
1031
|
|
data/package.json
CHANGED
@@ -28,9 +28,10 @@
|
|
28
28
|
"@theforeman/vendor-dev": "^4.14.0",
|
29
29
|
"babel-eslint": "^10.0.0",
|
30
30
|
"eslint": "^6.8.0",
|
31
|
-
"prettier": "^1.19.1"
|
31
|
+
"prettier": "^1.19.1",
|
32
|
+
"@patternfly/react-catalog-view-extension": "^4.8.126"
|
32
33
|
},
|
33
34
|
"peerDependencies": {
|
34
|
-
"@theforeman/vendor": "
|
35
|
+
"@theforeman/vendor": "^8.3.0"
|
35
36
|
}
|
36
37
|
}
|
@@ -23,4 +23,20 @@ class RemoteExecutionHelperTest < ActionView::TestCase
|
|
23
23
|
"Exit status: 0"])
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
describe 'test correct setting' do
|
28
|
+
it 'should found correct template from setting' do
|
29
|
+
Setting::RemoteExecution.load_defaults
|
30
|
+
template_name = 'Job Invocation Report Template'
|
31
|
+
setting_key = 'remote_execution_job_invocation_report_template'
|
32
|
+
template = FactoryBot.create(:report_template, name: template_name)
|
33
|
+
input = FactoryBot.create(:template_input, name: 'job_id', input_type: 'user')
|
34
|
+
template.template_inputs << input
|
35
|
+
Setting.expects(:[]).with(setting_key).returns(template_name)
|
36
|
+
|
37
|
+
found_template = job_report_template
|
38
|
+
|
39
|
+
assert_equal template.id, found_template.id
|
40
|
+
end
|
41
|
+
end
|
26
42
|
end
|
@@ -16,16 +16,34 @@ class JobInvocationComposerTest < ActiveSupport::TestCase
|
|
16
16
|
setup_user('create', 'hosts')
|
17
17
|
end
|
18
18
|
|
19
|
+
class AnsibleInputs < RemoteExecutionProvider
|
20
|
+
class << self
|
21
|
+
def provider_input_namespace
|
22
|
+
:ansible
|
23
|
+
end
|
24
|
+
|
25
|
+
def provider_inputs
|
26
|
+
[
|
27
|
+
ForemanRemoteExecution::ProviderInput.new(name: 'tags', label: 'Tags', value: 'fooo', value_type: 'plain'),
|
28
|
+
ForemanRemoteExecution::ProviderInput.new(name: 'tags_flag', label: 'Tags Flag', value: '--tags', options: "--tags\n--skip-tags"),
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
RemoteExecutionProvider.register(:AnsibleInputs, AnsibleInputs)
|
34
|
+
|
19
35
|
let(:trying_job_template_1) { FactoryBot.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying1', :provider_type => 'SSH') }
|
20
36
|
let(:trying_job_template_2) { FactoryBot.create(:job_template, :job_category => 'trying_job_template_2', :name => 'trying2', :provider_type => 'Mcollective') }
|
21
37
|
let(:trying_job_template_3) { FactoryBot.create(:job_template, :job_category => 'trying_job_template_1', :name => 'trying3', :provider_type => 'SSH') }
|
22
38
|
let(:unauthorized_job_template_1) { FactoryBot.create(:job_template, :job_category => 'trying_job_template_1', :name => 'unauth1', :provider_type => 'SSH') }
|
23
39
|
let(:unauthorized_job_template_2) { FactoryBot.create(:job_template, :job_category => 'unauthorized_job_template_2', :name => 'unauth2', :provider_type => 'Ansible') }
|
24
40
|
|
41
|
+
let(:provider_inputs_job_template) { FactoryBot.create(:job_template, :job_category => 'trying_test_inputs', :name => 'trying provider inputs', :provider_type => 'AnsibleInputs') }
|
25
42
|
|
26
43
|
let(:input1) { FactoryBot.create(:template_input, :template => trying_job_template_1, :input_type => 'user') }
|
27
44
|
let(:input2) { FactoryBot.create(:template_input, :template => trying_job_template_3, :input_type => 'user') }
|
28
45
|
let(:input3) { FactoryBot.create(:template_input, :template => trying_job_template_1, :input_type => 'user', :required => true) }
|
46
|
+
let(:input4) { FactoryBot.create(:template_input, :template => provider_inputs_job_template, :input_type => 'user') }
|
29
47
|
let(:unauthorized_input1) { FactoryBot.create(:template_input, :template => unauthorized_job_template_1, :input_type => 'user') }
|
30
48
|
|
31
49
|
let(:ansible_params) { { } }
|
@@ -605,7 +623,9 @@ class JobInvocationComposerTest < ActiveSupport::TestCase
|
|
605
623
|
end
|
606
624
|
|
607
625
|
describe '#from_api_params' do
|
608
|
-
let(:composer)
|
626
|
+
let(:composer) do
|
627
|
+
JobInvocationComposer.from_api_params(params)
|
628
|
+
end
|
609
629
|
let(:bookmark) { bookmarks(:one) }
|
610
630
|
|
611
631
|
context 'with targeting from bookmark' do
|
@@ -659,6 +679,26 @@ class JobInvocationComposerTest < ActiveSupport::TestCase
|
|
659
679
|
end
|
660
680
|
end
|
661
681
|
|
682
|
+
context 'with provider inputs' do
|
683
|
+
let(:params) do
|
684
|
+
{ :job_category => provider_inputs_job_template.job_category,
|
685
|
+
:job_template_id => provider_inputs_job_template.id,
|
686
|
+
:targeting_type => 'static_query',
|
687
|
+
:search_query => 'some hosts',
|
688
|
+
:inputs => { input4.name => 'some_value' },
|
689
|
+
:ansible => { 'tags' => 'bar', 'tags_flag' => '--skip-tags' } }
|
690
|
+
end
|
691
|
+
|
692
|
+
it 'detects provider inputs' do
|
693
|
+
assert composer.save!
|
694
|
+
scope = composer.job_invocation.pattern_template_invocations.first.provider_input_values
|
695
|
+
tags = scope.find_by :name => 'tags'
|
696
|
+
flags = scope.find_by :name => 'tags_flag'
|
697
|
+
assert_equal 'bar', tags.value
|
698
|
+
assert_equal '--skip-tags', flags.value
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
662
702
|
context 'with effective user' do
|
663
703
|
let(:params) do
|
664
704
|
{ :job_category => trying_job_template_1.job_category,
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class JobReportTemplateTest < ActiveSupport::TestCase
|
4
|
+
class FakeTask < OpenStruct
|
5
|
+
class Jail < Safemode::Jail
|
6
|
+
allow :action_continuous_output, :result, :ended_at
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'with valid job invocation report template' do
|
11
|
+
let(:job_invocation_template) do
|
12
|
+
file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/jobs_-_invocation_report_template.erb"))
|
13
|
+
template = ReportTemplate.import_without_save("Job Invocation Report Template", file_path)
|
14
|
+
template.save!
|
15
|
+
template
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'template setting' do
|
19
|
+
it 'in settings includes only report templates with job_id input' do
|
20
|
+
FactoryBot.create(:report_template, name: 'Template 1')
|
21
|
+
job_invocation_template
|
22
|
+
templates = Setting::RemoteExecution.job_invocation_report_templates_select
|
23
|
+
|
24
|
+
assert_include templates, 'Job Invocation Report Template'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'task reporting' do
|
29
|
+
let(:fake_outputs) do
|
30
|
+
[
|
31
|
+
{ 'output_type' => 'stderr', 'output' => "error", 'timestamp' => Time.new(2020, 12, 1, 0, 0, 0).utc },
|
32
|
+
{ 'output_type' => 'stdout', 'output' => "output", 'timestamp' => Time.new(2020, 12, 1, 0, 0, 0).utc },
|
33
|
+
{ 'output_type' => 'stdebug', 'output' => "debug", 'timestamp' => Time.new(2020, 12, 1, 0, 0, 0).utc },
|
34
|
+
]
|
35
|
+
end
|
36
|
+
let(:fake_task) { FakeTask.new(result: 'success', action_continuous_output: fake_outputs) }
|
37
|
+
|
38
|
+
it 'should render task outputs' do
|
39
|
+
job_invocation = FactoryBot.create(:job_invocation, :with_task)
|
40
|
+
JobInvocation.any_instance.expects(:sub_task_for_host).returns(fake_task)
|
41
|
+
|
42
|
+
input = job_invocation_template.template_inputs.first
|
43
|
+
composer_params = { template_id: job_invocation_template.id, input_values: { input.id.to_s => { value: job_invocation.id.to_s } } }
|
44
|
+
result = ReportComposer.new(composer_params).render
|
45
|
+
|
46
|
+
# parsing the CSV result
|
47
|
+
CSV.parse(result.strip, headers: true).each_with_index do |row, i|
|
48
|
+
row_hash = row.to_h
|
49
|
+
assert_equal 'success', row_hash['result']
|
50
|
+
assert_equal fake_outputs[i]['output_type'], row_hash['type']
|
51
|
+
assert_equal fake_outputs[i]['output'], row_hash['message']
|
52
|
+
assert_kind_of Time, Time.zone.parse(row_hash['time']), 'Parsing of time column failed'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,21 +1,45 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useState } from 'react';
|
2
2
|
import { Wizard } from '@patternfly/react-core';
|
3
3
|
import { translate as __ } from 'foremanReact/common/I18n';
|
4
4
|
import history from 'foremanReact/history';
|
5
|
+
import CategoryAndTemplate from './steps/CategoryAndTemplate/';
|
6
|
+
import './JobWizard.scss';
|
5
7
|
|
6
8
|
export const JobWizard = () => {
|
9
|
+
const [jobTemplate, setJobTemplate] = useState(null);
|
10
|
+
const [category, setCategory] = useState('');
|
7
11
|
const steps = [
|
8
12
|
{
|
9
13
|
name: __('Category and template'),
|
10
|
-
component:
|
14
|
+
component: (
|
15
|
+
<CategoryAndTemplate
|
16
|
+
jobTemplate={jobTemplate}
|
17
|
+
setJobTemplate={setJobTemplate}
|
18
|
+
category={category}
|
19
|
+
setCategory={setCategory}
|
20
|
+
/>
|
21
|
+
),
|
22
|
+
},
|
23
|
+
{
|
24
|
+
name: __('Target hosts'),
|
25
|
+
component: <p>TargetHosts </p>,
|
26
|
+
canJumpTo: !!jobTemplate,
|
27
|
+
},
|
28
|
+
{
|
29
|
+
name: __('Advanced fields'),
|
30
|
+
component: <p> AdvancedFields </p>,
|
31
|
+
canJumpTo: !!jobTemplate,
|
32
|
+
},
|
33
|
+
{
|
34
|
+
name: __('Schedule'),
|
35
|
+
component: <p>Schedule</p>,
|
36
|
+
canJumpTo: !!jobTemplate,
|
11
37
|
},
|
12
|
-
{ name: __('Target hosts'), component: <p>TargetHosts </p> },
|
13
|
-
{ name: __('Advanced fields'), component: <p> AdvancedFields </p> },
|
14
|
-
{ name: __('Schedule'), component: <p>Schedule</p> },
|
15
38
|
{
|
16
39
|
name: __('Review details'),
|
17
40
|
component: <p>ReviewDetails</p>,
|
18
41
|
nextButtonText: 'Run',
|
42
|
+
canJumpTo: !!jobTemplate,
|
19
43
|
},
|
20
44
|
];
|
21
45
|
const title = __('Run Job');
|
@@ -25,8 +49,7 @@ export const JobWizard = () => {
|
|
25
49
|
navAriaLabel={`${title} steps`}
|
26
50
|
steps={steps}
|
27
51
|
height="70vh"
|
52
|
+
className="job-wizard"
|
28
53
|
/>
|
29
54
|
);
|
30
55
|
};
|
31
|
-
|
32
|
-
export default JobWizard;
|