foreman_rh_cloud 6.0.42.2 → 6.0.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +3 -0
  3. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +11 -5
  4. data/lib/foreman_inventory_upload/async/delayed_start.rb +51 -0
  5. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +12 -9
  6. data/lib/foreman_inventory_upload/async/shell_process.rb +9 -1
  7. data/lib/foreman_inventory_upload/async/upload_report_job.rb +3 -1
  8. data/lib/foreman_rh_cloud/async/exponential_backoff.rb +55 -0
  9. data/lib/foreman_rh_cloud/version.rb +1 -1
  10. data/lib/foreman_rh_cloud.rb +4 -0
  11. data/lib/insights_cloud/async/insights_full_sync.rb +3 -1
  12. data/lib/insights_cloud/async/insights_resolutions_sync.rb +3 -1
  13. data/lib/insights_cloud/async/insights_rules_sync.rb +3 -1
  14. data/lib/insights_cloud/async/insights_scheduled_sync.rb +4 -1
  15. data/lib/inventory_sync/async/host_result.rb +1 -1
  16. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +5 -2
  17. data/lib/inventory_sync/async/query_inventory_job.rb +4 -1
  18. data/package.json +1 -1
  19. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +11 -0
  20. data/test/jobs/exponential_backoff_test.rb +45 -0
  21. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/index.js +14 -1
  22. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +4 -1
  23. data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +0 -2
  24. data/webpack/InsightsHostDetailsTab/InsightsTotalRiskChart.js +4 -1
  25. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +4 -3
  26. data/webpack/__mocks__/foremanReact/components/ConfirmModal/index.js +3 -0
  27. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 286d62e3c864ee4b0728bfc1c5d1d224e46ee0917d7a2ea517e096ea6dab0c5c
4
- data.tar.gz: 1ce1d58a07bdc5d57acb5dab27e4441594605608a79fdfa82f029c6e6018211e
3
+ metadata.gz: 44056fad5c50d5b78e64b5e13a622818525fd5e8176159462825ae8306cd035f
4
+ data.tar.gz: 6fa455af9f99ea4864c0d813962ecb7fcc9706517daf9459953c378ec547814d
5
5
  SHA512:
6
- metadata.gz: 5375be3e72da24347196c842946f663464bdf8d367b592b682c604eb7373221addc0f43f49735941cc3cfc279ebffb87888284e21752ca4c2b9ba863e99e88c0
7
- data.tar.gz: cc5d701cff558eaf96ea554a7d293fc5fe14e6d8c04daf05d537363dac759b7e611f8af66e780cb30e8856e2a696364a6b9b1efe58806b357f25d8c0f58b6954
6
+ metadata.gz: 9fb003eeadd973880052b4d5d04a682d46938e4805a5bd0aad57ae9c22a0ea5cd05488f8e827838db2c5093d04dd5c91d2cc44332f2472a0e5e76bcf2c78126d
7
+ data.tar.gz: efef456d8ecad910cb36ae64fb82202225733d484a227d6a142e71b145046a5533b626e2349d99d9f257282c03dc026a04de62ff8d436158226dd0f5a7fdcdb8
@@ -18,6 +18,9 @@ module ForemanInventoryUpload
18
18
  end
19
19
 
20
20
  def enable_cloud_connector
21
+ # Set the autoupload to true, since it's required by the feature.
22
+ Setting[:allow_auto_inventory_upload] = true
23
+
21
24
  cloud_connector = ForemanRhCloud::CloudConnector.new
22
25
  render json: cloud_connector.install.to_json
23
26
  end
@@ -33,10 +33,6 @@ module InsightsCloud::Api
33
33
  }, status: @cloud_response.code
34
34
  end
35
35
 
36
- if @cloud_response.headers[:content_disposition]
37
- return send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
38
- end
39
-
40
36
  # Append redhat-specific headers
41
37
  @cloud_response.headers.each do |key, value|
42
38
  assign_header(response, @cloud_response, key, false) if key.to_s.start_with?('x_rh_')
@@ -45,7 +41,17 @@ module InsightsCloud::Api
45
41
  assign_header(response, @cloud_response, :x_resource_count, true)
46
42
  headers[Rack::ETAG] = @cloud_response.headers[:etag]
47
43
 
48
- render json: @cloud_response, status: @cloud_response.code
44
+ if @cloud_response.headers[:content_disposition]
45
+ # If there is a Content-Disposition header, it means we are forwarding binary data, send the raw data with proper
46
+ # content type
47
+ send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
48
+ elsif @cloud_response.headers[:content_type] =~ /zip/
49
+ # if there is no Content-Disposition, but the content type is binary according the content type,
50
+ # forward the request as binry too
51
+ send_data @cloud_response, type: @cloud_response.headers[:content_type]
52
+ else
53
+ render json: @cloud_response, status: @cloud_response.code
54
+ end
49
55
  end
50
56
 
51
57
  def branch_info
@@ -0,0 +1,51 @@
1
+ module ForemanInventoryUpload
2
+ module Async
3
+ module DelayedStart
4
+ extend ActiveSupport::Concern
5
+
6
+ START_WINDOW = 3.hours.seconds
7
+
8
+ def after_delay(delay = nil, logger: nil, &block)
9
+ logger ||= self.logger if respond_to? :logger
10
+ delay ||= ForemanRhCloud.requests_delay || Random.new.rand(START_WINDOW)
11
+ delay = delay.to_i
12
+
13
+ logger&.debug("planning a delay for #{delay} seconds before the rest of the execution")
14
+
15
+ sequence do
16
+ plan_action(ForemanInventoryUpload::Async::DelayAction, delay)
17
+ concurrence(&block)
18
+ end
19
+ end
20
+
21
+ def humanized_name
22
+ _('Wait and %s' % super)
23
+ end
24
+ end
25
+
26
+ class DelayAction < ::Actions::EntryAction
27
+ Wake = Algebrick.atom
28
+
29
+ def plan(delay)
30
+ plan_self(delay: delay)
31
+ end
32
+
33
+ def run(event = nil)
34
+ case event
35
+ when nil
36
+ action_logger.debug("Going to sleep for #{sleep_seconds} seconds")
37
+ plan_event(Wake, sleep_seconds)
38
+ suspend
39
+ when Wake
40
+ action_logger.debug('Waking up')
41
+ else
42
+ action_logger.debug("DelayAction received unknown event #{event}")
43
+ end
44
+ end
45
+
46
+ def sleep_seconds
47
+ input[:delay].to_i
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,6 +2,7 @@ module ForemanInventoryUpload
2
2
  module Async
3
3
  class GenerateAllReportsJob < ::Actions::EntryAction
4
4
  include ::Actions::RecurringAction
5
+ include ForemanInventoryUpload::Async::DelayedStart
5
6
 
6
7
  def plan
7
8
  unless Setting[:allow_auto_inventory_upload]
@@ -12,17 +13,19 @@ module ForemanInventoryUpload
12
13
  return
13
14
  end
14
15
 
15
- organizations = Organization.unscoped.all
16
+ after_delay do
17
+ organizations = Organization.unscoped.all
16
18
 
17
- organizations.map do |organization|
18
- total_hosts = ForemanInventoryUpload::Generators::Queries.for_org(organization.id, use_batches: false).count
19
+ organizations.map do |organization|
20
+ total_hosts = ForemanInventoryUpload::Generators::Queries.for_org(organization.id, use_batches: false).count
19
21
 
20
- if total_hosts <= ForemanInventoryUpload.max_org_size
21
- plan_generate_report(ForemanInventoryUpload.generated_reports_folder, organization)
22
- else
23
- logger.info("Skipping automatic uploads for organization #{organization.name}, too many hosts (#{total_hosts}/#{ForemanInventoryUpload.max_org_size})")
24
- end
25
- end.compact
22
+ if total_hosts <= ForemanInventoryUpload.max_org_size
23
+ plan_generate_report(ForemanInventoryUpload.generated_reports_folder, organization)
24
+ else
25
+ logger.info("Skipping automatic uploads for organization #{organization.name}, too many hosts (#{total_hosts}/#{ForemanInventoryUpload.max_org_size})")
26
+ end
27
+ end.compact
28
+ end
26
29
  end
27
30
 
28
31
  def rescue_strategy_for_self
@@ -4,13 +4,14 @@ module ForemanInventoryUpload
4
4
  module Async
5
5
  class ShellProcess < ::Actions::EntryAction
6
6
  include AsyncHelpers
7
+ include ::ForemanRhCloud::Async::ExponentialBackoff
7
8
 
8
9
  def plan(instance_label, more_inputs = {})
9
10
  inputs = more_inputs.merge(instance_label: instance_label)
10
11
  plan_self(inputs)
11
12
  end
12
13
 
13
- def run
14
+ def try_execute
14
15
  klass_name = self.class.name
15
16
  logger.debug("Starting #{klass_name} with label #{instance_label}")
16
17
  progress_output do |progress_output|
@@ -25,6 +26,9 @@ module ForemanInventoryUpload
25
26
  end
26
27
  end
27
28
  logger.debug("Finished job #{klass_name} with label #{instance_label}")
29
+
30
+ assert_task_status(ProgressOutput.get(instance_label).status)
31
+ done!
28
32
  end
29
33
 
30
34
  def command
@@ -58,6 +62,10 @@ module ForemanInventoryUpload
58
62
  def instance_label
59
63
  input[:instance_label]
60
64
  end
65
+
66
+ def assert_task_status(status)
67
+ raise Foreman::Exception.new('Process exited with an unknown status: %{status}', status: status) unless status.match?(/pid \d+ exit 0/)
68
+ end
61
69
  end
62
70
  end
63
71
  end
@@ -12,11 +12,12 @@ module ForemanInventoryUpload
12
12
  super(label, filename: filename, organization_id: organization_id)
13
13
  end
14
14
 
15
- def run
15
+ def try_execute
16
16
  if content_disconnected?
17
17
  progress_output do |progress_output|
18
18
  progress_output.write_line('Upload was stopped since disconnected mode setting is enabled for content on this instance.')
19
19
  progress_output.status = "Task aborted, exit 1"
20
+ done!
20
21
  end
21
22
  return
22
23
  end
@@ -26,6 +27,7 @@ module ForemanInventoryUpload
26
27
  progress_output do |progress_output|
27
28
  progress_output.write_line("Skipping organization #{organization}, no candlepin certificate defined.")
28
29
  progress_output.status = "Task aborted, exit 1"
30
+ done!
29
31
  end
30
32
  return
31
33
  end
@@ -0,0 +1,55 @@
1
+ module ForemanRhCloud
2
+ module Async
3
+ module ExponentialBackoff
4
+ extend ActiveSupport::Concern
5
+ include Dynflow::Action::Polling
6
+
7
+ # Use each interval once
8
+ def attempts_before_next_interval
9
+ 1
10
+ end
11
+
12
+ # define poll intervals in the following way: [1/10..1, 1..10, 10..100] e.t.c.
13
+ # total count of intervals would be the amount of poll retries.
14
+ def poll_intervals
15
+ (1..poll_max_retries).map do |i|
16
+ base = 10**i
17
+ random_interval(base)
18
+ end
19
+ end
20
+
21
+ def done!
22
+ @done = true
23
+ end
24
+
25
+ def done?
26
+ @done
27
+ end
28
+
29
+ def invoke_external_task
30
+ # Call the polling method from task's framework
31
+ poll_external_task_with_rescue
32
+ # supress unexpected task output serialization
33
+ {}
34
+ end
35
+
36
+ def poll_external_task
37
+ try_execute
38
+ # supress unexpected task output serialization
39
+ {}
40
+ end
41
+
42
+ # override this method in the consumng class
43
+ # This is the action that we expect to retry in case of an exception.
44
+ def try_execute
45
+ raise NotImplementedError
46
+ end
47
+
48
+ private
49
+
50
+ def random_interval(base)
51
+ Random.new.rand(base..10 * base)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '6.0.42.2'.freeze
2
+ VERSION = '6.0.44'.freeze
3
3
  end
@@ -120,4 +120,8 @@ module ForemanRhCloud
120
120
  def self.cloud_url_validator
121
121
  @cloud_url_validator ||= Regexp.new(ENV['SATELLITE_RH_CLOUD_VALIDATOR'] || 'redhat.com$')
122
122
  end
123
+
124
+ def self.requests_delay
125
+ @requests_delay ||= ENV['SATELLITE_RH_CLOUD_REQUESTS_DELAY']
126
+ end
123
127
  end
@@ -5,6 +5,7 @@ module InsightsCloud
5
5
  module Async
6
6
  class InsightsFullSync < ::Actions::EntryAction
7
7
  include ::ForemanRhCloud::CertAuth
8
+ include ::ForemanRhCloud::Async::ExponentialBackoff
8
9
 
9
10
  def plan(organizations)
10
11
  organizations = organizations.select do |organization|
@@ -28,7 +29,7 @@ module InsightsCloud
28
29
  end
29
30
  end
30
31
 
31
- def run
32
+ def try_execute
32
33
  organizations.each do |organization|
33
34
  unless cert_auth_available?(organization)
34
35
  logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
@@ -37,6 +38,7 @@ module InsightsCloud
37
38
 
38
39
  perform_hits_sync(organization)
39
40
  end
41
+ done!
40
42
  end
41
43
 
42
44
  def perform_hits_sync(organization)
@@ -4,10 +4,11 @@ module InsightsCloud
4
4
  module Async
5
5
  class InsightsResolutionsSync < ::Actions::EntryAction
6
6
  include ::ForemanRhCloud::CertAuth
7
+ include ::ForemanRhCloud::Async::ExponentialBackoff
7
8
 
8
9
  RULE_ID_REGEX = /[^:]*:(?<id>.*)/
9
10
 
10
- def run
11
+ def try_execute
11
12
  InsightsResolution.transaction do
12
13
  InsightsResolution.delete_all
13
14
  rule_ids = relevant_rules
@@ -18,6 +19,7 @@ module InsightsCloud
18
19
  rule_ids -= Array(written_rules)
19
20
  end
20
21
  end
22
+ done!
21
23
  end
22
24
 
23
25
  def logger
@@ -4,6 +4,7 @@ module InsightsCloud
4
4
  module Async
5
5
  class InsightsRulesSync < ::Actions::EntryAction
6
6
  include ::ForemanRhCloud::CertAuth
7
+ include ::ForemanRhCloud::Async::ExponentialBackoff
7
8
 
8
9
  def plan(organizations)
9
10
  # since the tasks are not connected, we need to force sequence execution here
@@ -18,7 +19,7 @@ module InsightsCloud
18
19
  plan_action InsightsResolutionsSync
19
20
  end
20
21
 
21
- def run
22
+ def try_execute
22
23
  offset = 0
23
24
  InsightsRule.transaction do
24
25
  organizations.each do |organization|
@@ -36,6 +37,7 @@ module InsightsCloud
36
37
  # Remove all rules that do not have hits associated with them
37
38
  cleanup_rules
38
39
  end
40
+ done!
39
41
  end
40
42
 
41
43
  def logger
@@ -2,6 +2,7 @@ module InsightsCloud
2
2
  module Async
3
3
  class InsightsScheduledSync < ::Actions::EntryAction
4
4
  include ::Actions::RecurringAction
5
+ include ForemanInventoryUpload::Async::DelayedStart
5
6
 
6
7
  def plan
7
8
  unless Setting[:allow_auto_insights_sync]
@@ -12,7 +13,9 @@ module InsightsCloud
12
13
  return
13
14
  end
14
15
 
15
- plan_full_sync
16
+ after_delay do
17
+ plan_full_sync
18
+ end
16
19
  end
17
20
 
18
21
  def plan_full_sync
@@ -11,7 +11,7 @@ module InventorySync
11
11
  @per_page = result['per_page']
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
- @uuid_by_fqdn = Hash[result["results"].map { |host| [host['fqdn'].downcase, host['id']] }]
14
+ @uuid_by_fqdn = Hash[result["results"].map { |host| [host['fqdn']&.downcase, host['id']] }]
15
15
  end
16
16
 
17
17
  def status_hashes
@@ -2,6 +2,7 @@ module InventorySync
2
2
  module Async
3
3
  class InventoryScheduledSync < ::Actions::EntryAction
4
4
  include ::Actions::RecurringAction
5
+ include ForemanInventoryUpload::Async::DelayedStart
5
6
 
6
7
  def plan
7
8
  unless Setting[:allow_auto_inventory_upload]
@@ -12,8 +13,10 @@ module InventorySync
12
13
  return
13
14
  end
14
15
 
15
- Organization.unscoped.each do |org|
16
- plan_org_sync(org)
16
+ after_delay do
17
+ Organization.unscoped.each do |org|
18
+ plan_org_sync(org)
19
+ end
17
20
  end
18
21
  end
19
22
 
@@ -5,6 +5,7 @@ module InventorySync
5
5
  class QueryInventoryJob < ::Actions::EntryAction
6
6
  include ActiveSupport::Callbacks
7
7
  include ::ForemanRhCloud::CertAuth
8
+ include ::ForemanRhCloud::Async::ExponentialBackoff
8
9
 
9
10
  define_callbacks :iteration, :step
10
11
 
@@ -18,7 +19,7 @@ module InventorySync
18
19
  plan_self(actual_params)
19
20
  end
20
21
 
21
- def run
22
+ def try_execute
22
23
  run_callbacks :iteration do
23
24
  organizations.each do |organization|
24
25
  if !cert_auth_available?(organization) || organization.manifest_expired?
@@ -43,6 +44,8 @@ module InventorySync
43
44
  end
44
45
  end
45
46
  end
47
+ # declare the action as finished to stop iterations
48
+ done!
46
49
  end
47
50
 
48
51
  private
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "6.0.42.2",
3
+ "version": "6.0.44",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -72,6 +72,17 @@ module InsightsCloud::Api
72
72
  assert_equal etag, @response.headers[Rack::ETAG]
73
73
  end
74
74
 
75
+ test "should set content type header to response from cloud" do
76
+ req = RestClient::Request.new(:method => 'GET', :url => 'http://test.theforeman.org')
77
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
78
+ net_http_resp[:content_type] = 'application/zip'
79
+ res = RestClient::Response.create(@body, net_http_resp, req)
80
+ ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:forward_request).returns(res)
81
+
82
+ get :forward_request, params: { "path" => "static/v1/release/insights-core.egg" }
83
+ assert_equal net_http_resp[:content_type], @response.headers['Content-Type']
84
+ end
85
+
75
86
  test "should handle failed authentication to cloud" do
76
87
  net_http_resp = Net::HTTPResponse.new(1.0, 401, "Unauthorized")
77
88
  res = RestClient::Response.create(@body, net_http_resp, @http_req)
@@ -0,0 +1,45 @@
1
+ require 'test_plugin_helper'
2
+ require 'foreman_tasks/test_helpers'
3
+
4
+ class ExponentialBackoffTest < ActiveSupport::TestCase
5
+ include ForemanTasks::TestHelpers::WithInThreadExecutor
6
+
7
+ class TestAction < ::Actions::EntryAction
8
+ include ::ForemanRhCloud::Async::ExponentialBackoff
9
+
10
+ def try_execute
11
+ action_callback&.call(self)
12
+ end
13
+
14
+ # define a method to execute code inside the class context.
15
+ def action_callback(instance)
16
+ end
17
+ end
18
+
19
+ test 'executes an action once' do
20
+ TestAction.any_instance.expects(:action_callback).returns(->(instance) { instance.done! })
21
+
22
+ ForemanTasks.sync_task(TestAction)
23
+ end
24
+
25
+ test 'fails after a single excution if done was called' do
26
+ TestAction.any_instance.expects(:action_callback).returns(
27
+ lambda do |instance|
28
+ instance.done!
29
+ raise ::Foreman::Exception('Foo')
30
+ end)
31
+
32
+ ForemanTasks.sync_task(TestAction)
33
+ end
34
+
35
+ test 'executes the task three times before failing it' do
36
+ # speed up the execution
37
+ TestAction.any_instance.stubs(:poll_intervals).returns([0, 0, 0])
38
+
39
+ TestAction.any_instance.expects(:action_callback).raises(::Foreman::Exception.new('Foo')).times(3)
40
+
41
+ ForemanTasks.sync_task(TestAction)
42
+ rescue ForemanTasks::TaskError => ex
43
+ assert ex.aggregated_message =~ /Foo/
44
+ end
45
+ end
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
+ import { openConfirmModal } from 'foremanReact/components/ConfirmModal';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
3
5
  import { CloudConnectorButton } from './CloudConnectorButton';
4
6
  import { configureCloudConnector } from './CloudConnectorActions';
5
7
  import { selectStatus, selectJobLink } from './CloudConnectorSelectors';
@@ -12,7 +14,18 @@ const ConnectedCloudConnectorButton = () => {
12
14
  return (
13
15
  <CloudConnectorButton
14
16
  status={status}
15
- onClick={() => dispatch(configureCloudConnector())}
17
+ onClick={() =>
18
+ dispatch(
19
+ openConfirmModal({
20
+ title: __('Notice'),
21
+ message: __(
22
+ 'This action will also enable automatic reports upload'
23
+ ),
24
+ isWarning: true,
25
+ onConfirm: () => dispatch(configureCloudConnector()),
26
+ })
27
+ )
28
+ }
16
29
  jobLink={jobLink}
17
30
  />
18
31
  );
@@ -31,6 +31,7 @@ const InsightsTable = ({
31
31
  error,
32
32
  isAllSelected,
33
33
  hideHost,
34
+ hostname,
34
35
  }) => {
35
36
  const { perPage: appPerPage } = useForemanSettings();
36
37
  const perPage = urlPerPage || appPerPage;
@@ -40,7 +41,7 @@ const InsightsTable = ({
40
41
  // acts as componentDidMount
41
42
  useEffect(() => {
42
43
  fetchInsights({ page, perPage, query, sortBy, sortOrder });
43
- }, []);
44
+ }, [hostname]);
44
45
 
45
46
  useEffect(() => {
46
47
  setRows(
@@ -104,6 +105,7 @@ InsightsTable.propTypes = {
104
105
  error: PropTypes.string,
105
106
  isAllSelected: PropTypes.bool,
106
107
  hideHost: PropTypes.bool,
108
+ hostname: PropTypes.string,
107
109
  };
108
110
 
109
111
  InsightsTable.defaultProps = {
@@ -118,6 +120,7 @@ InsightsTable.defaultProps = {
118
120
  error: '',
119
121
  isAllSelected: false,
120
122
  hideHost: false,
123
+ hostname: '',
121
124
  };
122
125
 
123
126
  export default InsightsTable;
@@ -1,5 +1,3 @@
1
- @import '~@redhat-cloud-services/frontend-components/index.css';
2
-
3
1
  .rh-cloud-recommendations-table {
4
2
  .pf-c-table__check {
5
3
  input:disabled {
@@ -121,6 +121,7 @@ const InsightsTotalRiskCard = ({ hostDetails: { id } }) => {
121
121
  dropdownItems={[
122
122
  <DropdownItem
123
123
  key="insights-tab"
124
+ ouiaId="insights-tab-dropdown-item"
124
125
  onClick={() => hashHistory.push(`/Insights`)}
125
126
  >
126
127
  {__('View all recommendations')}
@@ -131,7 +132,9 @@ const InsightsTotalRiskCard = ({ hostDetails: { id } }) => {
131
132
  status={status}
132
133
  emptyState={
133
134
  <Bullseye>
134
- <Title headingLevel="h4"> {__('No results found')} </Title>
135
+ <Title ouiaId="no-results-title" headingLevel="h4">
136
+ {__('No results found')}
137
+ </Title>
135
138
  </Bullseye>
136
139
  }
137
140
  >
@@ -36,7 +36,7 @@ const NewHostDetailsTab = ({ hostName, router }) => {
36
36
  router.push({ pathname: '/foreman_rh_cloud/insights_cloud' });
37
37
 
38
38
  const dropdownItems = [
39
- <DropdownItem key="insights-link">
39
+ <DropdownItem key="insights-link" ouiaId="insights-link">
40
40
  <a onClick={onSatInsightsClick}>{__('Go to Satellite Insights page')}</a>
41
41
  </DropdownItem>,
42
42
  ];
@@ -44,7 +44,7 @@ const NewHostDetailsTab = ({ hostName, router }) => {
44
44
  if (hits.length) {
45
45
  const { host_uuid: uuid } = hits[0];
46
46
  dropdownItems.push(
47
- <DropdownItem key="insights-advisor-link">
47
+ <DropdownItem key="insights-advisor-link" ouiaId="insights-advisor-link">
48
48
  <a
49
49
  href={redHatAdvisorSystems(uuid)}
50
50
  target="_blank"
@@ -71,6 +71,7 @@ const NewHostDetailsTab = ({ hostName, router }) => {
71
71
  <RemediationModal />
72
72
  <Dropdown
73
73
  className="insights-dropdown"
74
+ ouiaId="insights-dropdown"
74
75
  onSelect={() => setIsDropdownOpen(false)}
75
76
  toggle={
76
77
  <KebabToggle onToggle={isOpen => setIsDropdownOpen(isOpen)} />
@@ -81,7 +82,7 @@ const NewHostDetailsTab = ({ hostName, router }) => {
81
82
  />
82
83
  </GridItem>
83
84
  <GridItem span={3}>
84
- <Pagination variant="top" isCompact />
85
+ <Pagination ouiaId="insights-pagination" variant="top" isCompact />
85
86
  </GridItem>
86
87
  <GridItem>
87
88
  <InsightsTable hideHost hostname={hostName} />
@@ -0,0 +1,3 @@
1
+ export const openConfirmModal = options => options;
2
+
3
+ export default openConfirmModal;
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: 6.0.42.2
4
+ version: 6.0.44
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: 2022-11-02 00:00:00.000000000 Z
11
+ date: 2022-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katello
@@ -202,6 +202,7 @@ files:
202
202
  - db/seeds.d/50_job_templates.rb
203
203
  - lib/foreman_inventory_upload.rb
204
204
  - lib/foreman_inventory_upload/async/async_helpers.rb
205
+ - lib/foreman_inventory_upload/async/delayed_start.rb
205
206
  - lib/foreman_inventory_upload/async/generate_all_reports_job.rb
206
207
  - lib/foreman_inventory_upload/async/generate_report_job.rb
207
208
  - lib/foreman_inventory_upload/async/progress_output.rb
@@ -218,6 +219,7 @@ files:
218
219
  - lib/foreman_inventory_upload/notifications/manifest_import_success_notification_override.rb
219
220
  - lib/foreman_inventory_upload/scripts/uploader.sh.erb
220
221
  - lib/foreman_rh_cloud.rb
222
+ - lib/foreman_rh_cloud/async/exponential_backoff.rb
221
223
  - lib/foreman_rh_cloud/engine.rb
222
224
  - lib/foreman_rh_cloud/settings.rb
223
225
  - lib/foreman_rh_cloud/version.rb
@@ -259,6 +261,7 @@ files:
259
261
  - test/factories/inventory_upload_factories.rb
260
262
  - test/jobs/cloud_connector_announce_task_test.rb
261
263
  - test/jobs/connector_playbook_execution_reporter_task_test.rb
264
+ - test/jobs/exponential_backoff_test.rb
262
265
  - test/jobs/insights_client_status_aging_test.rb
263
266
  - test/jobs/insights_full_sync_test.rb
264
267
  - test/jobs/insights_resolutions_sync_test.rb
@@ -625,6 +628,7 @@ files:
625
628
  - webpack/__mocks__/foremanReact/common/I18n.js
626
629
  - webpack/__mocks__/foremanReact/common/MountingService.js
627
630
  - webpack/__mocks__/foremanReact/common/helpers.js
631
+ - webpack/__mocks__/foremanReact/components/ConfirmModal/index.js
628
632
  - webpack/__mocks__/foremanReact/components/Head.js
629
633
  - webpack/__mocks__/foremanReact/components/Layout/LayoutConstants.js
630
634
  - webpack/__mocks__/foremanReact/components/ToastsList/index.js
@@ -693,6 +697,7 @@ test_files:
693
697
  - test/factories/inventory_upload_factories.rb
694
698
  - test/jobs/cloud_connector_announce_task_test.rb
695
699
  - test/jobs/connector_playbook_execution_reporter_task_test.rb
700
+ - test/jobs/exponential_backoff_test.rb
696
701
  - test/jobs/insights_client_status_aging_test.rb
697
702
  - test/jobs/insights_full_sync_test.rb
698
703
  - test/jobs/insights_resolutions_sync_test.rb