foreman_rh_cloud 13.0.4 → 13.0.5
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/controllers/concerns/insights_cloud/package_profile_upload_extensions.rb +2 -3
- data/app/services/foreman_rh_cloud/cert_auth.rb +13 -3
- data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +3 -1
- data/app/services/foreman_rh_cloud/tags_auth.rb +2 -1
- data/lib/foreman_inventory_upload/async/create_missing_insights_facets.rb +29 -0
- data/lib/foreman_inventory_upload/async/generate_host_report.rb +20 -0
- data/lib/foreman_inventory_upload/async/generate_report_job.rb +1 -1
- data/lib/foreman_inventory_upload/async/host_inventory_report_job.rb +39 -0
- data/lib/foreman_inventory_upload/async/single_host_report_job.rb +20 -0
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +2 -1
- data/lib/foreman_inventory_upload/generators/fact_helpers.rb +2 -2
- data/lib/foreman_inventory_upload/generators/slice.rb +3 -3
- data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +7 -1
- data/lib/foreman_rh_cloud/plugin.rb +9 -9
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud/async/vmaas_reposcan_sync.rb +8 -1
- data/lib/tasks/rh_cloud_inventory.rake +14 -32
- data/package.json +1 -1
- data/test/unit/fact_helpers_test.rb +47 -0
- data/test/unit/lib/insights_cloud/async/vmaas_reposcan_sync_test.rb +12 -2
- data/test/unit/slice_generator_test.rb +57 -0
- data/webpack/InsightsHostDetailsTab/InsightsTotalRiskChart.js +57 -21
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTotalRiskChart.test.js +194 -0
- metadata +6 -2
- data/app/services/foreman_rh_cloud/gateway_request.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ece8ef4c631103e6c100e8aa8029d0dc3473911e8f276267404c49190b800a47
|
4
|
+
data.tar.gz: cd9f6ab8349eec0d93cdf29fa1b80f8806d7175bc8c0f8af192f1ab4d83214cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e7cfc9880d367c0e558ca87136a66af84ffcdd1d82a852b956cd90c7988209280509325a9442bf6f5ebcbdd58d1cd4e29d87766c79eb4f9830c5f3e9452356c
|
7
|
+
data.tar.gz: a5f4543f5fea79d337002d9b17d4cc51830b2e3b2102426ba0a21b25c875e1a09109816fe1c8f4766d3bc52ae3f6a517e9da8b35faad999f59eeec396a75f628
|
@@ -15,11 +15,10 @@ module InsightsCloud
|
|
15
15
|
logger.debug("Generating host-specific report for host #{@host.name}")
|
16
16
|
|
17
17
|
ForemanTasks.async_task(
|
18
|
-
ForemanInventoryUpload::Async::
|
18
|
+
ForemanInventoryUpload::Async::SingleHostReportJob,
|
19
19
|
ForemanInventoryUpload.generated_reports_folder,
|
20
20
|
@host.organization_id,
|
21
|
-
|
22
|
-
"id=#{@host.id}"
|
21
|
+
@host.id
|
23
22
|
)
|
24
23
|
|
25
24
|
# in IoP case, the hosts are identified by the sub-man ID, and we can assume they already
|
@@ -11,11 +11,21 @@ module ForemanRhCloud
|
|
11
11
|
|
12
12
|
def execute_cloud_request(params)
|
13
13
|
organization = params.delete(:organization)
|
14
|
-
|
15
|
-
|
14
|
+
# Cache the value of with_iop_smart_proxy? to avoid multiple calls to the database
|
15
|
+
with_iop_smart_proxy = ForemanRhCloud.with_iop_smart_proxy?
|
16
|
+
certs = with_iop_smart_proxy ? foreman_certificate : candlepin_id_cert(organization)
|
17
|
+
default_params = {
|
16
18
|
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
17
19
|
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
18
|
-
}
|
20
|
+
}
|
21
|
+
|
22
|
+
if with_iop_smart_proxy && organization&.label
|
23
|
+
default_params[:headers] = {
|
24
|
+
'X-Org-Id' => organization&.label,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
final_params = default_params.deep_merge(params)
|
19
29
|
|
20
30
|
super(final_params)
|
21
31
|
end
|
@@ -2,7 +2,7 @@ require 'rest-client'
|
|
2
2
|
|
3
3
|
module ForemanRhCloud
|
4
4
|
class InsightsApiForwarder
|
5
|
-
include ForemanRhCloud::
|
5
|
+
include ForemanRhCloud::CertAuth
|
6
6
|
|
7
7
|
SCOPED_REQUESTS = [
|
8
8
|
{ test: %r{api/vulnerability/v1/vulnerabilities/cves}, tag_name: :tags },
|
@@ -26,6 +26,8 @@ module ForemanRhCloud
|
|
26
26
|
|
27
27
|
request_opts = prepare_request_opts(original_request, path, forward_payload, forward_params)
|
28
28
|
|
29
|
+
request_opts[:organization] = organization
|
30
|
+
|
29
31
|
logger.debug("Sending request to: #{request_opts[:url]}")
|
30
32
|
|
31
33
|
execute_cloud_request(request_opts)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ForemanRhCloud
|
2
2
|
class TagsAuth
|
3
|
-
include
|
3
|
+
include CertAuth
|
4
4
|
|
5
5
|
TAG_NAMESPACE = 'sat_iam'.freeze
|
6
6
|
TAG_SHORT_NAME = 'scope'.freeze
|
@@ -24,6 +24,7 @@ module ForemanRhCloud
|
|
24
24
|
|
25
25
|
payload = tags_query_payload
|
26
26
|
params = {
|
27
|
+
organization: @org,
|
27
28
|
method: :post,
|
28
29
|
url: "#{InsightsCloud.gateway_url}/tags",
|
29
30
|
headers: {
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Async
|
3
|
+
class CreateMissingInsightsFacets < ::Actions::EntryAction
|
4
|
+
def plan(organization_id)
|
5
|
+
plan_self(organization_id: organization_id)
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
organization = ::Organization.find(input[:organization_id])
|
10
|
+
hosts_without_facets = ::ForemanInventoryUpload::Generators::Queries.for_org(organization, hosts_query: 'null? insights_uuid')
|
11
|
+
facet_count = hosts_without_facets.count
|
12
|
+
hosts_without_facets.each do |batch|
|
13
|
+
facets = batch.pluck(:id, 'katello_subscription_facets.uuid').map do |host_id, uuid|
|
14
|
+
{
|
15
|
+
host_id: host_id,
|
16
|
+
uuid: uuid,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
# We don't need to validate the facets here as we create the necessary fields.
|
20
|
+
# rubocop:disable Rails/SkipsModelValidations
|
21
|
+
InsightsFacet.upsert_all(facets, unique_by: :host_id) unless facets.empty?
|
22
|
+
# rubocop:enable Rails/SkipsModelValidations
|
23
|
+
end
|
24
|
+
output[:result] = facet_count.zero? ? _("There were no missing Insights facets") : format(_("Missing Insights facets created: %s"), facet_count)
|
25
|
+
Rails.logger.info output[:result]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Async
|
3
|
+
class GenerateHostReport < ::Actions::EntryAction
|
4
|
+
def plan(base_folder, organization_id, filter)
|
5
|
+
plan_self(
|
6
|
+
base_folder: base_folder,
|
7
|
+
organization_id: organization_id,
|
8
|
+
filter: filter
|
9
|
+
)
|
10
|
+
input[:target] = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(input[:organization_id], input[:filter]))
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
archived_report_generator = ForemanInventoryUpload::Generators::ArchivedReport.new(input[:target])
|
15
|
+
archived_report_generator.render(organization: input[:organization_id], filter: input[:filter])
|
16
|
+
output[:result] = "Generated #{input[:target]} for organization id #{input[:organization_id]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -5,7 +5,7 @@ module ForemanInventoryUpload
|
|
5
5
|
"report_for_#{label}"
|
6
6
|
end
|
7
7
|
|
8
|
-
def plan(base_folder, organization_id, disconnected, hosts_filter = nil)
|
8
|
+
def plan(base_folder, organization_id, disconnected = false, hosts_filter = nil)
|
9
9
|
sequence do
|
10
10
|
super(
|
11
11
|
GenerateReportJob.output_label("#{organization_id}#{hosts_filter.empty? ? nil : "[#{hosts_filter.to_s.parameterize}]"}"),
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Async
|
3
|
+
class HostInventoryReportJob < ::Actions::EntryAction
|
4
|
+
def plan(base_folder, organization_id, hosts_filter = "", upload = true)
|
5
|
+
sequence do
|
6
|
+
plan_action(
|
7
|
+
GenerateHostReport,
|
8
|
+
base_folder,
|
9
|
+
organization_id,
|
10
|
+
hosts_filter
|
11
|
+
)
|
12
|
+
if upload
|
13
|
+
plan_action(
|
14
|
+
QueueForUploadJob,
|
15
|
+
base_folder,
|
16
|
+
ForemanInventoryUpload.facts_archive_name(organization_id, hosts_filter),
|
17
|
+
organization_id
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
if ForemanRhCloud.with_iop_smart_proxy?
|
22
|
+
plan_action(
|
23
|
+
CreateMissingInsightsFacets,
|
24
|
+
organization_id
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def humanized_name
|
31
|
+
_("Host inventory report job")
|
32
|
+
end
|
33
|
+
|
34
|
+
def organization_id
|
35
|
+
input[:organization_id]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Async
|
3
|
+
class SingleHostReportJob < HostInventoryReportJob
|
4
|
+
def plan(base_folder, organization_id, host_id)
|
5
|
+
input[:host_id] = host_id
|
6
|
+
super(base_folder, organization_id, "id=#{input[:host_id]}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def hostname(host_id)
|
10
|
+
host = ::Host.find_by(id: host_id)
|
11
|
+
host&.name
|
12
|
+
end
|
13
|
+
|
14
|
+
def humanized_name
|
15
|
+
hostname_result = hostname(input[:host_id])
|
16
|
+
hostname_result.present? ? format(_("Single-host report job for host %s"), hostname_result) : _("Single-host report job")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -59,7 +59,7 @@ module ForemanInventoryUpload
|
|
59
59
|
def obfuscate_hostname?(host)
|
60
60
|
# Returns true if hostname obfuscation should be applied for a given host, based on hierarchy:
|
61
61
|
# 1. Global setting for hostname obfuscation.
|
62
|
-
return true if Setting[:obfuscate_inventory_hostnames]
|
62
|
+
return true if Setting[:obfuscate_inventory_hostnames] && !ForemanRhCloud.with_iop_smart_proxy?
|
63
63
|
|
64
64
|
insights_client_setting = fact_value(host, 'insights_client::obfuscate_hostname_enabled')
|
65
65
|
insights_client_setting = ActiveModel::Type::Boolean.new.cast(insights_client_setting)
|
@@ -99,7 +99,7 @@ module ForemanInventoryUpload
|
|
99
99
|
def obfuscate_ips?(host)
|
100
100
|
# Returns true if IP obfuscation should be applied for a given host, based on hierarchy:
|
101
101
|
# 1. Global setting for IP obfuscation.
|
102
|
-
return true if Setting[:obfuscate_inventory_ips]
|
102
|
+
return true if Setting[:obfuscate_inventory_ips] && !ForemanRhCloud.with_iop_smart_proxy?
|
103
103
|
|
104
104
|
insights_client_ipv4_setting = fact_value(host, 'insights_client::obfuscate_ipv4_enabled')
|
105
105
|
insights_client_ipv6_setting = fact_value(host, 'insights_client::obfuscate_ipv6_enabled')
|
@@ -90,7 +90,7 @@ module ForemanInventoryUpload
|
|
90
90
|
def report_host(host)
|
91
91
|
host_ips_cache = host_ips(host)
|
92
92
|
@stream.object do
|
93
|
-
if Setting[:insights_minimal_data_collection]
|
93
|
+
if Setting[:insights_minimal_data_collection] && !ForemanRhCloud.with_iop_smart_proxy?
|
94
94
|
insights_minimal_data_collection(host)
|
95
95
|
else
|
96
96
|
@stream.simple_field('fqdn', fqdn(host))
|
@@ -205,7 +205,7 @@ module ForemanInventoryUpload
|
|
205
205
|
end.join(', '))
|
206
206
|
end
|
207
207
|
end
|
208
|
-
if !Setting[:insights_minimal_data_collection] && !Setting[:exclude_installed_packages]
|
208
|
+
if ForemanRhCloud.with_iop_smart_proxy? || (!Setting[:insights_minimal_data_collection] && !Setting[:exclude_installed_packages])
|
209
209
|
@stream.array_field('installed_packages') do
|
210
210
|
first = true
|
211
211
|
host.installed_packages.each do |package|
|
@@ -256,7 +256,7 @@ module ForemanInventoryUpload
|
|
256
256
|
|
257
257
|
@stream.array_field('yum_repos') do
|
258
258
|
host.content_facet.bound_repositories.each_with_index do |repo, index|
|
259
|
-
report_yum_repo(host.content_source.
|
259
|
+
report_yum_repo(host.content_source&.load_balancer_pulp_content_url || ::SmartProxy.pulp_primary.pulp_content_url, repo)
|
260
260
|
@stream.comma unless index == host.content_facet.bound_repositories.count - 1
|
261
261
|
end
|
262
262
|
end
|
@@ -27,6 +27,12 @@ else
|
|
27
27
|
AUTH_VAL="\"$RH_USERNAME\":\"$RH_PASSWORD\""
|
28
28
|
fi
|
29
29
|
|
30
|
+
ORG_HEADER=()
|
31
|
+
if [ -n "$ORG_ID" ]
|
32
|
+
then
|
33
|
+
+ ORG_HEADER=("-H" "X-Org-Id: $ORG_ID")
|
34
|
+
fi
|
35
|
+
|
30
36
|
# /tmp/a b/x.pem
|
31
37
|
# curl --cert /tmp/a\ b/x.pem
|
32
38
|
|
@@ -36,7 +42,7 @@ mkdir -p $DONE_DIR
|
|
36
42
|
|
37
43
|
for f in $FILES
|
38
44
|
do
|
39
|
-
curl -k -vvv -# --fail -F "file=@$f;type=application/vnd.redhat.qpc.tar+tgz" $DEST "$AUTH_KEY" "$AUTH_VAL"
|
45
|
+
curl -k -vvv -# --fail -F "file=@$f;type=application/vnd.redhat.qpc.tar+tgz" $DEST "$AUTH_KEY" "$AUTH_VAL" "${ORG_HEADER[@]}"
|
40
46
|
status=$?
|
41
47
|
if [ $status -eq 0 ]; then
|
42
48
|
mv $f $DONE_DIR
|
@@ -13,15 +13,15 @@ module ForemanRhCloud
|
|
13
13
|
|
14
14
|
settings do
|
15
15
|
category(:rh_cloud, N_('Insights')) do
|
16
|
-
setting('allow_auto_inventory_upload', type: :boolean, description: N_('Enable automatic upload of your host inventory to the Red Hat cloud'), default: true, full_name: N_('Automatic inventory upload'))
|
17
|
-
setting('allow_auto_insights_sync', type: :boolean, description: N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), default: true, full_name: N_('Synchronize recommendations Automatically'))
|
18
|
-
setting('allow_auto_insights_mismatch_delete', type: :boolean, description: N_('Enable automatic deletion of mismatched host records from the Red Hat cloud'), default: false, full_name: N_('Automatic mismatch deletion'))
|
19
|
-
setting('obfuscate_inventory_hostnames', type: :boolean, description: N_('Obfuscate host names sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host names are not included in the report.)'), default: false, full_name: N_('Obfuscate host names'))
|
20
|
-
setting('obfuscate_inventory_ips', type: :boolean, description: N_('Obfuscate ipv4 addresses sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host IPv4 addresses are not included in the report.)'), default: false, full_name: N_('Obfuscate host ipv4 addresses.'))
|
21
|
-
setting('exclude_installed_packages', type: :boolean, description: N_('Exclude installed packages from being uploaded to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored and installed packages are always excluded.)'), default: false, full_name: N_("Exclude installed packages"))
|
22
|
-
setting('include_parameter_tags', type: :boolean, description: N_('Should import include parameter tags from Foreman?'), default: false, full_name: N_('Include parameters in insights-client reports'))
|
23
|
-
setting('rhc_instance_id', type: :string, description: N_('RHC daemon id'), default: nil, full_name: N_('ID of the RHC(Yggdrasil) daemon'))
|
24
|
-
setting('insights_minimal_data_collection', type: :boolean, default: false, full_name: N_('Minimal data collection'), description: N_('Only include the minimum required data in inventory reports for uploading to Red Hat cloud. When this is true, installed packages are excluded from the report regardless of the exclude_installed_packages setting, and host names and IPv4 addresses are excluded from the report regardless of obfuscation settings.'))
|
16
|
+
setting('allow_auto_inventory_upload', type: :boolean, description: N_('Enable automatic upload of your host inventory to the Red Hat cloud. Ignored when using local Insights.'), default: true, full_name: N_('Automatic inventory upload'))
|
17
|
+
setting('allow_auto_insights_sync', type: :boolean, description: N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud. Ignored when using local Insights.'), default: true, full_name: N_('Synchronize recommendations Automatically'))
|
18
|
+
setting('allow_auto_insights_mismatch_delete', type: :boolean, description: N_('Enable automatic deletion of mismatched host records from the Red Hat cloud. Ignored when using local Insights.'), default: false, full_name: N_('Automatic mismatch deletion'))
|
19
|
+
setting('obfuscate_inventory_hostnames', type: :boolean, description: N_('Obfuscate host names sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host names are not included in the report.) Ignored when using local Insights.'), default: false, full_name: N_('Obfuscate host names'))
|
20
|
+
setting('obfuscate_inventory_ips', type: :boolean, description: N_('Obfuscate ipv4 addresses sent to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored because host IPv4 addresses are not included in the report.) Ignored when using local Insights.'), default: false, full_name: N_('Obfuscate host ipv4 addresses.'))
|
21
|
+
setting('exclude_installed_packages', type: :boolean, description: N_('Exclude installed packages from being uploaded to the Red Hat cloud. (If insights_minimal_data_collection is set to true, this setting is ignored and installed packages are always excluded.) Ignored when using local Insights.'), default: false, full_name: N_("Exclude installed packages"))
|
22
|
+
setting('include_parameter_tags', type: :boolean, description: N_('Should import include parameter tags from Foreman? Ignored when using local Insights.'), default: false, full_name: N_('Include parameters in insights-client reports'))
|
23
|
+
setting('rhc_instance_id', type: :string, description: N_('RHC daemon id. Ignored when using local Insights.'), default: nil, full_name: N_('ID of the RHC(Yggdrasil) daemon'))
|
24
|
+
setting('insights_minimal_data_collection', type: :boolean, default: false, full_name: N_('Minimal data collection'), description: N_('Only include the minimum required data in inventory reports for uploading to Red Hat cloud. When this is true, installed packages are excluded from the report regardless of the exclude_installed_packages setting, and host names and IPv4 addresses are excluded from the report regardless of obfuscation settings. Ignored when using local Insights.'))
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -23,13 +23,16 @@ module InsightsCloud
|
|
23
23
|
return
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
organization_id = Katello::Repository.find(repo_id).organization_id
|
27
|
+
|
28
|
+
plan_self(organization_id: organization_id)
|
27
29
|
end
|
28
30
|
|
29
31
|
def run
|
30
32
|
url = ::InsightsCloud.vmaas_reposcan_sync_url
|
31
33
|
|
32
34
|
response = execute_cloud_request(
|
35
|
+
organization: organization,
|
33
36
|
method: :put,
|
34
37
|
url: url,
|
35
38
|
headers: { 'Content-Type' => 'application/json' }
|
@@ -61,6 +64,10 @@ module InsightsCloud
|
|
61
64
|
Dynflow::Action::Rescue::Skip
|
62
65
|
end
|
63
66
|
|
67
|
+
def organization
|
68
|
+
@organization ||= Organization.find(input[:organization_id])
|
69
|
+
end
|
70
|
+
|
64
71
|
private
|
65
72
|
|
66
73
|
def logger
|
@@ -9,22 +9,20 @@ namespace :rh_cloud_inventory do
|
|
9
9
|
else
|
10
10
|
organizations = [Organization.where(:id => ENV['organization_id']).first]
|
11
11
|
end
|
12
|
-
disconnected = ForemanRhCloud.with_iop_smart_proxy?
|
13
12
|
User.as_anonymous_admin do
|
14
13
|
organizations.each do |organization|
|
15
14
|
ForemanTasks.async_task(
|
16
15
|
ForemanInventoryUpload::Async::GenerateReportJob,
|
17
16
|
ForemanInventoryUpload.generated_reports_folder,
|
18
|
-
organization.id
|
19
|
-
disconnected
|
17
|
+
organization.id
|
20
18
|
)
|
21
19
|
puts "Generated and uploaded inventory report for organization '#{organization.name}'"
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
25
23
|
desc 'Generate inventory report to be sent to Red Hat cloud'
|
26
|
-
task generate: :environment do
|
27
|
-
|
24
|
+
task generate: [:environment, 'dynflow:client'] do
|
25
|
+
organization_ids = [ENV['organization_id']]
|
28
26
|
base_folder = ENV['target'] || Dir.pwd
|
29
27
|
filter = ENV['hosts_filter']
|
30
28
|
|
@@ -34,37 +32,22 @@ namespace :rh_cloud_inventory do
|
|
34
32
|
puts "Using #{base_folder} for the output"
|
35
33
|
end
|
36
34
|
|
37
|
-
if
|
35
|
+
if organization_ids.empty?
|
38
36
|
puts "Must specify organization_id"
|
39
37
|
return
|
40
38
|
end
|
41
39
|
|
42
40
|
User.as_anonymous_admin do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
puts 'Creating missing insights facets'
|
53
|
-
hosts_without_facets = ForemanInventoryUpload::Generators::Queries.for_org(organization, hosts_query: 'null? insights_uuid')
|
54
|
-
hosts_without_facets.each do |batch|
|
55
|
-
facets = batch.pluck(:id, 'katello_subscription_facets.uuid').map do |host_id, uuid|
|
56
|
-
{
|
57
|
-
host_id: host_id,
|
58
|
-
uuid: uuid,
|
59
|
-
}
|
60
|
-
end
|
61
|
-
# We don't need to validate the facets here as we create the necessary fields.
|
62
|
-
# rubocop:disable Rails/SkipsModelValidations
|
63
|
-
InsightsFacet.upsert_all(facets, unique_by: :host_id) unless facets.empty?
|
64
|
-
# rubocop:enable Rails/SkipsModelValidations
|
65
|
-
end
|
66
|
-
puts 'Missing Insights facets created'
|
41
|
+
organization_ids.each do |organization_id|
|
42
|
+
ForemanTasks.sync_task(
|
43
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
44
|
+
base_folder,
|
45
|
+
organization_id,
|
46
|
+
filter,
|
47
|
+
false # don't upload; the user ran report:generate and not report:generate_upload
|
48
|
+
)
|
67
49
|
end
|
50
|
+
puts "Check the Uploading tab for report uploading status." if Setting[:subscription_connection_enabled]
|
68
51
|
end
|
69
52
|
end
|
70
53
|
desc 'Upload generated inventory report to Red Hat cloud'
|
@@ -72,8 +55,7 @@ namespace :rh_cloud_inventory do
|
|
72
55
|
base_folder = ENV['target'] || ForemanInventoryUpload.generated_reports_folder
|
73
56
|
organization_id = ENV['organization_id']
|
74
57
|
report_file = ForemanInventoryUpload.facts_archive_name(organization_id)
|
75
|
-
|
76
|
-
ForemanTasks.sync_task(ForemanInventoryUpload::Async::QueueForUploadJob, base_folder, report_file, organization_id, disconnected)
|
58
|
+
ForemanTasks.sync_task(ForemanInventoryUpload::Async::QueueForUploadJob, base_folder, report_file, organization_id)
|
77
59
|
puts "Uploaded #{report_file}"
|
78
60
|
end
|
79
61
|
end
|
data/package.json
CHANGED
@@ -313,4 +313,51 @@ class FactHelpersTest < ActiveSupport::TestCase
|
|
313
313
|
assert_equal '10.230.230.3', ip3
|
314
314
|
end
|
315
315
|
end
|
316
|
+
|
317
|
+
describe 'IoP smart proxy checks' do
|
318
|
+
test 'obfuscate_hostname? returns false when global setting is enabled but IoP is present' do
|
319
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(true)
|
320
|
+
ForemanRhCloud.expects(:with_iop_smart_proxy?).returns(true)
|
321
|
+
host = mock('host')
|
322
|
+
# When IoP is present, it falls back to checking host-specific facts
|
323
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_hostname_enabled').returns(nil)
|
324
|
+
|
325
|
+
result = @instance.obfuscate_hostname?(host)
|
326
|
+
|
327
|
+
refute result
|
328
|
+
end
|
329
|
+
|
330
|
+
test 'obfuscate_hostname? returns true when global setting is enabled and IoP is not present' do
|
331
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(true)
|
332
|
+
ForemanRhCloud.expects(:with_iop_smart_proxy?).returns(false)
|
333
|
+
host = mock('host')
|
334
|
+
|
335
|
+
result = @instance.obfuscate_hostname?(host)
|
336
|
+
|
337
|
+
assert result
|
338
|
+
end
|
339
|
+
|
340
|
+
test 'obfuscate_ips? returns false when global setting is enabled but IoP is present' do
|
341
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(true)
|
342
|
+
ForemanRhCloud.expects(:with_iop_smart_proxy?).returns(true)
|
343
|
+
host = mock('host')
|
344
|
+
# When IoP is present, it falls back to checking host-specific facts
|
345
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns(nil)
|
346
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns(nil)
|
347
|
+
|
348
|
+
result = @instance.obfuscate_ips?(host)
|
349
|
+
|
350
|
+
refute result
|
351
|
+
end
|
352
|
+
|
353
|
+
test 'obfuscate_ips? returns true when global setting is enabled and IoP is not present' do
|
354
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(true)
|
355
|
+
ForemanRhCloud.expects(:with_iop_smart_proxy?).returns(false)
|
356
|
+
host = mock('host')
|
357
|
+
|
358
|
+
result = @instance.obfuscate_ips?(host)
|
359
|
+
|
360
|
+
assert result
|
361
|
+
end
|
362
|
+
end
|
316
363
|
end
|
@@ -5,7 +5,16 @@ class VmaasReposcanSyncTest < ActiveSupport::TestCase
|
|
5
5
|
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
6
6
|
|
7
7
|
setup do
|
8
|
-
@
|
8
|
+
@root = FactoryBot.build(:katello_root_repository, :fedora_17_x86_64_dev_root)
|
9
|
+
@root.save(validate: false)
|
10
|
+
@repo = FactoryBot.create(
|
11
|
+
:katello_repository,
|
12
|
+
:with_product,
|
13
|
+
distribution_family: 'Red Hat',
|
14
|
+
distribution_version: '7.5',
|
15
|
+
root: @root
|
16
|
+
)
|
17
|
+
@repo_payload = { id: @repo.id }
|
9
18
|
@expected_url = 'https://example.com/api/v1/vmaas/reposcan/sync'
|
10
19
|
InsightsCloud.stubs(:vmaas_reposcan_sync_url).returns(@expected_url)
|
11
20
|
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
@@ -68,7 +77,8 @@ class VmaasReposcanSyncTest < ActiveSupport::TestCase
|
|
68
77
|
params[:method] == :put &&
|
69
78
|
params[:url] == @expected_url &&
|
70
79
|
params[:headers].is_a?(Hash) &&
|
71
|
-
params[:headers]['Content-Type'] == 'application/json'
|
80
|
+
params[:headers]['Content-Type'] == 'application/json' &&
|
81
|
+
params[:organization] == @repo.organization
|
72
82
|
end
|
73
83
|
.returns(mock_response)
|
74
84
|
|
@@ -107,6 +107,36 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
107
107
|
assert_equal 'test_nic1', actual_nic['name']
|
108
108
|
end
|
109
109
|
|
110
|
+
test 'does not generate a report with minimal data collection when iop is present' do
|
111
|
+
Setting[:insights_minimal_data_collection] = true
|
112
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
113
|
+
|
114
|
+
batch = Host.where(id: @host.id).in_batches.first
|
115
|
+
generator = create_generator(batch)
|
116
|
+
|
117
|
+
json_str = generator.render
|
118
|
+
actual = JSON.parse(json_str.join("\n"))
|
119
|
+
|
120
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
121
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
122
|
+
assert_nil actual_host['ip_addresses']
|
123
|
+
assert_nil actual_host['mac_addresses']
|
124
|
+
assert_equal @host.fqdn, actual_host['fqdn']
|
125
|
+
assert_equal '1234', actual_host['account']
|
126
|
+
assert_equal 1, generator.hosts_count
|
127
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
128
|
+
assert_nil actual_system_profile['number_of_cpus']
|
129
|
+
assert_nil actual_system_profile['number_of_sockets']
|
130
|
+
assert_nil actual_system_profile['cores_per_socket']
|
131
|
+
assert_nil actual_system_profile['system_memory_bytes']
|
132
|
+
assert_nil actual_system_profile['os_release']
|
133
|
+
assert_not_nil(actual_network_interfaces = actual_system_profile['network_interfaces'])
|
134
|
+
assert_not_nil(actual_nic = actual_network_interfaces.first)
|
135
|
+
refute actual_nic.key?('mtu')
|
136
|
+
refute actual_nic.key?('mac_address')
|
137
|
+
assert_equal 'test_nic1', actual_nic['name']
|
138
|
+
end
|
139
|
+
|
110
140
|
test 'generates a report with minimal data collection' do
|
111
141
|
Setting[:insights_minimal_data_collection] = true
|
112
142
|
create_fact_values(@host,
|
@@ -930,6 +960,33 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
930
960
|
assert_equal 'alibaba', actual_profile['cloud_provider']
|
931
961
|
end
|
932
962
|
|
963
|
+
test 'do not exclude packages when iop is present' do
|
964
|
+
Setting[:exclude_installed_packages] = true
|
965
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
966
|
+
installed_package = ::Katello::InstalledPackage.create(name: 'test-package', nvrea: 'test-package-1.0.x86_64', nvra: 'test-package-1.0.x86_64')
|
967
|
+
|
968
|
+
another_host = FactoryBot.create(
|
969
|
+
:host,
|
970
|
+
:with_subscription,
|
971
|
+
:with_content,
|
972
|
+
content_view: @host.content_views.first,
|
973
|
+
lifecycle_environment: @host.lifecycle_environments.first,
|
974
|
+
organization: @host.organization,
|
975
|
+
installed_packages: [installed_package]
|
976
|
+
)
|
977
|
+
|
978
|
+
batch = Host.where(id: another_host.id).in_batches.first
|
979
|
+
generator = create_generator(batch)
|
980
|
+
|
981
|
+
json_str = generator.render
|
982
|
+
actual = JSON.parse(json_str.join("\n"))
|
983
|
+
|
984
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
985
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
986
|
+
assert_not_nil(actual_profile = actual_host['system_profile'])
|
987
|
+
assert_not_nil(actual_profile['installed_packages'])
|
988
|
+
end
|
989
|
+
|
933
990
|
test 'include packages installed in the report' do
|
934
991
|
Setting[:exclude_installed_packages] = false
|
935
992
|
installed_package = ::Katello::InstalledPackage.create(name: 'test-package', nvrea: 'test-package-1.0.x86_64', nvra: 'test-package-1.0.x86_64')
|
@@ -18,36 +18,67 @@ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
|
|
18
18
|
import { insightsCloudUrl } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
|
19
19
|
import { getInitialRisks, theme } from './InsightsTabConstants';
|
20
20
|
|
21
|
-
const InsightsTotalRiskCard = ({ hostDetails
|
21
|
+
const InsightsTotalRiskCard = ({ hostDetails }) => {
|
22
|
+
const { id, insights_attributes: insightsFacet } = hostDetails;
|
23
|
+
const uuid = insightsFacet?.uuid;
|
24
|
+
// eslint-disable-next-line camelcase
|
25
|
+
const isIop = insightsFacet?.use_iop_mode;
|
22
26
|
const [totalRisks, setTotalRisks] = useState(getInitialRisks());
|
23
27
|
const hashHistory = useHistory();
|
24
28
|
const dispatch = useDispatch();
|
25
29
|
const API_KEY = `HOST_${id}_RECOMMENDATIONS`;
|
26
30
|
const API_OPTIONS = useMemo(() => ({ key: API_KEY }), [API_KEY]);
|
27
|
-
const url = id && insightsCloudUrl(`hits/${id}`); // This will keep the API call from being triggered if there's no host id.
|
28
|
-
const {
|
29
|
-
status = STATUS.PENDING,
|
30
|
-
response: { hits = [] },
|
31
|
-
} = useAPI('get', url, API_OPTIONS);
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
// This will keep the API call from being triggered if there's no host id.
|
33
|
+
const url = isIop
|
34
|
+
? uuid && insightsCloudUrl(`api/insights/v1/system/${uuid}`)
|
35
|
+
: id && insightsCloudUrl(`hits/${id}`);
|
36
|
+
const { status = STATUS.PENDING, response } = useAPI('get', url, API_OPTIONS);
|
37
|
+
|
38
|
+
const checkRisks = useMemo(() => {
|
39
|
+
if (!response || status !== STATUS.RESOLVED) {
|
40
|
+
return getInitialRisks();
|
41
|
+
}
|
42
|
+
|
43
|
+
const risks = getInitialRisks();
|
44
|
+
if (isIop) {
|
45
|
+
const {
|
46
|
+
low_hits: lowHits = 0,
|
47
|
+
moderate_hits: moderateHits = 0,
|
48
|
+
important_hits: importantHits = 0,
|
49
|
+
critical_hits: criticalHits = 0,
|
50
|
+
hits = 0,
|
51
|
+
} = response;
|
52
|
+
|
53
|
+
risks[1].value += lowHits;
|
54
|
+
risks[2].value += moderateHits;
|
55
|
+
risks[3].value += importantHits;
|
56
|
+
risks[4].value += criticalHits;
|
57
|
+
risks.total = hits;
|
58
|
+
} else {
|
59
|
+
const { hits = [] } = response;
|
36
60
|
hits.forEach(({ total_risk: risk }) => {
|
37
61
|
risks[risk].value += 1;
|
38
62
|
});
|
39
63
|
risks.total = hits.length;
|
40
|
-
setTotalRisks(risks);
|
41
64
|
}
|
42
|
-
|
65
|
+
return risks;
|
66
|
+
}, [response, status, isIop]);
|
67
|
+
|
68
|
+
useEffect(() => {
|
69
|
+
setTotalRisks(checkRisks);
|
70
|
+
}, [checkRisks]);
|
71
|
+
|
72
|
+
if (!insightsFacet) return null;
|
43
73
|
|
44
74
|
const onChartClick = (evt, { index }) => {
|
45
75
|
hashHistory.push(`/Insights`);
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
76
|
+
!isIop &&
|
77
|
+
dispatch(
|
78
|
+
push({
|
79
|
+
search: `search=total_risk+%3D+${index + 1}`,
|
80
|
+
})
|
81
|
+
);
|
51
82
|
};
|
52
83
|
|
53
84
|
const onChartHover = (evt, { index }) => [
|
@@ -61,11 +92,16 @@ const InsightsTotalRiskCard = ({ hostDetails: { id } }) => {
|
|
61
92
|
const { 1: low, 2: moderate, 3: important, 4: critical, total } = totalRisks;
|
62
93
|
|
63
94
|
// eslint-disable-next-line react/prop-types
|
64
|
-
const LegendLabel = ({ index, ...rest }) =>
|
65
|
-
|
66
|
-
<ChartLabel {...rest}
|
67
|
-
|
68
|
-
|
95
|
+
const LegendLabel = ({ index, ...rest }) => {
|
96
|
+
if (isIop) {
|
97
|
+
return <ChartLabel {...rest} />;
|
98
|
+
}
|
99
|
+
return (
|
100
|
+
<a key={index} onClick={() => onChartClick(null, { index })}>
|
101
|
+
<ChartLabel {...rest} />
|
102
|
+
</a>
|
103
|
+
);
|
104
|
+
};
|
69
105
|
|
70
106
|
const legend = (
|
71
107
|
<ChartLegend
|
@@ -0,0 +1,194 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
3
|
+
import '@testing-library/jest-dom';
|
4
|
+
import { Provider } from 'react-redux';
|
5
|
+
import { ConnectedRouter } from 'connected-react-router';
|
6
|
+
import { createMemoryHistory } from 'history';
|
7
|
+
import configureMockStore from 'redux-mock-store';
|
8
|
+
import { STATUS } from 'foremanReact/constants';
|
9
|
+
import * as APIHooks from 'foremanReact/common/hooks/API/APIHooks';
|
10
|
+
import InsightsTotalRiskCard from '../InsightsTotalRiskChart';
|
11
|
+
|
12
|
+
jest.mock('foremanReact/common/hooks/API/APIHooks');
|
13
|
+
jest.mock('foremanReact/common/I18n', () => ({
|
14
|
+
translate: jest.fn(str => str),
|
15
|
+
}));
|
16
|
+
|
17
|
+
const mockStore = configureMockStore();
|
18
|
+
const history = createMemoryHistory();
|
19
|
+
const store = mockStore({
|
20
|
+
router: {
|
21
|
+
location: {
|
22
|
+
pathname: '/',
|
23
|
+
search: '',
|
24
|
+
hash: '',
|
25
|
+
state: null,
|
26
|
+
},
|
27
|
+
action: 'POP',
|
28
|
+
},
|
29
|
+
});
|
30
|
+
|
31
|
+
const defaultHostDetails = {
|
32
|
+
id: 1,
|
33
|
+
insights_attributes: {
|
34
|
+
uuid: 'test-uuid',
|
35
|
+
use_iop_mode: false,
|
36
|
+
},
|
37
|
+
};
|
38
|
+
|
39
|
+
const renderComponent = (props = {}) => {
|
40
|
+
const allProps = {
|
41
|
+
hostDetails: defaultHostDetails,
|
42
|
+
...props,
|
43
|
+
};
|
44
|
+
|
45
|
+
return render(
|
46
|
+
<Provider store={store}>
|
47
|
+
<ConnectedRouter history={history}>
|
48
|
+
<InsightsTotalRiskCard {...allProps} />
|
49
|
+
</ConnectedRouter>
|
50
|
+
</Provider>
|
51
|
+
);
|
52
|
+
};
|
53
|
+
|
54
|
+
describe('InsightsTotalRiskChart', () => {
|
55
|
+
beforeEach(() => {
|
56
|
+
store.clearActions();
|
57
|
+
jest.clearAllMocks();
|
58
|
+
});
|
59
|
+
|
60
|
+
it('should show loading state initially', () => {
|
61
|
+
APIHooks.useAPI.mockReturnValue({
|
62
|
+
status: STATUS.PENDING,
|
63
|
+
response: null,
|
64
|
+
});
|
65
|
+
|
66
|
+
renderComponent();
|
67
|
+
// SkeletonLoader shows loading state when status is PENDING
|
68
|
+
expect(screen.queryByText('No results found')).not.toBeInTheDocument();
|
69
|
+
expect(
|
70
|
+
screen.queryByTestId('rh-cloud-total-risk-card')
|
71
|
+
).not.toBeInTheDocument();
|
72
|
+
});
|
73
|
+
|
74
|
+
it('should display error state when API fails', async () => {
|
75
|
+
APIHooks.useAPI.mockReturnValue({
|
76
|
+
status: STATUS.ERROR,
|
77
|
+
response: null,
|
78
|
+
});
|
79
|
+
|
80
|
+
renderComponent();
|
81
|
+
expect(screen.getByText('No results found')).toBeInTheDocument();
|
82
|
+
expect(
|
83
|
+
screen.queryByTestId('rh-cloud-total-risk-card')
|
84
|
+
).not.toBeInTheDocument();
|
85
|
+
});
|
86
|
+
|
87
|
+
it('should handle non-IoP mode API response correctly', async () => {
|
88
|
+
const mockResponse = {
|
89
|
+
hits: [
|
90
|
+
{ total_risk: 1 },
|
91
|
+
{ total_risk: 2 },
|
92
|
+
{ total_risk: 2 },
|
93
|
+
{ total_risk: 3 },
|
94
|
+
{ total_risk: 4 },
|
95
|
+
],
|
96
|
+
};
|
97
|
+
|
98
|
+
APIHooks.useAPI.mockReturnValue({
|
99
|
+
status: STATUS.RESOLVED,
|
100
|
+
response: mockResponse,
|
101
|
+
});
|
102
|
+
|
103
|
+
renderComponent();
|
104
|
+
|
105
|
+
await waitFor(() => {
|
106
|
+
// Check if total number of recommendations is displayed
|
107
|
+
expect(screen.getByText('5')).toBeInTheDocument();
|
108
|
+
// Check if risk levels are displayed correctly
|
109
|
+
expect(screen.getByText(/Low: 1/)).toBeInTheDocument();
|
110
|
+
expect(screen.getByText(/Moderate: 2/)).toBeInTheDocument();
|
111
|
+
expect(screen.getByText(/Important: 1/)).toBeInTheDocument();
|
112
|
+
expect(screen.getByText(/Critical: 1/)).toBeInTheDocument();
|
113
|
+
});
|
114
|
+
});
|
115
|
+
|
116
|
+
it('should handle IOP mode API response correctly', async () => {
|
117
|
+
const mockResponse = {
|
118
|
+
low_hits: 2,
|
119
|
+
moderate_hits: 3,
|
120
|
+
important_hits: 1,
|
121
|
+
critical_hits: 2,
|
122
|
+
hits: 8,
|
123
|
+
};
|
124
|
+
|
125
|
+
APIHooks.useAPI.mockReturnValue({
|
126
|
+
status: STATUS.RESOLVED,
|
127
|
+
response: mockResponse,
|
128
|
+
});
|
129
|
+
|
130
|
+
renderComponent({
|
131
|
+
hostDetails: {
|
132
|
+
...defaultHostDetails,
|
133
|
+
insights_attributes: {
|
134
|
+
...defaultHostDetails.insights_attributes,
|
135
|
+
use_iop_mode: true,
|
136
|
+
},
|
137
|
+
},
|
138
|
+
});
|
139
|
+
|
140
|
+
await waitFor(() => {
|
141
|
+
// Check if total number of recommendations is displayed
|
142
|
+
expect(screen.getByText('8')).toBeInTheDocument();
|
143
|
+
// Check if risk levels are displayed correctly
|
144
|
+
expect(screen.getByText(/Low: 2/)).toBeInTheDocument();
|
145
|
+
expect(screen.getByText(/Moderate: 3/)).toBeInTheDocument();
|
146
|
+
expect(screen.getByText(/Important: 1/)).toBeInTheDocument();
|
147
|
+
expect(screen.getByText(/Critical: 2/)).toBeInTheDocument();
|
148
|
+
});
|
149
|
+
});
|
150
|
+
|
151
|
+
it('should show empty state when no recommendations exist', async () => {
|
152
|
+
APIHooks.useAPI.mockReturnValue({
|
153
|
+
status: STATUS.RESOLVED,
|
154
|
+
response: { hits: [] },
|
155
|
+
});
|
156
|
+
|
157
|
+
renderComponent();
|
158
|
+
|
159
|
+
await waitFor(() => {
|
160
|
+
expect(screen.getByText(/Low: 0/)).toBeInTheDocument();
|
161
|
+
expect(screen.getByText(/Moderate: 0/)).toBeInTheDocument();
|
162
|
+
expect(screen.getByText(/Important: 0/)).toBeInTheDocument();
|
163
|
+
expect(screen.getByText(/Critical: 0/)).toBeInTheDocument();
|
164
|
+
});
|
165
|
+
});
|
166
|
+
|
167
|
+
it('should use correct API endpoint based on IOP mode', () => {
|
168
|
+
renderComponent({
|
169
|
+
hostDetails: {
|
170
|
+
...defaultHostDetails,
|
171
|
+
insights_attributes: {
|
172
|
+
...defaultHostDetails.insights_attributes,
|
173
|
+
use_iop_mode: true,
|
174
|
+
},
|
175
|
+
},
|
176
|
+
});
|
177
|
+
|
178
|
+
expect(APIHooks.useAPI).toHaveBeenCalledWith(
|
179
|
+
'get',
|
180
|
+
expect.stringContaining('/api/insights/v1/system/test-uuid'),
|
181
|
+
expect.any(Object)
|
182
|
+
);
|
183
|
+
|
184
|
+
jest.clearAllMocks();
|
185
|
+
|
186
|
+
renderComponent();
|
187
|
+
|
188
|
+
expect(APIHooks.useAPI).toHaveBeenCalledWith(
|
189
|
+
'get',
|
190
|
+
expect.stringContaining('/hits/1'),
|
191
|
+
expect.any(Object)
|
192
|
+
);
|
193
|
+
});
|
194
|
+
});
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_rh_cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 13.0.
|
4
|
+
version: 13.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Foreman Red Hat Cloud team
|
@@ -139,7 +139,6 @@ files:
|
|
139
139
|
- app/services/foreman_rh_cloud/cloud_presence.rb
|
140
140
|
- app/services/foreman_rh_cloud/cloud_request.rb
|
141
141
|
- app/services/foreman_rh_cloud/cloud_request_forwarder.rb
|
142
|
-
- app/services/foreman_rh_cloud/gateway_request.rb
|
143
142
|
- app/services/foreman_rh_cloud/hit_remediations_retriever.rb
|
144
143
|
- app/services/foreman_rh_cloud/hits_uploader.rb
|
145
144
|
- app/services/foreman_rh_cloud/insights_api_forwarder.rb
|
@@ -185,13 +184,17 @@ files:
|
|
185
184
|
- db/seeds.d/50_job_templates.rb
|
186
185
|
- lib/foreman_inventory_upload.rb
|
187
186
|
- lib/foreman_inventory_upload/async/async_helpers.rb
|
187
|
+
- lib/foreman_inventory_upload/async/create_missing_insights_facets.rb
|
188
188
|
- lib/foreman_inventory_upload/async/delayed_start.rb
|
189
189
|
- lib/foreman_inventory_upload/async/generate_all_reports_job.rb
|
190
|
+
- lib/foreman_inventory_upload/async/generate_host_report.rb
|
190
191
|
- lib/foreman_inventory_upload/async/generate_report_job.rb
|
192
|
+
- lib/foreman_inventory_upload/async/host_inventory_report_job.rb
|
191
193
|
- lib/foreman_inventory_upload/async/progress_output.rb
|
192
194
|
- lib/foreman_inventory_upload/async/queue_for_upload_job.rb
|
193
195
|
- lib/foreman_inventory_upload/async/remove_insights_hosts_job.rb
|
194
196
|
- lib/foreman_inventory_upload/async/shell_process.rb
|
197
|
+
- lib/foreman_inventory_upload/async/single_host_report_job.rb
|
195
198
|
- lib/foreman_inventory_upload/async/upload_report_job.rb
|
196
199
|
- lib/foreman_inventory_upload/generators/archived_report.rb
|
197
200
|
- lib/foreman_inventory_upload/generators/fact_helpers.rb
|
@@ -621,6 +624,7 @@ files:
|
|
621
624
|
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabIntegration.test.js
|
622
625
|
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabReducer.test.js
|
623
626
|
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabSelectors.test.js
|
627
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTotalRiskChart.test.js
|
624
628
|
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTab.test.js.snap
|
625
629
|
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabActions.test.js.snap
|
626
630
|
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabReducer.test.js.snap
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module ForemanRhCloud
|
2
|
-
module GatewayRequest
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
include CloudRequest
|
6
|
-
|
7
|
-
def execute_cloud_request(params)
|
8
|
-
certs = params.delete(:certs) || foreman_certificates
|
9
|
-
final_params = {
|
10
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
11
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
12
|
-
ssl_ca_file: Setting[:ssl_ca_file],
|
13
|
-
verify_ssl: OpenSSL::SSL::VERIFY_PEER,
|
14
|
-
}.deep_merge(params)
|
15
|
-
|
16
|
-
super(final_params)
|
17
|
-
end
|
18
|
-
|
19
|
-
def foreman_certificates
|
20
|
-
{
|
21
|
-
cert: File.read(Setting[:ssl_certificate]),
|
22
|
-
key: File.read(Setting[:ssl_priv_key]),
|
23
|
-
}
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|