hawkular-client 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.yardopts +1 -0
  4. data/CHANGES.rdoc +17 -4
  5. data/README.rdoc +15 -6
  6. data/api_breaking_changes.rdoc +79 -0
  7. data/hawkularclient.gemspec +6 -5
  8. data/lib/{alerts → hawkular/alerts}/alerts_api.rb +168 -7
  9. data/lib/{hawkular.rb → hawkular/base_client.rb} +7 -44
  10. data/lib/hawkular/hawkular_client.rb +60 -0
  11. data/lib/hawkular/hawkular_client_utils.rb +40 -0
  12. data/lib/{inventory → hawkular/inventory}/inventory_api.rb +167 -142
  13. data/lib/{metrics → hawkular/metrics}/metric_api.rb +1 -0
  14. data/lib/{metrics → hawkular/metrics}/metrics_client.rb +4 -4
  15. data/lib/{metrics → hawkular/metrics}/tenant_api.rb +0 -0
  16. data/lib/{metrics → hawkular/metrics}/types.rb +0 -0
  17. data/lib/{operations → hawkular/operations}/operations_api.rb +11 -8
  18. data/lib/{tokens → hawkular/tokens}/tokens_api.rb +1 -1
  19. data/lib/{version.rb → hawkular/version.rb} +1 -1
  20. data/spec/integration/alerts_spec.rb +200 -0
  21. data/spec/integration/hawkular_client_spec.rb +228 -0
  22. data/spec/integration/inventory_spec.rb +246 -160
  23. data/spec/integration/metric_spec.rb +52 -59
  24. data/spec/integration/operations_spec.rb +53 -29
  25. data/spec/spec_helper.rb +109 -8
  26. data/spec/unit/base_spec.rb +9 -0
  27. data/spec/unit/canonical_path_spec.rb +2 -2
  28. data/spec/vcr/vcr_setup.rb +6 -0
  29. data/spec/vcr_cassettes/Alert/Events/Should_create_an_event.yml +50 -0
  30. data/spec/vcr_cassettes/Alert/Groups/Should_operate_a_complex_group_trigger.yml +1726 -0
  31. data/spec/vcr_cassettes/Counter_metrics/Should_get_metrics_as_bucketed_results.yml +190 -0
  32. data/spec/vcr_cassettes/Counter_metrics/Should_get_metrics_with_limit_and_order.yml +30 -42
  33. data/spec/vcr_cassettes/HawkularClient/and_Inventory_client/Should_both_create_and_delete_feed.yml +287 -0
  34. data/spec/vcr_cassettes/{Inventory/Should_list_URLs.yml → HawkularClient/and_Inventory_client/Should_both_list_WildFlys.yml} +35 -33
  35. data/spec/vcr_cassettes/{Inventory/Should_list_types_with_bad_feed.yml → HawkularClient/and_Inventory_client/Should_both_list_types_with_bad_feed.yml} +16 -19
  36. data/spec/vcr_cassettes/HawkularClient/and_Inventory_client/Should_list_same_types_when_param_is_given.yml +245 -0
  37. data/spec/vcr_cassettes/{Inventory/Should_list_feeds.yml → HawkularClient/and_Inventory_client/Should_list_the_same_feeds.yml} +20 -20
  38. data/spec/vcr_cassettes/HawkularClient/and_Inventory_client/Should_list_the_same_resource_types.yml +249 -0
  39. data/spec/vcr_cassettes/HawkularClient/and_Metrics_client/Should_both_create_and_retrieve_tags_for_Availability.yml +155 -0
  40. data/spec/vcr_cassettes/HawkularClient/and_Metrics_client/Should_both_create_and_return_Availability_using_Hash_parameter.yml +155 -0
  41. data/spec/vcr_cassettes/HawkularClient/and_Metrics_client/Should_both_return_the_version.yml +89 -0
  42. data/spec/vcr_cassettes/HawkularClient/and_Metrics_client/Should_both_work_the_same_way_when_pushing_metric_data_to_non-existing_counter.yml +114 -0
  43. data/spec/vcr_cassettes/{Inventory/Should_list_WildFlys_with_props.yml → HawkularClient/and_Operations_client/Should_both_work_the_same_way.yml} +28 -50
  44. data/spec/vcr_cassettes/HawkularClient/and_Operations_client_Should_both_work_the_same_way.json +44 -0
  45. data/spec/vcr_cassettes/Inventory/Helpers/create_url.yml +48 -0
  46. data/spec/vcr_cassettes/Inventory/Helpers/generate_some_events_for_websocket.yml +4446 -0
  47. data/spec/vcr_cassettes/Inventory/Helpers/get_feeds.yml +54 -0
  48. data/spec/vcr_cassettes/Inventory/Templates/Client_should_listen_on_various_inventory_events.json +47 -0
  49. data/spec/vcr_cassettes/Inventory/{Should_create_a_resourcetype.yml → Templates/Client_should_listen_on_various_inventory_events.yml} +47 -61
  50. data/spec/vcr_cassettes/Inventory/Templates/Helpers/generate_some_events_for_websocket.yml +542 -0
  51. data/spec/vcr_cassettes/Inventory/{Should_List_datasources_with_no_props.yml → Templates/Should_List_datasources_with_no_props.yml} +26 -85
  52. data/spec/vcr_cassettes/Inventory/Templates/Should_create_a_feed.yml +54 -0
  53. data/spec/vcr_cassettes/Inventory/Templates/Should_create_a_feed_again.yml +164 -0
  54. data/spec/vcr_cassettes/Inventory/{Should_create_a_nested_resource_and_metric_on_it.yml → Templates/Should_create_a_nested_resource_and_metric_on_it.yml} +93 -74
  55. data/spec/vcr_cassettes/Inventory/{Should_create_a_resource_.yml → Templates/Should_create_a_resource.yml} +103 -76
  56. data/spec/vcr_cassettes/Inventory/{Should_create_a_resource_with_metric.yml → Templates/Should_create_a_resource_with_metric.yml} +91 -197
  57. data/spec/vcr_cassettes/Inventory/Templates/Should_create_a_resourcetype.yml +154 -0
  58. data/spec/vcr_cassettes/Inventory/Templates/Should_create_and_delete_feed.yml +145 -0
  59. data/spec/vcr_cassettes/Inventory/{Should_create_and_get_a_resource.yml → Templates/Should_create_and_get_a_resource.yml} +35 -20
  60. data/spec/vcr_cassettes/Inventory/Templates/Should_list_URLs.yml +65 -0
  61. data/spec/vcr_cassettes/Inventory/Templates/Should_list_WildFlys.yml +61 -0
  62. data/spec/vcr_cassettes/Inventory/{Should_list_WildFlys.yml → Templates/Should_list_WildFlys_with_props.yml} +36 -33
  63. data/spec/vcr_cassettes/Inventory/Templates/Should_list_all_the_resource_types.yml +126 -0
  64. data/spec/vcr_cassettes/Inventory/{Should_list_children_of_WildFly.yml → Templates/Should_list_children_of_WildFly.yml} +66 -112
  65. data/spec/vcr_cassettes/Inventory/{Should_list_children_of_nested_resource.yml → Templates/Should_list_children_of_nested_resource.yml} +13 -13
  66. data/spec/vcr_cassettes/Inventory/Templates/Should_list_feeds.yml +54 -0
  67. data/spec/vcr_cassettes/Inventory/Templates/Should_list_heap_metrics_for_WildFlys.yml +712 -0
  68. data/spec/vcr_cassettes/Inventory/Templates/Should_list_metrics_for_WildFlys.yml +278 -0
  69. data/spec/vcr_cassettes/Inventory/Templates/Should_list_metrics_of_given_metric_type.yml +530 -0
  70. data/spec/vcr_cassettes/Inventory/Templates/Should_list_metrics_of_given_resource_type.yml +278 -0
  71. data/spec/vcr_cassettes/Inventory/Templates/Should_list_operation_definitions_of_given_resource.yml +185 -0
  72. data/spec/vcr_cassettes/Inventory/Templates/Should_list_operation_definitions_of_given_resource_type.yml +126 -0
  73. data/spec/vcr_cassettes/Inventory/Templates/Should_list_recursive_children_of_WildFly.yml +2369 -0
  74. data/spec/vcr_cassettes/Inventory/Templates/Should_list_relationships_of_WildFly.yml +415 -0
  75. data/spec/vcr_cassettes/Inventory/Templates/Should_list_types_with_bad_feed.yml +51 -0
  76. data/spec/vcr_cassettes/Inventory/Templates/Should_list_types_with_feed.yml +124 -0
  77. data/spec/vcr_cassettes/Inventory/{Should_not_find_an_unknown_resource.yml → Templates/Should_not_find_an_unknown_resource.yml} +14 -13
  78. data/spec/vcr_cassettes/Inventory/{Should_return_config_data_of_given_nested_resource.yml → Templates/Should_return_config_data_of_given_nested_resource.yml} +4 -4
  79. data/spec/vcr_cassettes/Inventory/{Should_return_config_data_of_given_resource.yml → Templates/Should_return_config_data_of_given_resource.yml} +4 -4
  80. data/spec/vcr_cassettes/Inventory/Tenants/Should_Get_Tenant_For_Explicit_Credentials.yml +50 -0
  81. data/spec/vcr_cassettes/Inventory/Tenants/Should_Get_Tenant_For_Implicit_Credentials.yml +50 -0
  82. data/spec/vcr_cassettes/Operation/Helpers/get_feed.yml +54 -0
  83. data/spec/vcr_cassettes/Operation/Helpers/get_tenant.yml +50 -0
  84. data/spec/vcr_cassettes/Operation/Operation/Add_JDBC_driver_should_add_the_driver.json +26 -0
  85. data/spec/vcr_cassettes/Operation/Operation/Add_datasource_should_be_doable.json +26 -0
  86. data/spec/vcr_cassettes/Operation/Operation/Add_deployment_should_be_doable.json +26 -0
  87. data/spec/vcr_cassettes/Operation/Operation/Redeploy_can_be_run_multiple_times_in_parallel.json +40 -0
  88. data/spec/vcr_cassettes/Operation/Operation/Redeploy_should_be_performed_and_eventually_respond_with_success.json +26 -0
  89. data/spec/vcr_cassettes/Operation/Operation/Redeploy_should_not_be_performed_if_resource_path_is_wrong.json +26 -0
  90. data/spec/vcr_cassettes/Operation/Operation/Remove_JDBC_driver_should_be_performed_and_eventually_respond_with_success.json +26 -0
  91. data/spec/vcr_cassettes/Operation/Operation/Remove_datasource_should_be_performed_and_eventually_respond_with_success.json +26 -0
  92. data/spec/vcr_cassettes/Operation/Operation/Remove_deployment_should_be_performed_and_eventually_respond_with_success.json +26 -0
  93. data/spec/vcr_cassettes/Operation/Operation/Undeploy_should_be_performed_and_eventually_respond_with_success.json +26 -0
  94. data/spec/vcr_cassettes/Operation/Operation/should_not_be_possible_to_perform_on_closed_client.json +12 -0
  95. data/spec/vcr_cassettes/Operation/Websocket_connection/should_be_established.json +9 -0
  96. metadata +171 -72
  97. data/lib/hawkular_all.rb +0 -9
  98. data/spec/vcr_cassettes/Inventory/Should_create_a_feed.yml +0 -107
  99. data/spec/vcr_cassettes/Inventory/Should_create_a_feed_again.yml +0 -211
  100. data/spec/vcr_cassettes/Inventory/Should_create_and_delete_feed.yml +0 -201
  101. data/spec/vcr_cassettes/Inventory/Should_list_all_the_resource_types.yml +0 -177
  102. data/spec/vcr_cassettes/Inventory/Should_list_heap_metrics_for_WildFlys.yml +0 -775
  103. data/spec/vcr_cassettes/Inventory/Should_list_metrics_for_WildFlys.yml +0 -333
  104. data/spec/vcr_cassettes/Inventory/Should_list_metrics_of_given_metric_type.yml +0 -613
  105. data/spec/vcr_cassettes/Inventory/Should_list_metrics_of_given_resource_type.yml +0 -333
  106. data/spec/vcr_cassettes/Inventory/Should_list_recursive_children_of_WildFly.yml +0 -2064
  107. data/spec/vcr_cassettes/Inventory/Should_list_relationships_of_WildFly.yml +0 -460
  108. data/spec/vcr_cassettes/Inventory/Should_list_types_with_feed.yml +0 -175
@@ -1,14 +1,14 @@
1
1
  require 'base64'
2
2
  require 'addressable/uri'
3
+ require 'hawkular/hawkular_client_utils'
3
4
 
4
5
  module Hawkular
5
- module Metrics
6
- end
7
-
8
6
  # This is the base functionality for all the clients,
9
7
  # that inherit from it. You should not directly use it,
10
8
  # but through the more specialized clients.
11
9
  class BaseClient
10
+ include HawkularUtilsMixin
11
+
12
12
  # @!visibility private
13
13
  attr_reader :credentials, :entrypoint, :options
14
14
  # @return [Tenants] access tenants API
@@ -29,6 +29,7 @@ module Hawkular
29
29
  verify_ssl: OpenSSL::SSL::VERIFY_PEER,
30
30
  ssl_client_cert: nil,
31
31
  ssl_client_key: nil,
32
+ http_proxy_uri: nil,
32
33
  headers: {}
33
34
  }.merge(options)
34
35
 
@@ -43,45 +44,6 @@ module Hawkular
43
44
  handle_fault $ERROR_INFO
44
45
  end
45
46
 
46
- # Escapes the passed url part. This is necessary,
47
- # as many ids inside Hawkular can contain characters
48
- # that are invalid for an url/uri.
49
- # The passed value is duplicated
50
- # Does not escape the = character
51
- # @param [String] url_part Part of an url to be escaped
52
- # @return [String] escaped url_part as new string
53
- def hawk_escape(url_part)
54
- return url_part.to_s if url_part.is_a?(Numeric)
55
-
56
- if url_part.is_a? Symbol
57
- sub_url = url_part.to_s
58
- else
59
- sub_url = url_part.dup
60
- end
61
- sub_url.gsub!('%', '%25')
62
- sub_url.gsub!(' ', '%20')
63
- sub_url.gsub!('[', '%5b')
64
- sub_url.gsub!(']', '%5d')
65
- sub_url.gsub!('|', '%7c')
66
- sub_url.gsub!('(', '%28')
67
- sub_url.gsub!(')', '%29')
68
- sub_url.gsub!('/', '%2f')
69
- sub_url
70
- end
71
-
72
- # Escapes the passed url part. This is necessary,
73
- # as many ids inside Hawkular can contain characters
74
- # that are invalid for an url/uri.
75
- # The passed value is duplicated
76
- # Does escape the = character
77
- # @param [String] url_part Part of an url to be escaped
78
- # @return [String] escaped url_part as new string
79
- def hawk_escape_id(url_part)
80
- sub_url = hawk_escape url_part
81
- sub_url.gsub!('=', '%3d')
82
- sub_url
83
- end
84
-
85
47
  def http_post(suburl, hash, headers = {})
86
48
  body = JSON.generate(hash)
87
49
  res = rest_client(suburl).post(body, http_headers(headers))
@@ -115,6 +77,7 @@ module Hawkular
115
77
  options[:verify_ssl] = @options[:verify_ssl]
116
78
  options[:ssl_client_cert] = @options[:ssl_client_cert]
117
79
  options[:ssl_client_key] = @options[:ssl_client_key]
80
+ options[:proxy] = @options[:http_proxy_uri]
118
81
  options[:user] = @credentials[:username]
119
82
  options[:password] = @credentials[:password]
120
83
  # strip @endpoint in case suburl is absolute
@@ -183,8 +146,8 @@ module Hawkular
183
146
  end
184
147
 
185
148
  def tenant_header
186
- @options[:tenant].nil? ? {} : { :'Hawkular-Tenant' => @options[:tenant],
187
- 'tenantId' => @options[:tenant] }
149
+ @options[:tenant].nil? ? { 'Hawkular-Tenant' => 'hawkular' } : { :'Hawkular-Tenant' => @options[:tenant],
150
+ 'tenantId' => @options[:tenant] }
188
151
  end
189
152
 
190
153
  def handle_fault(f)
@@ -0,0 +1,60 @@
1
+ require 'hawkular/inventory/inventory_api'
2
+ require 'hawkular/metrics/metrics_client.rb'
3
+ require 'hawkular/alerts/alerts_api'
4
+ require 'hawkular/tokens/tokens_api'
5
+ require 'hawkular/operations/operations_api'
6
+ require 'hawkular/base_client'
7
+
8
+ module Hawkular
9
+ class Client
10
+ attr_reader :inventory, :metrics, :alerts, :operations, :tokens, :state
11
+
12
+ def initialize(hash)
13
+ hash[:entrypoint] ||= 'http://localhost:8080'
14
+ hash[:credentials] ||= {}
15
+ hash[:options] ||= {}
16
+ @state = hash
17
+
18
+ @inventory = Inventory::InventoryClient.create(entrypoint: "#{hash[:entrypoint]}/hawkular/inventory",
19
+ credentials: hash[:credentials])
20
+
21
+ @metrics = Metrics::Client.new("#{hash[:entrypoint]}/hawkular/metrics",
22
+ hash[:credentials],
23
+ hash[:options])
24
+
25
+ @alerts = Alerts::AlertsClient.new("#{hash[:entrypoint]}/hawkular/alerts", hash[:credentials])
26
+
27
+ @tokens = Token::TokenClient.new(hash[:entrypoint], hash[:credentials])
28
+ end
29
+
30
+ def method_missing(name, *args, &block)
31
+ delegate_client = case name
32
+ when /^inventory_/ then @inventory
33
+ when /^metrics_/ then @metrics
34
+ when /^alerts_/ then @alerts
35
+ when /^operations_/ then @operations ||= init_operations_client
36
+ when /^tokens_/ then @tokens
37
+ else
38
+ fail "unknown method prefix `#{name}`, allowed prefixes:"\
39
+ '`inventory_`, `metrics_`,`alerts_`,`operations_`, `tokens_`'
40
+ end
41
+ method = name.to_s.sub(/^[^_]+_/, '')
42
+ delegate_client.__send__(method, *args, &block)
43
+ end
44
+
45
+ # adds a way to explicitly open the new web socket connection (the default is to recycle it)
46
+ # @param open_new [Boolean] if true, opens the new websocket connection
47
+ def operations(open_new = false)
48
+ @operations = init_operations_client if open_new
49
+ @operations ||= init_operations_client
50
+ end
51
+
52
+ private
53
+
54
+ # this is in a dedicated method, because constructor opens the websocket connection to make the handshake
55
+ def init_operations_client
56
+ Operations::OperationsClient.new(entrypoint: @state[:entrypoint].gsub(/^https?/, 'ws'),
57
+ credentials: @state[:credentials])
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,40 @@
1
+ module HawkularUtilsMixin
2
+ # Escapes the passed url part. This is necessary,
3
+ # as many ids inside Hawkular can contain characters
4
+ # that are invalid for an url/uri.
5
+ # The passed value is duplicated
6
+ # Does not escape the = character
7
+ # @param [String] url_part Part of an url to be escaped
8
+ # @return [String] escaped url_part as new string
9
+ def hawk_escape(url_part)
10
+ return url_part.to_s if url_part.is_a?(Numeric)
11
+
12
+ if url_part.is_a? Symbol
13
+ sub_url = url_part.to_s
14
+ else
15
+ sub_url = url_part.dup
16
+ end
17
+ sub_url.gsub!('%', '%25')
18
+ sub_url.gsub!(' ', '%20')
19
+ sub_url.gsub!('[', '%5b')
20
+ sub_url.gsub!(']', '%5d')
21
+ sub_url.gsub!('|', '%7c')
22
+ sub_url.gsub!('(', '%28')
23
+ sub_url.gsub!(')', '%29')
24
+ sub_url.gsub!('/', '%2f')
25
+ sub_url
26
+ end
27
+
28
+ # Escapes the passed url part. This is necessary,
29
+ # as many ids inside Hawkular can contain characters
30
+ # that are invalid for an url/uri.
31
+ # The passed value is duplicated
32
+ # Does escape the = character
33
+ # @param [String] url_part Part of an url to be escaped
34
+ # @return [String] escaped url_part as new string
35
+ def hawk_escape_id(url_part)
36
+ sub_url = hawk_escape url_part
37
+ sub_url.gsub!('=', '%3d')
38
+ sub_url
39
+ end
40
+ end
@@ -1,4 +1,4 @@
1
- require 'hawkular'
1
+ require 'hawkular/base_client'
2
2
  require 'websocket-client-simple'
3
3
  require 'json'
4
4
 
@@ -55,57 +55,57 @@ module Hawkular::Inventory
55
55
  ret.map { |f| f['id'] }
56
56
  end
57
57
 
58
- # List resource types. If no need is given all types are listed
59
- # @param [String] feed The id of the feed the type lives under. Can be nil for feedless types
58
+ # List resource types. If no feed_id is given all types are listed
59
+ # @param [String] feed_id The id of the feed the type lives under. Can be nil for feedless types
60
60
  # @return [Array<ResourceType>] List of types, that can be empty
61
- def list_resource_types(feed = nil)
62
- if feed.nil?
61
+ def list_resource_types(feed_id = nil)
62
+ if feed_id.nil?
63
63
  ret = http_get('/resourceTypes')
64
64
  else
65
- the_feed = hawk_escape_id feed
65
+ the_feed = hawk_escape_id feed_id
66
66
  ret = http_get("/feeds/#{the_feed}/resourceTypes")
67
67
  end
68
68
  ret.map { |rt| ResourceType.new(rt) }
69
69
  end
70
70
 
71
71
  # Return all resources for a feed
72
- # @param [String] feed Id of the feed that hosts the resources
72
+ # @param [String] feed_id Id of the feed that hosts the resources
73
73
  # @param [Boolean] fetch_properties Should the config data be fetched too
74
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
75
+ def list_resources_for_feed(feed_id, fetch_properties = false, filter = {})
76
+ fail 'Feed id must be given' unless feed_id
77
77
  the_feed = hawk_escape_id feed
78
78
  ret = http_get("/feeds/#{the_feed}/resources")
79
- ret.map do |r|
79
+ to_filter = ret.map do |r|
80
80
  if fetch_properties
81
- p = get_config_data_for_resource(r['id'], feed)
81
+ p = get_config_data_for_resource(r['path'])
82
82
  r['properties'] = p['value']
83
83
  end
84
84
  Resource.new(r)
85
85
  end
86
+ filter_entities(to_filter, filter)
86
87
  end
87
88
 
88
- # List the resources for the passed feed and resource type. The representation for
89
- # resources under a feed are sparse and additional data must be retrived separately.
89
+ # List the resources for the passed resource type. The representation for
90
+ # resources under a feed are sparse and additional data must be retrieved separately.
90
91
  # It is possible though to also obtain runtime properties by setting #fetch_properties to true.
91
- # @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
92
- # @param [String] type Name of the type to look for. Can be obtained from {ResourceType}.id.
93
- # Must not be nil
92
+ # @param [String] resource_type_path Canonical path of the resource type. Can be obtained from {ResourceType}.path.
93
+ # Must not be nil. The tenant_id in the canonical path doesn't have to be there.
94
94
  # @param [Boolean] fetch_properties Shall additional runtime properties be fetched?
95
95
  # @return [Array<Resource>] List of resources. Can be empty
96
- def list_resources_for_type(feed, type, fetch_properties = false)
97
- fail 'Type must not be nil' unless type
98
- the_type = hawk_escape_id type
99
- if feed.nil?
100
- ret = http_get("resourceTypes/#{the_type}/resources")
96
+ def list_resources_for_type(resource_type_path, fetch_properties = false)
97
+ path = resource_type_path.is_a?(CanonicalPath) ? resource_type_path : CanonicalPath.parse(resource_type_path)
98
+ resource_type_id = path.resource_type_id
99
+ feed_id = path.feed_id
100
+ if feed_id.nil?
101
+ ret = http_get("resourceTypes/#{resource_type_id}/resources")
101
102
  else
102
103
 
103
- the_feed = hawk_escape_id feed
104
- ret = http_get("/feeds/#{the_feed}/resourceTypes/#{the_type}/resources")
104
+ ret = http_get("/feeds/#{feed_id}/resourceTypes/#{resource_type_id}/resources")
105
105
  end
106
106
  ret.map do |r|
107
- if fetch_properties && !feed.nil?
108
- p = get_config_data_for_resource(r['id'], feed)
107
+ if fetch_properties && !feed_id.nil?
108
+ p = get_config_data_for_resource(r['path'])
109
109
  r['properties'] = p['value']
110
110
  end
111
111
  Resource.new(r)
@@ -113,44 +113,45 @@ module Hawkular::Inventory
113
113
  end
114
114
 
115
115
  # Retrieve runtime properties for the passed resource
116
- # @param [String] feed_id Feed of the resource
117
- # @param [Array<String>] res_ids Ids of the resource to read properties from (parent to child order)
116
+ # @param [String] resource_path Canonical path of the resource to read properties from.
118
117
  # @return [Hash<String,Object] Hash with additional data
119
- def get_config_data_for_resource(res_ids, feed_id)
120
- resource_path = if res_ids.is_a?(Array)
121
- res_ids.map { |id| hawk_escape_id id }.join('/')
122
- else
123
- hawk_escape_id res_ids
124
- end
125
- the_feed = hawk_escape_id feed_id
118
+ def get_config_data_for_resource(resource_path)
119
+ path = resource_path.is_a?(CanonicalPath) ? resource_path : CanonicalPath.parse(resource_path)
120
+ resource_path = path.resource_ids.join('/')
121
+ feed_id = path.feed_id
126
122
  query = generate_query_params dataType: 'configuration'
127
- http_get("feeds/#{the_feed}/resources/#{resource_path}/data#{query}")
123
+ http_get("feeds/#{feed_id}/resources/#{resource_path}/data#{query}")
128
124
  rescue
129
125
  {}
130
126
  end
131
127
 
132
128
  # Obtain the child resources of the passed resource. In case of a WildFly server,
133
129
  # those would be Datasources, Deployments and so on.
134
- # @param [Resource] parent_resource Resource to obtain children from
130
+ # @param [String] parent_res_path Canonical path of the resource to obtain children from.
135
131
  # @param [Boolean] recursive Whether to fetch also all the children of children of ...
136
132
  # @return [Array<Resource>] List of resources that are children of the given parent resource.
137
133
  # Can be empty
138
- def list_child_resources(parent_resource, recursive = false)
139
- the_feed = hawk_escape_id parent_resource.feed
140
- resource_path_escaped = CanonicalPath.parse(parent_resource.path).resource_ids.join('/')
141
-
134
+ def list_child_resources(parent_res_path, recursive = false)
135
+ path = parent_res_path.is_a?(CanonicalPath) ? parent_res_path : CanonicalPath.parse(parent_res_path)
136
+ parent_resource_path = path.resource_ids.join('/')
137
+ feed_id = path.feed_id
142
138
  which_children = (recursive ? '/recursiveChildren' : '/children')
143
- ret = http_get("/feeds/#{the_feed}/resources/#{resource_path_escaped}#{which_children}")
139
+ ret = http_get("/feeds/#{feed_id}/resources/#{parent_resource_path}#{which_children}")
144
140
  ret.map { |r| Resource.new(r) }
145
141
  end
146
142
 
147
143
  # Obtain a list of relationships starting at the passed resource
148
- # @param [Resource] resource One end of the relationship
144
+ # @param [String] entity_path Canonical path of the entity that forms the one end of the relationship
149
145
  # @param [String] named Name of the relationship
150
146
  # @return [Array<Relationship>] List of relationships
151
- def list_relationships(resource, named = nil)
152
- query = named.nil? ? '' : (generate_query_params named: named)
153
- ret = http_get("/path#{resource.path}/relationships#{query}")
147
+ def list_relationships(entity_path, named = nil)
148
+ path = entity_path.is_a?(CanonicalPath) ? entity_path : CanonicalPath.parse(entity_path)
149
+ query_params = {
150
+ sort: '__targetCp'
151
+ }
152
+ query_params[:named] = named unless named.nil?
153
+ query = generate_query_params query_params
154
+ ret = http_get("/path#{path}/relationships#{query}")
154
155
  ret.map { |r| Relationship.new(r) }
155
156
  end
156
157
 
@@ -160,7 +161,11 @@ module Hawkular::Inventory
160
161
  # @return [Array<Relationship>] List of relationships
161
162
  def list_relationships_for_feed(feed_id, named = nil)
162
163
  the_feed = hawk_escape_id feed_id
163
- query = named.nil? ? '' : (generate_query_params named: named)
164
+ query_params = {
165
+ sort: '__targetCp'
166
+ }
167
+ query_params[:named] = named unless named.nil?
168
+ query = generate_query_params query_params
164
169
  ret = http_get("/feeds/#{the_feed}/relationships#{query}")
165
170
  ret.map { |r| Relationship.new(r) }
166
171
  rescue
@@ -168,10 +173,11 @@ module Hawkular::Inventory
168
173
  end
169
174
 
170
175
  # Retrieve a single entity from inventory by its canonical path
171
- # @param [CanonicalPath] path canonical path of the entity
176
+ # @param [String] path canonical path of the entity
172
177
  # @return inventory entity
173
178
  def get_entity(path)
174
- http_get("path#{path}")
179
+ c_path = path.is_a?(CanonicalPath) ? path : CanonicalPath.parse(path)
180
+ http_get("path#{c_path}")
175
181
  end
176
182
 
177
183
  # [15:01:51] <jkremser> pilhuhn, this works for me curl -XPOST
@@ -194,55 +200,54 @@ module Hawkular::Inventory
194
200
  # rel.to_h)
195
201
  # end
196
202
 
197
- # List the metrics for the passed feed and metric type. If feed is not passed,
203
+ # List the metrics for the passed metric type. If feed is not passed in the path,
198
204
  # all the metrics across all the feeds of a given type will be retrieved
199
205
  # This method may perform multiple REST calls.
200
- # @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
201
- # @param [String] type Name of the metric type to look for. Can be obtained from {MetricType}.id.
202
- # Must not be nil
206
+ # @param [String] metric_type_path Canonical path of the resource type to look for. Can be obtained from
207
+ # {MetricType}.path. Must not be nil. The tenant_id in the canonical path doesn't have to be there.
203
208
  # @return [Array<Metric>] List of metrics. Can be empty
204
- def list_metrics_for_metric_type(feed, type)
205
- fail 'Type must not be nil' unless type
206
- the_type = hawk_escape_id type
207
- if feed.nil?
208
- type_hash = http_get("metricTypes/#{the_type}")
209
+ def list_metrics_for_metric_type(metric_type_path)
210
+ path = metric_type_path.is_a?(CanonicalPath) ? metric_type_path : CanonicalPath.parse(metric_type_path)
211
+ metric_type_id = path.metric_type_id
212
+ feed_id = path.feed_id
213
+ if feed_id.nil?
214
+ type_hash = http_get("metricTypes/#{metric_type_id}")
209
215
  else
210
- the_feed = hawk_escape_id feed
211
- type_hash = http_get("/feeds/#{the_feed}/metricTypes/#{the_type}")
216
+ type_hash = http_get("/feeds/#{feed_id}/metricTypes/#{metric_type_id}")
212
217
  end
213
218
 
214
- rels = list_relationships(ResourceType.new(type_hash), 'defines')
215
- rels.map do |rel|
216
- path = CanonicalPath.parse(rel.target_id.to_s)
217
- metric_hash = get_entity path
219
+ relations = list_relationships(type_hash['path'], 'defines')
220
+ relations.map do |rel|
221
+ metric_hash = get_entity rel.target_id.to_s
218
222
  Metric.new(metric_hash)
219
223
  end
220
224
  rescue
221
225
  []
222
226
  end
223
227
 
224
- # List the metrics for the passed feed and all the resources of given resource type.
225
- # If feed is not passed, all the metrics across all the feeds of a resource type will be retrieved
226
- # This method may perform multiple REST calls.
227
- # @param [String] feed The id of the feed the type lives under. Can be nil for all feeds
228
- # @param [String] type Name of the resource type to look for. Can be obtained from {ResourceType}.id.
229
- # Must not be nil
228
+ # List the metrics for all the resources of a given resource type.
229
+ # If feed is not passed in the resource type canonical path, all the metrics across all the feeds of a resource
230
+ # type will be retrieved. This method may perform multiple REST calls.
231
+ # @param [String] resource_type_path Canonical path of the resource type to look for. Can be obtained from
232
+ # {ResourceType}.path. Must not be nil. The tenant_id in the canonical path doesn't have to be there.
230
233
  # @return [Array<Metric>] List of metrics. Can be empty
231
- def list_metrics_for_resource_type(feed, type)
232
- fail 'Type must not be nil' unless type
233
- the_type = hawk_escape_id type
234
- if feed.nil?
235
- ret = http_get("resourceTypes/#{the_type}/resources")
234
+ def list_metrics_for_resource_type(resource_type_path)
235
+ path = resource_type_path.is_a?(CanonicalPath) ? resource_type_path : CanonicalPath.parse(resource_type_path)
236
+ resource_type_id = path.resource_type_id
237
+ feed_id = path.feed_id
238
+
239
+ if feed_id.nil?
240
+ ret = http_get("resourceTypes/#{resource_type_id}/resources")
236
241
  else
237
- the_feed = hawk_escape_id feed
238
- ret = http_get("feeds/#{the_feed}/resourceTypes/#{the_type}/resources")
242
+ ret = http_get("feeds/#{feed_id}/resourceTypes/#{resource_type_id}/resources")
239
243
  end
240
244
  ret.flat_map do |r|
241
245
  path = CanonicalPath.parse(r['path'])
246
+ query = generate_query_params sort: 'id'
242
247
  if !path.feed_id.nil?
243
- nested_ret = http_get("feeds/#{path.feed_id}/resources/#{path.resource_ids.join('/')}/metrics")
248
+ nested_ret = http_get("feeds/#{path.feed_id}/resources/#{path.resource_ids.join('/')}/metrics#{query}")
244
249
  else
245
- nested_ret = http_get("#{path.environment_id}/resources/#{path.resource_ids.join('/')}/metrics")
250
+ nested_ret = http_get("#{path.environment_id}/resources/#{path.resource_ids.join('/')}/metrics#{query}")
246
251
  end
247
252
  nested_ret.map { |m| Metric.new(m) }
248
253
  end
@@ -250,7 +255,7 @@ module Hawkular::Inventory
250
255
 
251
256
  # List metric (definitions) for the passed resource. It is possible to filter down the
252
257
  # result by a filter to only return a subset. The
253
- # @param [Resource] resource
258
+ # @param [String] resource_path Canonical path of the resource.
254
259
  # @param [Hash{Symbol=>String}] filter for 'type' and 'match'
255
260
  # Metric type can be one of 'GAUGE', 'COUNTER', 'AVAILABILITY'. If a key is missing
256
261
  # it will not be used for filtering
@@ -262,17 +267,15 @@ module Hawkular::Inventory
262
267
  # client.list_metrics_for_resource(wild_fly, type: 'COUNTER')
263
268
  # # Don't filter, return all metric definitions
264
269
  # client.list_metrics_for_resource(wild_fly)
265
- def list_metrics_for_resource(resource, filter = {})
266
- the_feed = hawk_escape_id resource.feed
267
- resource_path_escaped = CanonicalPath.parse(resource.path).resource_ids.join('/')
268
-
269
- ret = http_get("/feeds/#{the_feed}/resources/#{resource_path_escaped}/metrics")
270
- with_nils = ret.map do |m|
271
- metric_new = Metric.new(m)
272
- found = should_include?(metric_new, filter)
273
- metric_new if found
274
- end
275
- with_nils.compact
270
+ def list_metrics_for_resource(resource_path, filter = {})
271
+ path = resource_path.is_a?(CanonicalPath) ? resource_path : CanonicalPath.parse(resource_path)
272
+ feed_id = path.feed_id
273
+ resource_path_escaped = path.resource_ids.join('/')
274
+
275
+ query = generate_query_params sort: 'id'
276
+ ret = http_get("/feeds/#{feed_id}/resources/#{resource_path_escaped}/metrics#{query}")
277
+ to_filter = ret.map { |m| Metric.new(m) }
278
+ filter_entities(to_filter, filter)
276
279
  end
277
280
 
278
281
  # Create a new feed
@@ -298,9 +301,9 @@ module Hawkular::Inventory
298
301
  end
299
302
 
300
303
  # Delete the feed with the passed feed id.
301
- # @param feed Id of the feed to be deleted.
302
- def delete_feed(feed)
303
- the_feed = hawk_escape_id feed
304
+ # @param feed_id Id of the feed to be deleted.
305
+ def delete_feed(feed_id)
306
+ the_feed = hawk_escape_id feed_id
304
307
  http_delete("/feeds/#{the_feed}")
305
308
  end
306
309
 
@@ -328,62 +331,61 @@ module Hawkular::Inventory
328
331
  ResourceType.new(res)
329
332
  end
330
333
 
331
- # Create a resource of a given type under a given feed. To retrieve that resource
334
+ # Create a resource of a given type. To retrieve that resource
332
335
  # you need to call {#get_resource}
333
- # @param [String] feed_id Id of the feed to add the resource to
334
- # @param [String] type_path Path of the resource type of this resource
335
- # @param [String] resource_id Id of the resource
336
- # @param [String] resource_name Name of the resource
336
+ # @param [String] resource_type_path Canonical path of the new resource's type.
337
+ # @param [String] resource_id Id of the new resource
338
+ # @param [String] resource_name Name of the new resource
337
339
  # @param [Hash<String,Object>] properties Additional properties. Those are not the config-properties
338
- def create_resource(feed_id, type_path, resource_id, resource_name = nil, properties = {})
339
- create_resource_under_resource(feed_id, type_path, [], resource_id, resource_name, properties)
340
+ def create_resource(resource_type_path, resource_id, resource_name = nil, properties = {})
341
+ create_resource_under_resource(resource_type_path, nil, resource_id, resource_name, properties)
340
342
  end
341
343
 
342
- # Create a resource of a given type under a given feed. To retrieve that resource
344
+ # Create a resource of a given type under a given resource. To retrieve that resource
343
345
  # you need to call {#get_resource}
344
- # @param [String] feed_id Id of the feed to add the resource to
345
- # @param [String] type_path Path of the resource type of this resource
346
- # @param [Array<String>] parent_resource_ids Ids of the resources under which we create this resource
347
- # (parent to child order)
346
+ # @param [String] res_type_path Canonical path of the new resource's type.
347
+ # @param [String] parent_res_path Canonical path of the resource under which we create this resource.
348
+ # If nil, the top-lvl resource will be created.
348
349
  # @param [String] resource_id Id of the resource
349
350
  # @param [String] resource_name Name of the resource
350
351
  # @param [Hash<String,Object>] properties Additional properties. Those are not the config-properties
351
- def create_resource_under_resource(feed_id, type_path, parent_resource_ids, resource_id, resource_name = nil,
352
+ def create_resource_under_resource(res_type_path, parent_res_path, resource_id, resource_name = nil,
352
353
  properties = {})
353
- the_feed = hawk_escape_id feed_id
354
+ type_path = res_type_path.is_a?(CanonicalPath) ? res_type_path : CanonicalPath.parse(res_type_path)
355
+ feed_id = type_path.feed_id
354
356
 
355
357
  res = create_blueprint
356
358
  res[:properties] = properties
357
359
  res[:id] = resource_id
358
360
  res[:name] = resource_name
359
- res[:resourceTypePath] = type_path
361
+ res[:resourceTypePath] = type_path.to_s
360
362
 
361
363
  begin
362
- if parent_resource_ids.empty?
363
- http_post("/feeds/#{the_feed}/resources", res)
364
+ if parent_res_path.nil?
365
+ res = http_post("/feeds/#{feed_id}/resources", res)
364
366
  else
365
- parent_resource_path = parent_resource_ids.map { |id| hawk_escape_id id }.join('/')
366
- http_post("/feeds/#{the_feed}/resources/#{parent_resource_path}", res)
367
+ path = parent_res_path.is_a?(CanonicalPath) ? parent_res_path : CanonicalPath.parse(parent_res_path)
368
+ resource_path = path.resource_ids.join('/')
369
+ res = http_post("/feeds/#{feed_id}/resources/#{resource_path}", res)
367
370
  end
368
371
  rescue HawkularException => error
369
372
  # 409 We already exist -> that is ok
370
373
  raise unless error.status_code == 409
371
374
  end
372
-
373
- get_resource feed_id, parent_resource_ids << resource_id, false
375
+ Resource.new(res)
374
376
  end
375
377
 
376
- # Return the resource object for the passed id
377
- # @param [String] feed_id Id of the feed this resource belongs to
378
- # @param [Array<String>] res_ids Ids of the resource to fetch (parent to child order)
378
+ # Return the resource object for the passed path
379
+ # @param [String] resource_path Canonical path of the resource to fetch.
379
380
  # @param [Boolean] fetch_resource_config Should the resource config data be fetched?
380
- def get_resource(feed_id, res_ids, fetch_resource_config = true)
381
- the_feed = hawk_escape_id feed_id
382
- res_path = res_ids.is_a?(Array) ? (res_ids.map { |id| hawk_escape_id id }.join('/')) : hawk_escape_id(res_ids)
381
+ def get_resource(resource_path, fetch_resource_config = true)
382
+ path = resource_path.is_a?(CanonicalPath) ? resource_path : CanonicalPath.parse(resource_path)
383
+ feed_id = path.feed_id
384
+ res_path = path.resource_ids.join('/')
383
385
 
384
- res = http_get("/feeds/#{the_feed}/resources/#{res_path}")
386
+ res = http_get("/feeds/#{feed_id}/resources/#{res_path}")
385
387
  if fetch_resource_config
386
- p = get_config_data_for_resource(res_ids, feed_id)
388
+ p = get_config_data_for_resource(resource_path)
387
389
  res['properties'] ||= {}
388
390
  res['properties'].merge p['value'] unless p['value'].nil?
389
391
  end
@@ -417,42 +419,60 @@ module Hawkular::Inventory
417
419
  MetricType.new(new_mt)
418
420
  end
419
421
 
422
+ # List operation definitions (types) for a given resource type
423
+ # @param [String] resource_type_path canonical path of the resource type entity
424
+ # @return [Array<String>] List of operation type ids
425
+ def list_operation_definitions(resource_type_path)
426
+ parsed_path = CanonicalPath.parse(resource_type_path.to_s)
427
+ feed_id = parsed_path.feed_id
428
+ resource_type_id = parsed_path.resource_type_id
429
+ ret = http_get("/feeds/#{feed_id}/resourceTypes/#{resource_type_id}/operationTypes")
430
+ ret.map { |ot| ot['id'] }
431
+ end
432
+
433
+ # List operation definitions (types) for a given resource
434
+ # @param [String] resource_path canonical path of the resource entity
435
+ # @return [Array<String>] List of operation type ids
436
+ def list_operation_definitions_for_resource(resource_path)
437
+ resource = get_resource(resource_path.to_s, false)
438
+ list_operation_definitions(resource.type_path)
439
+ end
440
+
420
441
  # Create a Metric and associate it with a resource.
421
- # @param [String] feed_id Id of the feed
442
+ # @param [String] metric_type_path Canonical path of the metric type of the new metric.
443
+ # @param [String] resource_path Canonical path of the resource to which we want to associate the metric.
422
444
  # @param [String] metric_id Id of the metric
423
- # @param [String] type_path Full path of the MetricType
424
- # @param [Array<String>] res_ids Ids of the resource to associate the metric with (from parent to child)
425
445
  # @param [String] metric_name a (display) name for the metric. If nil, #metric_id is used.
426
446
  # @return [Metric] The metric created or if it already existed the version from the server
427
- # rubocop:disable Metrics/CyclomaticComplexity
428
- def create_metric_for_resource(feed_id, metric_id, type_path, res_ids, metric_name = nil)
429
- the_feed = hawk_escape_id feed_id
430
- res_path = res_ids.is_a?(Array) ? (res_ids.map { |id| hawk_escape_id id }.join('/')) : hawk_escape_id(res_ids)
447
+ def create_metric_for_resource(metric_type_path, resource_path, metric_id, metric_name = nil)
448
+ type_path = metric_type_path.is_a?(CanonicalPath) ? metric_type_path : CanonicalPath.parse(metric_type_path)
449
+ feed_id = type_path.feed_id
450
+ res_path = resource_path.is_a?(CanonicalPath) ? resource_path : CanonicalPath.parse(resource_path)
451
+ res_path_str = res_path.resource_ids.join('/')
431
452
 
432
453
  m = {}
433
454
  m['id'] = metric_id
434
455
  m['name'] = metric_name || metric_id
435
- m['metricTypePath'] = type_path
456
+ m['metricTypePath'] = type_path.to_s
436
457
 
437
458
  begin
438
- http_post("/feeds/#{the_feed}/metrics", m)
459
+ http_post("/feeds/#{feed_id}/metrics", m)
439
460
  rescue HawkularException => error
440
461
  # 409 We already exist -> that is ok
441
462
  raise unless error.status_code == 409
442
463
  end
443
464
 
444
- ret = http_get("/feeds/#{the_feed}/metrics/#{metric_id}")
465
+ ret = http_get("/feeds/#{feed_id}/metrics/#{metric_id}")
445
466
  the_metric = Metric.new(ret)
446
467
 
447
468
  begin
448
- http_post("/feeds/#{the_feed}/resources/#{res_path}/metrics", [the_metric.path])
469
+ http_post("/feeds/#{feed_id}/resources/#{res_path_str}/metrics", [the_metric.path])
449
470
  rescue HawkularException => error
450
471
  # 409 We already exist -> that is ok
451
472
  raise unless error.status_code == 409
452
473
  end
453
474
  the_metric
454
475
  end
455
- # rubocop:enable Metrics/CyclomaticComplexity
456
476
 
457
477
  # Listen on inventory changes
458
478
  # @param [String] type Type of entity for which we want the events.
@@ -510,15 +530,17 @@ module Hawkular::Inventory
510
530
  mt
511
531
  end
512
532
 
513
- def should_include?(metric_new, filter)
514
- found = true
515
- if filter.empty?
533
+ def filter_entities(entities, filter)
534
+ entities.select do |entity|
516
535
  found = true
517
- else
518
- found = false unless filter[:type] == (metric_new.type) || filter[:type].nil?
519
- found = false unless filter[:match].nil? || metric_new.id.include?(filter[:match])
536
+ if filter.empty?
537
+ found = true
538
+ else
539
+ found = false unless filter[:type] == (entity.type) || filter[:type].nil?
540
+ found = false unless filter[:match].nil? || entity.id.include?(filter[:match])
541
+ end
542
+ found
520
543
  end
521
- found
522
544
  end
523
545
  end
524
546
 
@@ -558,6 +580,10 @@ module Hawkular::Inventory
558
580
  end
559
581
  end
560
582
 
583
+ def ==(other)
584
+ self.eql?(other) || other.class == self.class && other.id == @id
585
+ end
586
+
561
587
  # Returns a hash representation of the resource type
562
588
  # @return [Hash<String,Object>] hash of the type
563
589
  def to_h
@@ -663,7 +689,6 @@ module Hawkular::Inventory
663
689
  attr_reader :metric_type_id
664
690
 
665
691
  def initialize(hash)
666
- fail 'At least tenant_id must be specified' if hash[:tenant_id].to_s.strip.length == 0
667
692
  @tenant_id = hash[:tenant_id]
668
693
  @feed_id = hash[:feed_id]
669
694
  @environment_id = hash[:environment_id]