rabbitmq_http_api_client 1.15.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f9e2a79489994cac18b3d82cbae44444ad8c9f8336918beac33b2027f9a252e
4
- data.tar.gz: 6ecb5b243fa30f127992fdc1dda6c5b60e69612c2b2bfc0138f3dfb38856e05d
3
+ metadata.gz: 0a39be0a10b8f98fecdccfa407bf150811498cf8739ed6edef8cbf1b88b11bb2
4
+ data.tar.gz: d5898d4b21ceed5c53abffcd251277cfdfd72c90665e4a0ed5f3f72c57578ffd
5
5
  SHA512:
6
- metadata.gz: 6f92d37c3b8aed5323318cb4a1977d23783576e9e0c2a4add3a3dbf56c47f26777b261a8f9b2a8c260c7a5ece1b2ed4a80d99f7eb03d3d2c6d1a423096b6480b
7
- data.tar.gz: 2bf80f3b75c092791b1673823d877b1ce8bb49e118550a7da9931a2dea1b8419c4912b122516c0b95292065566bc3c5fd035702e0ca4a864faa6ab93e59f6365
6
+ metadata.gz: 2684a342bd54fc6fe432772e707f10562696b33b344eff100a2c3c1c0c017088e24eb59b31133e9020dd27698c22bb3f2c15619af411a95d5943eebc6946d9b1
7
+ data.tar.gz: afd8403234f005f8b6f133dcaf8cf203b8bf94fe9c94f6d66f020965a088eae05067f89cbb7c04f02ccaa607d95dc692e9bad82788b378366019e22a9240a389
data/ChangeLog.md CHANGED
@@ -1,7 +1,70 @@
1
- ## Changes Between 1.15.0 and 1.16.0 (unreleased)
1
+ ## Changes Between 2.2.0 and 2.3.0 (unreleased)
2
2
 
3
3
  No changes yet.
4
4
 
5
+
6
+ ## Changes Between 2.1.0 and 2.2.0 (May 19, 2022)
7
+
8
+ Test suite and CI automation changes.
9
+
10
+
11
+ ## Changes Between 2.0.0 and 2.1.0 (February 12, 2022)
12
+
13
+ ### Handle Responses that Do Not Contain a Body
14
+
15
+ GitHub issue: [#52](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/52)
16
+
17
+ ### Support for Management of Topic Permissions
18
+
19
+ Contributed by @bagedevimo.
20
+
21
+ GitHub issue: [#57](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/57)
22
+
23
+ ### Upgraded Faraday Middleware
24
+
25
+ Faraday (a dependency) has been upgraded to `1.2.x` to eliminate some deprecation warnings.
26
+
27
+
28
+ ## Changes Between 1.15.0 and 2.0.0 (May 21, 2021)
29
+
30
+ ### Health Check Endpoint Changes
31
+
32
+ `RabbitMQ::HTTP::Client#aliveness_test` has been removed. The endpoint has been deprecated
33
+ in favor of [more focussed health check endpoints](https://www.rabbitmq.com/monitoring.html#health-checks):
34
+
35
+ ``` ruby
36
+ c = RabbitMQ::HTTP::Client.new("http://username:s3kRe7@localhost:15672")
37
+
38
+ # Returns a pair of [success, details]. Details will be nil
39
+ # if the check succeeds.
40
+ #
41
+ # Checks for any alarms across the cluster
42
+ passed, details = c.health.check_alarms
43
+
44
+ # alarms on the given node
45
+ passed, details = c.health.check_local_alarms
46
+
47
+ # is this node essential for an online quorum of any quorum queues?
48
+ passed, details = c.health.check_if_node_is_quorum_critical
49
+
50
+ # do any certificates used by this node's TLS listeners expire within
51
+ # three months?
52
+ passed, details = c.health.check_certificate_expiration(3, "months")
53
+ ```
54
+
55
+ See the list of methods in `RabbitMQ::HTTP::HealthChecks` to find out what other
56
+ health checks are available.
57
+
58
+ ### User Tags Type Change
59
+
60
+ User tags returned by the `RabbitMQ::HTTP::Client#list_users` and `RabbitMQ::HTTP::Client#user_info`
61
+ methods are now arrays of strings instead of comma-separated strings.
62
+
63
+ Internally the method encodes both command-separated strings and JSON arrays in API responses
64
+ to support response types from RabbitMQ 3.9 and earlier versions.
65
+
66
+ See [rabbitmq/rabbitmq-server#2676](https://github.com/rabbitmq/rabbitmq-server/pull/2676) for details.
67
+
5
68
  ## Changes Between 1.14.0 and 1.15.0 (February 16th, 2021)
6
69
  ### Content Length Detection Changes
7
70
 
@@ -12,6 +75,7 @@ Contributed by Ryan @rquant Quant.
12
75
 
13
76
  GitHub issue: [#49](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/49)
14
77
 
78
+
15
79
  ## Changes Between 1.13.0 and 1.14.0 (July 8th, 2020)
16
80
 
17
81
  ### URI.escape is No Longer Used
data/README.md CHANGED
@@ -23,7 +23,7 @@ and will support more HTTP API features in the future
23
23
 
24
24
  ## Supported RabbitMQ Versions
25
25
 
26
- * RabbitMQ 3.x
26
+ All [supported RabbitMQ release series](https://www.rabbitmq.com/versions.html).
27
27
 
28
28
  All versions require [RabbitMQ Management UI plugin](http://www.rabbitmq.com/management.html) to be installed and enabled.
29
29
 
@@ -32,7 +32,7 @@ All versions require [RabbitMQ Management UI plugin](http://www.rabbitmq.com/man
32
32
  Add this line to your application's Gemfile:
33
33
 
34
34
  ``` ruby
35
- gem 'rabbitmq_http_api_client', '>= 1.13.0'
35
+ gem 'rabbitmq_http_api_client', '>= 2.0.0'
36
36
  ```
37
37
 
38
38
  And then execute:
@@ -0,0 +1,70 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday_middleware"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class HealthChecks
10
+
11
+ def initialize(client)
12
+ @client = client
13
+ @request_helper = @client.request_helper
14
+ @response_helper = @client.response_helper
15
+ end
16
+
17
+ def check_alarms
18
+ health_check_for("health/checks/alarms")
19
+ end
20
+
21
+ def check_local_alarms
22
+ health_check_for("health/checks/local-alarms")
23
+ end
24
+
25
+ def check_virtual_hosts
26
+ health_check_for("health/checks/virtual-hosts")
27
+ end
28
+
29
+ def check_if_node_is_quorum_critical
30
+ health_check_for("health/checks/node-is-quorum-critical")
31
+ end
32
+
33
+ def check_if_node_is_mirror_sync_critical
34
+ health_check_for("health/checks/node-is-mirror-sync-critical")
35
+ end
36
+
37
+ def check_port_listener(port)
38
+ health_check_for("health/checks/port-listener/#{encode_uri_path_segment(port)}")
39
+ end
40
+
41
+ def check_protocol_listener(proto)
42
+ health_check_for("health/checks/protocol-listener/#{encode_uri_path_segment(proto)}")
43
+ end
44
+
45
+ TIME_UNITS = %w(days weeks months years)
46
+
47
+ def check_certificate_expiration(within, unit)
48
+ raise ArgumentError.new("supported time units are #{TIME_UNITS.join(', ')}, given: #{unit}") if !TIME_UNITS.include?(unit)
49
+ raise ArgumentError.new("the number of time units must be a positive integer") if within <= 0
50
+
51
+ health_check_for("health/checks/certificate-expiration/#{@request_helper.encode_uri_path_segment(within)}/#{@request_helper.encode_uri_path_segment(unit)}")
52
+ end
53
+
54
+
55
+ def health_check_for(path)
56
+ begin
57
+ _ = @response_helper.decode_resource(@client.connection.get(path))
58
+ [true, nil]
59
+ rescue Faraday::ServerError => se
60
+ # health check endpoints respond with a 503 if the server fails
61
+ if se.response_status == 503
62
+ [false, @response_helper.decode_response_body(se.response[:body])]
63
+ else
64
+ raise se
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday_middleware"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class RequestHelper
10
+ def encode_uri_path_segment(segment)
11
+ # Correctly escapes spaces, see ruby-amqp/rabbitmq_http_api_client#28.
12
+ #
13
+ # Note that slashes also must be escaped since this is a single URI path segment,
14
+ # not an entire path.
15
+ Addressable::URI.encode_component(segment, Addressable::URI::CharacterClasses::UNRESERVED)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday_middleware"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class ResponseHelper
10
+
11
+ def initialize(client)
12
+ @client = client
13
+ end
14
+
15
+ def decode_resource(response)
16
+ if response.nil? || response.body.empty?
17
+ Hashie::Mash.new
18
+ else
19
+ decode_response_body(response.body)
20
+ end
21
+ end
22
+
23
+ def decode_response_body(body)
24
+ if body.empty?
25
+ Hashie::Mash.new
26
+ else
27
+ Hashie::Mash.new(body)
28
+ end
29
+ end
30
+
31
+ def decode_resource_collection(response)
32
+ collection = response.body.is_a?(Array) ? response.body : response.body.fetch('items')
33
+
34
+ collection.map { |i| Hashie::Mash.new(i) }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,7 +1,7 @@
1
1
  module RabbitMQ
2
2
  module HTTP
3
3
  class Client
4
- VERSION = "1.15.0"
4
+ VERSION = "2.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -5,6 +5,10 @@ require "faraday_middleware"
5
5
  require "multi_json"
6
6
  require "uri"
7
7
 
8
+ require_relative "client/request_helper"
9
+ require_relative "client/response_helper"
10
+ require_relative "client/health_checks"
11
+
8
12
  module RabbitMQ
9
13
  module HTTP
10
14
  class Client
@@ -13,7 +17,8 @@ module RabbitMQ
13
17
  # API
14
18
  #
15
19
 
16
- attr_reader :endpoint
20
+ attr_reader :endpoint, :health
21
+ attr_reader :connection, :request_helper, :response_helper
17
22
 
18
23
  def self.connect(endpoint, options = {})
19
24
  new(endpoint, options)
@@ -23,6 +28,10 @@ module RabbitMQ
23
28
  @endpoint = endpoint
24
29
  @options = options
25
30
 
31
+ @request_helper = RequestHelper.new()
32
+ @response_helper = ResponseHelper.new(self)
33
+ @health = HealthChecks.new(self)
34
+
26
35
  initialize_connection(endpoint, options)
27
36
  end
28
37
 
@@ -114,10 +123,10 @@ module RabbitMQ
114
123
 
115
124
  def declare_exchange(vhost, name, attributes = {})
116
125
  opts = {
117
- :type => "direct",
118
- :auto_delete => false,
119
- :durable => true,
120
- :arguments => {}
126
+ type: "direct",
127
+ auto_delete: false,
128
+ durable: true,
129
+ arguments: {}
121
130
  }.merge(attributes)
122
131
 
123
132
  response = @connection.put("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
@@ -290,14 +299,51 @@ module RabbitMQ
290
299
  decode_resource(@connection.delete("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
291
300
  end
292
301
 
302
+ def list_topic_permissions(vhost = nil, query = {})
303
+ path = if vhost
304
+ "vhosts/#{encode_uri_path_segment(vhost)}/topic-permissions"
305
+ else
306
+ "topic-permissions"
307
+ end
308
+
309
+ decode_resource_collection(@connection.get(path, query))
310
+ end
311
+
312
+ def list_topic_permissions_of(vhost, user)
313
+ path = "topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"
314
+ decode_resource_collection(@connection.get(path))
315
+ end
293
316
 
317
+ def update_topic_permissions_of(vhost, user, attributes)
318
+ response = @connection.put("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
319
+ req.headers['Content-Type'] = "application/json"
320
+ req.body = MultiJson.dump(attributes)
321
+ end
322
+
323
+ nil
324
+ end
325
+
326
+ def delete_topic_permissions_of(vhost, user)
327
+ decode_resource(@connection.delete("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
328
+ end
294
329
 
295
330
  def list_users(query = {})
296
- decode_resource_collection(@connection.get("users", query))
331
+ results = decode_resource_collection(@connection.get("users", query))
332
+
333
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
334
+ results.map do |u|
335
+ u.tags = u.tags.split(",") if u.tags.is_a?(String)
336
+ u
337
+ end
297
338
  end
298
339
 
299
340
  def user_info(name)
300
- decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
341
+ result = decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
342
+
343
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
344
+ result.tags = result.tags.split(",") if result.tags.is_a?(String)
345
+
346
+ result
301
347
  end
302
348
 
303
349
  def update_user(name, attributes)
@@ -389,14 +435,6 @@ module RabbitMQ
389
435
  decode_resource(@connection.delete("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
390
436
  end
391
437
 
392
-
393
-
394
- def aliveness_test(vhost)
395
- r = @connection.get("aliveness-test/#{encode_uri_path_segment(vhost)}")
396
- r.body["status"] == "ok"
397
- end
398
-
399
-
400
438
  protected
401
439
 
402
440
  def initialize_connection(endpoint, options = {})
@@ -408,7 +446,8 @@ module RabbitMQ
408
446
  adapter = options.delete(:adapter) || Faraday.default_adapter
409
447
 
410
448
  @connection = Faraday.new(options) do |conn|
411
- conn.basic_auth user, password
449
+ conn.request :basic_auth, user, password
450
+
412
451
  conn.use FaradayMiddleware::FollowRedirects, :limit => 3
413
452
  conn.use Faraday::Response::RaiseError
414
453
  conn.response :json, :content_type => /\bjson$/
@@ -418,25 +457,19 @@ module RabbitMQ
418
457
  end
419
458
 
420
459
  def encode_uri_path_segment(segment)
421
- # Correctly escapes spaces, see ruby-amqp/rabbitmq_http_api_client#28.
422
- #
423
- # Note that slashes also must be escaped since this is a single URI path segment,
424
- # not an entire path.
425
- Addressable::URI.encode_component(segment, Addressable::URI::CharacterClasses::UNRESERVED)
460
+ @request_helper.encode_uri_path_segment(segment)
426
461
  end
427
462
 
428
463
  def decode_resource(response)
429
- if response.body.empty?
430
- Hashie::Mash.new
431
- else
432
- Hashie::Mash.new(response.body)
433
- end
464
+ @response_helper.decode_resource(response)
434
465
  end
435
466
 
436
- def decode_resource_collection(response)
437
- collection = response.body.is_a?(Array) ? response.body : response.body.fetch('items')
467
+ def decode_response_body(body)
468
+ @response_helper.decode_response_body(body)
469
+ end
438
470
 
439
- collection.map { |i| Hashie::Mash.new(i) }
471
+ def decode_resource_collection(response)
472
+ @response_helper.decode_resource_collection(response)
440
473
  end
441
474
  end # Client
442
475
  end # HTTP
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbitmq_http_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Klishin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-16 00:00:00.000000000 Z
11
+ date: 2022-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.0'
75
+ version: '1.2'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.0'
82
+ version: '1.2'
83
83
  description: RabbitMQ HTTP API client for Ruby
84
84
  email:
85
85
  - michael@clojurewerkz.org
@@ -91,6 +91,9 @@ files:
91
91
  - LICENSE.txt
92
92
  - README.md
93
93
  - lib/rabbitmq/http/client.rb
94
+ - lib/rabbitmq/http/client/health_checks.rb
95
+ - lib/rabbitmq/http/client/request_helper.rb
96
+ - lib/rabbitmq/http/client/response_helper.rb
94
97
  - lib/rabbitmq/http/client/version.rb
95
98
  homepage: http://github.com/ruby-amqp/rabbitmq_http_api_client
96
99
  licenses:
@@ -112,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
115
  - !ruby/object:Gem::Version
113
116
  version: '0'
114
117
  requirements: []
115
- rubygems_version: 3.1.2
118
+ rubygems_version: 3.1.4
116
119
  signing_key:
117
120
  specification_version: 4
118
121
  summary: RabbitMQ HTTP API client for Ruby