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 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