foreman_rh_cloud 8.0.46 → 8.0.47
Sign up to get free protection for your applications and to get access to all the features.
- 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
|