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.
@@ -23,7 +23,8 @@ module Hawkular::Metrics
23
23
  # @param starts [Integer] optional timestamp (default now - 8h)
24
24
  # @param ends [Integer] optional timestamp (default now)
25
25
  # @return [Array[Hash]] datapoints
26
- def data_by_tags(tags, buckets: nil, bucketDuration:nil, start:nil, ends: nil)
26
+ def data_by_tags(tags, buckets: nil, bucketDuration: nil, # rubocop:disable Naming/VariableName
27
+ start: nil, ends: nil)
27
28
  data = {
28
29
  tags: tags_param(tags), buckets: buckets, bucketDuration: bucketDuration, start: start, end: ends
29
30
  }
@@ -56,7 +57,7 @@ module Hawkular::Metrics
56
57
  strings.each { |g| default_timestamp g[:data] }
57
58
  data = { gauges: gauges, counters: counters, availabilities: availabilities, strings: strings }
58
59
  path = '/metrics/'
59
- @legacy_api ? path << 'data' : path << 'raw'
60
+ path << (@legacy_api ? 'data' : 'raw')
60
61
  http_post(path, data)
61
62
  end
62
63
 
@@ -84,7 +85,7 @@ module Hawkular::Metrics
84
85
  path = '/metrics/stats/query'
85
86
  metrics = { gauge: gauge_ids, counter: counter_ids, availability: avail_ids }
86
87
  data = { metrics: metrics, start: starts, end: ends, bucketDuration: bucket_duration }
87
- data['types'] = %w(gauge gauge_rate counter counter_rate availability) if rates
88
+ data['types'] = %w[gauge gauge_rate counter counter_rate availability] if rates
88
89
  http_post(path, data)
89
90
  end
90
91
 
@@ -93,9 +94,11 @@ module Hawkular::Metrics
93
94
  def tags
94
95
  tags = []
95
96
  http_get('/metrics/').map do |g|
97
+ next if g['tags'].nil?
98
+
96
99
  g['tags'].map do |k, v|
97
100
  tags << { k => v }
98
- end unless g['tags'].nil?
101
+ end
99
102
  end
100
103
  tags.uniq!
101
104
  end
@@ -171,7 +174,7 @@ module Hawkular::Metrics
171
174
  def push_data(id, data)
172
175
  data = [data] unless data.is_a?(Array)
173
176
  uri = "/#{@resource}/#{ERB::Util.url_encode(id)}/"
174
- @legacy_api ? uri << 'data' : uri << 'raw'
177
+ uri << (@legacy_api ? 'data' : 'raw')
175
178
  @client.default_timestamp data
176
179
  @client.http_post(uri, data)
177
180
  end
@@ -187,8 +190,8 @@ module Hawkular::Metrics
187
190
  # @param order [String] optional Data point sort order, based on timestamp (ASC, DESC)
188
191
  # @return [Array[Hash]] datapoints
189
192
  # @see #push_data #push_data for datapoint detail
190
- def get_data(id, starts: nil, ends: nil, bucketDuration: nil, buckets: nil, percentiles: nil, limit: nil,
191
- order: nil)
193
+ def get_data(id, starts: nil, ends: nil, bucketDuration: nil, # rubocop:disable Naming/VariableName
194
+ buckets: nil, percentiles: nil, limit: nil, order: nil)
192
195
  params = { start: starts, end: ends, bucketDuration: bucketDuration, buckets: buckets,
193
196
  percentiles: percentiles, limit: limit, order: order }
194
197
  get_data_helper(id, params)
@@ -214,28 +217,32 @@ module Hawkular::Metrics
214
217
  # @param buckets [Integer] optional number of buckets
215
218
  # @return [Array[Hash]] datapoints
216
219
  # @see #push_data #push_data for datapoint detail
217
- def get_data_by_tags(tags, starts: nil, ends: nil, bucketDuration: nil, buckets:nil)
220
+ def get_data_by_tags(tags, starts: nil, ends: nil, bucketDuration: nil, # rubocop:disable Naming/VariableName
221
+ buckets: nil)
218
222
  params = { tags: @client.tags_param(tags), start: starts,
219
223
  end: ends, bucketDuration: bucketDuration, buckets: buckets }
220
224
  path = "/#{@resource}/"
221
- @legacy_api ? path << 'data/?' : path << 'stats/?'
225
+ path << (@legacy_api ? 'data/?' : 'stats/?')
222
226
  resp = @client.http_get(path + encode_params(params))
223
227
  resp.is_a?(Array) ? resp : [] # API returns no content (empty Hash) instead of empty array
224
228
  end
225
229
 
226
230
  def encode_params(params)
227
- URI.encode_www_form(params.select { |_k, v| !v.nil? })
231
+ URI.encode_www_form(params.reject { |_k, v| v.nil? })
228
232
  end
229
233
 
230
234
  private
231
235
 
232
236
  def get_data_helper(id, params)
233
237
  path = "/#{@resource}/#{ERB::Util.url_encode(id)}/"
234
- if @legacy_api
235
- path << 'data/?'
236
- else
237
- (params[:bucketDuration].nil? && params[:buckets].nil?) ? path << 'raw/?' : path << 'stats/?'
238
- end
238
+ path << if @legacy_api
239
+ 'data/?'
240
+ elsif params[:bucketDuration].nil? && params[:buckets].nil?
241
+ 'raw/?'
242
+ else
243
+ 'stats/?'
244
+ end
245
+
239
246
  path << encode_params(params)
240
247
  resp = @client.http_get(path)
241
248
  resp.is_a?(Array) ? resp : [] # API returns no content (empty Hash) instead of empty array
@@ -329,8 +336,8 @@ module Hawkular::Metrics
329
336
  # @param order [String] optional Data point sort order, based on timestamp (ASC, DESC)
330
337
  # @return [Array[Hash]] datapoints
331
338
  # @see #push_data #push_data for datapoint detail
332
- def get_data(id, starts: nil, ends: nil, bucketDuration: nil, buckets: nil, distinct: nil, limit: nil,
333
- order: nil)
339
+ def get_data(id, starts: nil, ends: nil, bucketDuration: nil, # rubocop:disable Naming/VariableName
340
+ buckets: nil, distinct: nil, limit: nil, order: nil)
334
341
  params = { start: starts, end: ends, bucketDuration: bucketDuration, buckets: buckets,
335
342
  distinct: distinct, limit: limit, order: order }
336
343
  get_data_helper(id, params)
@@ -35,12 +35,13 @@ module Hawkular::Metrics
35
35
 
36
36
  def check_version
37
37
  version_status_hash = fetch_version_and_status
38
+
38
39
  fail_version_msg = 'Unable to determine implementation version for metrics'
39
- fail fail_version_msg if version_status_hash['Implementation-Version'].nil?
40
+ fail Hawkular::Exception, fail_version_msg if version_status_hash['Implementation-Version'].nil?
40
41
  version = version_status_hash['Implementation-Version']
41
42
  major, minor = version.scan(/\d+/).map(&:to_i)
42
- fail fail_version_msg if major.nil? || minor.nil?
43
- @legacy_api = (major == 0 && minor < 16)
43
+ fail Hawkular::Exception, fail_version_msg if major.nil? || minor.nil?
44
+ @legacy_api = (major.zero? && minor < 16)
44
45
  end
45
46
 
46
47
  # Construct a new Hawkular Metrics client class.
@@ -1,3 +1,6 @@
1
+ require 'timeout'
2
+ require 'monitor'
3
+
1
4
  require 'hawkular/base_client'
2
5
  require 'websocket-client-simple'
3
6
  require 'json'
@@ -13,14 +16,7 @@ class Proc
13
16
  method_name = callable.to_sym
14
17
  define_method(method_name) { |&block| block.nil? ? true : block.call(result) }
15
18
  define_method("#{method_name}?") { true }
16
-
17
- # method_missing is here because we are not forcing the client to provide both success and error callbacks
18
- # rubocop:disable Lint/NestedMethodDefinition
19
- # https://github.com/bbatsov/rubocop/issues/2704
20
- def method_missing(_method_name, *_args, &_block)
21
- PerformMethodMissing
22
- end
23
- # rubocop:enable Lint/NestedMethodDefinition
19
+ define_method(:method_missing) { |*| PerformMethodMissing }
24
20
  end.new)
25
21
  end
26
22
  end
@@ -30,15 +26,42 @@ module Hawkular::Operations
30
26
  # Client class to interact with the agent via websockets
31
27
  class Client < Hawkular::BaseClient
32
28
  include WebSocket::Client
29
+ include MonitorMixin
33
30
 
34
- attr_accessor :ws, :session_id, :logger
31
+ attr_accessor :ws, :logger
35
32
 
36
33
  # helper for parsing the "OperationName=json_payload" messages
37
34
  class WebSocket::Frame::Data
38
35
  def to_msg_hash
39
- chunks = split('=', 2)
36
+ operation_name, json = split('=', 2)
37
+
38
+ # Check if there is a zip file following JSON.
39
+ # This check is done only in the first 100KB, hoping it's unlikely to
40
+ # have such large amount of JSON before a zip file is attached.
41
+ magic_bits = [
42
+ "\x50\x4B\x03\x04", # "PK" + 0x03 + 0x04 = Regular ZIP file
43
+ "\x50\x4B\x05\x06", # "PK" + 0x05 + 0x06 = Empty ZIP
44
+ "\x50\x4B\x07\x08" # "PK" + 0x07 + 0x08 = Spanned ZIP
45
+ ]
46
+ search_chunk = json[0, 102_400]
47
+ zip_file = nil
48
+
49
+ magic_bits.each do |bits|
50
+ idx = search_chunk.index(bits)
51
+
52
+ next unless idx
53
+
54
+ zip_file = json[idx..-1]
55
+ json = json[0, idx]
56
+ break
57
+ end
58
+
59
+ # Parse JSON and, if received, attach zip file
60
+ json = JSON.parse(json)
61
+ json[:attachments] = zip_file
40
62
 
41
- { operationName: chunks[0], data: JSON.parse(chunks[1]) }
63
+ # Return processed data
64
+ { operationName: operation_name, data: json }
42
65
  rescue
43
66
  {}
44
67
  end
@@ -72,72 +95,80 @@ module Hawkular::Operations
72
95
  if args[:entrypoint]
73
96
  uri = URI.parse(args[:entrypoint].to_s)
74
97
  args[:host] = "#{uri.host}:#{uri.port}"
75
- args[:use_secure_connection] = %w(https wss).include?(uri.scheme) ? true : false
98
+ args[:use_secure_connection] = %w[https wss].include?(uri.scheme) ? true : false
76
99
  end
77
100
 
78
- fail 'no parameter ":host" or ":entrypoint" given' if args[:host].nil?
101
+ fail Hawkular::ArgumentError, 'no parameter ":host" or ":entrypoint" given' if args[:host].nil?
79
102
 
80
103
  super(args[:host], args[:credentials], args[:options])
81
104
 
82
- url = "ws#{args[:use_secure_connection] ? 's' : ''}://#{args[:host]}/hawkular/command-gateway/ui/ws"
105
+ @logger = Hawkular::Logger.new
106
+
107
+ @url = "ws#{args[:use_secure_connection] ? 's' : ''}://#{args[:host]}/hawkular/command-gateway/ui/ws"
108
+ @credentials = args[:credentials]
109
+ @tenant = args[:options][:tenant]
110
+ @wait_time = args[:wait_time]
111
+ end
112
+
113
+ def base64_credentials
114
+ ["#{@credentials[:username]}:#{@credentials[:password]}"].pack('m').delete("\r\n")
115
+ end
116
+
117
+ def connect
118
+ return if @connecting || (@ws && @ws.open?)
83
119
 
84
- creds = args[:credentials]
85
- base64_creds = ["#{creds[:username]}:#{creds[:password]}"].pack('m').delete("\r\n")
120
+ @connecting = true
86
121
 
87
122
  ws_options = {
88
123
  headers: {
89
- 'Authorization' => 'Basic ' + base64_creds,
90
- 'Hawkular-Tenant' => args[:options][:tenant],
124
+ 'Authorization' => 'Basic ' + base64_credentials,
125
+ 'Hawkular-Tenant' => @tenant,
91
126
  'Accept' => 'application/json'
92
127
  }
93
128
  }
94
129
 
95
- @logger = Hawkular::Logger.new
96
-
97
- @ws = Simple.connect url, ws_options do |client|
130
+ @ws = Simple.connect @url, ws_options do |client|
98
131
  client.on(:message, once: true) do |msg|
99
132
  parsed_message = msg.data.to_msg_hash
100
133
 
134
+ logger = Hawkular::Logger.new
101
135
  logger.log("Sent WebSocket message: #{parsed_message}")
102
-
103
- case parsed_message[:operationName]
104
- when 'WelcomeResponse'
105
- @session_id = parsed_message[:data]['sessionId']
106
- end
107
136
  end
108
137
  end
109
138
 
110
- sleep args[:wait_time]
139
+ Timeout.timeout(@wait_time) { sleep 0.1 until @ws.open? }
140
+ ensure
141
+ @connecting = false
111
142
  end
112
143
 
113
144
  # Closes the WebSocket connection
114
145
  def close_connection!
115
- @ws.close
146
+ @ws && @ws.close
116
147
  end
117
148
 
118
149
  # Invokes a generic operation on the WildFly agent
119
150
  # (the operation name must be specified in the hash)
120
151
  # Note: if success and failure callbacks are omitted, the client will not wait for the Response message
121
- # @param hash [Hash{String=>Object}] a hash containing: resourcePath [String] denoting the resource on
122
- # which the operation is about to run, operationName [String]
152
+ # @param hash [Hash{String=>Object}] a hash containing: resourceId [String] denoting the resource on
153
+ # which the operation is about to run, feedId [String], operationName [String]
123
154
  # @param callback [Block] callback that is run after the operation is done
124
155
  def invoke_generic_operation(hash, &callback)
125
- required = [:resourcePath, :operationName]
156
+ required = %i[resourceId feedId operationName]
126
157
  check_pre_conditions hash, required, &callback
127
158
 
128
159
  invoke_operation_helper(hash, &callback)
129
160
  end
130
161
 
131
162
  # Invokes operation on the WildFly agent that has it's own message type
132
- # @param operation_payload [Hash{String=>Object}] a hash containing: resourcePath [String] denoting
133
- # the resource on which the operation is about to run
163
+ # @param operation_payload [Hash{String=>Object}] a hash containing: resourceId [String] denoting
164
+ # the resource on which the operation is about to run, feedId [String]
134
165
  # @param operation_name [String] the name of the operation. This must correspond with the message type, they can be
135
166
  # found here https://git.io/v2h1a (Use only the first part of the name without the Request/Response suffix), e.g.
136
167
  # RemoveDatasource (and not RemoveDatasourceRequest)
137
168
  # @param callback [Block] callback that is run after the operation is done
138
169
  def invoke_specific_operation(operation_payload, operation_name, &callback)
139
- fail 'Operation must be specified' if operation_name.nil?
140
- required = [:resourcePath]
170
+ fail Hawkular::ArgumentError, 'Operation must be specified' if operation_name.nil?
171
+ required = %i[resourceId feedId]
141
172
  check_pre_conditions operation_payload, required, &callback
142
173
 
143
174
  invoke_operation_helper(operation_payload, operation_name, &callback)
@@ -146,8 +177,9 @@ module Hawkular::Operations
146
177
  # Deploys an archive file into WildFly
147
178
  #
148
179
  # @param [Hash] hash Arguments for deployment
149
- # @option hash [String] :resource_path canonical path of the WildFly server into which we deploy
180
+ # @option hash [String] :resource_id ID of the WildFly server into which we deploy
150
181
  # or of the domain controller if we deploy into a server group (in case of domain mode)
182
+ # @option hash [String] :feed_id feed containing this resource
151
183
  # @option hash [String] :destination_file_name resulting file name
152
184
  # @option hash [String] :binary_content binary content representing the war file
153
185
  # @option hash [String] :enabled whether the deployment should be enabled immediately, or not (default = true)
@@ -158,7 +190,7 @@ module Hawkular::Operations
158
190
  def add_deployment(hash, &callback)
159
191
  hash[:enabled] = hash.key?(:enabled) ? hash[:enabled] : true
160
192
  hash[:force_deploy] = hash.key?(:force_deploy) ? hash[:force_deploy] : false
161
- required = [:resource_path, :destination_file_name, :binary_content]
193
+ required = %i[resource_id feed_id destination_file_name binary_content]
162
194
  check_pre_conditions hash, required, &callback
163
195
 
164
196
  operation_payload = prepare_payload_hash([:binary_content], hash)
@@ -168,7 +200,8 @@ module Hawkular::Operations
168
200
  # Undeploy a WildFly deployment
169
201
  #
170
202
  # @param [Hash] hash Arguments for deployment removal
171
- # @option hash [String] :resource_path canonical path of the WildFly server from which to undeploy the deployment
203
+ # @option hash [String] :resource_id ID of the WildFly server from which to undeploy the deployment
204
+ # @option hash [String] :feed_id feed containing this resource
172
205
  # @option hash [String] :deployment_name name of deployment to undeploy
173
206
  # @option hash [String] :remove_content whether to remove the deployment content or not (default = true)
174
207
  # @option hash [String] :server_groups comma-separated list of server groups for the operation (default = ignored)
@@ -176,12 +209,9 @@ module Hawkular::Operations
176
209
  # @param callback [Block] callback that is run after the operation is done
177
210
  def undeploy(hash, &callback)
178
211
  hash[:remove_content] = hash.key?(:remove_content) ? hash[:remove_content] : true
179
- required = [:resource_path, :deployment_name]
212
+ required = %i[resource_id feed_id deployment_name]
180
213
  check_pre_conditions hash, required, &callback
181
214
 
182
- cp = ::Hawkular::Inventory::CanonicalPath.parse hash[:resource_path]
183
- server_path = cp.up.to_s
184
- hash[:resource_path] = server_path
185
215
  hash[:destination_file_name] = hash[:deployment_name]
186
216
 
187
217
  operation_payload = prepare_payload_hash([:deployment_name], hash)
@@ -191,18 +221,16 @@ module Hawkular::Operations
191
221
  # Enable a WildFly deployment
192
222
  #
193
223
  # @param [Hash] hash Arguments for enable deployment
194
- # @option hash [String] :resource_path canonical path of the WildFly server from which to enable the deployment
224
+ # @option hash [String] :resource_id ID of the WildFly server from which to enable the deployment
225
+ # @option hash [String] :feed_id feed containing this resource
195
226
  # @option hash [String] :deployment_name name of deployment to enable
196
227
  # @option hash [String] :server_groups comma-separated list of server groups for the operation (default = ignored)
197
228
  #
198
229
  # @param callback [Block] callback that is run after the operation is done
199
230
  def enable_deployment(hash, &callback)
200
- required = [:resource_path, :deployment_name]
231
+ required = %i[resource_id feed_id deployment_name]
201
232
  check_pre_conditions hash, required, &callback
202
233
 
203
- cp = ::Hawkular::Inventory::CanonicalPath.parse hash[:resource_path]
204
- server_path = cp.up.to_s
205
- hash[:resource_path] = server_path
206
234
  hash[:destination_file_name] = hash[:deployment_name]
207
235
 
208
236
  operation_payload = prepare_payload_hash([:deployment_name], hash)
@@ -212,18 +240,16 @@ module Hawkular::Operations
212
240
  # Disable a WildFly deployment
213
241
  #
214
242
  # @param [Hash] hash Arguments for disable deployment
215
- # @option hash [String] :resource_path canonical path of the WildFly server from which to disable the deployment
243
+ # @option hash [String] :resource_id ID of the WildFly server from which to disable the deployment
244
+ # @option hash [String] :feed_id feed containing this resource
216
245
  # @option hash [String] :deployment_name name of deployment to disable
217
246
  # @option hash [String] :server_groups comma-separated list of server groups for the operation (default = ignored)
218
247
  #
219
248
  # @param callback [Block] callback that is run after the operation is done
220
249
  def disable_deployment(hash, &callback)
221
- required = [:resource_path, :deployment_name]
250
+ required = %i[resource_id feed_id deployment_name]
222
251
  check_pre_conditions hash, required, &callback
223
252
 
224
- cp = ::Hawkular::Inventory::CanonicalPath.parse hash[:resource_path]
225
- server_path = cp.up.to_s
226
- hash[:resource_path] = server_path
227
253
  hash[:destination_file_name] = hash[:deployment_name]
228
254
 
229
255
  operation_payload = prepare_payload_hash([:deployment_name], hash)
@@ -233,18 +259,16 @@ module Hawkular::Operations
233
259
  # Restart a WildFly deployment
234
260
  #
235
261
  # @param [Hash] hash Arguments for restart deployment
236
- # @option hash [String] :resource_path canonical path of the WildFly server from which to restart the deployment
262
+ # @option hash [String] :resource_id ID of the WildFly server from which to restart the deployment
263
+ # @option hash [String] :feed_id feed containing this resource
237
264
  # @option hash [String] :deployment_name name of deployment to restart
238
265
  # @option hash [String] :server_groups comma-separated list of server groups for the operation (default = ignored)
239
266
  #
240
267
  # @param callback [Block] callback that is run after the operation is done
241
268
  def restart_deployment(hash, &callback)
242
- required = [:resource_path, :deployment_name]
269
+ required = %i[resource_id feed_id deployment_name]
243
270
  check_pre_conditions hash, required, &callback
244
271
 
245
- cp = ::Hawkular::Inventory::CanonicalPath.parse hash[:resource_path]
246
- server_path = cp.up.to_s
247
- hash[:resource_path] = server_path
248
272
  hash[:destination_file_name] = hash[:deployment_name]
249
273
 
250
274
  operation_payload = prepare_payload_hash([:deployment_name], hash)
@@ -254,7 +278,8 @@ module Hawkular::Operations
254
278
  # Adds a new datasource
255
279
  #
256
280
  # @param [Hash] hash Arguments for the datasource
257
- # @option hash [String] :resourcePath canonical path of the WildFly server into which we add datasource
281
+ # @option hash [String] :resourceId ID of the WildFly server into which we add datasource
282
+ # @option hash [String] :feedId ID of the feed containing the WildFly server
258
283
  # @option hash [String] :xaDatasource XA DS or normal
259
284
  # @option hash [String] :datasourceName name of the datasource
260
285
  # @option hash [String] :jndiName JNDI name
@@ -267,7 +292,8 @@ module Hawkular::Operations
267
292
  #
268
293
  # @param callback [Block] callback that is run after the operation is done
269
294
  def add_datasource(hash, &callback)
270
- required = [:resourcePath, :xaDatasource, :datasourceName, :jndiName, :driverName, :driverClass, :connectionUrl]
295
+ required = %i[resourceId feedId xaDatasource datasourceName jndiName
296
+ driverName driverClass connectionUrl]
271
297
  check_pre_conditions hash, required, &callback
272
298
 
273
299
  invoke_specific_operation(hash, 'AddDatasource', &callback)
@@ -276,7 +302,8 @@ module Hawkular::Operations
276
302
  # Adds a new datasource
277
303
  #
278
304
  # @param [Hash] hash Arguments for the datasource
279
- # @option hash [String] :resource_path canonical path of the WildFly server into which we add driver
305
+ # @option hash [String] :resource_id ID of the WildFly server into which we add driver
306
+ # @option hash [String] :feed_id ID of the feed containing the WildFly server
280
307
  # @option hash [String] :driver_jar_name name of the jar file
281
308
  # @option hash [String] :driver_name name of the jdbc driver (when adding datasource, this is the driverName)
282
309
  # @option hash [String] :module_name name of the JBoss module into which the driver will be installed - 'foo.bar'
@@ -285,7 +312,8 @@ module Hawkular::Operations
285
312
  #
286
313
  # @param callback [Block] callback that is run after the operation is done
287
314
  def add_jdbc_driver(hash, &callback)
288
- required = [:resource_path, :driver_jar_name, :driver_name, :module_name, :driver_class, :binary_content]
315
+ required = %i[resource_id feed_id driver_jar_name driver_name module_name
316
+ driver_class binary_content]
289
317
  check_pre_conditions hash, required, &callback
290
318
 
291
319
  operation_payload = prepare_payload_hash([:binary_content], hash)
@@ -294,19 +322,28 @@ module Hawkular::Operations
294
322
 
295
323
  # Exports the JDR report
296
324
  #
297
- # @param [String] resource_path canonical path of the WildFly server
325
+ # @param [String] resource_id ID of the WildFly server
326
+ # @param [String] feed_id ID of the feed containing the WildFly server
327
+ # @param [Boolean] delete_immediately specifies whether the temporary file at the remote
328
+ # server should be deleted. False, by default.
298
329
  # @param callback [Block] callback that is run after the operation is done
299
- def export_jdr(resource_path, &callback)
300
- fail 'resource_path must be specified' if resource_path.nil?
330
+ def export_jdr(resource_id, feed_id, delete_immediately = false, sender_request_id = nil, &callback)
331
+ fail Hawkular::ArgumentError, 'resource_id must be specified' if resource_id.nil?
332
+ fail Hawkular::ArgumentError, 'feed_id must be specified' if feed_id.nil?
301
333
  check_pre_conditions(&callback)
302
334
 
303
- invoke_specific_operation({ resourcePath: resource_path }, 'ExportJdr', &callback)
335
+ invoke_specific_operation({ resourceId: resource_id,
336
+ feedId: feed_id,
337
+ deleteImmediately: delete_immediately,
338
+ senderRequestId: sender_request_id },
339
+ 'ExportJdr', &callback)
304
340
  end
305
341
 
306
342
  # Updates the collection intervals.
307
343
  #
308
344
  # @param [Hash] hash Arguments for update collection intervals
309
- # @option hash {resourcePath} a resource managed by the target agent
345
+ # @option hash {resourceId} a resource managed by the target agent
346
+ # @option hash {feedId} the related feed ID
310
347
  # @option hash {metricTypes} A map with key=MetricTypeId, value=interval (seconds).
311
348
  # MetricTypeId must be of form MetricTypeSet~MetricTypeName
312
349
  # @option hash {availTypes} A map with key=AvailTypeId, value=interval (seconds).
@@ -314,7 +351,7 @@ module Hawkular::Operations
314
351
  #
315
352
  # @param callback [Block] callback that is run after the operation is done
316
353
  def update_collection_intervals(hash, &callback)
317
- required = [:resourcePath, :metricTypes, :availTypes]
354
+ required = %i[resourceId feedId metricTypes availTypes]
318
355
  check_pre_conditions hash, required, &callback
319
356
  invoke_specific_operation(hash, 'UpdateCollectionIntervals', &callback)
320
357
  end
@@ -322,29 +359,38 @@ module Hawkular::Operations
322
359
  private
323
360
 
324
361
  def invoke_operation_helper(operation_payload, operation_name = nil, binary_content = nil, &callback)
362
+ synchronize { connect }
363
+
325
364
  # fallback to generic 'ExecuteOperation' if nothing is specified
326
365
  operation_name ||= 'ExecuteOperation'
327
366
  add_credentials! operation_payload
328
367
 
368
+ # if unset, set the :senderRequestId
369
+ operation_payload[:senderRequestId] = SecureRandom.uuid unless operation_payload[:senderRequestId]
370
+
329
371
  handle_message(operation_name, operation_payload, &callback) unless callback.nil?
330
372
 
331
373
  # sends a message that will actually run the operation
332
374
  payload = "#{operation_name}Request=#{operation_payload.to_json}"
333
375
  payload += binary_content unless binary_content.nil?
334
376
  @ws.send payload, type: binary_content.nil? ? :text : :binary
377
+ rescue => e
378
+ callback.perform(:failure, "#{e.class} - #{e.message}")
335
379
  end
336
380
 
337
381
  def check_pre_conditions(hash = {}, params = [], &callback)
338
- fail 'Handshake with server has not been done.' unless @ws.open?
339
- fail 'Hash cannot be nil.' if hash.nil?
340
- fail 'callback must have the perform method defined. include Hawkular::Operations' unless
382
+ fail Hawkular::ArgumentError, 'Hash cannot be nil.' if hash.nil?
383
+ fail Hawkular::ArgumentError, 'callback must have the perform method defined. include Hawkular::Operations' unless
341
384
  callback.nil? || callback.respond_to?('perform')
385
+
342
386
  params.each do |property|
343
387
  next unless hash[property].nil?
344
388
  err_callback = 'You need to specify error callback'
345
389
  err_message = "Hash property #{property} must be specified"
346
- fail(ArgumentError, err_callback) if callback.nil?
347
- fail(ArgumentError, err_callback) if callback.perform(:failure, err_message).equal? Proc::PerformMethodMissing
390
+
391
+ if !callback || callback.perform(:failure, err_message) == Proc::PerformMethodMissing
392
+ fail(Hawkular::ArgumentError, err_callback)
393
+ end
348
394
  end
349
395
  end
350
396
 
@@ -363,12 +409,8 @@ module Hawkular::Operations
363
409
 
364
410
  case parsed[:operationName]
365
411
  when "#{operation_name}Response"
366
- same_path = parsed[:data]['resourcePath'] == operation_payload[:resourcePath]
367
- # failed operations don't return the operation name from some strange reason
368
- same_name = operation_payload[:operationName].nil? ||
369
- parsed[:data]['operationName'] == operation_payload[:operationName].to_s
370
- if same_path # using the resource path as a correlation id
371
- success = same_name && parsed[:data]['status'] == 'OK'
412
+ if parsed[:data]['senderRequestId'] == operation_payload[:senderRequestId]
413
+ success = parsed[:data]['status'] == 'OK'
372
414
  success ? callback.perform(:success, parsed[:data]) : callback.perform(:failure, parsed[:data]['message'])
373
415
  client.remove_listener :message
374
416
  end
@@ -382,15 +424,18 @@ module Hawkular::Operations
382
424
  def self.handle_error(parsed_message, &callback)
383
425
  callback.perform(:failure, parsed_message == {} ? 'error' : parsed_message[:data]['errorMessage'])
384
426
  end
427
+ private_class_method :handle_error
385
428
 
386
429
  def prepare_payload_hash(ignored_params, hash)
387
430
  # it filters out ignored params and convert keys from snake_case to camelCase
388
- Hash[hash.select { |k, _| !ignored_params.include? k }.map { |k, v| [to_camel_case(k.to_s).to_sym, v] }]
431
+ Hash[hash.reject { |k, _| ignored_params.include? k }.map { |k, v| [to_camel_case(k.to_s).to_sym, v] }]
389
432
  end
390
433
 
391
434
  def to_camel_case(str)
392
- ret = str.split('_').collect(&:capitalize).join
393
- ret[0, 1].downcase + ret[1..-1]
435
+ subs = str.split('_')
436
+ ret = subs.length > 1 ? subs.collect(&:capitalize).join : subs[0]
437
+ ret[0] = ret[0].downcase
438
+ ret
394
439
  end
395
440
  end
396
441
  end