topological_inventory-providers-common 1.0.11 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +31 -0
  3. data/.rubocop.yml +1 -1
  4. data/.yamllint +8 -0
  5. data/CHANGELOG.md +28 -4
  6. data/lib/topological_inventory/providers/common.rb +1 -2
  7. data/lib/topological_inventory/providers/common/logging.rb +6 -3
  8. data/lib/topological_inventory/providers/common/messaging_client.rb +40 -0
  9. data/lib/topological_inventory/providers/common/metrics.rb +84 -0
  10. data/lib/topological_inventory/providers/common/mixins/sources_api.rb +61 -0
  11. data/lib/topological_inventory/providers/common/mixins/statuses.rb +19 -0
  12. data/lib/topological_inventory/providers/common/mixins/topology_api.rb +26 -0
  13. data/lib/topological_inventory/providers/common/mixins/x_rh_headers.rb +24 -0
  14. data/lib/topological_inventory/providers/common/operations/async_worker.rb +61 -0
  15. data/lib/topological_inventory/providers/common/operations/processor.rb +46 -104
  16. data/lib/topological_inventory/providers/common/operations/source.rb +183 -144
  17. data/lib/topological_inventory/providers/common/sources_api_client.rb +92 -0
  18. data/lib/topological_inventory/providers/common/topology_api_client.rb +43 -0
  19. data/lib/topological_inventory/providers/common/version.rb +1 -1
  20. data/spec/support/shared/availability_check.rb +254 -90
  21. data/spec/topological_inventory/providers/common/operations/async_worker_spec.rb +45 -0
  22. data/spec/topological_inventory/providers/common/operations/processor_spec.rb +52 -83
  23. data/topological_inventory-providers-common.gemspec +14 -10
  24. metadata +74 -9
  25. data/lib/topological_inventory/providers/common/operations/endpoint_client.rb +0 -65
  26. data/lib/topological_inventory/providers/common/operations/sources_api_client.rb +0 -94
  27. data/lib/topological_inventory/providers/common/operations/topology_api_client.rb +0 -28
@@ -0,0 +1,45 @@
1
+ require "topological_inventory/providers/common/operations/async_worker"
2
+
3
+ describe TopologicalInventory::Providers::Common::Operations::AsyncWorker do
4
+ let(:queue) { double }
5
+ let(:impl) { double }
6
+ let(:metrics) { double('metrics') }
7
+ let(:msg) { double }
8
+ let(:operation) { "Source.availability_check" }
9
+
10
+ subject { described_class.new(impl, :queue => queue, :metrics => metrics) }
11
+
12
+ before do
13
+ allow(queue).to receive(:length).and_return(0)
14
+ allow(msg).to receive(:message).and_return(operation)
15
+ end
16
+
17
+ context "when the message is able to be processed" do
18
+ let(:result) { subject.operation_status[:success] }
19
+ before do
20
+ allow(impl).to receive(:process!).with(msg, metrics).and_return(result)
21
+ allow(msg).to receive(:ack)
22
+ end
23
+
24
+ it "drains messages that are added to the queue" do
25
+ expect(impl).to receive(:process!).with(msg, metrics).once
26
+ expect(metrics).to receive(:record_operation).with(operation, :status => result)
27
+ subject.send(:process_message, msg)
28
+ end
29
+ end
30
+
31
+ context "when the message results in an error" do
32
+ let(:result) { subject.operation_status[:error] }
33
+ before do
34
+ allow(impl).to receive(:process!).with(msg, metrics).and_raise(StandardError.new("boom!"))
35
+ end
36
+
37
+ it "ack's the message on failure" do
38
+ allow(subject).to receive(:logger).and_return(double.as_null_object)
39
+
40
+ expect(msg).to receive(:ack).once
41
+ expect(metrics).to receive(:record_operation).with(operation, :status => result)
42
+ subject.send(:process_message, msg)
43
+ end
44
+ end
45
+ end
@@ -1,102 +1,71 @@
1
1
  require "topological_inventory/providers/common/operations/processor"
2
2
 
3
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
4
+ let(:operation_name) { 'Source.availability_check' }
5
+ let(:params) { {'source_id' => 1, 'external_tenant' => '12345'} }
6
+ let(:payload) { {"params" => params, "request_context" => double('request_context')} }
7
+ let(:message) { double("ManageIQ::Messaging::ReceivedMessage", :message => operation_name, :payload => payload) }
34
8
 
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
9
+ subject { described_class.new(message, nil) }
10
+
11
+ describe "#process" do
12
+ it "starts the operation if class and method exists" do
13
+ result = double('result')
52
14
 
53
- describe "#order_service" do
54
- it "orders job" do
55
- allow(@processor).to receive(:poll_order_complete_thread).and_return(double)
15
+ klass = TopologicalInventory::Providers::Common::Operations::Source
16
+ allow(subject).to receive(:operation_class).and_return(klass)
56
17
 
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
18
+ source = klass.new(params, payload['request_context'], nil)
19
+ expect(klass).to receive(:new).with(params, payload['request_context'], nil).and_return(source)
20
+ expect(source).to receive(:availability_check).and_return(result)
60
21
 
61
- it "updates task on error" do
62
- err_message = "Sample error"
22
+ expect(subject.process).to eq(result)
23
+ end
24
+
25
+ it "returns 'not_implemented' if class of method doesn't exist" do
26
+ allow(subject).to receive(:operation_class).and_return(nil)
27
+ allow(subject).to receive(:method).and_return('awesome')
63
28
 
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)
29
+ expect(subject.process).to eq(subject.operation_status[:not_implemented])
30
+ end
67
31
 
68
- expect(@processor).to receive(:update_task).with(payload['params']['task_id'], :state => "completed", :status => "error", :context => { :error => err_message })
32
+ it "updates task if not_implemented" do
33
+ allow(subject).to receive(:operation_class).and_return(nil)
34
+ allow(subject).to receive(:method).and_return('awesome')
69
35
 
70
- @processor.send(:order_service, payload['params'])
71
- end
36
+ subject.send(:params)['task_id'] = '1'
37
+ expect(subject).to(receive(:update_task).with('1',
38
+ :state => "completed",
39
+ :status => "error",
40
+ :context => anything))
41
+ subject.process
42
+ end
43
+
44
+ it "updates task if exception raised" do
45
+ subject.send(:params)['task_id'] = '1'
46
+ expect(subject).to(receive(:update_task).with('1',
47
+ :state => "completed",
48
+ :status => "error",
49
+ :context => anything))
50
+ expect { subject.process }.to raise_exception(NotImplementedError)
72
51
  end
73
52
  end
74
53
 
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
- }
54
+ describe "#with_time_measure" do
55
+ let(:metrics) { double("Metrics") }
56
+
57
+ it "records time and yields if metrics provided" do
58
+ allow(subject).to receive(:metrics).and_return(metrics)
59
+
60
+ expect(metrics).to receive(:record_operation_time).with(operation_name).and_yield
61
+
62
+ expect(subject.send(:with_time_measure) { 42 }).to eq(42)
91
63
  end
92
64
 
93
- describe "#order_service" do
94
- it "orders job" do
95
- allow(@processor).to receive(:poll_order_complete_thread).and_return(double)
65
+ it "only yields if metrics not present" do
66
+ expect(metrics).not_to receive(:record_operation_time)
96
67
 
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
68
+ expect(subject.send(:with_time_measure) { 42 }).to eq(42)
100
69
  end
101
70
  end
102
71
  end
@@ -26,16 +26,20 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency 'activesupport', '~> 5.2.4.3'
27
27
  spec.add_runtime_dependency 'config', '~> 1.7', '>= 1.7.2'
28
28
  spec.add_runtime_dependency 'json', '~> 2.3'
29
- spec.add_runtime_dependency "manageiq-loggers", ">= 0.4.2"
30
- spec.add_runtime_dependency "sources-api-client", "~> 3.0"
31
- spec.add_runtime_dependency "topological_inventory-api-client", "~> 3.0", ">= 3.0.1"
32
- spec.add_runtime_dependency "topological_inventory-ingress_api-client", "~> 1.0", ">= 1.0.3"
29
+ spec.add_runtime_dependency 'manageiq-loggers', '>= 0.4.2'
30
+ spec.add_runtime_dependency 'manageiq-messaging', '~> 1.0.0'
31
+ spec.add_runtime_dependency 'more_core_extensions'
32
+ spec.add_runtime_dependency 'prometheus_exporter', '~> 0.4.17'
33
+ spec.add_runtime_dependency 'sources-api-client', '~> 3.0'
34
+ spec.add_runtime_dependency 'topological_inventory-api-client', '~> 3.0', '>= 3.0.1'
35
+ spec.add_runtime_dependency 'topological_inventory-ingress_api-client', '~> 1.0', '>= 1.0.3'
33
36
 
34
- spec.add_development_dependency "bundler", "~> 2.0"
35
- spec.add_development_dependency "rake", ">= 12.3.3"
36
- spec.add_development_dependency "rspec", "~> 3.0"
37
- spec.add_development_dependency 'rubocop', '~>0.69.0'
38
- spec.add_development_dependency 'rubocop-performance', '~>1.3'
39
- spec.add_development_dependency "simplecov", "~> 0.17.1"
37
+ spec.add_development_dependency 'bundler', '~> 2.0'
38
+ spec.add_development_dependency 'rake', '>= 12.3.3'
39
+ spec.add_development_dependency 'rspec', '~> 3.0'
40
+ spec.add_development_dependency 'rubocop', '~> 1.0.0'
41
+ spec.add_development_dependency 'rubocop-performance', '~> 1.8'
42
+ spec.add_development_dependency 'rubocop-rails', '~> 2.8'
43
+ spec.add_development_dependency 'simplecov', '~> 0.17.1'
40
44
  spec.add_development_dependency 'webmock'
41
45
  end
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: 1.0.11
4
+ version: 2.1.2
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-09-04 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -72,6 +72,48 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 0.4.2
75
+ - !ruby/object:Gem::Dependency
76
+ name: manageiq-messaging
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 1.0.0
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 1.0.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: more_core_extensions
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: prometheus_exporter
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 0.4.17
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 0.4.17
75
117
  - !ruby/object:Gem::Dependency
76
118
  name: sources-api-client
77
119
  requirement: !ruby/object:Gem::Requirement
@@ -174,28 +216,42 @@ dependencies:
174
216
  requirements:
175
217
  - - "~>"
176
218
  - !ruby/object:Gem::Version
177
- version: 0.69.0
219
+ version: 1.0.0
178
220
  type: :development
179
221
  prerelease: false
180
222
  version_requirements: !ruby/object:Gem::Requirement
181
223
  requirements:
182
224
  - - "~>"
183
225
  - !ruby/object:Gem::Version
184
- version: 0.69.0
226
+ version: 1.0.0
185
227
  - !ruby/object:Gem::Dependency
186
228
  name: rubocop-performance
187
229
  requirement: !ruby/object:Gem::Requirement
188
230
  requirements:
189
231
  - - "~>"
190
232
  - !ruby/object:Gem::Version
191
- version: '1.3'
233
+ version: '1.8'
234
+ type: :development
235
+ prerelease: false
236
+ version_requirements: !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - "~>"
239
+ - !ruby/object:Gem::Version
240
+ version: '1.8'
241
+ - !ruby/object:Gem::Dependency
242
+ name: rubocop-rails
243
+ requirement: !ruby/object:Gem::Requirement
244
+ requirements:
245
+ - - "~>"
246
+ - !ruby/object:Gem::Version
247
+ version: '2.8'
192
248
  type: :development
193
249
  prerelease: false
194
250
  version_requirements: !ruby/object:Gem::Requirement
195
251
  requirements:
196
252
  - - "~>"
197
253
  - !ruby/object:Gem::Version
198
- version: '1.3'
254
+ version: '2.8'
199
255
  - !ruby/object:Gem::Dependency
200
256
  name: simplecov
201
257
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +287,7 @@ executables: []
231
287
  extensions: []
232
288
  extra_rdoc_files: []
233
289
  files:
290
+ - ".codeclimate.yml"
234
291
  - ".github/workflows/gem-push.yml"
235
292
  - ".gitignore"
236
293
  - ".rspec"
@@ -238,6 +295,7 @@ files:
238
295
  - ".rubocop_cc.yml"
239
296
  - ".rubocop_local.yml"
240
297
  - ".travis.yml"
298
+ - ".yamllint"
241
299
  - CHANGELOG.md
242
300
  - Gemfile
243
301
  - LICENSE.txt
@@ -252,14 +310,20 @@ files:
252
310
  - lib/topological_inventory/providers/common/collector/parser.rb
253
311
  - lib/topological_inventory/providers/common/collectors_pool.rb
254
312
  - lib/topological_inventory/providers/common/logging.rb
255
- - lib/topological_inventory/providers/common/operations/endpoint_client.rb
313
+ - lib/topological_inventory/providers/common/messaging_client.rb
314
+ - lib/topological_inventory/providers/common/metrics.rb
315
+ - lib/topological_inventory/providers/common/mixins/sources_api.rb
316
+ - lib/topological_inventory/providers/common/mixins/statuses.rb
317
+ - lib/topological_inventory/providers/common/mixins/topology_api.rb
318
+ - lib/topological_inventory/providers/common/mixins/x_rh_headers.rb
319
+ - lib/topological_inventory/providers/common/operations/async_worker.rb
256
320
  - lib/topological_inventory/providers/common/operations/health_check.rb
257
321
  - lib/topological_inventory/providers/common/operations/processor.rb
258
322
  - lib/topological_inventory/providers/common/operations/source.rb
259
- - lib/topological_inventory/providers/common/operations/sources_api_client.rb
260
- - lib/topological_inventory/providers/common/operations/topology_api_client.rb
261
323
  - lib/topological_inventory/providers/common/save_inventory/exception.rb
262
324
  - lib/topological_inventory/providers/common/save_inventory/saver.rb
325
+ - lib/topological_inventory/providers/common/sources_api_client.rb
326
+ - lib/topological_inventory/providers/common/topology_api_client.rb
263
327
  - lib/topological_inventory/providers/common/version.rb
264
328
  - spec/spec_helper.rb
265
329
  - spec/support/inventory_helper.rb
@@ -269,6 +333,7 @@ files:
269
333
  - spec/topological_inventory/providers/common/collectors/inventory_collection_wrapper_spec.rb
270
334
  - spec/topological_inventory/providers/common/collectors_pool_spec.rb
271
335
  - spec/topological_inventory/providers/common/logger_spec.rb
336
+ - spec/topological_inventory/providers/common/operations/async_worker_spec.rb
272
337
  - spec/topological_inventory/providers/common/operations/processor_spec.rb
273
338
  - spec/topological_inventory/providers/common/operations/source_spec.rb
274
339
  - spec/topological_inventory/providers/common/save_inventory/saver_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