foreman_rh_cloud 11.4.4 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/app/controllers/api/v2/rh_cloud/inventory_controller.rb +2 -2
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +22 -26
- data/app/services/foreman_rh_cloud/cloud_request.rb +2 -12
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +3 -17
- data/app/services/foreman_rh_cloud/rules_ingester.rb +1 -12
- data/config/routes.rb +0 -4
- data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +3 -3
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +4 -4
- data/lib/foreman_inventory_upload/generators/fact_helpers.rb +13 -65
- data/lib/foreman_inventory_upload/generators/queries.rb +3 -5
- data/lib/foreman_inventory_upload/generators/slice.rb +1 -0
- data/lib/foreman_rh_cloud/engine.rb +0 -11
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/foreman_rh_cloud.rb +0 -2
- data/lib/tasks/hybrid_cloud.rake +36 -94
- data/package.json +5 -5
- data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +2 -14
- data/test/controllers/inventory_upload/api/inventory_controller_test.rb +1 -1
- data/test/jobs/upload_report_job_test.rb +1 -1
- data/test/unit/fact_helpers_test.rb +2 -267
- data/test/unit/slice_generator_test.rb +10 -69
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +1 -7
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/__tests__/__snapshots__/ListItemStatus.test.js.snap +1 -5
- data/webpack/ForemanInventoryUpload/Components/AccountList/accountList.scss +3 -3
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/inventoryFilter.scss +1 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.scss +5 -5
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +5 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +18 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +0 -1
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +2 -10
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +5 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +7 -7
- data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +1 -1
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +5 -1
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationTableConstants.js +8 -1
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +8 -2
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +1 -1
- data/webpack/InsightsHostDetailsTab/InsightsTotalRiskChart.js +11 -2
- data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +5 -4
- data/webpack/common/DropdownToggle.js +2 -2
- data/webpack/common/Switcher/HelpLabel.js +1 -1
- data/webpack/common/Switcher/SwitcherPF4.scss +1 -1
- data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +2 -6
- data/webpack/common/table/EmptyState.js +25 -18
- metadata +3 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3666ab0afa45f6fbf3fbe06ec110cbbf7d7eca432b02686e945afca5b412f31
|
4
|
+
data.tar.gz: ce3380aca30486d23d89c3e9b30d17cbc862e51ba55032b1e60565ec63af1cc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b853fd7fe75e52c4127984c2644feb55fb455d52d68a86b55ed9d96b84e03d05408fc9ddf5190253d2938965c8583b33903682fabfe137f42ce06f57a2d96a09
|
7
|
+
data.tar.gz: fb4777f06aa6d47e0038cc3533b86779a95694c23e4d01b01bc78e10c07196f16df87ead87d4787e8c4dc518813d7ef4e250d8fe955857ebe6811ad5e8b0d3ec
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ for how to install Foreman plugins
|
|
15
15
|
|
16
16
|
#### Inventory upload
|
17
17
|
|
18
|
-
In UI:
|
18
|
+
In UI: Configure -> Inventory Upload -> Generate and upload report
|
19
19
|
|
20
20
|
From command-line:
|
21
21
|
|
@@ -38,7 +38,7 @@ From command-line:
|
|
38
38
|
|
39
39
|
#### Fetch hosts remediation data
|
40
40
|
|
41
|
-
In UI:
|
41
|
+
In UI: Configure -> Insights -> Sync now
|
42
42
|
|
43
43
|
From command-line:
|
44
44
|
|
@@ -46,7 +46,7 @@ From command-line:
|
|
46
46
|
|
47
47
|
#### Synchronize inventory status
|
48
48
|
|
49
|
-
In UI:
|
49
|
+
In UI: Configure -> Inventory Upload -> Sync all inventory status
|
50
50
|
|
51
51
|
From command-line:
|
52
52
|
|
@@ -18,10 +18,10 @@ module Api
|
|
18
18
|
|
19
19
|
api :POST, "/organizations/:organization_id/rh_cloud/report", N_("Start report generation")
|
20
20
|
param :organization_id, Integer, required: true, desc: N_("Set the current organization context for the request")
|
21
|
-
param :
|
21
|
+
param :no_upload, :bool, required: false, default: false, desc: N_('Generate the report, but do not upload')
|
22
22
|
def generate_report
|
23
23
|
organization_id = params[:organization_id]
|
24
|
-
disconnected = params[:
|
24
|
+
disconnected = params[:no_upload] || false
|
25
25
|
|
26
26
|
start_report_generation(organization_id, disconnected)
|
27
27
|
|
@@ -18,39 +18,35 @@ module InsightsCloud::Api
|
|
18
18
|
certs = candlepin_id_cert @organization
|
19
19
|
begin
|
20
20
|
@cloud_response = ::ForemanRhCloud::CloudRequestForwarder.new.forward_request(request, controller_name, @branch_id, certs)
|
21
|
-
rescue RestClient::
|
22
|
-
|
23
|
-
return render json: {
|
24
|
-
rescue RestClient::
|
25
|
-
logger.info("Forwarding request
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
message = 'Cloud request not modified'
|
31
|
-
return render json: { message: message, error: message }, status: :not_modified
|
32
|
-
rescue RestClient::ExceptionWithResponse => e
|
33
|
-
response_obj = e.response.presence || e.exception
|
34
|
-
code = response_obj.try(:code) || response_obj.try(:http_code) || 500
|
35
|
-
message = 'Cloud request failed'
|
21
|
+
rescue RestClient::Exception => e
|
22
|
+
logger.info("Forwarding request failed with exception: #{e}")
|
23
|
+
return render json: { error: e }, status: :bad_gateway
|
24
|
+
rescue RestClient::Timeout => e
|
25
|
+
logger.info("Forwarding request failed with timeout: #{e}")
|
26
|
+
return render json: { error: e }, status: :gateway_timeout
|
27
|
+
end
|
28
|
+
|
29
|
+
return render json: { message: @cloud_response.to_s }, status: :gateway_timeout if @cloud_response.is_a?(RestClient::Exceptions::OpenTimeout)
|
36
30
|
|
31
|
+
if @cloud_response.code == 401
|
37
32
|
return render json: {
|
38
|
-
:message =>
|
39
|
-
:error => response_obj.to_s,
|
33
|
+
:message => 'Authentication to the Insights Service failed.',
|
40
34
|
:headers => {},
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
}, status: :bad_gateway
|
36
|
+
end
|
37
|
+
|
38
|
+
if @cloud_response.code >= 300
|
39
|
+
return render json: {
|
40
|
+
:message => 'Cloud request failed',
|
41
|
+
:headers => {},
|
42
|
+
:response => @cloud_response,
|
43
|
+
}, status: @cloud_response.code
|
47
44
|
end
|
48
45
|
|
49
46
|
# Append redhat-specific headers
|
50
47
|
@cloud_response.headers.each do |key, value|
|
51
48
|
assign_header(response, @cloud_response, key, false) if key.to_s.start_with?('x_rh_')
|
52
49
|
end
|
53
|
-
|
54
50
|
# Append general headers
|
55
51
|
assign_header(response, @cloud_response, :x_resource_count, true)
|
56
52
|
headers[Rack::ETAG] = @cloud_response.headers[:etag]
|
@@ -60,8 +56,8 @@ module InsightsCloud::Api
|
|
60
56
|
# content type
|
61
57
|
send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
|
62
58
|
elsif @cloud_response.headers[:content_type] =~ /zip/
|
63
|
-
#
|
64
|
-
#
|
59
|
+
# if there is no Content-Disposition, but the content type is binary according the content type,
|
60
|
+
# forward the request as binry too
|
65
61
|
send_data @cloud_response, type: @cloud_response.headers[:content_type]
|
66
62
|
else
|
67
63
|
render json: @cloud_response, status: @cloud_response.code
|
@@ -8,23 +8,13 @@ module ForemanRhCloud
|
|
8
8
|
proxy: ForemanRhCloud.transformed_http_proxy_string,
|
9
9
|
}.deep_merge(params)
|
10
10
|
|
11
|
-
if ForemanRhCloud.with_local_advisor_engine?
|
12
|
-
final_params[:ssl_ca_file] ||= ForemanRhCloud.ca_cert
|
13
|
-
end
|
14
|
-
|
15
11
|
response = RestClient::Request.execute(final_params)
|
16
12
|
|
17
13
|
logger.debug("Response headers for request url #{final_params[:url]} are: #{response.headers}")
|
18
14
|
|
19
15
|
response
|
20
|
-
rescue RestClient::
|
21
|
-
logger.debug("
|
22
|
-
raise ex
|
23
|
-
rescue RestClient::ExceptionWithResponse => ex
|
24
|
-
logger.debug("Response headers for request url #{final_params[:url]} with status code #{ex.http_code} are: #{ex.http_headers} and body: #{ex.http_body}")
|
25
|
-
raise ex
|
26
|
-
rescue StandardError => ex
|
27
|
-
logger.debug("Exception raised for request url #{final_params[:url]}: #{ex}")
|
16
|
+
rescue RestClient::Exception => ex
|
17
|
+
logger.debug("Failed response with code #{ex.http_code} headers for request url #{final_params[:url]} are: #{ex.http_headers} and body: #{ex.http_body}")
|
28
18
|
raise ex
|
29
19
|
end
|
30
20
|
end
|
@@ -17,6 +17,8 @@ module ForemanRhCloud
|
|
17
17
|
logger.debug("Sending request to: #{request_opts[:url]}")
|
18
18
|
|
19
19
|
execute_cloud_request(request_opts)
|
20
|
+
rescue RestClient::ExceptionWithResponse => error_response
|
21
|
+
error_response.response.presence || error_response.exception
|
20
22
|
end
|
21
23
|
|
22
24
|
def prepare_request_opts(original_request, forward_payload, forward_params, certs)
|
@@ -32,13 +34,7 @@ module ForemanRhCloud
|
|
32
34
|
),
|
33
35
|
}
|
34
36
|
requested_url = original_request.original_fullpath.end_with?('/') ? original_request.path + '/' : original_request.path
|
35
|
-
|
36
|
-
|
37
|
-
if ForemanRhCloud.with_local_advisor_engine?
|
38
|
-
params[:ssl_ca_file] = ForemanRhCloud.ca_cert
|
39
|
-
end
|
40
|
-
|
41
|
-
base_params.merge(params)
|
37
|
+
base_params.merge(path_params(requested_url, certs))
|
42
38
|
end
|
43
39
|
|
44
40
|
def prepare_forward_payload(original_request, controller_name)
|
@@ -67,12 +63,6 @@ module ForemanRhCloud
|
|
67
63
|
|
68
64
|
def path_params(request_path, certs)
|
69
65
|
case request_path
|
70
|
-
when lightspeed?
|
71
|
-
{
|
72
|
-
url: ForemanRhCloud.cert_base_url + request_path,
|
73
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
74
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
75
|
-
}
|
76
66
|
when platform_request?
|
77
67
|
{
|
78
68
|
url: ForemanRhCloud.cert_base_url + request_path.sub('/redhat_access/r/insights/platform', '/api'),
|
@@ -105,10 +95,6 @@ module ForemanRhCloud
|
|
105
95
|
headers
|
106
96
|
end
|
107
97
|
|
108
|
-
def lightspeed?
|
109
|
-
->(request_path) { request_path.include? '/lightspeed' }
|
110
|
-
end
|
111
|
-
|
112
98
|
def platform_request?
|
113
99
|
->(request_path) { request_path.include? '/platform' }
|
114
100
|
end
|
@@ -13,18 +13,7 @@ module ForemanRhCloud
|
|
13
13
|
|
14
14
|
def fetch_rules_data
|
15
15
|
advisor_url = "#{ForemanRhCloud.on_premise_url}/r/insights/v1/static/release/content.json"
|
16
|
-
|
17
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
18
|
-
http.use_ssl = true
|
19
|
-
|
20
|
-
# Set CA certificate
|
21
|
-
http.ca_file = ForemanRhCloud.ca_cert
|
22
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
23
|
-
|
24
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
25
|
-
|
26
|
-
response = http.request(request)
|
27
|
-
JSON.parse(response.body, symbolize_names: true)
|
16
|
+
JSON.parse(Net::HTTP.get(URI.parse(advisor_url)), symbolize_names: true)
|
28
17
|
end
|
29
18
|
|
30
19
|
def fetch_rules_and_resolutions
|
data/config/routes.rb
CHANGED
@@ -49,10 +49,6 @@ Rails.application.routes.draw do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
scope :module => :'insights_cloud/api' do
|
53
|
-
match '/api/lightspeed/*path', to: 'machine_telemetries#forward_request', via: :all
|
54
|
-
end
|
55
|
-
|
56
52
|
# API routes
|
57
53
|
|
58
54
|
namespace :api, :defaults => { :format => 'json' } do
|
@@ -3,7 +3,7 @@ module ForemanInventoryUpload
|
|
3
3
|
class QueueForUploadJob < ::Actions::EntryAction
|
4
4
|
def plan(base_folder, report_file, organization_id, disconnected)
|
5
5
|
enqueue_task = plan_self(base_folder: base_folder, report_file: report_file)
|
6
|
-
plan_upload_report(enqueue_task.output[:enqueued_file_name], organization_id
|
6
|
+
plan_upload_report(enqueue_task.output[:enqueued_file_name], organization_id, disconnected)
|
7
7
|
end
|
8
8
|
|
9
9
|
def run
|
@@ -59,8 +59,8 @@ module ForemanInventoryUpload
|
|
59
59
|
input[:report_file]
|
60
60
|
end
|
61
61
|
|
62
|
-
def plan_upload_report(enqueued_file_name, organization_id)
|
63
|
-
plan_action(UploadReportJob, enqueued_file_name, organization_id)
|
62
|
+
def plan_upload_report(enqueued_file_name, organization_id, disconnected)
|
63
|
+
plan_action(UploadReportJob, enqueued_file_name, organization_id, disconnected)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -7,15 +7,15 @@ module ForemanInventoryUpload
|
|
7
7
|
"upload_for_#{label}"
|
8
8
|
end
|
9
9
|
|
10
|
-
def plan(filename, organization_id)
|
10
|
+
def plan(filename, organization_id, disconnected = false)
|
11
11
|
label = UploadReportJob.output_label(organization_id)
|
12
|
-
super(label, filename: filename, organization_id: organization_id)
|
12
|
+
super(label, filename: filename, organization_id: organization_id, disconnected: disconnected)
|
13
13
|
end
|
14
14
|
|
15
15
|
def try_execute
|
16
16
|
if content_disconnected?
|
17
17
|
progress_output do |progress_output|
|
18
|
-
progress_output.write_line('Upload
|
18
|
+
progress_output.write_line('Upload canceled because connection to Insights is not enabled or the --no-upload option was passed.')
|
19
19
|
progress_output.status = "Task aborted, exit 1"
|
20
20
|
done!
|
21
21
|
end
|
@@ -78,7 +78,7 @@ module ForemanInventoryUpload
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def content_disconnected?
|
81
|
-
!Setting[:subscription_connection_enabled]
|
81
|
+
input[:disconnected] || !Setting[:subscription_connection_enabled]
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -57,39 +57,17 @@ module ForemanInventoryUpload
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def obfuscate_hostname?(host)
|
60
|
-
# Returns true if hostname obfuscation should be applied for a given host, based on hierarchy:
|
61
|
-
# 1. Global setting for hostname obfuscation.
|
62
|
-
return true if Setting[:obfuscate_inventory_hostnames]
|
63
|
-
|
64
60
|
insights_client_setting = fact_value(host, 'insights_client::obfuscate_hostname_enabled')
|
65
61
|
insights_client_setting = ActiveModel::Type::Boolean.new.cast(insights_client_setting)
|
62
|
+
return insights_client_setting unless insights_client_setting.nil?
|
66
63
|
|
67
|
-
|
68
|
-
# 3. if neither of the above, don't obfuscate.
|
69
|
-
insights_client_setting.nil? ? false : insights_client_setting
|
64
|
+
Setting[:obfuscate_inventory_hostnames]
|
70
65
|
end
|
71
66
|
|
72
67
|
def fqdn(host)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# Example format of `parsed_insights_array`:
|
77
|
-
# [{"original"=>"host.example.com", "obfuscated"=>"0dd449d0a027.example.com"},
|
78
|
-
# {"original"=>"satellite.example.com", "obfuscated"=>"host2.example.com"}]
|
79
|
-
begin
|
80
|
-
parsed_insights_array = JSON.parse(fact_value(host, 'insights_client::obfuscated_hostname') || '[]')
|
81
|
-
rescue JSON::ParserError
|
82
|
-
parsed_insights_array = []
|
83
|
-
end
|
84
|
-
# Obfuscate using the following hierarchy:
|
85
|
-
# 1. the obfuscated_hostname fact sent by insights_client
|
86
|
-
parsed_insights_item = parsed_insights_array.find { |item| item['original'] == host.fqdn }
|
87
|
-
# 2. our own helper method
|
88
|
-
parsed_insights_item&.[]('obfuscated') || obfuscate_fqdn(host.fqdn)
|
89
|
-
else
|
90
|
-
# If hostname obfuscation is not enabled for this host, return the host's original FQDN.
|
91
|
-
host.fqdn
|
92
|
-
end
|
68
|
+
return host.fqdn unless obfuscate_hostname?(host)
|
69
|
+
|
70
|
+
fact_value(host, 'insights_client::hostname') || obfuscate_fqdn(host.fqdn)
|
93
71
|
end
|
94
72
|
|
95
73
|
def obfuscate_fqdn(fqdn)
|
@@ -97,65 +75,35 @@ module ForemanInventoryUpload
|
|
97
75
|
end
|
98
76
|
|
99
77
|
def obfuscate_ips?(host)
|
100
|
-
|
101
|
-
|
102
|
-
return
|
103
|
-
|
104
|
-
insights_client_ipv4_setting = fact_value(host, 'insights_client::obfuscate_ipv4_enabled')
|
105
|
-
insights_client_ipv6_setting = fact_value(host, 'insights_client::obfuscate_ipv6_enabled')
|
106
|
-
|
107
|
-
cast_ipv4_setting = ActiveModel::Type::Boolean.new.cast(insights_client_ipv4_setting)
|
108
|
-
cast_ipv6_setting = ActiveModel::Type::Boolean.new.cast(insights_client_ipv6_setting)
|
78
|
+
insights_client_setting = fact_value(host, 'insights_client::obfuscate_ip_enabled')
|
79
|
+
insights_client_setting = ActiveModel::Type::Boolean.new.cast(insights_client_setting)
|
80
|
+
return insights_client_setting unless insights_client_setting.nil?
|
109
81
|
|
110
|
-
|
111
|
-
# 3. If neither of the above, don't obfuscate.
|
112
|
-
cast_ipv4_setting || cast_ipv6_setting || false
|
82
|
+
Setting[:obfuscate_inventory_ips]
|
113
83
|
end
|
114
84
|
|
115
85
|
def host_ips(host)
|
116
|
-
# Determines and returns the IP addresses associated with a host, applying obfuscation if enabled.
|
117
|
-
|
118
|
-
# If IP obfuscation is enabled for the host return a representation of obfuscated IP addresses.
|
119
86
|
return obfuscated_ips(host) if obfuscate_ips?(host)
|
120
87
|
|
121
|
-
#
|
122
|
-
# where when you try to access a key in it
|
123
|
-
# if the key doesn't exist, it simply returns the key itself.
|
124
|
-
# This is useful because it means if you try to get an IP from this hash,
|
125
|
-
# you'll just get the original IP back. It allows the calling code to
|
126
|
-
# use the same interface whether obfuscation is applied or not.
|
88
|
+
# return a pass through proxy hash in case no obfuscation needed
|
127
89
|
Hash.new { |h, k| k }
|
128
90
|
end
|
129
91
|
|
130
92
|
def obfuscated_ips(host)
|
131
|
-
|
132
|
-
# [{"original": "192.168.1.10", "obfuscated": "10.230.230.1"},
|
133
|
-
# {"original": "192.168.1.11", "obfuscated": "10.230.230.2"}]
|
134
|
-
begin
|
135
|
-
parsed_insights_array = JSON.parse(fact_value(host, 'insights_client::obfuscated_ipv4') || '[]')
|
136
|
-
rescue JSON::ParserError
|
137
|
-
parsed_insights_array = []
|
138
|
-
end
|
93
|
+
insights_client_ips = JSON.parse(fact_value(host, 'insights_client::ips') || '[]')
|
139
94
|
|
140
|
-
# Create a new Hash to store the mapping from original IP addresses to their obfuscated versions.
|
141
|
-
# where the 'original' IP is the key and the 'obfuscated' IP is the value.
|
142
95
|
obfuscated_ips = Hash[
|
143
|
-
|
96
|
+
insights_client_ips.map { |ip_record| [ip_record['original'], ip_record['obfuscated']] }
|
144
97
|
]
|
145
98
|
|
146
|
-
# Sets a default proc for the obfuscated_ips hash.
|
147
|
-
# When a key is accessed that does not exist in the hash, this proc is called.
|
148
|
-
# It assigns the result of obfuscate_ip(key, hash) to the missing key in the hash.
|
149
|
-
# This ensures that any missing IP address key will be obfuscated and stored automatically.
|
150
99
|
obfuscated_ips.default_proc = proc do |hash, key|
|
151
100
|
hash[key] = obfuscate_ip(key, hash)
|
152
101
|
end
|
102
|
+
|
153
103
|
obfuscated_ips
|
154
104
|
end
|
155
105
|
|
156
106
|
def obfuscate_ip(ip, ips_dict)
|
157
|
-
# Produce a new, unique obfuscated IP that is
|
158
|
-
# numerically one greater than the highest existing obfuscated IP
|
159
107
|
max_obfuscated = ips_dict.values.map { |v| IPAddr.new(v).to_i }.max || IPAddr.new('10.230.230.0').to_i
|
160
108
|
|
161
109
|
IPAddr.new(max_obfuscated + 1, Socket::AF_INET).to_s
|
@@ -24,11 +24,9 @@ module ForemanInventoryUpload
|
|
24
24
|
'dmi::system::product_name',
|
25
25
|
'dmi::chassis::asset_tag',
|
26
26
|
'insights_client::obfuscate_hostname_enabled',
|
27
|
-
'insights_client::
|
28
|
-
'insights_client::
|
29
|
-
'insights_client::
|
30
|
-
'insights_client::obfuscated_ipv6',
|
31
|
-
'insights_client::obfuscated_hostname',
|
27
|
+
'insights_client::obfuscate_ip_enabled',
|
28
|
+
'insights_client::hostname',
|
29
|
+
'insights_client::ips',
|
32
30
|
'insights_id',
|
33
31
|
'conversions::activity',
|
34
32
|
'conversions::packages::0::nevra',
|
@@ -149,6 +149,7 @@ module ForemanInventoryUpload
|
|
149
149
|
) { |v| os_release_value(*v) }
|
150
150
|
@stream.simple_field('os_kernel_version', fact_value(host, 'uname::release'))
|
151
151
|
@stream.simple_field('arch', host.architecture&.name)
|
152
|
+
@stream.simple_field('katello_agent_running', false)
|
152
153
|
@stream.simple_field(
|
153
154
|
'infrastructure_type',
|
154
155
|
ActiveModel::Type::Boolean.new.cast(fact_value(host, 'virt::is_guest')) ? 'virtual' : 'physical'
|
@@ -212,15 +212,4 @@ module ForemanRhCloud
|
|
212
212
|
def self.with_local_advisor_engine?
|
213
213
|
SETTINGS.dig(:foreman_rh_cloud, :use_local_advisor_engine) || false
|
214
214
|
end
|
215
|
-
|
216
|
-
def self.ca_cert
|
217
|
-
# The reference to candlepin ca_cert_file can be removed
|
218
|
-
# once the setting is dropped. Foreman 3.15 introduces
|
219
|
-
# a single CA file that bundles all CAs.
|
220
|
-
if ::SETTINGS.dig(:katello, :candlepin, :ca_cert_file)
|
221
|
-
::SETTINGS[:katello][:candlepin][:ca_cert_file]
|
222
|
-
else
|
223
|
-
::SETTINGS[:ssl_ca_file]
|
224
|
-
end
|
225
|
-
end
|
226
215
|
end
|
data/lib/foreman_rh_cloud.rb
CHANGED
data/lib/tasks/hybrid_cloud.rake
CHANGED
@@ -1,122 +1,64 @@
|
|
1
1
|
require 'io/console'
|
2
|
-
require 'uri'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
namespace :rh_cloud do
|
9
|
-
desc 'Register Satellite Organization with Hybrid Cloud API.'
|
10
|
-
# This task registers the Satellite Organization with the Hybrid Cloud API.
|
11
|
-
# It requires the user to input their organization ID, Insights URL, and token.
|
12
|
-
# The task will then send a POST request to the Hybrid Cloud API to register the organization.
|
13
|
-
# The response will be logged, and any errors will be caught and logged as well.
|
14
|
-
# The task will exit with an error message if the organization does not have a manifest imported or if the token is not entered.
|
15
|
-
# The task will also log a warning if the custom URL is not set and the default one is used.
|
3
|
+
namespace :rh_cloud do |args|
|
4
|
+
desc 'Register Satellite Organization with Hybrid Cloud API. \
|
5
|
+
Specify org_id=x replace your organization ID with x. \
|
6
|
+
Specify SATELLITE_RH_CLOUD_URL=https://x with the Hybrid Cloud endpoint you are connecting to.'
|
16
7
|
task hybridcloud_register: [:environment] do
|
17
8
|
include ::ForemanRhCloud::CertAuth
|
18
9
|
include ::InsightsCloud::CandlepinCache
|
19
10
|
|
20
|
-
|
21
|
-
|
22
|
-
if custom_url.empty?
|
23
|
-
logger.warn("Custom url is not set, using the default one: #{ForemanRhCloud.base_url}")
|
24
|
-
URI.join(ForemanRhCloud.base_url, '/api/identity/certificate/registrations').to_s
|
25
|
-
else
|
26
|
-
URI.join(custom_url, '/api/identity/certificate/registrations').to_s
|
27
|
-
end
|
11
|
+
def logger
|
12
|
+
@logger ||= Logger.new(STDOUT)
|
28
13
|
end
|
29
14
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
input = STDIN.gets.chomp
|
34
|
-
if input.match?(/^\d+$/) # Checks if input consists only of digits
|
35
|
-
@user_org_id = input.to_i
|
36
|
-
break
|
37
|
-
else
|
38
|
-
puts "Invalid input. Please enter a numeric organization ID."
|
39
|
-
end
|
15
|
+
def registrations_url
|
16
|
+
logger.warn("Custom url is not set, using the default one: #{ForemanRhCloud.base_url}") if ENV['SATELLITE_RH_CLOUD_URL'].empty?
|
17
|
+
ForemanRhCloud.base_url + '/api/identity/certificate/registrations'
|
40
18
|
end
|
41
19
|
|
42
|
-
|
43
|
-
|
44
|
-
insights_user_input = STDIN.gets.chomp
|
45
|
-
|
46
|
-
# --- Data Preparation ---
|
47
|
-
|
48
|
-
organization = Organization.find_by(id: @user_org_id)
|
49
|
-
|
50
|
-
if organization.nil?
|
51
|
-
logger.error("Organization with ID '#{@user_org_id}' not found.")
|
20
|
+
if ENV['org_id'].nil?
|
21
|
+
logger.error('ERROR: org_id needs to be specified.')
|
52
22
|
exit(1)
|
53
23
|
end
|
54
24
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
25
|
+
@organization = Organization.find_by(id: ENV['org_id'].to_i) # saw this coming in as a string, so making sure it gets passed as an integer.
|
26
|
+
@uid = cp_owner_id(@organization)
|
27
|
+
@hostname = ForemanRhCloud.foreman_host_name
|
28
|
+
logger.error('Organization provided does not have a manifest imported.') + exit(1) if @uid.nil?
|
60
29
|
|
61
|
-
|
62
|
-
|
30
|
+
puts 'Paste your token, output will be hidden.'
|
31
|
+
@token = STDIN.noecho(&:gets).chomp
|
32
|
+
logger.error('Token was not entered.') + exit(1) if @token.empty?
|
63
33
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
if token.empty?
|
70
|
-
logger.error('Token was not entered.')
|
71
|
-
exit(1)
|
34
|
+
def headers
|
35
|
+
{
|
36
|
+
Authorization: "Bearer #{@token}",
|
37
|
+
}
|
72
38
|
end
|
73
39
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
payload = {
|
81
|
-
'uid': uid,
|
82
|
-
"display_name": "#{hostname}+#{organization.label}",
|
83
|
-
}
|
40
|
+
def payload
|
41
|
+
{
|
42
|
+
"uid": @uid,
|
43
|
+
"display_name": "#{@hostname}+#{@organization.label}",
|
44
|
+
}
|
45
|
+
end
|
84
46
|
|
85
|
-
|
47
|
+
def method
|
48
|
+
:post
|
49
|
+
end
|
86
50
|
|
87
51
|
begin
|
88
52
|
response = execute_cloud_request(
|
89
|
-
organization: organization,
|
90
|
-
method:
|
91
|
-
url:
|
53
|
+
organization: @organization,
|
54
|
+
method: method,
|
55
|
+
url: registrations_url,
|
92
56
|
headers: headers,
|
93
57
|
payload: payload.to_json
|
94
58
|
)
|
95
|
-
logger.debug(
|
96
|
-
# Add a more specific rescue for 401 Unauthorized errors
|
97
|
-
rescue RestClient::Unauthorized => _ex
|
98
|
-
logger.error('Registration failed: Your token is invalid or unauthorized. Please check your token and try again.')
|
99
|
-
# Optionally, you can still log the full debug info if helpful for advanced troubleshooting
|
100
|
-
# logger.debug(ex.backtrace.join("\n"))
|
101
|
-
exit(1)
|
102
|
-
rescue RestClient::ExceptionWithResponse => ex
|
103
|
-
# This catches any RestClient exception that has a response (like 400, 403, 404, 500, etc.)
|
104
|
-
status_code = begin
|
105
|
-
ex.response.code
|
106
|
-
rescue StandardError
|
107
|
-
"unknown"
|
108
|
-
end
|
109
|
-
logger.error("Registration failed with HTTP status #{status_code}: #{ex.message}")
|
110
|
-
logger.debug("Response body (if available): #{ex.response.body}")
|
111
|
-
# logger.debug(ex.backtrace.join("\n"))
|
112
|
-
exit(1)
|
59
|
+
logger.debug(response)
|
113
60
|
rescue StandardError => ex
|
114
|
-
|
115
|
-
logger.error("An unexpected error occurred during registration: #{ex.message}")
|
116
|
-
# logger.debug(ex.backtrace.join("\n")) # Log backtrace for more info
|
117
|
-
exit(1)
|
61
|
+
logger.error(ex)
|
118
62
|
end
|
119
|
-
|
120
|
-
logger.info("Satellite Organization '#{organization.label}' (ID: #{@user_org_id}) successfully registered.")
|
121
63
|
end
|
122
64
|
end
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "foreman_rh_cloud",
|
3
|
-
"version": "
|
3
|
+
"version": "12.0.0",
|
4
4
|
"description": "Inventory Upload =============",
|
5
5
|
"main": "index.js",
|
6
6
|
"scripts": {
|
@@ -19,13 +19,13 @@
|
|
19
19
|
"url": "http://projects.theforeman.org/projects/foreman_rh_cloud/issues"
|
20
20
|
},
|
21
21
|
"peerDependencies": {
|
22
|
-
"@theforeman/vendor": ">=
|
22
|
+
"@theforeman/vendor": ">= 15.0.1"
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
25
25
|
"@babel/core": "^7.7.0",
|
26
|
-
"@theforeman/builder": ">=
|
27
|
-
"@theforeman/test": ">=
|
28
|
-
"@theforeman/eslint-plugin-foreman": ">=
|
26
|
+
"@theforeman/builder": ">= 15.0.1",
|
27
|
+
"@theforeman/test": ">= 15.0.1",
|
28
|
+
"@theforeman/eslint-plugin-foreman": ">= 15.0.1",
|
29
29
|
"babel-eslint": "~10.0.0",
|
30
30
|
"eslint": "~6.7.2",
|
31
31
|
"eslint-plugin-spellcheck": "~0.0.17",
|