hawkular-client 3.0.2 → 5.0.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/CHANGES.rdoc +22 -0
- data/README.rdoc +1 -2
- data/lib/hawkular/alerts/alerts_api.rb +16 -15
- data/lib/hawkular/base_client.rb +22 -26
- data/lib/hawkular/client_utils.rb +18 -0
- data/lib/hawkular/hawkular_client.rb +37 -23
- data/lib/hawkular/inventory/entities.rb +85 -257
- data/lib/hawkular/inventory/inventory_api.rb +64 -412
- data/lib/hawkular/metrics/metric_api.rb +24 -17
- data/lib/hawkular/metrics/metrics_client.rb +4 -3
- data/lib/hawkular/operations/operations_api.rb +126 -81
- data/lib/hawkular/prometheus/prometheus_api.rb +66 -0
- data/lib/hawkular/version.rb +1 -1
- data/lib/hawkularclient.rb +1 -0
- metadata +56 -55
@@ -1,16 +1,8 @@
|
|
1
1
|
require 'hawkular/base_client'
|
2
|
-
require 'websocket-client-simple'
|
3
|
-
require 'json'
|
4
|
-
require 'zlib'
|
5
|
-
require 'stringio'
|
6
2
|
|
7
3
|
require 'hawkular/inventory/entities'
|
8
4
|
|
9
5
|
# Inventory module provides access to the Hawkular Inventory REST API.
|
10
|
-
# @see http://www.hawkular.org/docs/rest/rest-inventory.html
|
11
|
-
#
|
12
|
-
# @note While Inventory supports 'environments', they are not used currently
|
13
|
-
# and thus set to 'test' as default value.
|
14
6
|
module Hawkular::Inventory
|
15
7
|
# Client class to interact with Hawkular Inventory
|
16
8
|
class Client < Hawkular::BaseClient
|
@@ -21,12 +13,13 @@ module Hawkular::Inventory
|
|
21
13
|
# http://localhost:8080/hawkular/inventory
|
22
14
|
# @param credentials [Hash{String=>String}] Hash of username, password, token(optional)
|
23
15
|
# @param options [Hash{String=>String}] Additional rest client options
|
24
|
-
def initialize(entrypoint = nil, credentials = {}, options = {})
|
25
|
-
entrypoint = normalize_entrypoint_url entrypoint, 'hawkular/
|
16
|
+
def initialize(entrypoint = nil, credentials = {}, options = {}, page_size = nil)
|
17
|
+
entrypoint = normalize_entrypoint_url entrypoint, 'hawkular/inventory'
|
26
18
|
@entrypoint = entrypoint
|
27
19
|
super(entrypoint, credentials, options)
|
28
20
|
version = fetch_version_and_status['Implementation-Version']
|
29
21
|
@version = version.scan(/\d+/).map(&:to_i)
|
22
|
+
@page_size = page_size || 100
|
30
23
|
end
|
31
24
|
|
32
25
|
# Creates a new Inventory Client
|
@@ -34,261 +27,71 @@ module Hawkular::Inventory
|
|
34
27
|
# entrypoint: http://localhost:8080/hawkular/inventory
|
35
28
|
# and another sub-hash containing the hash with username[String], password[String], token(optional)
|
36
29
|
def self.create(hash)
|
37
|
-
fail 'no parameter ":entrypoint" given' unless hash[:entrypoint]
|
30
|
+
fail Hawkular::ArgumentError, 'no parameter ":entrypoint" given' unless hash[:entrypoint]
|
31
|
+
|
38
32
|
hash[:credentials] ||= {}
|
39
33
|
hash[:options] ||= {}
|
40
|
-
Client.new(hash[:entrypoint], hash[:credentials], hash[:options])
|
34
|
+
Client.new(hash[:entrypoint], hash[:credentials], hash[:options], hash[:page_size])
|
41
35
|
end
|
42
36
|
|
43
|
-
#
|
44
|
-
# @return
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
# Get single resource by id
|
38
|
+
# @return Resource the resource
|
39
|
+
def resource(id)
|
40
|
+
hash = http_get(url('/resources/%s', id))
|
41
|
+
Resource.new(hash)
|
42
|
+
rescue ::Hawkular::Exception => e
|
43
|
+
return if e.cause.is_a?(::RestClient::NotFound)
|
44
|
+
raise
|
49
45
|
end
|
50
46
|
|
51
|
-
#
|
52
|
-
# @
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
feed_path = feed_cp(feed_id)
|
57
|
-
response = http_post(
|
58
|
-
'/strings/raw/query',
|
59
|
-
fromEarliest: true,
|
60
|
-
order: 'DESC',
|
61
|
-
tags: "#{feed_path.to_tags},type:rt")
|
62
|
-
structures = extract_structures_from_body(response)
|
63
|
-
structures.map do |rt|
|
64
|
-
root_hash = entity_json_to_hash(-> (id) { feed_path.resource_type(id) }, rt['inventoryStructure'], false)
|
65
|
-
ResourceType.new(root_hash)
|
66
|
-
end
|
47
|
+
# Get resource by id with its complete subtree
|
48
|
+
# @return Resource the resource
|
49
|
+
def resource_tree(id)
|
50
|
+
hash = http_get(url('/resources/%s/tree', id))
|
51
|
+
Resource.new(hash)
|
67
52
|
end
|
68
53
|
|
69
|
-
#
|
70
|
-
# @
|
71
|
-
|
72
|
-
|
73
|
-
fail 'Feed id must be given' unless feed_id
|
74
|
-
feed_path = feed_cp(feed_id)
|
75
|
-
response = http_post(
|
76
|
-
'/strings/raw/query',
|
77
|
-
fromEarliest: true,
|
78
|
-
order: 'DESC',
|
79
|
-
tags: "#{feed_path.to_tags},type:mt")
|
80
|
-
structures = extract_structures_from_body(response)
|
81
|
-
structures.map do |mt|
|
82
|
-
root_hash = entity_json_to_hash(-> (id) { feed_path.metric_type(id) }, mt['inventoryStructure'], false)
|
83
|
-
MetricType.new(root_hash)
|
84
|
-
end
|
54
|
+
# Get childrens of a resource
|
55
|
+
# @return Children of a resource
|
56
|
+
def children_resources(parent_id)
|
57
|
+
http_get(url('/resources/%s/children', parent_id))['results'].map { |r| Resource.new(r) }
|
85
58
|
end
|
86
59
|
|
87
|
-
#
|
88
|
-
# @
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
fail 'Feed id must be given' unless feed_id
|
93
|
-
feed_path = feed_cp(feed_id)
|
94
|
-
response = http_post(
|
95
|
-
'/strings/raw/query',
|
96
|
-
fromEarliest: true,
|
97
|
-
order: 'DESC',
|
98
|
-
tags: "#{feed_path.to_tags},type:r")
|
99
|
-
structures = extract_structures_from_body(response)
|
100
|
-
to_filter = structures.map do |r|
|
101
|
-
root_hash = entity_json_to_hash(-> (id) { feed_path.down(id) }, r['inventoryStructure'], fetch_properties)
|
102
|
-
Resource.new(root_hash)
|
103
|
-
end
|
104
|
-
filter_entities(to_filter, filter)
|
60
|
+
# Get parent of a resource
|
61
|
+
# @return Resource the parent resource, or nil if the provided ID referred to a root resource
|
62
|
+
def parent(id)
|
63
|
+
hash = http_get(url('/resources/%s/parent', id))
|
64
|
+
Resource.new(hash) if hash
|
105
65
|
end
|
106
66
|
|
107
|
-
# List
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
# Must not be nil. The tenant_id in the canonical path doesn't have to be there.
|
112
|
-
# @param [Boolean] fetch_properties Shall additional runtime properties be fetched?
|
113
|
-
# @return [Array<Resource>] List of resources. Can be empty
|
114
|
-
def list_resources_for_type(resource_type_path, fetch_properties = false)
|
115
|
-
path = CanonicalPath.parse_if_string(resource_type_path)
|
116
|
-
fail 'Feed id must be given' unless path.feed_id
|
117
|
-
fail 'Resource type must be given' unless path.resource_type_id
|
118
|
-
|
119
|
-
# Fetch metrics by tag
|
120
|
-
feed_path = feed_cp(URI.unescape(path.feed_id))
|
121
|
-
resource_type_id = URI.unescape(path.resource_type_id)
|
122
|
-
escaped_for_regex = Regexp.quote("|#{resource_type_id}|")
|
123
|
-
response = http_post(
|
124
|
-
'/strings/raw/query',
|
125
|
-
fromEarliest: true,
|
126
|
-
order: 'DESC',
|
127
|
-
tags: "#{feed_path.to_tags},type:r,restypes:.*#{escaped_for_regex}.*")
|
128
|
-
structures = extract_structures_from_body(response)
|
129
|
-
return [] if structures.empty?
|
130
|
-
|
131
|
-
# Now find each collected resource path in their belonging InventoryStructure
|
132
|
-
extract_resources_for_type(structures, feed_path, resource_type_id, fetch_properties)
|
67
|
+
# List root resources
|
68
|
+
# @return [Enumeration<Resource>] Lazy-loaded Enumeration of resources
|
69
|
+
def root_resources
|
70
|
+
resources root: 'true'
|
133
71
|
end
|
134
72
|
|
135
|
-
#
|
136
|
-
# @param [
|
137
|
-
# @
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
73
|
+
# List resources
|
74
|
+
# @param [Hash] filter options to filter the resource list
|
75
|
+
# @option filter :root If truthy, only get root resources
|
76
|
+
# @option filter :feedId Filter by feed id
|
77
|
+
# @option filter :typeId Filter by type id
|
78
|
+
# @return [Enumeration<Resource>] Lazy-loaded Enumeration of resources
|
79
|
+
def resources(filter = {})
|
80
|
+
filter[:root] = !filter[:root].nil? if filter.key? :root
|
81
|
+
filter[:maxResults] = @page_size
|
144
82
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
# @return [Array<Resource>] List of resources that are children of the given parent resource.
|
150
|
-
# Can be empty
|
151
|
-
def list_child_resources(parent_res_path, recursive = false)
|
152
|
-
path = CanonicalPath.parse_if_string(parent_res_path)
|
153
|
-
feed_id = path.feed_id
|
154
|
-
fail 'Feed id must be given' unless feed_id
|
155
|
-
entity_hash = get_raw_entity_hash(path)
|
156
|
-
extract_child_resources([], path.to_s, entity_hash, recursive) if entity_hash
|
157
|
-
end
|
158
|
-
|
159
|
-
# List the metrics for the passed metric type. If feed is not passed in the path,
|
160
|
-
# all the metrics across all the feeds of a given type will be retrieved
|
161
|
-
# @param [String] metric_type_path Canonical path of the resource type to look for. Can be obtained from
|
162
|
-
# {MetricType}.path. Must not be nil. The tenant_id in the canonical path doesn't have to be there.
|
163
|
-
# @return [Array<Metric>] List of metrics. Can be empty
|
164
|
-
def list_metrics_for_metric_type(metric_type_path)
|
165
|
-
path = CanonicalPath.parse_if_string(metric_type_path)
|
166
|
-
fail 'Feed id must be given' unless path.feed_id
|
167
|
-
fail 'Metric type id must be given' unless path.metric_type_id
|
168
|
-
feed_id = URI.unescape(path.feed_id)
|
169
|
-
metric_type_id = URI.unescape(path.metric_type_id)
|
170
|
-
|
171
|
-
feed_path = feed_cp(feed_id)
|
172
|
-
escaped_for_regex = Regexp.quote("|#{metric_type_id}|")
|
173
|
-
response = http_post(
|
174
|
-
'/strings/raw/query',
|
175
|
-
fromEarliest: true,
|
176
|
-
order: 'DESC',
|
177
|
-
tags: "#{feed_path.to_tags},type:r,mtypes:.*#{escaped_for_regex}.*")
|
178
|
-
structures = extract_structures_from_body(response)
|
179
|
-
return [] if structures.empty?
|
180
|
-
|
181
|
-
# Now find each collected resource path in their belonging InventoryStructure
|
182
|
-
metric_type = get_metric_type(path)
|
183
|
-
extract_metrics_for_type(structures, feed_path, metric_type)
|
184
|
-
end
|
185
|
-
|
186
|
-
# List metric (definitions) for the passed resource. It is possible to filter down the
|
187
|
-
# result by a filter to only return a subset. The
|
188
|
-
# @param [String] resource_path Canonical path of the resource.
|
189
|
-
# @param [Hash{Symbol=>String}] filter for 'type' and 'match'
|
190
|
-
# Metric type can be one of 'GAUGE', 'COUNTER', 'AVAILABILITY'. If a key is missing
|
191
|
-
# it will not be used for filtering
|
192
|
-
# @return [Array<Metric>] List of metrics that can be empty.
|
193
|
-
# @example
|
194
|
-
# # Filter by type and match on metrics id
|
195
|
-
# client.list_metrics_for_resource(wild_fly, type: 'GAUGE', match: 'Metrics~Heap')
|
196
|
-
# # Filter by type only
|
197
|
-
# client.list_metrics_for_resource(wild_fly, type: 'COUNTER')
|
198
|
-
# # Don't filter, return all metric definitions
|
199
|
-
# client.list_metrics_for_resource(wild_fly)
|
200
|
-
def list_metrics_for_resource(resource_path, filter = {})
|
201
|
-
path = CanonicalPath.parse_if_string(resource_path)
|
202
|
-
raw_hash = get_raw_entity_hash(path)
|
203
|
-
return [] unless raw_hash
|
204
|
-
to_filter = []
|
205
|
-
if (raw_hash.key? 'children') && (raw_hash['children'].key? 'metric') && !raw_hash['children']['metric'].empty?
|
206
|
-
# Need to merge metric type info that we must grab from another place
|
207
|
-
metric_types = list_metric_types(URI.unescape(path.feed_id))
|
208
|
-
metric_types_index = {}
|
209
|
-
metric_types.each { |mt| metric_types_index[mt.path] = mt }
|
210
|
-
to_filter = raw_hash['children']['metric'].map do |m|
|
211
|
-
metric_data = m['data']
|
212
|
-
metric_data['path'] = "#{path}/m;#{metric_data['id']}"
|
213
|
-
metric_type = metric_types_index[metric_data['metricTypePath']]
|
214
|
-
Metric.new(metric_data, metric_type) if metric_type
|
215
|
-
end
|
216
|
-
to_filter = to_filter.select { |m| m }
|
83
|
+
fetch_func = lambda do |offset|
|
84
|
+
filter[:startOffSet] = offset
|
85
|
+
filter_query = '?' + filter.keys.join('=%s&') + '=%s' unless filter.empty?
|
86
|
+
http_get(url("/resources#{filter_query}", *filter.values))
|
217
87
|
end
|
218
|
-
|
88
|
+
ResultFetcher.new(fetch_func).map { |r| Resource.new(r) }
|
219
89
|
end
|
220
90
|
|
221
|
-
#
|
222
|
-
# @
|
223
|
-
|
224
|
-
|
225
|
-
path = CanonicalPath.parse_if_string(resource_path)
|
226
|
-
raw_hash = get_raw_entity_hash(path)
|
227
|
-
unless raw_hash
|
228
|
-
exception = HawkularException.new("Resource not found: #{resource_path}")
|
229
|
-
fail exception
|
230
|
-
end
|
231
|
-
entity_hash = entity_json_to_hash(-> (_) { path }, raw_hash, fetch_properties)
|
232
|
-
Resource.new(entity_hash)
|
233
|
-
end
|
234
|
-
|
235
|
-
# Return the resource type object for the passed path
|
236
|
-
# @param [String] resource_type_path Canonical path of the resource type to fetch.
|
237
|
-
def get_resource_type(resource_type_path)
|
238
|
-
path = CanonicalPath.parse_if_string(resource_type_path)
|
239
|
-
raw_hash = get_raw_entity_hash(path)
|
240
|
-
unless raw_hash
|
241
|
-
exception = HawkularException.new("Resource type not found: #{resource_type_path}")
|
242
|
-
fail exception
|
243
|
-
end
|
244
|
-
entity_hash = entity_json_to_hash(-> (_) { path }, raw_hash, false)
|
245
|
-
ResourceType.new(entity_hash)
|
246
|
-
end
|
247
|
-
|
248
|
-
# Return the metric type object for the passed path
|
249
|
-
# @param [String] metric_type_path Canonical path of the metric type to fetch.
|
250
|
-
def get_metric_type(metric_type_path)
|
251
|
-
path = CanonicalPath.parse_if_string(metric_type_path)
|
252
|
-
raw_hash = get_raw_entity_hash(path)
|
253
|
-
unless raw_hash
|
254
|
-
exception = HawkularException.new("Metric type not found: #{metric_type_path}")
|
255
|
-
fail exception
|
256
|
-
end
|
257
|
-
entity_hash = entity_json_to_hash(-> (_) { path }, raw_hash, false)
|
258
|
-
MetricType.new(entity_hash)
|
259
|
-
end
|
260
|
-
|
261
|
-
# List operation definitions (types) for a given resource type
|
262
|
-
# @param [String] resource_type_path canonical path of the resource type entity
|
263
|
-
# @return [Array<String>] List of operation type ids
|
264
|
-
def list_operation_definitions(resource_type_path)
|
265
|
-
path = CanonicalPath.parse_if_string(resource_type_path)
|
266
|
-
fail 'Missing feed_id in resource_type_path' unless path.feed_id
|
267
|
-
fail 'Missing resource_type_id in resource_type_path' unless path.resource_type_id
|
268
|
-
response = http_post(
|
269
|
-
'/strings/raw/query',
|
270
|
-
fromEarliest: true,
|
271
|
-
order: 'DESC',
|
272
|
-
tags: path.to_tags)
|
273
|
-
structures = extract_structures_from_body(response)
|
274
|
-
res = {}
|
275
|
-
structures.map { |rt| rt['inventoryStructure'] }
|
276
|
-
.select { |rt| rt['children'] && rt['children']['operationType'] }
|
277
|
-
.flat_map { |rt| rt['children']['operationType'] }
|
278
|
-
.each do |ot|
|
279
|
-
hash = optype_json_to_hash(ot)
|
280
|
-
od = OperationDefinition.new hash
|
281
|
-
res[od.name] = od
|
282
|
-
end
|
283
|
-
res
|
284
|
-
end
|
285
|
-
|
286
|
-
# List operation definitions (types) for a given resource
|
287
|
-
# @param [String] resource_path canonical path of the resource entity
|
288
|
-
# @return [Array<String>] List of operation type ids
|
289
|
-
def list_operation_definitions_for_resource(resource_path)
|
290
|
-
resource = get_resource(resource_path, false)
|
291
|
-
list_operation_definitions(resource.type_path)
|
91
|
+
# List resources for type
|
92
|
+
# @return [Enumeration<Resource>] Lazy-loaded Enumeration of resources
|
93
|
+
def resources_for_type(type)
|
94
|
+
resources typeId: type
|
292
95
|
end
|
293
96
|
|
294
97
|
# Return version and status information for the used version of Hawkular-Inventory
|
@@ -297,176 +100,25 @@ module Hawkular::Inventory
|
|
297
100
|
def fetch_version_and_status
|
298
101
|
http_get('/status')
|
299
102
|
end
|
103
|
+
end
|
300
104
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
private
|
306
|
-
|
307
|
-
def filter_entities(entities, filter)
|
308
|
-
entities.select do |entity|
|
309
|
-
found = true
|
310
|
-
if filter.empty?
|
311
|
-
found = true
|
312
|
-
else
|
313
|
-
found = false unless filter[:type] == (entity.type) || filter[:type].nil?
|
314
|
-
found = false unless filter[:match].nil? || entity.id.include?(filter[:match])
|
315
|
-
end
|
316
|
-
found
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
def entity_json_to_hash(path_getter, json, fetch_properties)
|
321
|
-
data = json['data']
|
322
|
-
data['path'] = path_getter.call(data['id']).to_s
|
323
|
-
if fetch_properties
|
324
|
-
props = fetch_properties(json)
|
325
|
-
data['properties'].merge! props if props
|
326
|
-
end
|
327
|
-
data
|
328
|
-
end
|
329
|
-
|
330
|
-
def fetch_properties(json)
|
331
|
-
return unless (json.key? 'children') && (json['children'].key? 'dataEntity')
|
332
|
-
config = json['children']['dataEntity'].find { |d| d['data']['id'] == 'configuration' }
|
333
|
-
config['data']['value'] if config
|
334
|
-
end
|
335
|
-
|
336
|
-
def optype_json_to_hash(json)
|
337
|
-
data = json['data']
|
338
|
-
# Fetch parameterTypes
|
339
|
-
if (json.key? 'children') && (json['children'].key? 'dataEntity')
|
340
|
-
param_types = json['children']['dataEntity'].find { |d| d['data']['id'] == 'parameterTypes' }
|
341
|
-
data['parameters'] = param_types['data']['value'] if param_types
|
342
|
-
end
|
343
|
-
data
|
344
|
-
end
|
345
|
-
|
346
|
-
def get_raw_entity_hash(path)
|
347
|
-
c_path = CanonicalPath.parse_if_string(path)
|
348
|
-
raw = http_post(
|
349
|
-
'/strings/raw/query',
|
350
|
-
fromEarliest: true,
|
351
|
-
order: 'DESC',
|
352
|
-
tags: c_path.to_tags
|
353
|
-
)
|
354
|
-
structure = extract_structure_from_body(raw)
|
355
|
-
find_entity_in_tree(c_path, structure)
|
356
|
-
end
|
357
|
-
|
358
|
-
def find_entity_in_tree(fullpath, inventory_structure)
|
359
|
-
entity = inventory_structure
|
360
|
-
if fullpath.resource_ids
|
361
|
-
relative = fullpath.resource_ids.drop(1)
|
362
|
-
relative.each do |child|
|
363
|
-
if (entity.key? 'children') && (entity['children'].key? 'resource')
|
364
|
-
unescaped = URI.unescape(child)
|
365
|
-
entity = entity['children']['resource'].find { |r| r['data']['id'] == unescaped }
|
366
|
-
else
|
367
|
-
entity = nil
|
368
|
-
break
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
if fullpath.metric_id
|
373
|
-
if (entity.key? 'children') && (entity['children'].key? 'metric')
|
374
|
-
unescaped = URI.unescape(fullpath.metric_id)
|
375
|
-
entity = entity['children']['metric'].find { |r| r['data']['id'] == unescaped }
|
376
|
-
else
|
377
|
-
entity = nil
|
378
|
-
end
|
379
|
-
end
|
380
|
-
entity
|
381
|
-
end
|
382
|
-
|
383
|
-
def extract_child_resources(arr, path, parent_hash, recursive)
|
384
|
-
c_path = CanonicalPath.parse_if_string(path)
|
385
|
-
if (parent_hash.key? 'children') && (parent_hash['children'].key? 'resource')
|
386
|
-
parent_hash['children']['resource'].each do |r|
|
387
|
-
entity = entity_json_to_hash(-> (id) { c_path.down(id) }, r, false)
|
388
|
-
arr.push(Resource.new(entity))
|
389
|
-
extract_child_resources(arr, entity['path'], r, true) if recursive
|
390
|
-
end
|
391
|
-
end
|
392
|
-
arr
|
393
|
-
end
|
394
|
-
|
395
|
-
def extract_resources_for_type(structures, feed_path, resource_type_id, fetch_properties)
|
396
|
-
matching_resources = []
|
397
|
-
structures.each do |full_struct|
|
398
|
-
next unless full_struct.key? 'typesIndex'
|
399
|
-
next unless full_struct['typesIndex'].key? resource_type_id
|
400
|
-
inventory_structure = full_struct['inventoryStructure']
|
401
|
-
root_path = feed_path.down(inventory_structure['data']['id'])
|
402
|
-
full_struct['typesIndex'][resource_type_id].each do |relative_path|
|
403
|
-
if relative_path.empty?
|
404
|
-
# Root resource
|
405
|
-
resource = entity_json_to_hash(-> (id) { feed_path.down(id) }, inventory_structure, fetch_properties)
|
406
|
-
matching_resources.push(Resource.new(resource))
|
407
|
-
else
|
408
|
-
# Search for child
|
409
|
-
fullpath = CanonicalPath.parse("#{root_path}/#{relative_path}")
|
410
|
-
resource_json = find_entity_in_tree(fullpath, inventory_structure)
|
411
|
-
if resource_json
|
412
|
-
resource = entity_json_to_hash(-> (_) { fullpath }, resource_json, fetch_properties)
|
413
|
-
matching_resources.push(Resource.new(resource))
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
|
-
end
|
418
|
-
matching_resources
|
419
|
-
end
|
420
|
-
|
421
|
-
def extract_metrics_for_type(structures, feed_path, metric_type)
|
422
|
-
matching_metrics = []
|
423
|
-
structures.each do |full_struct|
|
424
|
-
next unless full_struct.key? 'metricTypesIndex'
|
425
|
-
next unless full_struct['metricTypesIndex'].key? metric_type.id
|
426
|
-
inventory_structure = full_struct['inventoryStructure']
|
427
|
-
root_path = feed_path.down(inventory_structure['data']['id'])
|
428
|
-
full_struct['metricTypesIndex'][metric_type.id].each do |relative_path|
|
429
|
-
# Search for child
|
430
|
-
fullpath = CanonicalPath.parse("#{root_path}/#{relative_path}")
|
431
|
-
metric_json = find_entity_in_tree(fullpath, inventory_structure)
|
432
|
-
if metric_json
|
433
|
-
metric_hash = entity_json_to_hash(-> (_) { fullpath }, metric_json, false)
|
434
|
-
matching_metrics.push(Metric.new(metric_hash, metric_type))
|
435
|
-
end
|
436
|
-
end
|
437
|
-
end
|
438
|
-
matching_metrics
|
439
|
-
end
|
105
|
+
# Lazy fetching results, based on Inventory "ResultSet" model
|
106
|
+
class ResultFetcher
|
107
|
+
include Enumerable
|
440
108
|
|
441
|
-
def
|
442
|
-
|
443
|
-
structures = extract_structures_from_body(response_body_array)
|
444
|
-
structures[0]['inventoryStructure'] unless structures.empty?
|
109
|
+
def initialize(fetcher)
|
110
|
+
@fetcher = fetcher
|
445
111
|
end
|
446
112
|
|
447
|
-
def
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
master_data = data_node[0]
|
456
|
-
return Base64.decode64(master_data['value']) unless (master_data.key? 'tags') &&
|
457
|
-
(master_data['tags'].key? 'chunks')
|
458
|
-
last_chunk = master_data['tags']['chunks'].to_i - 1
|
459
|
-
all = Base64.decode64(master_data['value'])
|
460
|
-
return if all.empty?
|
461
|
-
(1..last_chunk).inject(all) do |full, chunk_id|
|
462
|
-
slave_data = data_node[chunk_id]
|
463
|
-
full.concat(Base64.decode64(slave_data['value']))
|
113
|
+
def each
|
114
|
+
offset = 0
|
115
|
+
loop do
|
116
|
+
result_set = @fetcher.call(offset)
|
117
|
+
results = result_set['results']
|
118
|
+
results.each { |r| yield(r) }
|
119
|
+
offset += results.length
|
120
|
+
break if offset >= result_set['resultSize']
|
464
121
|
end
|
465
122
|
end
|
466
|
-
|
467
|
-
def decompress(raw)
|
468
|
-
gz = Zlib::GzipReader.new(StringIO.new(raw))
|
469
|
-
JSON.parse(gz.read)
|
470
|
-
end
|
471
123
|
end
|
472
124
|
end
|