hawkular-client 3.0.2 → 5.0.0

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
  SHA1:
3
- metadata.gz: 7ab85ad134aa538531c4b1a49bd2719fa891e571
4
- data.tar.gz: 3f6eac54b04032844df33902c440e34f6e08f674
3
+ metadata.gz: e41fdf0699f44cfc71f223daa51bd936be6b6db7
4
+ data.tar.gz: 504979a3d89220826149247458d30d50fdbd783c
5
5
  SHA512:
6
- metadata.gz: 006e318a94934bf4c982cdee7cddd0c0e0d511a5162aa79cccd19a0a6d9c956f0a4fa3dbca75f2faf32d03f1b3c5eeebe770fa37d8e68e10961308bbf391700c
7
- data.tar.gz: 1858d7ad7caac9a136f42419da8b7b9e990216f62cf4529dbdeaa45080a84d3e6f69fe55cdda8296b593f0aa6157f01718c3377ddb51547cd900e6e25ff840f2
6
+ metadata.gz: 1e75e32352cf4981d90ac6bf55cf177d489fe9e62fc3274a6ffbbc44500ed71c2a3fd702bc3e88fcab7a0c06ea1a7ba62dfa85636ee8a3fe0a532d35371d2dfd
7
+ data.tar.gz: c8d1e5fac46c5bacbdce0c007ff387545a23154ca4294ab6b277ab7865bfeefe10def5b86df63e6b35d64e0c0acbfdffe806102ae52f2004d49c59d0518b929a
@@ -3,6 +3,28 @@
3
3
  This document describes the relevant changes between releases of the
4
4
  _hawkular-client_ project.
5
5
 
6
+ === v 5.0.0.pre1
7
+ * Hawkular services version 0.40.x and Hawkular Agent 1.x will be the last
8
+ versions to include support for _inventory-on-metrics_ and Hawkular Metrics.
9
+ The following versions won't be backwards compatible. Right now, a new API
10
+ for inventory is already implemented. This pre-release of the client is
11
+ adding support for this new inventory API and removing all support for the
12
+ previous implementation. See link:api_breaking_changes.rdoc for more details.
13
+ * Because of the new inventory implementation, the _Operations_ client requires
14
+ the feed id to be sent on all operations. See link:api_breaking_changes.rdoc
15
+ for more details.
16
+ * Support for a _sender_request_id_ has been added to the _Operations_ client.
17
+ This allows to match operation requests with their respective operation result
18
+ websocket messages.
19
+
20
+ === v 4.1.0
21
+ * Fixed binary data handling when invoking <em>Export JDR</em> on operations API.
22
+ * Added <em>delete_immediately</em> parameter to <em>Export JDR</em> operation.
23
+
24
+ === v 4.0.0
25
+ * Standardized Exceptions under the Hawkular namespace, and the old names were deprecated, here is the list:
26
+ 1. <code>Hawkular::BaseClient::HawkularException</code> -> <code>Hawkular::Exception</code>
27
+ 2. <code>Hawkular::BaseClient::HawkularConnectionException</code> -> <code>Hawkular::ConnectionException</code>
6
28
 
7
29
  === v 3.0.2
8
30
  * Adding <code>URI.unescape</code> in the <code>list_metrics_for_resource</code> method to fix the behavior of the method
@@ -6,7 +6,7 @@
6
6
 
7
7
  A Ruby Hawkular Client.
8
8
 
9
- Documentation[http://www.hawkular.org/hawkular-client-ruby/docs/]
9
+ Documentation[http://www.hawkular.org/hawkular-client-ruby/]
10
10
 
11
11
  == Changelog
12
12
 
@@ -135,7 +135,6 @@ Check each resource API for a detailed description of what methods are available
135
135
  Integration tests are recorded and played against cassettes recorded with VCR
136
136
  (http://www.relishapp.com/vcr/vcr/docs)
137
137
 
138
- * Edit the endpoint properties in the file +spec/endpoint.yml+ (user, password and host name) if needed
139
138
  * From command line run
140
139
  rake spec
141
140
  * To run the tests against a live server, set +VCR_OFF+ to +1+ as in
@@ -182,11 +182,7 @@ module Hawkular::Alerts
182
182
  # Obtains action definition/plugin from the server.
183
183
  # @param [String] action_plugin Id of the action plugin to fetch. If nil, all the plugins are fetched
184
184
  def get_action_definition(action_plugin = nil)
185
- if action_plugin.nil?
186
- plugins = http_get('plugins')
187
- else
188
- plugins = [action_plugin]
189
- end
185
+ plugins = action_plugin.nil? ? http_get('plugins') : [action_plugin]
190
186
  ret = {}
191
187
  plugins.each do |p|
192
188
  ret[p] = http_get("/plugins/#{p}")
@@ -232,7 +228,8 @@ module Hawkular::Alerts
232
228
  # Obtain the alerts for the Trigger with the passed id
233
229
  # @param [String] trigger_id Id of the trigger that has fired the alerts
234
230
  # @return [Array<Alert>] List of alerts for the trigger. Can be empty
235
- def get_alerts_for_trigger(trigger_id) # TODO: add additional filters
231
+ def get_alerts_for_trigger(trigger_id)
232
+ # TODO: add additional filters
236
233
  return [] unless trigger_id
237
234
 
238
235
  url = '/?triggerIds=' + trigger_id
@@ -254,7 +251,7 @@ module Hawkular::Alerts
254
251
  # @param [Array] tenants optional list of tenants. The elements of the array can be any object
255
252
  # convertible to a string
256
253
  # @return [Array<Alert>] List of alerts in the system. Can be empty
257
- def alerts(criteria: {}, tenants:nil)
254
+ def alerts(criteria: {}, tenants: nil)
258
255
  query = generate_query_params(criteria)
259
256
  uri = tenants ? '/admin/alerts/' : '/'
260
257
  ret = http_get(uri + query, multi_tenants_header(tenants))
@@ -389,7 +386,7 @@ module Hawkular::Alerts
389
386
  attr_accessor :auto_resolve, :auto_resolve_alerts, :tags, :type
390
387
  attr_accessor :tenant, :description, :group, :severity, :event_type, :event_category, :member_of, :data_id_map
391
388
  attr_reader :conditions, :dampenings
392
- attr_accessor :enabled, :actions, :firing_match, :auto_resolve_match
389
+ attr_accessor :enabled, :firing_match, :auto_resolve_match
393
390
 
394
391
  def initialize(trigger_hash)
395
392
  return if trigger_hash.nil?
@@ -427,9 +424,10 @@ module Hawkular::Alerts
427
424
  ret = x.to_s.split('_').collect(&:capitalize).join
428
425
  ret[0, 1].downcase + ret[1..-1]
429
426
  end
430
- fields = [:id, :name, :enabled, :severity, :auto_resolve, :auto_resolve_alerts, :event_type, :event_category,
431
- :description, :auto_enable, :auto_disable, :context, :type, :tags, :member_of, :data_id_map,
432
- :firing_match, :auto_resolve_match]
427
+ fields = %i[id name enabled severity auto_resolve auto_resolve_alerts
428
+ event_type event_category description auto_enable auto_disable
429
+ context type tags member_of data_id_map firing_match
430
+ auto_resolve_match]
433
431
 
434
432
  fields.each do |field|
435
433
  camelized_field = to_camel.call(field)
@@ -448,6 +446,7 @@ module Hawkular::Alerts
448
446
  class Condition
449
447
  attr_accessor :condition_id, :type, :operator, :threshold
450
448
  attr_accessor :trigger_mode, :data_id, :data2_id, :data2_multiplier
449
+ attr_accessor :alerter_id, :expression
451
450
  attr_reader :condition_set_size, :condition_set_index, :trigger_id
452
451
 
453
452
  def initialize(cond_hash)
@@ -461,7 +460,8 @@ module Hawkular::Alerts
461
460
  @data2_id = cond_hash['data2Id']
462
461
  @data2_multiplier = cond_hash['data2Multiplier']
463
462
  @trigger_id = cond_hash['triggerId']
464
- @interval = cond_hash['interval']
463
+ @alerter_id = cond_hash['alerterId']
464
+ @expression = cond_hash['expression']
465
465
  end
466
466
 
467
467
  def to_h
@@ -476,7 +476,8 @@ module Hawkular::Alerts
476
476
  cond_hash['data2Id'] = @data2_id
477
477
  cond_hash['data2Multiplier'] = @data2_multiplier
478
478
  cond_hash['triggerId'] = @trigger_id
479
- cond_hash['interval'] = @interval
479
+ cond_hash['alerterId'] = @alerter_id
480
+ cond_hash['expression'] = @expression
480
481
  cond_hash
481
482
  end
482
483
  end
@@ -601,8 +602,8 @@ module Hawkular::Alerts
601
602
  end
602
603
 
603
604
  # for some API back compatibility
604
- alias_method :ackBy, :ack_by
605
- alias_method :resolvedBy, :resolved_by
605
+ alias ackBy ack_by
606
+ alias resolvedBy resolved_by
606
607
  end
607
608
 
608
609
  # Representation of one event.
@@ -3,12 +3,16 @@ require 'addressable/uri'
3
3
 
4
4
  require 'hawkular/logger'
5
5
  require 'hawkular/client_utils'
6
+ require 'erb'
6
7
 
7
8
  module Hawkular
8
9
  # This is the base functionality for all the clients,
9
10
  # that inherit from it. You should not directly use it,
10
11
  # but through the more specialized clients.
11
12
  class BaseClient
13
+ HawkularException = Hawkular::Exception
14
+ HawkularConnectionException = Hawkular::ConnectionException
15
+
12
16
  include ClientUtils
13
17
 
14
18
  # @!visibility private
@@ -34,7 +38,11 @@ module Hawkular
34
38
 
35
39
  @logger = Hawkular::Logger.new
36
40
 
37
- fail 'You need to provide an entrypoint' if entrypoint.nil?
41
+ fail Hawkular::ArgumentError, 'You need to provide an entrypoint' if entrypoint.nil?
42
+ end
43
+
44
+ def url(url_format, *params)
45
+ url_format % params.map { |p| ERB::Util.url_encode(p) }
38
46
  end
39
47
 
40
48
  def http_get(suburl, headers = {})
@@ -87,7 +95,7 @@ module Hawkular
87
95
  opts[:user] = @credentials[:username]
88
96
  opts[:password] = @credentials[:password]
89
97
  # strip @endpoint in case suburl is absolute
90
- suburl = suburl[@entrypoint.length, suburl.length] if suburl.match(/^http/)
98
+ suburl = suburl[@entrypoint.length, suburl.length] if suburl =~ /^http/
91
99
  RestClient::Resource.new(@entrypoint, opts)[suburl]
92
100
  end
93
101
 
@@ -123,12 +131,12 @@ module Hawkular
123
131
  # @param params [Hash] key-values pairs
124
132
  # @return [String] complete query string to append to a base url, '' if no valid params
125
133
  def generate_query_params(params = {})
126
- params = params.select { |_k, v| !(v.nil? || ((v.instance_of? Array) && v.empty?)) }
134
+ params = params.reject { |_k, v| v.nil? || ((v.instance_of? Array) && v.empty?) }
127
135
  return '' if params.empty?
128
136
 
129
137
  params.inject('?') do |ret, (k, v)|
130
138
  ret += '&' unless ret == '?'
131
- part = (v.instance_of? Array) ? "#{k}=#{v.join(',')}" : "#{k}=#{v}"
139
+ part = v.instance_of?(Array) ? "#{k}=#{v.join(',')}" : "#{k}=#{v}"
132
140
  ret + hawk_escape(part)
133
141
  end
134
142
  end
@@ -141,7 +149,8 @@ module Hawkular
141
149
  # @param suffix_path [String] sufix path to be added if it doesn't exist
142
150
  # @return [String] URL with path attached to it at the end
143
151
  def normalize_entrypoint_url(entrypoint, suffix_path)
144
- fail ArgumentError, 'suffix_path must not be empty' if suffix_path.empty?
152
+ fail Hawkular::ArgumentError, 'suffix_path must not be empty' if suffix_path.empty?
153
+
145
154
  strip_path = suffix_path.gsub(%r{/$}, '')
146
155
  strip_path.nil? || suffix_path = strip_path
147
156
  strip_path = suffix_path.gsub(%r{^/}, '')
@@ -165,21 +174,6 @@ module Hawkular
165
174
  url.to_s.sub(/^http(s?)/, 'ws\1')
166
175
  end
167
176
 
168
- # Specialized exception to be thrown
169
- # when the interaction with Hawkular fails
170
- class HawkularException < StandardError
171
- def initialize(message, status_code = 0)
172
- @message = message
173
- @status_code = status_code
174
- super(message)
175
- end
176
-
177
- attr_reader :message, :status_code
178
- end
179
-
180
- class HawkularConnectionException < HawkularException
181
- end
182
-
183
177
  def admin_header
184
178
  headers = {}
185
179
  headers[:'Hawkular-Admin-Token'] = @admin_token unless @admin_token.nil?
@@ -201,17 +195,18 @@ module Hawkular
201
195
  # @!visibility private
202
196
  def connect_error(fault)
203
197
  if fault.is_a?(SocketError)
204
- HawkularConnectionException.new(fault.to_s)
198
+ Hawkular::ConnectionException.new(fault.to_s)
205
199
  elsif [Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH,
206
200
  Errno::EADDRNOTAVAIL, Errno::ENETDOWN, Errno::ENETUNREACH,
207
201
  Errno::ETIMEDOUT].include?(fault.class)
208
- HawkularConnectionException.new(fault.to_s, fault.class::Errno)
202
+ Hawkular::ConnectionException.new(fault.to_s, fault.class::Errno)
209
203
  end
210
204
  end
211
205
 
212
206
  def handle_fault(f)
213
207
  http_code = (f.respond_to?(:http_code) ? f.http_code : 0)
214
- fail HawkularException.new('Unauthorized', http_code) if f.instance_of? RestClient::Unauthorized
208
+ fail Hawkular::Exception.new('Unauthorized', http_code) if f.instance_of? RestClient::Unauthorized
209
+
215
210
  if f.respond_to?(:http_body) && !f.http_body.nil?
216
211
  begin
217
212
  json_body = JSON.parse(f.http_body)
@@ -219,11 +214,12 @@ module Hawkular
219
214
  rescue JSON::ParserError
220
215
  fault_message = f.http_body
221
216
  end
222
- fail HawkularException.new(fault_message, http_code)
217
+
218
+ fail Hawkular::Exception.new(fault_message, http_code)
223
219
  elsif (connect_error_exception = connect_error(f))
224
- fail connect_error_exception
220
+ fail Hawkular::ConnectionException, connect_error_exception
225
221
  else
226
- fail f
222
+ fail Hawkular::Exception, f
227
223
  end
228
224
  end
229
225
  end
@@ -1,4 +1,22 @@
1
1
  module Hawkular
2
+ # Specialized exception to be thrown
3
+ # when the interaction with Hawkular fails
4
+ class Exception < StandardError
5
+ def initialize(message, status_code = 0)
6
+ @message = message
7
+ @status_code = status_code
8
+ super(message)
9
+ end
10
+
11
+ attr_reader :message, :status_code
12
+ end
13
+
14
+ class ConnectionException < Hawkular::Exception
15
+ end
16
+
17
+ class ArgumentError < Hawkular::Exception
18
+ end
19
+
2
20
  module ClientUtils
3
21
  # Escapes the passed url part. This is necessary,
4
22
  # as many ids inside Hawkular can contain characters
@@ -1,48 +1,42 @@
1
1
  require 'hawkular/inventory/inventory_api'
2
- require 'hawkular/metrics/metrics_client'
3
2
  require 'hawkular/alerts/alerts_api'
4
3
  require 'hawkular/tokens/tokens_api'
5
4
  require 'hawkular/operations/operations_api'
5
+ require 'hawkular/prometheus/prometheus_api'
6
6
  require 'hawkular/base_client'
7
7
 
8
8
  module Hawkular
9
9
  class Client
10
- attr_reader :inventory, :metrics, :alerts, :operations, :tokens, :state
11
-
12
10
  def initialize(hash)
13
11
  hash[:credentials] ||= {}
14
12
  hash[:options] ||= {}
15
- fail 'no parameter ":entrypoint" given' if hash[:entrypoint].nil?
13
+
14
+ fail Hawkular::ArgumentError, 'no parameter ":entrypoint" given' if hash[:entrypoint].nil?
15
+
16
16
  @state = hash
17
17
  end
18
18
 
19
+ def respond_to_missing?(method_name, include_private = false)
20
+ delegate_client = client_for_method(method_name)
21
+ return super if delegate_client.nil?
22
+
23
+ method = submethod_name_for(method_name)
24
+ return super unless delegate_client.respond_to?(method)
25
+
26
+ true
27
+ end
28
+
19
29
  def method_missing(name, *args, &block)
20
- delegate_client = case name
21
- when /^inventory_/ then inventory
22
- when /^metrics_/ then metrics
23
- when /^alerts_/ then alerts
24
- when /^operations_/ then operations
25
- when /^tokens_/ then tokens
26
- else
27
- fail "unknown method prefix `#{name}`, allowed prefixes:"\
28
- '`inventory_`, `metrics_`,`alerts_`,`operations_`, `tokens_`'
29
- end
30
- method = name.to_s.sub(/^[^_]+_/, '')
31
- delegate_client.__send__(method, *args, &block)
30
+ super unless respond_to?(name)
31
+ client_for_method(name).__send__(submethod_name_for(name), *args, &block)
32
32
  end
33
33
 
34
34
  def inventory
35
- @inventory ||= Inventory::Client.new("#{@state[:entrypoint]}/hawkular/metrics",
35
+ @inventory ||= Inventory::Client.new("#{@state[:entrypoint]}/hawkular/inventory",
36
36
  @state[:credentials],
37
37
  @state[:options])
38
38
  end
39
39
 
40
- def metrics
41
- @metrics ||= Metrics::Client.new("#{@state[:entrypoint]}/hawkular/metrics",
42
- @state[:credentials],
43
- @state[:options])
44
- end
45
-
46
40
  def alerts
47
41
  @alerts ||= Alerts::Client.new("#{@state[:entrypoint]}/hawkular/alerts",
48
42
  @state[:credentials],
@@ -62,6 +56,12 @@ module Hawkular
62
56
  @state[:options])
63
57
  end
64
58
 
59
+ def prometheus
60
+ @prometheus ||= Prometheus::Client.new(@state[:entrypoint],
61
+ @state[:credentials],
62
+ @state[:options])
63
+ end
64
+
65
65
  private
66
66
 
67
67
  # this is in a dedicated method, because constructor opens the websocket connection to make the handshake
@@ -70,5 +70,19 @@ module Hawkular
70
70
  credentials: @state[:credentials],
71
71
  options: @state[:options])
72
72
  end
73
+
74
+ def client_for_method(method_name)
75
+ case method_name
76
+ when /^inventory_/ then inventory
77
+ when /^alerts_/ then alerts
78
+ when /^operations_/ then operations
79
+ when /^tokens_/ then tokens
80
+ when /^prometheus_/ then prometheus
81
+ end
82
+ end
83
+
84
+ def submethod_name_for(method_name)
85
+ method_name.to_s.sub(/^[^_]+_/, '')
86
+ end
73
87
  end
74
88
  end
@@ -1,306 +1,134 @@
1
1
  # It contains class definitions that are used by the inventory REST client
2
2
  module Hawkular::Inventory
3
- # A Basic inventory entity with id, name, path and optional properties
4
- class BaseEntity
5
- # @return [String] Full path of the entity
6
- attr_reader :path
7
- # @return [String] Name of the entity
3
+ class Metric
4
+ # @return [String] Provider Name of the metric
8
5
  attr_reader :name
9
- # @return [String] Id of the entity
10
- attr_reader :id
11
- # @return [String] Feed this entity belongs to (or nil in case of a feedless entity)
12
- attr_reader :feed
13
- # @return [String] Name of the environment for this entity
14
- attr_reader :env
15
- # @return [String] Properties of this entity
6
+ # @return [String] Display Name of the metric
7
+ attr_reader :display_name
8
+ # @return [String] Family of the metric (Prometheus family name)
9
+ attr_reader :family
10
+ # @return [String] Promql expression for fetching the time series
11
+ attr_reader :expression
12
+ # @return [String] Unit of the metric
13
+ attr_reader :unit
14
+ # @return [Hash<String,String>] Labels of this metric (Prometheus labels)
15
+ attr_reader :labels
16
+ # @return [Hash<String,String>] Properties of this metric
16
17
  attr_reader :properties
17
18
 
18
19
  def initialize(hash)
19
- @id = hash['id']
20
- @path = hash['path']
21
- @name = hash['name'] || @id
20
+ @name = hash['displayName']
21
+ @display_name = hash['displayName']
22
+ @family = hash['family']
23
+ @expression = hash['expression']
24
+ @unit = hash['unit']
25
+ @labels = hash['labels'] || {}
22
26
  @properties = hash['properties'] || {}
23
27
  @_hash = hash.dup
24
-
25
- return if @path.nil?
26
-
27
- tmp = @path.split('/')
28
- tmp.each do |pair|
29
- (key, val) = pair.split(';')
30
- case key
31
- when 'f'
32
- @feed = val
33
- when 'e'
34
- @env = val
35
- end
36
- end
37
28
  end
38
29
 
39
- def ==(other)
40
- self.equal?(other) || other.class == self.class && other.id == @id
41
- end
42
-
43
- # Returns a hash representation of the resource type
44
- # @return [Hash<String,Object>] hash of the type
30
+ # Returns a hash representation of the metric type
31
+ # @return [Hash<String,Object>] hash of the metric type
45
32
  def to_h
46
33
  @_hash.dup
47
34
  end
48
35
  end
49
36
 
50
- # A ResourceType is like a class definition for {Resource}s
51
- # ResourceTypes are currently unique per feed, but one can assume
52
- # that a two types with the same name of two different feeds are
53
- # (more or less) the same.
54
- class ResourceType < BaseEntity
55
- def initialize(rt_hash)
56
- super(rt_hash)
57
- end
58
- end
59
-
60
- # A Resource is an instantiation of a {ResourceType}
61
- class Resource < BaseEntity
62
- # @return [String] Full path of the {ResourceType}
63
- attr_reader :type_path
64
-
65
- def initialize(res_hash)
66
- super(res_hash)
67
- if res_hash.key? :resourceTypePath
68
- @type_path = res_hash[:resourceTypePath]
69
- elsif res_hash.key? 'resourceTypePath'
70
- @type_path = res_hash['resourceTypePath']
71
- else
72
- @type = res_hash['type']
73
- @type_path = res_hash['type']['path']
74
- end
75
- end
76
- end
77
-
78
- # Fields that are common for MetricType and Metric
79
- module MetricFields
80
- # @return [String] GAUGE, COUNTER, etc.
81
- attr_reader :type
82
- # @return [String] metric unit such as NONE, BYTES, etc.
83
- attr_reader :unit
84
- # @return [Long] collection interval in seconds, it has different semantics for MetricType and for Metric
85
- # for MetricType it's a default that will be applied to all the metric of that type,
86
- # in the Metric this can be overridden
87
- attr_reader :collection_interval
88
- end
89
-
90
- # Definition of a Metric Type inside the inventory.
91
- class MetricType < BaseEntity
92
- include MetricFields
93
-
94
- def initialize(type_hash)
95
- super(type_hash)
96
- @type = type_hash['type']
97
- @unit = type_hash['unit']
98
- @collection_interval = type_hash['collectionInterval']
99
- end
100
- end
101
-
102
- # Definition of a Metric inside the inventory.
103
- class Metric < BaseEntity
104
- include MetricFields
105
-
106
- attr_reader :type_id
107
- # @return [String] metric id used in Hawkular Metrics
108
- attr_reader :hawkular_metric_id
109
-
110
- def initialize(metric_hash, metric_type)
111
- super(metric_hash)
112
- @type = metric_type.type
113
- @type_path = metric_hash['metricTypePath']
114
- @type_id = metric_type.id
115
- @unit = metric_type.unit
116
- @collection_interval = metric_hash['collectionInterval'] || metric_type.collection_interval
117
- @hawkular_metric_id = @properties.key?('hawkular-metric-id') ? @properties['hawkular-metric-id'] : @id
118
- end
119
- end
120
-
121
- class OperationDefinition < BaseEntity
37
+ class Operation
38
+ # @return [String] Name of the operation
39
+ attr_reader :name
122
40
  attr_reader :params
123
41
 
124
42
  def initialize(op_hash)
125
- super(op_hash)
126
- @params = (op_hash.key? 'parameters') ? op_hash['parameters'] : {}
43
+ @name = op_hash['name']
44
+ @params = op_hash.key?('parameters') ? op_hash['parameters'] : {}
127
45
  end
128
46
  end
129
47
 
130
- # Definition of a Relationship between two entities in Inventory
131
- class Relationship
132
- attr_accessor :source_id
133
- attr_reader :target_id
134
- attr_reader :properties
135
- attr_reader :name
48
+ class ResourceType
49
+ # @return [String] Id of the resource type
136
50
  attr_reader :id
51
+ # @return [Hash<String,String>] Properties of this resource type
52
+ attr_reader :properties
53
+ # @return [List<Operation>] Operations associated with this type
54
+ attr_reader :operations
137
55
 
138
- def initialize(hash = {})
139
- if hash.empty?
140
- @properties = {}
141
- return
142
- end
143
-
144
- @source_id = hash['source']
145
- @target_id = hash['target']
146
- @properties = hash['properties']
147
- @name = hash['name']
56
+ def initialize(hash)
148
57
  @id = hash['id']
58
+ @properties = hash['properties'] || {}
59
+ @operations = (hash['operations'] || []).map { |op| Operation.new(op) }
60
+ @_hash = hash.dup
61
+ end
62
+
63
+ def ==(other)
64
+ equal?(other) || other.class == self.class && other.id == @id
149
65
  end
150
66
 
67
+ # Returns a hash representation of the resource type
68
+ # @return [Hash<String,Object>] hash of the resource type
151
69
  def to_h
152
- hash = {}
153
- hash['source'] = @source_id
154
- hash['target'] = @target_id
155
- hash['properties'] = @properties
156
- hash['name'] = @name
157
- hash['id'] = @id
158
- hash
70
+ @_hash.dup
159
71
  end
160
72
  end
161
73
 
162
- class CanonicalPath
163
- include Hawkular::ClientUtils
164
-
165
- attr_reader :tenant_id
166
- attr_reader :feed_id
167
- attr_reader :environment_id
168
- attr_reader :resource_ids
169
- attr_reader :metric_id
170
- attr_reader :resource_type_id
171
- attr_reader :metric_type_id
74
+ class Resource
75
+ # @return [String] Id of the entity
76
+ attr_reader :id
77
+ # @return [String] Name of the entity
78
+ attr_reader :name
79
+ # @return [String] Feed this entity belongs to
80
+ attr_reader :feed
81
+ # @return [ResourceType] Type of this resource
82
+ attr_reader :type
83
+ # @return [String] Parent ID of this entity (nil if it's a root resource)
84
+ attr_reader :parent_id
85
+ # @return [Hash<String,String>] Properties of this resource
86
+ attr_reader :properties
87
+ # @return [Hash<String,String>] Config map of this resource
88
+ attr_reader :config
172
89
 
173
90
  def initialize(hash)
174
- @tenant_id = hash[:tenant_id]
175
- @feed_id = hash[:feed_id]
176
- @environment_id = hash[:environment_id]
177
- @resource_type_id = hash[:resource_type_id]
178
- @metric_type_id = hash[:metric_type_id]
179
- @resource_ids = hash[:resource_ids]
180
- @metric_id = hash[:metric_id]
181
- end
182
-
183
- def self.parse(path)
184
- fail 'CanonicalPath must not be nil or empty' if path.to_s.strip.length == 0
185
- CanonicalPath.new(path_to_h path)
186
- end
187
-
188
- def self.parse_if_string(path)
189
- path.is_a?(CanonicalPath) ? path : CanonicalPath.parse(path)
190
- end
191
-
192
- def copy_hash
193
- hash = to_h
194
- hash[:resource_ids] = hash[:resource_ids].clone unless hash[:resource_ids].nil?
195
- hash
91
+ @id = hash['id']
92
+ @name = hash['name']
93
+ @feed = hash['feedId']
94
+ @type = ResourceType.new(hash['type'])
95
+ @parent_id = hash['parentId']
96
+ @properties = hash['properties'] || {}
97
+ @config = hash['config'] || {}
98
+ @metrics = (hash['metrics'] || []).map { |m| Metric.new(m) }
99
+ @children = hash['children'].map { |r| Resource.new(r) } if hash.key? 'children'
100
+ @_hash = hash.dup
196
101
  end
197
102
 
198
- # Move up to the parent path of the resource. resource_ids set to empty array when there is no parent.
199
- # @return CanonicalPath corresponding to the direct ancestor of the resource represented by this path object.
200
- def up
201
- hash = copy_hash
202
- res = hash[:resource_ids] || []
203
- res = res.take(res.length - 1) unless res.empty?
204
- hash[:resource_ids] = res
205
- CanonicalPath.new(hash)
103
+ def children(recursive = false)
104
+ return @children unless recursive == true
105
+ fail Hawkular::ArgumentError 'Resource tree not loaded, load it by calling resource_tree' if @children.nil?
106
+ @children.flat_map do |child|
107
+ [child, *child.children(recursive)]
108
+ end
206
109
  end
207
110
 
208
- # Add resource down to the current path
209
- # @return a new CanonicalPath based on the current one
210
- def down(resource)
211
- hash = copy_hash
212
- hash[:resource_ids] = (hash[:resource_ids] || []) << hawk_escape_id(resource)
213
- CanonicalPath.new(hash)
111
+ def children_by_type(type, recursive = false)
112
+ children(recursive).select { |c| c.type.id == type }
214
113
  end
215
114
 
216
- # Set resource type to the current path
217
- # @return a new CanonicalPath based on the current one
218
- def resource_type(resource_type)
219
- hash = copy_hash
220
- hash[:resource_type_id] = hawk_escape_id(resource_type)
221
- CanonicalPath.new(hash)
115
+ def metrics(recursive = false)
116
+ return @metrics unless recursive == true
117
+ children(recursive).collect(&:metrics).flat_map(&:itself).concat(@metrics)
222
118
  end
223
119
 
224
- # Set metric type to the current path
225
- # @return a new CanonicalPath based on the current one
226
- def metric_type(metric_type)
227
- hash = copy_hash
228
- hash[:metric_type_id] = hawk_escape_id(metric_type)
229
- CanonicalPath.new(hash)
120
+ def metrics_by_family(family)
121
+ @metrics.select { |m| m.family == family }
230
122
  end
231
123
 
232
124
  def ==(other)
233
- self.equal?(other) || other.class == self.class && other.state == state
125
+ equal?(other) || other.class == self.class && other.id == @id
234
126
  end
235
127
 
128
+ # Returns a hash representation of the resource
129
+ # @return [Hash<String,Object>] hash of the resource
236
130
  def to_h
237
- {
238
- tenant_id: @tenant_id,
239
- feed_id: @feed_id,
240
- environment_id: environment_id,
241
- resource_type_id: resource_type_id,
242
- metric_type_id: metric_type_id,
243
- resource_ids: resource_ids,
244
- metric_id: @metric_id
245
- }
246
- end
247
-
248
- def to_s
249
- ret = "/t;#{@tenant_id}"
250
- ret += "/f;#{@feed_id}" unless @feed_id.nil?
251
- ret += "/e;#{@environment_id}" unless @environment_id.nil?
252
- ret += "/rt;#{@resource_type_id}" unless @resource_type_id.nil?
253
- ret += "/mt;#{@metric_type_id}" unless @metric_type_id.nil?
254
- ret += resources_chunk.to_s
255
- ret += "/m;#{@metric_id}" unless @metric_id.nil?
256
- ret
257
- end
258
-
259
- def to_tags
260
- fail 'Missing feed_id' if @feed_id.nil?
261
- tags = "module:inventory,feed:#{Regexp.quote(@feed_id)}"
262
- tags += ",type:rt,id:#{Regexp.quote(@resource_type_id)}" if @resource_type_id
263
- tags += ",type:mt,id:#{Regexp.quote(@metric_type_id)}" if @metric_type_id
264
- tags += ",type:r,id:#{Regexp.quote(@resource_ids[0])}" if @resource_ids && (!@resource_ids.empty?)
265
- tags
266
- end
267
-
268
- protected
269
-
270
- def state
271
- [@tenant_id, @feed_id, @environment_id, @resource_ids, @metric_id, @metric_type_id, @resource_type_id]
272
- end
273
-
274
- private
275
-
276
- def resources_chunk
277
- @resource_ids.map { |r| "/r;#{r}" }.join unless @resource_ids.nil?
278
- end
279
-
280
- def self.path_to_h(path)
281
- tmp = path.split('/')
282
- hash = {}
283
- tmp.each do |pair|
284
- (key, val) = pair.split(';')
285
- case key
286
- when 't'
287
- hash[:tenant_id] = val
288
- when 'f'
289
- hash[:feed_id] = val
290
- when 'e'
291
- hash[:environment_id] = val
292
- when 'm'
293
- hash[:metric_id] = val
294
- when 'r'
295
- hash[:resource_ids] = [] if hash[:resource_ids].nil?
296
- hash[:resource_ids].push(val)
297
- when 'mt'
298
- hash[:metric_type_id] = val
299
- when 'rt'
300
- hash[:resource_type_id] = val
301
- end
302
- end
303
- hash
131
+ @_hash.dup
304
132
  end
305
133
  end
306
134
  end