topological_inventory-providers-common 1.0.12 → 2.0.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/CHANGELOG.md +8 -4
- data/lib/topological_inventory/providers/common.rb +0 -2
- data/lib/topological_inventory/providers/common/logging.rb +6 -3
- data/lib/topological_inventory/providers/common/mixins/sources_api.rb +58 -0
- data/lib/topological_inventory/providers/common/mixins/topology_api.rb +26 -0
- data/lib/topological_inventory/providers/common/mixins/x_rh_headers.rb +24 -0
- data/lib/topological_inventory/providers/common/operations/source.rb +119 -144
- data/lib/topological_inventory/providers/common/sources_api_client.rb +92 -0
- data/lib/topological_inventory/providers/common/topology_api_client.rb +43 -0
- data/lib/topological_inventory/providers/common/version.rb +1 -1
- data/spec/support/shared/availability_check.rb +1 -1
- metadata +7 -7
- data/lib/topological_inventory/providers/common/operations/endpoint_client.rb +0 -65
- data/lib/topological_inventory/providers/common/operations/processor.rb +0 -135
- data/lib/topological_inventory/providers/common/operations/sources_api_client.rb +0 -94
- data/lib/topological_inventory/providers/common/operations/topology_api_client.rb +0 -28
- data/spec/topological_inventory/providers/common/operations/processor_spec.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 134e945b201072b8bdd7fc6af73b04a6f60698da831ef3989ab973453a1a5159
|
4
|
+
data.tar.gz: 20e4f260c411551572b557f4e4454fdc03c9e3b2ac9c8f5997e6600780298c1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a847566f6fb20e9518faef660c626788e6afd20d26cec28a5899e645c68cedd7c017974d0cb1c3c2524253007386b9728a1bb67a0f0a9101fe62bd388f03ccb
|
7
|
+
data.tar.gz: 6e786659b1bf913fe1e22d9c0618986d03dc4bc169d782e446ecd089b97a136b639f83be85c562006dccde83a8d025b102863b565aa571746767fa292e4dae89
|
data/CHANGELOG.md
CHANGED
@@ -4,17 +4,20 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [2.0.0]
|
8
|
+
Operations/API clients refactoring
|
9
|
+
|
7
10
|
## [1.0.12] - 2020-10-01
|
8
11
|
Add Operations Async Worker class #55
|
9
12
|
|
10
|
-
## [1.0.11]
|
13
|
+
## [1.0.11] - 2020-09-04
|
11
14
|
Make Collector Poll Time a parameter so we can tweak the collection interval #51
|
12
15
|
|
13
|
-
## [1.0.10]
|
16
|
+
## [1.0.10] - 2020-08-26
|
14
17
|
Add HealthCheck class for operations workers #48
|
15
18
|
Set the LOG_LEVEL if present #50
|
16
19
|
|
17
|
-
## [1.0.9]
|
20
|
+
## [1.0.9] - 2020-08-17
|
18
21
|
Added refresh-type to save and sweep inventory #45
|
19
22
|
|
20
23
|
## [1.0.8] - 2020-08-12
|
@@ -59,7 +62,8 @@ manageiq-loggers to >= 0.4.2 #20
|
|
59
62
|
## [1.0.0] - 2020-03-19
|
60
63
|
### Initial release to rubygems.org
|
61
64
|
|
62
|
-
[Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/
|
65
|
+
[Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.0.0...HEAD
|
66
|
+
[2.0.0]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.12...v2.0.0
|
63
67
|
[1.0.12]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.11...v1.0.12
|
64
68
|
[1.0.11]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.10...v1.0.11
|
65
69
|
[1.0.10]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.9...v1.0.10
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require "topological_inventory/providers/common/version"
|
2
2
|
require "topological_inventory/providers/common/logging"
|
3
|
-
require "topological_inventory/providers/common/operations/processor"
|
4
|
-
require "topological_inventory/providers/common/operations/endpoint_client"
|
5
3
|
require "topological_inventory/providers/common/operations/health_check"
|
6
4
|
require "topological_inventory/providers/common/collectors_pool"
|
7
5
|
require "topological_inventory/providers/common/collector"
|
@@ -23,11 +23,14 @@ module TopologicalInventory
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def availability_check(message, severity = :info)
|
26
|
-
|
26
|
+
send("#{severity}_ext", "Source#availability_check", message)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
%w[debug info warn error fatal].each do |severity|
|
30
|
+
define_method("#{severity}_ext".to_sym) do |prefix, message|
|
31
|
+
ext_message = [prefix, message].compact.join(' - ')
|
32
|
+
send(severity, ext_message)
|
33
|
+
end
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "topological_inventory/providers/common/sources_api_client"
|
2
|
+
|
3
|
+
module TopologicalInventory
|
4
|
+
module Providers
|
5
|
+
module Common
|
6
|
+
module Mixins
|
7
|
+
module SourcesApi
|
8
|
+
AUTH_NOT_NECESSARY = "n/a".freeze
|
9
|
+
|
10
|
+
def sources_api
|
11
|
+
@sources_api ||= TopologicalInventory::Providers::Common::SourcesApiClient.new(identity)
|
12
|
+
end
|
13
|
+
|
14
|
+
def endpoint
|
15
|
+
@endpoint ||= sources_api.fetch_default_endpoint(source_id)
|
16
|
+
rescue => e
|
17
|
+
logger.error_ext(operation, "Failed to fetch Endpoint for Source #{source_id}: #{e.message}")
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def authentication
|
22
|
+
@authentication ||= if endpoint.receptor_node.present?
|
23
|
+
AUTH_NOT_NECESSARY
|
24
|
+
else
|
25
|
+
sources_api.fetch_authentication(source_id, endpoint)
|
26
|
+
end
|
27
|
+
rescue => e
|
28
|
+
logger.error_ext(operation, "Failed to fetch Authentication for Source #{source_id}: #{e.message}")
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def application
|
33
|
+
@application ||= sources_api.fetch_application(source_id)
|
34
|
+
rescue => e
|
35
|
+
logger.error_ext(operation, "Failed to fetch Application for Source #{source_id}: #{e.message}")
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_premise?
|
40
|
+
@on_premise ||= endpoint&.receptor_node.to_s.strip.present?
|
41
|
+
end
|
42
|
+
|
43
|
+
def verify_ssl_mode
|
44
|
+
endpoint&.verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
45
|
+
end
|
46
|
+
|
47
|
+
def full_hostname(endpoint)
|
48
|
+
if on_premise?
|
49
|
+
"receptor://#{endpoint.receptor_node}"
|
50
|
+
else
|
51
|
+
endpoint.host.tap { |host| host << ":#{endpoint.port}" if endpoint.port }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "topological_inventory/providers/common/topology_api_client"
|
2
|
+
|
3
|
+
module TopologicalInventory
|
4
|
+
module Providers
|
5
|
+
module Common
|
6
|
+
module Mixins
|
7
|
+
module TopologyApi
|
8
|
+
# @identity attr_reader is expected
|
9
|
+
def topology_api
|
10
|
+
@topology_api ||= TopologicalInventory::Providers::Common::TopologyApiClient.new(identity)
|
11
|
+
end
|
12
|
+
|
13
|
+
def update_task(task_id, source_id: nil, state:, status:, target_type: nil, target_source_ref: nil, context: nil)
|
14
|
+
topology_api.update_task(task_id,
|
15
|
+
:source_id => source_id,
|
16
|
+
:state => state,
|
17
|
+
:status => status,
|
18
|
+
:target_type => target_type,
|
19
|
+
:target_source_ref => target_source_ref,
|
20
|
+
:context => context)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TopologicalInventory
|
2
|
+
module Providers
|
3
|
+
module Common
|
4
|
+
module Mixins
|
5
|
+
module XRhHeaders
|
6
|
+
def account_number_by_identity(identity)
|
7
|
+
return @account_number if @account_number
|
8
|
+
return if identity.try(:[], 'x-rh-identity').nil?
|
9
|
+
|
10
|
+
identity_hash = JSON.parse(Base64.decode64(identity['x-rh-identity']))
|
11
|
+
@account_number = identity_hash.dig('identity', 'account_number')
|
12
|
+
rescue JSON::ParserError => e
|
13
|
+
logger.error_ext(operation, "Failed to parse identity header: #{e.message}")
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def identity_by_account_number(account_number)
|
18
|
+
@identity ||= {"x-rh-identity" => Base64.strict_encode64({"identity" => {"account_number" => account_number, "user" => {"is_org_admin" => true}}}.to_json)}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,194 +1,169 @@
|
|
1
1
|
require "topological_inventory/providers/common/logging"
|
2
2
|
require "active_support/core_ext/numeric/time"
|
3
|
-
require "topological_inventory/providers/common/
|
3
|
+
require "topological_inventory/providers/common/mixins/sources_api"
|
4
|
+
require "topological_inventory/providers/common/mixins/x_rh_headers"
|
4
5
|
|
5
6
|
module TopologicalInventory
|
6
7
|
module Providers
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
module Common
|
9
|
+
module Operations
|
10
|
+
class Source
|
11
|
+
include Logging
|
12
|
+
include Mixins::SourcesApi
|
13
|
+
include Mixins::XRhHeaders
|
11
14
|
|
12
|
-
|
15
|
+
STATUS_AVAILABLE, STATUS_UNAVAILABLE = %w[available unavailable].freeze
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
ERROR_MESSAGES = {
|
18
|
+
:authentication_not_found => "Authentication not found in Sources API",
|
19
|
+
:endpoint_or_application_not_found => "Endpoint or Application not found in Sources API",
|
20
|
+
}.freeze
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
LAST_CHECKED_AT_THRESHOLD = 5.minutes.freeze
|
23
|
+
AUTH_NOT_NECESSARY = "n/a".freeze
|
21
24
|
|
22
|
-
|
25
|
+
attr_accessor :identity, :operation, :params, :request_context, :source_id, :account_number
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
27
|
+
def initialize(params = {}, request_context = nil)
|
28
|
+
self.operation = 'Source'
|
29
|
+
self.params = params
|
30
|
+
self.request_context = request_context
|
31
|
+
self.source_id = params['source_id']
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
+
self.account_number = params['external_tenant']
|
34
|
+
self.identity = identity_by_account_number(account_number)
|
35
|
+
end
|
33
36
|
|
34
|
-
|
37
|
+
def availability_check
|
38
|
+
self.operation += '#availability_check'
|
35
39
|
|
36
|
-
|
40
|
+
return if params_missing?
|
37
41
|
|
38
|
-
|
42
|
+
return if checked_recently?
|
39
43
|
|
40
|
-
|
41
|
-
end
|
44
|
+
status, error_message = connection_status
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
def required_params
|
46
|
-
%w[source_id]
|
47
|
-
end
|
46
|
+
update_source_and_subresources(status, error_message)
|
48
47
|
|
49
|
-
|
50
|
-
is_missing = false
|
51
|
-
required_params.each do |attr|
|
52
|
-
if (is_missing = params[attr].blank?)
|
53
|
-
logger.availability_check("Missing #{attr} for the availability_check request [Source ID: #{source_id}]", :error)
|
54
|
-
break
|
55
|
-
end
|
48
|
+
logger.availability_check("Completed: Source #{source_id} is #{status}")
|
56
49
|
end
|
57
50
|
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def checked_recently?
|
62
|
-
checked_recently = if endpoint.present?
|
63
|
-
endpoint.last_checked_at.present? && endpoint.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
|
64
|
-
elsif application.present?
|
65
|
-
application.last_checked_at.present? && application.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
|
66
|
-
end
|
51
|
+
private
|
67
52
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
53
|
+
def required_params
|
54
|
+
%w[source_id]
|
55
|
+
end
|
72
56
|
|
73
|
-
|
74
|
-
|
75
|
-
|
57
|
+
def params_missing?
|
58
|
+
is_missing = false
|
59
|
+
required_params.each do |attr|
|
60
|
+
if (is_missing = params[attr].blank?)
|
61
|
+
logger.availability_check("Missing #{attr} for the availability_check request [Source ID: #{source_id}]", :error)
|
62
|
+
break
|
63
|
+
end
|
64
|
+
end
|
76
65
|
|
77
|
-
|
78
|
-
if endpoint
|
79
|
-
endpoint_connection_check
|
80
|
-
elsif application
|
81
|
-
application_connection_check
|
66
|
+
is_missing
|
82
67
|
end
|
83
|
-
end
|
84
68
|
|
85
|
-
|
86
|
-
|
69
|
+
def checked_recently?
|
70
|
+
checked_recently = if endpoint.present?
|
71
|
+
endpoint.last_checked_at.present? && endpoint.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
|
72
|
+
elsif application.present?
|
73
|
+
application.last_checked_at.present? && application.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
|
74
|
+
end
|
87
75
|
|
88
|
-
|
89
|
-
connection_check
|
90
|
-
end
|
76
|
+
logger.availability_check("Skipping, last check at #{endpoint.last_checked_at || application.last_checked_at} [Source ID: #{source_id}] ") if checked_recently
|
91
77
|
|
92
|
-
|
93
|
-
case application.availability_status
|
94
|
-
when "available"
|
95
|
-
[STATUS_AVAILABLE, nil]
|
96
|
-
when "unavailable"
|
97
|
-
[STATUS_UNAVAILABLE, "Application id #{application.id} unavailable"]
|
78
|
+
checked_recently
|
98
79
|
end
|
99
|
-
end
|
100
80
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
def update_source_and_subresources(status, error_message = nil)
|
107
|
-
logger.availability_check("Updating source [#{source_id}] status [#{status}] message [#{error_message}]")
|
81
|
+
def connection_status
|
82
|
+
# we need either an endpoint or application to check the source.
|
83
|
+
return [STATUS_UNAVAILABLE, ERROR_MESSAGES[:endpoint_or_application_not_found]] unless endpoint || application
|
108
84
|
|
109
|
-
|
85
|
+
check_time
|
86
|
+
if endpoint
|
87
|
+
endpoint_connection_check
|
88
|
+
elsif application
|
89
|
+
application_connection_check
|
90
|
+
end
|
91
|
+
end
|
110
92
|
|
111
|
-
|
112
|
-
|
113
|
-
end
|
93
|
+
def endpoint_connection_check
|
94
|
+
return [STATUS_UNAVAILABLE, ERROR_MESSAGES[:authentication_not_found]] unless authentication
|
114
95
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
source.last_checked_at = check_time
|
119
|
-
source.last_available_at = check_time if status == STATUS_AVAILABLE
|
96
|
+
# call down into the operations pod implementation of `Source#connection_check`
|
97
|
+
connection_check
|
98
|
+
end
|
120
99
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
100
|
+
def application_connection_check
|
101
|
+
case application.availability_status
|
102
|
+
when "available"
|
103
|
+
[STATUS_AVAILABLE, nil]
|
104
|
+
when "unavailable"
|
105
|
+
[STATUS_UNAVAILABLE, "Application id #{application.id} unavailable"]
|
106
|
+
end
|
107
|
+
end
|
125
108
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
return
|
109
|
+
# @return [Array<String, String|nil] - STATUS_[UN]AVAILABLE, error message
|
110
|
+
def connection_check
|
111
|
+
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
130
112
|
end
|
131
113
|
|
132
|
-
|
114
|
+
def update_source_and_subresources(status, error_message = nil)
|
115
|
+
logger.availability_check("Updating source [#{source_id}] status [#{status}] message [#{error_message}]")
|
133
116
|
|
134
|
-
|
135
|
-
endpoint_update.availability_status_error = error_message.to_s
|
136
|
-
endpoint_update.last_checked_at = check_time
|
137
|
-
endpoint_update.last_available_at = check_time if status == STATUS_AVAILABLE
|
117
|
+
update_source(status)
|
138
118
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
119
|
+
update_endpoint(status, error_message) if endpoint
|
120
|
+
update_application(status) if application
|
121
|
+
end
|
143
122
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
123
|
+
def update_source(status)
|
124
|
+
source = ::SourcesApiClient::Source.new
|
125
|
+
source.availability_status = status
|
126
|
+
source.last_checked_at = check_time
|
127
|
+
source.last_available_at = check_time if status == STATUS_AVAILABLE
|
148
128
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
129
|
+
sources_api.update_source(source_id, source)
|
130
|
+
rescue ::SourcesApiClient::ApiError => e
|
131
|
+
logger.availability_check("Failed to update Source id:#{source_id} - #{e.message}", :error)
|
132
|
+
end
|
153
133
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
end
|
134
|
+
def update_endpoint(status, error_message)
|
135
|
+
if endpoint.nil?
|
136
|
+
logger.availability_check("Failed to update Endpoint for Source id:#{source_id}. Endpoint not found", :error)
|
137
|
+
return
|
138
|
+
end
|
160
139
|
|
161
|
-
|
162
|
-
@authentication ||= if endpoint.receptor_node.present?
|
163
|
-
AUTH_NOT_NECESSARY
|
164
|
-
else
|
165
|
-
api_client.fetch_authentication(source_id, endpoint)
|
166
|
-
end
|
167
|
-
rescue => e
|
168
|
-
logger.availability_check("Failed to fetch Authentication for Source #{source_id}: #{e.message}", :error)
|
169
|
-
nil
|
170
|
-
end
|
140
|
+
endpoint_update = ::SourcesApiClient::Endpoint.new
|
171
141
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
nil
|
177
|
-
end
|
142
|
+
endpoint_update.availability_status = status
|
143
|
+
endpoint_update.availability_status_error = error_message.to_s
|
144
|
+
endpoint_update.last_checked_at = check_time
|
145
|
+
endpoint_update.last_available_at = check_time if status == STATUS_AVAILABLE
|
178
146
|
|
179
|
-
|
180
|
-
|
181
|
-
|
147
|
+
sources_api.update_endpoint(endpoint.id, endpoint_update)
|
148
|
+
rescue ::SourcesApiClient::ApiError => e
|
149
|
+
logger.availability_check("Failed to update Endpoint(ID: #{endpoint.id}) - #{e.message}", :error)
|
150
|
+
end
|
182
151
|
|
183
|
-
|
184
|
-
|
185
|
-
|
152
|
+
def update_application(status)
|
153
|
+
application_update = ::SourcesApiClient::Application.new
|
154
|
+
application_update.last_checked_at = check_time
|
155
|
+
application_update.last_available_at = check_time if status == STATUS_AVAILABLE
|
186
156
|
|
187
|
-
|
188
|
-
|
157
|
+
sources_api.update_application(application.id, application_update)
|
158
|
+
rescue ::SourcesApiClient::ApiError => e
|
159
|
+
logger.availability_check("Failed to update Application id: #{application.id} - #{e.message}", :error)
|
160
|
+
end
|
161
|
+
|
162
|
+
def check_time
|
163
|
+
@check_time ||= Time.now.utc
|
164
|
+
end
|
189
165
|
end
|
190
166
|
end
|
191
167
|
end
|
192
168
|
end
|
193
|
-
end
|
194
169
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "sources-api-client"
|
2
|
+
|
3
|
+
module TopologicalInventory
|
4
|
+
module Providers
|
5
|
+
module Common
|
6
|
+
class SourcesApiClient < ::SourcesApiClient::ApiClient
|
7
|
+
delegate :update_source, :update_endpoint, :update_application, :to => :api
|
8
|
+
|
9
|
+
INTERNAL_API_PATH = '//internal/v1.0'.freeze
|
10
|
+
|
11
|
+
def initialize(identity = nil)
|
12
|
+
super(::SourcesApiClient::Configuration.default)
|
13
|
+
self.identity = identity
|
14
|
+
self.api = init_default_api
|
15
|
+
end
|
16
|
+
|
17
|
+
def init_default_api
|
18
|
+
default_headers.merge!(identity) if identity.present?
|
19
|
+
::SourcesApiClient::DefaultApi.new(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def fetch_default_endpoint(source_id)
|
23
|
+
endpoints = api.list_source_endpoints(source_id)&.data || []
|
24
|
+
endpoints.find(&:default)
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch_application(source_id)
|
28
|
+
applications = api.list_source_applications(source_id)&.data || []
|
29
|
+
applications.first
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch_authentication(source_id, default_endpoint = nil, authtype = nil)
|
33
|
+
endpoint = default_endpoint || fetch_default_endpoint(source_id)
|
34
|
+
return if endpoint.nil?
|
35
|
+
|
36
|
+
endpoint_authentications = api.list_endpoint_authentications(endpoint.id.to_s).data || []
|
37
|
+
return if endpoint_authentications.empty?
|
38
|
+
|
39
|
+
auth_id = if authtype.nil?
|
40
|
+
endpoint_authentications.first&.id
|
41
|
+
else
|
42
|
+
endpoint_authentications.detect { |a| a.authtype = authtype }&.id
|
43
|
+
end
|
44
|
+
return if auth_id.nil?
|
45
|
+
|
46
|
+
fetch_authentication_with_password(auth_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_accessor :identity, :api, :custom_base_path
|
52
|
+
|
53
|
+
def fetch_authentication_with_password(auth_id)
|
54
|
+
on_internal_api do
|
55
|
+
local_var_path = "/authentications/#{auth_id}"
|
56
|
+
|
57
|
+
query_params = "expose_encrypted_attribute[]=password"
|
58
|
+
|
59
|
+
header_params = {'Accept' => select_header_accept(['application/json'])}
|
60
|
+
return_type = 'Authentication'
|
61
|
+
data, _, _ = call_api(:GET, local_var_path,
|
62
|
+
:header_params => header_params,
|
63
|
+
:query_params => query_params,
|
64
|
+
:auth_names => ['UserSecurity'],
|
65
|
+
:return_type => return_type)
|
66
|
+
data
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_request_url(path)
|
71
|
+
# Add leading and trailing slashes to path
|
72
|
+
path = "/#{path}".gsub(/\/+/, '/')
|
73
|
+
URI.encode((custom_base_url || @config.base_url) + path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def custom_base_url
|
77
|
+
return nil if custom_base_path.nil?
|
78
|
+
|
79
|
+
url = "#{@config.scheme}://#{[@config.host, custom_base_path].join('/').gsub(/\/+/, '/')}".sub(/\/+\z/, '')
|
80
|
+
URI.encode(url)
|
81
|
+
end
|
82
|
+
|
83
|
+
def on_internal_api
|
84
|
+
self.custom_base_path = INTERNAL_API_PATH
|
85
|
+
yield
|
86
|
+
ensure
|
87
|
+
self.custom_base_path = nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "topological_inventory-api-client"
|
2
|
+
|
3
|
+
module TopologicalInventory
|
4
|
+
module Providers
|
5
|
+
module Common
|
6
|
+
class TopologyApiClient < ::TopologicalInventoryApiClient::ApiClient
|
7
|
+
attr_accessor :api
|
8
|
+
|
9
|
+
def initialize(identity = nil)
|
10
|
+
super(::TopologicalInventoryApiClient::Configuration.default)
|
11
|
+
|
12
|
+
self.identity = identity
|
13
|
+
self.api = init_default_api
|
14
|
+
end
|
15
|
+
|
16
|
+
def init_default_api
|
17
|
+
default_headers.merge!(identity) if identity.present?
|
18
|
+
::TopologicalInventoryApiClient::DefaultApi.new(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_task(task_id, source_id: nil, state:, status:, target_type: nil, target_source_ref: nil, context: nil)
|
22
|
+
params = {'state' => state,
|
23
|
+
'status' => status}
|
24
|
+
params['context'] = context if context
|
25
|
+
params['source_id'] = source_id if source_id
|
26
|
+
params['target_type'] = target_type if target_type
|
27
|
+
params['target_source_ref'] = target_source_ref if target_source_ref
|
28
|
+
task = TopologicalInventoryApiClient::Task.new(params)
|
29
|
+
api.update_task(task_id, task)
|
30
|
+
end
|
31
|
+
|
32
|
+
def svc_instance_url(service_instance)
|
33
|
+
rest_api_path = '/service_instances/{id}'.sub('{' + 'id' + '}', service_instance&.id.to_s)
|
34
|
+
build_request(:GET, rest_api_path).url
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_accessor :identity
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -94,7 +94,7 @@ RSpec.shared_examples "availability_check" do
|
|
94
94
|
stub_patch(:source, source_patch_body)
|
95
95
|
|
96
96
|
# Check
|
97
|
-
api_client = subject.send(:
|
97
|
+
api_client = subject.send(:sources_api)
|
98
98
|
expect(api_client).not_to receive(:update_endpoint)
|
99
99
|
|
100
100
|
subject.availability_check
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: topological_inventory-providers-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Slemr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -252,15 +252,16 @@ files:
|
|
252
252
|
- lib/topological_inventory/providers/common/collector/parser.rb
|
253
253
|
- lib/topological_inventory/providers/common/collectors_pool.rb
|
254
254
|
- lib/topological_inventory/providers/common/logging.rb
|
255
|
+
- lib/topological_inventory/providers/common/mixins/sources_api.rb
|
256
|
+
- lib/topological_inventory/providers/common/mixins/topology_api.rb
|
257
|
+
- lib/topological_inventory/providers/common/mixins/x_rh_headers.rb
|
255
258
|
- lib/topological_inventory/providers/common/operations/async_worker.rb
|
256
|
-
- lib/topological_inventory/providers/common/operations/endpoint_client.rb
|
257
259
|
- lib/topological_inventory/providers/common/operations/health_check.rb
|
258
|
-
- lib/topological_inventory/providers/common/operations/processor.rb
|
259
260
|
- lib/topological_inventory/providers/common/operations/source.rb
|
260
|
-
- lib/topological_inventory/providers/common/operations/sources_api_client.rb
|
261
|
-
- lib/topological_inventory/providers/common/operations/topology_api_client.rb
|
262
261
|
- lib/topological_inventory/providers/common/save_inventory/exception.rb
|
263
262
|
- lib/topological_inventory/providers/common/save_inventory/saver.rb
|
263
|
+
- lib/topological_inventory/providers/common/sources_api_client.rb
|
264
|
+
- lib/topological_inventory/providers/common/topology_api_client.rb
|
264
265
|
- lib/topological_inventory/providers/common/version.rb
|
265
266
|
- spec/spec_helper.rb
|
266
267
|
- spec/support/inventory_helper.rb
|
@@ -271,7 +272,6 @@ files:
|
|
271
272
|
- spec/topological_inventory/providers/common/collectors_pool_spec.rb
|
272
273
|
- spec/topological_inventory/providers/common/logger_spec.rb
|
273
274
|
- spec/topological_inventory/providers/common/operations/async_worker_spec.rb
|
274
|
-
- spec/topological_inventory/providers/common/operations/processor_spec.rb
|
275
275
|
- spec/topological_inventory/providers/common/operations/source_spec.rb
|
276
276
|
- spec/topological_inventory/providers/common/save_inventory/saver_spec.rb
|
277
277
|
- spec/topological_inventory/providers/common_spec.rb
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require "topological_inventory/providers/common/operations/topology_api_client"
|
2
|
-
require "topological_inventory/providers/common/operations/sources_api_client"
|
3
|
-
|
4
|
-
module TopologicalInventory
|
5
|
-
module Providers
|
6
|
-
module Common
|
7
|
-
module Operations
|
8
|
-
class EndpointClient
|
9
|
-
include TopologyApiClient
|
10
|
-
|
11
|
-
def initialize(source_id, task_id, identity = nil)
|
12
|
-
self.identity = identity
|
13
|
-
self.source_id = source_id
|
14
|
-
self.task_id = task_id
|
15
|
-
end
|
16
|
-
|
17
|
-
def order_service(service_offering, service_plan, order_params)
|
18
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
19
|
-
end
|
20
|
-
|
21
|
-
def source_ref_of(endpoint_svc_instance)
|
22
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
23
|
-
end
|
24
|
-
|
25
|
-
def wait_for_provision_complete(source_id, endpoint_svc_instance, context = {})
|
26
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
27
|
-
end
|
28
|
-
|
29
|
-
def provisioned_successfully?(endpoint_svc_instance)
|
30
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
31
|
-
end
|
32
|
-
|
33
|
-
# Endpoint for conversion of provisioned service's status to
|
34
|
-
# TopologicalInventory Task's status
|
35
|
-
def task_status_for(endpoint_svc_instance)
|
36
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
attr_accessor :identity, :task_id, :source_id
|
42
|
-
|
43
|
-
def sources_api
|
44
|
-
@sources_api ||= SourcesApiClient.new(identity)
|
45
|
-
end
|
46
|
-
|
47
|
-
def default_endpoint
|
48
|
-
@default_endpoint ||= sources_api.fetch_default_endpoint(source_id)
|
49
|
-
raise "Sources API: Endpoint not found! (source id: #{source_id})" if @default_endpoint.nil?
|
50
|
-
|
51
|
-
@default_endpoint
|
52
|
-
end
|
53
|
-
|
54
|
-
def authentication
|
55
|
-
@authentication ||= sources_api.fetch_authentication(source_id, default_endpoint)
|
56
|
-
end
|
57
|
-
|
58
|
-
def verify_ssl_mode
|
59
|
-
default_endpoint.verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require "topological_inventory/providers/common/operations/topology_api_client"
|
2
|
-
|
3
|
-
module TopologicalInventory
|
4
|
-
module Providers
|
5
|
-
module Common
|
6
|
-
module Operations
|
7
|
-
class Processor
|
8
|
-
include Logging
|
9
|
-
include TopologyApiClient
|
10
|
-
|
11
|
-
SLEEP_POLL = 10
|
12
|
-
POLL_TIMEOUT = 1800
|
13
|
-
|
14
|
-
def self.process!(message)
|
15
|
-
model, method = message.headers['message_type'].to_s.split(".")
|
16
|
-
new(model, method, message.payload).process
|
17
|
-
end
|
18
|
-
|
19
|
-
# @param payload [Hash] https://github.com/ManageIQ/topological_inventory-api/blob/master/app/controllers/api/v0/service_plans_controller.rb#L32-L41
|
20
|
-
def initialize(model, method, payload, metrics = nil)
|
21
|
-
self.model = model
|
22
|
-
self.method = method
|
23
|
-
self.params = payload["params"]
|
24
|
-
self.identity = payload["request_context"]
|
25
|
-
self.metrics = metrics
|
26
|
-
end
|
27
|
-
|
28
|
-
def process
|
29
|
-
logger.info("Processing #{model}##{method} [#{params}]...")
|
30
|
-
result = order_service(params)
|
31
|
-
logger.info("Processing #{model}##{method} [#{params}]...Complete")
|
32
|
-
|
33
|
-
result
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
attr_accessor :identity, :model, :method, :metrics, :params
|
39
|
-
|
40
|
-
def endpoint_client(source_id, task_id, identity)
|
41
|
-
raise NotImplementedError, "#{__method__} must be implemented in a subclass as kind of TopologicalInventory::Providers::Common::EndpointClient class"
|
42
|
-
end
|
43
|
-
|
44
|
-
def order_service(params)
|
45
|
-
task_id, service_offering_id, service_plan_id, order_params = params.values_at("task_id", "service_offering_id", "service_plan_id", "order_params")
|
46
|
-
|
47
|
-
service_plan = topology_api_client.show_service_plan(service_plan_id) if service_plan_id.present?
|
48
|
-
service_offering_id = service_plan.service_offering_id if service_offering_id.nil? && service_plan.present?
|
49
|
-
service_offering = topology_api_client.show_service_offering(service_offering_id)
|
50
|
-
|
51
|
-
source_id = service_offering.source_id
|
52
|
-
client = endpoint_client(source_id, task_id, identity)
|
53
|
-
|
54
|
-
logger.info("Ordering #{service_offering.name}...")
|
55
|
-
remote_service_instance = client.order_service(service_offering, service_plan.presence, order_params)
|
56
|
-
logger.info("Ordering #{service_offering.name}...Complete")
|
57
|
-
|
58
|
-
poll_order_complete_thread(task_id, source_id, remote_service_instance)
|
59
|
-
rescue StandardError => err
|
60
|
-
metrics&.record_error
|
61
|
-
logger.error("[Task #{task_id}] Ordering error: #{err}\n#{err.backtrace.join("\n")}")
|
62
|
-
update_task(task_id, :state => "completed", :status => "error", :context => {:error => err.to_s})
|
63
|
-
end
|
64
|
-
|
65
|
-
def poll_order_complete_thread(task_id, source_id, remote_svc_instance)
|
66
|
-
Thread.new do
|
67
|
-
begin
|
68
|
-
poll_order_complete(task_id, source_id, remote_svc_instance)
|
69
|
-
rescue StandardError => err
|
70
|
-
logger.error("[Task #{task_id}] Waiting for complete: #{err}\n#{err.backtrace.join("\n")}")
|
71
|
-
update_task(task_id, :state => "completed", :status => "warn", :context => {:error => err.to_s})
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def poll_order_complete(task_id, source_id, remote_svc_instance)
|
77
|
-
client = endpoint_client(source_id, task_id, identity)
|
78
|
-
|
79
|
-
context = {
|
80
|
-
:service_instance => {
|
81
|
-
:source_id => source_id,
|
82
|
-
:source_ref => client.source_ref_of(remote_svc_instance)
|
83
|
-
}
|
84
|
-
}
|
85
|
-
|
86
|
-
remote_svc_instance = client.wait_for_provision_complete(task_id, remote_svc_instance, context)
|
87
|
-
|
88
|
-
if client.provisioned_successfully?(remote_svc_instance)
|
89
|
-
if (service_instance = load_topological_svc_instance(source_id, client.source_ref_of(remote_svc_instance))).present?
|
90
|
-
context[:service_instance][:id] = service_instance.id
|
91
|
-
context[:service_instance][:url] = svc_instance_url(service_instance)
|
92
|
-
else
|
93
|
-
logger.warn("Failed to get service_instance API URL (endpoint's service instance: #{remote_svc_instance.inspect})")
|
94
|
-
end
|
95
|
-
end
|
96
|
-
update_task(task_id, :state => "completed", :status => client.task_status_for(remote_svc_instance), :context => context)
|
97
|
-
end
|
98
|
-
|
99
|
-
def load_topological_svc_instance(source_id, source_ref)
|
100
|
-
api = topology_api_client.api_client
|
101
|
-
|
102
|
-
count = 0
|
103
|
-
timeout_count = POLL_TIMEOUT / SLEEP_POLL
|
104
|
-
|
105
|
-
header_params = { 'Accept' => api.select_header_accept(['application/json']) }
|
106
|
-
query_params = { :'source_id' => source_id, :'source_ref' => source_ref }
|
107
|
-
return_type = 'ServiceInstancesCollection'
|
108
|
-
|
109
|
-
service_instance = nil
|
110
|
-
loop do
|
111
|
-
data, _status_code, _headers = api.call_api(:GET, "/service_instances",
|
112
|
-
:header_params => header_params,
|
113
|
-
:query_params => query_params,
|
114
|
-
:auth_names => ['UserSecurity'],
|
115
|
-
:return_type => return_type)
|
116
|
-
|
117
|
-
service_instance = data.data&.first if data.meta.count > 0
|
118
|
-
break if service_instance.present?
|
119
|
-
|
120
|
-
break if (count += 1) >= timeout_count
|
121
|
-
|
122
|
-
sleep(SLEEP_POLL) # seconds
|
123
|
-
end
|
124
|
-
|
125
|
-
if service_instance.nil?
|
126
|
-
logger.error("Failed to find service_instance by source_id [#{source_id}] source_ref [#{source_ref}]")
|
127
|
-
end
|
128
|
-
|
129
|
-
service_instance
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require "sources-api-client"
|
2
|
-
|
3
|
-
module TopologicalInventory
|
4
|
-
module Providers
|
5
|
-
module Common
|
6
|
-
module Operations
|
7
|
-
class SourcesApiClient < ::SourcesApiClient::ApiClient
|
8
|
-
delegate :update_source, :update_endpoint, :update_application, :to => :api
|
9
|
-
|
10
|
-
INTERNAL_API_PATH = '//internal/v1.0'.freeze
|
11
|
-
|
12
|
-
def initialize(identity = nil)
|
13
|
-
super(::SourcesApiClient::Configuration.default)
|
14
|
-
self.identity = identity
|
15
|
-
self.api = init_default_api
|
16
|
-
end
|
17
|
-
|
18
|
-
def init_default_api
|
19
|
-
default_headers.merge!(identity) if identity.present?
|
20
|
-
::SourcesApiClient::DefaultApi.new(self)
|
21
|
-
end
|
22
|
-
|
23
|
-
def fetch_default_endpoint(source_id)
|
24
|
-
endpoints = api.list_source_endpoints(source_id)&.data || []
|
25
|
-
endpoints.find(&:default)
|
26
|
-
end
|
27
|
-
|
28
|
-
def fetch_application(source_id)
|
29
|
-
applications = api.list_source_applications(source_id)&.data || []
|
30
|
-
applications.first
|
31
|
-
end
|
32
|
-
|
33
|
-
def fetch_authentication(source_id, default_endpoint = nil, authtype = nil)
|
34
|
-
endpoint = default_endpoint || fetch_default_endpoint(source_id)
|
35
|
-
return if endpoint.nil?
|
36
|
-
|
37
|
-
endpoint_authentications = api.list_endpoint_authentications(endpoint.id.to_s).data || []
|
38
|
-
return if endpoint_authentications.empty?
|
39
|
-
|
40
|
-
auth_id = if authtype.nil?
|
41
|
-
endpoint_authentications.first&.id
|
42
|
-
else
|
43
|
-
endpoint_authentications.detect { |a| a.authtype = authtype }&.id
|
44
|
-
end
|
45
|
-
return if auth_id.nil?
|
46
|
-
|
47
|
-
fetch_authentication_with_password(auth_id)
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
attr_accessor :identity, :api, :custom_base_path
|
53
|
-
|
54
|
-
def fetch_authentication_with_password(auth_id)
|
55
|
-
on_internal_api do
|
56
|
-
local_var_path = "/authentications/#{auth_id}"
|
57
|
-
|
58
|
-
query_params = "expose_encrypted_attribute[]=password"
|
59
|
-
|
60
|
-
header_params = { 'Accept' => select_header_accept(['application/json']) }
|
61
|
-
return_type = 'Authentication'
|
62
|
-
data, _, _ = call_api(:GET, local_var_path,
|
63
|
-
:header_params => header_params,
|
64
|
-
:query_params => query_params,
|
65
|
-
:auth_names => ['UserSecurity'],
|
66
|
-
:return_type => return_type)
|
67
|
-
data
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def build_request_url(path)
|
72
|
-
# Add leading and trailing slashes to path
|
73
|
-
path = "/#{path}".gsub(/\/+/, '/')
|
74
|
-
URI.encode((custom_base_url || @config.base_url) + path)
|
75
|
-
end
|
76
|
-
|
77
|
-
def custom_base_url
|
78
|
-
return nil if custom_base_path.nil?
|
79
|
-
|
80
|
-
url = "#{@config.scheme}://#{[@config.host, custom_base_path].join('/').gsub(/\/+/, '/')}".sub(/\/+\z/, '')
|
81
|
-
URI.encode(url)
|
82
|
-
end
|
83
|
-
|
84
|
-
def on_internal_api
|
85
|
-
self.custom_base_path = INTERNAL_API_PATH
|
86
|
-
yield
|
87
|
-
ensure
|
88
|
-
self.custom_base_path = nil
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module TopologicalInventory
|
2
|
-
module Providers
|
3
|
-
module Common
|
4
|
-
module Operations
|
5
|
-
module TopologyApiClient
|
6
|
-
def topology_api_client
|
7
|
-
@topology_api_client ||=
|
8
|
-
begin
|
9
|
-
api_client = TopologicalInventoryApiClient::ApiClient.new
|
10
|
-
api_client.default_headers.merge!(identity) if identity.present?
|
11
|
-
TopologicalInventoryApiClient::DefaultApi.new(api_client)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def update_task(task_id, state:, status:, context:)
|
16
|
-
task = TopologicalInventoryApiClient::Task.new("state" => state, "status" => status, "context" => context)
|
17
|
-
topology_api_client.update_task(task_id, task)
|
18
|
-
end
|
19
|
-
|
20
|
-
def svc_instance_url(service_instance)
|
21
|
-
rest_api_path = '/service_instances/{id}'.sub('{' + 'id' + '}', service_instance&.id.to_s)
|
22
|
-
topology_api_client.api_client.build_request(:GET, rest_api_path).url
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require "topological_inventory/providers/common/operations/processor"
|
2
|
-
|
3
|
-
RSpec.describe TopologicalInventory::Providers::Common::Operations::Processor do
|
4
|
-
let(:topology_api_client) { double }
|
5
|
-
let(:source_id) { 1 }
|
6
|
-
let(:source_ref) { 1000 }
|
7
|
-
let(:service_plan) { double("TopologicalInventoryApiClient::ServicePlan") }
|
8
|
-
let(:service_offering) { double("TopologicalInventoryApiClient::ServiceOffering") }
|
9
|
-
|
10
|
-
# Overriden in contexts
|
11
|
-
let(:payload) { {} }
|
12
|
-
|
13
|
-
before do
|
14
|
-
@processor = described_class.new(nil, nil, payload)
|
15
|
-
allow(@processor).to receive(:logger).and_return(double('null_object').as_null_object)
|
16
|
-
|
17
|
-
allow(service_plan).to receive(:service_offering_id).and_return(1)
|
18
|
-
allow(service_plan).to receive(:name).and_return(double)
|
19
|
-
|
20
|
-
allow(service_offering).to receive(:name).and_return(double)
|
21
|
-
allow(service_offering).to receive(:source_ref).and_return(source_ref)
|
22
|
-
allow(service_offering).to receive(:extra).and_return({:type => 'job_template'})
|
23
|
-
allow(service_offering).to receive(:source_id).and_return(source_id)
|
24
|
-
|
25
|
-
@endpoint_client = double
|
26
|
-
allow(@endpoint_client).to receive(:order_service)
|
27
|
-
|
28
|
-
allow(@processor).to receive(:endpoint_client).and_return(@endpoint_client)
|
29
|
-
allow(@processor).to receive(:topology_api_client).and_return(topology_api_client)
|
30
|
-
allow(topology_api_client).to receive(:update_task)
|
31
|
-
allow(topology_api_client).to receive(:show_service_plan).and_return(service_plan)
|
32
|
-
allow(topology_api_client).to receive(:show_service_offering).and_return(service_offering)
|
33
|
-
end
|
34
|
-
|
35
|
-
context "Order by ServicePlan" do
|
36
|
-
let(:payload) do
|
37
|
-
{
|
38
|
-
'request_context' => {"x-rh-identity" => 'abcd'},
|
39
|
-
'params' => {
|
40
|
-
'order_params' => {
|
41
|
-
'service_plan_id' => 1,
|
42
|
-
'service_parameters' => { :name => "Job 1",
|
43
|
-
:param1 => "Test Topology",
|
44
|
-
:param2 => 50 },
|
45
|
-
'provider_control_parameters' => {}
|
46
|
-
},
|
47
|
-
'service_plan_id' => 1,
|
48
|
-
'task_id' => 1 # in tp-inv api (Task)
|
49
|
-
}
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#order_service" do
|
54
|
-
it "orders job" do
|
55
|
-
allow(@processor).to receive(:poll_order_complete_thread).and_return(double)
|
56
|
-
|
57
|
-
expect(@endpoint_client).to receive(:order_service).with(service_offering, service_plan, payload['params']['order_params'])
|
58
|
-
@processor.send(:order_service, payload['params'])
|
59
|
-
end
|
60
|
-
|
61
|
-
it "updates task on error" do
|
62
|
-
err_message = "Sample error"
|
63
|
-
|
64
|
-
allow(@processor).to receive(:poll_order_complete_thread).and_return(double)
|
65
|
-
allow(@processor).to receive(:update_task).and_return(double)
|
66
|
-
allow(@endpoint_client).to receive(:order_service).and_raise(err_message)
|
67
|
-
|
68
|
-
expect(@processor).to receive(:update_task).with(payload['params']['task_id'], :state => "completed", :status => "error", :context => { :error => err_message })
|
69
|
-
|
70
|
-
@processor.send(:order_service, payload['params'])
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context "Order by ServiceOffering" do
|
76
|
-
let(:payload) do
|
77
|
-
{
|
78
|
-
'request_context' => {"x-rh-identity" => 'abcd'},
|
79
|
-
'params' => {
|
80
|
-
'order_params' => {
|
81
|
-
'service_offering_id' => 1,
|
82
|
-
'service_parameters' => { :name => "Job 1",
|
83
|
-
:param1 => "Test Topology",
|
84
|
-
:param2 => 50 },
|
85
|
-
'provider_control_parameters' => {}
|
86
|
-
},
|
87
|
-
'service_offering_id' => 1,
|
88
|
-
'task_id' => 1 # in tp-inv api (Task)
|
89
|
-
}
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
describe "#order_service" do
|
94
|
-
it "orders job" do
|
95
|
-
allow(@processor).to receive(:poll_order_complete_thread).and_return(double)
|
96
|
-
|
97
|
-
expect(@endpoint_client).to receive(:order_service).with(service_offering, nil, payload['params']['order_params'])
|
98
|
-
@processor.send(:order_service, payload['params'])
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|