foreman_rh_cloud 10.0.5 → 10.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfabc05d2ec5effb2a007e85471ba31e9d0067495fcbf52d07bb37b4f3c1a15c
4
- data.tar.gz: c5f0db2ca590193d014d69358882c0abf98adf523158ceec65536391b454ca23
3
+ metadata.gz: bcf5c802bcf566375518a4f83d5a5fae3ec98c5554e89dea57af748af526f998
4
+ data.tar.gz: 1c8d77163d1cac3161813bf9aab5f70f3a8496ce9351a5e2a4d071aaecfb1ad6
5
5
  SHA512:
6
- metadata.gz: fd794c63904449ceb0f7b4b2d02de6e8b97cdde7745c24a5d6a02d52047fc036d3b995e11bca5aa0cf241a8b2def0f6efda15e810cd2dfdb9a5060e1cfe984bf
7
- data.tar.gz: 73d24b976d3a00150696e403d5bd5f134faa1c60ca8b75063a0ac12e57da85427c6a301faf96d502e736f515c60e6bb6b25627c056909698b3fe9fac17751da7
6
+ metadata.gz: 807e09c7f560217178221cf3a2c7eda52aee500ea50fe18d56b86f53cffee23d0d7ca50e6b4bd174a7b3c038273158a41cb6c5d60339fd121e5d0c06e0010788
7
+ data.tar.gz: ad3a808a270922e52e25778f9101db3a358fbe99b0ded5f01fab67c5d1a398cc7c997ed816f909b528af579a47f44f5b97a9a6c5621d4fa97d59dc8f43851a3c
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: Insights -> Inventory Upload -> select the organization -> Generate and upload report
19
19
 
20
20
  From command-line:
21
21
 
@@ -38,7 +38,7 @@ From command-line:
38
38
 
39
39
  #### Fetch hosts remediation data
40
40
 
41
- In UI: Configure -> Insights -> Sync now
41
+ In UI: Insights -> Recommendations -> Sync recommendations (under the vertical ellipsis)
42
42
 
43
43
  From command-line:
44
44
 
@@ -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: Insights -> Inventory Upload -> Sync all inventory status
50
50
 
51
51
  From command-line:
52
52
 
@@ -16,29 +16,41 @@ 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::Exceptions::Timeout => e
22
+ response_obj = e.response.presence || e.exception
23
+ return render json: { message: response_obj.to_s, error: response_obj.to_s }, status: :gateway_timeout
24
+ rescue RestClient::Unauthorized => e
25
+ logger.warn("Forwarding request auth error: #{e}")
26
+ message = 'Authentication to the Insights Service failed.'
27
+ return render json: { message: message, error: message }, status: :unauthorized
28
+ rescue RestClient::NotModified => e
29
+ logger.info("Forwarding request not modified: #{e}")
30
+ message = 'Cloud request not modified'
31
+ return render json: { message: message, error: message }, status: :not_modified
32
+ rescue RestClient::ExceptionWithResponse => e
33
+ response_obj = e.response.presence || e.exception
34
+ code = response_obj.try(:code) || response_obj.try(:http_code) || 500
35
+ message = 'Cloud request failed'
20
36
 
21
- return render json: { message: @cloud_response.to_s }, status: :gateway_timeout if @cloud_response.is_a?(RestClient::Exceptions::OpenTimeout)
22
-
23
- if @cloud_response.code == 401
24
- return render json: {
25
- :message => 'Authentication to the Insights Service failed.',
26
- :headers => {},
27
- }, status: :bad_gateway
28
- end
29
-
30
- if @cloud_response.code >= 300
31
37
  return render json: {
32
- :message => 'Cloud request failed',
38
+ :message => message,
39
+ :error => response_obj.to_s,
33
40
  :headers => {},
34
- :response => @cloud_response,
35
- }, status: @cloud_response.code
41
+ :response => response_obj,
42
+ }, status: code
43
+ rescue StandardError => e
44
+ # Catch any other exceptions here, such as Errno::ECONNREFUSED
45
+ logger.warn("Cloud request failed with exception: #{e}")
46
+ return render json: { error: e.to_s }, status: :bad_gateway
36
47
  end
37
48
 
38
49
  # Append redhat-specific headers
39
50
  @cloud_response.headers.each do |key, value|
40
51
  assign_header(response, @cloud_response, key, false) if key.to_s.start_with?('x_rh_')
41
52
  end
53
+
42
54
  # Append general headers
43
55
  assign_header(response, @cloud_response, :x_resource_count, true)
44
56
  headers[Rack::ETAG] = @cloud_response.headers[:etag]
@@ -48,8 +60,8 @@ module InsightsCloud::Api
48
60
  # content type
49
61
  send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
50
62
  elsif @cloud_response.headers[:content_type] =~ /zip/
51
- # if there is no Content-Disposition, but the content type is binary according the content type,
52
- # forward the request as binry too
63
+ # If there is no Content-Disposition, but the content type is binary according to Content-Type, send the raw data
64
+ # with proper content type
53
65
  send_data @cloud_response, type: @cloud_response.headers[:content_type]
54
66
  else
55
67
  render json: @cloud_response, status: @cloud_response.code
@@ -13,9 +13,15 @@ module ForemanRhCloud
13
13
  logger.debug("Response headers for request url #{final_params[:url]} are: #{response.headers}")
14
14
 
15
15
  response
16
- rescue RestClient::Exception => ex
17
- logger.debug("Failed response with code #{ex.http_code} headers for request url #{final_params[:url]} are: #{ex.http_headers} and body: #{ex.http_body}")
18
- raise ex
16
+ rescue RestClient::Exceptions::Timeout => ex
17
+ logger.debug("Timeout exception raised for request url #{final_params[:url]}: #{ex}")
18
+ raise
19
+ rescue RestClient::ExceptionWithResponse => ex
20
+ logger.debug("Response headers for request url #{final_params[:url]} with status code #{ex.http_code} are: #{ex.http_headers} and body: #{ex.http_body}")
21
+ raise
22
+ rescue StandardError => ex
23
+ logger.debug("Exception raised for request url #{final_params[:url]}: #{ex}")
24
+ raise
19
25
  end
20
26
  end
21
27
  end
@@ -17,8 +17,6 @@ module ForemanRhCloud
17
17
  logger.debug("Sending request to: #{request_opts[:url]}")
18
18
 
19
19
  execute_cloud_request(request_opts)
20
- rescue RestClient::ExceptionWithResponse => error_response
21
- error_response.response.presence || error_response.exception
22
20
  end
23
21
 
24
22
  def prepare_request_opts(original_request, forward_payload, forward_params, certs)
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '10.0.5'.freeze
2
+ VERSION = '10.0.6'.freeze
3
3
  end
@@ -9,10 +9,11 @@ module InsightsCloud
9
9
 
10
10
  def plan(organizations)
11
11
  organizations = organizations.select do |organization|
12
- if cert_auth_available?(organization)
12
+ checker = ::Katello::UpstreamConnectionChecker.new(organization)
13
+ if cert_auth_available?(organization) && !organization.manifest_expired? && checker.can_connect?
13
14
  true
14
15
  else
15
- logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
16
+ logger.info("A manifest is not available for org: #{organization.name}, or it has expired, or been deleted. skipping insights sync")
16
17
  false
17
18
  end
18
19
  end
@@ -20,19 +21,23 @@ module InsightsCloud
20
21
  sequence do
21
22
  # This can be turned off when we enable automatic status syncs
22
23
  # This step will query cloud inventory to retrieve inventory uuids for each host
23
- plan_hosts_sync(organizations)
24
- plan_self(organization_ids: organizations.map(&:id))
25
- concurrence do
26
- plan_rules_sync(organizations)
27
- plan_notifications
24
+ valid_organizations = organizations.reject(&:manifest_expired?)
25
+ if valid_organizations.any?
26
+ plan_hosts_sync(organizations)
27
+ plan_self(organization_ids: organizations.map(&:id))
28
+ concurrence do
29
+ plan_rules_sync(organizations)
30
+ plan_notifications
31
+ end
28
32
  end
29
33
  end
30
34
  end
31
35
 
32
36
  def try_execute
33
37
  organizations.each do |organization|
34
- unless cert_auth_available?(organization)
35
- logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
38
+ checker = ::Katello::UpstreamConnectionChecker.new(organization)
39
+ if !cert_auth_available?(organization) && organization.manifest_expired && !checker.can_connect?
40
+ logger.info("A manifest is not available for org: #{organization.name}, or it has expired, or been deleted. skipping insights sync")
36
41
  next
37
42
  end
38
43
 
@@ -13,7 +13,11 @@ module InsightsCloud
13
13
  InsightsResolution.delete_all
14
14
  rule_ids = relevant_rules
15
15
  Organization.all.each do |organization|
16
- next if !cert_auth_available?(organization) || organization.manifest_expired?
16
+ checker = ::Katello::UpstreamConnectionChecker.new(organization)
17
+ if !cert_auth_available?(organization) || organization.manifest_expired? || !checker.can_connect?
18
+ logger.info("A manifest is not available for org: #{organization.name}, or it has expired, or been deleted. skipping resolutions sync")
19
+ next
20
+ end
17
21
  api_response = query_insights_resolutions(rule_ids, organization) unless rule_ids.empty?
18
22
  written_rules = write_resolutions(api_response) if api_response
19
23
  rule_ids -= Array(written_rules)
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "10.0.5",
3
+ "version": "10.0.6",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -96,13 +96,46 @@ module InsightsCloud::Api
96
96
  assert_equal net_http_resp[:content_type], @response.headers['Content-Type']
97
97
  end
98
98
 
99
+ test "should handle StandardError" do
100
+ error_message = "Connection refused"
101
+ ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(Errno::ECONNREFUSED.new)
102
+
103
+ get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
104
+ assert_equal 502, @response.status
105
+ body = JSON.parse(@response.body)
106
+ assert_equal error_message, body['error']
107
+ end
108
+
109
+ test "should handle 304 cloud" do
110
+ net_http_resp = Net::HTTPResponse.new(1.0, 304, "Not Modified")
111
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
112
+
113
+ ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::NotModified.new(res))
114
+
115
+ get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
116
+ assert_equal 304, @response.status
117
+ assert_equal 'Cloud request not modified', JSON.parse(@response.body)['message']
118
+ end
119
+
120
+ test "should handle RestClient::Exceptions::Timeout" do
121
+ timeout_message = "execution expired"
122
+ ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::Exceptions::Timeout.new(timeout_message))
123
+
124
+ get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
125
+ assert_equal 504, @response.status
126
+ body = JSON.parse(@response.body)
127
+ assert_equal timeout_message, body['message']
128
+ assert_equal timeout_message, body['error']
129
+ end
130
+
99
131
  test "should handle failed authentication to cloud" do
100
132
  net_http_resp = Net::HTTPResponse.new(1.0, 401, "Unauthorized")
101
133
  res = RestClient::Response.create(@body, net_http_resp, @http_req)
102
- ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:forward_request).returns(res)
134
+
135
+ ::ForemanRhCloud::CloudRequestForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::Unauthorized.new(res))
103
136
 
104
137
  get :forward_request, params: { "path" => "platform/module-update-router/v1/channel" }
105
- assert_equal 502, @response.status
138
+ assert_equal 401, @response.status
106
139
  assert_equal 'Authentication to the Insights Service failed.', JSON.parse(@response.body)['message']
107
140
  end
108
141
 
@@ -65,6 +65,8 @@ class InsightsFullSyncTest < ActiveSupport::TestCase
65
65
  end
66
66
 
67
67
  test 'Hits data is replaced with data from cloud' do
68
+ Organization.any_instance.stubs(:manifest_expired?).returns(false)
69
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
68
70
  InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(@hits)
69
71
 
70
72
  InsightsCloud::Async::InsightsFullSync.any_instance.expects(:plan_hosts_sync)
@@ -79,7 +81,31 @@ class InsightsFullSyncTest < ActiveSupport::TestCase
79
81
  assert_equal 1, @host2.insights.hits.count
80
82
  end
81
83
 
84
+ test 'Manifest is expired do not run task steps' do
85
+ Organization.any_instance.stubs(:manifest_expired?).returns(true)
86
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
87
+
88
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).never
89
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:plan_hosts_sync).never
90
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:plan_self).never
91
+
92
+ ForemanTasks.sync_task(InsightsCloud::Async::InsightsFullSync, [@host1.organization])
93
+ end
94
+
95
+ test 'Manifest is deleted do not run task steps' do
96
+ Organization.any_instance.stubs(:manifest_expired?).returns(false)
97
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(false)
98
+
99
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).never
100
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:plan_hosts_sync).never
101
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:plan_self).never
102
+
103
+ ForemanTasks.sync_task(InsightsCloud::Async::InsightsFullSync, [@host1.organization])
104
+ end
105
+
82
106
  test 'Hits counters are reset correctly' do
107
+ Organization.any_instance.stubs(:manifest_expired?).returns(false)
108
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
83
109
  InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(@hits).twice
84
110
 
85
111
  InsightsCloud::Async::InsightsFullSync.any_instance.stubs(:plan_hosts_sync)
@@ -97,6 +123,8 @@ class InsightsFullSyncTest < ActiveSupport::TestCase
97
123
  end
98
124
 
99
125
  test 'Hits ignoring non-existent hosts' do
126
+ Organization.any_instance.stubs(:manifest_expired?).returns(false)
127
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
100
128
  hits_json = <<-HITS_JSON
101
129
  [
102
130
  {
@@ -73,6 +73,7 @@ class InsightsResolutionsSyncTest < ActiveSupport::TestCase
73
73
  end
74
74
 
75
75
  test 'Resolutions data is replaced with data from cloud' do
76
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
76
77
  InsightsCloud::Async::InsightsResolutionsSync.any_instance.stubs(:query_insights_resolutions).returns(@resolutions)
77
78
 
78
79
  ForemanTasks.sync_task(InsightsCloud::Async::InsightsResolutionsSync)
@@ -82,7 +83,28 @@ class InsightsResolutionsSyncTest < ActiveSupport::TestCase
82
83
  assert_equal 2, @rule.resolutions.count
83
84
  end
84
85
 
86
+ test 'Manifest is deleted do not run task steps' do
87
+ Organization.any_instance.stubs(:manifest_expired?).returns(false)
88
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(false)
89
+ InsightsCloud::Async::InsightsResolutionsSync.any_instance.expects(:query_insights_resolutions).never
90
+
91
+ ForemanTasks.sync_task(InsightsCloud::Async::InsightsResolutionsSync)
92
+
93
+ assert_equal 0, InsightsResolution.all.count
94
+ end
95
+
96
+ test 'Manifest is expired do not run task steps' do
97
+ Organization.any_instance.stubs(:manifest_expired?).returns(true)
98
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
99
+ InsightsCloud::Async::InsightsResolutionsSync.any_instance.expects(:query_insights_resolutions).never
100
+
101
+ ForemanTasks.sync_task(InsightsCloud::Async::InsightsResolutionsSync)
102
+
103
+ assert_equal 0, InsightsResolution.all.count
104
+ end
105
+
85
106
  test 'Skips pinging the cloud if no rule ids were found' do
107
+ Katello::UpstreamConnectionChecker.any_instance.stubs(:can_connect?).returns(true)
86
108
  InsightsCloud::Async::InsightsResolutionsSync.any_instance.expects(:query_insights_resolutions).never
87
109
  InsightsRule.all.delete_all
88
110
 
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: 10.0.5
4
+ version: 10.0.6
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: 2025-04-07 00:00:00.000000000 Z
11
+ date: 2025-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: foreman_ansible