foreman_rh_cloud 11.0.2 → 11.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/controllers/api/v2/advisor_engine/advisor_engine_controller.rb +98 -0
  4. data/app/controllers/api/v2/rh_cloud/advisor_engine_config_controller.rb +16 -0
  5. data/app/models/concerns/rh_cloud_host.rb +5 -0
  6. data/app/services/foreman_rh_cloud/cloud_connector.rb +1 -1
  7. data/app/services/foreman_rh_cloud/cloud_request.rb +1 -1
  8. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +2 -1
  9. data/app/services/foreman_rh_cloud/hits_uploader.rb +55 -0
  10. data/app/views/api/v2/advisor_engine/host_details.json.rabl +9 -0
  11. data/app/views/api/v2/hosts/insights/base.rabl +5 -0
  12. data/app/views/api/v2/hosts/insights/insights.rabl +3 -0
  13. data/config/routes.rb +6 -1
  14. data/db/migrate/20241217190624_add_unique_index_to_rule_id_and_host_id_in_insights_hits.rb +5 -0
  15. data/db/migrate/20241220184900_change_sync_insights_recommendations_to_true.rb +5 -0
  16. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +21 -13
  17. data/lib/foreman_inventory_upload/async/shell_process.rb +6 -0
  18. data/lib/foreman_inventory_upload/async/upload_report_job.rb +1 -1
  19. data/lib/foreman_inventory_upload/generators/queries.rb +10 -0
  20. data/lib/foreman_inventory_upload/generators/slice.rb +23 -1
  21. data/lib/foreman_rh_cloud/engine.rb +24 -5
  22. data/lib/foreman_rh_cloud/version.rb +1 -1
  23. data/lib/foreman_rh_cloud.rb +21 -31
  24. data/lib/insights_cloud/async/insights_scheduled_sync.rb +10 -2
  25. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +15 -7
  26. data/package.json +1 -1
  27. data/test/controllers/insights_cloud/api/advisor_engine_controller_test.rb +48 -0
  28. data/test/controllers/insights_sync/settings_controller_test.rb +3 -0
  29. data/test/factories/insights_factories.rb +1 -1
  30. data/test/jobs/inventory_scheduled_sync_test.rb +10 -0
  31. data/test/unit/rh_cloud_http_proxy_test.rb +1 -26
  32. data/test/unit/services/foreman_rh_cloud/hits_uploader_test.rb +120 -0
  33. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +1 -1
  34. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +2 -2
  35. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +2 -2
  36. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +4 -2
  37. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +2 -2
  38. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +1 -1
  39. data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +1 -1
  40. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +1 -1
  41. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +1 -1
  42. data/webpack/ForemanRhCloudHelpers.js +5 -2
  43. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +26 -22
  44. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsActions.js +2 -1
  45. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +10 -1
  46. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +8 -1
  47. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableHelpers.js +3 -1
  48. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +5 -0
  49. data/webpack/InsightsCloudSync/InsightsCloudSync.js +1 -2
  50. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +1 -1
  51. data/webpack/InsightsHostDetailsTab/InsightsTotalRiskChartWrapper.js +1 -1
  52. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +3 -1
  53. data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +3 -0
  54. data/webpack/common/Hooks/ConfigHooks.js +19 -0
  55. metadata +19 -11
  56. data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +0 -8
  57. data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +0 -16
  58. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettings.test.js +0 -18
  59. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +0 -15
  60. data/webpack/InsightsCloudSync/Components/__tests__/InsightsHeader.test.js +0 -10
  61. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f59aefea33a7933386cdc77e326b13ceca715d51f4fdf3c02905896363bcc33
4
- data.tar.gz: 95b711179cb036dbfcb8a6261db1f6c9911ff931807a4a0d9765440534c30c8f
3
+ metadata.gz: a0510d9fc263ac8ff7313350cdcdf6fc82e0d13c35c5e8936463f1d5f7367d88
4
+ data.tar.gz: 14561397aed26a96af5a7105c24147c7cf31d9235ea987d065dcb451fb7b05a7
5
5
  SHA512:
6
- metadata.gz: 4bf762fb0c67730e9317948e6ca74921717d8699fb532b4f3c196049ac38f5ba145d7a9a54122f9c18710e4ede293c4d35beb3e3b462b20e936acd8c5547ed8f
7
- data.tar.gz: 91e0dceccebc4fb48d93c7916f0a229a0b1d2077f0319e67fa014ecb29f0adade7c28e6af1ac717d0b12488065031b37ecf20b84c816086d260385211d15e468
6
+ metadata.gz: 7947b880d5a0e7544f1e668d59f67bf5ec8169a4a0d0fd5922160949cd60636e1f8294637f033df4d1df18a624deb207d16da95292511731735e530f1d959534
7
+ data.tar.gz: 58f596790b70a0daa7174ba6360094d2bbf024cacce3cda74e2dedb8319333395df96ce0590c4cf397f3bd6ca3f5c36c89e839fe6fa364beb62314d533050483
data/README.md CHANGED
@@ -15,7 +15,7 @@ for how to install Foreman plugins
15
15
 
16
16
  #### Inventory upload
17
17
 
18
- In UI: Configure -> Inventory Upload -> Restart
18
+ In UI: Configure -> Inventory Upload -> Generate and upload report
19
19
 
20
20
  From command-line:
21
21
 
@@ -46,7 +46,7 @@ From command-line:
46
46
 
47
47
  #### Synchronize inventory status
48
48
 
49
- In UI: Configure -> Inventory Upload -> Sync inventory status
49
+ In UI: Configure -> Inventory Upload -> Sync all inventory status
50
50
 
51
51
  From command-line:
52
52
 
@@ -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
@@ -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)
@@ -33,7 +33,8 @@ module ForemanRhCloud
33
33
  }
34
34
  ),
35
35
  }
36
- base_params.merge(path_params(original_request.path, certs))
36
+ requested_url = original_request.original_fullpath.end_with?('/') ? original_request.path + '/' : original_request.path
37
+ base_params.merge(path_params(requested_url, certs))
37
38
  end
38
39
 
39
40
  def prepare_forward_payload(original_request, controller_name)
@@ -0,0 +1,55 @@
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
+ # rubocop:disable Rails/SkipsModelValidations
39
+ ::InsightsRule.upsert_all(@payload[:rules], unique_by: :rule_id)
40
+ rules = @payload[:rules].map { |rule| rule[:rule_id] }
41
+
42
+ return if @payload[:resolutions].blank?
43
+ ::InsightsResolution.where(rule_id: rules).delete_all
44
+ ::InsightsResolution.insert_all(@payload[:resolutions])
45
+ # rubocop:enable Rails/SkipsModelValidations
46
+ end
47
+
48
+ def update_details
49
+ return if @payload[:details].blank?
50
+ fact_name = FactName.where(name: "insights::hit_details", short_name: 'insights_details').first_or_create
51
+ fact_value = @host.fact_values.where(fact_name: fact_name).first_or_create
52
+ fact_value.update(value: @payload[:details])
53
+ end
54
+ end
55
+ end
@@ -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
@@ -62,8 +62,13 @@ Rails.application.routes.draw do
62
62
 
63
63
  namespace 'rh_cloud' do
64
64
  post 'enable_connector', to: 'inventory#enable_cloud_connector'
65
-
66
65
  post 'cloud_request', to: 'cloud_request#update'
66
+ get 'advisor_engine_config', to: 'advisor_engine_config#show'
67
+ end
68
+
69
+ namespace 'advisor_engine' do
70
+ get 'host_details', to: 'advisor_engine#host_details'
71
+ patch 'upload_hits', to: 'advisor_engine#upload_hits'
67
72
  end
68
73
  end
69
74
  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
@@ -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
@@ -7,6 +7,7 @@ module ForemanInventoryUpload
7
7
  include ::ForemanRhCloud::Async::ExponentialBackoff
8
8
 
9
9
  def plan(instance_label, more_inputs = {})
10
+ clear_task_output(instance_label)
10
11
  inputs = more_inputs.merge(instance_label: instance_label)
11
12
  plan_self(inputs)
12
13
  end
@@ -53,6 +54,11 @@ module ForemanInventoryUpload
53
54
  Dynflow::Action::Rescue::Fail
54
55
  end
55
56
 
57
+ def clear_task_output(label)
58
+ TaskOutputLine.where(label: label).delete_all
59
+ TaskOutputStatus.where(label: label).delete_all
60
+ end
61
+
56
62
  private
57
63
 
58
64
  def preprocess_command(command)
@@ -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
@@ -28,6 +28,16 @@ module ForemanInventoryUpload
28
28
  'insights_client::hostname',
29
29
  'insights_client::ips',
30
30
  'insights_id',
31
+ 'conversions::activity',
32
+ 'conversions::packages::0::nevra',
33
+ 'conversions::packages::0::signature',
34
+ 'conversions::activity_started',
35
+ 'conversions::activity_ended',
36
+ 'conversions::success',
37
+ 'conversions::source_os::name',
38
+ 'conversions::source_os::version',
39
+ 'conversions::target_os::name',
40
+ 'conversions::target_os::version',
31
41
  ]).pluck(:name, :id)
32
42
  ]
33
43
  end
@@ -40,6 +40,16 @@ module ForemanInventoryUpload
40
40
  end
41
41
  end
42
42
 
43
+ def report_conversions(host)
44
+ @stream.simple_field('convert2rhel_through_foreman', host.subscription_facet&.convert2rhel_through_foreman)
45
+ @stream.simple_field('activity', fact_value(host, 'conversions::activity'))
46
+ @stream.simple_field('packages_0_nevra', fact_value(host, 'conversions::packages::0::nevra'))
47
+ @stream.simple_field('packages_0_signature', fact_value(host, 'conversions::packages::0::signature'))
48
+ @stream.simple_field('activity_started', fact_value(host, 'conversions::activity_started'))
49
+ @stream.simple_field('activity_ended', fact_value(host, 'conversions::activity_ended'))
50
+ @stream.simple_field('success', ActiveModel::Type::Boolean.new.cast(fact_value(host, 'conversions::success')), :last)
51
+ end
52
+
43
53
  def report_host(host)
44
54
  host_ips_cache = host_ips(host)
45
55
  @stream.object do
@@ -47,7 +57,19 @@ module ForemanInventoryUpload
47
57
  @stream.simple_field('account', account_id(host.organization).to_s)
48
58
  @stream.simple_field('subscription_manager_id', uuid_value!(host.subscription_facet&.uuid))
49
59
  @stream.simple_field('satellite_id', uuid_value!(host.subscription_facet&.uuid))
50
- @stream.simple_field('convert2rhel_through_foreman', host.subscription_facet&.convert2rhel_through_foreman)
60
+ if host.subscription_facet&.convert2rhel_through_foreman.present?
61
+ @stream.object_field('conversions') do
62
+ @stream.object_field('source_os') do
63
+ @stream.simple_field('name', fact_value(host, 'conversions::source_os::name'))
64
+ @stream.simple_field('version', fact_value(host, 'conversions::source_os::version') || 'Unknown - Fact not reported', :last)
65
+ end
66
+ @stream.object_field('target_os') do
67
+ @stream.simple_field('name', fact_value(host, 'conversions::target_os::name'))
68
+ @stream.simple_field('version', fact_value(host, 'conversions::target_os::version') || 'Unknown - Fact not reported', :last)
69
+ end
70
+ report_conversions(host)
71
+ end
72
+ end
51
73
  @stream.simple_field('bios_uuid', bios_uuid(host))
52
74
  @stream.simple_field('vm_uuid', uuid_value(fact_value(host, 'virt::uuid')))
53
75
  @stream.simple_field('insights_id', uuid_value(fact_value(host, 'insights_id')))
@@ -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.2'.freeze
2
+ VERSION = '11.1.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
@@ -13,11 +13,19 @@ module InsightsCloud
13
13
  return
14
14
  end
15
15
 
16
- after_delay do
17
- plan_full_sync
16
+ if ForemanRhCloud.with_local_advisor_engine?
17
+ plan_self
18
+ else
19
+ after_delay do
20
+ plan_full_sync # so that 'run' runs
21
+ end
18
22
  end
19
23
  end
20
24
 
25
+ def run
26
+ 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?
27
+ end
28
+
21
29
  def plan_full_sync
22
30
  plan_action(InsightsFullSync, Organization.unscoped.all)
23
31
  end
@@ -13,13 +13,17 @@ module InventorySync
13
13
  return
14
14
  end
15
15
 
16
- after_delay do
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.id) if Setting[:allow_auto_insights_mismatch_delete]
16
+ if ForemanRhCloud.with_local_advisor_engine?
17
+ plan_self # so that 'run' runs
18
+ else
19
+ after_delay do
20
+ # perform a sequence of sync then delete in parallel for all organizations
21
+ concurrence do
22
+ Organization.unscoped.each do |org|
23
+ sequence do
24
+ plan_org_sync(org)
25
+ plan_remove_insights_hosts(org.id) if Setting[:allow_auto_insights_mismatch_delete]
26
+ end
23
27
  end
24
28
  end
25
29
  end
@@ -30,6 +34,10 @@ module InventorySync
30
34
  plan_action InventoryFullSync, org
31
35
  end
32
36
 
37
+ def run
38
+ 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?
39
+ end
40
+
33
41
  def plan_remove_insights_hosts(org_id)
34
42
  # plan a remove hosts action with search set to empty (all records)
35
43
  plan_action(ForemanInventoryUpload::Async::RemoveInsightsHostsJob, '', org_id)