foreman_rh_cloud 8.0.46 → 8.0.47
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/foreman_inventory_upload/uploads_settings_controller.rb +1 -0
- data/app/models/insights_missing_host.rb +5 -0
- data/db/migrate/20230515140211_add_missing_hosts_table.foreman_rh_cloud.rb +13 -0
- data/lib/foreman_inventory_upload/async/remove_insights_hosts_job.rb +68 -0
- data/lib/foreman_inventory_upload.rb +6 -1
- data/lib/foreman_rh_cloud/engine.rb +2 -1
- data/lib/foreman_rh_cloud/settings.rb +1 -0
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/inventory_sync/async/host_result.rb +5 -0
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +30 -1
- data/lib/inventory_sync/async/inventory_scheduled_sync.rb +13 -2
- data/lib/tasks/hybrid_cloud.rake +6 -5
- data/package.json +1 -1
- data/test/factories/insights_factories.rb +8 -0
- data/test/jobs/inventory_hosts_sync_test.rb +32 -0
- data/test/jobs/inventory_scheduled_sync_test.rb +12 -0
- data/test/jobs/remove_insights_hosts_job_test.rb +90 -0
- data/test/test_plugin_helper.rb +11 -0
- data/test/unit/slice_generator_test.rb +1 -0
- data/test/unit/tags_generator_test.rb +1 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/AdvancedSettingsConstants.js +7 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettingsSelectors.js +3 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/__snapshots__/InventorySettings.test.js.snap +4 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4c84356ce25f9683795e8adb7ab42d223cef0a4ba84a4a8d9f5836cc6b80986
|
|
4
|
+
data.tar.gz: 5f86cd9c8240aff463e25620a5e0bb47fbc15ab7318647f40918d98a85513ab8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a7765f56a4d7e695dd253b17fd87820e8455fbe95a23450e2577125f65f20acc813723a2ff036c81d6b41c4d75d1bcf3b3aea65fb1b4042b916a68a117340a5
|
|
7
|
+
data.tar.gz: d8e8db10a0fc49b9741d38f93e5d59917f85b7ac6fcc8e3007dcb84346ccd15c07bd644a91de1a5ea38942cbb5b27553d5a7c59315e317fe79d1b13b542151bd
|
|
@@ -6,6 +6,7 @@ module ForemanInventoryUpload
|
|
|
6
6
|
hostObfuscationEnabled: Setting[:obfuscate_inventory_hostnames],
|
|
7
7
|
ipsObfuscationEnabled: Setting[:obfuscate_inventory_ips],
|
|
8
8
|
excludePackagesEnabled: Setting[:exclude_installed_packages],
|
|
9
|
+
allowAutoInsightsMismatchDelete: Setting[:allow_auto_insights_mismatch_delete],
|
|
9
10
|
CloudConnectorStatus: ForemanInventoryUpload::UploadsSettingsController.cloud_connector_status,
|
|
10
11
|
lastSyncTask: last_successful_inventory_sync_task,
|
|
11
12
|
}, status: :ok
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddMissingHostsTable < ActiveRecord::Migration[6.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :insights_missing_hosts do |t|
|
|
6
|
+
t.integer :organization_id
|
|
7
|
+
t.string :name
|
|
8
|
+
t.string :insights_id
|
|
9
|
+
t.string :rhsm_id
|
|
10
|
+
t.string :ip_address
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module ForemanInventoryUpload
|
|
2
|
+
module Async
|
|
3
|
+
class RemoveInsightsHostsJob < ::Actions::EntryAction
|
|
4
|
+
include ForemanRhCloud::CertAuth
|
|
5
|
+
|
|
6
|
+
def plan(search_term, organization_id)
|
|
7
|
+
plan_self(search_term: search_term, organization_id: organization_id)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def run
|
|
11
|
+
logger.debug("Attempting to remove hosts by search term: #{search_term}")
|
|
12
|
+
|
|
13
|
+
host_uuids = InsightsMissingHost.search_for(search_term).pluck(:insights_id)
|
|
14
|
+
|
|
15
|
+
page_number = 1
|
|
16
|
+
while (current_page = host_uuids.paginate(page: page_number, per_page: page_size)).present?
|
|
17
|
+
logger.debug("Removing #{(page_number - 1) * page_size} - #{page_number * page_size}/#{current_page.total_entries} hosts: #{current_page.join(',')}")
|
|
18
|
+
response = delete_page(current_page, organization)
|
|
19
|
+
# write the response in case we want to track it later
|
|
20
|
+
output["response_page#{page_number}"] = response.body
|
|
21
|
+
|
|
22
|
+
# remove host records that reported success after deletion
|
|
23
|
+
if response.code >= 200 && response.code < 300
|
|
24
|
+
remove_host_records(current_page)
|
|
25
|
+
else
|
|
26
|
+
error! "Cloud responded with code: #{response.code}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
page_number += 1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def logger
|
|
34
|
+
Foreman::Logging.logger('background')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def search_term
|
|
38
|
+
input[:search_term]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def organization
|
|
42
|
+
@organization ||= Organization.find_by(id: input[:organization_id])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def delete_page(host_uuids, organization)
|
|
46
|
+
execute_cloud_request(
|
|
47
|
+
organization: organization,
|
|
48
|
+
method: :delete,
|
|
49
|
+
url: ForemanInventoryUpload.hosts_by_ids_url(host_uuids),
|
|
50
|
+
headers: {
|
|
51
|
+
content_type: :json,
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
rescue RestClient::ExceptionWithResponse => error_response
|
|
55
|
+
error_response.response
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def remove_host_records(uuids)
|
|
59
|
+
InsightsMissingHost.where(insights_id: uuids).delete_all
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def page_size
|
|
63
|
+
# the_most_conservative_url_size_limit(2083) / uri_size(36) with some spares for the domain name
|
|
64
|
+
40
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -71,7 +71,7 @@ module ForemanInventoryUpload
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def self.inventory_base_url
|
|
74
|
-
ForemanRhCloud.cert_base_url
|
|
74
|
+
"#{ForemanRhCloud.cert_base_url}/api/inventory/v1/hosts"
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def self.inventory_export_url
|
|
@@ -82,4 +82,9 @@ module ForemanInventoryUpload
|
|
|
82
82
|
def self.inventory_self_url
|
|
83
83
|
inventory_base_url + "?hostname_or_id=#{ForemanRhCloud.foreman_host.fqdn}"
|
|
84
84
|
end
|
|
85
|
+
|
|
86
|
+
def self.hosts_by_ids_url(host_ids)
|
|
87
|
+
host_ids_string = host_ids.join(',')
|
|
88
|
+
"#{inventory_base_url}/#{host_ids_string}"
|
|
89
|
+
end
|
|
85
90
|
end
|
|
@@ -127,7 +127,8 @@ module ForemanRhCloud
|
|
|
127
127
|
|
|
128
128
|
extend_page 'hosts/_list' do |context|
|
|
129
129
|
context.with_profile :cloud, _('RH Cloud'), default: true do
|
|
130
|
-
add_pagelet :hosts_table_column_header, key: :insights_recommendations_count, label: _('Recommendations'), sortable: true, width: '12%', class: 'hidden-xs ellipsis', priority: 100
|
|
130
|
+
add_pagelet :hosts_table_column_header, key: :insights_recommendations_count, label: _('Recommendations'), sortable: true, width: '12%', class: 'hidden-xs ellipsis', priority: 100,
|
|
131
|
+
export_data: CsvExporter::ExportDefinition.new(:insights_recommendations_count, callback: ->(host) { host&.insights_hits&.count })
|
|
131
132
|
add_pagelet :hosts_table_column_content, key: :insights_recommendations_count, callback: ->(host) { hits_counts_cell(host) }, class: 'hidden-xs ellipsis text-center', priority: 100
|
|
132
133
|
end
|
|
133
134
|
end
|
|
@@ -2,6 +2,7 @@ Foreman::SettingManager.define(:foreman) do
|
|
|
2
2
|
category(:rh_cloud, N_('RHCloud')) do
|
|
3
3
|
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'))
|
|
4
4
|
setting('allow_auto_insights_sync', type: :boolean, description: N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), default: false, full_name: N_('Synchronize recommendations Automatically'))
|
|
5
|
+
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'))
|
|
5
6
|
setting('obfuscate_inventory_hostnames', type: :boolean, description: N_('Obfuscate host names sent to the Red Hat cloud'), default: false, full_name: N_('Obfuscate host names'))
|
|
6
7
|
setting('obfuscate_inventory_ips', type: :boolean, description: N_('Obfuscate ipv4 addresses sent to the Red Hat cloud'), default: false, full_name: N_('Obfuscate host ipv4 addresses'))
|
|
7
8
|
setting('exclude_installed_packages', type: :boolean, description: N_('Exclude installed packages from being uploaded to the Red Hat cloud'), default: false, full_name: N_("Exclude installed Packages"))
|
|
@@ -12,6 +12,7 @@ module InventorySync
|
|
|
12
12
|
@sub_ids = result["results"].map { |host| host['subscription_manager_id'] }
|
|
13
13
|
@uuid_by_sub_id = Hash[result["results"].map { |host| [host['subscription_manager_id'], host['id']] }]
|
|
14
14
|
@uuid_by_fqdn = Hash[result["results"].map { |host| [host['fqdn']&.downcase, host['id']] }]
|
|
15
|
+
@results = result["results"]
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def status_hashes
|
|
@@ -42,6 +43,10 @@ module InventorySync
|
|
|
42
43
|
@host_uuids ||= Hash[@sub_ids.map { |sub_id| [host_id(sub_id), @uuid_by_sub_id[sub_id]] }].except(nil)
|
|
43
44
|
end
|
|
44
45
|
|
|
46
|
+
def missing_hosts
|
|
47
|
+
@results.select { |host| hosts[host['subscription_manager_id']].nil? }
|
|
48
|
+
end
|
|
49
|
+
|
|
45
50
|
def percentage
|
|
46
51
|
ratio = @per_page * @page * 1.0 / @total * 100
|
|
47
52
|
ratio > 100 ? 100 : ratio.truncate(2)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module InventorySync
|
|
2
2
|
module Async
|
|
3
3
|
class InventoryHostsSync < QueryInventoryJob
|
|
4
|
+
MAX_IP_STRING_SIZE = 254
|
|
5
|
+
|
|
4
6
|
set_callback :iteration, :around, :setup_facet_transaction
|
|
5
7
|
set_callback :step, :around, :create_facets
|
|
8
|
+
set_callback :step, :around, :create_missing_hosts
|
|
6
9
|
|
|
7
10
|
def plan(organizations)
|
|
8
11
|
# by default the tasks will be executed concurrently
|
|
@@ -11,7 +14,7 @@ module InventorySync
|
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
def setup_facet_transaction
|
|
14
|
-
|
|
17
|
+
ActiveRecord::Base.transaction do
|
|
15
18
|
yield
|
|
16
19
|
end
|
|
17
20
|
end
|
|
@@ -23,6 +26,17 @@ module InventorySync
|
|
|
23
26
|
results
|
|
24
27
|
end
|
|
25
28
|
|
|
29
|
+
def create_missing_hosts
|
|
30
|
+
results = yield
|
|
31
|
+
missing_hosts = results.missing_hosts.map { |host| to_missing_host_record(host, results.organization) }
|
|
32
|
+
# remove records that are no longer in the query results
|
|
33
|
+
InsightsMissingHost.
|
|
34
|
+
where.not(insights_id: missing_hosts.map { |host_hash| host_hash[:insights_id] }).
|
|
35
|
+
where(organization_id: results.organization.id).delete_all
|
|
36
|
+
# readd new hosts that appear in the results, but the subscription_id is missing from the DB.
|
|
37
|
+
InsightsMissingHost.upsert_all(missing_hosts) if missing_hosts.present?
|
|
38
|
+
end
|
|
39
|
+
|
|
26
40
|
def rescue_strategy_for_self
|
|
27
41
|
Dynflow::Action::Rescue::Fail
|
|
28
42
|
end
|
|
@@ -42,6 +56,21 @@ module InventorySync
|
|
|
42
56
|
InsightsFacet.upsert_all(all_facets, unique_by: :host_id) unless all_facets.empty?
|
|
43
57
|
end
|
|
44
58
|
|
|
59
|
+
def to_missing_host_record(host_result, organization)
|
|
60
|
+
{
|
|
61
|
+
name: host_result['fqdn'],
|
|
62
|
+
insights_id: host_result['id'],
|
|
63
|
+
rhsm_id: host_result['subscription_manager_id'],
|
|
64
|
+
ip_address: to_ip_address_string(host_result['ip_addresses']),
|
|
65
|
+
organization_id: organization.id,
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def to_ip_address_string(ip_addresses)
|
|
70
|
+
string_size = 0
|
|
71
|
+
ip_addresses.take_while { |address| (string_size += address.length) <= MAX_IP_STRING_SIZE }
|
|
72
|
+
end
|
|
73
|
+
|
|
45
74
|
def plan_self_host_sync
|
|
46
75
|
plan_action InventorySync::Async::InventorySelfHostSync
|
|
47
76
|
end
|
|
@@ -14,8 +14,14 @@ module InventorySync
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
after_delay do
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
# perform a sequence of sync then delete in parallel for all organizations
|
|
18
|
+
concurrence do
|
|
19
|
+
Organization.unscoped.each do |org|
|
|
20
|
+
sequence do
|
|
21
|
+
plan_org_sync(org)
|
|
22
|
+
plan_remove_insights_hosts(org) if Setting[:allow_auto_insights_mismatch_delete]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
19
25
|
end
|
|
20
26
|
end
|
|
21
27
|
end
|
|
@@ -24,6 +30,11 @@ module InventorySync
|
|
|
24
30
|
plan_action InventoryFullSync, org
|
|
25
31
|
end
|
|
26
32
|
|
|
33
|
+
def plan_remove_insights_hosts
|
|
34
|
+
# plan a remove hosts action with search set to empty (all records)
|
|
35
|
+
plan_action(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, '', org.id)
|
|
36
|
+
end
|
|
37
|
+
|
|
27
38
|
def logger
|
|
28
39
|
action_logger
|
|
29
40
|
end
|
data/lib/tasks/hybrid_cloud.rake
CHANGED
|
@@ -22,9 +22,9 @@ namespace :rh_cloud do |args|
|
|
|
22
22
|
exit(1)
|
|
23
23
|
end
|
|
24
24
|
|
|
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
|
-
|
|
27
|
-
@
|
|
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
28
|
logger.error('Organization provided does not have a manifest imported.') + exit(1) if @uid.nil?
|
|
29
29
|
|
|
30
30
|
puts 'Paste your token, output will be hidden.'
|
|
@@ -39,7 +39,8 @@ namespace :rh_cloud do |args|
|
|
|
39
39
|
|
|
40
40
|
def payload
|
|
41
41
|
{
|
|
42
|
-
"uid": @uid
|
|
42
|
+
"uid": @uid,
|
|
43
|
+
"display_name": "#{@hostname}+#{@organization.label}"
|
|
43
44
|
}
|
|
44
45
|
end
|
|
45
46
|
|
|
@@ -49,7 +50,7 @@ namespace :rh_cloud do |args|
|
|
|
49
50
|
|
|
50
51
|
begin
|
|
51
52
|
response = execute_cloud_request(
|
|
52
|
-
organization: organization,
|
|
53
|
+
organization: @organization,
|
|
53
54
|
method: method,
|
|
54
55
|
url: registrations_url,
|
|
55
56
|
headers: headers,
|
data/package.json
CHANGED
|
@@ -41,6 +41,14 @@ FactoryBot.define do
|
|
|
41
41
|
resolution_risk { 1 }
|
|
42
42
|
resolution_type { 'fix' }
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
factory :insights_missing_host do
|
|
46
|
+
organization { association :organization }
|
|
47
|
+
sequence(:name) { |n| "removed.host#{n}.test" }
|
|
48
|
+
insights_id { Foreman.uuid }
|
|
49
|
+
rhsm_id { Foreman.uuid }
|
|
50
|
+
ip_address { "192.168.1.1,192.168.2.1" }
|
|
51
|
+
end
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
FactoryBot.modify do
|
|
@@ -294,4 +294,36 @@ class InventoryHostsSyncTest < ActiveSupport::TestCase
|
|
|
294
294
|
|
|
295
295
|
assert_nil @host2.insights
|
|
296
296
|
end
|
|
297
|
+
|
|
298
|
+
test 'Inventory should create new missing host records' do
|
|
299
|
+
org = FactoryBot.create(:organization)
|
|
300
|
+
|
|
301
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:query_inventory).returns(@inventory)
|
|
302
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:plan_self_host_sync)
|
|
303
|
+
|
|
304
|
+
setup_certs_expectation do
|
|
305
|
+
InventorySync::Async::InventoryHostsSync.any_instance.stubs(:candlepin_id_cert)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryHostsSync, [org])
|
|
309
|
+
|
|
310
|
+
assert_equal 2, InsightsMissingHost.count
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
test 'Inventory should remove old missing host records' do
|
|
314
|
+
org = FactoryBot.create(:organization)
|
|
315
|
+
|
|
316
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:query_inventory).returns(@inventory)
|
|
317
|
+
InventorySync::Async::InventoryHostsSync.any_instance.expects(:plan_self_host_sync)
|
|
318
|
+
|
|
319
|
+
FactoryBot.create(:insights_missing_host, organization: org)
|
|
320
|
+
|
|
321
|
+
setup_certs_expectation do
|
|
322
|
+
InventorySync::Async::InventoryHostsSync.any_instance.stubs(:candlepin_id_cert)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryHostsSync, [org])
|
|
326
|
+
|
|
327
|
+
assert_equal 2, InsightsMissingHost.count
|
|
328
|
+
end
|
|
297
329
|
end
|
|
@@ -6,8 +6,10 @@ class InventoryScheduledSyncTest < ActiveSupport::TestCase
|
|
|
6
6
|
|
|
7
7
|
test 'Schedules an execution if auto upload is enabled' do
|
|
8
8
|
Setting[:allow_auto_inventory_upload] = true
|
|
9
|
+
Setting[:allow_auto_insights_mismatch_delete] = true
|
|
9
10
|
|
|
10
11
|
InventorySync::Async::InventoryScheduledSync.any_instance.expects(:plan_org_sync).times(Organization.unscoped.count)
|
|
12
|
+
InventorySync::Async::InventoryScheduledSync.any_instance.expects(:plan_remove_insights_hosts).times(Organization.unscoped.count)
|
|
11
13
|
|
|
12
14
|
ForemanTasks.sync_task(InventorySync::Async::InventoryScheduledSync)
|
|
13
15
|
end
|
|
@@ -19,4 +21,14 @@ class InventoryScheduledSyncTest < ActiveSupport::TestCase
|
|
|
19
21
|
|
|
20
22
|
ForemanTasks.sync_task(InventorySync::Async::InventoryScheduledSync)
|
|
21
23
|
end
|
|
24
|
+
|
|
25
|
+
test 'Skips mismatch deletion if the setting is disabled' do
|
|
26
|
+
Setting[:allow_auto_inventory_upload] = true
|
|
27
|
+
Setting[:allow_auto_insights_mismatch_delete] = false
|
|
28
|
+
|
|
29
|
+
InventorySync::Async::InventoryScheduledSync.any_instance.expects(:plan_org_sync).times(Organization.unscoped.count)
|
|
30
|
+
InventorySync::Async::InventoryScheduledSync.any_instance.expects(:plan_remove_insights_hosts).never
|
|
31
|
+
|
|
32
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryScheduledSync)
|
|
33
|
+
end
|
|
22
34
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class RemoveInsightsHostJobTest < ActiveSupport::TestCase
|
|
5
|
+
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
|
6
|
+
|
|
7
|
+
setup do
|
|
8
|
+
User.current = User.find_by(login: 'secret_admin')
|
|
9
|
+
|
|
10
|
+
Organization.any_instance.stubs(:manifest_expired?).returns(false)
|
|
11
|
+
@org = FactoryBot.create(:organization)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'Deletes host records on cloud success' do
|
|
15
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.expects(:execute_cloud_request).returns(
|
|
16
|
+
mock_response
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
FactoryBot.create(:insights_missing_host, organization: @org)
|
|
20
|
+
|
|
21
|
+
task = ForemanTasks.sync_task(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, '', @org.id)
|
|
22
|
+
|
|
23
|
+
assert_equal 0, InsightsMissingHost.count
|
|
24
|
+
assert_equal 'success', task.result
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test 'Does not delete hosts on cloud failure' do
|
|
28
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.expects(:execute_cloud_request).raises(
|
|
29
|
+
RestClient::Exceptions::EXCEPTIONS_MAP.fetch(500).new(mock_response(code: 500), 500)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
FactoryBot.create(:insights_missing_host, organization: @org)
|
|
33
|
+
|
|
34
|
+
begin
|
|
35
|
+
ForemanTasks.sync_task(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, '', @org.id)
|
|
36
|
+
rescue ForemanTasks::TaskError => ex
|
|
37
|
+
task = ex.task
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
assert_equal 1, InsightsMissingHost.count
|
|
41
|
+
assert_equal 'error', task.result
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
test 'Paginates the hosts list' do
|
|
45
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.stubs(:page_size).returns(1)
|
|
46
|
+
|
|
47
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.expects(:execute_cloud_request).returns(
|
|
48
|
+
mock_response(body: 'response2')
|
|
49
|
+
)
|
|
50
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.expects(:execute_cloud_request).returns(
|
|
51
|
+
mock_response(body: 'response1')
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
FactoryBot.create(:insights_missing_host, organization: @org)
|
|
55
|
+
FactoryBot.create(:insights_missing_host, organization: @org)
|
|
56
|
+
|
|
57
|
+
task = ForemanTasks.sync_task(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, '', @org.id)
|
|
58
|
+
|
|
59
|
+
assert_equal 0, InsightsMissingHost.count
|
|
60
|
+
assert_equal 'success', task.result
|
|
61
|
+
assert_equal 'response1', task.output[:response_page1]
|
|
62
|
+
assert_equal 'response2', task.output[:response_page2]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
test 'Uses scoped_search to select hosts' do
|
|
66
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.stubs(:page_size).returns(1)
|
|
67
|
+
|
|
68
|
+
# Since the request is paginated per 1 host, I would expect only one call to execute_cloud_request
|
|
69
|
+
ForemanInventoryUpload::Async::RemoveInsightsHostsJob.any_instance.expects(:execute_cloud_request).returns(
|
|
70
|
+
mock_response(body: 'response1')
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
FactoryBot.create(:insights_missing_host, name: 'test a', organization: @org)
|
|
74
|
+
FactoryBot.create(:insights_missing_host, name: 'test b', organization: @org)
|
|
75
|
+
|
|
76
|
+
task = ForemanTasks.sync_task(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, 'name ~ b', @org.id)
|
|
77
|
+
|
|
78
|
+
assert_equal 1, InsightsMissingHost.count
|
|
79
|
+
assert_equal 'test a', InsightsMissingHost.first.name
|
|
80
|
+
assert_equal 'success', task.result
|
|
81
|
+
assert_equal 'response1', task.output[:response_page1]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def mock_response(code: 200, body: '')
|
|
85
|
+
response = mock('response')
|
|
86
|
+
response.stubs(:code).returns(code)
|
|
87
|
+
response.stubs(:body).returns(body)
|
|
88
|
+
response
|
|
89
|
+
end
|
|
90
|
+
end
|
data/test/test_plugin_helper.rb
CHANGED
|
@@ -10,6 +10,7 @@ FactoryBot.reload
|
|
|
10
10
|
|
|
11
11
|
begin
|
|
12
12
|
require 'pry-rescue/minitest'
|
|
13
|
+
require 'pry-byebug'
|
|
13
14
|
rescue LoadError
|
|
14
15
|
# if the extension is not loaded - please continue, no harm done.
|
|
15
16
|
end
|
|
@@ -106,3 +107,13 @@ module MockForemanHostname
|
|
|
106
107
|
end
|
|
107
108
|
end
|
|
108
109
|
end
|
|
110
|
+
|
|
111
|
+
module CandlepinIsolation
|
|
112
|
+
extend ActiveSupport::Concern
|
|
113
|
+
|
|
114
|
+
included do
|
|
115
|
+
setup do
|
|
116
|
+
Katello::Host::SubscriptionFacet.any_instance.stubs(:backend_update_needed?).returns(false)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -25,4 +25,11 @@ export const settingsDict = {
|
|
|
25
25
|
'Exclude installed packages from being uploaded to the Red Hat cloud'
|
|
26
26
|
),
|
|
27
27
|
},
|
|
28
|
+
allowAutoInsightsMismatchDelete: {
|
|
29
|
+
name: 'allow_auto_insights_mismatch_delete',
|
|
30
|
+
label: __('Automatic mismatch deletion'),
|
|
31
|
+
tooltip: __(
|
|
32
|
+
'Enable automatic deletion of mismatched host records from the Red Hat cloud'
|
|
33
|
+
),
|
|
34
|
+
},
|
|
28
35
|
};
|
|
@@ -23,5 +23,9 @@ exports[`InventorySettings rendering render without Props 1`] = `
|
|
|
23
23
|
key="excludePackagesEnabled"
|
|
24
24
|
setting="excludePackagesEnabled"
|
|
25
25
|
/>
|
|
26
|
+
<AdvancedSetting
|
|
27
|
+
key="allowAutoInsightsMismatchDelete"
|
|
28
|
+
setting="allowAutoInsightsMismatchDelete"
|
|
29
|
+
/>
|
|
26
30
|
</div>
|
|
27
31
|
`;
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_rh_cloud
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.0.
|
|
4
|
+
version: 8.0.47
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Foreman Red Hat Cloud team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-06-
|
|
11
|
+
date: 2023-06-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: katello
|
|
@@ -141,6 +141,7 @@ files:
|
|
|
141
141
|
- app/models/insights_client_report_status.rb
|
|
142
142
|
- app/models/insights_facet.rb
|
|
143
143
|
- app/models/insights_hit.rb
|
|
144
|
+
- app/models/insights_missing_host.rb
|
|
144
145
|
- app/models/insights_resolution.rb
|
|
145
146
|
- app/models/insights_rule.rb
|
|
146
147
|
- app/models/inventory_sync/inventory_status.rb
|
|
@@ -183,6 +184,7 @@ files:
|
|
|
183
184
|
- db/migrate/20211027000001_create_task_output.foreman_rh_cloud.rb
|
|
184
185
|
- db/migrate/20220321000001_add_unique_to_insights_rules.foreman_rh_cloud.rb
|
|
185
186
|
- db/migrate/20221102110254_fix_rh_cloud_settings_category_to_dsl.rb
|
|
187
|
+
- db/migrate/20230515140211_add_missing_hosts_table.foreman_rh_cloud.rb
|
|
186
188
|
- db/seeds.d/179_ui_notifications.rb
|
|
187
189
|
- db/seeds.d/50_job_templates.rb
|
|
188
190
|
- lib/foreman_inventory_upload.rb
|
|
@@ -192,6 +194,7 @@ files:
|
|
|
192
194
|
- lib/foreman_inventory_upload/async/generate_report_job.rb
|
|
193
195
|
- lib/foreman_inventory_upload/async/progress_output.rb
|
|
194
196
|
- lib/foreman_inventory_upload/async/queue_for_upload_job.rb
|
|
197
|
+
- lib/foreman_inventory_upload/async/remove_insights_hosts_job.rb
|
|
195
198
|
- lib/foreman_inventory_upload/async/shell_process.rb
|
|
196
199
|
- lib/foreman_inventory_upload/async/upload_report_job.rb
|
|
197
200
|
- lib/foreman_inventory_upload/generators/archived_report.rb
|
|
@@ -256,6 +259,7 @@ files:
|
|
|
256
259
|
- test/jobs/inventory_hosts_sync_test.rb
|
|
257
260
|
- test/jobs/inventory_scheduled_sync_test.rb
|
|
258
261
|
- test/jobs/inventory_self_host_sync_test.rb
|
|
262
|
+
- test/jobs/remove_insights_hosts_job_test.rb
|
|
259
263
|
- test/jobs/upload_report_job_test.rb
|
|
260
264
|
- test/models/insights_client_report_status_test.rb
|
|
261
265
|
- test/test_plugin_helper.rb
|
|
@@ -692,6 +696,7 @@ test_files:
|
|
|
692
696
|
- test/jobs/inventory_hosts_sync_test.rb
|
|
693
697
|
- test/jobs/inventory_scheduled_sync_test.rb
|
|
694
698
|
- test/jobs/inventory_self_host_sync_test.rb
|
|
699
|
+
- test/jobs/remove_insights_hosts_job_test.rb
|
|
695
700
|
- test/jobs/upload_report_job_test.rb
|
|
696
701
|
- test/models/insights_client_report_status_test.rb
|
|
697
702
|
- test/test_plugin_helper.rb
|