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 +4 -4
- data/.codeclimate.yml +31 -0
- data/.rubocop.yml +1 -1
- data/.yamllint +8 -0
- data/CHANGELOG.md +8 -2
- data/lib/topological_inventory/providers/common.rb +1 -0
- data/lib/topological_inventory/providers/common/messaging_client.rb +40 -0
- data/lib/topological_inventory/providers/common/metrics.rb +84 -0
- data/lib/topological_inventory/providers/common/mixins/sources_api.rb +3 -0
- data/lib/topological_inventory/providers/common/mixins/statuses.rb +19 -0
- data/lib/topological_inventory/providers/common/operations/processor.rb +77 -0
- data/lib/topological_inventory/providers/common/operations/source.rb +82 -18
- data/lib/topological_inventory/providers/common/version.rb +1 -1
- data/spec/support/shared/availability_check.rb +254 -90
- data/spec/topological_inventory/providers/common/operations/processor_spec.rb +71 -0
- data/topological_inventory-providers-common.gemspec +14 -10
- metadata +69 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aad209b97efea9bb19ce488782adb1dabfa8d650c12f8637e2b348ed4ec95a15
|
4
|
+
data.tar.gz: 69b9bbed6a2d725990206ab3bfc7b13ec25b10f7e0c1a979b48c61b67e53fd0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45722b70f009a764d8cd804424157cc98b1a225b72326b8b8971fecd093fa6260446777db76bc3502e487d27dc82b2b4325959302f4a1abe13fbbf8c015c1d54
|
7
|
+
data.tar.gz: b1a6de8e2eb93b2b26d4b609f17a1a518cf4b318dbcf117c6225fe297bb3ec97f870b944e151786977ad90f42c16746eeeadf6a3d113b648921e278cb831aadd
|
data/.codeclimate.yml
ADDED
@@ -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
|
data/.rubocop.yml
CHANGED
data/.yamllint
ADDED
data/CHANGELOG.md
CHANGED
@@ -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.
|
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.
|
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
|
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.
|
29
|
-
self.
|
30
|
-
self.
|
31
|
-
self.
|
32
|
-
|
33
|
-
self.account_number
|
34
|
-
self.
|
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
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
154
|
-
application_update.last_checked_at
|
155
|
-
application_update.last_available_at
|
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
|
@@ -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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
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
|
-
|
52
|
-
|
70
|
+
expect(kafka_client).to receive(:publish_message).with(
|
71
|
+
kafka_message("Source", source_id, status_available)
|
72
|
+
)
|
53
73
|
|
54
|
-
|
55
|
-
|
74
|
+
expect(kafka_client).to receive(:publish_message).with(
|
75
|
+
kafka_message("Endpoint", endpoint_id, status_available, '')
|
76
|
+
)
|
56
77
|
|
57
|
-
|
78
|
+
expect(kafka_client).to receive(:publish_message).with(
|
79
|
+
kafka_message("Application", application_id, status_available)
|
80
|
+
)
|
58
81
|
|
59
|
-
|
60
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
76
|
-
stub_patch(:endpoint, endpoint_patch_body)
|
90
|
+
expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
|
77
91
|
|
78
|
-
|
79
|
-
|
92
|
+
expect(kafka_client).to receive(:publish_message).with(
|
93
|
+
kafka_message("Source", source_id, status_unavailable)
|
94
|
+
)
|
80
95
|
|
81
|
-
|
96
|
+
expect(kafka_client).to receive(:publish_message).with(
|
97
|
+
kafka_message("Endpoint", endpoint_id, status_unavailable, error_message)
|
98
|
+
)
|
82
99
|
|
83
|
-
|
84
|
-
|
85
|
-
|
100
|
+
expect(kafka_client).to receive(:publish_message).with(
|
101
|
+
kafka_message("Application", application_id, status_unavailable)
|
102
|
+
)
|
86
103
|
|
87
|
-
|
88
|
-
|
89
|
-
stub_not_found(:endpoint)
|
90
|
-
stub_not_found(:application)
|
104
|
+
subject.availability_check
|
105
|
+
end
|
91
106
|
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
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
|
-
|
116
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
123
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
152
|
-
stub_patch(:application, application_patch_body)
|
259
|
+
expect(subject).to receive(:connection_status).and_return([status_available, ''])
|
153
260
|
|
154
|
-
|
155
|
-
|
156
|
-
|
261
|
+
expect(kafka_client).to receive(:publish_message).with(
|
262
|
+
kafka_message("Source", source_id, status_available)
|
263
|
+
)
|
157
264
|
|
158
|
-
|
159
|
-
|
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
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
173
|
-
stub_patch(:application, application_patch_body)
|
308
|
+
expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
|
174
309
|
|
175
|
-
|
176
|
-
|
177
|
-
|
310
|
+
expect(kafka_client).to receive(:publish_message).with(
|
311
|
+
kafka_message("Source", source_id, status_unavailable)
|
312
|
+
)
|
178
313
|
|
179
|
-
|
180
|
-
|
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
|
30
|
-
spec.add_runtime_dependency
|
31
|
-
spec.add_runtime_dependency
|
32
|
-
spec.add_runtime_dependency
|
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
|
35
|
-
spec.add_development_dependency
|
36
|
-
spec.add_development_dependency
|
37
|
-
spec.add_development_dependency 'rubocop', '~>0.
|
38
|
-
spec.add_development_dependency 'rubocop-performance', '~>1.
|
39
|
-
spec.add_development_dependency
|
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.
|
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-
|
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.
|
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.
|
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.
|
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: '
|
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
|