topological_inventory-providers-common 2.0.0 → 2.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +31 -0
- data/.rubocop.yml +1 -1
- data/.yamllint +8 -0
- data/CHANGELOG.md +26 -3
- data/README.md +1 -1
- 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 +109 -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/async_worker.rb +12 -7
- data/lib/topological_inventory/providers/common/operations/processor.rb +77 -0
- data/lib/topological_inventory/providers/common/operations/source.rb +83 -19
- 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/async_worker_spec.rb +14 -5
- 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: 9c17638d4fd82db196de0019069a765bf1c6becdb20498765507ae35a02727eb
|
4
|
+
data.tar.gz: a395cd7243591bc3dab9f841e491bb978a2502d2ba1cfec3fdb004de784523dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba2b33ec9748ef58b4ca7dc30f14d34443c17026e7915fb2bd9aef2a4ec95c4c287a8149a371b91cab88974a0341f7dfd362a987ca55ea644a5b67646adafde6
|
7
|
+
data.tar.gz: 41edf911fa71ef7dcdaa220a417a236e8a593a01e227ab4f0f88e70318141f8736ad8bd9bff7e642d6cef1134d017baa8aea0c1c194987b08770a721a7a2ff00
|
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
@@ -3,11 +3,30 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
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
|
+
## [2.1.4] - 2020-12-14
|
7
|
+
Common Counter metrics init #71
|
6
8
|
|
7
|
-
## [2.
|
9
|
+
## [2.1.3] - 2020-12-14
|
10
|
+
Update travis URL in README file #67
|
11
|
+
Kafka availability_checks fix #68
|
12
|
+
|
13
|
+
## [2.1.2] - 2020-11-24
|
14
|
+
Custom Metrics for AsyncWorker #60
|
15
|
+
Change error metric name to errors_total #64
|
16
|
+
|
17
|
+
## [2.1.1] - 2020-11-04
|
18
|
+
MessagingClient and Source fix #61
|
19
|
+
Fix availability_check in app check #62
|
20
|
+
|
21
|
+
## [2.1.0] - 2020-11-02
|
22
|
+
Add Availability checks for sources via Kafka #54
|
23
|
+
Common Metrics exporter #57
|
24
|
+
Rubocop rules from insights-api-common + yamllint #59
|
25
|
+
|
26
|
+
## [2.0.0] - 2020-10-20
|
8
27
|
Operations/API clients refactoring
|
9
28
|
|
10
|
-
## [1.0.12] - 2020-10-
|
29
|
+
## [1.0.12] - 2020-10-05
|
11
30
|
Add Operations Async Worker class #55
|
12
31
|
|
13
32
|
## [1.0.11] - 2020-09-04
|
@@ -62,7 +81,11 @@ manageiq-loggers to >= 0.4.2 #20
|
|
62
81
|
## [1.0.0] - 2020-03-19
|
63
82
|
### Initial release to rubygems.org
|
64
83
|
|
65
|
-
[Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.
|
84
|
+
[Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.1.3...HEAD
|
85
|
+
[2.1.3]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.1.2...v2.1.3
|
86
|
+
[2.1.2]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.1.1...v2.1.2
|
87
|
+
[2.1.1]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.1.0...v2.1.1
|
88
|
+
[2.1.0]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v2.0.0...v2.1.0
|
66
89
|
[2.0.0]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.12...v2.0.0
|
67
90
|
[1.0.12]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.11...v1.0.12
|
68
91
|
[1.0.11]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.10...v1.0.11
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# TopologicalInventory::Providers::Common
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.
|
3
|
+
[![Build Status](https://travis-ci.com/RedHatInsights/topological_inventory-providers-common.svg?branch=master)](https://travis-ci.com/RedHatInsights/topological_inventory-providers-common)
|
4
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/df747492b802bfea3c83/maintainability)](https://codeclimate.com/github/RedHatInsights/topological_inventory-providers-common/maintainability)
|
5
5
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/df747492b802bfea3c83/test_coverage)](https://codeclimate.com/github/RedHatInsights/topological_inventory-providers-common/test_coverage)
|
6
6
|
[![security](https://hakiri.io/github/RedHatInsights/topological_inventory-providers-common/master.svg)](https://hakiri.io/github/RedHatInsights/topological_inventory-providers-common/master)
|
@@ -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
|
+
self.queue_host = ENV['QUEUE_HOST'] || 'localhost'
|
15
|
+
self.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 => default.queue_host, :port => default.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,109 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "prometheus_exporter"
|
3
|
+
require "prometheus_exporter/server"
|
4
|
+
require "prometheus_exporter/client"
|
5
|
+
require "prometheus_exporter/instrumentation"
|
6
|
+
require "topological_inventory/providers/common/mixins/statuses"
|
7
|
+
|
8
|
+
module TopologicalInventory
|
9
|
+
module Providers
|
10
|
+
module Common
|
11
|
+
class Metrics
|
12
|
+
include TopologicalInventory::Providers::Common::Mixins::Statuses
|
13
|
+
|
14
|
+
ERROR_COUNTER_MESSAGE = "total number of errors".freeze
|
15
|
+
ERROR_TYPES = %i[general].freeze
|
16
|
+
OPERATIONS = %w[].freeze
|
17
|
+
|
18
|
+
def initialize(port = 9394)
|
19
|
+
return if port == 0
|
20
|
+
|
21
|
+
configure_server(port)
|
22
|
+
configure_metrics
|
23
|
+
|
24
|
+
init_counters
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop_server
|
28
|
+
@server&.stop
|
29
|
+
end
|
30
|
+
|
31
|
+
def record_error(type = :general)
|
32
|
+
@error_counter&.observe(1, :type => type.to_s)
|
33
|
+
end
|
34
|
+
|
35
|
+
def record_refresh_timing(labels = {}, &block)
|
36
|
+
record_time(@refresh_timer, labels, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def record_operation(name, labels = {})
|
40
|
+
@status_counter&.observe(1, (labels || {}).merge(:name => name))
|
41
|
+
end
|
42
|
+
|
43
|
+
def record_operation_time(name, labels = {}, &block)
|
44
|
+
record_time(@duration_seconds, (labels || {}).merge(:name => name), &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Common method for gauge
|
48
|
+
def record_gauge(metric, opt, value: nil, labels: {})
|
49
|
+
case opt
|
50
|
+
when :set then
|
51
|
+
metric&.observe(value.to_i, labels)
|
52
|
+
when :add then
|
53
|
+
metric&.increment(labels)
|
54
|
+
when :remove then
|
55
|
+
metric&.decrement(labels)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Common method for histogram
|
60
|
+
def record_time(metric, labels = {})
|
61
|
+
result = nil
|
62
|
+
time = Benchmark.realtime { result = yield }
|
63
|
+
metric&.observe(time, labels)
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Set all values to 0 (otherwise the counter is undefined)
|
70
|
+
def init_counters
|
71
|
+
self.class::ERROR_TYPES.each do |err_type|
|
72
|
+
@error_counter&.observe(0, :type => err_type)
|
73
|
+
end
|
74
|
+
|
75
|
+
self.class::OPERATIONS.each do |op|
|
76
|
+
operation_status.each_key do |status|
|
77
|
+
@status_counter&.observe(0, :name => op, :status => status.to_s)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def configure_server(port)
|
83
|
+
@server = PrometheusExporter::Server::WebServer.new(:port => port)
|
84
|
+
@server.start
|
85
|
+
|
86
|
+
PrometheusExporter::Client.default = PrometheusExporter::LocalClient.new(:collector => @server.collector)
|
87
|
+
end
|
88
|
+
|
89
|
+
def configure_metrics
|
90
|
+
PrometheusExporter::Instrumentation::Process.start
|
91
|
+
PrometheusExporter::Metric::Base.default_prefix = default_prefix
|
92
|
+
|
93
|
+
@duration_seconds = PrometheusExporter::Metric::Histogram.new('duration_seconds', 'Duration of processed operation')
|
94
|
+
@refresh_timer = PrometheusExporter::Metric::Histogram.new('refresh_time', 'Duration of full refresh')
|
95
|
+
@error_counter = PrometheusExporter::Metric::Counter.new('errors_total', ERROR_COUNTER_MESSAGE)
|
96
|
+
@status_counter = PrometheusExporter::Metric::Counter.new('status_counter', 'number of processed operations')
|
97
|
+
|
98
|
+
[@duration_seconds, @refresh_timer, @error_counter, @status_counter].each do |metric|
|
99
|
+
@server.collector.register_metric(metric)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def default_prefix
|
104
|
+
raise NotImplementedError, "#{__method__} must be implemented in a subclass"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
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
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "topological_inventory/providers/common/logging"
|
2
|
+
require "topological_inventory/providers/common/mixins/statuses"
|
2
3
|
require "topological_inventory/providers/common/operations/health_check"
|
3
4
|
|
4
5
|
module TopologicalInventory
|
@@ -7,10 +8,12 @@ module TopologicalInventory
|
|
7
8
|
module Operations
|
8
9
|
class AsyncWorker
|
9
10
|
include Logging
|
11
|
+
include TopologicalInventory::Providers::Common::Mixins::Statuses
|
10
12
|
|
11
|
-
def initialize(processor, queue
|
13
|
+
def initialize(processor, queue: nil, metrics: nil)
|
12
14
|
@processor = processor
|
13
|
-
@queue
|
15
|
+
@queue = queue || Queue.new
|
16
|
+
@metrics = metrics
|
14
17
|
end
|
15
18
|
|
16
19
|
def start
|
@@ -37,15 +40,17 @@ module TopologicalInventory
|
|
37
40
|
|
38
41
|
private
|
39
42
|
|
40
|
-
attr_reader :thread, :queue, :processor
|
43
|
+
attr_reader :thread, :queue, :processor, :metrics
|
41
44
|
|
42
|
-
def process_message(
|
43
|
-
processor.process!(
|
45
|
+
def process_message(message)
|
46
|
+
result = processor.process!(message, metrics)
|
47
|
+
metrics&.record_operation(message.message, :status => result)
|
44
48
|
rescue => err
|
45
|
-
model, method =
|
49
|
+
model, method = message.message.to_s.split(".")
|
46
50
|
logger.error("#{model}##{method}: async worker failure: #{err.cause}\n#{err}\n#{err.backtrace.join("\n")}")
|
51
|
+
metrics&.record_operation(message.message, :status => operation_status[:error])
|
47
52
|
ensure
|
48
|
-
|
53
|
+
message.ack
|
49
54
|
TopologicalInventory::Providers::Common::Operations::HealthCheck.touch_file
|
50
55
|
logger.debug("Operations::AsyncWorker queue length: #{queue.length}") if queue.length >= 20 && queue.length % 5 == 0
|
51
56
|
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
|
@@ -73,7 +83,7 @@ module TopologicalInventory
|
|
73
83
|
application.last_checked_at.present? && application.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
|
74
84
|
end
|
75
85
|
|
76
|
-
logger.availability_check("Skipping, last check at #{endpoint
|
86
|
+
logger.availability_check("Skipping, last check at #{endpoint&.last_checked_at || application&.last_checked_at} [Source ID: #{source_id}] ") if checked_recently
|
77
87
|
|
78
88
|
checked_recently
|
79
89
|
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_topic(
|
212
|
+
:service => SERVICE_NAME,
|
213
|
+
:event => EVENT_AVAILABILITY_STATUS,
|
214
|
+
:payload => payload.to_json
|
215
|
+
)
|
216
|
+
rescue => err
|
217
|
+
logger.availability_check("Failed to update #{payload[:resource_type]} id: #{payload[:resource_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
|