hawkular-client 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +19 -6
- data/CHANGES.rdoc +13 -3
- data/README.rdoc +9 -3
- data/hawkularclient.gemspec +8 -4
- data/lib/alerts/alerts_api.rb +202 -32
- data/lib/hawkular.rb +35 -67
- data/lib/hawkular_all.rb +2 -0
- data/lib/inventory/inventory_api.rb +459 -130
- data/lib/metrics/metric_api.rb +14 -9
- data/lib/operations/operations_api.rb +247 -0
- data/lib/tokens/tokens_api.rb +33 -0
- data/lib/version.rb +1 -1
- data/spec/integration/alerts_spec.rb +272 -20
- data/spec/integration/hello-world-definitions.json +46 -0
- data/spec/integration/inventory_spec.rb +253 -89
- data/spec/integration/metric_spec.rb +36 -0
- data/spec/integration/operations_spec.rb +420 -0
- data/spec/integration/tokens_spec.rb +45 -0
- data/spec/resources/driver.jar +0 -0
- data/spec/resources/sample.war +0 -0
- data/spec/spec_helper.rb +30 -6
- data/spec/unit/base_spec.rb +22 -1
- data/spec/unit/canonical_path_spec.rb +92 -0
- data/spec/vcr/vcr_setup.rb +3 -4
- data/spec/vcr_cassettes/Alert/EndToEnd/Should_create_and_fire_a_trigger.yml +1187 -0
- data/spec/vcr_cassettes/Alert/Events/Should_list_events.yml +101 -0
- data/spec/vcr_cassettes/Alert/Events/Should_list_events_using_criteria.yml +79 -0
- data/spec/vcr_cassettes/Alert/Events/Should_not_list_events_using_criteria.yml +49 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_bulk_load_triggers.yml +225 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_create_a_basic_trigger_with_action.yml +355 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_create_an_action.yml +134 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_create_an_action_for_webhooks.yml +220 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_get_the_action_definitions.yml +218 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_not_create_an_action_for_unknown_plugin.yml +46 -0
- data/spec/vcr_cassettes/Alert/Triggers/Should_not_create_an_action_for_unknown_properties.yml +134 -0
- data/spec/vcr_cassettes/Counter_metrics/Should_get_metrics_with_limit_and_order.yml +270 -0
- data/spec/vcr_cassettes/Inventory/Client_should_listen_on_various_inventory_events.json +47 -0
- data/spec/vcr_cassettes/Inventory/Client_should_listen_on_various_inventory_events.yml +191 -0
- data/spec/vcr_cassettes/Inventory/Helpers/generate_some_events_for_websocket.yml +507 -0
- data/spec/vcr_cassettes/Inventory/Should_List_datasources_with_no_props.yml +74 -69
- data/spec/vcr_cassettes/Inventory/{Should_list_types_without_feed.yml → Should_create_a_feed.yml} +29 -32
- data/spec/vcr_cassettes/Inventory/Should_create_a_feed_again.yml +211 -0
- data/spec/vcr_cassettes/Inventory/Should_create_a_resource_.yml +355 -0
- data/spec/vcr_cassettes/Inventory/Should_create_a_resource_with_metric.yml +786 -0
- data/spec/vcr_cassettes/Inventory/Should_create_a_resourcetype.yml +205 -0
- data/spec/vcr_cassettes/Inventory/Should_create_and_delete_feed.yml +201 -0
- data/spec/vcr_cassettes/Inventory/Should_create_and_get_a_resource.yml +419 -0
- data/spec/vcr_cassettes/Inventory/Should_list_URLs.yml +39 -27
- data/spec/vcr_cassettes/Inventory/Should_list_WildFlys.yml +37 -29
- data/spec/vcr_cassettes/Inventory/Should_list_WildFlys_with_props.yml +53 -45
- data/spec/vcr_cassettes/Inventory/Should_list_all_the_resource_types.yml +177 -0
- data/spec/vcr_cassettes/Inventory/Should_list_children_of_WildFly.yml +230 -56
- data/spec/vcr_cassettes/Inventory/Should_list_feeds.yml +27 -24
- data/spec/vcr_cassettes/Inventory/Should_list_heap_metrics_for_WildFlys.yml +586 -119
- data/spec/vcr_cassettes/Inventory/Should_list_metrics_for_WildFlys.yml +220 -59
- data/spec/vcr_cassettes/Inventory/Should_list_metrics_of_given_metric_type.yml +613 -0
- data/spec/vcr_cassettes/Inventory/Should_list_metrics_of_given_resource_type.yml +333 -0
- data/spec/vcr_cassettes/Inventory/Should_list_recursive_children_of_WildFly.yml +2064 -0
- data/spec/vcr_cassettes/Inventory/Should_list_relationships_of_WildFly.yml +460 -0
- data/spec/vcr_cassettes/Inventory/Should_list_types_with_bad_feed.yml +26 -25
- data/spec/vcr_cassettes/Inventory/Should_list_types_with_feed.yml +102 -36
- data/spec/vcr_cassettes/Inventory/Should_not_find_an_unknown_resource.yml +54 -0
- data/spec/vcr_cassettes/Inventory/Tenants/Should_Get_Tenant_For_Explicit_Credentials.yml +50 -0
- data/spec/vcr_cassettes/Inventory/Tenants/Should_Get_Tenant_For_Implicit_Credentials.yml +50 -0
- data/spec/vcr_cassettes/Operation/Helpers/get_tenant.yml +50 -0
- data/spec/vcr_cassettes/Operation/Operation/Add_JDBC_driver_should_add_the_driver.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Add_datasource_should_be_doable.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Add_deployment_should_be_doable.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Redeploy_can_be_run_multiple_times_in_parallel.json +40 -0
- data/spec/vcr_cassettes/Operation/Operation/Redeploy_should_be_performed_and_eventually_respond_with_success.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Redeploy_should_not_be_performed_if_resource_path_is_wrong.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Remove_JDBC_driver_should_be_performed_and_eventually_respond_with_success.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Remove_datasource_should_be_performed_and_eventually_respond_with_success.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Remove_deployment_should_be_performed_and_eventually_respond_with_success.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/Undeploy_should_be_performed_and_eventually_respond_with_success.json +26 -0
- data/spec/vcr_cassettes/Operation/Operation/should_not_be_possible_to_perform_on_closed_client.json +12 -0
- data/spec/vcr_cassettes/Operation/Websocket_connection/should_be_established.json +9 -0
- data/spec/vcr_cassettes/Tokens/Should_be_able_to_create_a_new_token_for_an_actual_user.yml +57 -0
- data/spec/vcr_cassettes/Tokens/Should_be_able_to_list_the_available_tokens.yml +49 -0
- data/spec/vcr_cassettes/Tokens/Should_get_a_401_when_attempting_to_create_a_token_with_a_wrong_password.yml +56 -0
- data/spec/vcr_cassettes/Tokens/Should_get_a_401_when_attempting_to_create_a_token_without_a_password.yml +55 -0
- metadata +175 -11
- data/lib/metrics/version.rb +0 -7
data/lib/hawkular.rb
CHANGED
@@ -21,7 +21,7 @@ module Hawkular
|
|
21
21
|
@credentials = {
|
22
22
|
username: nil,
|
23
23
|
password: nil,
|
24
|
-
token:
|
24
|
+
token: nil
|
25
25
|
}.merge(credentials)
|
26
26
|
@options = {
|
27
27
|
tenant: nil,
|
@@ -50,7 +50,13 @@ module Hawkular
|
|
50
50
|
# @param [String] url_part Part of an url to be escaped
|
51
51
|
# @return [String] escaped url_part as new string
|
52
52
|
def hawk_escape(url_part)
|
53
|
-
|
53
|
+
return url_part.to_s if url_part.is_a?(Numeric)
|
54
|
+
|
55
|
+
if url_part.is_a? Symbol
|
56
|
+
sub_url = url_part.to_s
|
57
|
+
else
|
58
|
+
sub_url = url_part.dup
|
59
|
+
end
|
54
60
|
sub_url.gsub!('%', '%25')
|
55
61
|
sub_url.gsub!(' ', '%20')
|
56
62
|
sub_url.gsub!('[', '%5b')
|
@@ -91,28 +97,17 @@ module Hawkular
|
|
91
97
|
# @!visibility private
|
92
98
|
def rest_client(suburl)
|
93
99
|
options[:timeout] = ENV['HAWKULARCLIENT_REST_TIMEOUT'] if ENV['HAWKULARCLIENT_REST_TIMEOUT']
|
94
|
-
options[:ssl_ca_file]
|
95
|
-
options[:verify_ssl]
|
100
|
+
options[:ssl_ca_file] = @options[:ssl_ca_file]
|
101
|
+
options[:verify_ssl] = @options[:verify_ssl]
|
96
102
|
options[:ssl_client_cert] = @options[:ssl_client_cert]
|
97
|
-
options[:ssl_client_key]
|
98
|
-
options[:user]
|
99
|
-
options[:password]
|
103
|
+
options[:ssl_client_key] = @options[:ssl_client_key]
|
104
|
+
options[:user] = @credentials[:username]
|
105
|
+
options[:password] = @credentials[:password]
|
100
106
|
# strip @endpoint in case suburl is absolute
|
101
107
|
suburl = suburl[@entrypoint.length, suburl.length] if suburl.match(/^http/)
|
102
108
|
RestClient::Resource.new(@entrypoint, options)[suburl]
|
103
109
|
end
|
104
110
|
|
105
|
-
# @!visibility private
|
106
|
-
def base_url
|
107
|
-
url = URI.parse(@entrypoint)
|
108
|
-
"#{url.scheme}://#{url.host}:#{url.port}"
|
109
|
-
end
|
110
|
-
|
111
|
-
# @!visibility private
|
112
|
-
def self.parse_response(response)
|
113
|
-
JSON.parse(response)
|
114
|
-
end
|
115
|
-
|
116
111
|
# @!visibility private
|
117
112
|
def http_headers(headers = {})
|
118
113
|
{}.merge(tenant_header)
|
@@ -140,50 +135,34 @@ module Hawkular
|
|
140
135
|
encoded.rstrip!
|
141
136
|
end
|
142
137
|
|
143
|
-
# Generate a query string from the passed hash
|
144
|
-
# This string starts with a `?` if the hash is
|
145
|
-
# not empty.
|
138
|
+
# Generate a query string from the passed hash, starting with '?'
|
146
139
|
# Values may be an array, in which case the array values are joined together by `,`.
|
147
|
-
# @param
|
148
|
-
# @return [String] complete query string to append to a base url
|
149
|
-
def generate_query_params(
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
param_hash.each do |k, v|
|
158
|
-
next if not_suitable?(v)
|
159
|
-
|
160
|
-
if v.instance_of? Array
|
161
|
-
part = "#{k}=#{v.join(',')}"
|
162
|
-
else
|
163
|
-
part = "#{k}=#{v}"
|
164
|
-
end
|
165
|
-
|
166
|
-
ret += hawk_escape part
|
167
|
-
|
168
|
-
i += 1
|
169
|
-
ret += '&' if i < num
|
140
|
+
# @param params [Hash] key-values pairs
|
141
|
+
# @return [String] complete query string to append to a base url, '' if no valid params
|
142
|
+
def generate_query_params(params = {})
|
143
|
+
params = params.select { |_k, v| !(v.nil? || ((v.instance_of? Array) && v.empty?)) }
|
144
|
+
return '' if params.empty?
|
145
|
+
|
146
|
+
params.inject('?') do |ret, (k, v)|
|
147
|
+
ret += '&' unless ret == '?'
|
148
|
+
part = (v.instance_of? Array) ? "#{k}=#{v.join(',')}" : "#{k}=#{v}"
|
149
|
+
ret + hawk_escape(part)
|
170
150
|
end
|
171
|
-
ret
|
172
151
|
end
|
173
152
|
|
174
|
-
|
153
|
+
# Specialized exception to be thrown
|
154
|
+
# when the interaction with Hawkular fails
|
155
|
+
class HawkularException < StandardError
|
156
|
+
def initialize(message, status_code = 0)
|
157
|
+
@message = message
|
158
|
+
@status_code = status_code
|
159
|
+
super(message)
|
160
|
+
end
|
175
161
|
|
176
|
-
|
177
|
-
v.nil? || (v.instance_of? Array) && v.size == 0
|
162
|
+
attr_reader :message, :status_code
|
178
163
|
end
|
179
164
|
|
180
|
-
|
181
|
-
num = 0
|
182
|
-
param_hash.each do |_k, v|
|
183
|
-
num += 1 unless not_suitable?(v)
|
184
|
-
end
|
185
|
-
num
|
186
|
-
end
|
165
|
+
private
|
187
166
|
|
188
167
|
def token_header
|
189
168
|
@credentials[:token].nil? ? {} : { 'Authorization' => "Bearer #{@credentials[:token]}" }
|
@@ -202,21 +181,10 @@ module Hawkular
|
|
202
181
|
rescue JSON::ParserError
|
203
182
|
fault_message = f.http_body
|
204
183
|
end
|
205
|
-
fail HawkularException,
|
184
|
+
fail HawkularException.new(fault_message, (f.respond_to?(:http_code) ? f.http_code : 0))
|
206
185
|
else
|
207
186
|
fail f
|
208
187
|
end
|
209
188
|
end
|
210
189
|
end
|
211
|
-
|
212
|
-
# Specialized exception to be thrown
|
213
|
-
# when the interction with Hawkular fails
|
214
|
-
class HawkularException < StandardError
|
215
|
-
def initialize(message)
|
216
|
-
@message = message
|
217
|
-
super
|
218
|
-
end
|
219
|
-
|
220
|
-
attr_reader :message
|
221
|
-
end
|
222
190
|
end
|
data/lib/hawkular_all.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'hawkular'
|
2
|
+
require 'websocket-client-simple'
|
3
|
+
require 'json'
|
2
4
|
|
3
5
|
# Inventory module provides access to the Hawkular Inventory REST API.
|
4
6
|
# @see http://www.hawkular.org/docs/rest/rest-inventory.html
|
@@ -14,10 +16,19 @@ module Hawkular::Inventory
|
|
14
16
|
# @param credentials [Hash{String=>String}] Hash of username, password, token(optional)
|
15
17
|
def initialize(entrypoint = nil, credentials = {})
|
16
18
|
@entrypoint = entrypoint
|
17
|
-
|
18
19
|
super(entrypoint, credentials)
|
19
20
|
end
|
20
21
|
|
22
|
+
# Creates a new Inventory Client
|
23
|
+
# @param hash [Hash{String=>Object}] a hash containing base url of Hawkular-inventory - e.g
|
24
|
+
# entrypoint: http://localhost:8080/hawkular/inventory
|
25
|
+
# and another sub-hash containing the hash with username[String], password[String], token(optional)
|
26
|
+
def self.create(hash)
|
27
|
+
hash[:entrypoint] ||= 'http://localhost:8080/hawkular/inventory'
|
28
|
+
hash[:credentials] ||= {}
|
29
|
+
InventoryClient.new(hash[:entrypoint], hash[:credentials])
|
30
|
+
end
|
31
|
+
|
21
32
|
# Retrieve the tenant id for the passed credentials.
|
22
33
|
# If no credentials are passed, the ones from the constructor are used
|
23
34
|
# @param credentials [Hash{String=>String}] Hash of username, password, token(optional)
|
@@ -32,7 +43,7 @@ module Hawkular::Inventory
|
|
32
43
|
end
|
33
44
|
|
34
45
|
# TODO: revisit and potentially move to Base ?
|
35
|
-
def impersonate(credentials = {})
|
46
|
+
def impersonate!(credentials = {})
|
36
47
|
@tenant = get_tenant(credentials)
|
37
48
|
@options[:tenant] = @tenant
|
38
49
|
end
|
@@ -41,9 +52,7 @@ module Hawkular::Inventory
|
|
41
52
|
# @return [Array<String>] List of feed ids
|
42
53
|
def list_feeds(_environment = 'test')
|
43
54
|
ret = http_get('feeds')
|
44
|
-
|
45
|
-
ret.each { |f| val.push(f['id']) }
|
46
|
-
val
|
55
|
+
ret.map { |f| f['id'] }
|
47
56
|
end
|
48
57
|
|
49
58
|
# List resource types. If no need is given all types are listed
|
@@ -54,17 +63,32 @@ module Hawkular::Inventory
|
|
54
63
|
ret = http_get('/resourceTypes')
|
55
64
|
else
|
56
65
|
the_feed = hawk_escape feed
|
57
|
-
ret = http_get(
|
66
|
+
ret = http_get("/feeds/#{the_feed}/resourceTypes")
|
67
|
+
end
|
68
|
+
ret.map { |rt| ResourceType.new(rt) }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return all resources for a feed
|
72
|
+
# @param [String] feed Id of the feed that hosts the resources
|
73
|
+
# @param [Boolean] fetch_properties Should the config data be fetched too
|
74
|
+
# @return [Array<Resource>] List of resources, which can be empty.
|
75
|
+
def list_resources_for_feed(feed, fetch_properties = false)
|
76
|
+
fail 'Feed must be given' unless feed
|
77
|
+
the_feed = hawk_escape feed
|
78
|
+
ret = http_get("/feeds/#{the_feed}/resources")
|
79
|
+
ret.map do |r|
|
80
|
+
if fetch_properties
|
81
|
+
p = get_config_data_for_resource(r['id'], feed)
|
82
|
+
r['properties'] = p['value']
|
83
|
+
end
|
84
|
+
Resource.new(r)
|
58
85
|
end
|
59
|
-
val = []
|
60
|
-
ret.each { |rt| val.push(ResourceType.new(rt)) }
|
61
|
-
val
|
62
86
|
end
|
63
87
|
|
64
88
|
# List the resources for the passed feed and resource type. The representation for
|
65
89
|
# resources under a feed are sparse and additional data must be retrived separately.
|
66
90
|
# It is possible though to also obtain runtime properties by setting #fetch_properties to true.
|
67
|
-
# @param [String] feed The id of the feed the type lives under. Can be nil for
|
91
|
+
# @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
|
68
92
|
# @param [String] type Name of the type to look for. Can be obtained from {ResourceType}.id.
|
69
93
|
# Must not be nil
|
70
94
|
# @param [Boolean] fetch_properties Shall additional runtime properties be fetched?
|
@@ -73,21 +97,19 @@ module Hawkular::Inventory
|
|
73
97
|
fail 'Type must not be nil' unless type
|
74
98
|
the_type = hawk_escape type
|
75
99
|
if feed.nil?
|
76
|
-
ret = http_get(
|
100
|
+
ret = http_get("resourceTypes/#{the_type}/resources")
|
77
101
|
else
|
78
102
|
|
79
103
|
the_feed = hawk_escape feed
|
80
|
-
ret = http_get(
|
104
|
+
ret = http_get("/feeds/#{the_feed}/resourceTypes/#{the_type}/resources")
|
81
105
|
end
|
82
|
-
|
83
|
-
ret.each do |r|
|
106
|
+
ret.map do |r|
|
84
107
|
if fetch_properties && !feed.nil?
|
85
108
|
p = get_config_data_for_resource(r['id'], feed)
|
86
109
|
r['properties'] = p['value']
|
87
110
|
end
|
88
|
-
|
111
|
+
Resource.new(r)
|
89
112
|
end
|
90
|
-
val
|
91
113
|
end
|
92
114
|
|
93
115
|
# Retrieve runtime properties for the passed resource
|
@@ -97,7 +119,8 @@ module Hawkular::Inventory
|
|
97
119
|
def get_config_data_for_resource(resource_id, feed)
|
98
120
|
the_id = hawk_escape resource_id
|
99
121
|
the_feed = hawk_escape feed
|
100
|
-
|
122
|
+
query = generate_query_params dataType: 'configuration'
|
123
|
+
http_get("feeds/#{the_feed}/resources/#{the_id}/data#{query}")
|
101
124
|
rescue
|
102
125
|
{}
|
103
126
|
end
|
@@ -105,47 +128,48 @@ module Hawkular::Inventory
|
|
105
128
|
# Obtain the child resources of the passed resource. In case of a WildFly server,
|
106
129
|
# those would be Datasources, Deployments and so on.
|
107
130
|
# @param [Resource] parent_resource Resource to obtain children from
|
131
|
+
# @param [Boolean] recursive Whether to fetch also all the children of children of ...
|
108
132
|
# @return [Array<Resource>] List of resources that are children of the given parent resource.
|
109
133
|
# Can be empty
|
110
|
-
def list_child_resources(parent_resource)
|
134
|
+
def list_child_resources(parent_resource, recursive = false)
|
111
135
|
the_feed = hawk_escape parent_resource.feed
|
112
136
|
the_id = hawk_escape parent_resource.id
|
113
137
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
ret.each { |r| val.push(Resource.new(r)) }
|
118
|
-
val
|
138
|
+
which_children = (recursive ? '/recursiveChildren' : '/children')
|
139
|
+
ret = http_get("/feeds/#{the_feed}/resources/#{the_id}#{which_children}")
|
140
|
+
ret.map { |r| Resource.new(r) }
|
119
141
|
end
|
120
142
|
|
121
143
|
# Obtain a list of relationships starting at the passed resource
|
122
144
|
# @param [Resource] resource One end of the relationship
|
145
|
+
# @param [String] named Name of the relationship
|
123
146
|
# @return [Array<Relationship>] List of relationships
|
124
|
-
def list_relationships(resource)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
ret = http_get('/feeds/' + the_feed + '/resources/' + the_id + '/relationships')
|
129
|
-
val = []
|
130
|
-
ret.each { |r| val.push(Relationship.new(r)) }
|
131
|
-
val
|
132
|
-
rescue
|
133
|
-
[]
|
147
|
+
def list_relationships(resource, named = nil)
|
148
|
+
query = named.nil? ? '' : (generate_query_params named: named)
|
149
|
+
ret = http_get("/path#{resource.path}/relationships#{query}")
|
150
|
+
ret.map { |r| Relationship.new(r) }
|
134
151
|
end
|
135
152
|
|
136
153
|
# Obtain a list of relationships for the passed feed
|
137
154
|
# @param [String] feed_id Id of the feed
|
155
|
+
# @param [String] named Name of the relationship
|
138
156
|
# @return [Array<Relationship>] List of relationships
|
139
|
-
def list_relationships_for_feed(feed_id)
|
157
|
+
def list_relationships_for_feed(feed_id, named = nil)
|
140
158
|
the_feed = hawk_escape feed_id
|
141
|
-
|
142
|
-
|
143
|
-
ret.
|
144
|
-
val
|
159
|
+
query = named.nil? ? '' : (generate_query_params named: named)
|
160
|
+
ret = http_get("/feeds/#{the_feed}/relationships#{query}")
|
161
|
+
ret.map { |r| Relationship.new(r) }
|
145
162
|
rescue
|
146
163
|
[]
|
147
164
|
end
|
148
165
|
|
166
|
+
# Retrieve a single entity from inventory by its canonical path
|
167
|
+
# @param [CanonicalPath] path canonical path of the entity
|
168
|
+
# @return inventory entity
|
169
|
+
def get_entity(path)
|
170
|
+
http_get("path#{path}")
|
171
|
+
end
|
172
|
+
|
149
173
|
# [15:01:51] <jkremser> pilhuhn, this works for me curl -XPOST
|
150
174
|
# -H "Content-Type: application/json"
|
151
175
|
# -u jdoe:password -d
|
@@ -166,9 +190,59 @@ module Hawkular::Inventory
|
|
166
190
|
# rel.to_h)
|
167
191
|
# end
|
168
192
|
|
169
|
-
#
|
170
|
-
#
|
171
|
-
#
|
193
|
+
# List the metrics for the passed feed and metric type. If feed is not passed,
|
194
|
+
# all the metrics across all the feeds of a given type will be retrieved
|
195
|
+
# This method may perform multiple REST calls.
|
196
|
+
# @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
|
197
|
+
# @param [String] type Name of the metric type to look for. Can be obtained from {MetricType}.id.
|
198
|
+
# Must not be nil
|
199
|
+
# @return [Array<Metric>] List of metrics. Can be empty
|
200
|
+
def list_metrics_for_metric_type(feed, type)
|
201
|
+
fail 'Type must not be nil' unless type
|
202
|
+
the_type = hawk_escape type
|
203
|
+
if feed.nil?
|
204
|
+
type_hash = http_get("metricTypes/#{the_type}")
|
205
|
+
else
|
206
|
+
the_feed = hawk_escape feed
|
207
|
+
type_hash = http_get("/feeds/#{the_feed}/metricTypes/#{the_type}")
|
208
|
+
end
|
209
|
+
|
210
|
+
rels = list_relationships(ResourceType.new(type_hash), 'defines')
|
211
|
+
rels.map do |rel|
|
212
|
+
path = CanonicalPath.parse(rel.target_id.to_s)
|
213
|
+
metric_hash = get_entity path
|
214
|
+
Metric.new(metric_hash)
|
215
|
+
end
|
216
|
+
rescue
|
217
|
+
[]
|
218
|
+
end
|
219
|
+
|
220
|
+
# List the metrics for the passed feed and all the resources of given resource type.
|
221
|
+
# If feed is not passed, all the metrics across all the feeds of a resource type will be retrieved
|
222
|
+
# This method may perform multiple REST calls.
|
223
|
+
# @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
|
224
|
+
# @param [String] type Name of the resource type to look for. Can be obtained from {ResourceType}.id.
|
225
|
+
# Must not be nil
|
226
|
+
# @return [Array<Metric>] List of metrics. Can be empty
|
227
|
+
def list_metrics_for_resource_type(feed, type)
|
228
|
+
fail 'Type must not be nil' unless type
|
229
|
+
the_type = hawk_escape type
|
230
|
+
if feed.nil?
|
231
|
+
ret = http_get("resourceTypes/#{the_type}/resources")
|
232
|
+
else
|
233
|
+
the_feed = hawk_escape feed
|
234
|
+
ret = http_get("feeds/#{the_feed}/resourceTypes/#{the_type}/resources")
|
235
|
+
end
|
236
|
+
ret.flat_map do |r|
|
237
|
+
path = CanonicalPath.parse(r['path'])
|
238
|
+
if !path.feed_id.nil?
|
239
|
+
nested_ret = http_get("feeds/#{path.feed_id}/resources/#{path.resource_ids.join('/')}/metrics")
|
240
|
+
else
|
241
|
+
nested_ret = http_get("#{path.environment_id}/resources/#{path.resource_ids.join('/')}/metrics")
|
242
|
+
end
|
243
|
+
nested_ret.map { |m| Metric.new(m) }
|
244
|
+
end
|
245
|
+
end
|
172
246
|
|
173
247
|
# List metric (definitions) for the passed resource. It is possible to filter down the
|
174
248
|
# result by a filter to only return a subset. The
|
@@ -176,7 +250,7 @@ module Hawkular::Inventory
|
|
176
250
|
# @param [Hash{Symbol=>String}] filter for 'type' and 'match'
|
177
251
|
# Metric type can be one of 'GAUGE', 'COUNTER', 'AVAILABILITY'. If a key is missing
|
178
252
|
# it will not be used for filtering
|
179
|
-
# @return [
|
253
|
+
# @return [Array<Metric>] List of metrics that can be empty.
|
180
254
|
# @example
|
181
255
|
# # Filter by type and match on metrics id
|
182
256
|
# client.list_metrics_for_resource(wild_fly, type: 'GAUGE', match: 'Metrics~Heap')
|
@@ -188,20 +262,229 @@ module Hawkular::Inventory
|
|
188
262
|
the_feed = hawk_escape resource.feed
|
189
263
|
the_id = hawk_escape resource.id
|
190
264
|
|
191
|
-
ret = http_get(
|
192
|
-
|
193
|
-
the_id + '/metrics')
|
194
|
-
val = []
|
195
|
-
ret.each do |m|
|
265
|
+
ret = http_get("/feeds/#{the_feed}/resources/#{the_id}/metrics")
|
266
|
+
with_nils = ret.map do |m|
|
196
267
|
metric_new = Metric.new(m)
|
197
268
|
found = should_include?(metric_new, filter)
|
198
|
-
|
269
|
+
metric_new if found
|
270
|
+
end
|
271
|
+
with_nils.compact
|
272
|
+
end
|
273
|
+
|
274
|
+
# Create a new feed
|
275
|
+
# @param [String] feed_id Id of a feed - required
|
276
|
+
# @param [String] feed_name A display name for the feed
|
277
|
+
# @return [Object]
|
278
|
+
def create_feed(feed_id, feed_name = nil)
|
279
|
+
feed = create_blueprint
|
280
|
+
feed[:id] = feed_id
|
281
|
+
feed[:name] = feed_name
|
282
|
+
|
283
|
+
begin
|
284
|
+
return http_post('/feeds/', feed)
|
285
|
+
rescue HawkularException => error
|
286
|
+
# 409 We already exist -> that is ok
|
287
|
+
if error.status_code == 409
|
288
|
+
the_feed = hawk_escape feed_id
|
289
|
+
http_get("/feeds/#{the_feed}")
|
290
|
+
else
|
291
|
+
raise
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# Delete the feed with the passed feed id.
|
297
|
+
# @param feed Id of the feed to be deleted.
|
298
|
+
def delete_feed(feed)
|
299
|
+
the_feed = hawk_escape feed
|
300
|
+
http_delete("/feeds/#{the_feed}")
|
301
|
+
end
|
302
|
+
|
303
|
+
# Create a new resource type
|
304
|
+
# @param [String] feed_id Id of the feed to add the type to
|
305
|
+
# @param [String] type_id Id of the new type
|
306
|
+
# @param [String] type_name Name of the type
|
307
|
+
# @return [ResourceType] ResourceType object just created
|
308
|
+
def create_resource_type(feed_id, type_id, type_name)
|
309
|
+
the_feed = hawk_escape feed_id
|
310
|
+
|
311
|
+
type = create_blueprint
|
312
|
+
type[:id] = type_id
|
313
|
+
type[:name] = type_name
|
314
|
+
|
315
|
+
begin
|
316
|
+
http_post("/feeds/#{the_feed}/resourceTypes", type)
|
317
|
+
rescue HawkularException => error
|
318
|
+
# 409 We already exist -> that is ok
|
319
|
+
raise unless error.status_code == 409
|
320
|
+
ensure
|
321
|
+
the_type = hawk_escape type_id
|
322
|
+
res = http_get("/feeds/#{the_feed}/resourceTypes/#{the_type}")
|
199
323
|
end
|
200
|
-
|
324
|
+
ResourceType.new(res)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Create a resource of a given type under a given feed. To retrieve that resource
|
328
|
+
# you need to call {#get_resource}
|
329
|
+
# @param [String] feed_id Id of the feed to add the resource to
|
330
|
+
# @param [String] type_path Path of the resource type of this resource
|
331
|
+
# @param [String] resource_id Id of the resource
|
332
|
+
# @param [String] resource_name Name of the resource
|
333
|
+
# @param [Hash<String,Object>] properties Additional properties. Those are not the config-properties
|
334
|
+
# TODO allow to create this as child of another resource
|
335
|
+
def create_resource(feed_id, type_path, resource_id, resource_name = nil, properties = {})
|
336
|
+
the_feed = hawk_escape feed_id
|
337
|
+
|
338
|
+
res = create_blueprint
|
339
|
+
res[:properties] = properties
|
340
|
+
res[:id] = resource_id
|
341
|
+
res[:name] = resource_name
|
342
|
+
res[:resourceTypePath] = type_path
|
343
|
+
|
344
|
+
begin
|
345
|
+
http_post("/feeds/#{the_feed}/resources", res)
|
346
|
+
rescue HawkularException => error
|
347
|
+
# 409 We already exist -> that is ok
|
348
|
+
raise unless error.status_code == 409
|
349
|
+
end
|
350
|
+
|
351
|
+
get_resource feed_id, resource_id, false
|
352
|
+
end
|
353
|
+
|
354
|
+
# Return the resource object for the passed id
|
355
|
+
# @param [String] feed_id Id of the feed this resource belongs to
|
356
|
+
# @param [String] res_id Id of the resource to fetch
|
357
|
+
# @param [Boolean] fetch_resource_config Should the resource config data be fetched?
|
358
|
+
def get_resource(feed_id, res_id, fetch_resource_config = true)
|
359
|
+
the_feed = hawk_escape feed_id
|
360
|
+
the_resource = hawk_escape res_id
|
361
|
+
|
362
|
+
res = http_get("/feeds/#{the_feed}/resources/#{the_resource}")
|
363
|
+
if fetch_resource_config
|
364
|
+
p = get_config_data_for_resource(res_id, feed_id)
|
365
|
+
res['properties'].merge p['value'] unless p['value'].nil?
|
366
|
+
end
|
367
|
+
Resource.new(res)
|
368
|
+
end
|
369
|
+
|
370
|
+
# Create a new metric type for a feed
|
371
|
+
# @param [String] feed_id Id of the feed
|
372
|
+
# @param [String] metric_type_id Id of the metric type to create
|
373
|
+
# @param [String] type Type of the Metric. Allowed are GAUGE,COUNTER, AVAILABILITY
|
374
|
+
# @param [String] unit Unit of the metric
|
375
|
+
# @param [Numeric] collection_interval
|
376
|
+
# @return [MetricType] Type just created or the one from the server if it already existed.
|
377
|
+
def create_metric_type(feed_id, metric_type_id, type = 'GAUGE', unit = 'NONE', collection_interval = 60)
|
378
|
+
the_feed = hawk_escape feed_id
|
379
|
+
|
380
|
+
metric_kind = type.nil? ? 'GAUGE' : type.upcase
|
381
|
+
fail "Unknown type #{metric_kind}" unless %w(GAUGE COUNTER AVAILABILITY').include?(metric_kind)
|
382
|
+
|
383
|
+
mt = build_metric_type_hash(collection_interval, metric_kind, metric_type_id, unit)
|
384
|
+
|
385
|
+
begin
|
386
|
+
http_post("/feeds/#{the_feed}/metricTypes", mt)
|
387
|
+
rescue HawkularException => error
|
388
|
+
# 409 We already exist -> that is ok
|
389
|
+
raise unless error.status_code == 409
|
390
|
+
end
|
391
|
+
|
392
|
+
new_mt = http_get("/feeds/#{the_feed}/metricTypes/#{metric_type_id}")
|
393
|
+
|
394
|
+
MetricType.new(new_mt)
|
395
|
+
end
|
396
|
+
|
397
|
+
# Create a Metric and associate it with a resource.
|
398
|
+
# @param [String] feed_id Id of the feed
|
399
|
+
# @param [String] metric_id Id of the metric
|
400
|
+
# @param [String] type_path Full path of the MetricType
|
401
|
+
# @param [String] resource_id Id of the resource to associate the metric with
|
402
|
+
# @param [String] metric_name a (display) name for the metric. If nil, #metric_id is used.
|
403
|
+
# @return [Metric] The metric created or if it already existed the version from the server
|
404
|
+
def create_metric_for_resource(feed_id, metric_id, type_path, resource_id, metric_name = nil)
|
405
|
+
the_feed = hawk_escape feed_id
|
406
|
+
the_resource = hawk_escape resource_id
|
407
|
+
|
408
|
+
m = {}
|
409
|
+
m['id'] = metric_id
|
410
|
+
m['name'] = (metric_name.nil?) ? metric_id : metric_name
|
411
|
+
m['metricTypePath'] = type_path
|
412
|
+
|
413
|
+
begin
|
414
|
+
http_post("/feeds/#{the_feed}/metrics", m)
|
415
|
+
rescue HawkularException => error
|
416
|
+
# 409 We already exist -> that is ok
|
417
|
+
raise unless error.status_code == 409
|
418
|
+
end
|
419
|
+
|
420
|
+
ret = http_get("/feeds/#{the_feed}/metrics/#{metric_id}")
|
421
|
+
the_metric = Metric.new(ret)
|
422
|
+
|
423
|
+
begin
|
424
|
+
http_post("/feeds/#{the_feed}/resources/#{the_resource}/metrics", [the_metric.path])
|
425
|
+
rescue HawkularException => error
|
426
|
+
# 409 We already exist -> that is ok
|
427
|
+
raise unless error.status_code == 409
|
428
|
+
end
|
429
|
+
the_metric
|
430
|
+
end
|
431
|
+
|
432
|
+
# Listen on inventory changes
|
433
|
+
# @param [String] type Type of entity for which we want the events.
|
434
|
+
# Allowed values: resource, metric, resourcetype, metrictype, feed, environment, operationtype, metadatapack
|
435
|
+
# @param [String] action What types of events are we interested in.
|
436
|
+
# Allowed values: created, updated, deleted, copied, registered
|
437
|
+
def events(type = 'resource', action = 'created')
|
438
|
+
tenant_id = get_tenant
|
439
|
+
url = "#{entrypoint.gsub(/https?/, 'ws')}/ws/events?tenantId=#{tenant_id}&type=#{type}&action=#{action}"
|
440
|
+
@ws = WebSocket::Client::Simple.connect url do |client|
|
441
|
+
client.on :message do |msg|
|
442
|
+
parsed_message = JSON.parse(msg.data)
|
443
|
+
entity = case type
|
444
|
+
when 'resource'
|
445
|
+
Resource.new(parsed_message)
|
446
|
+
when 'resourcetype'
|
447
|
+
ResourceType.new(parsed_message)
|
448
|
+
when 'metric'
|
449
|
+
Metric.new(parsed_message)
|
450
|
+
when 'metrictype'
|
451
|
+
MetricType.new(parsed_message)
|
452
|
+
else
|
453
|
+
BaseEntity.new(parsed_message)
|
454
|
+
end
|
455
|
+
yield entity
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
# Stop listening on inventory events.
|
461
|
+
# this method closes the web socket connection
|
462
|
+
def no_more_events!
|
463
|
+
@ws.close
|
201
464
|
end
|
202
465
|
|
203
466
|
private
|
204
467
|
|
468
|
+
# Creates a hash with the fields required by the Blueprint api in Hawkular-Inventory
|
469
|
+
def create_blueprint
|
470
|
+
res = {}
|
471
|
+
res[:properties] = {}
|
472
|
+
res[:id] = nil
|
473
|
+
res[:name] = nil
|
474
|
+
res[:outgoing] = {}
|
475
|
+
res[:incoming] = {}
|
476
|
+
res
|
477
|
+
end
|
478
|
+
|
479
|
+
def build_metric_type_hash(collection_interval, metric_kind, metric_type_id, unit)
|
480
|
+
mt = {}
|
481
|
+
mt['id'] = metric_type_id
|
482
|
+
mt['type'] = metric_kind
|
483
|
+
mt['unit'] = unit.nil? ? 'NONE' : unit.upcase
|
484
|
+
mt['collectionInterval'] = collection_interval.nil? ? 60 : collection_interval
|
485
|
+
mt
|
486
|
+
end
|
487
|
+
|
205
488
|
def should_include?(metric_new, filter)
|
206
489
|
found = true
|
207
490
|
if filter.empty?
|
@@ -214,32 +497,31 @@ module Hawkular::Inventory
|
|
214
497
|
end
|
215
498
|
end
|
216
499
|
|
217
|
-
# A
|
218
|
-
|
219
|
-
|
220
|
-
# (more or less) the same.
|
221
|
-
class ResourceType
|
222
|
-
# @return [String] Full path of the type
|
500
|
+
# A Basic inventory entity with id, name, path and optional properties
|
501
|
+
class BaseEntity
|
502
|
+
# @return [String] Full path of the entity
|
223
503
|
attr_reader :path
|
224
|
-
# @return [String] Name of the
|
504
|
+
# @return [String] Name of the entity
|
225
505
|
attr_reader :name
|
226
|
-
# @return [String] Name of the
|
506
|
+
# @return [String] Name of the entity
|
227
507
|
attr_reader :id
|
228
|
-
# @return [String] Feed this
|
508
|
+
# @return [String] Feed this entity belongs to (or nil in case of a feedless entity)
|
229
509
|
attr_reader :feed
|
230
|
-
# @return [String]
|
510
|
+
# @return [String] Name of the environment for this entity
|
231
511
|
attr_reader :env
|
232
|
-
# @return [String] Properties of this
|
512
|
+
# @return [String] Properties of this entity
|
233
513
|
attr_reader :properties
|
234
514
|
|
235
|
-
def initialize(
|
236
|
-
@id =
|
237
|
-
@path =
|
238
|
-
@name =
|
239
|
-
@properties =
|
240
|
-
@_hash =
|
515
|
+
def initialize(hash)
|
516
|
+
@id = hash['id']
|
517
|
+
@path = hash['path']
|
518
|
+
@name = hash['name'] || @id
|
519
|
+
@properties = hash['properties'] || {}
|
520
|
+
@_hash = hash.dup
|
241
521
|
|
242
|
-
|
522
|
+
return if @path.nil?
|
523
|
+
|
524
|
+
tmp = @path.split('/')
|
243
525
|
tmp.each do |pair|
|
244
526
|
(key, val) = pair.split(';')
|
245
527
|
case key
|
@@ -258,89 +540,59 @@ module Hawkular::Inventory
|
|
258
540
|
end
|
259
541
|
end
|
260
542
|
|
543
|
+
# A ResourceType is like a class definition for {Resource}s
|
544
|
+
# ResourceTypes are currently unique per feed, but one can assume
|
545
|
+
# that a two types with the same name of two different feeds are
|
546
|
+
# (more or less) the same.
|
547
|
+
class ResourceType < BaseEntity
|
548
|
+
def initialize(rt_hash)
|
549
|
+
super(rt_hash)
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
261
553
|
# A Resource is an instantiation of a {ResourceType}
|
262
|
-
class Resource
|
263
|
-
# @return [String] Full path of the resource including feed id
|
264
|
-
attr_reader :path
|
265
|
-
# @return [String] Name of the resource
|
266
|
-
attr_reader :name
|
267
|
-
# @return [String] Name of the resource
|
268
|
-
attr_reader :id
|
269
|
-
# @return [String] Name of the feed for this resource
|
270
|
-
attr_reader :feed
|
271
|
-
# @return [String] Name of the environment for this resource -- currently unused
|
272
|
-
attr_reader :env
|
554
|
+
class Resource < BaseEntity
|
273
555
|
# @return [String] Full path of the {ResourceType}
|
274
556
|
attr_reader :type_path
|
275
|
-
# @return [Hash<String,Object>] Hash with additional, resource specific properties
|
276
|
-
attr_reader :properties
|
277
557
|
|
278
558
|
def initialize(res_hash)
|
279
|
-
|
280
|
-
@
|
281
|
-
@properties = res_hash['properties'] || {}
|
559
|
+
super(res_hash)
|
560
|
+
@type = res_hash['type']
|
282
561
|
@type_path = res_hash['type']['path']
|
283
|
-
@_hash = res_hash
|
284
|
-
|
285
|
-
tmp = @path.split('/')
|
286
|
-
tmp.each do |pair|
|
287
|
-
(key, val) = pair.split(';')
|
288
|
-
case key
|
289
|
-
when 'f'
|
290
|
-
@feed = val
|
291
|
-
when 'e'
|
292
|
-
@env = val
|
293
|
-
when 'n'
|
294
|
-
@name = val.nil? ? id : val
|
295
|
-
end
|
296
|
-
end
|
297
|
-
self
|
298
562
|
end
|
563
|
+
end
|
299
564
|
|
300
|
-
|
301
|
-
|
565
|
+
class MetricType < BaseEntity
|
566
|
+
# @return [String] GAUGE, COUNTER, etc.
|
567
|
+
attr_reader :type
|
568
|
+
# @return [String] metric unit such as NONE, BYTES, etc.
|
569
|
+
attr_reader :unit
|
570
|
+
# @return [Long] collection interval in seconds
|
571
|
+
attr_reader :collection_interval
|
572
|
+
|
573
|
+
def initialize(type_hash)
|
574
|
+
super(type_hash)
|
575
|
+
@type = type_hash['type']
|
576
|
+
@unit = type_hash['unit']
|
577
|
+
@collection_interval = type_hash['collectionInterval']
|
302
578
|
end
|
303
579
|
end
|
304
580
|
|
305
581
|
# Definition of a Metric inside the inventory.
|
306
|
-
class Metric
|
307
|
-
# @return [String]
|
308
|
-
attr_reader :path
|
309
|
-
# @return [String] Name of the metric
|
310
|
-
attr_reader :name
|
311
|
-
attr_reader :id
|
312
|
-
attr_reader :feed
|
313
|
-
attr_reader :env
|
582
|
+
class Metric < BaseEntity
|
583
|
+
# @return [String] GAUGE, COUNTER, etc.
|
314
584
|
attr_reader :type
|
585
|
+
# @return [String] metric unit such as NONE, BYTES, etc.
|
315
586
|
attr_reader :unit
|
316
587
|
# @return [Long] collection interval in seconds
|
317
588
|
attr_reader :collection_interval
|
318
589
|
|
319
590
|
def initialize(metric_hash)
|
320
|
-
|
321
|
-
@path = metric_hash['path']
|
322
|
-
@name = metric_hash['name'] || @id
|
323
|
-
@_hash = metric_hash.dup
|
324
|
-
|
325
|
-
tmp = path.split('/')
|
326
|
-
tmp.each do |pair|
|
327
|
-
(key, val) = pair.split(';')
|
328
|
-
case key
|
329
|
-
when 'f'
|
330
|
-
@feed = val
|
331
|
-
when 'e'
|
332
|
-
@env = val
|
333
|
-
when 'n'
|
334
|
-
@name = val.nil? ? id : val
|
335
|
-
end
|
336
|
-
end
|
591
|
+
super(metric_hash)
|
337
592
|
@type = metric_hash['type']['type']
|
593
|
+
@type_path = metric_hash['type']['path']
|
338
594
|
@unit = metric_hash['type']['unit']
|
339
|
-
@collection_interval = metric_hash['collectionInterval']
|
340
|
-
end
|
341
|
-
|
342
|
-
def to_h
|
343
|
-
@_hash.dup
|
595
|
+
@collection_interval = metric_hash['type']['collectionInterval']
|
344
596
|
end
|
345
597
|
end
|
346
598
|
|
@@ -375,4 +627,81 @@ module Hawkular::Inventory
|
|
375
627
|
hash
|
376
628
|
end
|
377
629
|
end
|
630
|
+
|
631
|
+
class CanonicalPath
|
632
|
+
attr_reader :tenant_id
|
633
|
+
attr_reader :feed_id
|
634
|
+
attr_reader :environment_id
|
635
|
+
attr_reader :resource_ids
|
636
|
+
attr_reader :metric_id
|
637
|
+
attr_reader :resource_type_id
|
638
|
+
attr_reader :metric_type_id
|
639
|
+
|
640
|
+
def initialize(hash)
|
641
|
+
fail 'At least tenant_id must be specified' if hash[:tenant_id].to_s.strip.length == 0
|
642
|
+
@tenant_id = hash[:tenant_id]
|
643
|
+
@feed_id = hash[:feed_id]
|
644
|
+
@environment_id = hash[:environment_id]
|
645
|
+
@resource_type_id = hash[:resource_type_id]
|
646
|
+
@metric_type_id = hash[:metric_type_id]
|
647
|
+
@resource_ids = hash[:resource_ids]
|
648
|
+
@metric_id = hash[:metric_id]
|
649
|
+
end
|
650
|
+
|
651
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
652
|
+
def self.parse(path)
|
653
|
+
fail 'CanonicalPath must not be nil or emtpy' if path.to_s.strip.length == 0
|
654
|
+
tmp = path.split('/')
|
655
|
+
hash = {}
|
656
|
+
tmp.each do |pair|
|
657
|
+
(key, val) = pair.split(';')
|
658
|
+
case key
|
659
|
+
when 't'
|
660
|
+
hash[:tenant_id] = val
|
661
|
+
when 'f'
|
662
|
+
hash[:feed_id] = val
|
663
|
+
when 'e'
|
664
|
+
hash[:environment_id] = val
|
665
|
+
when 'm'
|
666
|
+
hash[:metric_id] = val
|
667
|
+
when 'r'
|
668
|
+
hash[:resource_ids] = [] if hash[:resource_ids].nil?
|
669
|
+
hash[:resource_ids].push(val)
|
670
|
+
when 'mt'
|
671
|
+
hash[:metric_type_id] = val
|
672
|
+
when 'rt'
|
673
|
+
hash[:resource_type_id] = val
|
674
|
+
end
|
675
|
+
end
|
676
|
+
CanonicalPath.new(hash)
|
677
|
+
end
|
678
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
679
|
+
|
680
|
+
def ==(other)
|
681
|
+
self.eql?(other) || other.class == self.class && other.state == state
|
682
|
+
end
|
683
|
+
|
684
|
+
def to_s
|
685
|
+
ret = "/t;#{@tenant_id}"
|
686
|
+
ret += "/f;#{@feed_id}" unless @feed_id.nil?
|
687
|
+
ret += "/e;#{@environment_id}" unless @environment_id.nil?
|
688
|
+
ret += "/rt;#{@resource_type_id}" unless @resource_type_id.nil?
|
689
|
+
ret += "/mt;#{@metric_type_id}" unless @metric_type_id.nil?
|
690
|
+
ret += "/m;#{@metric_id}" unless @metric_id.nil?
|
691
|
+
ret += resources_chunk.to_s
|
692
|
+
ret
|
693
|
+
end
|
694
|
+
|
695
|
+
protected
|
696
|
+
|
697
|
+
def state
|
698
|
+
[@tenant_id, @feed_id, @environment_id, @resource_ids, @metric_id, @metric_type_id, @resource_type_id]
|
699
|
+
end
|
700
|
+
|
701
|
+
private
|
702
|
+
|
703
|
+
def resources_chunk
|
704
|
+
@resource_ids.map { |r| "/r;#{r}" }.join unless @resource_ids.nil?
|
705
|
+
end
|
706
|
+
end
|
378
707
|
end
|