topological_inventory-providers-common 1.0.1

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.
@@ -0,0 +1,14 @@
1
+ module TopologicalInventory
2
+ module Providers
3
+ module Common
4
+ module SaveInventory
5
+ class Exception
6
+ class Error < StandardError;
7
+ end
8
+ class EntityTooLarge < Error;
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,124 @@
1
+ require "topological_inventory/providers/common/save_inventory/exception"
2
+
3
+ module TopologicalInventory
4
+ module Providers
5
+ module Common
6
+ module SaveInventory
7
+ class Saver
8
+ # As defined in:
9
+ # https://github.com/zendesk/ruby-kafka/blob/02f7e2816e1130c5202764c275e36837f57ca4af/lib/kafka/protocol/message.rb#L11-L17
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
13
+
14
+ def initialize(client:, logger:, max_bytes: 1_000_000)
15
+ @client = client
16
+ @logger = logger
17
+ @max_bytes = max_bytes - KAFKA_RESERVED_HEADER_SIZE
18
+ end
19
+
20
+ attr_reader :client, :logger, :max_bytes
21
+
22
+ # @return [Integer] A total number of parts that the payload was divided into
23
+ def save(data)
24
+ inventory = data[:inventory].to_hash
25
+
26
+ inventory_json = JSON.generate(inventory)
27
+ if inventory_json.size < max_bytes
28
+ save_inventory(inventory_json)
29
+ return 1
30
+ else
31
+ # GC can clean this up
32
+ inventory_json = nil
33
+ return save_payload_in_batches(inventory)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def save_payload_in_batches(inventory)
40
+ parts = 0
41
+ new_inventory = build_new_inventory(inventory)
42
+
43
+ inventory[:collections].each do |collection|
44
+ new_collection = build_new_collection(collection)
45
+
46
+ data = collection[:data].map { |x| JSON.generate(x) }
47
+ # Lets compute sizes of the each data item, plus 1 byte for comma
48
+ data_sizes = data.map { |x| x.size + 1 }
49
+
50
+ # Size of the current inventory and new_collection wrapper, plus 2 bytes for array signs
51
+ wrapper_size = JSON.generate(new_inventory).size + JSON.generate(new_collection).size + 2
52
+ total_size = wrapper_size
53
+ counter = 0
54
+ data_sizes.each do |data_size|
55
+ counter += 1
56
+ total_size += data_size
57
+
58
+ if total_size > max_bytes
59
+ # Remove the last data part, that caused going over the max limit
60
+ counter -= 1
61
+
62
+ # Add the entities to new collection, so the total size is below max
63
+ if counter > 0
64
+ new_collection[:data] = collection[:data].shift(counter)
65
+ new_inventory[:collections] << new_collection
66
+ end
67
+
68
+ # Save the current batch
69
+ serialize_and_save_inventory(new_inventory)
70
+ parts += 1
71
+
72
+ # Create new data containers for a new batch
73
+ new_inventory = build_new_inventory(inventory)
74
+ new_collection = build_new_collection(collection)
75
+ wrapper_size = JSON.generate(new_inventory).size + JSON.generate(new_collection).size + 2
76
+
77
+ # Start with the data part we've removed from the currently saved payload
78
+ total_size = wrapper_size + data_size
79
+ counter = 1
80
+ end
81
+ end
82
+
83
+ # Store the rest of the collection
84
+ new_collection[:data] = collection[:data].shift(counter)
85
+ new_inventory[:collections] << new_collection
86
+ end
87
+
88
+ # save the rest
89
+ serialize_and_save_inventory(new_inventory)
90
+ parts += 1
91
+
92
+ return parts
93
+ end
94
+
95
+ def save_inventory(inventory_json)
96
+ client.save_inventory_with_http_info(inventory_json)
97
+ end
98
+
99
+ def serialize_and_save_inventory(inventory)
100
+ payload = JSON.generate(inventory)
101
+ if payload.size > max_bytes
102
+ raise Exception::EntityTooLarge,
103
+ "Entity is bigger than total limit and can't be split: #{payload}"
104
+ end
105
+
106
+ # Save the current batch
107
+ save_inventory(payload)
108
+ end
109
+
110
+ def build_new_collection(collection)
111
+ {:name => collection[:name], :data => []}
112
+ end
113
+
114
+ def build_new_inventory(inventory)
115
+ new_inventory = inventory.clone
116
+ new_inventory[:refresh_state_part_uuid] = SecureRandom.uuid
117
+ new_inventory[:collections] = []
118
+ new_inventory
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,7 @@
1
+ module TopologicalInventory
2
+ module Providers
3
+ module Common
4
+ VERSION = "1.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "topological_inventory/providers/common/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "topological_inventory-providers-common"
8
+ spec.version = TopologicalInventory::Providers::Common::VERSION
9
+ spec.authors = ["Martin Slemr"]
10
+ spec.email = ["mslemr@redhat.com"]
11
+
12
+ spec.summary = %q{Common classes for topological-inventory collectors/operations}
13
+ spec.description = %q{Common classes for topological-inventory collectors/operations}
14
+ spec.homepage = "https://github.com/RedHatInsights/topological_inventory-providers-common"
15
+ spec.license = "Apache-2.0"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_runtime_dependency 'config', '~> 1.7', '>= 1.7.2'
27
+ spec.add_runtime_dependency "activesupport", "~> 5.2.2"
28
+ spec.add_runtime_dependency "manageiq-loggers", ">= 0.4.2"
29
+ spec.add_runtime_dependency 'json', '~> 2.1', '>= 2.1.0'
30
+ spec.add_runtime_dependency "topological_inventory-api-client", "~> 3.0", ">= 3.0.1"
31
+
32
+ spec.add_development_dependency "bundler", "~> 2.0"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.0"
35
+ end
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: topological_inventory-providers-common
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Martin Slemr
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: config
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.7.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.7.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 5.2.2
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 5.2.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: manageiq-loggers
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.4.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: json
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.1.0
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '2.1'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.0
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '2.1'
81
+ - !ruby/object:Gem::Dependency
82
+ name: topological_inventory-api-client
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 3.0.1
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '3.0'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 3.0.1
101
+ - !ruby/object:Gem::Dependency
102
+ name: bundler
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '2.0'
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '2.0'
115
+ - !ruby/object:Gem::Dependency
116
+ name: rake
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '10.0'
122
+ type: :development
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '10.0'
129
+ - !ruby/object:Gem::Dependency
130
+ name: rspec
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '3.0'
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '3.0'
143
+ description: Common classes for topological-inventory collectors/operations
144
+ email:
145
+ - mslemr@redhat.com
146
+ executables: []
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - ".gitignore"
151
+ - ".rspec"
152
+ - ".travis.yml"
153
+ - CHANGELOG.md
154
+ - Gemfile
155
+ - LICENSE.txt
156
+ - README.md
157
+ - Rakefile
158
+ - bin/console
159
+ - bin/setup
160
+ - lib/topological_inventory/providers/common.rb
161
+ - lib/topological_inventory/providers/common/collector.rb
162
+ - lib/topological_inventory/providers/common/collector/inventory_collection_storage.rb
163
+ - lib/topological_inventory/providers/common/collector/inventory_collection_wrapper.rb
164
+ - lib/topological_inventory/providers/common/collector/parser.rb
165
+ - lib/topological_inventory/providers/common/collectors_pool.rb
166
+ - lib/topological_inventory/providers/common/logging.rb
167
+ - lib/topological_inventory/providers/common/operations/endpoint_client.rb
168
+ - lib/topological_inventory/providers/common/operations/processor.rb
169
+ - lib/topological_inventory/providers/common/operations/sources_api_client.rb
170
+ - lib/topological_inventory/providers/common/operations/topology_api_client.rb
171
+ - lib/topological_inventory/providers/common/save_inventory/exception.rb
172
+ - lib/topological_inventory/providers/common/save_inventory/saver.rb
173
+ - lib/topological_inventory/providers/common/version.rb
174
+ - topological_inventory-providers-common.gemspec
175
+ homepage: https://github.com/RedHatInsights/topological_inventory-providers-common
176
+ licenses:
177
+ - Apache-2.0
178
+ metadata: {}
179
+ post_install_message:
180
+ rdoc_options: []
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ requirements: []
194
+ rubygems_version: 3.0.8
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Common classes for topological-inventory collectors/operations
198
+ test_files: []