topological_inventory-providers-common 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcac7f624e6e6d2ba88bed97e3d089cfd4258e38b968cbed141528888ede0ca0
4
- data.tar.gz: 7fe176f46948a2359192f503091bce1fadfe3abbb089e4c8efc5606ea07e6ed0
3
+ metadata.gz: 00d8f69979f477e6b74d6c7b2785647cc043b3909a45ff424562504146955e2b
4
+ data.tar.gz: 1b009a746f92137d0502c71bf67346ba86de56aba196eb05e52a6280b86861ec
5
5
  SHA512:
6
- metadata.gz: 2609f90ca604593f8d1bed9c0567feae6151bb6a0805a6299a9077e8b812a58d49573e32eb1cc7a0ff9cf70369c8d7936f88887c4c0b6a7af7f9e50d1013275c
7
- data.tar.gz: 36a45b32003a82705b03d15bc15fbdae18038fc04c2238db55b0077c50868b39ea199de86185a6b00c2d9afc6ce76d9308db8c0ef5ddbc844ef57340f71d6eb7
6
+ metadata.gz: 84a4936e15d4fa024d425d430ba2489485259e59be735e86aa3801852b5745825b324a58b2e847781700607d76c1e5e2deb13bb453f019dba2b0e5382f705c8b
7
+ data.tar.gz: 10e5edc584fbfcfd85ae196aef5f83c1e7e42fb0e4325f29b302feecc8c2937925580e23d903442546e8af826afb91fd8c9ea2164812f4e1baabed2087fb6025
@@ -0,0 +1,23 @@
1
+ name: Release Ruby Gem
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ paths:
7
+ - 'lib/topological_inventory/providers/common/version.rb'
8
+
9
+ jobs:
10
+ build:
11
+ name: Build + Publish
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v1
16
+
17
+ - name: Publish to Rubygems
18
+ uses: cadwallion/publish-rubygems-action@v1.0
19
+ env:
20
+ GITHUB_TOKEN: ${{secrets.GH_API_KEY}}
21
+ RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
22
+ RELEASE_COMMAND: rake release
23
+
data/.gitignore CHANGED
@@ -11,3 +11,6 @@
11
11
 
12
12
  # rspec failure tracking
13
13
  .rspec_status
14
+
15
+ # generated rubocop file
16
+ .rubocop-https*
@@ -0,0 +1,3 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml
3
+ - .rubocop_local.yml
@@ -0,0 +1,4 @@
1
+ inherit_from:
2
+ - .rubocop_base.yml
3
+ - .rubocop_cc_base.yml
4
+ - .rubocop_local.yml
@@ -0,0 +1,2 @@
1
+ #AllCops:
2
+ # Exclude:
@@ -1,4 +1,5 @@
1
1
  ---
2
+ dist: xenial
2
3
  sudo: false
3
4
  language: ruby
4
5
  cache: bundler
@@ -8,3 +9,10 @@ rvm:
8
9
  before_install:
9
10
  - 'echo ''gem: --no-ri --no-rdoc --no-document'' > ~/.gemrc'
10
11
  - gem install bundler
12
+ before_script:
13
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
14
+ > ./cc-test-reporter
15
+ - chmod +x ./cc-test-reporter
16
+ - "./cc-test-reporter before-build"
17
+ after_script:
18
+ - "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
@@ -4,7 +4,11 @@ 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
- ## [1.0.3] - 2020-06-?
7
+ ## [1.0.4] - 2020-06-09
8
+ Common availability check operation #25
9
+ Rubocop and codecoverage #29
10
+
11
+ ## [1.0.3] - 2020-06-04
8
12
  ### Changed
9
13
 
10
14
  Bump Sources API client to 3.0 #26
@@ -25,7 +29,8 @@ manageiq-loggers to >= 0.4.2 #20
25
29
  ## [1.0.0] - 2020-03-19
26
30
  ### Initial release to rubygems.org
27
31
 
28
- [Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.3...HEAD
32
+ [Unreleased]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.4...HEAD
33
+ [1.0.4]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.3...v1.0.4
29
34
  [1.0.3]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.2...v1.0.3
30
35
  [1.0.2]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.1...v1.0.2
31
36
  [1.0.1]: https://github.com/RedHatInsights/topological_inventory-providers-common/compare/v1.0.0...v1.0.1
@@ -21,6 +21,14 @@ module TopologicalInventory
21
21
  msg = "[#{status.to_s.upcase}] Sweeping inactive records, :sweep_scope => #{sweep_scope}, :source_uid => #{source}, :refresh_state_uuid => #{refresh_state_uuid}"
22
22
  info(msg)
23
23
  end
24
+
25
+ def availability_check(message, severity = :info)
26
+ log_with_prefix("Source#availability_check", message, severity)
27
+ end
28
+
29
+ def log_with_prefix(prefix, message, severity)
30
+ send(severity, "#{prefix} - #{message}") if respond_to?(severity)
31
+ end
24
32
  end
25
33
 
26
34
  class Logger < ManageIQ::Loggers::CloudWatch
@@ -46,6 +46,9 @@ module TopologicalInventory
46
46
 
47
47
  def default_endpoint
48
48
  @default_endpoint ||= sources_api.fetch_default_endpoint(source_id)
49
+ raise "Sources API: Endpoint not found! (source id: #{source_id})" if @default_endpoint.nil?
50
+
51
+ @default_endpoint
49
52
  end
50
53
 
51
54
  def authentication
@@ -0,0 +1,140 @@
1
+ require "topological_inventory/providers/common/logging"
2
+ require "active_support/core_ext/numeric/time"
3
+ require "topological_inventory/providers/common/operations/sources_api_client"
4
+
5
+ module TopologicalInventory
6
+ module Providers
7
+ module Common
8
+ module Operations
9
+ class Source
10
+ include Logging
11
+
12
+ STATUS_AVAILABLE, STATUS_UNAVAILABLE = %w[available unavailable].freeze
13
+
14
+ ERROR_MESSAGES = {
15
+ :authentication_not_found => "Authentication not found in Sources API",
16
+ :endpoint_not_found => "Endpoint not found in Sources API",
17
+ }.freeze
18
+
19
+ LAST_CHECKED_AT_THRESHOLD = 5.minutes.freeze
20
+
21
+ attr_accessor :params, :request_context, :source_id
22
+
23
+ def initialize(params = {}, request_context = nil)
24
+ self.params = params
25
+ self.request_context = request_context
26
+ self.source_id = params['source_id']
27
+ end
28
+
29
+ def availability_check
30
+ return if params_missing?
31
+
32
+ return if checked_recently?
33
+
34
+ status, error_message = connection_status
35
+
36
+ update_source_and_endpoint(status, error_message)
37
+
38
+ logger.availability_check("Completed: Source #{source_id} is #{status}")
39
+ end
40
+
41
+ private
42
+
43
+ def required_params
44
+ %w[source_id]
45
+ end
46
+
47
+ def params_missing?
48
+ is_missing = false
49
+ required_params.each do |attr|
50
+ if (is_missing = params[attr].blank?)
51
+ logger.availability_check("Missing #{attr} for the availability_check request [Source ID: #{source_id}]", :error)
52
+ break
53
+ end
54
+ end
55
+
56
+ is_missing
57
+ end
58
+
59
+ def checked_recently?
60
+ return false if endpoint.nil?
61
+
62
+ checked_recently = endpoint.last_checked_at.present? && endpoint.last_checked_at >= LAST_CHECKED_AT_THRESHOLD.ago
63
+ logger.availability_check("Skipping, last check at #{endpoint.last_checked_at} [Source ID: #{source_id}] ") if checked_recently
64
+
65
+ checked_recently
66
+ end
67
+
68
+ def connection_status
69
+ return [STATUS_UNAVAILABLE, ERROR_MESSAGES[:endpoint_not_found]] unless endpoint
70
+ return [STATUS_UNAVAILABLE, ERROR_MESSAGES[:authentication_not_found]] unless authentication
71
+
72
+ check_time
73
+ connection_check
74
+ end
75
+
76
+ # @return [Array<String, String|nil] - STATUS_[UN]AVAILABLE, error message
77
+ def connection_check
78
+ raise NotImplementedError, "#{__method__} must be implemented in a subclass"
79
+ end
80
+
81
+ def update_source_and_endpoint(status, error_message = nil)
82
+ logger.availability_check("Updating source [#{source_id}] status [#{status}] message [#{error_message}]")
83
+
84
+ update_source(status)
85
+ update_endpoint(status, error_message)
86
+ end
87
+
88
+ def update_source(status)
89
+ source = ::SourcesApiClient::Source.new
90
+ source.availability_status = status
91
+ source.last_checked_at = check_time
92
+ source.last_available_at = check_time if status == STATUS_AVAILABLE
93
+
94
+ api_client.update_source(source_id, source)
95
+ rescue ::SourcesApiClient::ApiError => e
96
+ logger.availability_check("Failed to update Source id:#{source_id} - #{e.message}", :error)
97
+ end
98
+
99
+ def update_endpoint(status, error_message)
100
+ if endpoint.nil?
101
+ logger.availability_check("Failed to update Endpoint for Source id:#{source_id}. Endpoint not found", :error)
102
+ return
103
+ end
104
+
105
+ endpoint_update = ::SourcesApiClient::Endpoint.new
106
+
107
+ endpoint_update.availability_status = status
108
+ endpoint_update.availability_status_error = error_message.to_s
109
+ endpoint_update.last_checked_at = check_time
110
+ endpoint_update.last_available_at = check_time if status == STATUS_AVAILABLE
111
+
112
+ api_client.update_endpoint(endpoint.id, endpoint_update)
113
+ rescue ::SourcesApiClient::ApiError => e
114
+ logger.availability_check("Failed to update Endpoint(ID: #{endpoint.id}) - #{e.message}", :error)
115
+ end
116
+
117
+ def endpoint
118
+ @endpoint ||= api_client.fetch_default_endpoint(source_id)
119
+ end
120
+
121
+ def authentication
122
+ @authentication ||= api_client.fetch_authentication(source_id, endpoint)
123
+ end
124
+
125
+ def check_time
126
+ @check_time ||= Time.now.utc
127
+ end
128
+
129
+ def identity
130
+ @identity ||= {"x-rh-identity" => Base64.strict_encode64({"identity" => {"account_number" => params["external_tenant"], "user" => {"is_org_admin" => true}}}.to_json)}
131
+ end
132
+
133
+ def api_client
134
+ @api_client ||= TopologicalInventory::Providers::Common::Operations::SourcesApiClient.new(identity)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -5,6 +5,8 @@ module TopologicalInventory
5
5
  module Common
6
6
  module Operations
7
7
  class SourcesApiClient < ::SourcesApiClient::ApiClient
8
+ delegate :update_source, :update_endpoint, :to => :api
9
+
8
10
  INTERNAL_API_PATH = '//internal/v1.0'.freeze
9
11
 
10
12
  def initialize(identity = nil)
@@ -20,21 +22,23 @@ module TopologicalInventory
20
22
 
21
23
  def fetch_default_endpoint(source_id)
22
24
  endpoints = api.list_source_endpoints(source_id)&.data || []
23
- endpoint = endpoints.find(&:default)
24
-
25
- raise "Sources API: Endpoint not found! (source id: #{source_id})" if endpoint.nil?
26
-
27
- endpoint
25
+ endpoints.find(&:default)
28
26
  end
29
27
 
30
- def fetch_authentication(source_id, default_endpoint = nil)
28
+ def fetch_authentication(source_id, default_endpoint = nil, authtype = nil)
31
29
  endpoint = default_endpoint || fetch_default_endpoint(source_id)
32
30
  return if endpoint.nil?
33
31
 
34
32
  endpoint_authentications = api.list_endpoint_authentications(endpoint.id.to_s).data || []
35
33
  return if endpoint_authentications.empty?
36
34
 
37
- auth_id = endpoint_authentications.first.id
35
+ auth_id = if authtype.nil?
36
+ endpoint_authentications.first&.id
37
+ else
38
+ endpoint_authentications.detect { |a| a.authtype = authtype }&.id
39
+ end
40
+ return if auth_id.nil?
41
+
38
42
  fetch_authentication_with_password(auth_id)
39
43
  end
40
44
 
@@ -8,13 +8,14 @@ module TopologicalInventory
8
8
  # As defined in:
9
9
  # https://github.com/zendesk/ruby-kafka/blob/02f7e2816e1130c5202764c275e36837f57ca4af/lib/kafka/protocol/message.rb#L11-L17
10
10
  # There is at least 112 bytes that are added as a message header, so we need to keep room for that. Lets make
11
- # it 200 bytes, just for sure.
12
- KAFKA_RESERVED_HEADER_SIZE = 200
11
+ # it 512 bytes, just for sure.
12
+ KAFKA_PAYLOAD_MAX_BYTES_DEFAULT = 750_000
13
+ KAFKA_RESERVED_HEADER_SIZE = 512
13
14
 
14
- def initialize(client:, logger:, max_bytes: 1_000_000)
15
+ def initialize(client:, logger:, max_bytes: KAFKA_PAYLOAD_MAX_BYTES_DEFAULT)
15
16
  @client = client
16
17
  @logger = logger
17
- @max_bytes = max_bytes - KAFKA_RESERVED_HEADER_SIZE
18
+ @max_bytes = payload_max_size(max_bytes)
18
19
  end
19
20
 
20
21
  attr_reader :client, :logger, :max_bytes
@@ -117,6 +118,14 @@ module TopologicalInventory
117
118
  new_inventory[:collections] = []
118
119
  new_inventory
119
120
  end
121
+
122
+ def payload_max_size(max_bytes)
123
+ if ENV['KAFKA_PAYLOAD_MAX_BYTES']
124
+ max_bytes.clamp(5_000, ENV['KAFKA_PAYLOAD_MAX_BYTES'].to_i) - KAFKA_RESERVED_HEADER_SIZE
125
+ else
126
+ max_bytes - KAFKA_RESERVED_HEADER_SIZE
127
+ end
128
+ end
120
129
  end
121
130
  end
122
131
  end
@@ -1,7 +1,7 @@
1
1
  module TopologicalInventory
2
2
  module Providers
3
3
  module Common
4
- VERSION = "1.0.3"
4
+ VERSION = "1.0.4"
5
5
  end
6
6
  end
7
7
  end
@@ -34,4 +34,8 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "bundler", "~> 2.0"
35
35
  spec.add_development_dependency "rake", ">= 12.3.3"
36
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"
40
+ spec.add_development_dependency 'webmock'
37
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: topological_inventory-providers-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
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-06-04 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -162,6 +162,62 @@ dependencies:
162
162
  - - "~>"
163
163
  - !ruby/object:Gem::Version
164
164
  version: '3.0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rubocop
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: 0.69.0
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: 0.69.0
179
+ - !ruby/object:Gem::Dependency
180
+ name: rubocop-performance
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '1.3'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '1.3'
193
+ - !ruby/object:Gem::Dependency
194
+ name: simplecov
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: 0.17.1
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: 0.17.1
207
+ - !ruby/object:Gem::Dependency
208
+ name: webmock
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
165
221
  description: Common classes for topological-inventory collectors/operations
166
222
  email:
167
223
  - mslemr@redhat.com
@@ -169,8 +225,12 @@ executables: []
169
225
  extensions: []
170
226
  extra_rdoc_files: []
171
227
  files:
228
+ - ".github/workflows/gem-push.yml"
172
229
  - ".gitignore"
173
230
  - ".rspec"
231
+ - ".rubocop.yml"
232
+ - ".rubocop_cc.yml"
233
+ - ".rubocop_local.yml"
174
234
  - ".travis.yml"
175
235
  - CHANGELOG.md
176
236
  - Gemfile
@@ -188,6 +248,7 @@ files:
188
248
  - lib/topological_inventory/providers/common/logging.rb
189
249
  - lib/topological_inventory/providers/common/operations/endpoint_client.rb
190
250
  - lib/topological_inventory/providers/common/operations/processor.rb
251
+ - lib/topological_inventory/providers/common/operations/source.rb
191
252
  - lib/topological_inventory/providers/common/operations/sources_api_client.rb
192
253
  - lib/topological_inventory/providers/common/operations/topology_api_client.rb
193
254
  - lib/topological_inventory/providers/common/save_inventory/exception.rb