foreman_rh_cloud 4.0.25 → 4.0.29
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 +18 -4
- data/app/controllers/insights_cloud/hits_controller.rb +0 -1
- 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/config/Gemfile.lock.gh_test +169 -160
- data/config/database.yml.example +2 -2
- data/config/rh_cert-api_chain.pem +74 -0
- data/config/routes.rb +3 -1
- data/lib/foreman_inventory_upload/generators/queries.rb +1 -16
- data/lib/foreman_inventory_upload/generators/tags.rb +1 -2
- data/lib/foreman_rh_cloud/engine.rb +2 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/foreman_rh_cloud.rb +16 -1
- data/lib/insights_cloud/async/insights_client_status_aging.rb +4 -0
- data/lib/insights_cloud/async/insights_full_sync.rb +4 -0
- data/lib/insights_cloud/async/insights_generate_notifications.rb +4 -0
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +7 -2
- data/lib/insights_cloud/async/insights_rules_sync.rb +10 -2
- data/lib/insights_cloud.rb +4 -0
- data/lib/inventory_sync/async/host_result.rb +0 -5
- data/lib/inventory_sync/async/inventory_full_sync.rb +18 -9
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +6 -6
- data/lib/inventory_sync/async/inventory_scheduled_sync.rb +4 -0
- data/lib/inventory_sync/async/inventory_self_host_sync.rb +4 -0
- data/lib/inventory_sync/async/query_inventory_job.rb +4 -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/factories/inventory_upload_factories.rb +14 -0
- data/test/jobs/insights_resolutions_sync_test.rb +10 -1
- data/test/jobs/inventory_full_sync_test.rb +28 -2
- data/test/jobs/inventory_hosts_sync_test.rb +15 -0
- data/test/test_plugin_helper.rb +53 -0
- data/test/unit/foreman_rh_cloud_self_host_test.rb +28 -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/slice_generator_test.rb +36 -4
- data/test/unit/tags_generator_test.rb +16 -16
- 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/ForemanInventoryConstants.js +2 -0
- 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 +5 -24
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +11 -4
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +51 -0
- 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/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/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 +16 -24
- 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
@@ -37,6 +37,18 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
37
37
|
@host2.subscription_facet.pools << pool
|
38
38
|
@host2_inventory_id = '4536bf5c-ff03-4154-a8c9-32ff4b40e40c'
|
39
39
|
|
40
|
+
# this host would pass our plugin queries, so it could be uploaded to the cloud.
|
41
|
+
@host3 = FactoryBot.create(
|
42
|
+
:host,
|
43
|
+
:with_subscription,
|
44
|
+
:with_content,
|
45
|
+
content_view: cv.first,
|
46
|
+
lifecycle_environment: env,
|
47
|
+
organization: env.organization
|
48
|
+
)
|
49
|
+
|
50
|
+
@host3.subscription_facet.pools << pool
|
51
|
+
|
40
52
|
ForemanInventoryUpload::Generators::Queries.instance_variable_set(:@fact_names, nil)
|
41
53
|
|
42
54
|
inventory_json = <<-INVENTORY_JSON
|
@@ -151,7 +163,7 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
151
163
|
{
|
152
164
|
"insights_id": "b533848e-465f-4f1a-9b2b-b71cb2d5239d",
|
153
165
|
"rhel_machine_id": null,
|
154
|
-
"subscription_manager_id": "
|
166
|
+
"subscription_manager_id": "#{@host3.subscription_facet.uuid}",
|
155
167
|
"satellite_id": "d29bde40-348e-437c-8acf-8fa98320fc1b",
|
156
168
|
"bios_uuid": "3cd5d972-cfb5-451a-8314-fd2f56629d7c",
|
157
169
|
"ip_addresses": [
|
@@ -159,7 +171,7 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
159
171
|
"fd6e:2298:736e::857",
|
160
172
|
"fd6e:2298:736e:0:2c66:6101:9cc6:2b23"
|
161
173
|
],
|
162
|
-
"fqdn": "
|
174
|
+
"fqdn": "#{@host3.fqdn}",
|
163
175
|
"mac_addresses": [
|
164
176
|
"6e:66:a6:fe:fc:07",
|
165
177
|
"00:00:00:00:00:00"
|
@@ -271,4 +283,18 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
271
283
|
|
272
284
|
ForemanTasks.sync_task(InventorySync::Async::InventoryFullSync, @host1.organization)
|
273
285
|
end
|
286
|
+
|
287
|
+
test 'Should skip hosts that are not returned in query' do
|
288
|
+
assert_nil InventorySync::InventoryStatus.where(host_id: @host3.id).first
|
289
|
+
|
290
|
+
Setting[:rh_cloud_token] = 'TEST TOKEN'
|
291
|
+
InventorySync::Async::InventoryFullSync.any_instance.expects(:query_inventory).returns(@inventory)
|
292
|
+
InventorySync::Async::InventoryFullSync.any_instance.expects(:affected_host_ids).returns([@host1.id, @host2.id])
|
293
|
+
FactoryBot.create(:fact_value, fact_name: fact_names['virt::uuid'], value: '1234', host: @host2)
|
294
|
+
|
295
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryFullSync, @host1.organization)
|
296
|
+
@host2.reload
|
297
|
+
|
298
|
+
assert_nil InventorySync::InventoryStatus.where(host_id: @host3.id).first
|
299
|
+
end
|
274
300
|
end
|
@@ -265,4 +265,19 @@ class InventoryHostsSyncTest < ActiveSupport::TestCase
|
|
265
265
|
|
266
266
|
assert_equal @host2_inventory_id, @host2.insights.uuid
|
267
267
|
end
|
268
|
+
|
269
|
+
test 'Inventory should sync empty facets list' do
|
270
|
+
empty_inventory = @inventory.deep_clone
|
271
|
+
empty_inventory['results'] = []
|
272
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:query_inventory).returns(empty_inventory)
|
273
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:plan_self_host_sync)
|
274
|
+
|
275
|
+
assert_nil @host2.insights
|
276
|
+
|
277
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryHostsSync)
|
278
|
+
|
279
|
+
@host2.reload
|
280
|
+
|
281
|
+
assert_nil @host2.insights
|
282
|
+
end
|
268
283
|
end
|
data/test/test_plugin_helper.rb
CHANGED
@@ -38,3 +38,56 @@ module KatelloLocationFix
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
module MockCerts
|
43
|
+
extend ActiveSupport::Concern
|
44
|
+
|
45
|
+
def test_certificate
|
46
|
+
@test_certificate ||= "-----BEGIN CERTIFICATE-----\r\n" +
|
47
|
+
"MIIFdDCCA1ygAwIBAgIJAM5Uqykb3EAtMA0GCSqGSIb3DQEBCwUAME8xCzAJBgNV\r\n" +
|
48
|
+
"BAYTAklMMREwDwYDVQQIDAhUZWwgQXZpdjEUMBIGA1UECgwLVGhlIEZvcmVtYW4x\r\n" +
|
49
|
+
"FzAVBgNVBAMMDnRoZWZvcmVtYW4ub3JnMB4XDTE4MDMyNDEyMzYyOFoXDTI4MDMy\r\n" +
|
50
|
+
"MTEyMzYyOFowTzELMAkGA1UEBhMCSUwxETAPBgNVBAgMCFRlbCBBdml2MRQwEgYD\r\n" +
|
51
|
+
"VQQKDAtUaGUgRm9yZW1hbjEXMBUGA1UEAwwOdGhlZm9yZW1hbi5vcmcwggIiMA0G\r\n" +
|
52
|
+
"CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF04/s4h+BgHPG1HDZ/sDlYq925pkc\r\n" +
|
53
|
+
"RTVAfnE2EXDAmZ6W4Q9ueDY65MHe3ZWO5Dg72kNSP2sK9kRI7Dk5CAFOgyw1rH8t\r\n" +
|
54
|
+
"Hd1+0xp/lv6e4SvSYghxIL68vFe0ftKkm1usqejBM5ZTgKr7JCI+XSIN36F65Kde\r\n" +
|
55
|
+
"c+vxwBnayuhP04r9/aaE/709SXML4eRVYW8I3qFy9FPtUOm+bY8U2PIv5fHayqbG\r\n" +
|
56
|
+
"cL/4t3+MCtMhHJsLzdBXya+1P5t+HcKjUNlmwoUF961YAktVuEFloGd0RMRlqF3/\r\n" +
|
57
|
+
"itU3QNlXgA5QBIciE5VPr/PiqgMC3zgd5avjF4OribZ+N9AATLiQMW78il5wSfcc\r\n" +
|
58
|
+
"kQjU9ChOLrzku455vQ8KE4bc0qvpCWGfUah6MvL9JB+TQkRl/8kxl0b9ZinIvJDH\r\n" +
|
59
|
+
"ynVMb4cB/TDEjrjOfzn9mWLH0ZJqjmc2bER/G12WQxOaYLxdVwRStD3Yh6PtiFWu\r\n" +
|
60
|
+
"sXOk19UOTVkeuvGFVtvzLfEwQ1lDEo7+VBQz8FG/HBu2Hpq3IwCFrHuicikwjQJk\r\n" +
|
61
|
+
"nfturgD0rBOKEc1qWNZRCvovYOLL6ihvv5Orujsx5ZCHOAtnVNxkvIlFt2RS45LF\r\n" +
|
62
|
+
"MtPJyhAc6SjitllfUEirxprsbmeSZqrIfzcGaEhgOSnyik1WMv6bYiqPfBg8Fzjh\r\n" +
|
63
|
+
"vOCbtiDNPmvgOwIDAQABo1MwUTAdBgNVHQ4EFgQUtkAgQopsTtG9zSG3MgW2IxHD\r\n" +
|
64
|
+
"MDwwHwYDVR0jBBgwFoAUtkAgQopsTtG9zSG3MgW2IxHDMDwwDwYDVR0TAQH/BAUw\r\n" +
|
65
|
+
"AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAJq7iN+ZroRBweNhvUobxs75bLIV6tNn1\r\n" +
|
66
|
+
"MdNHDRA+hezwf+gxHZhFyaAHfTpst2/9leK5Qe5Zd6gZLr3E5/8ppQuRod72H39B\r\n" +
|
67
|
+
"vxMlG5zxDss0WMo3vZeKZbTY6QhXi/lY2IZ6OGV4feSvCsYxn27GTjjrRUSLFeHH\r\n" +
|
68
|
+
"JVemCwCDMavaE3+OIY4v2P4FcG+MjUvfOB9ahI24TWL7YgrsNVmJjCILq+EeUj0t\r\n" +
|
69
|
+
"Gde1SXVyLkqt7PoxHRJAE0BCEMJSnjxaVB329acJgeehBUxjj4CCPqtDxtbz9HEH\r\n" +
|
70
|
+
"mOKfNdaKpFor+DUeEKUWVGnr9U9xOaC+Ws+oX7MIEUCDM7p2ob4JwcjnFs1jZgHh\r\n" +
|
71
|
+
"Hwig+i7doTlc701PvKWO96fuNHK3B3/jTb1fVvSZ49O/RvY1VWODdUdxWmXGHNh3\r\n" +
|
72
|
+
"LoR8tSPEb46lC2DXGaIQumqQt8PnBG+vL1qkQa1SGTV7dJ8TTbxbv0S+sS+igkk9\r\n" +
|
73
|
+
"zsIEK8Ea3Ep935cXximz0faAAKHSA+It+xHLAyDtqy2KaAEBgGsBuuWlUfK6TaP3\r\n" +
|
74
|
+
"Gwdjct3y4yYUO45lUsUfHqX8vk/4ttW5zYeDiW+HArJz+9VUXNbEdury4kGuHgBj\r\n" +
|
75
|
+
"xHD4Bsul65+hHZ9QywKU26F1A6TLkYpQ2rk/Dx9LGICM4m4IlHjWJPFsQdtkyOor\r\n" +
|
76
|
+
"osxMtcaZZ1E=\r\n" +
|
77
|
+
"-----END CERTIFICATE-----"
|
78
|
+
end
|
79
|
+
|
80
|
+
def generate_certs_hash
|
81
|
+
{
|
82
|
+
cert: test_certificate,
|
83
|
+
key: OpenSSL::PKey::RSA.new(1024).to_pem,
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def setup_certs_expectation
|
88
|
+
expectation = yield
|
89
|
+
expectation.returns(
|
90
|
+
generate_certs_hash
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class ForemanRhCloudSelfHostTest < ActiveSupport::TestCase
|
4
|
+
setup do
|
5
|
+
# reset cached value
|
6
|
+
ForemanRhCloud.instance_variable_set(:@foreman_host, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'finds host by fullname' do
|
10
|
+
@domain
|
11
|
+
@host = FactoryBot.create(:host, :managed)
|
12
|
+
ForemanRhCloud.expects(:foreman_host_name).returns(@host.name)
|
13
|
+
|
14
|
+
actual = ForemanRhCloud.foreman_host
|
15
|
+
|
16
|
+
assert_not_nil actual
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'finds host by shortname' do
|
20
|
+
@host = FactoryBot.create(:host, :managed)
|
21
|
+
Host.where(name: @host.name).update_all(name: @host.shortname)
|
22
|
+
ForemanRhCloud.expects(:foreman_host_name).returns(@host.name)
|
23
|
+
|
24
|
+
actual = ForemanRhCloud.foreman_host
|
25
|
+
|
26
|
+
assert_not_nil actual
|
27
|
+
end
|
28
|
+
end
|
@@ -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
|
@@ -22,7 +22,13 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
22
22
|
location: location
|
23
23
|
)
|
24
24
|
|
25
|
-
@host.organization.pools << FactoryBot.create(
|
25
|
+
@host.organization.pools << FactoryBot.create(
|
26
|
+
:katello_pool,
|
27
|
+
account_number: '1234',
|
28
|
+
cp_id: 1,
|
29
|
+
organization: env.organization,
|
30
|
+
subscription: FactoryBot.create(:katello_subscription, organization_id: env.organization.id)
|
31
|
+
)
|
26
32
|
@host.interfaces.first.identifier = 'test_nic1'
|
27
33
|
@host.save!
|
28
34
|
|
@@ -441,6 +447,18 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
441
447
|
assert_equal 1, generator.hosts_count
|
442
448
|
end
|
443
449
|
|
450
|
+
test 'excludes hosts with host_registration_insights set to false' do
|
451
|
+
@host.host_parameters << HostParameter.create(
|
452
|
+
name: 'host_registration_insights',
|
453
|
+
value: "false",
|
454
|
+
parameter_type: 'boolean'
|
455
|
+
)
|
456
|
+
|
457
|
+
count = ForemanInventoryUpload::Generators::Queries.for_org(@host.organization_id).count
|
458
|
+
|
459
|
+
assert_equal 0, count
|
460
|
+
end
|
461
|
+
|
444
462
|
test 'shows system_memory_bytes in bytes' do
|
445
463
|
FactoryBot.create(:fact_value, fact_name: fact_names['memory::memtotal'], value: '1', host: @host)
|
446
464
|
|
@@ -457,9 +475,23 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
457
475
|
end
|
458
476
|
|
459
477
|
test 'reports an account for hosts with multiple pools' do
|
460
|
-
|
461
|
-
|
462
|
-
|
478
|
+
new_org = FactoryBot.create(:organization)
|
479
|
+
first_pool = FactoryBot.create(
|
480
|
+
:katello_pool,
|
481
|
+
account_number: '5678',
|
482
|
+
cp_id: 2,
|
483
|
+
organization: new_org,
|
484
|
+
subscription: FactoryBot.create(:katello_subscription, organization_id: new_org.id)
|
485
|
+
)
|
486
|
+
second_pool = FactoryBot.create(
|
487
|
+
:katello_pool,
|
488
|
+
account_number: '9012',
|
489
|
+
cp_id: 3,
|
490
|
+
organization: new_org,
|
491
|
+
subscription: FactoryBot.create(:katello_subscription, organization_id: new_org.id)
|
492
|
+
)
|
493
|
+
new_org.pools << first_pool
|
494
|
+
new_org.pools << second_pool
|
463
495
|
|
464
496
|
another_host = FactoryBot.create(
|
465
497
|
:host,
|
@@ -65,14 +65,14 @@ class TagsGeneratorTest < ActiveSupport::TestCase
|
|
65
65
|
test 'generates parameter tags' do
|
66
66
|
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => true)
|
67
67
|
|
68
|
-
@host.stubs(:
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
68
|
+
@host.stubs(:host_params).returns(
|
69
|
+
{
|
70
|
+
'bool_param' => true,
|
71
|
+
'false_param' => false,
|
72
|
+
'int_param' => 1,
|
73
|
+
'empty_param' => nil,
|
74
|
+
'empty_str_param' => '',
|
75
|
+
}
|
76
76
|
)
|
77
77
|
|
78
78
|
generator = create_generator
|
@@ -87,14 +87,14 @@ class TagsGeneratorTest < ActiveSupport::TestCase
|
|
87
87
|
test 'skips parameter tags if include_parameter_tags setting is off' do
|
88
88
|
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
|
89
89
|
|
90
|
-
@host.stubs(:
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
90
|
+
@host.stubs(:host_params).returns(
|
91
|
+
{
|
92
|
+
'bool_param' => true,
|
93
|
+
'false_param' => false,
|
94
|
+
'int_param' => 1,
|
95
|
+
'empty_param' => nil,
|
96
|
+
'empty_str_param' => '',
|
97
|
+
}
|
98
98
|
)
|
99
99
|
|
100
100
|
generator = create_generator
|
@@ -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;
|