topological_inventory-providers-common 2.0.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 134e945b201072b8bdd7fc6af73b04a6f60698da831ef3989ab973453a1a5159
4
- data.tar.gz: 20e4f260c411551572b557f4e4454fdc03c9e3b2ac9c8f5997e6600780298c1a
3
+ metadata.gz: aad209b97efea9bb19ce488782adb1dabfa8d650c12f8637e2b348ed4ec95a15
4
+ data.tar.gz: 69b9bbed6a2d725990206ab3bfc7b13ec25b10f7e0c1a979b48c61b67e53fd0d
5
5
  SHA512:
6
- metadata.gz: 0a847566f6fb20e9518faef660c626788e6afd20d26cec28a5899e645c68cedd7c017974d0cb1c3c2524253007386b9728a1bb67a0f0a9101fe62bd388f03ccb
7
- data.tar.gz: 6e786659b1bf913fe1e22d9c0618986d03dc4bc169d782e446ecd089b97a136b639f83be85c562006dccde83a8d025b102863b565aa571746767fa292e4dae89
6
+ metadata.gz: 45722b70f009a764d8cd804424157cc98b1a225b72326b8b8971fecd093fa6260446777db76bc3502e487d27dc82b2b4325959302f4a1abe13fbbf8c015c1d54
7
+ data.tar.gz: b1a6de8e2eb93b2b26d4b609f17a1a518cf4b318dbcf117c6225fe297bb3ec97f870b944e151786977ad90f42c16746eeeadf6a3d113b648921e278cb831aadd
@@ -0,0 +1,31 @@
1
+ ---
2
+ version: '2'
3
+ prepare:
4
+ fetch:
5
+ - url: https://raw.githubusercontent.com/RedHatInsights/insights-api-common-rails/master/.rubocop_base.yml
6
+ path: ".rubocop_base.yml"
7
+ - url: https://raw.githubusercontent.com/RedHatInsights/insights-api-common-rails/master/.rubocop_cc_base.yml
8
+ path: ".rubocop_cc_base.yml"
9
+ checks:
10
+ argument-count:
11
+ enabled: false
12
+ complex-logic:
13
+ enabled: false
14
+ file-lines:
15
+ enabled: false
16
+ method-complexity:
17
+ config:
18
+ threshold: 11
19
+ method-count:
20
+ enabled: false
21
+ method-lines:
22
+ enabled: false
23
+ nested-control-flow:
24
+ enabled: false
25
+ return-statements:
26
+ enabled: false
27
+ plugins:
28
+ rubocop:
29
+ enabled: true
30
+ config: ".rubocop_cc.yml"
31
+ channel: rubocop-1-0
@@ -1,3 +1,3 @@
1
1
  inherit_from:
2
- - https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml
2
+ - https://raw.githubusercontent.com/RedHatInsights/insights-api-common-rails/master/.rubocop_base.yml
3
3
  - .rubocop_local.yml
@@ -0,0 +1,8 @@
1
+ ---
2
+ ignore: |
3
+
4
+ extends: relaxed
5
+
6
+ rules:
7
+ line-length:
8
+ max: 120
@@ -4,7 +4,12 @@ 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]
7
+ ## [2.1.0]
8
+ Add Availability checks for sources via Kafka #54
9
+ Common Metrics exporter #57
10
+ Rubocop rules from insights-api-common + yamllint #59
11
+
12
+ ## [2.0.0] - 2020-10-20
8
13
  Operations/API clients refactoring
9
14
 
10
15
  ## [1.0.12] - 2020-10-01
@@ -62,7 +67,8 @@ manageiq-loggers to >= 0.4.2 #20
62
67
  ## [1.0.0] - 2020-03-19
63
68
  ### Initial release to rubygems.org
64
69
 
65
- [Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.0.0...HEAD
70
+ [Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.1.0...HEAD
71
+ [2.1.0]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.0.0...v2.1.0
66
72
  [2.0.0]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.12...v2.0.0
67
73
  [1.0.12]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.11...v1.0.12
68
74
  [1.0.11]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.10...v1.0.11
@@ -3,6 +3,7 @@ require "topological_inventory/providers/common/logging"
3
3
  require "topological_inventory/providers/common/operations/health_check"
4
4
  require "topological_inventory/providers/common/collectors_pool"
5
5
  require "topological_inventory/providers/common/collector"
6
+ require "topological_inventory/providers/common/metrics"
6
7
 
7
8
  module TopologicalInventory
8
9
  module Providers
@@ -0,0 +1,40 @@
1
+ require "more_core_extensions/core_ext/module/cache_with_timeout"
2
+ require "manageiq-messaging"
3
+
4
+ module TopologicalInventory
5
+ module Providers
6
+ module Common
7
+ class MessagingClient
8
+ # Kafka host name
9
+ attr_accessor :queue_host
10
+ # Kafka port
11
+ attr_accessor :queue_port
12
+
13
+ def initialize
14
+ @queue_host = ENV['QUEUE_HOST'] || 'localhost'
15
+ @queue_port = (ENV['QUEUE_PORT'] || 9092).to_i
16
+ end
17
+
18
+ def self.default
19
+ @@default ||= new
20
+ end
21
+
22
+ def self.configure
23
+ if block_given?
24
+ yield(default)
25
+ else
26
+ default
27
+ end
28
+ end
29
+
30
+ cache_with_timeout(:client) do
31
+ ManageIQ::Messaging::Client.open(:protocol => :Kafka, :host => @queue_host, :port => @queue_port)
32
+ end
33
+
34
+ def client
35
+ self.class.client
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,84 @@
1
+ require "benchmark"
2
+ require "prometheus_exporter"
3
+ require "prometheus_exporter/server"
4
+ require "prometheus_exporter/client"
5
+ require "prometheus_exporter/instrumentation"
6
+
7
+ module TopologicalInventory
8
+ module Providers
9
+ module Common
10
+ class Metrics
11
+ ERROR_COUNTER_MESSAGE = "total number of errors".freeze
12
+
13
+ def initialize(port = 9394)
14
+ return if port == 0
15
+
16
+ configure_server(port)
17
+ configure_metrics
18
+ end
19
+
20
+ def stop_server
21
+ @server&.stop
22
+ end
23
+
24
+ def record_error(type = :general)
25
+ @error_counter&.observe(1, :type => type.to_s)
26
+ end
27
+
28
+ def record_operation(name, labels = {})
29
+ @status_counter&.observe(1, (labels || {}).merge(:name => name))
30
+ end
31
+
32
+ def record_operation_time(name, labels = {}, &block)
33
+ record_time(@duration_seconds, (labels || {}).merge(:name => name), &block)
34
+ end
35
+
36
+ # Common method for gauge
37
+ def record_gauge(metric, opt, value: nil, labels: {})
38
+ case opt
39
+ when :set then
40
+ metric&.observe(value.to_i, labels)
41
+ when :add then
42
+ metric&.increment(labels)
43
+ when :remove then
44
+ metric&.decrement(labels)
45
+ end
46
+ end
47
+
48
+ # Common method for histogram
49
+ def record_time(metric, labels = {})
50
+ result = nil
51
+ time = Benchmark.realtime { result = yield }
52
+ metric&.observe(time, labels)
53
+ result
54
+ end
55
+
56
+ private
57
+
58
+ def configure_server(port)
59
+ @server = PrometheusExporter::Server::WebServer.new(:port => port)
60
+ @server.start
61
+
62
+ PrometheusExporter::Client.default = PrometheusExporter::LocalClient.new(:collector => @server.collector)
63
+ end
64
+
65
+ def configure_metrics
66
+ PrometheusExporter::Instrumentation::Process.start
67
+ PrometheusExporter::Metric::Base.default_prefix = default_prefix
68
+
69
+ @duration_seconds = PrometheusExporter::Metric::Histogram.new('duration_seconds', 'Duration of processed operation')
70
+ @error_counter = PrometheusExporter::Metric::Counter.new("error", ERROR_COUNTER_MESSAGE)
71
+ @status_counter = PrometheusExporter::Metric::Counter.new('status_counter', 'number of processed operations')
72
+
73
+ [@duration_seconds, @error_counter, @status_counter].each do |metric|
74
+ @server.collector.register_metric(metric)
75
+ end
76
+ end
77
+
78
+ def default_prefix
79
+ raise NotImplementedError, "#{__method__} must be implemented in a subclass"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -14,6 +14,7 @@ module TopologicalInventory
14
14
  def endpoint
15
15
  @endpoint ||= sources_api.fetch_default_endpoint(source_id)
16
16
  rescue => e
17
+ metrics&.record_error(:sources_api)
17
18
  logger.error_ext(operation, "Failed to fetch Endpoint for Source #{source_id}: #{e.message}")
18
19
  nil
19
20
  end
@@ -25,6 +26,7 @@ module TopologicalInventory
25
26
  sources_api.fetch_authentication(source_id, endpoint)
26
27
  end
27
28
  rescue => e
29
+ metrics&.record_error(:sources_api)
28
30
  logger.error_ext(operation, "Failed to fetch Authentication for Source #{source_id}: #{e.message}")
29
31
  nil
30
32
  end
@@ -32,6 +34,7 @@ module TopologicalInventory
32
34
  def application
33
35
  @application ||= sources_api.fetch_application(source_id)
34
36
  rescue => e
37
+ metrics&.record_error(:sources_api)
35
38
  logger.error_ext(operation, "Failed to fetch Application for Source #{source_id}: #{e.message}")
36
39
  nil
37
40
  end
@@ -0,0 +1,19 @@
1
+ module TopologicalInventory
2
+ module Providers
3
+ module Common
4
+ module Mixins
5
+ module Statuses
6
+ def operation_status
7
+ return @statuses if @statuses.present?
8
+
9
+ @statuses = {}
10
+ %i[success error skipped not_implemented].each do |status|
11
+ @statuses[status] = status.to_s
12
+ end
13
+ @statuses
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,77 @@
1
+ require "topological_inventory/providers/common/logging"
2
+ require "topological_inventory/providers/common/mixins/statuses"
3
+ require "topological_inventory/providers/common/mixins/topology_api"
4
+
5
+ module TopologicalInventory
6
+ module Providers
7
+ module Common
8
+ module Operations
9
+ class Processor
10
+ include Logging
11
+ include Mixins::Statuses
12
+ include Mixins::TopologyApi
13
+
14
+ def self.process!(message, metrics)
15
+ new(message, metrics).process
16
+ end
17
+
18
+ def initialize(message, metrics)
19
+ self.message = message
20
+ self.metrics = metrics
21
+ self.model, self.method = message.message.split(".")
22
+
23
+ self.params = message.payload["params"]
24
+ self.identity = message.payload["request_context"]
25
+ end
26
+
27
+ def process
28
+ logger.info(status_log_msg)
29
+ impl = operation_class&.new(params, identity, metrics)
30
+ if impl&.respond_to?(method)
31
+ with_time_measure do
32
+ result = impl.send(method)
33
+
34
+ logger.info(status_log_msg("Complete"))
35
+ result
36
+ end
37
+ else
38
+ logger.warn(status_log_msg("Not Implemented!"))
39
+ complete_task("not implemented") if params["task_id"]
40
+ operation_status[:not_implemented]
41
+ end
42
+ rescue StandardError, NotImplementedError => e
43
+ complete_task(e.message) if params["task_id"]
44
+ raise
45
+ end
46
+
47
+ private
48
+
49
+ attr_accessor :message, :identity, :model, :method, :metrics, :params
50
+
51
+ def operation_class
52
+ raise NotImplementedError, "#{__method__} must be implemented in a subclass"
53
+ end
54
+
55
+ def with_time_measure
56
+ if metrics.present?
57
+ metrics.record_operation_time(message.message) { yield }
58
+ else
59
+ yield
60
+ end
61
+ end
62
+
63
+ def complete_task(msg, status = "error")
64
+ update_task(params["task_id"],
65
+ :state => "completed",
66
+ :status => status,
67
+ :context => {:error => "#{model}##{method} - #{msg}"})
68
+ end
69
+
70
+ def status_log_msg(status = nil)
71
+ "Processing #{model}##{method} [#{params}]...#{status}"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,7 +1,9 @@
1
1
  require "topological_inventory/providers/common/logging"
2
2
  require "active_support/core_ext/numeric/time"
3
3
  require "topological_inventory/providers/common/mixins/sources_api"
4
+ require "topological_inventory/providers/common/mixins/statuses"
4
5
  require "topological_inventory/providers/common/mixins/x_rh_headers"
6
+ require "topological_inventory/providers/common/messaging_client"
5
7
 
6
8
  module TopologicalInventory
7
9
  module Providers
@@ -11,8 +13,11 @@ module TopologicalInventory
11
13
  include Logging
12
14
  include Mixins::SourcesApi
13
15
  include Mixins::XRhHeaders
16
+ include Mixins::Statuses
14
17
 
15
18
  STATUS_AVAILABLE, STATUS_UNAVAILABLE = %w[available unavailable].freeze
19
+ EVENT_AVAILABILITY_STATUS = "availability_status".freeze
20
+ SERVICE_NAME = "platform.sources.status".freeze
16
21
 
17
22
  ERROR_MESSAGES = {
18
23
  :authentication_not_found => "Authentication not found in Sources API",
@@ -20,36 +25,41 @@ module TopologicalInventory
20
25
  }.freeze
21
26
 
22
27
  LAST_CHECKED_AT_THRESHOLD = 5.minutes.freeze
23
- AUTH_NOT_NECESSARY = "n/a".freeze
28
+ AUTH_NOT_NECESSARY = "n/a".freeze
24
29
 
25
30
  attr_accessor :identity, :operation, :params, :request_context, :source_id, :account_number
26
31
 
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']
32
-
33
- self.account_number = params['external_tenant']
34
- self.identity = identity_by_account_number(account_number)
32
+ def initialize(params = {}, request_context = nil, metrics = nil)
33
+ self.metrics = metrics
34
+ self.operation = 'Source'
35
+ self.params = params
36
+ self.request_context = request_context
37
+ self.source_id = params['source_id']
38
+ self.account_number = params['external_tenant']
39
+ self.updates_via_kafka = ENV['UPDATE_SOURCES_VIA_API'].blank?
40
+ self.identity = identity_by_account_number(account_number)
35
41
  end
36
42
 
37
43
  def availability_check
38
44
  self.operation += '#availability_check'
39
45
 
40
- return if params_missing?
46
+ return operation_status[:error] if params_missing?
41
47
 
42
- return if checked_recently?
48
+ return operation_status[:skipped] if checked_recently?
43
49
 
44
50
  status, error_message = connection_status
45
51
 
46
52
  update_source_and_subresources(status, error_message)
47
53
 
48
54
  logger.availability_check("Completed: Source #{source_id} is #{status}")
55
+
56
+ operation_status[:success]
49
57
  end
50
58
 
51
59
  private
52
60
 
61
+ attr_accessor :metrics, :updates_via_kafka
62
+
53
63
  def required_params
54
64
  %w[source_id]
55
65
  end
@@ -114,10 +124,15 @@ module TopologicalInventory
114
124
  def update_source_and_subresources(status, error_message = nil)
115
125
  logger.availability_check("Updating source [#{source_id}] status [#{status}] message [#{error_message}]")
116
126
 
117
- update_source(status)
118
-
119
- update_endpoint(status, error_message) if endpoint
120
- update_application(status) if application
127
+ if updates_via_kafka
128
+ update_source_by_kafka(status)
129
+ update_endpoint_by_kafka(status, error_message) if endpoint
130
+ update_application_by_kafka(status) if application
131
+ else
132
+ update_source(status)
133
+ update_endpoint(status, error_message) if endpoint
134
+ update_application(status) if application
135
+ end
121
136
  end
122
137
 
123
138
  def update_source(status)
@@ -128,9 +143,18 @@ module TopologicalInventory
128
143
 
129
144
  sources_api.update_source(source_id, source)
130
145
  rescue ::SourcesApiClient::ApiError => e
146
+ metrics&.record_error(:sources_api)
131
147
  logger.availability_check("Failed to update Source id:#{source_id} - #{e.message}", :error)
132
148
  end
133
149
 
150
+ def update_source_by_kafka(status)
151
+ availability_status_message(
152
+ :resource_type => "Source",
153
+ :resource_id => source_id,
154
+ :status => status
155
+ )
156
+ end
157
+
134
158
  def update_endpoint(status, error_message)
135
159
  if endpoint.nil?
136
160
  logger.availability_check("Failed to update Endpoint for Source id:#{source_id}. Endpoint not found", :error)
@@ -146,19 +170,59 @@ module TopologicalInventory
146
170
 
147
171
  sources_api.update_endpoint(endpoint.id, endpoint_update)
148
172
  rescue ::SourcesApiClient::ApiError => e
173
+ metrics&.record_error(:sources_api)
149
174
  logger.availability_check("Failed to update Endpoint(ID: #{endpoint.id}) - #{e.message}", :error)
150
175
  end
151
176
 
177
+ def update_endpoint_by_kafka(status, error_message)
178
+ if endpoint.nil?
179
+ logger.availability_check("Failed to update Endpoint for Source id:#{source_id}. Endpoint not found", :error)
180
+ return
181
+ end
182
+
183
+ availability_status_message(
184
+ :resource_type => "Endpoint",
185
+ :resource_id => endpoint.id,
186
+ :status => status,
187
+ :error => error_message
188
+ )
189
+ end
190
+
152
191
  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
192
+ application_update = ::SourcesApiClient::Application.new
193
+ application_update.last_checked_at = check_time
194
+ application_update.last_available_at = check_time if status == STATUS_AVAILABLE
156
195
 
157
196
  sources_api.update_application(application.id, application_update)
158
197
  rescue ::SourcesApiClient::ApiError => e
198
+ metrics&.record_error(:sources_api)
159
199
  logger.availability_check("Failed to update Application id: #{application.id} - #{e.message}", :error)
160
200
  end
161
201
 
202
+ def update_application_by_kafka(status)
203
+ availability_status_message(
204
+ :resource_type => "Application",
205
+ :resource_id => application.id,
206
+ :status => status
207
+ )
208
+ end
209
+
210
+ def availability_status_message(payload)
211
+ messaging_client.publish_message(
212
+ :service => SERVICE_NAME,
213
+ :message => EVENT_AVAILABILITY_STATUS,
214
+ :payload => payload.to_json
215
+ )
216
+ rescue => err
217
+ logger.availability_check("Failed to update Application id: #{application.id} - #{err.message}", :error)
218
+ ensure
219
+ messaging_client&.close
220
+ end
221
+
222
+ def messaging_client
223
+ TopologicalInventory::Providers::Common::MessagingClient.default.client
224
+ end
225
+
162
226
  def check_time
163
227
  @check_time ||= Time.now.utc
164
228
  end
@@ -1,7 +1,7 @@
1
1
  module TopologicalInventory
2
2
  module Providers
3
3
  module Common
4
- VERSION = "2.0.0".freeze
4
+ VERSION = "2.1.0".freeze
5
5
  end
6
6
  end
7
7
  end
@@ -7,8 +7,12 @@ RSpec.shared_examples "availability_check" do
7
7
  let(:sources_api_url) { "#{host_url}#{sources_api_path}" }
8
8
 
9
9
  let(:external_tenant) { '11001' }
10
+ let(:kafka_client) { TopologicalInventory::Providers::Common::MessagingClient.default.client }
10
11
  let(:identity) { {'x-rh-identity' => Base64.strict_encode64({'identity' => {'account_number' => external_tenant, 'user' => {'is_org_admin' => true}}}.to_json)} }
11
12
  let(:headers) { {'Content-Type' => 'application/json'}.merge(identity) }
13
+ let(:status_available) { described_class::STATUS_AVAILABLE }
14
+ let(:status_unavailable) { described_class::STATUS_UNAVAILABLE }
15
+ let(:error_message) { 'error_message' }
12
16
  let(:source_id) { '123' }
13
17
  let(:endpoint_id) { '234' }
14
18
  let(:application_id) { '345' }
@@ -32,101 +36,208 @@ RSpec.shared_examples "availability_check" do
32
36
 
33
37
  subject { described_class.new(payload["params"]) }
34
38
 
39
+ def kafka_message(resource_type, resource_id, status, error_message = nil)
40
+ res = {
41
+ :service => described_class::SERVICE_NAME,
42
+ :message => described_class::EVENT_AVAILABILITY_STATUS,
43
+ :payload => {
44
+ :resource_type => resource_type,
45
+ :resource_id => resource_id,
46
+ :status => status
47
+ }
48
+ }
49
+ res[:payload][:error] = error_message if error_message
50
+ res[:payload] = res[:payload].to_json
51
+ res
52
+ end
53
+
54
+ before do
55
+ allow(subject).to receive(:messaging_client).and_return(kafka_client)
56
+ end
57
+
35
58
  context "when not checked recently" do
36
59
  before do
37
60
  allow(subject).to receive(:checked_recently?).and_return(false)
38
61
  end
39
62
 
40
- it "updates Source and Endpoint when available" do
41
- # GET
42
- stub_get(:endpoint, list_endpoints_response)
43
- stub_get(:authentication, list_endpoint_authentications_response)
44
- stub_get(:password, internal_api_authentication_response)
45
- stub_not_found(:application)
63
+ context 'kafka' do
64
+ it 'updates Source and Endpoint when available' do
65
+ stub_get(:endpoint, list_endpoints_response)
66
+ stub_get(:application, list_applications_response)
46
67
 
47
- # PATCH
48
- source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
49
- endpoint_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'availability_status_error' => '', 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
68
+ expect(subject).to receive(:connection_status).and_return([status_available, ''])
50
69
 
51
- stub_patch(:source, source_patch_body)
52
- stub_patch(:endpoint, endpoint_patch_body)
70
+ expect(kafka_client).to receive(:publish_message).with(
71
+ kafka_message("Source", source_id, status_available)
72
+ )
53
73
 
54
- # Check ---
55
- expect(subject).to receive(:connection_check).and_return([described_class::STATUS_AVAILABLE, nil])
74
+ expect(kafka_client).to receive(:publish_message).with(
75
+ kafka_message("Endpoint", endpoint_id, status_available, '')
76
+ )
56
77
 
57
- subject.availability_check
78
+ expect(kafka_client).to receive(:publish_message).with(
79
+ kafka_message("Application", application_id, status_available)
80
+ )
58
81
 
59
- assert_patch(:source, source_patch_body)
60
- assert_patch(:endpoint, endpoint_patch_body)
61
- end
82
+ subject.availability_check
83
+ end
62
84
 
63
- it "updates Source and Endpoint when unavailable" do
64
- # GET
65
- stub_get(:endpoint, list_endpoints_response)
66
- stub_get(:authentication, list_endpoint_authentications_response)
67
- stub_get(:password, internal_api_authentication_response)
68
- stub_not_found(:application)
69
85
 
70
- # PATCH
71
- connection_error_message = "Some connection error"
72
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
73
- endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => connection_error_message, 'last_checked_at' => subject.send(:check_time)}.to_json
86
+ it "updates Source and Endpoint when unavailable" do
87
+ stub_get(:endpoint, list_endpoints_response)
88
+ stub_get(:application, list_applications_response)
74
89
 
75
- stub_patch(:source, source_patch_body)
76
- stub_patch(:endpoint, endpoint_patch_body)
90
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
77
91
 
78
- # Check ---
79
- expect(subject).to receive(:connection_check).and_return([described_class::STATUS_UNAVAILABLE, connection_error_message])
92
+ expect(kafka_client).to receive(:publish_message).with(
93
+ kafka_message("Source", source_id, status_unavailable)
94
+ )
80
95
 
81
- subject.availability_check
96
+ expect(kafka_client).to receive(:publish_message).with(
97
+ kafka_message("Endpoint", endpoint_id, status_unavailable, error_message)
98
+ )
82
99
 
83
- assert_patch(:source, source_patch_body)
84
- assert_patch(:endpoint, endpoint_patch_body)
85
- end
100
+ expect(kafka_client).to receive(:publish_message).with(
101
+ kafka_message("Application", application_id, status_unavailable)
102
+ )
86
103
 
87
- it "updates only Source to 'unavailable' status if Endpoint not found" do
88
- # GET
89
- stub_not_found(:endpoint)
90
- stub_not_found(:application)
104
+ subject.availability_check
105
+ end
91
106
 
92
- # PATCH
93
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
94
- stub_patch(:source, source_patch_body)
107
+ it "updates only Source to 'unavailable' status if Endpoint not found" do
108
+ stub_not_found(:endpoint)
109
+ stub_not_found(:application)
95
110
 
96
- # Check
97
- api_client = subject.send(:sources_api)
98
- expect(api_client).not_to receive(:update_endpoint)
111
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
99
112
 
100
- subject.availability_check
113
+ expect(kafka_client).to receive(:publish_message).with(
114
+ kafka_message("Source", source_id, status_unavailable)
115
+ )
116
+
117
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_unavailable}] message [#{error_message}]")
118
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_unavailable}")
119
+
120
+ subject.availability_check
121
+ end
122
+
123
+ it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
124
+ stub_get(:endpoint, list_endpoints_response)
125
+ stub_not_found(:application)
126
+
127
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
128
+
129
+ expect(kafka_client).to receive(:publish_message).with(
130
+ kafka_message("Source", source_id, status_unavailable)
131
+ )
132
+
133
+ expect(kafka_client).to receive(:publish_message).with(
134
+ kafka_message("Endpoint", endpoint_id, status_unavailable, error_message)
135
+ )
101
136
 
102
- assert_patch(:source, source_patch_body)
137
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_unavailable}] message [#{error_message}]")
138
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_unavailable}")
139
+
140
+ subject.availability_check
141
+ end
103
142
  end
104
143
 
105
- it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
106
- # GET
107
- stub_get(:endpoint, list_endpoints_response)
108
- stub_get(:authentication, list_endpoint_authentications_response_empty)
109
- stub_not_found(:application)
144
+ context 'sources_api' do
145
+ before do
146
+ subject.send(:updates_via_kafka=, false)
147
+ end
110
148
 
111
- # PATCH
112
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
113
- endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => described_class::ERROR_MESSAGES[:authentication_not_found], 'last_checked_at' => subject.send(:check_time)}.to_json
149
+ it "updates Source and Endpoint when available" do
150
+ # GET
151
+ stub_get(:endpoint, list_endpoints_response)
152
+ stub_get(:authentication, list_endpoint_authentications_response)
153
+ stub_get(:password, internal_api_authentication_response)
154
+ stub_not_found(:application)
114
155
 
115
- stub_patch(:source, source_patch_body)
116
- stub_patch(:endpoint, endpoint_patch_body)
156
+ # PATCH
157
+ source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
158
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'availability_status_error' => '', 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
117
159
 
118
- # Check
119
- expect(subject).not_to receive(:connection_check)
120
- subject.availability_check
160
+ stub_patch(:source, source_patch_body)
161
+ stub_patch(:endpoint, endpoint_patch_body)
162
+
163
+ # Check ---
164
+ expect(subject).to receive(:connection_check).and_return([described_class::STATUS_AVAILABLE, nil])
165
+
166
+ subject.availability_check
167
+
168
+ assert_patch(:source, source_patch_body)
169
+ assert_patch(:endpoint, endpoint_patch_body)
170
+ end
171
+
172
+ it "updates Source and Endpoint when unavailable" do
173
+ # GET
174
+ stub_get(:endpoint, list_endpoints_response)
175
+ stub_get(:authentication, list_endpoint_authentications_response)
176
+ stub_get(:password, internal_api_authentication_response)
177
+ stub_not_found(:application)
178
+
179
+ # PATCH
180
+ connection_error_message = "Some connection error"
181
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
182
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => connection_error_message, 'last_checked_at' => subject.send(:check_time)}.to_json
183
+
184
+ stub_patch(:source, source_patch_body)
185
+ stub_patch(:endpoint, endpoint_patch_body)
186
+
187
+ # Check ---
188
+ expect(subject).to receive(:connection_check).and_return([described_class::STATUS_UNAVAILABLE, connection_error_message])
189
+
190
+ subject.availability_check
191
+
192
+ assert_patch(:source, source_patch_body)
193
+ assert_patch(:endpoint, endpoint_patch_body)
194
+ end
195
+
196
+ it "updates only Source to 'unavailable' status if Endpoint not found" do
197
+ # GET
198
+ stub_not_found(:endpoint)
199
+ stub_not_found(:application)
200
+
201
+ # PATCH
202
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
203
+ stub_patch(:source, source_patch_body)
204
+
205
+ # Check
206
+ api_client = subject.send(:sources_api)
207
+ expect(api_client).not_to receive(:update_endpoint)
208
+
209
+ subject.availability_check
210
+
211
+ assert_patch(:source, source_patch_body)
212
+ end
213
+
214
+ it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
215
+ # GET
216
+ stub_get(:endpoint, list_endpoints_response)
217
+ stub_get(:authentication, list_endpoint_authentications_response_empty)
218
+ stub_not_found(:application)
121
219
 
122
- assert_patch(:source, source_patch_body)
123
- assert_patch(:endpoint, endpoint_patch_body)
220
+ # PATCH
221
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
222
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => described_class::ERROR_MESSAGES[:authentication_not_found], 'last_checked_at' => subject.send(:check_time)}.to_json
223
+
224
+ stub_patch(:source, source_patch_body)
225
+ stub_patch(:endpoint, endpoint_patch_body)
226
+
227
+ # Check
228
+ expect(subject).not_to receive(:connection_check)
229
+ subject.availability_check
230
+
231
+ assert_patch(:source, source_patch_body)
232
+ assert_patch(:endpoint, endpoint_patch_body)
233
+ end
124
234
  end
125
235
  end
126
236
 
127
237
  context "when checked recently" do
128
238
  before do
129
239
  allow(subject).to receive(:checked_recently?).and_return(true)
240
+ subject.send(:updates_via_kafka=, false)
130
241
  end
131
242
 
132
243
  it "doesn't do connection check" do
@@ -140,44 +251,97 @@ RSpec.shared_examples "availability_check" do
140
251
 
141
252
  context "when there is an application" do
142
253
  context "when it is available" do
143
- it "updates the availability status to available" do
144
- # GET
145
- stub_not_found(:endpoint)
146
- stub_get(:application, list_applications_response)
147
- # PATCH
148
- application_patch_body = {'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
149
- source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
254
+ context 'kafka' do
255
+ it "updates the availability status to available" do
256
+ stub_not_found(:endpoint)
257
+ stub_get(:application, list_applications_response)
150
258
 
151
- stub_patch(:source, source_patch_body)
152
- stub_patch(:application, application_patch_body)
259
+ expect(subject).to receive(:connection_status).and_return([status_available, ''])
153
260
 
154
- # Check
155
- expect(subject).not_to receive(:connection_check)
156
- subject.availability_check
261
+ expect(kafka_client).to receive(:publish_message).with(
262
+ kafka_message("Source", source_id, status_available)
263
+ )
157
264
 
158
- assert_patch(:source, source_patch_body)
159
- assert_patch(:application, application_patch_body)
265
+ expect(kafka_client).to receive(:publish_message).with(
266
+ kafka_message("Application", application_id, status_available)
267
+ )
268
+
269
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_available}] message []")
270
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_available}")
271
+
272
+ subject.availability_check
273
+ end
274
+ end
275
+
276
+ context 'sources_api' do
277
+ before do
278
+ subject.send(:updates_via_kafka=, false)
279
+ end
280
+
281
+ it "updates the availability status to available" do
282
+ # GET
283
+ stub_not_found(:endpoint)
284
+ stub_get(:application, list_applications_response)
285
+ # PATCH
286
+ application_patch_body = {'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
287
+ source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
288
+
289
+ stub_patch(:source, source_patch_body)
290
+ stub_patch(:application, application_patch_body)
291
+
292
+ # Check
293
+ expect(subject).not_to receive(:connection_check)
294
+ subject.availability_check
295
+
296
+ assert_patch(:source, source_patch_body)
297
+ assert_patch(:application, application_patch_body)
298
+ end
160
299
  end
161
300
  end
162
301
 
163
302
  context "when it is unavailable" do
164
- it "updates the availability status to unavailable" do
165
- # GET
166
- stub_not_found(:endpoint)
167
- stub_get(:application, list_applications_unavailable_response)
168
- # PATCH
169
- application_patch_body = {'last_checked_at' => subject.send(:check_time)}.to_json
170
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
303
+ context 'kafka' do
304
+ it "updates the availability status to unavailable" do
305
+ stub_not_found(:endpoint)
306
+ stub_get(:application, list_applications_unavailable_response)
171
307
 
172
- stub_patch(:source, source_patch_body)
173
- stub_patch(:application, application_patch_body)
308
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
174
309
 
175
- # Check
176
- expect(subject).not_to receive(:connection_check)
177
- subject.availability_check
310
+ expect(kafka_client).to receive(:publish_message).with(
311
+ kafka_message("Source", source_id, status_unavailable)
312
+ )
178
313
 
179
- assert_patch(:source, source_patch_body)
180
- assert_patch(:application, application_patch_body)
314
+ expect(kafka_client).to receive(:publish_message).with(
315
+ kafka_message("Application", application_id, status_unavailable)
316
+ )
317
+
318
+ subject.availability_check
319
+ end
320
+ end
321
+
322
+ context 'sources_api' do
323
+ before do
324
+ subject.send(:updates_via_kafka=, false)
325
+ end
326
+
327
+ it "updates the availability status to unavailable" do
328
+ # GET
329
+ stub_not_found(:endpoint)
330
+ stub_get(:application, list_applications_unavailable_response)
331
+ # PATCH
332
+ application_patch_body = {'last_checked_at' => subject.send(:check_time)}.to_json
333
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
334
+
335
+ stub_patch(:source, source_patch_body)
336
+ stub_patch(:application, application_patch_body)
337
+
338
+ # Check
339
+ expect(subject).not_to receive(:connection_check)
340
+ subject.availability_check
341
+
342
+ assert_patch(:source, source_patch_body)
343
+ assert_patch(:application, application_patch_body)
344
+ end
181
345
  end
182
346
  end
183
347
  end
@@ -0,0 +1,71 @@
1
+ require "topological_inventory/providers/common/operations/processor"
2
+
3
+ RSpec.describe TopologicalInventory::Providers::Common::Operations::Processor do
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) }
8
+
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')
14
+
15
+ klass = TopologicalInventory::Providers::Common::Operations::Source
16
+ allow(subject).to receive(:operation_class).and_return(klass)
17
+
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)
21
+
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')
28
+
29
+ expect(subject.process).to eq(subject.operation_status[:not_implemented])
30
+ end
31
+
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')
35
+
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)
51
+ end
52
+ end
53
+
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)
63
+ end
64
+
65
+ it "only yields if metrics not present" do
66
+ expect(metrics).not_to receive(:record_operation_time)
67
+
68
+ expect(subject.send(:with_time_measure) { 42 }).to eq(42)
69
+ end
70
+ end
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: 2.0.0
4
+ version: 2.1.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-20 00:00:00.000000000 Z
11
+ date: 2020-11-02 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,11 +310,15 @@ 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
313
+ - lib/topological_inventory/providers/common/messaging_client.rb
314
+ - lib/topological_inventory/providers/common/metrics.rb
255
315
  - lib/topological_inventory/providers/common/mixins/sources_api.rb
316
+ - lib/topological_inventory/providers/common/mixins/statuses.rb
256
317
  - lib/topological_inventory/providers/common/mixins/topology_api.rb
257
318
  - lib/topological_inventory/providers/common/mixins/x_rh_headers.rb
258
319
  - lib/topological_inventory/providers/common/operations/async_worker.rb
259
320
  - lib/topological_inventory/providers/common/operations/health_check.rb
321
+ - lib/topological_inventory/providers/common/operations/processor.rb
260
322
  - lib/topological_inventory/providers/common/operations/source.rb
261
323
  - lib/topological_inventory/providers/common/save_inventory/exception.rb
262
324
  - lib/topological_inventory/providers/common/save_inventory/saver.rb
@@ -272,6 +334,7 @@ files:
272
334
  - spec/topological_inventory/providers/common/collectors_pool_spec.rb
273
335
  - spec/topological_inventory/providers/common/logger_spec.rb
274
336
  - spec/topological_inventory/providers/common/operations/async_worker_spec.rb
337
+ - spec/topological_inventory/providers/common/operations/processor_spec.rb
275
338
  - spec/topological_inventory/providers/common/operations/source_spec.rb
276
339
  - spec/topological_inventory/providers/common/save_inventory/saver_spec.rb
277
340
  - spec/topological_inventory/providers/common_spec.rb