foreman_rh_cloud 11.0.3 → 11.2.0

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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/assets/javascripts/foreman_rh_cloud/locale/en/foreman_rh_cloud.js +248 -161
  4. data/app/assets/javascripts/foreman_rh_cloud/locale/fr/foreman_rh_cloud.js +393 -306
  5. data/app/assets/javascripts/foreman_rh_cloud/locale/ja/foreman_rh_cloud.js +393 -306
  6. data/app/assets/javascripts/foreman_rh_cloud/locale/ka/foreman_rh_cloud.js +393 -306
  7. data/app/assets/javascripts/foreman_rh_cloud/locale/ko/foreman_rh_cloud.js +589 -0
  8. data/app/assets/javascripts/foreman_rh_cloud/locale/zh_CN/foreman_rh_cloud.js +393 -306
  9. data/app/controllers/api/v2/advisor_engine/advisor_engine_controller.rb +98 -0
  10. data/app/controllers/api/v2/rh_cloud/advisor_engine_config_controller.rb +16 -0
  11. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +9 -1
  12. data/app/models/concerns/rh_cloud_host.rb +5 -0
  13. data/app/services/foreman_rh_cloud/cloud_connector.rb +1 -1
  14. data/app/services/foreman_rh_cloud/cloud_request.rb +1 -1
  15. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +4 -2
  16. data/app/services/foreman_rh_cloud/hits_uploader.rb +50 -0
  17. data/app/services/foreman_rh_cloud/rules_ingester.rb +61 -0
  18. data/app/services/foreman_rh_cloud/template_renderer_helper.rb +1 -1
  19. data/app/views/api/v2/advisor_engine/host_details.json.rabl +9 -0
  20. data/app/views/api/v2/hosts/insights/base.rabl +5 -0
  21. data/app/views/api/v2/hosts/insights/insights.rabl +3 -0
  22. data/config/routes.rb +15 -4
  23. data/db/migrate/20241217190624_add_unique_index_to_rule_id_and_host_id_in_insights_hits.rb +5 -0
  24. data/db/migrate/20241220184900_change_sync_insights_recommendations_to_true.rb +5 -0
  25. data/db/seeds.d/189_add_host_inventory_param.rb +7 -0
  26. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +21 -13
  27. data/lib/foreman_inventory_upload/async/upload_report_job.rb +2 -2
  28. data/lib/foreman_inventory_upload/generators/queries.rb +1 -1
  29. data/lib/foreman_inventory_upload/generators/slice.rb +1 -1
  30. data/lib/foreman_rh_cloud/engine.rb +24 -5
  31. data/lib/foreman_rh_cloud/version.rb +1 -1
  32. data/lib/foreman_rh_cloud.rb +21 -31
  33. data/lib/insights_cloud/async/insights_scheduled_sync.rb +10 -2
  34. data/lib/insights_cloud.rb +4 -0
  35. data/lib/inventory_sync/async/inventory_full_sync.rb +0 -10
  36. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +15 -7
  37. data/lib/tasks/insights.rake +10 -7
  38. data/lib/tasks/rh_cloud_inventory.rake +8 -3
  39. data/locale/Makefile +12 -2
  40. data/locale/en/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  41. data/locale/en/foreman_rh_cloud.po +111 -22
  42. data/locale/foreman_rh_cloud.pot +217 -96
  43. data/locale/fr/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  44. data/locale/fr/foreman_rh_cloud.po +106 -19
  45. data/locale/ja/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  46. data/locale/ja/foreman_rh_cloud.po +106 -19
  47. data/locale/ka/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  48. data/locale/ka/foreman_rh_cloud.po +106 -19
  49. data/locale/ko/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  50. data/locale/ko/foreman_rh_cloud.po +591 -0
  51. data/locale/zh_CN/LC_MESSAGES/foreman_rh_cloud.mo +0 -0
  52. data/locale/zh_CN/foreman_rh_cloud.po +106 -19
  53. data/package.json +1 -1
  54. data/test/controllers/insights_cloud/api/advisor_engine_controller_test.rb +48 -0
  55. data/test/controllers/insights_sync/settings_controller_test.rb +3 -0
  56. data/test/factories/insights_factories.rb +1 -1
  57. data/test/jobs/inventory_scheduled_sync_test.rb +10 -0
  58. data/test/unit/rh_cloud_http_proxy_test.rb +1 -26
  59. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +24 -0
  60. data/test/unit/services/foreman_rh_cloud/hits_uploader_test.rb +131 -0
  61. data/test/unit/services/foreman_rh_cloud/rules_ingester_test.rb +60 -0
  62. data/test/unit/slice_generator_test.rb +24 -2
  63. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +1 -1
  64. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +2 -2
  65. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +2 -2
  66. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +3 -1
  67. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +1 -1
  68. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +1 -1
  69. data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +1 -1
  70. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +1 -1
  71. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +1 -1
  72. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +26 -22
  73. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsActions.js +2 -1
  74. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +10 -1
  75. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +8 -1
  76. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableHelpers.js +3 -1
  77. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +5 -1
  78. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +5 -0
  79. data/webpack/InsightsCloudSync/InsightsCloudSync.js +1 -2
  80. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +1 -1
  81. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +3 -1
  82. data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +3 -0
  83. data/webpack/common/Hooks/ConfigHooks.js +19 -0
  84. metadata +23 -8
  85. data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +0 -8
  86. data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +0 -16
  87. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettings.test.js +0 -18
  88. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +0 -15
  89. data/webpack/InsightsCloudSync/Components/__tests__/InsightsHeader.test.js +0 -10
  90. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +0 -13
@@ -0,0 +1,98 @@
1
+ module Api
2
+ module V2
3
+ module AdvisorEngine
4
+ class AdvisorEngineController < ::Api::V2::BaseController
5
+ include ::Api::Version2
6
+ include Foreman::Controller::SmartProxyAuth
7
+ include ::Foreman::Controller::FilterParameters
8
+
9
+ filter_parameters :payload
10
+ add_smart_proxy_filters [:host_details, :upload_hits]
11
+
12
+ api :GET, "/advisor_engine/host_details", N_('Fetch Insights-related host details')
13
+ param :host_uuids, Array, required: true, desc: N_('List of host UUIDs')
14
+ def host_details
15
+ uuids = params.require(:host_uuids)
16
+ @hosts = ::Host.joins(:insights).where(:insights => { :uuid => uuids })
17
+ if @hosts.empty?
18
+ render json: { error: 'No hosts found for the given UUIDs' }, status: :not_found
19
+ else
20
+ respond_to do |format|
21
+ format.json { render 'api/v2/advisor_engine/host_details' }
22
+ end
23
+ end
24
+ end
25
+
26
+ api :PATCH, "/advisor_engine/upload_hits", N_("Upload hits from iop-advisor-engine")
27
+ param :host_name, String, required: true
28
+ param :host_uuid, String
29
+
30
+ param :payload, Hash, :desc => N_("iop payload including resolutions, rules, hits") do
31
+ param :resolutions, Array, :desc => N_("upload resolutions related to the hits") do
32
+ param :rule_id, String, :desc => N_("rule id"), :required => true
33
+ param :description, String, :desc => N_("resolution description")
34
+ param :needs_reboot, :bool, :desc => N_("Whether the resolution requires reboot")
35
+ param :resolution_risk, String, :desc => N_("resolution risk")
36
+ param :resolution_type, String, :desc => N_("type")
37
+ end
38
+
39
+ param :rules, Array, :desc => N_("Upload rules related to the hits") do
40
+ param :rule_id, String, :desc => N_("rule id"), :required => true
41
+ param :description, String, :desc => N_("rule description")
42
+ param :category_name, String, :desc => N_("category name")
43
+ param :impact_name, String, :desc => N_("impact name")
44
+ param :summary, String, :desc => N_("summary")
45
+ param :generic, String, :desc => N_("generic")
46
+ param :reason, String, :desc => N_("reason")
47
+ param :total_risk, :number, :desc => N_("total risk")
48
+ param :reboot_required, :bool, :desc => N_("reboot required")
49
+ param :more_info, String, :desc => N_("more info")
50
+ param :rating, :number, :desc => N_("rating")
51
+ end
52
+
53
+ param :hits, Array, :desc => N_("Upload hits information") do
54
+ param :rule_id, String, :desc => N_("rule id"), :required => true
55
+ param :title, String, :desc => N_("rule title")
56
+ param :solution_url, String, :desc => N_("solution url")
57
+ param :total_risk, :number, :desc => N_("total risk")
58
+ param :likelihood, :number, :desc => N_("likelihood number")
59
+ param :publish_date, String, :desc => N_("publish date (YYYY-MM-DD)")
60
+ param :results_url, String, :desc => N_("result url")
61
+ end
62
+ param :details, String, :desc => N_("upload hits details json")
63
+ end
64
+
65
+ def upload_hits
66
+ host = Host.find_by(name: params.require(:host_name))
67
+ if host.blank?
68
+ render json: { error: 'No host found for the given host name' }, status: :not_found
69
+ else
70
+ hits_uploader = ForemanRhCloud::HitsUploader.new(host: host, payload: payload_params.to_h, uuid: params[:host_uuid])
71
+ hits_uploader.upload!
72
+ render json: {
73
+ action_status: 'success',
74
+ }, status: :ok
75
+ end
76
+ end
77
+
78
+ def payload_params
79
+ params.require(:payload).permit(
80
+ :details,
81
+ {
82
+ resolutions: [
83
+ :rule_id, :description, :needs_reboot, :resolution_risk, :resolution_type
84
+ ],
85
+ rules: [
86
+ :rule_id, :description, :category_name, :impact_name, :summary, :generic,
87
+ :reason, :total_risk, :reboot_required, :more_info, :rating
88
+ ],
89
+ hits: [
90
+ :rule_id, :title, :solution_url, :total_risk, :likelihood, :publish_date, :results_url
91
+ ],
92
+ }
93
+ )
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,16 @@
1
+ module Api
2
+ module V2
3
+ module RhCloud
4
+ class AdvisorEngineConfigController < ::Api::V2::BaseController
5
+ include ::Api::Version2
6
+
7
+ api :GET, "/rh_cloud/advisor_engine_config", N_("Show if system is configured to use local iop-advisor-engine.")
8
+ def show
9
+ render json: {
10
+ use_local_advisor_engine: ForemanRhCloud.with_local_advisor_engine?,
11
+ }, status: :ok
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -16,7 +16,15 @@ module InsightsCloud::Api
16
16
  # The method that "proxies" requests over to Cloud
17
17
  def forward_request
18
18
  certs = candlepin_id_cert @organization
19
- @cloud_response = ::ForemanRhCloud::CloudRequestForwarder.new.forward_request(request, controller_name, @branch_id, certs)
19
+ begin
20
+ @cloud_response = ::ForemanRhCloud::CloudRequestForwarder.new.forward_request(request, controller_name, @branch_id, certs)
21
+ rescue RestClient::Exception => e
22
+ logger.info("Forwarding request failed with exception: #{e}")
23
+ return render json: { error: e }, status: :bad_gateway
24
+ rescue RestClient::Timeout => e
25
+ logger.info("Forwarding request failed with timeout: #{e}")
26
+ return render json: { error: e }, status: :gateway_timeout
27
+ end
20
28
 
21
29
  if @cloud_response.code == 401
22
30
  return render json: {
@@ -21,5 +21,10 @@ module RhCloudHost
21
21
  scoped_search :relation => :inventory_sync_status_object, :on => :status, :rename => :insights_inventory_sync_status,
22
22
  :complete_value => { :disconnect => ::InventorySync::InventoryStatus::DISCONNECT,
23
23
  :sync => ::InventorySync::InventoryStatus::SYNC }
24
+ scoped_search :relation => :insights, :on => :uuid, :only_explicit => true, :rename => :insights_uuid
25
+
26
+ def insights_facet
27
+ insights
28
+ end
24
29
  end
25
30
  end
@@ -17,7 +17,7 @@ module ForemanRhCloud
17
17
  :satellite_cloud_connector_password => token_value,
18
18
  }
19
19
 
20
- if (http_proxy = ForemanRhCloud.proxy_setting(logger: Foreman::Logging.logger('app')))
20
+ if (http_proxy = ForemanRhCloud.proxy_setting)
21
21
  input[:satellite_cloud_connector_http_proxy] = http_proxy
22
22
  end
23
23
 
@@ -5,7 +5,7 @@ module ForemanRhCloud
5
5
  def execute_cloud_request(params)
6
6
  final_params = {
7
7
  verify_ssl: ForemanRhCloud.verify_ssl_method,
8
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
8
+ proxy: ForemanRhCloud.transformed_http_proxy_string,
9
9
  }.deep_merge(params)
10
10
 
11
11
  response = RestClient::Request.execute(final_params)
@@ -17,7 +17,7 @@ module ForemanRhCloud
17
17
  logger.debug("Sending request to: #{request_opts[:url]}")
18
18
 
19
19
  execute_cloud_request(request_opts)
20
- rescue RestClient::Exception => error_response
20
+ rescue RestClient::ExceptionWithResponse => error_response
21
21
  error_response.response
22
22
  end
23
23
 
@@ -52,7 +52,9 @@ module ForemanRhCloud
52
52
 
53
53
  def prepare_forward_params(original_request, branch_id)
54
54
  forward_params = original_request.query_parameters
55
- if original_request.user_agent && !original_request.user_agent.include?('redhat_access_cfme')
55
+ compliance_request = original_request.path.match?(/compliance\/v2(\/.*)?/)
56
+ user_agent = original_request.user_agent.present? && !original_request.user_agent.include?('redhat_access_cfme')
57
+ if user_agent && !compliance_request
56
58
  forward_params = forward_params.merge(:branch_id => branch_id)
57
59
  end
58
60
 
@@ -0,0 +1,50 @@
1
+ module ForemanRhCloud
2
+ class HitsUploader
3
+ def initialize(host:, payload:, uuid: nil)
4
+ @host = host
5
+ @uuid = uuid
6
+ @payload = payload
7
+ end
8
+
9
+ def upload!
10
+ ActiveRecord::Base.transaction do
11
+ update_facets
12
+ update_hits
13
+ update_rules_and_resolutions
14
+ update_details
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def update_facets
21
+ facet = InsightsFacet.find_or_create_by(host_id: @host.id)
22
+ facet.update!(uuid: @uuid) if @uuid.present?
23
+ @host.reload
24
+ end
25
+
26
+ def update_hits
27
+ facet = @host.insights
28
+ facet.hits.delete_all
29
+ hits = @payload[:hits]
30
+ # rubocop:disable Rails/SkipsModelValidations
31
+ facet.hits.insert_all(hits) if hits.present?
32
+ # rubocop:enable Rails/SkipsModelValidations
33
+ InsightsFacet.reset_counters(facet.id, :hits_count)
34
+ end
35
+
36
+ def update_rules_and_resolutions
37
+ return if @payload[:rules].blank?
38
+ rule_ids = @payload[:rules].map { |rule| rule[:rule_id] }
39
+ has_missing_rules = InsightsRule.where(rule_id: rule_ids).count != rule_ids.count
40
+ RulesIngester.new.ingest_rules_and_resolutions! if has_missing_rules
41
+ end
42
+
43
+ def update_details
44
+ return if @payload[:details].blank?
45
+ fact_name = FactName.where(name: "insights::hit_details", short_name: 'insights_details').first_or_create
46
+ fact_value = @host.fact_values.where(fact_name: fact_name).first_or_create
47
+ fact_value.update(value: @payload[:details])
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,61 @@
1
+ module ForemanRhCloud
2
+ class RulesIngester
3
+ def ingest_rules_and_resolutions!
4
+ rules, resolutions = fetch_rules_and_resolutions
5
+ # rubocop:disable Rails/SkipsModelValidations
6
+ ::InsightsRule.upsert_all(rules, unique_by: :rule_id)
7
+ ::InsightsResolution.delete_all
8
+ ::InsightsResolution.insert_all(resolutions)
9
+ # rubocop:enable Rails/SkipsModelValidations
10
+ end
11
+
12
+ private
13
+
14
+ def fetch_rules_data
15
+ advisor_url = "#{ForemanRhCloud.on_premise_url}/r/insights/v1/static/release/content.json"
16
+ JSON.parse(Net::HTTP.get(URI.parse(advisor_url)), symbolize_names: true)
17
+ end
18
+
19
+ def fetch_rules_and_resolutions
20
+ rules = fetch_rules_data.values.map do |rule|
21
+ next unless rule[:active]
22
+ next if rule[:playbooks].blank?
23
+ rule.slice(:description, :category,
24
+ :impact_name, :summary, :generic, :reason,
25
+ :rec_likelihood, :rec_impact, :reboot_required,
26
+ :more_info, :rule_id, :playbooks)
27
+ end
28
+ rules.compact!
29
+
30
+ resolutions = rules.flat_map do |rule|
31
+ rule[:playbooks].map do |fix_type, playbook|
32
+ {
33
+ rule_id: rule[:rule_id],
34
+ description: playbook[:name],
35
+ needs_reboot: playbook[:reboot_required] == true,
36
+ resolution_risk: rule[:resolution_risk],
37
+ resolution_type: fix_type,
38
+ }
39
+ end
40
+ end
41
+
42
+ rules.map! do |rule|
43
+ {
44
+ rule_id: rule[:rule_id],
45
+ description: rule[:description],
46
+ category_name: rule[:category],
47
+ impact_name: rule[:impact_name],
48
+ summary: rule[:summary],
49
+ generic: rule[:generic],
50
+ reason: rule[:reason],
51
+ total_risk: ((rule[:rec_likelihood] + rule[:rec_impact]) / 2).to_i,
52
+ reboot_required: rule[:reboot_required] == true,
53
+ more_info: rule[:more_info],
54
+ rating: 0,
55
+ }
56
+ end
57
+
58
+ [rules, resolutions]
59
+ end
60
+ end
61
+ end
@@ -25,7 +25,7 @@ module ForemanRhCloud
25
25
  returns String, desc: 'Playbook downloaded from the cloud'
26
26
  end
27
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
+ retriever = ForemanRhCloud::URLRemediationsRetriever.new(url: playbook_url, organization_id: organization_id, logger: template_logger)
29
29
 
30
30
  cached("rh_playbook_#{playbook_url}") do
31
31
  retriever.create_playbook
@@ -0,0 +1,9 @@
1
+ collection @hosts
2
+
3
+ attributes :name
4
+ node :insights_uuid do |host|
5
+ host.insights_facet&.uuid
6
+ end
7
+ node :insights_hit_details do |host|
8
+ host&.facts('insights::hit_details')&.values&.first
9
+ end
@@ -0,0 +1,5 @@
1
+ attributes :uuid
2
+
3
+ node :insights_hit_details do |facet|
4
+ facet&.host&.facts('insights::hit_details')&.values&.first
5
+ end
@@ -0,0 +1,3 @@
1
+ node :insights_attributes do
2
+ partial 'api/v2/hosts/insights/base', object: @object&.insights_facet
3
+ end
data/config/routes.rb CHANGED
@@ -9,7 +9,9 @@ Rails.application.routes.draw do
9
9
  get 'settings', to: 'uploads_settings#index'
10
10
  post 'setting', to: 'uploads_settings#set_advanced_setting'
11
11
 
12
- post 'cloud_connector', to: 'uploads#enable_cloud_connector'
12
+ unless ForemanRhCloud.with_local_advisor_engine?
13
+ post 'cloud_connector', to: 'uploads#enable_cloud_connector'
14
+ end
13
15
 
14
16
  resources :tasks, only: [:create, :show]
15
17
 
@@ -31,7 +33,9 @@ Rails.application.routes.draw do
31
33
  end
32
34
 
33
35
  namespace :foreman_rh_cloud do
34
- get 'inventory_upload', to: '/react#index'
36
+ unless ForemanRhCloud.with_local_advisor_engine?
37
+ get 'inventory_upload', to: '/react#index'
38
+ end
35
39
  get 'insights_cloud', to: '/react#index' # Uses foreman's react controller
36
40
  end
37
41
 
@@ -61,9 +65,16 @@ Rails.application.routes.draw do
61
65
  end
62
66
 
63
67
  namespace 'rh_cloud' do
64
- post 'enable_connector', to: 'inventory#enable_cloud_connector'
68
+ unless ForemanRhCloud.with_local_advisor_engine?
69
+ post 'enable_connector', to: 'inventory#enable_cloud_connector'
70
+ post 'cloud_request', to: 'cloud_request#update'
71
+ end
72
+ get 'advisor_engine_config', to: 'advisor_engine_config#show'
73
+ end
65
74
 
66
- post 'cloud_request', to: 'cloud_request#update'
75
+ namespace 'advisor_engine' do
76
+ get 'host_details', to: 'advisor_engine#host_details'
77
+ patch 'upload_hits', to: 'advisor_engine#upload_hits'
67
78
  end
68
79
  end
69
80
  end
@@ -0,0 +1,5 @@
1
+ class AddUniqueIndexToRuleIdAndHostIdInInsightsHits < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_index :insights_hits, [:rule_id, :host_id], unique: true, name: 'index_insight_hits_on_rule_id_and_host_id'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeSyncInsightsRecommendationsToTrue < ActiveRecord::Migration[7.0]
2
+ def change
3
+ Setting.where(name: 'allow_auto_insights_sync')&.destroy_all
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ CommonParameter.without_auditing do
2
+ params = [
3
+ { name: "host_registration_insights_inventory", key_type: "boolean", value: true },
4
+ ]
5
+
6
+ params.each { |param| CommonParameter.find_or_create_by(param) }
7
+ end
@@ -13,22 +13,30 @@ module ForemanInventoryUpload
13
13
  return
14
14
  end
15
15
 
16
- after_delay do
17
- organizations = Organization.unscoped.all
18
-
19
- organizations.map do |organization|
20
- total_hosts = ForemanInventoryUpload::Generators::Queries.for_org(organization.id, use_batches: false).count
21
-
22
- if total_hosts <= ForemanInventoryUpload.max_org_size
23
- disconnected = false
24
- plan_generate_report(ForemanInventoryUpload.generated_reports_folder, organization, disconnected)
25
- else
26
- logger.info("Skipping automatic uploads for organization #{organization.name}, too many hosts (#{total_hosts}/#{ForemanInventoryUpload.max_org_size})")
27
- end
28
- end.compact
16
+ if ForemanRhCloud.with_local_advisor_engine?
17
+ plan_self # so that 'run' runs
18
+ else
19
+ after_delay do
20
+ organizations = Organization.unscoped.all
21
+
22
+ organizations.map do |organization|
23
+ total_hosts = ForemanInventoryUpload::Generators::Queries.for_org(organization.id, use_batches: false).count
24
+
25
+ if total_hosts <= ForemanInventoryUpload.max_org_size
26
+ disconnected = false
27
+ plan_generate_report(ForemanInventoryUpload.generated_reports_folder, organization, disconnected)
28
+ else
29
+ logger.info("Skipping automatic uploads for organization #{organization.name}, too many hosts (#{total_hosts}/#{ForemanInventoryUpload.max_org_size})")
30
+ end
31
+ end.compact
32
+ end
29
33
  end
30
34
  end
31
35
 
36
+ def run
37
+ output[:status] = _('The scheduled process is disabled because this Foreman is configured with the use_local_advisor_engine option.') if ForemanRhCloud.with_local_advisor_engine?
38
+ end
39
+
32
40
  def rescue_strategy_for_self
33
41
  Dynflow::Action::Rescue::Fail
34
42
  end
@@ -51,7 +51,7 @@ module ForemanInventoryUpload
51
51
  'CER_PATH' => @cer_path
52
52
  )
53
53
 
54
- http_proxy_string = ForemanRhCloud.http_proxy_string(logger: logger)
54
+ http_proxy_string = ForemanRhCloud.http_proxy_string
55
55
  if http_proxy_string
56
56
  env_vars['http_proxy'] = http_proxy_string
57
57
  env_vars['https_proxy'] = http_proxy_string
@@ -78,7 +78,7 @@ module ForemanInventoryUpload
78
78
  end
79
79
 
80
80
  def content_disconnected?
81
- Setting[:content_disconnected]
81
+ !Setting[:subscription_connection_enabled]
82
82
  end
83
83
  end
84
84
  end
@@ -44,7 +44,7 @@ module ForemanInventoryUpload
44
44
 
45
45
  def self.for_slice(base)
46
46
  base
47
- .search_for("not params.#{InsightsCloud.enable_client_param} = f")
47
+ .search_for("not params.#{InsightsCloud.enable_client_param_inventory} = f")
48
48
  .joins(:subscription_facet)
49
49
  .preload(
50
50
  :interfaces,
@@ -47,7 +47,7 @@ module ForemanInventoryUpload
47
47
  @stream.simple_field('packages_0_signature', fact_value(host, 'conversions::packages::0::signature'))
48
48
  @stream.simple_field('activity_started', fact_value(host, 'conversions::activity_started'))
49
49
  @stream.simple_field('activity_ended', fact_value(host, 'conversions::activity_ended'))
50
- @stream.simple_field('success', fact_value(host, 'conversions::success') || false, :last)
50
+ @stream.simple_field('success', ActiveModel::Type::Boolean.new.cast(fact_value(host, 'conversions::success')), :last)
51
51
  end
52
52
 
53
53
  def report_host(host)
@@ -42,7 +42,7 @@ module ForemanRhCloud
42
42
  settings do
43
43
  category(:rh_cloud, N_('RHCloud')) do
44
44
  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'))
45
- 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'))
45
+ setting('allow_auto_insights_sync', type: :boolean, description: N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), default: true, full_name: N_('Synchronize recommendations Automatically'))
46
46
  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'))
47
47
  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'))
48
48
  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'))
@@ -74,6 +74,7 @@ module ForemanRhCloud
74
74
  'foreman_inventory_upload/cloud_status': [:index],
75
75
  'foreman_inventory_upload/uploads_settings': [:index],
76
76
  'foreman_inventory_upload/missing_hosts': [:index],
77
+ 'api/v2/rh_cloud/advisor_engine_config': [:show],
77
78
  'react': [:index]
78
79
  )
79
80
  permission(
@@ -105,13 +106,21 @@ module ForemanRhCloud
105
106
  Role::MANAGER => plugin_permissions,
106
107
  Role::SYSTEM_ADMIN => plugin_permissions
107
108
 
108
- # Adding a sub menu after hosts menu
109
- divider :top_menu, caption: N_('RH Cloud'), parent: :configure_menu
110
- menu :top_menu, :inventory_upload, caption: N_('Inventory Upload'), url: '/foreman_rh_cloud/inventory_upload', url_hash: { controller: :react, action: :index }, parent: :configure_menu
111
- menu :top_menu, :insights_hits, caption: N_('Insights'), url: '/foreman_rh_cloud/insights_cloud', url_hash: { controller: :react, action: :index }, parent: :configure_menu
109
+ # Adding a top-level menu item
110
+ sub_menu :top_menu, :insights_menu, caption: N_('Insights'), icon: 'fa fa-cloud', after: :hosts_menu do
111
+ menu :top_menu,
112
+ :inventory_upload,
113
+ caption: N_('Inventory Upload'),
114
+ url: '/foreman_rh_cloud/inventory_upload',
115
+ url_hash: { controller: :react, action: :index },
116
+ parent: :insights_menu,
117
+ if: -> { !ForemanRhCloud.with_local_advisor_engine? }
118
+ menu :top_menu, :insights_hits, caption: N_('Recommendations'), url: '/foreman_rh_cloud/insights_cloud', url_hash: { controller: :react, action: :index }, parent: :insights_menu
119
+ end
112
120
 
113
121
  register_facet InsightsFacet, :insights do
114
122
  configure_host do
123
+ api_view :list => 'api/v2/hosts/insights/insights'
115
124
  set_dependent_action :destroy
116
125
  end
117
126
  end
@@ -151,6 +160,12 @@ module ForemanRhCloud
151
160
  end
152
161
  end
153
162
 
163
+ initializer "foreman_rh_cloud.add_rabl_view_path" do
164
+ Rabl.configure do |config|
165
+ config.view_paths << ForemanRhCloud::Engine.root.join('app', 'views')
166
+ end
167
+ end
168
+
154
169
  initializer 'foreman_rh_cloud.register_scheduled_tasks', :before => :finisher_hook do |_app|
155
170
  # skip database manipulations while tables do not exist, like in migrations
156
171
  # skip object creation when admin user is not present, for example in test DB
@@ -193,4 +208,8 @@ module ForemanRhCloud
193
208
  end
194
209
  end
195
210
  end
211
+
212
+ def self.with_local_advisor_engine?
213
+ SETTINGS.dig(:foreman_rh_cloud, :use_local_advisor_engine) || false
214
+ end
196
215
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '11.0.3'.freeze
2
+ VERSION = '11.2.0'.freeze
3
3
  end
@@ -3,17 +3,27 @@ require 'cgi'
3
3
  require 'uri'
4
4
 
5
5
  module ForemanRhCloud
6
+ def self.on_premise_url
7
+ return unless ForemanRhCloud.with_local_advisor_engine?
8
+ port = ENV['ADVISOR_ENGINE_PORT'] || "24443"
9
+ ENV['ADVISOR_ENGINE_URL'] || "https://localhost:#{port}"
10
+ end
11
+
12
+ def self.env_or_on_premise_url(env_var_name)
13
+ ENV[env_var_name] || on_premise_url
14
+ end
15
+
6
16
  def self.base_url
7
17
  # for testing set ENV to 'https://ci.cloud.redhat.com'
8
- @base_url ||= ENV['SATELLITE_RH_CLOUD_URL'] || 'https://cloud.redhat.com'
18
+ @base_url ||= env_or_on_premise_url('SATELLITE_RH_CLOUD_URL') || 'https://cloud.redhat.com'
9
19
  end
10
20
 
11
21
  def self.cert_base_url
12
- @cert_base_url ||= ENV['SATELLITE_CERT_RH_CLOUD_URL'] || 'https://cert.cloud.redhat.com'
22
+ @cert_base_url ||= env_or_on_premise_url('SATELLITE_CERT_RH_CLOUD_URL') || 'https://cert.cloud.redhat.com'
13
23
  end
14
24
 
15
25
  def self.legacy_insights_url
16
- @legacy_insights_url ||= ENV['SATELLITE_LEGACY_INSIGHTS_URL'] || 'https://cert-api.access.redhat.com'
26
+ @legacy_insights_url ||= env_or_on_premise_url('SATELLITE_LEGACY_INSIGHTS_URL') || 'https://cert-api.access.redhat.com'
17
27
  end
18
28
 
19
29
  def self.verify_ssl_method
@@ -24,21 +34,20 @@ module ForemanRhCloud
24
34
  @query_limit ||= ENV['SATELLITE_RH_CLOUD_QUERY_LIMIT'] ? ENV['SATELLITE_RH_CLOUD_QUERY_LIMIT'].to_i : 100
25
35
  end
26
36
 
27
- def self.http_proxy_string(logger: Foreman::Logging.logger('background'))
28
- ForemanRhCloud.proxy_setting(logger: logger)
37
+ def self.http_proxy_string
38
+ ForemanRhCloud.proxy_setting
29
39
  end
30
40
 
31
- def self.transformed_http_proxy_string(logger: Foreman::Logging.logger('background'))
32
- ForemanRhCloud.transform_scheme(ForemanRhCloud.proxy_setting(logger: logger))
41
+ def self.transformed_http_proxy_string
42
+ ForemanRhCloud.transform_scheme(ForemanRhCloud.proxy_setting)
33
43
  end
34
44
 
35
- def self.proxy_setting(logger: Foreman::Logging.logger('background'))
36
- fix_port(proxy_string(logger: logger))
45
+ def self.proxy_setting
46
+ fix_port(proxy_string)
37
47
  end
38
48
 
39
- def self.proxy_string(logger: Foreman::Logging.logger('background'))
49
+ def self.proxy_string
40
50
  HttpProxy.default_global_content_proxy&.full_url ||
41
- ForemanRhCloud.cdn_proxy(logger: logger) ||
42
51
  ForemanRhCloud.global_foreman_proxy ||
43
52
  ''
44
53
  end
@@ -52,25 +61,6 @@ module ForemanRhCloud
52
61
  uri.to_s
53
62
  end
54
63
 
55
- def self.cdn_proxy(logger: Foreman::Logging.logger('app'))
56
- proxy_config = SETTINGS[:katello][:cdn_proxy]
57
- return nil unless proxy_config
58
-
59
- uri = URI('')
60
- uri.host = proxy_config[:host]
61
- uri.port = proxy_config[:port]
62
- uri.scheme = proxy_config[:scheme] || 'http'
63
-
64
- if proxy_config[:user]
65
- uri.user = CGI.escape(proxy_config[:user])
66
- uri.password = CGI.escape(proxy_config[:password])
67
- end
68
- uri.to_s
69
- rescue URI::Error => e
70
- logger.warn("cdn_proxy parsing failed: #{e}")
71
- nil
72
- end
73
-
74
64
  def self.global_foreman_proxy
75
65
  Setting[:http_proxy]
76
66
  end
@@ -114,7 +104,7 @@ module ForemanRhCloud
114
104
  end
115
105
 
116
106
  def self.legacy_insights_ca
117
- "#{ForemanRhCloud::Engine.root}/config/rh_cert-api_chain.pem"
107
+ "#{ForemanRhCloud::Engine.root}/config/rh_cert-api_chain.pem" unless ForemanRhCloud.with_local_advisor_engine?
118
108
  end
119
109
 
120
110
  def self.cloud_url_validator