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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8db662f6cd6809ba5dd5b183ec76330b4a1d4eb6db931136c8e34dcdf53c796c
4
- data.tar.gz: e410219ca7fcbd0555d157f05123cc7c7618b29531157de42a3e3413d9d96eb4
3
+ metadata.gz: e4c84356ce25f9683795e8adb7ab42d223cef0a4ba84a4a8d9f5836cc6b80986
4
+ data.tar.gz: 5f86cd9c8240aff463e25620a5e0bb47fbc15ab7318647f40918d98a85513ab8
5
5
  SHA512:
6
- metadata.gz: 601501b2ec41be00150bbc9797ad9fe7c93a92aea619ca1781ef3df88224e3f6fb04b2c16e2c2e974832ef67926794108d3c8f2c7654d52056e25a218887cd55
7
- data.tar.gz: 6a7ca4b57eb655c5d4c3a880f0deac4af3f86c6a4b71ddd4ff02b7adc4aa9bf5c0cb2a70731f5472ce763b841a75f755835e0674d489c6b5d51759ee9d1c85f3
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,5 @@
1
+ class InsightsMissingHost < ApplicationRecord
2
+ belongs_to :organization
3
+
4
+ scoped_search on: [:name, :insights_id, :rhsm_id, :ip_address]
5
+ end
@@ -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 + "/api/inventory/v1/hosts"
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"))
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '8.0.46'.freeze
2
+ VERSION = '8.0.47'.freeze
3
3
  end
@@ -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
- InsightsFacet.transaction do
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
- Organization.unscoped.each do |org|
18
- plan_org_sync(org)
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
@@ -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
- @uid = cp_owner_id(organization)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "8.0.46",
3
+ "version": "8.0.47",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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
@@ -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
@@ -2,6 +2,7 @@ require 'test_plugin_helper'
2
2
 
3
3
  class SliceGeneratorTest < ActiveSupport::TestCase
4
4
  include KatelloLocationFix
5
+ include CandlepinIsolation
5
6
 
6
7
  setup do
7
8
  User.current = User.find_by(login: 'secret_admin')
@@ -2,6 +2,7 @@ require 'test_plugin_helper'
2
2
 
3
3
  class TagsGeneratorTest < ActiveSupport::TestCase
4
4
  include KatelloLocationFix
5
+ include CandlepinIsolation
5
6
 
6
7
  setup do
7
8
  User.current = User.find_by(login: 'secret_admin')
@@ -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
  };
@@ -15,3 +15,6 @@ export const selectIpsObfuscationEnabled = state =>
15
15
 
16
16
  export const selectExcludePackages = state =>
17
17
  selectSettings(state).excludePackagesEnabled;
18
+
19
+ export const selectMismatchDelete = state =>
20
+ selectSettings(state).allowAutoInsightsMismatchDelete;
@@ -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.46
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 00:00:00.000000000 Z
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