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 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