foreman_rh_cloud 11.4.2 → 11.4.4
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/insights_cloud/api/machine_telemetries_controller.rb +26 -22
- data/app/services/foreman_rh_cloud/cloud_request.rb +8 -2
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +0 -2
- data/lib/foreman_inventory_upload/generators/fact_helpers.rb +65 -13
- data/lib/foreman_inventory_upload/generators/queries.rb +5 -3
- data/lib/foreman_inventory_upload/generators/slice.rb +0 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/tasks/hybrid_cloud.rake +94 -36
- data/package.json +1 -1
- data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +14 -2
- data/test/unit/fact_helpers_test.rb +267 -2
- data/test/unit/slice_generator_test.rb +69 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a69803d7adc37a51cb851a218a60b2150a56503eccece90e30b688f1ec8a1ae6
|
4
|
+
data.tar.gz: 1d79759ed6f0095579f485ead899d8708f151920f9c33e979797672ab78b1585
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6b24e9d002cebdbfd00e74d08fbb04cfe8b413648d9e0ec3b60c1eb2222b652dbe14e5379cd5fbf9927b707144d7b4d61204ee490397cae187189012a153d67
|
7
|
+
data.tar.gz: d63ecaa47ba66a4078b15367092840a44f219f1e99a5cb619bbc7fe7fe3f40569ac8068de89b98c08e2b1f7f4e0ff98502ce8b5a473b635367d80a1f077959e4
|
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: Insights -> Inventory Upload -> select the organization -> 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: Insights -> Recommendations -> Sync recommendations (under the vertical ellipsis)
|
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: Insights -> Inventory Upload -> Sync all inventory status
|
50
50
|
|
51
51
|
From command-line:
|
52
52
|
|
@@ -18,35 +18,39 @@ 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: { error:
|
24
|
-
rescue RestClient::
|
25
|
-
logger.info("Forwarding request
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
rescue RestClient::Exceptions::Timeout => e
|
22
|
+
response_obj = e.response.presence || e.exception
|
23
|
+
return render json: { message: response_obj.to_s, error: response_obj.to_s }, status: :gateway_timeout
|
24
|
+
rescue RestClient::Unauthorized => e
|
25
|
+
logger.info("Forwarding request auth error: #{e}")
|
26
|
+
message = 'Authentication to the Insights Service failed.'
|
27
|
+
return render json: { message: message, error: message }, status: :unauthorized
|
28
|
+
rescue RestClient::NotModified => e
|
29
|
+
logger.info("Forwarding request not modified: #{e}")
|
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'
|
30
36
|
|
31
|
-
if @cloud_response.code == 401
|
32
37
|
return render json: {
|
33
|
-
:message =>
|
38
|
+
:message => message,
|
39
|
+
:error => response_obj.to_s,
|
34
40
|
:headers => {},
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
:headers => {},
|
42
|
-
:response => @cloud_response,
|
43
|
-
}, status: @cloud_response.code
|
41
|
+
:response => response_obj,
|
42
|
+
}, status: code
|
43
|
+
rescue StandardError => e
|
44
|
+
# Catch any other exceptions here, such as Errno::ECONNREFUSED
|
45
|
+
logger.info("Cloud request failed with exception: #{e}")
|
46
|
+
return render json: { error: e }, status: :bad_gateway
|
44
47
|
end
|
45
48
|
|
46
49
|
# Append redhat-specific headers
|
47
50
|
@cloud_response.headers.each do |key, value|
|
48
51
|
assign_header(response, @cloud_response, key, false) if key.to_s.start_with?('x_rh_')
|
49
52
|
end
|
53
|
+
|
50
54
|
# Append general headers
|
51
55
|
assign_header(response, @cloud_response, :x_resource_count, true)
|
52
56
|
headers[Rack::ETAG] = @cloud_response.headers[:etag]
|
@@ -56,8 +60,8 @@ module InsightsCloud::Api
|
|
56
60
|
# content type
|
57
61
|
send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
|
58
62
|
elsif @cloud_response.headers[:content_type] =~ /zip/
|
59
|
-
#
|
60
|
-
#
|
63
|
+
# If there is no Content-Disposition, but the content type is binary according to Content-Type, send the raw data
|
64
|
+
# with proper content type
|
61
65
|
send_data @cloud_response, type: @cloud_response.headers[:content_type]
|
62
66
|
else
|
63
67
|
render json: @cloud_response, status: @cloud_response.code
|
@@ -17,8 +17,14 @@ module ForemanRhCloud
|
|
17
17
|
logger.debug("Response headers for request url #{final_params[:url]} are: #{response.headers}")
|
18
18
|
|
19
19
|
response
|
20
|
-
rescue RestClient::
|
21
|
-
logger.debug("
|
20
|
+
rescue RestClient::Exceptions::Timeout => ex
|
21
|
+
logger.debug("Timeout exception raised for request url #{final_params[:url]}: #{ex}")
|
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}")
|
22
28
|
raise ex
|
23
29
|
end
|
24
30
|
end
|
@@ -17,8 +17,6 @@ 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
|
22
20
|
end
|
23
21
|
|
24
22
|
def prepare_request_opts(original_request, forward_payload, forward_params, certs)
|
@@ -57,17 +57,39 @@ 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
|
+
|
60
64
|
insights_client_setting = fact_value(host, 'insights_client::obfuscate_hostname_enabled')
|
61
65
|
insights_client_setting = ActiveModel::Type::Boolean.new.cast(insights_client_setting)
|
62
|
-
return insights_client_setting unless insights_client_setting.nil?
|
63
66
|
|
64
|
-
|
67
|
+
# 2. host fact reported by insights_client
|
68
|
+
# 3. if neither of the above, don't obfuscate.
|
69
|
+
insights_client_setting.nil? ? false : insights_client_setting
|
65
70
|
end
|
66
71
|
|
67
72
|
def fqdn(host)
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
if obfuscate_hostname?(host)
|
74
|
+
# If obfuscation is enabled, attempt to retrieve an already obfuscated hostname
|
75
|
+
# from the 'insights_client::obfuscated_hostname' fact.
|
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
|
71
93
|
end
|
72
94
|
|
73
95
|
def obfuscate_fqdn(fqdn)
|
@@ -75,35 +97,65 @@ module ForemanInventoryUpload
|
|
75
97
|
end
|
76
98
|
|
77
99
|
def obfuscate_ips?(host)
|
78
|
-
|
79
|
-
|
80
|
-
return
|
100
|
+
# Returns true if IP obfuscation should be applied for a given host, based on hierarchy:
|
101
|
+
# 1. Global setting for IP obfuscation.
|
102
|
+
return true if Setting[:obfuscate_inventory_ips]
|
81
103
|
|
82
|
-
|
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)
|
109
|
+
|
110
|
+
# 2. The host's IPv4 or IPv6 obfuscation fact value is true
|
111
|
+
# 3. If neither of the above, don't obfuscate.
|
112
|
+
cast_ipv4_setting || cast_ipv6_setting || false
|
83
113
|
end
|
84
114
|
|
85
115
|
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.
|
86
119
|
return obfuscated_ips(host) if obfuscate_ips?(host)
|
87
120
|
|
88
|
-
#
|
121
|
+
# If IP obfuscation is NOT needed, return a special kind of Hash.
|
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.
|
89
127
|
Hash.new { |h, k| k }
|
90
128
|
end
|
91
129
|
|
92
130
|
def obfuscated_ips(host)
|
93
|
-
|
131
|
+
# Example format of `parsed_insights_array`:
|
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
|
94
139
|
|
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.
|
95
142
|
obfuscated_ips = Hash[
|
96
|
-
|
143
|
+
parsed_insights_array.map { |ip_record| [ip_record['original'], ip_record['obfuscated']] }
|
97
144
|
]
|
98
145
|
|
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.
|
99
150
|
obfuscated_ips.default_proc = proc do |hash, key|
|
100
151
|
hash[key] = obfuscate_ip(key, hash)
|
101
152
|
end
|
102
|
-
|
103
153
|
obfuscated_ips
|
104
154
|
end
|
105
155
|
|
106
156
|
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
|
107
159
|
max_obfuscated = ips_dict.values.map { |v| IPAddr.new(v).to_i }.max || IPAddr.new('10.230.230.0').to_i
|
108
160
|
|
109
161
|
IPAddr.new(max_obfuscated + 1, Socket::AF_INET).to_s
|
@@ -24,9 +24,11 @@ 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::
|
27
|
+
'insights_client::obfuscate_ipv4_enabled',
|
28
|
+
'insights_client::obfuscate_ipv6_enabled',
|
29
|
+
'insights_client::obfuscated_ipv4',
|
30
|
+
'insights_client::obfuscated_ipv6',
|
31
|
+
'insights_client::obfuscated_hostname',
|
30
32
|
'insights_id',
|
31
33
|
'conversions::activity',
|
32
34
|
'conversions::packages::0::nevra',
|
@@ -149,7 +149,6 @@ 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)
|
153
152
|
@stream.simple_field(
|
154
153
|
'infrastructure_type',
|
155
154
|
ActiveModel::Type::Boolean.new.cast(fact_value(host, 'virt::is_guest')) ? 'virtual' : 'physical'
|
data/lib/tasks/hybrid_cloud.rake
CHANGED
@@ -1,64 +1,122 @@
|
|
1
1
|
require 'io/console'
|
2
|
+
require 'uri'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def logger
|
5
|
+
@logger ||= Logger.new(STDOUT)
|
6
|
+
end
|
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.
|
7
16
|
task hybridcloud_register: [:environment] do
|
8
17
|
include ::ForemanRhCloud::CertAuth
|
9
18
|
include ::InsightsCloud::CandlepinCache
|
10
19
|
|
11
|
-
|
12
|
-
|
20
|
+
# Helper method to get the registrations URL, with a warning for default usage
|
21
|
+
def registrations_url(custom_url)
|
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
|
13
28
|
end
|
14
29
|
|
15
|
-
|
16
|
-
|
17
|
-
|
30
|
+
# --- Input Collection ---
|
31
|
+
puts "Paste in your organization ID, this can be retrieved with the command: hammer organization list"
|
32
|
+
loop do
|
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
|
18
40
|
end
|
19
41
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
42
|
+
puts "\n" + "-" * 50 + "\n\n"
|
43
|
+
puts 'Paste in your Custom Insights URL. If nothing is entered, the default will be used.'
|
44
|
+
insights_user_input = STDIN.gets.chomp
|
24
45
|
|
25
|
-
|
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?
|
46
|
+
# --- Data Preparation ---
|
29
47
|
|
30
|
-
|
31
|
-
@token = STDIN.noecho(&:gets).chomp
|
32
|
-
logger.error('Token was not entered.') + exit(1) if @token.empty?
|
48
|
+
organization = Organization.find_by(id: @user_org_id)
|
33
49
|
|
34
|
-
|
35
|
-
{
|
36
|
-
|
37
|
-
}
|
50
|
+
if organization.nil?
|
51
|
+
logger.error("Organization with ID '#{@user_org_id}' not found.")
|
52
|
+
exit(1)
|
38
53
|
end
|
39
54
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
}
|
55
|
+
uid = cp_owner_id(organization)
|
56
|
+
if uid.nil?
|
57
|
+
logger.error('Organization provided does not have a manifest imported.')
|
58
|
+
exit(1)
|
45
59
|
end
|
46
60
|
|
47
|
-
|
48
|
-
|
61
|
+
hostname = ForemanRhCloud.foreman_host_name
|
62
|
+
insights_url = registrations_url(insights_user_input)
|
63
|
+
|
64
|
+
puts "\n" + "-" * 50 + "\n\n"
|
65
|
+
puts 'Paste in your Hybrid Cloud API token, output will be hidden.'
|
66
|
+
puts 'This token can be retrieved from the Hybrid Cloud console.'
|
67
|
+
token = STDIN.noecho(&:gets).chomp
|
68
|
+
|
69
|
+
if token.empty?
|
70
|
+
logger.error('Token was not entered.')
|
71
|
+
exit(1)
|
49
72
|
end
|
50
73
|
|
74
|
+
# --- API Request Configuration ---
|
75
|
+
|
76
|
+
headers = {
|
77
|
+
Authorization: "Bearer #{token}",
|
78
|
+
}
|
79
|
+
|
80
|
+
payload = {
|
81
|
+
'uid': uid,
|
82
|
+
"display_name": "#{hostname}+#{organization.label}",
|
83
|
+
}
|
84
|
+
|
85
|
+
# --- Execute Request ---
|
86
|
+
|
51
87
|
begin
|
52
88
|
response = execute_cloud_request(
|
53
|
-
organization:
|
54
|
-
method:
|
55
|
-
url:
|
89
|
+
organization: organization,
|
90
|
+
method: :post,
|
91
|
+
url: insights_url,
|
56
92
|
headers: headers,
|
57
93
|
payload: payload.to_json
|
58
94
|
)
|
59
|
-
logger.debug(response)
|
95
|
+
logger.debug("Cloud request completed: status=#{response.code}, body_preview=#{response.body&.slice(0, 200)}")
|
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)
|
60
113
|
rescue StandardError => ex
|
61
|
-
|
114
|
+
# This is the catch-all for any other unexpected errors
|
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)
|
62
118
|
end
|
119
|
+
|
120
|
+
logger.info("Satellite Organization '#{organization.label}' (ID: #{@user_org_id}) successfully registered.")
|
63
121
|
end
|
64
122
|
end
|
data/package.json
CHANGED
@@ -98,13 +98,25 @@ module InsightsCloud::Api
|
|
98
98
|
assert_equal net_http_resp[:content_type], @response.headers['Content-Type']
|
99
99
|
end
|
100
100
|
|
101
|
+
test "should handle 304 cloud" do
|
102
|
+
net_http_resp = Net::HTTPResponse.new(1.0, 304, "Not Modified")
|
103
|
+
res = RestClient::Response.create(@body, net_http_resp, @http_req)
|
104
|
+
|
105
|
+
::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::NotModified.new(res))
|
106
|
+
|
107
|
+
get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
|
108
|
+
assert_equal 304, @response.status
|
109
|
+
assert_equal 'Cloud request not modified', JSON.parse(@response.body)['message']
|
110
|
+
end
|
111
|
+
|
101
112
|
test "should handle failed authentication to cloud" do
|
102
113
|
net_http_resp = Net::HTTPResponse.new(1.0, 401, "Unauthorized")
|
103
114
|
res = RestClient::Response.create(@body, net_http_resp, @http_req)
|
104
|
-
|
115
|
+
|
116
|
+
::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::Unauthorized.new(res))
|
105
117
|
|
106
118
|
get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
|
107
|
-
assert_equal
|
119
|
+
assert_equal 401, @response.status
|
108
120
|
assert_equal 'Authentication to the Insights Service failed.', JSON.parse(@response.body)['message']
|
109
121
|
end
|
110
122
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'test_plugin_helper'
|
2
|
+
require 'digest'
|
2
3
|
|
3
4
|
class FactHelpersTest < ActiveSupport::TestCase
|
4
5
|
class FactsHelpersTestStub
|
@@ -29,7 +30,7 @@ class FactHelpersTest < ActiveSupport::TestCase
|
|
29
30
|
|
30
31
|
test 'obfuscates ips with insights-client data' do
|
31
32
|
host = mock('host')
|
32
|
-
@instance.expects(:fact_value).with(host, 'insights_client::
|
33
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns(
|
33
34
|
'[{"obfuscated": "10.230.230.1", "original": "224.0.0.1"}, {"obfuscated": "10.230.230.255", "original": "224.0.0.251"}]'
|
34
35
|
)
|
35
36
|
|
@@ -41,11 +42,275 @@ class FactHelpersTest < ActiveSupport::TestCase
|
|
41
42
|
|
42
43
|
test 'obfuscates ips without insights-client data' do
|
43
44
|
host = mock('host')
|
44
|
-
@instance.expects(:fact_value).with(host, 'insights_client::
|
45
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns(nil)
|
45
46
|
|
46
47
|
actual = @instance.obfuscated_ips(host)
|
47
48
|
|
48
49
|
assert_equal '10.230.230.1', actual['224.0.0.1']
|
49
50
|
assert_equal '10.230.230.2', actual['224.0.0.2']
|
50
51
|
end
|
52
|
+
|
53
|
+
describe 'obfuscate_hostname?' do
|
54
|
+
test 'returns true when global setting is enabled' do
|
55
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(true)
|
56
|
+
host = mock('host')
|
57
|
+
|
58
|
+
result = @instance.obfuscate_hostname?(host)
|
59
|
+
|
60
|
+
assert result
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'returns false when global setting is disabled and no host-specific setting' do
|
64
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(false)
|
65
|
+
host = mock('host')
|
66
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_hostname_enabled').returns(nil)
|
67
|
+
|
68
|
+
result = @instance.obfuscate_hostname?(host)
|
69
|
+
|
70
|
+
refute result
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'returns true when host-specific setting is enabled' do
|
74
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(false)
|
75
|
+
host = mock('host')
|
76
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_hostname_enabled').returns('true')
|
77
|
+
|
78
|
+
result = @instance.obfuscate_hostname?(host)
|
79
|
+
|
80
|
+
assert result
|
81
|
+
end
|
82
|
+
|
83
|
+
test 'returns false when host-specific setting is disabled' do
|
84
|
+
Setting.expects(:[]).with(:obfuscate_inventory_hostnames).returns(false)
|
85
|
+
host = mock('host')
|
86
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_hostname_enabled').returns('false')
|
87
|
+
|
88
|
+
result = @instance.obfuscate_hostname?(host)
|
89
|
+
|
90
|
+
refute result
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'fqdn' do
|
95
|
+
test 'returns original fqdn when obfuscation is disabled' do
|
96
|
+
host = mock('host')
|
97
|
+
host.expects(:fqdn).returns('test.example.com')
|
98
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(false)
|
99
|
+
|
100
|
+
result = @instance.fqdn(host)
|
101
|
+
|
102
|
+
assert_equal 'test.example.com', result
|
103
|
+
end
|
104
|
+
|
105
|
+
test 'returns obfuscated hostname from insights_client fact when available' do
|
106
|
+
host = mock('host')
|
107
|
+
host.expects(:fqdn).returns('test.example.com').once
|
108
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(true)
|
109
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_hostname').returns(
|
110
|
+
'[{"original": "test.example.com", "obfuscated": "abc123.example.com"}]'
|
111
|
+
)
|
112
|
+
|
113
|
+
result = @instance.fqdn(host)
|
114
|
+
|
115
|
+
assert_equal 'abc123.example.com', result
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'returns dynamically obfuscated hostname when insights_client fact is not available' do
|
119
|
+
host = mock('host')
|
120
|
+
host.stubs(:fqdn).returns('test.example.com')
|
121
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(true)
|
122
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_hostname').returns(nil)
|
123
|
+
|
124
|
+
result = @instance.fqdn(host)
|
125
|
+
|
126
|
+
expected = "#{Digest::SHA1.hexdigest('test.example.com')}.example.com"
|
127
|
+
assert_equal expected, result
|
128
|
+
end
|
129
|
+
|
130
|
+
test 'returns dynamically obfuscated hostname when insights_client fact does not contain matching host' do
|
131
|
+
host = mock('host')
|
132
|
+
host.expects(:fqdn).returns('test.example.com').twice
|
133
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(true)
|
134
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_hostname').returns(
|
135
|
+
'[{"original": "other.example.com", "obfuscated": "abc123.example.com"}]'
|
136
|
+
)
|
137
|
+
@instance.expects(:obfuscate_fqdn).with('test.example.com').returns('dynamically_obfuscated.example.com')
|
138
|
+
|
139
|
+
result = @instance.fqdn(host)
|
140
|
+
|
141
|
+
assert_equal 'dynamically_obfuscated.example.com', result
|
142
|
+
end
|
143
|
+
|
144
|
+
test 'handles invalid JSON in insights_client fact gracefully' do
|
145
|
+
host = mock('host')
|
146
|
+
host.stubs(:fqdn).returns('test.example.com')
|
147
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(true)
|
148
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_hostname').returns('invalid json')
|
149
|
+
|
150
|
+
result = @instance.fqdn(host)
|
151
|
+
|
152
|
+
expected = "#{Digest::SHA1.hexdigest('test.example.com')}.example.com"
|
153
|
+
assert_equal expected, result
|
154
|
+
end
|
155
|
+
|
156
|
+
test 'handles empty insights_client fact' do
|
157
|
+
host = mock('host')
|
158
|
+
host.stubs(:fqdn).returns('test.example.com')
|
159
|
+
@instance.expects(:obfuscate_hostname?).with(host).returns(true)
|
160
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_hostname').returns('[]')
|
161
|
+
|
162
|
+
result = @instance.fqdn(host)
|
163
|
+
|
164
|
+
expected = "#{Digest::SHA1.hexdigest('test.example.com')}.example.com"
|
165
|
+
assert_equal expected, result
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'obfuscate_ips?' do
|
170
|
+
test 'returns true when global setting is enabled' do
|
171
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(true)
|
172
|
+
host = mock('host')
|
173
|
+
|
174
|
+
result = @instance.obfuscate_ips?(host)
|
175
|
+
|
176
|
+
assert result
|
177
|
+
end
|
178
|
+
|
179
|
+
test 'returns false when global setting is disabled and no host-specific settings' do
|
180
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(false)
|
181
|
+
host = mock('host')
|
182
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns(nil)
|
183
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns(nil)
|
184
|
+
|
185
|
+
result = @instance.obfuscate_ips?(host)
|
186
|
+
|
187
|
+
refute result
|
188
|
+
end
|
189
|
+
|
190
|
+
test 'returns true when host-specific IPv4 setting is enabled' do
|
191
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(false)
|
192
|
+
host = mock('host')
|
193
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns('true')
|
194
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns(nil)
|
195
|
+
|
196
|
+
result = @instance.obfuscate_ips?(host)
|
197
|
+
|
198
|
+
assert result
|
199
|
+
end
|
200
|
+
|
201
|
+
test 'returns true when host-specific IPv6 setting is enabled' do
|
202
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(false)
|
203
|
+
host = mock('host')
|
204
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns(nil)
|
205
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns('true')
|
206
|
+
|
207
|
+
result = @instance.obfuscate_ips?(host)
|
208
|
+
|
209
|
+
assert result
|
210
|
+
end
|
211
|
+
|
212
|
+
test 'returns true when both IPv4 and IPv6 settings are enabled' do
|
213
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(false)
|
214
|
+
host = mock('host')
|
215
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns('true')
|
216
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns('true')
|
217
|
+
|
218
|
+
result = @instance.obfuscate_ips?(host)
|
219
|
+
|
220
|
+
assert result
|
221
|
+
end
|
222
|
+
|
223
|
+
test 'returns false when both IPv4 and IPv6 settings are disabled' do
|
224
|
+
Setting.expects(:[]).with(:obfuscate_inventory_ips).returns(false)
|
225
|
+
host = mock('host')
|
226
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv4_enabled').returns('false')
|
227
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscate_ipv6_enabled').returns('false')
|
228
|
+
|
229
|
+
result = @instance.obfuscate_ips?(host)
|
230
|
+
|
231
|
+
refute result
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe 'obfuscate_ip' do
|
236
|
+
test 'generates first IP when no existing obfuscated IPs' do
|
237
|
+
ips_dict = {}
|
238
|
+
|
239
|
+
result = @instance.obfuscate_ip('192.168.1.1', ips_dict)
|
240
|
+
|
241
|
+
assert_equal '10.230.230.1', result
|
242
|
+
end
|
243
|
+
|
244
|
+
test 'generates next sequential IP when existing obfuscated IPs present' do
|
245
|
+
ips_dict = { '192.168.1.1' => '10.230.230.5', '192.168.1.2' => '10.230.230.10' }
|
246
|
+
|
247
|
+
result = @instance.obfuscate_ip('192.168.1.3', ips_dict)
|
248
|
+
|
249
|
+
assert_equal '10.230.230.11', result
|
250
|
+
end
|
251
|
+
|
252
|
+
test 'handles mixed IP ranges correctly' do
|
253
|
+
ips_dict = { '192.168.1.1' => '10.230.230.255', '192.168.1.2' => '10.230.230.1' }
|
254
|
+
|
255
|
+
result = @instance.obfuscate_ip('192.168.1.3', ips_dict)
|
256
|
+
|
257
|
+
assert_equal '10.230.231.0', result
|
258
|
+
end
|
259
|
+
|
260
|
+
test 'generates valid IP addresses' do
|
261
|
+
ips_dict = {}
|
262
|
+
|
263
|
+
result = @instance.obfuscate_ip('any.ip.address', ips_dict)
|
264
|
+
|
265
|
+
assert_match(/\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/, result)
|
266
|
+
assert_nothing_raised { IPAddr.new(result) }
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe 'obfuscated_ips' do
|
271
|
+
test 'handles invalid JSON in insights_client fact gracefully' do
|
272
|
+
host = mock('host')
|
273
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns('invalid json')
|
274
|
+
|
275
|
+
result = @instance.obfuscated_ips(host)
|
276
|
+
|
277
|
+
assert_equal '10.230.230.1', result['192.168.1.1']
|
278
|
+
end
|
279
|
+
|
280
|
+
test 'handles empty insights_client fact' do
|
281
|
+
host = mock('host')
|
282
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns('[]')
|
283
|
+
|
284
|
+
result = @instance.obfuscated_ips(host)
|
285
|
+
|
286
|
+
assert_equal '10.230.230.1', result['192.168.1.1']
|
287
|
+
end
|
288
|
+
|
289
|
+
test 'preserves existing obfuscated IPs and generates new ones' do
|
290
|
+
host = mock('host')
|
291
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns(
|
292
|
+
'[{"original": "192.168.1.1", "obfuscated": "10.230.230.5"}]'
|
293
|
+
)
|
294
|
+
|
295
|
+
result = @instance.obfuscated_ips(host)
|
296
|
+
|
297
|
+
assert_equal '10.230.230.5', result['192.168.1.1']
|
298
|
+
assert_equal '10.230.230.6', result['192.168.1.2']
|
299
|
+
end
|
300
|
+
|
301
|
+
test 'default_proc generates unique sequential IPs' do
|
302
|
+
host = mock('host')
|
303
|
+
@instance.expects(:fact_value).with(host, 'insights_client::obfuscated_ipv4').returns(nil)
|
304
|
+
|
305
|
+
result = @instance.obfuscated_ips(host)
|
306
|
+
|
307
|
+
ip1 = result['192.168.1.1']
|
308
|
+
ip2 = result['192.168.1.2']
|
309
|
+
ip3 = result['192.168.1.3']
|
310
|
+
|
311
|
+
assert_equal '10.230.230.1', ip1
|
312
|
+
assert_equal '10.230.230.2', ip2
|
313
|
+
assert_equal '10.230.230.3', ip3
|
314
|
+
end
|
315
|
+
end
|
51
316
|
end
|
@@ -56,9 +56,10 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
56
56
|
'dmi::system::product_name',
|
57
57
|
'dmi::chassis::asset_tag',
|
58
58
|
'insights_client::obfuscate_hostname_enabled',
|
59
|
+
'insights_client::obfuscated_hostname',
|
60
|
+
'insights_client::obfuscate_ipv4_enabled',
|
61
|
+
'insights_client::obfuscated_ipv4',
|
59
62
|
'insights_client::hostname',
|
60
|
-
'insights_client::obfuscate_ip_enabled',
|
61
|
-
'insights_client::ips',
|
62
63
|
'insights_id',
|
63
64
|
]
|
64
65
|
end
|
@@ -210,14 +211,38 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
210
211
|
assert_equal 1, generator.hosts_count
|
211
212
|
end
|
212
213
|
|
213
|
-
test '
|
214
|
+
test 'does not obfuscate fqdn when insights_client obfuscate_hostname_enabled fact is missing and obfuscate_inventory_hostnames setting is false' do
|
215
|
+
# Create a host and obfuscated_hostname fact, but do NOT create the obfuscate_hostname_enabled fact
|
216
|
+
obfuscated_hostname_data = [
|
217
|
+
{ 'original' => @host.fqdn, 'obfuscated' => '0dd449d0a027.example.com' },
|
218
|
+
]
|
219
|
+
obfuscated_hostname_value = JSON.generate(obfuscated_hostname_data)
|
220
|
+
FactoryBot.create(:fact_value,
|
221
|
+
fact_name: fact_names['insights_client::obfuscated_hostname'],
|
222
|
+
value: obfuscated_hostname_value,
|
223
|
+
host: @host)
|
224
|
+
# Do NOT create the 'insights_client::obfuscate_hostname_enabled' fact
|
225
|
+
|
226
|
+
batch = Host.where(id: @host.id).in_batches.first
|
227
|
+
generator = create_generator(batch)
|
228
|
+
|
229
|
+
json_str = generator.render
|
230
|
+
actual = JSON.parse(json_str.join("\n"))
|
231
|
+
|
232
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
233
|
+
assert_equal @host.fqdn, actual_host['fqdn'], "FQDN should not be obfuscated when obfuscate_hostname_enabled is missing and setting is false"
|
234
|
+
assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
|
235
|
+
assert_not_equal true, actual_facts['is_hostname_obfuscated']
|
236
|
+
end
|
237
|
+
|
238
|
+
test 'generates obfuscated ip_address fields when insights-client facts are present' do
|
214
239
|
nic = FactoryBot.build(:nic_managed)
|
215
240
|
@host.interfaces << nic
|
216
241
|
|
217
|
-
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::
|
242
|
+
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::obfuscate_ipv4_enabled'], value: 'true', host: @host)
|
218
243
|
FactoryBot.create(
|
219
244
|
:fact_value,
|
220
|
-
fact_name: fact_names['insights_client::
|
245
|
+
fact_name: fact_names['insights_client::obfuscated_ipv4'],
|
221
246
|
value: "[{\"obfuscated\": \"10.230.230.100\", \"original\": \"#{nic.ip}\"}]",
|
222
247
|
host: @host
|
223
248
|
)
|
@@ -240,9 +265,17 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
240
265
|
assert_equal 1, generator.hosts_count
|
241
266
|
end
|
242
267
|
|
243
|
-
test 'obfuscates fqdn when
|
268
|
+
test 'obfuscates fqdn when insights-client facts are present' do
|
269
|
+
obfuscated_hostname_data = [
|
270
|
+
{ 'original' => @host.fqdn, 'obfuscated' => '0dd449d0a027.example.com' },
|
271
|
+
{ 'original' => 'satellite.theforeman.org', 'obfuscated' => 'host2.example.com' },
|
272
|
+
]
|
273
|
+
obfuscated_hostname_value = JSON.generate(obfuscated_hostname_data)
|
274
|
+
FactoryBot.create(:fact_value,
|
275
|
+
fact_name: fact_names['insights_client::obfuscated_hostname'],
|
276
|
+
value: obfuscated_hostname_value,
|
277
|
+
host: @host)
|
244
278
|
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::obfuscate_hostname_enabled'], value: 'true', host: @host)
|
245
|
-
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::hostname'], value: 'obfuscated_name', host: @host)
|
246
279
|
|
247
280
|
batch = Host.where(id: @host.id).in_batches.first
|
248
281
|
generator = create_generator(batch)
|
@@ -252,7 +285,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
252
285
|
|
253
286
|
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
254
287
|
assert_not_nil(actual_host = actual['hosts'].first)
|
255
|
-
assert_equal '
|
288
|
+
assert_equal obfuscated_hostname_data.first['obfuscated'], actual_host['fqdn']
|
256
289
|
assert_equal '1234', actual_host['account']
|
257
290
|
assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
|
258
291
|
assert_equal true, actual_facts['is_hostname_obfuscated']
|
@@ -279,9 +312,35 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
279
312
|
assert_equal 1, generator.hosts_count
|
280
313
|
end
|
281
314
|
|
282
|
-
test '
|
315
|
+
test 'obfuscates host fqdn with insights-client when setting set' do
|
316
|
+
Setting[:obfuscate_inventory_hostnames] = true
|
317
|
+
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::hostname'], value: @host.fqdn, host: @host)
|
318
|
+
|
319
|
+
batch = Host.where(id: @host.id).in_batches.first
|
320
|
+
generator = create_generator(batch)
|
321
|
+
|
322
|
+
json_str = generator.render
|
323
|
+
actual = JSON.parse(json_str.join("\n"))
|
324
|
+
|
325
|
+
obfuscated_fqdn = Digest::SHA1.hexdigest(@host.fqdn) + '.example.com'
|
326
|
+
|
327
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
328
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
329
|
+
assert_equal obfuscated_fqdn, actual_host['fqdn']
|
330
|
+
assert_equal '1234', actual_host['account']
|
331
|
+
assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
|
332
|
+
assert_equal true, actual_facts['is_hostname_obfuscated']
|
333
|
+
assert_equal 1, generator.hosts_count
|
334
|
+
end
|
335
|
+
|
336
|
+
test 'does not obfuscate fqdn when host fact from insights-client has a value of false' do
|
337
|
+
obfuscated_hostname_data = [
|
338
|
+
{ 'original' => @host.fqdn, 'obfuscated' => '0dd449d0a027.example.com' },
|
339
|
+
{ 'original' => 'satellite.theforeman.org', 'obfuscated' => 'host2.example.com' },
|
340
|
+
]
|
341
|
+
obfuscated_hostname_value = JSON.generate(obfuscated_hostname_data)
|
283
342
|
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::obfuscate_hostname_enabled'], value: 'false', host: @host)
|
284
|
-
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::
|
343
|
+
FactoryBot.create(:fact_value, fact_name: fact_names['insights_client::obfuscated_hostname'], value: obfuscated_hostname_value, host: @host)
|
285
344
|
|
286
345
|
batch = Host.where(id: @host.id).in_batches.first
|
287
346
|
generator = create_generator(batch)
|
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: 11.4.
|
4
|
+
version: 11.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Foreman Red Hat Cloud team
|
@@ -697,7 +697,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
697
697
|
- !ruby/object:Gem::Version
|
698
698
|
version: '0'
|
699
699
|
requirements: []
|
700
|
-
rubygems_version: 3.6.
|
700
|
+
rubygems_version: 3.6.9
|
701
701
|
specification_version: 4
|
702
702
|
summary: Summary of ForemanRhCloud.
|
703
703
|
test_files:
|