foreman_rh_cloud 5.0.34 → 5.0.37

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/rh_cloud/cloud_request_controller.rb +1 -1
  3. data/app/controllers/foreman_inventory_upload/uploads_settings_controller.rb +0 -1
  4. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +7 -1
  5. data/app/controllers/insights_cloud/hits_controller.rb +0 -1
  6. data/app/controllers/insights_cloud/settings_controller.rb +0 -8
  7. data/app/controllers/insights_cloud/tasks_controller.rb +1 -1
  8. data/app/models/insights_facet.rb +1 -0
  9. data/app/models/insights_hit.rb +1 -0
  10. data/app/models/insights_rule.rb +2 -0
  11. data/app/models/setting/rh_cloud.rb +1 -2
  12. data/app/services/foreman_rh_cloud/cert_auth.rb +22 -0
  13. data/app/services/foreman_rh_cloud/cloud_connector.rb +10 -1
  14. data/app/services/foreman_rh_cloud/cloud_ping_service.rb +0 -27
  15. data/app/services/foreman_rh_cloud/hit_remediations_retriever.rb +4 -0
  16. data/app/services/foreman_rh_cloud/remediations_retriever.rb +7 -3
  17. data/app/services/foreman_rh_cloud/template_renderer_helper.rb +4 -3
  18. data/app/services/foreman_rh_cloud/url_remediations_retriever.rb +6 -1
  19. data/app/views/job_templates/cloud_connector.erb +6 -0
  20. data/app/views/job_templates/rh_cloud_download_playbook.erb +5 -1
  21. data/config/routes.rb +0 -1
  22. data/db/migrate/20220321000001_add_unique_to_insights_rules.foreman_rh_cloud.rb +13 -0
  23. data/lib/foreman_inventory_upload.rb +1 -1
  24. data/lib/foreman_rh_cloud/engine.rb +14 -11
  25. data/lib/foreman_rh_cloud/version.rb +1 -1
  26. data/lib/foreman_rh_cloud.rb +0 -5
  27. data/lib/insights_cloud/async/connector_playbook_execution_reporter_task.rb +7 -1
  28. data/lib/insights_cloud/async/insights_full_sync.rb +40 -24
  29. data/lib/insights_cloud/async/insights_resolutions_sync.rb +10 -13
  30. data/lib/insights_cloud/async/insights_rules_sync.rb +27 -19
  31. data/lib/insights_cloud/async/insights_scheduled_sync.rb +5 -1
  32. data/lib/insights_cloud.rb +4 -8
  33. data/lib/inventory_sync/async/host_result.rb +3 -2
  34. data/lib/inventory_sync/async/inventory_full_sync.rb +3 -3
  35. data/lib/inventory_sync/async/inventory_hosts_sync.rb +11 -10
  36. data/lib/inventory_sync/async/inventory_self_host_sync.rb +5 -6
  37. data/lib/inventory_sync/async/query_inventory_job.rb +40 -12
  38. data/lib/tasks/insights.rake +1 -1
  39. data/package.json +1 -1
  40. data/test/controllers/insights_cloud/api/cloud_request_controller_test.rb +0 -1
  41. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +16 -0
  42. data/test/controllers/inventory_upload/cloud_status_controller_test.rb +0 -6
  43. data/test/jobs/insights_full_sync_test.rb +9 -5
  44. data/test/jobs/insights_resolutions_sync_test.rb +7 -1
  45. data/test/jobs/insights_rules_sync_test.rb +8 -4
  46. data/test/jobs/inventory_full_sync_test.rb +16 -5
  47. data/test/jobs/inventory_hosts_sync_test.rb +18 -4
  48. data/test/jobs/inventory_self_host_sync_test.rb +6 -1
  49. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +12 -8
  50. data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +1 -14
  51. data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +5 -1
  52. data/test/unit/services/foreman_rh_cloud/url_remediations_retriever_test.rb +3 -1
  53. data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettingsSelectors.js +0 -2
  54. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +1 -10
  55. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +3 -12
  56. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButton.test.js +1 -1
  57. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +0 -4
  58. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/index.js +0 -2
  59. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
  60. data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +16 -0
  61. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTableSelectors.test.js +0 -2
  62. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableSelectors.test.js.snap +0 -2
  63. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/fixtures.js +0 -1
  64. data/webpack/InsightsCloudSync/InsightsCloudSync.js +1 -17
  65. data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +0 -7
  66. data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +0 -4
  67. data/webpack/InsightsCloudSync/InsightsCloudSyncHelpers.js +0 -7
  68. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +0 -9
  69. data/webpack/InsightsCloudSync/index.js +1 -5
  70. metadata +11 -17
  71. data/app/services/foreman_rh_cloud/cloud_auth.rb +0 -44
  72. data/config/package-lock.json +0 -41822
  73. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +0 -5
  74. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +0 -63
  75. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/modal.scss +0 -20
  76. data/webpack/InsightsCloudSync/Components/NoTokenEmptyState.js +0 -79
  77. data/webpack/InsightsCloudSync/Components/__tests__/NoTokenEmptyState.test.js +0 -19
  78. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +0 -225
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0389d4bf9e9af791b23a3ea7b271feca1385e2fcf4fc6acc7d954283477c8706'
4
- data.tar.gz: 839cc45d7b92a308841f995152ae4a68503acd69feb95cd95b19772f99cec6c9
3
+ metadata.gz: 8b1fcbb6ac1367f8d83a29a6723c9244314b70cd3d8fb675747cdf44ae312a27
4
+ data.tar.gz: c9adec3a0002212f49e8ab7a30e793431809076e9b204a43725001b0a9e391ee
5
5
  SHA512:
6
- metadata.gz: 7b37d242c63e0260a76d06a6096ac569423237bf62f6e8685f79d6cf7b3e85246cfa92f35f0907a18b10539deb09f991189ea5914fa519236786aa2456e8aed6
7
- data.tar.gz: e2baeab2eceeae447276db3ce9c8fa6c7236ff082eab418b835afea4c97ea9172a86eabeeb8ba430012f9662c26bd5a95cc86cc5f45e67a8f6ee4bb2d3a76ac8
6
+ metadata.gz: db98fee746e070be33b584993e56479290df9b462ab9277a66f43c3b5c0af37a9ba3a765f66c4d3fc03f114d300b4ce206db3a8228e0417544c9a092f0e25e23
7
+ data.tar.gz: '09dd3108525df34ef72654cf8f9030af5fc2a6996b806d78b026e56d493b3d49cb5794852733b63dd500102878049e6e4e9f96d16428aa52f55ad8c1c727a610'
@@ -40,7 +40,6 @@ module Api::V2::RhCloud
40
40
  end
41
41
 
42
42
  def handle_run_playbook_request
43
- logger.error("API token is not set, unable to fetch data from the cloud") && return if Setting[:rh_cloud_token].empty?
44
43
  logger.error("Playbook URL is not valid: #{content}") && return unless valid_url?(content)
45
44
  logger.error("Reporting URL is not valid: #{metadata['return_url']}") && return unless valid_url?(metadata['return_url'])
46
45
 
@@ -60,6 +59,7 @@ module Api::V2::RhCloud
60
59
  host_ids,
61
60
  {
62
61
  playbook_url: content,
62
+ organization_id: org_id,
63
63
  report_url: metadata['return_url'],
64
64
  report_interval: metadata['response_interval'].to_i,
65
65
  correlation_id: metadata['correlation_id'],
@@ -7,7 +7,6 @@ module ForemanInventoryUpload
7
7
  ipsObfuscationEnabled: Setting[:obfuscate_inventory_ips],
8
8
  excludePackagesEnabled: Setting[:exclude_installed_packages],
9
9
  CloudConnectorStatus: ForemanInventoryUpload::UploadsSettingsController.cloud_connector_status,
10
- cloudToken: !Setting[:rh_cloud_token].empty?,
11
10
  lastSyncTask: last_successful_inventory_sync_task,
12
11
  }, status: :ok
13
12
  end
@@ -49,7 +49,13 @@ module InsightsCloud::Api
49
49
  end
50
50
 
51
51
  def branch_info
52
- render :json => ForemanRhCloud::BranchInfo.new.generate(@uuid, @host, @branch_id, request.host).to_json
52
+ payload = nil
53
+
54
+ User.as_anonymous_admin do
55
+ payload = ForemanRhCloud::BranchInfo.new.generate(@uuid, @host, @branch_id, request.host).to_json
56
+ end
57
+
58
+ render :json => payload
53
59
  end
54
60
 
55
61
  def assign_header(res, cloud_res, header, transform)
@@ -6,7 +6,6 @@ module InsightsCloud
6
6
  hits = resource_base_search_and_page.preload(:host, :rule)
7
7
 
8
8
  render json: {
9
- hasToken: !Setting[:rh_cloud_token].empty?,
10
9
  hits: hits.map { |hit| hit.attributes.merge(hostname: hit.host&.name, has_playbook: hit.has_playbook?, host_uuid: hit.host_uuid) },
11
10
  itemCount: hits.count,
12
11
  }, status: :ok
@@ -9,14 +9,6 @@ module InsightsCloud
9
9
  render_setting(:insightsSyncEnabled, :allow_auto_insights_sync)
10
10
  end
11
11
 
12
- def save_token_and_sync
13
- token = Setting::RhCloud.find_by_name("rh_cloud_token")
14
- token.value = params.require(:value)
15
- token.save!
16
- ForemanTasks.sync_task(InsightsCloud::Async::InsightsFullSync)
17
- redirect_to(:controller => "hits", :action => 'index')
18
- end
19
-
20
12
  private
21
13
 
22
14
  def render_setting(node_name, setting)
@@ -1,7 +1,7 @@
1
1
  module InsightsCloud
2
2
  class TasksController < ::ApplicationController
3
3
  def create
4
- task = ForemanTasks.async_task(InsightsCloud::Async::InsightsFullSync)
4
+ task = ForemanTasks.async_task(InsightsCloud::Async::InsightsFullSync, Organization.authorized)
5
5
 
6
6
  render json: {
7
7
  task: task,
@@ -4,4 +4,5 @@ class InsightsFacet < HostFacets::Base
4
4
  primary_key: :host_id,
5
5
  class_name: 'InsightsHit',
6
6
  dependent: :destroy
7
+ scope :for_organizations, ->(organization_ids) { joins(:host).where(hosts: { organization_id: organization_ids}) }
7
8
  end
@@ -8,6 +8,7 @@ class InsightsHit < ApplicationRecord
8
8
  has_one :rule, class_name: 'InsightsRule', foreign_key: 'rule_id', primary_key: 'rule_id'
9
9
 
10
10
  scope :with_playbook, -> { joins(:rule) }
11
+ scope :for_organizations, ->(organization_ids) { joins(:host).where(hosts: { organization_id: organization_ids}) }
11
12
 
12
13
  scoped_search on: :title, complete_value: true
13
14
  scoped_search on: :total_risk, complete_value: true
@@ -1,3 +1,5 @@
1
1
  class InsightsRule < ApplicationRecord
2
2
  has_many :resolutions, class_name: 'InsightsResolution', dependent: :destroy, foreign_key: 'rule_id', primary_key: 'rule_id', inverse_of: :rule
3
+
4
+ has_many :hits, class_name: 'InsightsHit', foreign_key: 'rule_id', primary_key: 'rule_id', inverse_of: :rule
3
5
  end
@@ -1,5 +1,5 @@
1
1
  class Setting::RhCloud < Setting
2
- ::Setting::BLANK_ATTRS.concat %w{rh_cloud_token rhc_instance_id}
2
+ ::Setting::BLANK_ATTRS.concat %w{rhc_instance_id}
3
3
 
4
4
  def self.load_defaults
5
5
  return false unless table_exists?
@@ -17,7 +17,6 @@ class Setting::RhCloud < Setting
17
17
  set('allow_auto_insights_sync', N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), false, N_('Synchronize recommendations Automatically')),
18
18
  set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to the Red Hat cloud'), false, N_('Obfuscate host names')),
19
19
  set('obfuscate_inventory_ips', N_('Obfuscate ipv4 addresses sent to the Red Hat cloud'), false, N_('Obfuscate host ipv4 addresses')),
20
- set('rh_cloud_token', N_('Authentication token to Red Hat cloud services. Used to authenticate requests to cloud APIs'), nil, N_('Red Hat Cloud token'), nil, encrypted: true),
21
20
  set('exclude_installed_packages', N_('Exclude installed packages from being uploaded to the Red Hat cloud'), false, N_("Exclude installed Packages")),
22
21
  set('include_parameter_tags', N_('Should import include parameter tags from Foreman?'), false, N_('Include parameters in insights-client reports')),
23
22
  set('rhc_instance_id', N_('RHC daemon id'), nil, N_('ID of the RHC(Yggdrasil) daemon')),
@@ -0,0 +1,22 @@
1
+ module ForemanRhCloud
2
+ module CertAuth
3
+ extend ActiveSupport::Concern
4
+
5
+ include CloudRequest
6
+ include InsightsCloud::CandlepinCache
7
+
8
+ def cert_auth_available?(organization)
9
+ !!candlepin_id_cert(organization)
10
+ end
11
+
12
+ def execute_cloud_request(params)
13
+ certs = candlepin_id_cert(params.delete(:organization))
14
+ final_params = {
15
+ ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
16
+ ssl_client_key: OpenSSL::PKey::RSA.new(certs[:key]),
17
+ }.deep_merge(params)
18
+
19
+ super(final_params)
20
+ end
21
+ end
22
+ end
@@ -12,11 +12,20 @@ module ForemanRhCloud
12
12
  target_host = foreman_host
13
13
  composer = nil
14
14
 
15
+ input = {
16
+ :satellite_cloud_connector_user => service_user.login,
17
+ :satellite_cloud_connector_password => token_value,
18
+ }
19
+
20
+ if (http_proxy = ForemanRhCloud.proxy_setting(logger: Foreman::Logging.logger('app')))
21
+ input[:satellite_cloud_connector_http_proxy] = http_proxy
22
+ end
23
+
15
24
  Taxonomy.as_taxonomy(target_host.organization, target_host.location) do
16
25
  composer = ::JobInvocationComposer.for_feature(
17
26
  CLOUD_CONNECTOR_FEATURE,
18
27
  [target_host.id],
19
- {:satellite_cloud_connector_user => service_user.login, :satellite_cloud_connector_password => token_value}
28
+ input
20
29
  )
21
30
  composer.trigger!
22
31
  end
@@ -2,28 +2,6 @@ require 'rest-client'
2
2
 
3
3
  module ForemanRhCloud
4
4
  class CloudPingService
5
- class TokenPing
6
- include ForemanRhCloud::CloudAuth
7
-
8
- attr_accessor :logger
9
-
10
- def initialize(logger)
11
- @logger = logger
12
- end
13
-
14
- def ping
15
- execute_cloud_request(
16
- method: :get,
17
- url: ForemanRhCloud.base_url + "/api/inventory/v1/hosts?per_page=1",
18
- headers: {
19
- content_type: :json,
20
- }
21
- )
22
- rescue StandardError => ex
23
- ex
24
- end
25
- end
26
-
27
5
  class CertPing
28
6
  include ForemanRhCloud::CloudRequest
29
7
  include InsightsCloud::CandlepinCache
@@ -62,12 +40,7 @@ module ForemanRhCloud
62
40
  end
63
41
 
64
42
  def ping
65
- token_response = TokenPing.new(@logger).ping
66
43
  {
67
- token_auth: {
68
- success: token_response.is_a?(RestClient::Response),
69
- error: (token_response.is_a?(Exception) ? token_response.inspect : nil),
70
- },
71
44
  cert_auth: Hash[
72
45
  @organizations.map do |org|
73
46
  cert_response = CertPing.new(org, @logger).ping
@@ -63,5 +63,9 @@ module ForemanRhCloud
63
63
  def method
64
64
  :post
65
65
  end
66
+
67
+ def organization
68
+ InsightsHit.find(@hit_remediation_pairs.first['hit_id']).host.organization
69
+ end
66
70
  end
67
71
  end
@@ -1,6 +1,6 @@
1
1
  module ForemanRhCloud
2
2
  class RemediationsRetriever
3
- include CloudAuth
3
+ include CertAuth
4
4
 
5
5
  attr_reader :logger
6
6
 
@@ -9,8 +9,8 @@ module ForemanRhCloud
9
9
  end
10
10
 
11
11
  def create_playbook
12
- unless cloud_auth_available?
13
- logger.debug('Cloud authentication is not available, cannot continue')
12
+ unless cert_auth_available?(organization)
13
+ logger.debug('Manifest is not available, cannot continue')
14
14
  return
15
15
  end
16
16
 
@@ -25,6 +25,7 @@ module ForemanRhCloud
25
25
 
26
26
  def query_playbook
27
27
  execute_cloud_request(
28
+ organization: organization,
28
29
  method: method,
29
30
  url: playbook_url,
30
31
  headers: headers,
@@ -47,5 +48,8 @@ module ForemanRhCloud
47
48
  def method
48
49
  :get
49
50
  end
51
+
52
+ def organization
53
+ end
50
54
  end
51
55
  end
@@ -20,11 +20,12 @@ module ForemanRhCloud
20
20
  end
21
21
 
22
22
  apipie :method, 'Returns a Red Hat remediation playbook compiled on console.redhat.com' do
23
- required :remediation_path, String, desc: ''
23
+ required :playbook_url, String, desc: 'URL of the playbook on console.redhat.com'
24
+ required :organization_id, Integer, desc: 'Id of the organization that owns the playbook'
24
25
  returns String, desc: 'Playbook downloaded from the cloud'
25
26
  end
26
- def download_rh_playbook(playbook_url)
27
- retriever = ForemanRhCloud::UrlRemediationsRetriever.new(url: playbook_url, logger: template_logger)
27
+ def download_rh_playbook(playbook_url, organization_id)
28
+ retriever = ForemanRhCloud::UrlRemediationsRetriever.new(url: playbook_url, organization_id: organization_id, logger: template_logger)
28
29
 
29
30
  cached("rh_playbook_#{playbook_url}") do
30
31
  retriever.create_playbook
@@ -2,12 +2,13 @@ module ForemanRhCloud
2
2
  class UrlRemediationsRetriever < RemediationsRetriever
3
3
  attr_reader :url, :payload, :headers
4
4
 
5
- def initialize(url:, payload: '', headers: {}, logger: Logger.new(IO::NULL))
5
+ def initialize(url:, organization_id:, payload: '', headers: {}, logger: Logger.new(IO::NULL))
6
6
  super(logger: logger)
7
7
 
8
8
  @url = url
9
9
  @payload = payload
10
10
  @headers = headers
11
+ @organization_id = organization_id
11
12
  end
12
13
 
13
14
  private
@@ -33,5 +34,9 @@ module ForemanRhCloud
33
34
  def method
34
35
  :get
35
36
  end
37
+
38
+ def organization
39
+ Organization.find(@organization_id)
40
+ end
36
41
  end
37
42
  end
@@ -14,6 +14,12 @@ template_inputs:
14
14
  advanced: false
15
15
  value_type: plain
16
16
  hidden_value: true
17
+ - name: satellite_cloud_connector_http_proxy
18
+ required: false
19
+ input_type: user
20
+ advanced: true
21
+ value_type: plain
22
+ hidden_value: false
17
23
  model: JobTemplate
18
24
  job_category: Maintenance Operations
19
25
  description_format: "%{template_name}"
@@ -9,6 +9,10 @@ template_inputs:
9
9
  description: URL of the playbook to run
10
10
  input_type: user
11
11
  required: true
12
+ - name: organization_id
13
+ description: Id of the organization that owns the playbook
14
+ input_type: user
15
+ required: true
12
16
  - name: report_url
13
17
  description: URL for calling the report callback
14
18
  input_type: user
@@ -23,4 +27,4 @@ template_inputs:
23
27
  required: true
24
28
  provider_type: Ansible
25
29
  %>
26
- <%= download_rh_playbook(input('playbook_url')) %>
30
+ <%= download_rh_playbook(input('playbook_url'), input('organization_id')) %>
data/config/routes.rb CHANGED
@@ -25,7 +25,6 @@ Rails.application.routes.draw do
25
25
  end
26
26
  end
27
27
  match 'hits/:host_id', to: 'hits#show', via: :get
28
- post 'save_token_and_sync', to: 'settings#save_token_and_sync'
29
28
  end
30
29
 
31
30
  namespace :foreman_rh_cloud do
@@ -0,0 +1,13 @@
1
+ class AddUniqueToInsightsRules < ActiveRecord::Migration[5.2]
2
+ def change
3
+ begin
4
+ # remove old index
5
+ remove_index :insights_rules, [:rule_id]
6
+ rescue ArgumentError
7
+ # noop, if the index is not there, it's OK.
8
+ end
9
+
10
+ # add unique constraint
11
+ add_index :insights_rules, [:rule_id], unique: true
12
+ end
13
+ end
@@ -71,7 +71,7 @@ module ForemanInventoryUpload
71
71
  end
72
72
 
73
73
  def self.inventory_base_url
74
- ForemanRhCloud.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
@@ -6,15 +6,18 @@ module ForemanRhCloud
6
6
  engine_name 'foreman_rh_cloud'
7
7
 
8
8
  def self.register_scheduled_task(task_class, cronline)
9
- return if ForemanTasks::RecurringLogic.joins(:tasks)
10
- .merge(ForemanTasks::Task.where(label: task_class.name))
11
- .exists?
12
-
13
- User.as_anonymous_admin do
14
- recurring_logic = ForemanTasks::RecurringLogic.new_from_cronline(cronline)
15
- recurring_logic.save!
16
- recurring_logic.start(task_class)
9
+ ForemanTasks::RecurringLogic.transaction(isolation: :serializable) do
10
+ return if ForemanTasks::RecurringLogic.joins(:tasks)
11
+ .merge(ForemanTasks::Task.where(label: task_class.name))
12
+ .exists?
13
+
14
+ User.as_anonymous_admin do
15
+ recurring_logic = ForemanTasks::RecurringLogic.new_from_cronline(cronline)
16
+ recurring_logic.save!
17
+ recurring_logic.start(task_class)
18
+ end
17
19
  end
20
+ rescue ActiveRecord::TransactionIsolationError
18
21
  end
19
22
 
20
23
  initializer 'foreman_rh_cloud.load_default_settings', :before => :load_config_initializers do
@@ -53,7 +56,7 @@ module ForemanRhCloud
53
56
  'api/v2/rh_cloud/inventory': [:sync_inventory_status, :download_file, :generate_report, :enable_cloud_connector],
54
57
  'foreman_inventory_upload/uploads': [:enable_cloud_connector],
55
58
  'foreman_inventory_upload/uploads_settings': [:set_advanced_setting],
56
- 'insights_cloud/settings': [:save_token_and_sync, :update],
59
+ 'insights_cloud/settings': [:update],
57
60
  'insights_cloud/tasks': [:create]
58
61
  )
59
62
  permission(
@@ -140,9 +143,9 @@ module ForemanRhCloud
140
143
  Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
141
144
  end
142
145
 
143
- config.to_prepare do
146
+ initializer 'foreman_rh_cloud.register_rex_features', :before => :finisher_hook do |_app|
144
147
  # skip database manipulations while tables do not exist, like in migrations
145
- if ActiveRecord::Base.connection.data_source_exists?(ForemanTasks::Task.table_name) &&
148
+ if ActiveRecord::Base.connection.data_source_exists?(ForemanTasks::Task.table_name)
146
149
  RemoteExecutionFeature.register(
147
150
  :rh_cloud_remediate_hosts,
148
151
  N_('Apply Insights recommendations'),
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '5.0.34'.freeze
2
+ VERSION = '5.0.37'.freeze
3
3
  end
@@ -16,11 +16,6 @@ module ForemanRhCloud
16
16
  @legacy_insights_url ||= ENV['SATELLITE_LEGACY_INSIGHTS_URL'] || 'https://cert-api.access.redhat.com'
17
17
  end
18
18
 
19
- def self.authentication_url
20
- # https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
21
- @authentication_url ||= ENV['SATELLITE_RH_CLOUD_SSO_URL'] || 'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token'
22
- end
23
-
24
19
  def self.verify_ssl_method
25
20
  @verify_ssl_method ||= ENV['SATELLITE_RH_CLOUD_URL'] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
26
21
  end
@@ -2,7 +2,7 @@ module InsightsCloud
2
2
  module Async
3
3
  class ConnectorPlaybookExecutionReporterTask < ::Actions::EntryAction
4
4
  include Dynflow::Action::Polling
5
- include ForemanRhCloud::CloudAuth
5
+ include ForemanRhCloud::CertAuth
6
6
 
7
7
  def self.subscribe
8
8
  Actions::RemoteExecution::RunHostsJob
@@ -23,6 +23,7 @@ module InsightsCloud
23
23
  correlation_id = invocation_inputs['correlation_id']
24
24
 
25
25
  plan_self(
26
+ current_org_id: job_invocation.targeted_hosts.first.organization_id,
26
27
  report_url: report_url,
27
28
  report_interval: report_interval,
28
29
  job_invocation_id: job_invocation.id,
@@ -159,6 +160,7 @@ module InsightsCloud
159
160
 
160
161
  def send_report(report)
161
162
  execute_cloud_request(
163
+ organization: current_org,
162
164
  method: :post,
163
165
  url: report_url,
164
166
  content_type: 'application/vnd.redhat.playbook-sat.v3+jsonl',
@@ -188,6 +190,10 @@ module InsightsCloud
188
190
  def logger
189
191
  action_logger
190
192
  end
193
+
194
+ def current_org
195
+ Organization.find(input[:current_org_id])
196
+ end
191
197
  end
192
198
  end
193
199
  end
@@ -3,37 +3,48 @@ require 'rest-client'
3
3
  module InsightsCloud
4
4
  module Async
5
5
  class InsightsFullSync < ::Actions::EntryAction
6
- include ::ForemanRhCloud::CloudAuth
7
-
8
- def plan
9
- unless cloud_auth_available?
10
- logger.debug('Cloud authentication is not available, skipping insights sync')
11
- return
6
+ include ::ForemanRhCloud::CertAuth
7
+
8
+ def plan(organizations)
9
+ organizations = organizations.select do |organization|
10
+ if cert_auth_available?(organization)
11
+ true
12
+ else
13
+ logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
14
+ false
15
+ end
12
16
  end
13
17
 
14
18
  sequence do
15
19
  # This can be turned off when we enable automatic status syncs
16
20
  # This step will query cloud inventory to retrieve inventory uuids for each host
17
- plan_hosts_sync
18
- plan_self
21
+ plan_hosts_sync(organizations)
22
+ plan_self(organization_ids: organizations.map(&:id))
19
23
  concurrence do
20
- plan_rules_sync
24
+ plan_rules_sync(organizations)
21
25
  plan_notifications
22
26
  end
23
27
  end
24
28
  end
25
29
 
26
30
  def run
27
- perform_hits_sync
31
+ organizations.each do |organization|
32
+ unless cert_auth_available?(organization)
33
+ logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
34
+ next
35
+ end
36
+
37
+ perform_hits_sync(organization)
38
+ end
28
39
  end
29
40
 
30
- def perform_hits_sync
31
- hits = query_insights_hits
41
+ def perform_hits_sync(organization)
42
+ hits = query_insights_hits(organization)
32
43
 
33
44
  uuids = hits.map { |hit| hit['uuid'] }
34
- setup_host_ids(uuids)
45
+ setup_host_ids(uuids, organization)
35
46
 
36
- replace_hits_data(hits)
47
+ replace_hits_data(hits, organization)
37
48
  end
38
49
 
39
50
  def logger
@@ -42,20 +53,21 @@ module InsightsCloud
42
53
 
43
54
  private
44
55
 
45
- def plan_hosts_sync
46
- plan_action InventorySync::Async::InventoryHostsSync
56
+ def plan_hosts_sync(organizations)
57
+ plan_action(InventorySync::Async::InventoryHostsSync, organizations)
47
58
  end
48
59
 
49
- def plan_rules_sync
50
- plan_action InsightsRulesSync
60
+ def plan_rules_sync(organizations)
61
+ plan_action(InsightsRulesSync, organizations)
51
62
  end
52
63
 
53
64
  def plan_notifications
54
65
  plan_action InsightsGenerateNotifications
55
66
  end
56
67
 
57
- def query_insights_hits
68
+ def query_insights_hits(organization)
58
69
  hits_response = execute_cloud_request(
70
+ organization: organization,
59
71
  method: :get,
60
72
  url: InsightsCloud.hits_export_url
61
73
  )
@@ -72,9 +84,9 @@ module InsightsCloud
72
84
  JSON.parse(rules_response)
73
85
  end
74
86
 
75
- def setup_host_ids(uuids)
87
+ def setup_host_ids(uuids, organization)
76
88
  @host_ids = Hash[
77
- InsightsFacet.where(uuid: uuids).pluck(:uuid, :host_id)
89
+ InsightsFacet.for_organizations(organization.id).where(uuid: uuids).pluck(:uuid, :host_id)
78
90
  ]
79
91
  end
80
92
 
@@ -82,11 +94,11 @@ module InsightsCloud
82
94
  @host_ids[uuid]
83
95
  end
84
96
 
85
- def replace_hits_data(hits)
97
+ def replace_hits_data(hits, organization)
86
98
  InsightsHit.transaction do
87
99
  # Reset hit counters to 0, they will be recreated later
88
- InsightsFacet.unscoped.update_all(hits_count: 0)
89
- InsightsHit.delete_all
100
+ InsightsFacet.for_organizations(organization.id).update_all(hits_count: 0)
101
+ InsightsHit.for_organizations(organization.id).delete_all
90
102
  InsightsHit.create(hits.map { |hits_hash| to_model_hash(hits_hash) }.compact)
91
103
  end
92
104
  end
@@ -122,6 +134,10 @@ module InsightsCloud
122
134
  def rescue_strategy_for_self
123
135
  Dynflow::Action::Rescue::Fail
124
136
  end
137
+
138
+ def organizations
139
+ @organizations ||= Organization.where(id: input[:organization_ids])
140
+ end
125
141
  end
126
142
  end
127
143
  end
@@ -3,25 +3,20 @@ require 'rest-client'
3
3
  module InsightsCloud
4
4
  module Async
5
5
  class InsightsResolutionsSync < ::Actions::EntryAction
6
- include ::ForemanRhCloud::CloudAuth
6
+ include ::ForemanRhCloud::CertAuth
7
7
 
8
8
  RULE_ID_REGEX = /[^:]*:(?<id>.*)/
9
9
 
10
- def plan
11
- unless cloud_auth_available?
12
- logger.debug('Cloud authentication is not available, skipping resolutions sync')
13
- return
14
- end
15
-
16
- plan_self
17
- end
18
-
19
10
  def run
20
11
  InsightsResolution.transaction do
21
12
  InsightsResolution.delete_all
22
13
  rule_ids = relevant_rules
23
- api_response = query_insights_resolutions(rule_ids) unless rule_ids.empty?
24
- write_resolutions(api_response) if api_response
14
+ Organization.all.each do |organization|
15
+ next if !cert_auth_available?(organization) || organization.manifest_expired?
16
+ api_response = query_insights_resolutions(rule_ids, organization) unless rule_ids.empty?
17
+ written_rules = write_resolutions(api_response) if api_response
18
+ rule_ids -= Array(written_rules)
19
+ end
25
20
  end
26
21
  end
27
22
 
@@ -31,8 +26,9 @@ module InsightsCloud
31
26
 
32
27
  private
33
28
 
34
- def query_insights_resolutions(rule_ids)
29
+ def query_insights_resolutions(rule_ids, organization)
35
30
  resolutions_response = execute_cloud_request(
31
+ organization: organization,
36
32
  method: :post,
37
33
  url: InsightsCloud.resolutions_url,
38
34
  headers: {
@@ -66,6 +62,7 @@ module InsightsCloud
66
62
  end.flatten
67
63
 
68
64
  InsightsResolution.create(all_resolutions)
65
+ response.keys
69
66
  end
70
67
 
71
68
  def to_rule_id(resolution_rule_id)