foreman_remote_execution 17.2.3 → 18.0.0
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/foreman_remote_execution/locale/fr/foreman_remote_execution.js +7 -7
- data/app/assets/javascripts/foreman_remote_execution/locale/ja/foreman_remote_execution.js +27 -27
- data/app/assets/javascripts/foreman_remote_execution/locale/ko/foreman_remote_execution.js +8 -8
- data/app/assets/javascripts/foreman_remote_execution/locale/zh_CN/foreman_remote_execution.js +1 -1
- data/app/controllers/api/v2/foreign_input_sets_controller.rb +4 -0
- data/app/models/remote_execution_provider.rb +1 -1
- data/db/seeds.d/60-ssh_proxy_feature.rb +2 -2
- data/db/seeds.d/90-bookmarks.rb +1 -1
- data/db/seeds.d/95-mail_notifications.rb +1 -1
- data/lib/foreman_remote_execution/plugin.rb +1 -1
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/fr/foreman_remote_execution.po +7 -7
- data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/ja/foreman_remote_execution.po +27 -27
- data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/ko/foreman_remote_execution.po +8 -8
- data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/zh_CN/foreman_remote_execution.po +1 -1
- data/test/unit/remote_execution_provider_test.rb +1 -1
- data/webpack/JobInvocationDetail/JobInvocationConstants.js +10 -0
- data/webpack/JobInvocationDetail/JobInvocationHostTable.js +8 -1
- data/webpack/JobInvocationDetail/__tests__/JobInvocationHostTablePolling.test.js +113 -7
- data/webpack/JobInvocationDetail/__tests__/areAllHostsTerminal.test.js +40 -0
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +191 -212
- metadata +3 -8
|
@@ -195,7 +195,7 @@ msgid "Cancel job invocation or matching tasks only"
|
|
|
195
195
|
msgstr "ジョブ呼び出しまたは一致するタスクのみをキャンセルします"
|
|
196
196
|
|
|
197
197
|
msgid "Cancel recurring"
|
|
198
|
-
msgstr "
|
|
198
|
+
msgstr "繰り返しのキャンセル"
|
|
199
199
|
|
|
200
200
|
msgid "Cancel selected"
|
|
201
201
|
msgstr "選択項目をキャンセル"
|
|
@@ -378,13 +378,13 @@ msgid "Default SSH password"
|
|
|
378
378
|
msgstr "デフォルトの SSH パスワード"
|
|
379
379
|
|
|
380
380
|
msgid "Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase"
|
|
381
|
-
msgstr "SSH に使用するデフォルトの鍵パスフレーズ。remote_execution_ssh_key_passphrase
|
|
381
|
+
msgstr "SSH に使用するデフォルトの鍵パスフレーズ。remote_execution_ssh_key_passphrase という名前のパラメーターを設定することにより、ホストごとに上書きできます"
|
|
382
382
|
|
|
383
383
|
msgid "Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password"
|
|
384
|
-
msgstr "SSH に使用するデフォルトパスワード。remote_execution_ssh_password
|
|
384
|
+
msgstr "SSH に使用するデフォルトパスワード。remote_execution_ssh_password という名前のパラメーターを設定することにより、ホストごとに上書きできます"
|
|
385
385
|
|
|
386
386
|
msgid "Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user."
|
|
387
|
-
msgstr "SSH に使用するデフォルトユーザー。remote_execution_ssh_user
|
|
387
|
+
msgstr "SSH に使用するデフォルトユーザー。remote_execution_ssh_user という名前のパラメーターを設定することにより、ホストごとに上書きできます。"
|
|
388
388
|
|
|
389
389
|
msgid "Default user to use for executing the script. If the user differs from the SSH user, su or sudo is used to switch the user."
|
|
390
390
|
msgstr "スクリプトを実行するために使用するデフォルトユーザー。ユーザーが SSH ユーザーと異なる場合は、su または sudo を使用してユーザーを切り替えます。"
|
|
@@ -408,7 +408,7 @@ msgid "Designation of a special purpose"
|
|
|
408
408
|
msgstr "特別な目的の指定"
|
|
409
409
|
|
|
410
410
|
msgid "Disable recurring"
|
|
411
|
-
msgstr "
|
|
411
|
+
msgstr "繰り返しの無効化"
|
|
412
412
|
|
|
413
413
|
msgid "Display advanced fields"
|
|
414
414
|
msgstr "詳細フィールドを表示"
|
|
@@ -468,7 +468,7 @@ msgid "Enable Global Proxy"
|
|
|
468
468
|
msgstr "グローバルプロキシーを有効にする"
|
|
469
469
|
|
|
470
470
|
msgid "Enable recurring"
|
|
471
|
-
msgstr "
|
|
471
|
+
msgstr "繰り返しの有効化"
|
|
472
472
|
|
|
473
473
|
msgid "End time needs to be after start time"
|
|
474
474
|
msgstr "終了時刻は開始時刻の後でなければなりません"
|
|
@@ -828,7 +828,7 @@ msgid "Manual selection"
|
|
|
828
828
|
msgstr "手動選択"
|
|
829
829
|
|
|
830
830
|
msgid "Minute can only be a number between 0-59"
|
|
831
|
-
msgstr "分は 0
|
|
831
|
+
msgstr "分は 0-59 の間の数字のみ指定できます。"
|
|
832
832
|
|
|
833
833
|
msgid "Missing the required permissions: ${missingPermissions.join( ', ' )}"
|
|
834
834
|
msgstr "必須パーミッションがありません: ${missingPermissions.join( ', ' )}"
|
|
@@ -861,10 +861,10 @@ msgid "Next occurrence"
|
|
|
861
861
|
msgstr "次の実行"
|
|
862
862
|
|
|
863
863
|
msgid "No (override)"
|
|
864
|
-
msgstr "No (
|
|
864
|
+
msgstr "No (上書き)"
|
|
865
865
|
|
|
866
866
|
msgid "No Results"
|
|
867
|
-
msgstr "
|
|
867
|
+
msgstr "結果なし"
|
|
868
868
|
|
|
869
869
|
msgid "No Target Hosts"
|
|
870
870
|
msgstr "ターゲットホストがありません"
|
|
@@ -882,7 +882,7 @@ msgid "No output for the selected filters"
|
|
|
882
882
|
msgstr "選択したフィルターの出力はありません"
|
|
883
883
|
|
|
884
884
|
msgid "No results found"
|
|
885
|
-
msgstr "
|
|
885
|
+
msgstr "結果は見つかりませんでした"
|
|
886
886
|
|
|
887
887
|
msgid "No template mapped to feature %{feature_name}"
|
|
888
888
|
msgstr "機能 %{feature_name} にマッピングされたテンプレートがありません"
|
|
@@ -930,19 +930,19 @@ msgid "Open selected in new tab"
|
|
|
930
930
|
msgstr "選択項目を新規タブで開きます"
|
|
931
931
|
|
|
932
932
|
msgid "Opening job invocation form"
|
|
933
|
-
msgstr "
|
|
933
|
+
msgstr "ジョブ呼び出しフォームを開く"
|
|
934
934
|
|
|
935
935
|
msgid "Organization"
|
|
936
936
|
msgstr "組織"
|
|
937
937
|
|
|
938
938
|
msgid "Override the description format from the template for this invocation only"
|
|
939
|
-
msgstr "
|
|
939
|
+
msgstr "この呼び出しに対してのみテンプレートから説明形式を上書き"
|
|
940
940
|
|
|
941
941
|
msgid "Override the global time to pickup interval for this invocation only"
|
|
942
|
-
msgstr "
|
|
942
|
+
msgstr "グローバル時間をこの呼び出しだけの取得間隔に上書きする"
|
|
943
943
|
|
|
944
944
|
msgid "Override the timeout interval from the template for this invocation only"
|
|
945
|
-
msgstr "
|
|
945
|
+
msgstr "この呼び出しに対してのみテンプレートからタイムアウト間隔を上書き"
|
|
946
946
|
|
|
947
947
|
msgid "Overview"
|
|
948
948
|
msgstr "概要"
|
|
@@ -975,7 +975,7 @@ msgid "Please enter a search query"
|
|
|
975
975
|
msgstr "検索クエリーを入力してください"
|
|
976
976
|
|
|
977
977
|
msgid "Please go back to \\\"Schedule\\\" - \\\"Future execution\\\" or \\\"Recurring execution\\\" step to fix the error"
|
|
978
|
-
msgstr "エラーを修正するには、スケジュール -
|
|
978
|
+
msgstr "エラーを修正するには、スケジュール - 後で実行または定期的な実行の手順に戻ってください。"
|
|
979
979
|
|
|
980
980
|
msgid "Please go back to \\\"Schedule\\\" - \\\"Future execution\\\" step to fix the error"
|
|
981
981
|
msgstr "「スケジュール」- 「後で実行」の手順に戻り、エラーを修正してください"
|
|
@@ -993,7 +993,7 @@ msgid "Please select at least one host"
|
|
|
993
993
|
msgstr "ホストを 1 つ以上選択してください"
|
|
994
994
|
|
|
995
995
|
msgid "Please select at least one host collection"
|
|
996
|
-
msgstr "ホストコレクションを少なくとも 1
|
|
996
|
+
msgstr "ホストコレクションを少なくとも 1 つ選択してください。"
|
|
997
997
|
|
|
998
998
|
msgid "Please select at least one host group"
|
|
999
999
|
msgstr "少なくとも 1 つのホストグループを選択してください"
|
|
@@ -1002,7 +1002,7 @@ msgid "Popups are blocked by your browser. Please allow popups for this site to
|
|
|
1002
1002
|
msgstr "ブラウザーでポップアップがブロックされています。このサイトのすべての呼び出しを新しいタブで開くには、ポップアップを許可してください。"
|
|
1003
1003
|
|
|
1004
1004
|
msgid "Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port."
|
|
1005
|
-
msgstr "SSH 通信に使用するポート。デフォルトのポートは 22 です。remote_execution_ssh_port
|
|
1005
|
+
msgstr "SSH 通信に使用するポート。デフォルトのポートは 22 です。remote_execution_ssh_port という名前のパラメーターを設定することにより、ホストごとに上書きできます。"
|
|
1006
1006
|
|
|
1007
1007
|
msgid "Prefer IPv6 over IPv4"
|
|
1008
1008
|
msgstr "IPv4 よりも IPv6 を優先する"
|
|
@@ -1071,16 +1071,16 @@ msgid "Recurring execution"
|
|
|
1071
1071
|
msgstr "繰り返し実行"
|
|
1072
1072
|
|
|
1073
1073
|
msgid "Recurring logic"
|
|
1074
|
-
msgstr "
|
|
1074
|
+
msgstr "再帰論理"
|
|
1075
1075
|
|
|
1076
1076
|
msgid "Recurring logic %s cancelled successfully."
|
|
1077
|
-
msgstr "
|
|
1077
|
+
msgstr "再帰論理 %s が正常にキャンセルされました。"
|
|
1078
1078
|
|
|
1079
1079
|
msgid "Recurring logic %s disabled successfully."
|
|
1080
|
-
msgstr "
|
|
1080
|
+
msgstr "再帰論理 %s が正常に無効になりました。"
|
|
1081
1081
|
|
|
1082
1082
|
msgid "Recurring logic %s enabled successfully."
|
|
1083
|
-
msgstr "
|
|
1083
|
+
msgstr "再帰論理 %s が正常に有効になりました。"
|
|
1084
1084
|
|
|
1085
1085
|
msgid "Recursive rendering of templates detected"
|
|
1086
1086
|
msgstr "検出されたテンプレートの再帰的なレンダリング"
|
|
@@ -1311,7 +1311,7 @@ msgid "Setup remote execution pull mode. If set to `Yes`, pull provider client w
|
|
|
1311
1311
|
msgstr "リモート実行のプルモードを設定します。`はい` に設定すると、登録したホストにプルプロパイダークライアントがデプロイされます。継承される値は、`host_registration_remote_execution_pull` パラメーターに基づきます。これは、ホストグループ、オペレーティングシステム、組織などから継承できます。オーバーライドされると、選択した値がホストパラメーターレベルで保存されます。"
|
|
1312
1312
|
|
|
1313
1313
|
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. For dual-stacked hosts you should consider the remote_execution_connect_by_ip_prefer_ipv6 setting"
|
|
1314
|
-
msgstr "ホストインターフェイスの ip アドレスは fqdn よりも優先されますか? DNS が fqdn を適切に解決しない場合、これは役に立ちます。remote_execution_connect_by_ip
|
|
1314
|
+
msgstr "ホストインターフェイスの ip アドレスは fqdn よりも優先されますか? DNS が fqdn を適切に解決しない場合、これは役に立ちます。remote_execution_connect_by_ip というパラメーターを設定し、ホストごとにこれを上書きすることができます。デュアルスタックのホストの場合は、remote_execution_connect_by_ip_prefer_ipv6 設定を検討する必要があります"
|
|
1315
1315
|
|
|
1316
1316
|
msgid "Should this interface be used for remote execution?"
|
|
1317
1317
|
msgstr "このインターフェイスをリモート実行に使用する必要がありますか?"
|
|
@@ -1380,7 +1380,7 @@ msgid "Static query"
|
|
|
1380
1380
|
msgstr "静的クエリー"
|
|
1381
1381
|
|
|
1382
1382
|
msgid "Status"
|
|
1383
|
-
msgstr "
|
|
1383
|
+
msgstr "ステータス"
|
|
1384
1384
|
|
|
1385
1385
|
msgid "Submit"
|
|
1386
1386
|
msgstr "送信"
|
|
@@ -1720,16 +1720,16 @@ msgid "What user should be used to run the script (using sudo-like mechanisms).
|
|
|
1720
1720
|
msgstr "スクリプトを実行するために使用するユーザー (sudo と同様のメカニズムを使用)。デフォルト値は、テンプレートパラメーターまたはグローバル設定です。"
|
|
1721
1721
|
|
|
1722
1722
|
msgid "When connecting using ip address, should the IPv6 addresses be preferred? If no IPv6 address is set, it falls back to IPv4 automatically. You may override this per host by setting a parameter called remote_execution_connect_by_ip_prefer_ipv6. By default and for compatibility, IPv4 will be preferred over IPv6 by default"
|
|
1723
|
-
msgstr "ip address を使用して接続する場合は、IPv6 アドレスを優先する必要がありますか? IPv6 アドレスが設定されていない場合は、IPv4 に自動的にフォールバックします。remote_execution_connect_by_ip_prefer_ipv6
|
|
1723
|
+
msgstr "ip address を使用して接続する場合は、IPv6 アドレスを優先する必要がありますか? IPv6 アドレスが設定されていない場合は、IPv4 に自動的にフォールバックします。remote_execution_connect_by_ip_prefer_ipv6 というパラメーターを設定し、ホストごとにこれを上書きすることができます。互換性のために、デフォルトでは IPv4 が IPv6 よりも優先されます"
|
|
1724
1724
|
|
|
1725
1725
|
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."
|
|
1726
|
-
msgstr "有効にすると、作業ディレクトリーはタスクの完了後に削除されます。remote_execution_cleanup_working_dirs
|
|
1726
|
+
msgstr "有効にすると、作業ディレクトリーはタスクの完了後に削除されます。remote_execution_cleanup_working_dirs と呼ばれるパラメーターを設定して、ホストごとにこれを上書きすることができます。"
|
|
1727
1727
|
|
|
1728
1728
|
msgid "Where to find the Cockpit instance for the Web Console button. By default, no button is shown."
|
|
1729
1729
|
msgstr "Web コンソールボタンの Cockpit インスタンスを検索する場所。デフォルトでは、ボタンは表示されません。"
|
|
1730
1730
|
|
|
1731
1731
|
msgid "Whether it should be allowed to override the effective user from the invocation form."
|
|
1732
|
-
msgstr "
|
|
1732
|
+
msgstr "呼び出し形式から実効ユーザーを上書きするのを許可するかどうか。"
|
|
1733
1733
|
|
|
1734
1734
|
msgid "Whether or not the template is locked for editing"
|
|
1735
1735
|
msgstr "テンプレートの編集機能をロックするかどうか"
|
|
@@ -1744,7 +1744,7 @@ msgid "Whether we should sync templates from disk when running db:seed."
|
|
|
1744
1744
|
msgstr "db:seed を実行するときにディスクからテンプレートを同期するかどうか。"
|
|
1745
1745
|
|
|
1746
1746
|
msgid "Yes (override)"
|
|
1747
|
-
msgstr "Yes (
|
|
1747
|
+
msgstr "Yes (上書き)"
|
|
1748
1748
|
|
|
1749
1749
|
msgid "You are not allowed to see the currently assigned template. Saving the form now would unassign the template."
|
|
1750
1750
|
msgstr "現在割り当てられているテンプレートを参照できません。フォームを保存すると、テンプレートの割り当てが解除されます。"
|
|
Binary file
|
|
@@ -360,7 +360,7 @@ msgid "Daily"
|
|
|
360
360
|
msgstr "매일"
|
|
361
361
|
|
|
362
362
|
msgid "Date must be in the future"
|
|
363
|
-
msgstr "날짜는
|
|
363
|
+
msgstr "날짜는 미래여야 합니다."
|
|
364
364
|
|
|
365
365
|
msgid "Days"
|
|
366
366
|
msgstr "일"
|
|
@@ -423,7 +423,7 @@ msgid "Dynamic query"
|
|
|
423
423
|
msgstr "동적 쿼리"
|
|
424
424
|
|
|
425
425
|
msgid "Edit %s"
|
|
426
|
-
msgstr "%s 편집"
|
|
426
|
+
msgstr "%s 편집 "
|
|
427
427
|
|
|
428
428
|
msgid "Edit Job Template"
|
|
429
429
|
msgstr "작업 템플릿 편집"
|
|
@@ -837,7 +837,7 @@ msgid "Must select a bookmark or enter a search query"
|
|
|
837
837
|
msgstr "북마크를 선택하거나 검색 쿼리를 입력해야 합니다."
|
|
838
838
|
|
|
839
839
|
msgid "N/A"
|
|
840
|
-
msgstr "해당 없음"
|
|
840
|
+
msgstr "해당 없음 "
|
|
841
841
|
|
|
842
842
|
msgid "Name"
|
|
843
843
|
msgstr "이름 "
|
|
@@ -1341,7 +1341,7 @@ msgid "Smart proxy"
|
|
|
1341
1341
|
msgstr "스마트 프록시"
|
|
1342
1342
|
|
|
1343
1343
|
msgid "Snippet"
|
|
1344
|
-
msgstr "
|
|
1344
|
+
msgstr "조각 모음 "
|
|
1345
1345
|
|
|
1346
1346
|
msgid "Start"
|
|
1347
1347
|
msgstr "시작"
|
|
@@ -1377,7 +1377,7 @@ msgid "Static query"
|
|
|
1377
1377
|
msgstr "정적 쿼리"
|
|
1378
1378
|
|
|
1379
1379
|
msgid "Status"
|
|
1380
|
-
msgstr "상태"
|
|
1380
|
+
msgstr "상태 "
|
|
1381
1381
|
|
|
1382
1382
|
msgid "Submit"
|
|
1383
1383
|
msgstr "보내기"
|
|
@@ -1525,7 +1525,7 @@ msgid "This can happen if the host is removed or moved to another organization o
|
|
|
1525
1525
|
msgstr "작업이 시작된 후 호스트가 제거되거나 다른 조직이나 위치로 이동된 경우 이러한 문제가 발생할 수 있습니다."
|
|
1526
1526
|
|
|
1527
1527
|
msgid "This template is locked for editing."
|
|
1528
|
-
msgstr "이 템플릿은
|
|
1528
|
+
msgstr "이 템플릿은 편집 용으로 잠금되어 있습니다. "
|
|
1529
1529
|
|
|
1530
1530
|
msgid "This template is locked. Please clone it to a new template to customize."
|
|
1531
1531
|
msgstr "이 템플릿은 잠겨 있습니다. 사용자 정의하려면 이를 새 템플릿에 복제하십시오. "
|
|
@@ -1636,7 +1636,7 @@ msgid "Unable to save template. Correct highlighted errors"
|
|
|
1636
1636
|
msgstr "템플릿을 저장할 수 없습니다. 강조된 오류를 수정합니다."
|
|
1637
1637
|
|
|
1638
1638
|
msgid "Unknown"
|
|
1639
|
-
msgstr "알 수 없음"
|
|
1639
|
+
msgstr "알 수 없음 "
|
|
1640
1640
|
|
|
1641
1641
|
msgid "Unknown execution status"
|
|
1642
1642
|
msgstr "알 수 없는 실행 상태"
|
|
@@ -1729,7 +1729,7 @@ msgid "Whether it should be allowed to override the effective user from the invo
|
|
|
1729
1729
|
msgstr "호출할 유효 사용자를 덮어쓰도록 허용할지 여부입니다."
|
|
1730
1730
|
|
|
1731
1731
|
msgid "Whether or not the template is locked for editing"
|
|
1732
|
-
msgstr "
|
|
1732
|
+
msgstr "편집을 위한 템플릿의 잠금 여부 "
|
|
1733
1733
|
|
|
1734
1734
|
msgid "Whether the current user login should be used as the effective user"
|
|
1735
1735
|
msgstr "현재 사용자 로그인을 유효 사용자로 사용할지 여부입니다."
|
|
Binary file
|
|
@@ -1074,7 +1074,7 @@ msgid "Recurring logic"
|
|
|
1074
1074
|
msgstr "重复逻辑"
|
|
1075
1075
|
|
|
1076
1076
|
msgid "Recurring logic %s cancelled successfully."
|
|
1077
|
-
msgstr "
|
|
1077
|
+
msgstr "成功取消重复逻辑 %s。"
|
|
1078
1078
|
|
|
1079
1079
|
msgid "Recurring logic %s disabled successfully."
|
|
1080
1080
|
msgstr "成功禁用重复逻辑 %s。"
|
|
@@ -125,7 +125,7 @@ class RemoteExecutionProviderTest < ActiveSupport::TestCase
|
|
|
125
125
|
describe 'effective user' do
|
|
126
126
|
it 'takes the effective user from value from the template invocation' do
|
|
127
127
|
template_invocation.effective_user = 'my user'
|
|
128
|
-
assert_equal 'my
|
|
128
|
+
assert_equal 'my user', proxy_options[:effective_user]
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
@@ -55,6 +55,16 @@ export const STATUS_TITLES = {
|
|
|
55
55
|
NOT_STARTED: { id: 'N/A', title: __('Scheduled') },
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
export const TERMINAL_HOST_STATUSES = new Set([
|
|
59
|
+
'success',
|
|
60
|
+
'error',
|
|
61
|
+
'cancelled',
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
export const areAllHostsTerminal = results =>
|
|
65
|
+
results?.length > 0 &&
|
|
66
|
+
results.every(host => TERMINAL_HOST_STATUSES.has(host.job_status));
|
|
67
|
+
|
|
58
68
|
export const DATE_OPTIONS = {
|
|
59
69
|
day: 'numeric',
|
|
60
70
|
month: 'short',
|
|
@@ -42,6 +42,7 @@ import Columns, {
|
|
|
42
42
|
STATUS_UPPERCASE,
|
|
43
43
|
AWAITING_STATUS_FILTER,
|
|
44
44
|
AUTO_REFRESH_INTERVAL_MS,
|
|
45
|
+
areAllHostsTerminal,
|
|
45
46
|
} from './JobInvocationConstants';
|
|
46
47
|
import { TemplateInvocation } from './TemplateInvocation';
|
|
47
48
|
import { RowActions } from './TemplateInvocationComponents/TemplateActionButtons';
|
|
@@ -196,7 +197,13 @@ const JobInvocationHostTable = ({
|
|
|
196
197
|
if (thisRequest !== requestIdRef.current) return;
|
|
197
198
|
if (!mountedRef.current) return;
|
|
198
199
|
updateHostsState(data);
|
|
199
|
-
|
|
200
|
+
const hasActiveFilter = !!(
|
|
201
|
+
currentPollParams.current.search ||
|
|
202
|
+
currentPollParams.current.awaiting
|
|
203
|
+
);
|
|
204
|
+
const pageAllTerminal =
|
|
205
|
+
!hasActiveFilter && areAllHostsTerminal(data.data?.results);
|
|
206
|
+
if (!jobFinishedRef.current && !pageAllTerminal) {
|
|
200
207
|
pollTimeoutId.current = setTimeout(
|
|
201
208
|
() => makeApiCall(currentPollParams.current),
|
|
202
209
|
AUTO_REFRESH_INTERVAL_MS
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { render, act } from '@testing-library/react';
|
|
3
4
|
import '@testing-library/jest-dom';
|
|
@@ -44,13 +45,28 @@ const hostsResponse = {
|
|
|
44
45
|
operatingsystem_name: 'RHEL 9',
|
|
45
46
|
hostgroup_id: 1,
|
|
46
47
|
hostgroup_name: 'default',
|
|
47
|
-
job_status: '
|
|
48
|
+
job_status: 'running',
|
|
48
49
|
smart_proxy_id: 1,
|
|
49
50
|
smart_proxy_name: 'proxy1',
|
|
50
51
|
},
|
|
51
52
|
],
|
|
52
53
|
};
|
|
53
54
|
|
|
55
|
+
const terminalHostsResponse = {
|
|
56
|
+
...hostsResponse,
|
|
57
|
+
results: [{ ...hostsResponse.results[0], job_status: 'success' }],
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const mixedHostsResponse = {
|
|
61
|
+
...hostsResponse,
|
|
62
|
+
total: 2,
|
|
63
|
+
subtotal: 2,
|
|
64
|
+
results: [
|
|
65
|
+
{ ...hostsResponse.results[0], id: 1, job_status: 'success' },
|
|
66
|
+
{ ...hostsResponse.results[0], id: 2, job_status: 'running' },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
|
|
54
70
|
let apiGetSpy;
|
|
55
71
|
let hostsCalls;
|
|
56
72
|
let pendingCallbacks;
|
|
@@ -66,9 +82,9 @@ const flushPendingCallbacks = () => {
|
|
|
66
82
|
batch.forEach(cb => cb());
|
|
67
83
|
};
|
|
68
84
|
|
|
69
|
-
const renderTable = (props = {}) => {
|
|
85
|
+
const renderTable = (props = {}, historyEntries = ['/']) => {
|
|
70
86
|
const store = createStore();
|
|
71
|
-
const history = createMemoryHistory();
|
|
87
|
+
const history = createMemoryHistory({ initialEntries: historyEntries });
|
|
72
88
|
const Wrapper = createForemanContextWrapper();
|
|
73
89
|
|
|
74
90
|
const defaultProps = {
|
|
@@ -93,16 +109,14 @@ const renderTable = (props = {}) => {
|
|
|
93
109
|
return { ...result, store, history };
|
|
94
110
|
};
|
|
95
111
|
|
|
96
|
-
const setupSuccessMock = () => {
|
|
112
|
+
const setupSuccessMock = (response = hostsResponse) => {
|
|
97
113
|
apiGetSpy = jest
|
|
98
114
|
.spyOn(APIActions, 'get')
|
|
99
115
|
.mockImplementation(opts => dispatch => {
|
|
100
116
|
if (opts.key === JOB_INVOCATION_HOSTS) {
|
|
101
117
|
hostsCalls.push(opts);
|
|
102
118
|
if (opts.handleSuccess) {
|
|
103
|
-
pendingCallbacks.push(() =>
|
|
104
|
-
opts.handleSuccess({ data: hostsResponse })
|
|
105
|
-
);
|
|
119
|
+
pendingCallbacks.push(() => opts.handleSuccess({ data: response }));
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
});
|
|
@@ -311,6 +325,98 @@ describe('JobInvocationHostTable polling', () => {
|
|
|
311
325
|
expect(hostsCalls.length).toBeGreaterThan(callsAfterFilterChange);
|
|
312
326
|
});
|
|
313
327
|
|
|
328
|
+
it('stops polling when all hosts on the page are terminal', () => {
|
|
329
|
+
apiGetSpy.mockRestore();
|
|
330
|
+
setupSuccessMock(terminalHostsResponse);
|
|
331
|
+
|
|
332
|
+
renderTable();
|
|
333
|
+
|
|
334
|
+
expect(hostsCalls).toHaveLength(1);
|
|
335
|
+
|
|
336
|
+
act(() => {
|
|
337
|
+
flushPendingCallbacks();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
act(() => {
|
|
341
|
+
jest.advanceTimersByTime(10000);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
act(() => {
|
|
345
|
+
flushPendingCallbacks();
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
expect(hostsCalls).toHaveLength(1);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('continues polling when at least one host on the page is non-terminal', () => {
|
|
352
|
+
apiGetSpy.mockRestore();
|
|
353
|
+
setupSuccessMock(mixedHostsResponse);
|
|
354
|
+
|
|
355
|
+
renderTable();
|
|
356
|
+
|
|
357
|
+
expect(hostsCalls).toHaveLength(1);
|
|
358
|
+
|
|
359
|
+
act(() => {
|
|
360
|
+
flushPendingCallbacks();
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
act(() => {
|
|
364
|
+
jest.advanceTimersByTime(5000);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
act(() => {
|
|
368
|
+
flushPendingCallbacks();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
expect(hostsCalls).toHaveLength(2);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('continues polling when all hosts on the page are terminal but a status filter is active', () => {
|
|
375
|
+
apiGetSpy.mockRestore();
|
|
376
|
+
setupSuccessMock(terminalHostsResponse);
|
|
377
|
+
|
|
378
|
+
renderTable({ initialFilter: 'success' });
|
|
379
|
+
|
|
380
|
+
expect(hostsCalls).toHaveLength(1);
|
|
381
|
+
|
|
382
|
+
act(() => {
|
|
383
|
+
flushPendingCallbacks();
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
act(() => {
|
|
387
|
+
jest.advanceTimersByTime(5000);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
act(() => {
|
|
391
|
+
flushPendingCallbacks();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(hostsCalls).toHaveLength(2);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('continues polling when all hosts on the page are terminal but a search query is active', () => {
|
|
398
|
+
apiGetSpy.mockRestore();
|
|
399
|
+
setupSuccessMock(terminalHostsResponse);
|
|
400
|
+
|
|
401
|
+
renderTable({}, ['/?search=host1']);
|
|
402
|
+
|
|
403
|
+
expect(hostsCalls).toHaveLength(1);
|
|
404
|
+
|
|
405
|
+
act(() => {
|
|
406
|
+
flushPendingCallbacks();
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
act(() => {
|
|
410
|
+
jest.advanceTimersByTime(5000);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
act(() => {
|
|
414
|
+
flushPendingCallbacks();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
expect(hostsCalls).toHaveLength(2);
|
|
418
|
+
});
|
|
419
|
+
|
|
314
420
|
it('sends include_permissions only on the first request', () => {
|
|
315
421
|
renderTable();
|
|
316
422
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { areAllHostsTerminal } from '../JobInvocationConstants';
|
|
2
|
+
|
|
3
|
+
describe('areAllHostsTerminal', () => {
|
|
4
|
+
it('returns false for an empty results array', () => {
|
|
5
|
+
expect(areAllHostsTerminal([])).toBe(false);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('returns false for undefined results', () => {
|
|
9
|
+
expect(areAllHostsTerminal(undefined)).toBe(false);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('returns true when every host is in a terminal state', () => {
|
|
13
|
+
expect(
|
|
14
|
+
areAllHostsTerminal([
|
|
15
|
+
{ id: 1, job_status: 'success' },
|
|
16
|
+
{ id: 2, job_status: 'error' },
|
|
17
|
+
{ id: 3, job_status: 'cancelled' },
|
|
18
|
+
])
|
|
19
|
+
).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('returns false when at least one host is non-terminal', () => {
|
|
23
|
+
expect(
|
|
24
|
+
areAllHostsTerminal([
|
|
25
|
+
{ id: 1, job_status: 'success' },
|
|
26
|
+
{ id: 2, job_status: 'running' },
|
|
27
|
+
])
|
|
28
|
+
).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('returns false when every host is non-terminal', () => {
|
|
32
|
+
expect(
|
|
33
|
+
areAllHostsTerminal([
|
|
34
|
+
{ id: 1, job_status: 'running' },
|
|
35
|
+
{ id: 2, job_status: 'planned' },
|
|
36
|
+
{ id: 3, job_status: 'N/A' },
|
|
37
|
+
])
|
|
38
|
+
).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
});
|