foreman_rh_cloud 14.3.0 → 14.5.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.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/rh_cloud/cloud_request_controller.rb +1 -0
- data/app/controllers/api/v2/rh_cloud/inventory_controller.rb +11 -5
- data/app/controllers/foreman_inventory_upload/accounts_controller.rb +0 -1
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +0 -11
- data/app/controllers/foreman_inventory_upload/uploads_settings_controller.rb +0 -8
- data/app/services/foreman_rh_cloud/cloud_presence.rb +23 -0
- data/config/routes.rb +1 -3
- data/lib/foreman_rh_cloud/engine.rb +1 -6
- data/lib/foreman_rh_cloud/plugin.rb +3 -2
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud/async/cloud_connector_announce_task.rb +76 -19
- data/package.json +1 -1
- data/test/controllers/inventory_upload/api/inventory_controller_test.rb +10 -8
- data/test/jobs/cloud_connector_announce_task_test.rb +116 -106
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/MinimalInventoryDropdown.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/integrations.test.js +4 -12
- data/webpack/ForemanRhCloudPages.js +6 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsLabel.js +8 -7
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +2 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +1 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTableActions.test.js +2 -2
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +1 -0
- data/webpack/InsightsCloudSync/__tests__/InsightsCloudSyncActions.test.js +7 -5
- data/webpack/InsightsHostDetailsTab/InsightsTab.js +53 -39
- data/webpack/InsightsHostDetailsTab/InsightsTab.scss +7 -73
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.fixtures.js +7 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js +52 -30
- data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +43 -35
- data/webpack/InsightsHostDetailsTab/components/ListItem/__tests__/ListItem.test.js +111 -0
- data/webpack/InsightsVulnerabilityActionsBar/__tests__/InsightsVulnerabilityActionsBar.test.js +1 -5
- data/webpack/IopPathwayDetails/IopPathwayDetails.js +40 -0
- data/webpack/IopRecommendationDetails/IopRecommendationDetails.js +0 -18
- data/webpack/common/DropdownToggle.js +1 -0
- data/webpack/common/Switcher/HelpLabel.js +7 -5
- data/webpack/test_setup.js +1 -0
- metadata +4 -8
- data/app/services/foreman_rh_cloud/cloud_connector.rb +0 -74
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +0 -6
- data/webpack/__mocks__/foremanReact/common/I18n.js +0 -6
- data/webpack/__mocks__/foremanReact/common/helpers.js +0 -14
- data/webpack/__mocks__/foremanReact/constants.js +0 -24
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +0 -24
- data/webpack/__mocks__/foremanReact/redux/API/index.js +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3d41bcf3b5de41dab8c50751aecf9374fcb0bce44f1e0896011161b25ace53e
|
|
4
|
+
data.tar.gz: 8eb6a78729500fcb4ae06e8a35e452a0ed7a57e8dbc9f1d8ddf46b8c2a341016
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d42639d1e4cb269096eb8cabe57a4337ee9c3e04e6339d2fdf8ac79ccf87188d60293820b5c6c61d79d03ecf40b5c042c2da8e81bb70251dda030cc24c74d1e2
|
|
7
|
+
data.tar.gz: c709b8044deff700aa3c541c6c21a9afdec88a449366785251057c64f1d85f73b9080b4391aca99d7564657509e3ee53c03de90f9f6d98dc9239d9de9a29f053
|
|
@@ -7,7 +7,7 @@ module Api
|
|
|
7
7
|
include InventoryUpload::TaskActions
|
|
8
8
|
include ForemanRhCloud::IopSmartProxyAccess
|
|
9
9
|
|
|
10
|
-
before_action :require_non_iop_smart_proxy, only: [:
|
|
10
|
+
before_action :require_non_iop_smart_proxy, only: [:announce_to_sources]
|
|
11
11
|
|
|
12
12
|
api :GET, "/organizations/:organization_id/rh_cloud/report", N_("Download latest report")
|
|
13
13
|
param :organization_id, Integer, required: true, desc: N_("Set the current organization context for the request")
|
|
@@ -70,10 +70,16 @@ module Api
|
|
|
70
70
|
render json: { message: error.message }, status: :bad_request
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
api :POST, "/rh_cloud/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
api :POST, "/rh_cloud/announce_to_sources", N_("Schedule a task to register in Red Hat Sources for cloud connector")
|
|
74
|
+
param :instance_id, String, required: true, desc: N_("RHC instance ID to register with Red Hat Sources")
|
|
75
|
+
def announce_to_sources
|
|
76
|
+
Setting[:rhc_instance_id] = params[:instance_id]
|
|
77
|
+
|
|
78
|
+
task = ForemanTasks.async_task(InsightsCloud::Async::CloudConnectorAnnounceTask, true)
|
|
79
|
+
|
|
80
|
+
render json: {
|
|
81
|
+
task: task,
|
|
82
|
+
}, status: :accepted
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
end
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
module ForemanInventoryUpload
|
|
2
2
|
class UploadsController < ::ApplicationController
|
|
3
3
|
include InventoryUpload::ReportActions
|
|
4
|
-
include ForemanRhCloud::IopSmartProxyAccess
|
|
5
|
-
|
|
6
|
-
before_action :require_non_iop_smart_proxy, only: [:enable_cloud_connector]
|
|
7
4
|
|
|
8
5
|
def download_file
|
|
9
6
|
filename, file = report_file(params[:organization_id])
|
|
10
7
|
|
|
11
8
|
send_file file, disposition: 'attachment', filename: filename
|
|
12
9
|
end
|
|
13
|
-
|
|
14
|
-
def enable_cloud_connector
|
|
15
|
-
# Set the autoupload to true, since it's required by the feature.
|
|
16
|
-
Setting[:allow_auto_inventory_upload] = true
|
|
17
|
-
|
|
18
|
-
cloud_connector = ForemanRhCloud::CloudConnector.new
|
|
19
|
-
render json: cloud_connector.install.to_json
|
|
20
|
-
end
|
|
21
10
|
end
|
|
22
11
|
end
|
|
@@ -9,7 +9,6 @@ module ForemanInventoryUpload
|
|
|
9
9
|
ipsObfuscationEnabled: Setting[:obfuscate_inventory_ips],
|
|
10
10
|
excludePackagesEnabled: Setting[:exclude_installed_packages],
|
|
11
11
|
allowAutoInsightsMismatchDelete: Setting[:allow_auto_insights_mismatch_delete],
|
|
12
|
-
CloudConnectorStatus: ForemanInventoryUpload::UploadsSettingsController.cloud_connector_status,
|
|
13
12
|
lastSyncTask: last_successful_inventory_sync_task,
|
|
14
13
|
}, status: :ok
|
|
15
14
|
end
|
|
@@ -19,13 +18,6 @@ module ForemanInventoryUpload
|
|
|
19
18
|
index
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
def self.cloud_connector_status
|
|
23
|
-
cloud_connector = ForemanRhCloud::CloudConnector.new
|
|
24
|
-
job = cloud_connector&.latest_job
|
|
25
|
-
return nil unless job
|
|
26
|
-
{ id: job.id, task: ForemanTasks::Task.where(:id => job.task_id).first }
|
|
27
|
-
end
|
|
28
|
-
|
|
29
21
|
def last_successful_inventory_sync_task
|
|
30
22
|
task = ForemanTasks::Task.where(label: 'InventorySync::Async::InventoryFullSync', result: 'success')
|
|
31
23
|
.reorder('ended_at desc').first
|
|
@@ -74,6 +74,9 @@ module ForemanRhCloud
|
|
|
74
74
|
|
|
75
75
|
def register_rhc_instance
|
|
76
76
|
raise Foreman::Exception.new('rhc_instance_id is empty, cannot register RHC to the cloud') if Setting[:rhc_instance_id].empty?
|
|
77
|
+
|
|
78
|
+
return :already_registered if rhc_connection_exists?
|
|
79
|
+
|
|
77
80
|
source_id = satellite_instance_source || create_satellite_instance_source
|
|
78
81
|
|
|
79
82
|
create_response = JSON.parse(
|
|
@@ -95,6 +98,22 @@ module ForemanRhCloud
|
|
|
95
98
|
@satellite_instance_source = create_response['id']
|
|
96
99
|
end
|
|
97
100
|
|
|
101
|
+
def rhc_connection_exists?
|
|
102
|
+
response = JSON.parse(
|
|
103
|
+
execute_cloud_request(
|
|
104
|
+
method: :get,
|
|
105
|
+
url: rhc_connection_url,
|
|
106
|
+
headers: {
|
|
107
|
+
content_type: :json,
|
|
108
|
+
},
|
|
109
|
+
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
|
110
|
+
ssl_client_key: OpenSSL::PKey.read(certs[:key])
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
response['data']&.any?
|
|
115
|
+
end
|
|
116
|
+
|
|
98
117
|
private
|
|
99
118
|
|
|
100
119
|
def sources_url(path)
|
|
@@ -113,6 +132,10 @@ module ForemanRhCloud
|
|
|
113
132
|
sources_url('/sources')
|
|
114
133
|
end
|
|
115
134
|
|
|
135
|
+
def rhc_connection_url
|
|
136
|
+
sources_url("/rhc_connections?filter[rhc_id]=#{Setting[:rhc_instance_id]}")
|
|
137
|
+
end
|
|
138
|
+
|
|
116
139
|
def create_rhc_connections_url
|
|
117
140
|
sources_url('/rhc_connections')
|
|
118
141
|
end
|
data/config/routes.rb
CHANGED
|
@@ -7,8 +7,6 @@ Rails.application.routes.draw do
|
|
|
7
7
|
get 'settings', to: 'uploads_settings#index'
|
|
8
8
|
post 'setting', to: 'uploads_settings#set_advanced_setting'
|
|
9
9
|
|
|
10
|
-
post 'cloud_connector', to: 'uploads#enable_cloud_connector'
|
|
11
|
-
|
|
12
10
|
resources :tasks, only: [:create, :show]
|
|
13
11
|
|
|
14
12
|
get 'status', to: 'cloud_status#index'
|
|
@@ -72,7 +70,7 @@ Rails.application.routes.draw do
|
|
|
72
70
|
end
|
|
73
71
|
|
|
74
72
|
namespace 'rh_cloud' do
|
|
75
|
-
post '
|
|
73
|
+
post 'announce_to_sources', to: 'inventory#announce_to_sources'
|
|
76
74
|
post 'cloud_request', to: 'cloud_request#update'
|
|
77
75
|
get 'advisor_engine_config', to: 'advisor_engine_config#show'
|
|
78
76
|
|
|
@@ -61,6 +61,7 @@ module ForemanRhCloud
|
|
|
61
61
|
ForemanRhCloud::Engine.register_scheduled_task(InventorySync::Async::InventoryScheduledSync, '0 0 * * *')
|
|
62
62
|
ForemanRhCloud::Engine.register_scheduled_task(InsightsCloud::Async::InsightsScheduledSync, '0 0 * * *')
|
|
63
63
|
ForemanRhCloud::Engine.register_scheduled_task(InsightsCloud::Async::InsightsClientStatusAging, '0 0 * * *')
|
|
64
|
+
ForemanRhCloud::Engine.register_scheduled_task(InsightsCloud::Async::CloudConnectorAnnounceTask, '0 0 * * *')
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
rescue ActiveRecord::NoDatabaseError
|
|
@@ -80,12 +81,6 @@ module ForemanRhCloud
|
|
|
80
81
|
host_action_button: false,
|
|
81
82
|
provided_inputs: ['playbook_url', 'report_url', 'correlation_id', 'report_interval']
|
|
82
83
|
)
|
|
83
|
-
RemoteExecutionFeature.register(
|
|
84
|
-
:ansible_configure_cloud_connector,
|
|
85
|
-
N_('Configure Cloud Connector on given hosts'),
|
|
86
|
-
:description => N_('Configure Cloud Connector on given hosts'),
|
|
87
|
-
:proxy_selector_override => ::RemoteExecutionProxySelector::INTERNAL_PROXY
|
|
88
|
-
)
|
|
89
84
|
end
|
|
90
85
|
|
|
91
86
|
# Ideally this code belongs to an initializer. The problem is that Katello controllers are not initialized completely until after the end of the to_prepare blocks
|
|
@@ -31,8 +31,7 @@ module ForemanRhCloud
|
|
|
31
31
|
:generate_foreman_rh_cloud,
|
|
32
32
|
'foreman_inventory_upload/reports': [:generate],
|
|
33
33
|
'foreman_inventory_upload/tasks': [:create],
|
|
34
|
-
'api/v2/rh_cloud/inventory': [:get_hosts, :remove_hosts, :sync_inventory_status, :download_file, :generate_report, :
|
|
35
|
-
'foreman_inventory_upload/uploads': [:enable_cloud_connector],
|
|
34
|
+
'api/v2/rh_cloud/inventory': [:get_hosts, :remove_hosts, :sync_inventory_status, :download_file, :generate_report, :announce_to_sources],
|
|
36
35
|
'foreman_inventory_upload/uploads_settings': [:set_advanced_setting],
|
|
37
36
|
'foreman_inventory_upload/missing_hosts': [:remove_hosts],
|
|
38
37
|
'insights_cloud/settings': [:update],
|
|
@@ -123,6 +122,8 @@ module ForemanRhCloud
|
|
|
123
122
|
role 'ForemanRhCloud Read Only', read_only_permissions, 'Role granting read-only permissions to view
|
|
124
123
|
Insights Compliance, Vulnerability, Advisor, and host inventory'
|
|
125
124
|
|
|
125
|
+
role 'Cloud Connector', [:dispatch_cloud_requests], 'Role granting permission to dispatch cloud connector requests'
|
|
126
|
+
|
|
126
127
|
add_permissions_to_default_roles Role::ORG_ADMIN => plugin_permissions,
|
|
127
128
|
Role::MANAGER => plugin_permissions,
|
|
128
129
|
Role::SYSTEM_ADMIN => plugin_permissions
|
|
@@ -1,39 +1,96 @@
|
|
|
1
1
|
module InsightsCloud
|
|
2
2
|
module Async
|
|
3
3
|
class CloudConnectorAnnounceTask < ::Actions::EntryAction
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
include ::Actions::RecurringAction
|
|
5
|
+
include ::ForemanRhCloud::CertAuth
|
|
6
|
+
include ForemanInventoryUpload::Async::DelayedStart
|
|
7
7
|
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
def plan(immediate = false)
|
|
9
|
+
if ForemanRhCloud.with_iop_smart_proxy?
|
|
10
|
+
logger.debug('Sources announcement skipped: running in IoP mode')
|
|
11
|
+
return
|
|
12
|
+
end
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
if Setting[:rhc_instance_id].blank?
|
|
15
|
+
logger.debug('Sources announcement skipped: rhc_instance_id is not set')
|
|
16
|
+
return
|
|
17
|
+
end
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
unless Setting[:allow_auto_inventory_upload]
|
|
20
|
+
logger.debug(
|
|
21
|
+
'Cloud connector is configured (rhc_instance_id is set) but automatic inventory upload is disabled. ' \
|
|
22
|
+
'Enable the "Automatic inventory upload" setting for full cloud connector functionality.'
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if immediate
|
|
27
|
+
plan_self
|
|
28
|
+
else
|
|
29
|
+
after_delay do
|
|
30
|
+
plan_self
|
|
31
|
+
end
|
|
32
|
+
end
|
|
16
33
|
end
|
|
17
34
|
|
|
18
|
-
def
|
|
35
|
+
def run
|
|
36
|
+
registered = []
|
|
37
|
+
confirmed_by_remediation = []
|
|
38
|
+
already_registered = []
|
|
39
|
+
skipped = []
|
|
40
|
+
failed = {}
|
|
41
|
+
|
|
19
42
|
Organization.unscoped.each do |org|
|
|
43
|
+
unless cert_auth_available?(org)
|
|
44
|
+
skipped << org.name
|
|
45
|
+
next
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if recent_cloud_remediation?(org)
|
|
49
|
+
confirmed_by_remediation << org.name
|
|
50
|
+
next
|
|
51
|
+
end
|
|
52
|
+
|
|
20
53
|
presence = ForemanRhCloud::CloudPresence.new(org, logger)
|
|
21
|
-
presence.announce_to_sources
|
|
54
|
+
result = presence.announce_to_sources
|
|
55
|
+
if result == :already_registered
|
|
56
|
+
already_registered << org.name
|
|
57
|
+
else
|
|
58
|
+
registered << org.name
|
|
59
|
+
end
|
|
22
60
|
rescue StandardError => ex
|
|
23
|
-
logger.warn(ex)
|
|
61
|
+
logger.warn("Failed to announce to Sources for organization #{org.name}: #{ex}")
|
|
62
|
+
logger.debug { ex.backtrace.join("\n") }
|
|
63
|
+
failed[org.name] = ex.message
|
|
24
64
|
end
|
|
25
|
-
end
|
|
26
65
|
|
|
27
|
-
|
|
28
|
-
|
|
66
|
+
parts = []
|
|
67
|
+
parts << "Registered: #{registered.join(', ')}" if registered.any?
|
|
68
|
+
parts << "Already registered: #{already_registered.join(', ')}" if already_registered.any?
|
|
69
|
+
parts << "Already registered (recent cloud remediation): #{confirmed_by_remediation.join(', ')}" if confirmed_by_remediation.any?
|
|
70
|
+
parts << "Skipped (no manifest): #{skipped.join(', ')}" if skipped.any?
|
|
71
|
+
if failed.any?
|
|
72
|
+
failed_details = failed.map { |name, msg| "#{name}: #{msg}" }.join('; ')
|
|
73
|
+
parts << "Failed: #{failed_details}"
|
|
74
|
+
end
|
|
75
|
+
output[:status] = parts.join('. ')
|
|
76
|
+
|
|
77
|
+
error!("Sources announcement failed for: #{failed.keys.join(', ')}") if failed.any?
|
|
29
78
|
end
|
|
30
79
|
|
|
31
|
-
def
|
|
32
|
-
|
|
80
|
+
def recent_cloud_remediation?(org)
|
|
81
|
+
feature = RemoteExecutionFeature.find_by(label: 'rh_cloud_connector_run_playbook')
|
|
82
|
+
return false unless feature
|
|
83
|
+
|
|
84
|
+
JobInvocation.where(remote_execution_feature_id: feature.id)
|
|
85
|
+
.joins(:task)
|
|
86
|
+
.joins(targeting: :hosts)
|
|
87
|
+
.where(hosts: { organization_id: org.id })
|
|
88
|
+
.where('foreman_tasks_tasks.started_at > ?', 24.hours.ago)
|
|
89
|
+
.exists?
|
|
33
90
|
end
|
|
34
91
|
|
|
35
|
-
def
|
|
36
|
-
|
|
92
|
+
def rescue_strategy_for_self
|
|
93
|
+
Dynflow::Action::Rescue::Skip
|
|
37
94
|
end
|
|
38
95
|
|
|
39
96
|
def logger
|
data/package.json
CHANGED
|
@@ -35,20 +35,22 @@ module InventoryUpload::Api
|
|
|
35
35
|
assert_equal test_task.id.to_s, actual_task['id']
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
test '
|
|
39
|
-
|
|
38
|
+
test 'Triggers Sources announcement task' do
|
|
39
|
+
test_task = FactoryBot.create(:some_task)
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
.returns(
|
|
41
|
+
ForemanTasks.expects(:async_task)
|
|
42
|
+
.with(InsightsCloud::Async::CloudConnectorAnnounceTask, true)
|
|
43
|
+
.returns(test_task)
|
|
44
44
|
|
|
45
|
-
post :
|
|
45
|
+
post :announce_to_sources, params: { instance_id: 'test-instance-id' }
|
|
46
46
|
|
|
47
47
|
assert_response :success
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
assert_equal 'test-instance-id', Setting[:rhc_instance_id]
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
actual_task = @response.parsed_body['task']
|
|
52
|
+
assert_not_nil actual_task
|
|
53
|
+
assert_equal test_task.id.to_s, actual_task['id']
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
end
|
|
@@ -1,125 +1,135 @@
|
|
|
1
|
-
require 'json'
|
|
2
1
|
require 'test_plugin_helper'
|
|
3
2
|
require 'foreman_tasks/test_helpers'
|
|
4
|
-
require "#{ForemanTasks::Engine.root}/test/support/dummy_dynflow_action"
|
|
5
3
|
|
|
6
4
|
class CloudConnectorAnnounceTaskTest < ActiveSupport::TestCase
|
|
7
5
|
include Dynflow::Testing::Factories
|
|
8
6
|
|
|
9
7
|
setup do
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
)
|
|
8
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
9
|
+
.stubs(:recent_cloud_remediation?).returns(false)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
teardown do
|
|
13
|
+
ForemanRhCloud.unstub(:with_iop_smart_proxy?)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
test 'announces to sources for all organizations when rhc_instance_id is set' do
|
|
17
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
18
|
+
|
|
19
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
20
|
+
.stubs(:cert_auth_available?).returns(true)
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
ForemanRhCloud::CloudPresence.any_instance
|
|
23
|
+
.expects(:announce_to_sources)
|
|
24
|
+
.times(Organization.unscoped.count)
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
27
|
+
action = run_action(action)
|
|
28
|
+
|
|
29
|
+
status = action.output[:status].to_s
|
|
30
|
+
assert_match(/Registered:|Already registered:/, status)
|
|
31
|
+
refute_match(/Skipped/, status)
|
|
32
|
+
refute_match(/Failed/, status)
|
|
21
33
|
end
|
|
22
34
|
|
|
23
|
-
test '
|
|
24
|
-
|
|
35
|
+
test 'skips when rhc_instance_id is not set' do
|
|
36
|
+
Setting[:rhc_instance_id] = nil
|
|
37
|
+
|
|
38
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
25
39
|
|
|
26
|
-
action
|
|
27
|
-
finalize_action(action)
|
|
40
|
+
assert_empty action.execution_plan.planned_run_steps
|
|
28
41
|
end
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
:required => true)
|
|
57
|
-
job_template.template_inputs << report_interval_input = FactoryBot.build(:template_input,
|
|
58
|
-
:name => 'report_interval',
|
|
59
|
-
:input_type => 'user',
|
|
60
|
-
:required => true)
|
|
61
|
-
|
|
62
|
-
template_invocation = FactoryBot.build(:template_invocation,
|
|
63
|
-
:template => job_template,
|
|
64
|
-
:job_invocation => job_invocation)
|
|
65
|
-
|
|
66
|
-
template_invocation.input_values << FactoryBot.create(
|
|
67
|
-
:template_invocation_input_value,
|
|
68
|
-
:template_invocation => template_invocation,
|
|
69
|
-
:template_input => playbook_url_input,
|
|
70
|
-
:value => 'http://example.com/TEST_PLAYBOOK'
|
|
71
|
-
)
|
|
72
|
-
template_invocation.input_values << FactoryBot.create(
|
|
73
|
-
:template_invocation_input_value,
|
|
74
|
-
:template_invocation => template_invocation,
|
|
75
|
-
:template_input => report_url_input,
|
|
76
|
-
:value => 'http://example.com/TEST_REPORT'
|
|
77
|
-
)
|
|
78
|
-
template_invocation.input_values << FactoryBot.create(
|
|
79
|
-
:template_invocation_input_value,
|
|
80
|
-
:template_invocation => template_invocation,
|
|
81
|
-
:template_input => correlation_id_input,
|
|
82
|
-
:value => 'TEST_CORRELATION'
|
|
83
|
-
)
|
|
84
|
-
template_invocation.input_values << FactoryBot.create(
|
|
85
|
-
:template_invocation_input_value,
|
|
86
|
-
:template_invocation => template_invocation,
|
|
87
|
-
:template_input => report_interval_input,
|
|
88
|
-
:value => '1'
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
@host1 = FactoryBot.create(:host, :with_insights_hits, name: 'host1')
|
|
92
|
-
@host1.insights.uuid = 'TEST_UUID1'
|
|
93
|
-
@host1.insights.save!
|
|
94
|
-
@host2 = FactoryBot.create(:host, :with_insights_hits, name: 'host2')
|
|
95
|
-
@host2.insights.uuid = 'TEST_UUID2'
|
|
96
|
-
@host2.insights.save!
|
|
97
|
-
|
|
98
|
-
targeting = FactoryBot.create(:targeting, hosts: [@host1, @host2])
|
|
99
|
-
job_invocation.targeting = targeting
|
|
100
|
-
job_invocation.save!
|
|
101
|
-
|
|
102
|
-
job_invocation.template_invocations << FactoryBot.create(
|
|
103
|
-
:template_invocation,
|
|
104
|
-
run_host_job_task: FactoryBot.create(:dynflow_task),
|
|
105
|
-
host_id: @host1.id
|
|
106
|
-
)
|
|
107
|
-
job_invocation.template_invocations << FactoryBot.create(
|
|
108
|
-
:template_invocation,
|
|
109
|
-
run_host_job_task: FactoryBot.create(:dynflow_task),
|
|
110
|
-
host_id: @host2.id
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
fake_output = (1..5).map do |i|
|
|
114
|
-
{ 'timestamp' => (Time.now - (5 - i)).to_f, 'output' => "#{i}\n" }
|
|
115
|
-
end
|
|
116
|
-
Support::DummyDynflowAction.any_instance.stubs(:live_output).returns(fake_output)
|
|
117
|
-
Support::DummyDynflowAction.any_instance.stubs(:exit_status).returns(0)
|
|
43
|
+
test 'skips when rhc_instance_id is empty string' do
|
|
44
|
+
Setting[:rhc_instance_id] = ''
|
|
45
|
+
|
|
46
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
47
|
+
|
|
48
|
+
assert_empty action.execution_plan.planned_run_steps
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
test 'skips when in IoP mode' do
|
|
52
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
53
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
54
|
+
|
|
55
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
56
|
+
|
|
57
|
+
assert_empty action.execution_plan.planned_run_steps
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
test 'skips organizations without a manifest' do
|
|
61
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
62
|
+
|
|
63
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
64
|
+
.stubs(:cert_auth_available?).returns(false)
|
|
65
|
+
|
|
66
|
+
ForemanRhCloud::CloudPresence.any_instance
|
|
67
|
+
.expects(:announce_to_sources)
|
|
68
|
+
.never
|
|
118
69
|
|
|
119
|
-
|
|
70
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
71
|
+
action = run_action(action)
|
|
72
|
+
|
|
73
|
+
status = action.output[:status].to_s
|
|
74
|
+
assert_match(/Skipped \(no manifest\):/, status)
|
|
75
|
+
refute_match(/Registered/, status)
|
|
76
|
+
refute_match(/Failed/, status)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
test 'still runs when allow_auto_inventory_upload is disabled' do
|
|
80
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
81
|
+
Setting[:allow_auto_inventory_upload] = false
|
|
82
|
+
|
|
83
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
84
|
+
.stubs(:cert_auth_available?).returns(true)
|
|
85
|
+
|
|
86
|
+
ForemanRhCloud::CloudPresence.any_instance
|
|
87
|
+
.expects(:announce_to_sources)
|
|
88
|
+
.times(Organization.unscoped.count)
|
|
89
|
+
|
|
90
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
91
|
+
action = run_action(action)
|
|
92
|
+
|
|
93
|
+
assert_match(/Registered:|Already registered:/, action.output[:status].to_s)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test 'skips orgs with recent cloud remediation jobs' do
|
|
97
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
98
|
+
|
|
99
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
100
|
+
.stubs(:cert_auth_available?).returns(true)
|
|
101
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
102
|
+
.stubs(:recent_cloud_remediation?).returns(true)
|
|
103
|
+
|
|
104
|
+
ForemanRhCloud::CloudPresence.any_instance
|
|
105
|
+
.expects(:announce_to_sources)
|
|
106
|
+
.never
|
|
107
|
+
|
|
108
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
109
|
+
action = run_action(action)
|
|
110
|
+
|
|
111
|
+
status = action.output[:status].to_s
|
|
112
|
+
assert_match(/Already registered \(recent cloud remediation\):/, status)
|
|
113
|
+
refute_match(/\bRegistered:/, status)
|
|
120
114
|
end
|
|
121
115
|
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
test 'continues processing other orgs when one fails and task errors' do
|
|
117
|
+
Setting[:rhc_instance_id] = 'test-rhc-id'
|
|
118
|
+
|
|
119
|
+
InsightsCloud::Async::CloudConnectorAnnounceTask.any_instance
|
|
120
|
+
.stubs(:cert_auth_available?).returns(true)
|
|
121
|
+
|
|
122
|
+
call_count = 0
|
|
123
|
+
ForemanRhCloud::CloudPresence.any_instance.stubs(:announce_to_sources).with do
|
|
124
|
+
call_count += 1
|
|
125
|
+
raise(StandardError.new('API error')) if call_count == 1
|
|
126
|
+
true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask)
|
|
130
|
+
|
|
131
|
+
error = assert_raises(StandardError) { run_action(action) }
|
|
132
|
+
assert_match(/Sources announcement failed for:/, error.message)
|
|
133
|
+
assert_equal Organization.unscoped.count, call_count
|
|
124
134
|
end
|
|
125
135
|
end
|