foreman_rh_cloud 4.0.24 → 4.0.26
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/rh_cloud/inventory_controller.rb +4 -1
- data/app/controllers/foreman_inventory_upload/cloud_status_controller.rb +26 -0
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +23 -7
- data/app/controllers/insights_cloud/hits_controller.rb +0 -1
- data/app/models/insights_client_report_status.rb +8 -23
- data/app/services/foreman_rh_cloud/cloud_auth.rb +4 -0
- data/app/services/foreman_rh_cloud/cloud_ping_service.rb +83 -0
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +15 -3
- data/app/services/foreman_rh_cloud/insights_status_cleaner.rb +17 -0
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +5 -0
- data/config/Gemfile.lock.gh_test +74 -84
- data/config/rh_cert-api_chain.pem +74 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20210720000001_remove_old_insights_statuses.foreman_rh_cloud.rb +6 -0
- data/lib/foreman_inventory_upload/generators/queries.rb +0 -16
- data/lib/foreman_inventory_upload/generators/tags.rb +3 -1
- data/lib/foreman_rh_cloud/engine.rb +2 -3
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/foreman_rh_cloud.rb +4 -0
- data/lib/insights_cloud/async/insights_client_status_aging.rb +13 -3
- data/lib/insights_cloud/async/insights_full_sync.rb +9 -0
- data/lib/insights_cloud/async/insights_generate_notifications.rb +4 -0
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +16 -2
- data/lib/insights_cloud/async/insights_rules_sync.rb +15 -2
- data/lib/insights_cloud.rb +4 -0
- data/lib/inventory_sync/async/inventory_full_sync.rb +9 -0
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +9 -0
- data/lib/inventory_sync/async/inventory_scheduled_sync.rb +4 -0
- data/lib/inventory_sync/async/inventory_self_host_sync.rb +13 -0
- data/lib/inventory_sync/async/query_inventory_job.rb +4 -0
- data/lib/tasks/insights.rake +15 -0
- data/lib/tasks/rh_cloud_inventory.rake +2 -9
- data/package.json +1 -1
- data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +20 -39
- data/test/controllers/inventory_upload/cloud_status_controller_test.rb +44 -0
- data/test/jobs/insights_client_status_aging_test.rb +7 -7
- data/test/jobs/insights_full_sync_test.rb +1 -0
- data/test/jobs/insights_resolutions_sync_test.rb +11 -1
- data/test/jobs/insights_rules_sync_test.rb +1 -0
- data/test/jobs/inventory_full_sync_test.rb +10 -0
- data/test/jobs/inventory_hosts_sync_test.rb +1 -0
- data/test/jobs/inventory_self_host_sync_test.rb +1 -0
- data/test/models/insights_client_report_status_test.rb +70 -72
- data/test/test_plugin_helper.rb +53 -0
- data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +29 -34
- data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +66 -0
- data/test/unit/services/foreman_rh_cloud/insights_status_cleaner_test.rb +31 -0
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -0
- data/test/unit/tags_generator_test.rb +41 -0
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/EmptyState.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/__tests__/__snapshots__/EmptyState.test.js.snap +1 -2
- data/webpack/ForemanInventoryUpload/Components/FileDownload/FileDownload.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/FileDownload/__tests__/__snapshots__/FileDownload.test.js.snap +2 -1
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -2
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilterConstants.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.scss +0 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +12 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +10 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +144 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +5 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/StatusChart/StatusChart.js +4 -3
- data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +2 -0
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
- data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +5 -1
- data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +6 -6
- data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +9 -5
- data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +6 -6
- data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +1 -14
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +4 -22
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +25 -4
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +51 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +3 -68
- data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +10 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +11 -10
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +14 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +0 -2
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +32 -0
- data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +5 -5
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +19 -13
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +82 -2
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +16 -6
- data/webpack/InsightsHostDetailsTab/InsightsTab.js +3 -2
- data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -4
- data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +9 -7
- data/webpack/common/Switcher/HelpLabel.js +1 -1
- data/webpack/common/Switcher/SwitcherPF4.js +1 -1
- data/webpack/common/Switcher/SwitcherPF4.scss +6 -7
- data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +1 -1
- data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -1
- metadata +18 -25
- data/app/subscribers/foreman_rh_cloud/insights_subscriber.rb +0 -9
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.fixtures.js +0 -1
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +0 -45
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/InsightsSyncSwitcher.test.js +0 -17
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/__snapshots__/InsightsSyncSwitcher.test.js.snap +0 -38
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/index.js +0 -1
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/insightsSyncSwitcher.scss +0 -3
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +0 -59
@@ -2,41 +2,10 @@ require 'test_plugin_helper'
|
|
2
2
|
require 'puma/null_io'
|
3
3
|
|
4
4
|
class CloudRequestForwarderTest < ActiveSupport::TestCase
|
5
|
+
include MockCerts
|
6
|
+
|
5
7
|
setup do
|
6
8
|
@forwarder = ::ForemanRhCloud::CloudRequestForwarder.new
|
7
|
-
|
8
|
-
@cert1 = "-----BEGIN CERTIFICATE-----\r\n" +
|
9
|
-
"MIIFdDCCA1ygAwIBAgIJAM5Uqykb3EAtMA0GCSqGSIb3DQEBCwUAME8xCzAJBgNV\r\n" +
|
10
|
-
"BAYTAklMMREwDwYDVQQIDAhUZWwgQXZpdjEUMBIGA1UECgwLVGhlIEZvcmVtYW4x\r\n" +
|
11
|
-
"FzAVBgNVBAMMDnRoZWZvcmVtYW4ub3JnMB4XDTE4MDMyNDEyMzYyOFoXDTI4MDMy\r\n" +
|
12
|
-
"MTEyMzYyOFowTzELMAkGA1UEBhMCSUwxETAPBgNVBAgMCFRlbCBBdml2MRQwEgYD\r\n" +
|
13
|
-
"VQQKDAtUaGUgRm9yZW1hbjEXMBUGA1UEAwwOdGhlZm9yZW1hbi5vcmcwggIiMA0G\r\n" +
|
14
|
-
"CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF04/s4h+BgHPG1HDZ/sDlYq925pkc\r\n" +
|
15
|
-
"RTVAfnE2EXDAmZ6W4Q9ueDY65MHe3ZWO5Dg72kNSP2sK9kRI7Dk5CAFOgyw1rH8t\r\n" +
|
16
|
-
"Hd1+0xp/lv6e4SvSYghxIL68vFe0ftKkm1usqejBM5ZTgKr7JCI+XSIN36F65Kde\r\n" +
|
17
|
-
"c+vxwBnayuhP04r9/aaE/709SXML4eRVYW8I3qFy9FPtUOm+bY8U2PIv5fHayqbG\r\n" +
|
18
|
-
"cL/4t3+MCtMhHJsLzdBXya+1P5t+HcKjUNlmwoUF961YAktVuEFloGd0RMRlqF3/\r\n" +
|
19
|
-
"itU3QNlXgA5QBIciE5VPr/PiqgMC3zgd5avjF4OribZ+N9AATLiQMW78il5wSfcc\r\n" +
|
20
|
-
"kQjU9ChOLrzku455vQ8KE4bc0qvpCWGfUah6MvL9JB+TQkRl/8kxl0b9ZinIvJDH\r\n" +
|
21
|
-
"ynVMb4cB/TDEjrjOfzn9mWLH0ZJqjmc2bER/G12WQxOaYLxdVwRStD3Yh6PtiFWu\r\n" +
|
22
|
-
"sXOk19UOTVkeuvGFVtvzLfEwQ1lDEo7+VBQz8FG/HBu2Hpq3IwCFrHuicikwjQJk\r\n" +
|
23
|
-
"nfturgD0rBOKEc1qWNZRCvovYOLL6ihvv5Orujsx5ZCHOAtnVNxkvIlFt2RS45LF\r\n" +
|
24
|
-
"MtPJyhAc6SjitllfUEirxprsbmeSZqrIfzcGaEhgOSnyik1WMv6bYiqPfBg8Fzjh\r\n" +
|
25
|
-
"vOCbtiDNPmvgOwIDAQABo1MwUTAdBgNVHQ4EFgQUtkAgQopsTtG9zSG3MgW2IxHD\r\n" +
|
26
|
-
"MDwwHwYDVR0jBBgwFoAUtkAgQopsTtG9zSG3MgW2IxHDMDwwDwYDVR0TAQH/BAUw\r\n" +
|
27
|
-
"AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAJq7iN+ZroRBweNhvUobxs75bLIV6tNn1\r\n" +
|
28
|
-
"MdNHDRA+hezwf+gxHZhFyaAHfTpst2/9leK5Qe5Zd6gZLr3E5/8ppQuRod72H39B\r\n" +
|
29
|
-
"vxMlG5zxDss0WMo3vZeKZbTY6QhXi/lY2IZ6OGV4feSvCsYxn27GTjjrRUSLFeHH\r\n" +
|
30
|
-
"JVemCwCDMavaE3+OIY4v2P4FcG+MjUvfOB9ahI24TWL7YgrsNVmJjCILq+EeUj0t\r\n" +
|
31
|
-
"Gde1SXVyLkqt7PoxHRJAE0BCEMJSnjxaVB329acJgeehBUxjj4CCPqtDxtbz9HEH\r\n" +
|
32
|
-
"mOKfNdaKpFor+DUeEKUWVGnr9U9xOaC+Ws+oX7MIEUCDM7p2ob4JwcjnFs1jZgHh\r\n" +
|
33
|
-
"Hwig+i7doTlc701PvKWO96fuNHK3B3/jTb1fVvSZ49O/RvY1VWODdUdxWmXGHNh3\r\n" +
|
34
|
-
"LoR8tSPEb46lC2DXGaIQumqQt8PnBG+vL1qkQa1SGTV7dJ8TTbxbv0S+sS+igkk9\r\n" +
|
35
|
-
"zsIEK8Ea3Ep935cXximz0faAAKHSA+It+xHLAyDtqy2KaAEBgGsBuuWlUfK6TaP3\r\n" +
|
36
|
-
"Gwdjct3y4yYUO45lUsUfHqX8vk/4ttW5zYeDiW+HArJz+9VUXNbEdury4kGuHgBj\r\n" +
|
37
|
-
"xHD4Bsul65+hHZ9QywKU26F1A6TLkYpQ2rk/Dx9LGICM4m4IlHjWJPFsQdtkyOor\r\n" +
|
38
|
-
"osxMtcaZZ1E=\r\n" +
|
39
|
-
"-----END CERTIFICATE-----"
|
40
9
|
end
|
41
10
|
|
42
11
|
test 'should prepare correct cloud url' do
|
@@ -48,10 +17,11 @@ class CloudRequestForwarderTest < ActiveSupport::TestCase
|
|
48
17
|
"/redhat_access/r/insights/platform/inventory/v1/hosts" => "https://cert.cloud.redhat.com/api/inventory/v1/hosts",
|
49
18
|
"/redhat_access/r/insights/platform/ingress/v1/upload" => "https://cert.cloud.redhat.com/api/ingress/v1/upload",
|
50
19
|
"/redhat_access/r/insights/uploads/67200803-132b-474b-a6f9-37be74185df4" => "https://cert-api.access.redhat.com/r/insights/uploads/67200803-132b-474b-a6f9-37be74185df4",
|
20
|
+
"/redhat_access/r/insights/" => "https://cert.cloud.redhat.com/api/apicast-tests/ping",
|
51
21
|
}
|
52
22
|
|
53
23
|
paths.each do |key, value|
|
54
|
-
actual_params = @forwarder.path_params(key,
|
24
|
+
actual_params = @forwarder.path_params(key, generate_certs_hash)
|
55
25
|
assert_equal value, actual_params[:url]
|
56
26
|
end
|
57
27
|
end
|
@@ -138,4 +108,29 @@ class CloudRequestForwarderTest < ActiveSupport::TestCase
|
|
138
108
|
)
|
139
109
|
assert_equal params.merge(:branch_id => 74), @forwarder.prepare_forward_params(req, 74)
|
140
110
|
end
|
111
|
+
|
112
|
+
test 'should reuse BranchInfo identifiers for user_agent' do
|
113
|
+
user_agent = { :foo => :bar }
|
114
|
+
params = { :page => 5, :per_page => 42 }
|
115
|
+
ForemanRhCloud::BranchInfo.any_instance.expects(:core_app_name).returns('test_app')
|
116
|
+
ForemanRhCloud::BranchInfo.any_instance.expects(:core_app_version).returns('test_ver')
|
117
|
+
|
118
|
+
req = ActionDispatch::Request.new(
|
119
|
+
'REQUEST_URI' => '/foo/bar',
|
120
|
+
'REQUEST_METHOD' => 'GET',
|
121
|
+
'HTTP_USER_AGENT' => user_agent,
|
122
|
+
'rack.input' => ::Puma::NullIO.new,
|
123
|
+
'action_dispatch.request.query_parameters' => params
|
124
|
+
)
|
125
|
+
|
126
|
+
actual = @forwarder.prepare_request_opts(req, 'TEST PAYLOAD', params, generate_certs_hash)
|
127
|
+
|
128
|
+
assert_match /foo/, actual[:headers][:user_agent]
|
129
|
+
assert_match /bar/, actual[:headers][:user_agent]
|
130
|
+
assert_match /test_app/, actual[:headers][:user_agent]
|
131
|
+
assert_match /test_ver/, actual[:headers][:user_agent]
|
132
|
+
assert_equal 'TEST PAYLOAD', actual[:payload]
|
133
|
+
assert_equal 'GET', actual[:method]
|
134
|
+
assert_equal params, actual[:headers][:params]
|
135
|
+
end
|
141
136
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class CloudStatusServiceTest < ActiveSupport::TestCase
|
4
|
+
include MockCerts
|
5
|
+
|
6
|
+
setup do
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'generates ping response for each org' do
|
10
|
+
organizations = FactoryBot.create_list(:organization, 2)
|
11
|
+
|
12
|
+
ForemanRhCloud::CloudPingService::TokenPing.any_instance.expects(:execute_cloud_request).returns(
|
13
|
+
RestClient::Response.new('TEST RESPONSE')
|
14
|
+
)
|
15
|
+
|
16
|
+
setup_certs_expectation do
|
17
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:candlepin_id_cert).with(organizations[0])
|
18
|
+
end
|
19
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:execute_cloud_request).returns(
|
20
|
+
RestClient::Response.new('TEST RESPONSE ORG 0')
|
21
|
+
)
|
22
|
+
|
23
|
+
setup_certs_expectation do
|
24
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:candlepin_id_cert).with(organizations[1])
|
25
|
+
end
|
26
|
+
|
27
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:execute_cloud_request).returns(
|
28
|
+
RestClient::Response.new('TEST RESPONSE ORG 1')
|
29
|
+
)
|
30
|
+
|
31
|
+
service = ForemanRhCloud::CloudPingService.new(organizations, nil)
|
32
|
+
actual = service.ping
|
33
|
+
|
34
|
+
assert actual[:token_auth][:success]
|
35
|
+
assert_nil actual[:token_auth][:error]
|
36
|
+
assert actual[:cert_auth][organizations[0]][:success]
|
37
|
+
assert_nil actual[:cert_auth][organizations[0]][:error]
|
38
|
+
assert actual[:cert_auth][organizations[1]][:success]
|
39
|
+
assert_nil actual[:cert_auth][organizations[1]][:error]
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'generates ping error response for org and token' do
|
43
|
+
organizations = FactoryBot.create_list(:organization, 1)
|
44
|
+
|
45
|
+
ForemanRhCloud::CloudPingService::TokenPing.any_instance.expects(:execute_cloud_request).raises(
|
46
|
+
RuntimeError,
|
47
|
+
'TEST RESPONSE TOKEN'
|
48
|
+
)
|
49
|
+
|
50
|
+
setup_certs_expectation do
|
51
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:candlepin_id_cert).with(organizations[0])
|
52
|
+
end
|
53
|
+
ForemanRhCloud::CloudPingService::CertPing.any_instance.expects(:execute_cloud_request).raises(
|
54
|
+
RuntimeError,
|
55
|
+
'TEST RESPONSE ORG 0'
|
56
|
+
)
|
57
|
+
|
58
|
+
service = ForemanRhCloud::CloudPingService.new(organizations, nil)
|
59
|
+
actual = service.ping
|
60
|
+
|
61
|
+
refute actual[:token_auth][:success]
|
62
|
+
assert_match /TEST RESPONSE TOKEN/, actual[:token_auth][:error]
|
63
|
+
refute actual[:cert_auth][organizations[0]][:success]
|
64
|
+
assert_match /TEST RESPONSE ORG 0/, actual[:cert_auth][organizations[0]][:error]
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class InsightsStatusCleanerTest < ActiveSupport::TestCase
|
4
|
+
setup do
|
5
|
+
@host1 = FactoryBot.create(:host)
|
6
|
+
@host2 = FactoryBot.create(:host)
|
7
|
+
|
8
|
+
InsightsClientReportStatus.find_or_initialize_by(host_id: @host1.id).update(status: InsightsClientReportStatus::NO_REPORT, reported_at: Time.now - InsightsClientReportStatus::REPORT_INTERVAL + 1.day)
|
9
|
+
InsightsClientReportStatus.find_or_initialize_by(host_id: @host2.id).update(status: InsightsClientReportStatus::NO_REPORT, reported_at: Time.now - InsightsClientReportStatus::REPORT_INTERVAL + 1.day)
|
10
|
+
|
11
|
+
@host1.refresh_global_status!
|
12
|
+
@host2.refresh_global_status!
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'Cleans hosts by search condition' do
|
16
|
+
assert_equal HostStatus::Global::ERROR, @host1.global_status
|
17
|
+
assert_equal HostStatus::Global::ERROR, @host2.global_status
|
18
|
+
|
19
|
+
instance = ForemanRhCloud::InsightsStatusCleaner.new
|
20
|
+
actual_count = instance.clean("name = #{@host1.name}")
|
21
|
+
|
22
|
+
@host1.reload
|
23
|
+
@host2.refresh_global_status!
|
24
|
+
|
25
|
+
assert_equal 1, actual_count
|
26
|
+
assert_equal HostStatus::Global::OK, @host1.global_status
|
27
|
+
assert_equal HostStatus::Global::ERROR, @host2.global_status
|
28
|
+
assert InsightsClientReportStatus.where(host_id: @host1.id).empty?
|
29
|
+
refute InsightsClientReportStatus.where(host_id: @host2.id).empty?
|
30
|
+
end
|
31
|
+
end
|
@@ -8,6 +8,7 @@ class TemplateRendererHelperTest < ActiveSupport::TestCase
|
|
8
8
|
response.stubs(:body).returns('TEST PLAYBOOK')
|
9
9
|
ForemanRhCloud::RemediationsRetriever.any_instance.stubs(:query_playbook).returns(response)
|
10
10
|
@host1 = FactoryBot.create(:host)
|
11
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
11
12
|
end
|
12
13
|
|
13
14
|
test 'Generates a playbook for hit and remediation' do
|
@@ -62,6 +62,47 @@ class TagsGeneratorTest < ActiveSupport::TestCase
|
|
62
62
|
assert_equal false, actual.key?('content_view')
|
63
63
|
end
|
64
64
|
|
65
|
+
test 'generates parameter tags' do
|
66
|
+
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => true)
|
67
|
+
|
68
|
+
@host.stubs(:host_inherited_params_objects).returns(
|
69
|
+
[
|
70
|
+
OpenStruct.new(name: 'bool_param', value: true),
|
71
|
+
OpenStruct.new(name: 'false_param', value: false),
|
72
|
+
OpenStruct.new(name: 'int_param', value: 1),
|
73
|
+
OpenStruct.new(name: 'empty_param', value: nil),
|
74
|
+
OpenStruct.new(name: 'empty_str_param', value: ''),
|
75
|
+
]
|
76
|
+
)
|
77
|
+
|
78
|
+
generator = create_generator
|
79
|
+
actual = Hash[generator.generate_parameters]
|
80
|
+
|
81
|
+
assert_equal 3, actual.count
|
82
|
+
assert_equal true, actual['bool_param']
|
83
|
+
assert_equal false, actual['false_param']
|
84
|
+
assert_equal 1, actual['int_param']
|
85
|
+
end
|
86
|
+
|
87
|
+
test 'skips parameter tags if include_parameter_tags setting is off' do
|
88
|
+
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
|
89
|
+
|
90
|
+
@host.stubs(:host_inherited_params_objects).returns(
|
91
|
+
[
|
92
|
+
OpenStruct.new(name: 'bool_param', value: true),
|
93
|
+
OpenStruct.new(name: 'false_param', value: false),
|
94
|
+
OpenStruct.new(name: 'int_param', value: 1),
|
95
|
+
OpenStruct.new(name: 'empty_param', value: nil),
|
96
|
+
OpenStruct.new(name: 'empty_str_param', value: ''),
|
97
|
+
]
|
98
|
+
)
|
99
|
+
|
100
|
+
generator = create_generator
|
101
|
+
actual = generator.generate_parameters.group_by { |key, value| key }
|
102
|
+
|
103
|
+
assert_equal 0, actual.count
|
104
|
+
end
|
105
|
+
|
65
106
|
private
|
66
107
|
|
67
108
|
def create_generator
|
data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/EmptyState.js
CHANGED
@@ -9,7 +9,7 @@ const inventoryEmptyState = () => (
|
|
9
9
|
<EmptyState.Title>
|
10
10
|
{__('Fetching data about your accounts')}
|
11
11
|
</EmptyState.Title>
|
12
|
-
<EmptyState.Info>{__('Loading')}
|
12
|
+
<EmptyState.Info>{__('Loading...')}</EmptyState.Info>
|
13
13
|
</EmptyState>
|
14
14
|
);
|
15
15
|
|
@@ -2,12 +2,14 @@ import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import { Grid, Button, Icon } from 'patternfly-react';
|
4
4
|
import { noop } from 'foremanReact/common/helpers';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
|
5
7
|
import './fileDownload.scss';
|
6
8
|
|
7
9
|
const FileDownload = ({ onClick }) => (
|
8
10
|
<Grid.Col sm={12}>
|
9
11
|
<Button onClick={onClick} className="download-button">
|
10
|
-
Download Report <Icon name="download" />
|
12
|
+
{__('Download Report')} <Icon name="download" />
|
11
13
|
</Button>
|
12
14
|
</Grid.Col>
|
13
15
|
);
|
@@ -15,8 +15,7 @@ const InventoryFilter = ({
|
|
15
15
|
organization,
|
16
16
|
}) => {
|
17
17
|
useEffect(() => {
|
18
|
-
const initialTerm =
|
19
|
-
organization === __(ANY_ORGANIZATION) ? '' : organization;
|
18
|
+
const initialTerm = organization === ANY_ORGANIZATION ? '' : organization;
|
20
19
|
handleFilterChange(initialTerm);
|
21
20
|
}, []);
|
22
21
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
2
|
+
|
1
3
|
export const INVENTORY_FILTER_UPDATE = 'INVENTORY_FILTER_UPDATE';
|
2
4
|
export const INVENTORY_FILTER_CLEAR = 'INVENTORY_FILTER_CLEAR';
|
3
|
-
export const ANY_ORGANIZATION = 'Any Organization';
|
5
|
+
export const ANY_ORGANIZATION = __('Any Organization');
|
@@ -9,14 +9,18 @@ import {
|
|
9
9
|
INVENTORY_PAGE_TITLE,
|
10
10
|
ACTIONS_HISTORY_BUTTON_TEXT,
|
11
11
|
DOCS_BUTTON_TEXT,
|
12
|
+
CLOUD_PING_TITLE,
|
12
13
|
} from '../../ForemanInventoryConstants';
|
13
14
|
import {
|
14
15
|
getActionsHistoryUrl,
|
15
16
|
getInventoryDocsUrl,
|
16
17
|
} from '../../ForemanInventoryHelpers';
|
18
|
+
import CloudPingModal from './components/CloudPingModal';
|
17
19
|
|
18
20
|
const PageTitle = () => {
|
19
21
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
22
|
+
const [showPingModal, setPingModal] = useState(false);
|
23
|
+
const togglePingModal = () => setPingModal(v => !v);
|
20
24
|
const dropdownItems = [
|
21
25
|
<DropdownItem
|
22
26
|
key="tasks-history-button"
|
@@ -34,6 +38,9 @@ const PageTitle = () => {
|
|
34
38
|
>
|
35
39
|
{DOCS_BUTTON_TEXT}
|
36
40
|
</DropdownItem>,
|
41
|
+
<DropdownItem key="cloud-ping" onClick={togglePingModal}>
|
42
|
+
{CLOUD_PING_TITLE}
|
43
|
+
</DropdownItem>,
|
37
44
|
];
|
38
45
|
return (
|
39
46
|
<div className="row form-group inventory-upload-header-title">
|
@@ -47,6 +54,11 @@ const PageTitle = () => {
|
|
47
54
|
dropdownItems={dropdownItems}
|
48
55
|
position={DropdownPosition.right}
|
49
56
|
/>
|
57
|
+
<CloudPingModal
|
58
|
+
isOpen={showPingModal}
|
59
|
+
toggle={togglePingModal}
|
60
|
+
title={CLOUD_PING_TITLE}
|
61
|
+
/>
|
50
62
|
</div>
|
51
63
|
);
|
52
64
|
};
|
@@ -27,6 +27,11 @@ exports[`PageTitle rendering render without Props 1`] = `
|
|
27
27
|
>
|
28
28
|
Documentation
|
29
29
|
</DropdownItem>,
|
30
|
+
<DropdownItem
|
31
|
+
onClick={[Function]}
|
32
|
+
>
|
33
|
+
Connectivity test
|
34
|
+
</DropdownItem>,
|
30
35
|
]
|
31
36
|
}
|
32
37
|
isOpen={false}
|
@@ -39,5 +44,10 @@ exports[`PageTitle rendering render without Props 1`] = `
|
|
39
44
|
/>
|
40
45
|
}
|
41
46
|
/>
|
47
|
+
<CloudPingModal
|
48
|
+
isOpen={false}
|
49
|
+
title="Connectivity test"
|
50
|
+
toggle={[Function]}
|
51
|
+
/>
|
42
52
|
</div>
|
43
53
|
`;
|
@@ -0,0 +1,144 @@
|
|
1
|
+
/* eslint-disable camelcase */
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
5
|
+
import { Table, TableBody, TableHeader } from '@patternfly/react-table';
|
6
|
+
import {
|
7
|
+
Card,
|
8
|
+
CardTitle,
|
9
|
+
CardBody,
|
10
|
+
Modal,
|
11
|
+
ModalVariant,
|
12
|
+
Spinner,
|
13
|
+
Text,
|
14
|
+
} from '@patternfly/react-core';
|
15
|
+
import {
|
16
|
+
CheckCircleIcon,
|
17
|
+
ExclamationCircleIcon,
|
18
|
+
} from '@patternfly/react-icons';
|
19
|
+
import { get } from 'foremanReact/redux/API';
|
20
|
+
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
21
|
+
import { STATUS } from 'foremanReact/constants';
|
22
|
+
import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
|
23
|
+
import { inventoryUrl } from '../../../../ForemanInventoryHelpers';
|
24
|
+
import './index.scss';
|
25
|
+
|
26
|
+
export const API_KEY = 'CLOUD_PING';
|
27
|
+
|
28
|
+
const CloudPingModal = ({ title, isOpen, toggle }) => {
|
29
|
+
const [rows, setRows] = useState([]);
|
30
|
+
const [tokenStatus, setTokenStatus] = useState({});
|
31
|
+
const dispatch = useDispatch();
|
32
|
+
const handleSuccess = useCallback(
|
33
|
+
({
|
34
|
+
data: {
|
35
|
+
ping: { cert_auth = [], token_auth = {} },
|
36
|
+
},
|
37
|
+
}) => {
|
38
|
+
cert_auth.length &&
|
39
|
+
setRows(
|
40
|
+
cert_auth.map(cert => ({
|
41
|
+
cells: [
|
42
|
+
{
|
43
|
+
title: (
|
44
|
+
<>
|
45
|
+
<StatusIcon
|
46
|
+
isPending={status === STATUS.PENDING}
|
47
|
+
authStatus={cert}
|
48
|
+
/>{' '}
|
49
|
+
{cert.org_name}
|
50
|
+
</>
|
51
|
+
),
|
52
|
+
},
|
53
|
+
],
|
54
|
+
}))
|
55
|
+
);
|
56
|
+
setTokenStatus(token_auth);
|
57
|
+
},
|
58
|
+
[status]
|
59
|
+
);
|
60
|
+
|
61
|
+
useEffect(() => {
|
62
|
+
isOpen &&
|
63
|
+
dispatch(
|
64
|
+
get({
|
65
|
+
key: API_KEY,
|
66
|
+
url: inventoryUrl('status'),
|
67
|
+
handleSuccess,
|
68
|
+
})
|
69
|
+
);
|
70
|
+
}, [isOpen, dispatch, handleSuccess]);
|
71
|
+
|
72
|
+
const status = useSelector(state => selectAPIStatus(state, API_KEY));
|
73
|
+
const isPending = status === STATUS.PENDING;
|
74
|
+
// const error = useSelector(state => selectAPIErrorMessage(state, API_KEY));
|
75
|
+
|
76
|
+
return (
|
77
|
+
<>
|
78
|
+
<Modal
|
79
|
+
id="cloud-ping-modal"
|
80
|
+
appendTo={document.getElementsByClassName('react-container')[0]}
|
81
|
+
variant={ModalVariant.large}
|
82
|
+
title={title}
|
83
|
+
isOpen={isOpen}
|
84
|
+
onClose={toggle}
|
85
|
+
>
|
86
|
+
<Card className="token-status">
|
87
|
+
<CardTitle>
|
88
|
+
<StatusIcon isPending={isPending} authStatus={tokenStatus} />{' '}
|
89
|
+
{__('API token status')}
|
90
|
+
</CardTitle>
|
91
|
+
</Card>
|
92
|
+
<Card className="certs-status">
|
93
|
+
<CardTitle>{__('Organization status')}</CardTitle>
|
94
|
+
<CardBody>
|
95
|
+
<Text>
|
96
|
+
{__('Displays manifest statuses per accessible organizations.')}
|
97
|
+
</Text>
|
98
|
+
{isPending ? (
|
99
|
+
<Spinner size="xl" />
|
100
|
+
) : (
|
101
|
+
<>
|
102
|
+
<Text className="pull-right">
|
103
|
+
{sprintf(__('%s organizations'), rows.length)}
|
104
|
+
</Text>
|
105
|
+
<Table aria-label="Simple Table" cells={['']} rows={rows}>
|
106
|
+
<TableHeader />
|
107
|
+
<TableBody />
|
108
|
+
</Table>{' '}
|
109
|
+
</>
|
110
|
+
)}
|
111
|
+
</CardBody>
|
112
|
+
</Card>
|
113
|
+
</Modal>
|
114
|
+
</>
|
115
|
+
);
|
116
|
+
};
|
117
|
+
|
118
|
+
const StatusIcon = ({ isPending, authStatus }) => {
|
119
|
+
if (isPending) return <Spinner size="sm" />;
|
120
|
+
if (authStatus.success) return <CheckCircleIcon color="green" />;
|
121
|
+
if (authStatus.error) return <ExclamationCircleIcon color="red" />;
|
122
|
+
return <Spinner size="sm" />;
|
123
|
+
};
|
124
|
+
|
125
|
+
StatusIcon.propTypes = {
|
126
|
+
isPending: PropTypes.bool,
|
127
|
+
authStatus: PropTypes.shape({
|
128
|
+
success: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
129
|
+
error: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
130
|
+
}),
|
131
|
+
};
|
132
|
+
|
133
|
+
StatusIcon.defaultProps = {
|
134
|
+
isPending: true,
|
135
|
+
authStatus: {},
|
136
|
+
};
|
137
|
+
|
138
|
+
CloudPingModal.propTypes = {
|
139
|
+
title: PropTypes.string.isRequired,
|
140
|
+
isOpen: PropTypes.bool.isRequired,
|
141
|
+
toggle: PropTypes.func.isRequired,
|
142
|
+
};
|
143
|
+
|
144
|
+
export default CloudPingModal;
|