topological_inventory-providers-common 1.0.12 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|