rabbitmq_http_api_client 1.15.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f9e2a79489994cac18b3d82cbae44444ad8c9f8336918beac33b2027f9a252e
4
- data.tar.gz: 6ecb5b243fa30f127992fdc1dda6c5b60e69612c2b2bfc0138f3dfb38856e05d
3
+ metadata.gz: b9fe9cd3da39f8ad9d88cab48895b67278e5df0e5df8f5a397660bc6c73af671
4
+ data.tar.gz: cd233d873f713a5ec50a751a8a58992920f3f03761c8f18b313207febf57acb3
5
5
  SHA512:
6
- metadata.gz: 6f92d37c3b8aed5323318cb4a1977d23783576e9e0c2a4add3a3dbf56c47f26777b261a8f9b2a8c260c7a5ece1b2ed4a80d99f7eb03d3d2c6d1a423096b6480b
7
- data.tar.gz: 2bf80f3b75c092791b1673823d877b1ce8bb49e118550a7da9931a2dea1b8419c4912b122516c0b95292065566bc3c5fd035702e0ca4a864faa6ab93e59f6365
6
+ metadata.gz: a72745520c25dfbc6f5133dc6978b2ff4739ec3f8f56c4e344497a75f9716f7930d1c17fbf93f07a4e544818567d987f5d795ec2ede94e191a030627b2cb835a
7
+ data.tar.gz: 53c18efe60eec7b84f3e0738e6d7e04b76a796cdf6a15746fb9574cbf7becb5a379891fff9a9a8d88475df3e2bf619aa7d227ec6de872e37a5acaa66ba00152a
data/ChangeLog.md CHANGED
@@ -1,6 +1,89 @@
1
- ## Changes Between 1.15.0 and 1.16.0 (unreleased)
1
+ ## Changes Between 2.2.0 and 3.0.0 (July 20, 2024)
2
2
 
3
- No changes yet.
3
+ ### Why the Major Version Bump?
4
+
5
+ This release adopts a new major version of Faraday and targets
6
+ only [community supported RabbitMQ versions](https://www.rabbitmq.com/release-information),
7
+ which at this time means `3.13.x`.
8
+
9
+ While there are no major breaking changes in the library itself,
10
+ these two changes and more than two years that have passed since 2.0.0
11
+ warrant a major version bump.
12
+
13
+ ### Support for Faraday 2.x
14
+
15
+ Contributed by @shashankmehra.
16
+
17
+ GitHub issue: [#63](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/63)
18
+
19
+ ### Queue Deletion: Support for if-unused and if-empty
20
+
21
+ Contributed by @shashankmehra.
22
+
23
+ GitHub issue: [#62](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/62)
24
+
25
+
26
+ ## Changes Between 2.1.0 and 2.2.0 (May 19, 2022)
27
+
28
+ Test suite and CI automation changes.
29
+
30
+
31
+ ## Changes Between 2.0.0 and 2.1.0 (February 12, 2022)
32
+
33
+ ### Handle Responses that Do Not Contain a Body
34
+
35
+ GitHub issue: [#52](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/52)
36
+
37
+ ### Support for Management of Topic Permissions
38
+
39
+ Contributed by @bagedevimo.
40
+
41
+ GitHub issue: [#57](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/57)
42
+
43
+ ### Upgraded Faraday Middleware
44
+
45
+ Faraday (a dependency) has been upgraded to `1.2.x` to eliminate some deprecation warnings.
46
+
47
+
48
+ ## Changes Between 1.15.0 and 2.0.0 (May 21, 2021)
49
+
50
+ ### Health Check Endpoint Changes
51
+
52
+ `RabbitMQ::HTTP::Client#aliveness_test` has been removed. The endpoint has been deprecated
53
+ in favor of [more focussed health check endpoints](https://www.rabbitmq.com/monitoring.html#health-checks):
54
+
55
+ ``` ruby
56
+ c = RabbitMQ::HTTP::Client.new("http://username:s3kRe7@localhost:15672")
57
+
58
+ # Returns a pair of [success, details]. Details will be nil
59
+ # if the check succeeds.
60
+ #
61
+ # Checks for any alarms across the cluster
62
+ passed, details = c.health.check_alarms
63
+
64
+ # alarms on the given node
65
+ passed, details = c.health.check_local_alarms
66
+
67
+ # is this node essential for an online quorum of any quorum queues?
68
+ passed, details = c.health.check_if_node_is_quorum_critical
69
+
70
+ # do any certificates used by this node's TLS listeners expire within
71
+ # three months?
72
+ passed, details = c.health.check_certificate_expiration(3, "months")
73
+ ```
74
+
75
+ See the list of methods in `RabbitMQ::HTTP::HealthChecks` to find out what other
76
+ health checks are available.
77
+
78
+ ### User Tags Type Change
79
+
80
+ User tags returned by the `RabbitMQ::HTTP::Client#list_users` and `RabbitMQ::HTTP::Client#user_info`
81
+ methods are now arrays of strings instead of comma-separated strings.
82
+
83
+ Internally the method encodes both command-separated strings and JSON arrays in API responses
84
+ to support response types from RabbitMQ 3.9 and earlier versions.
85
+
86
+ See [rabbitmq/rabbitmq-server#2676](https://github.com/rabbitmq/rabbitmq-server/pull/2676) for details.
4
87
 
5
88
  ## Changes Between 1.14.0 and 1.15.0 (February 16th, 2021)
6
89
  ### Content Length Detection Changes
@@ -12,6 +95,7 @@ Contributed by Ryan @rquant Quant.
12
95
 
13
96
  GitHub issue: [#49](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/49)
14
97
 
98
+
15
99
  ## Changes Between 1.13.0 and 1.14.0 (July 8th, 2020)
16
100
 
17
101
  ### URI.escape is No Longer Used
data/README.md CHANGED
@@ -18,12 +18,12 @@ and will support more HTTP API features in the future
18
18
 
19
19
  ## Supported Ruby Versions
20
20
 
21
- * CRuby 2.2 through 2.7.x
21
+ * CRuby 2.5 through 3.x
22
22
  * JRuby 9K
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.2.0'
36
36
  ```
37
37
 
38
38
  And then execute:
@@ -116,7 +116,6 @@ h = client.overview
116
116
  # List cluster nodes with detailed status info for each one of them
117
117
  nodes = client.list_nodes
118
118
  n = nodes.first
119
- puts n.sockets_used
120
119
  puts n.mem_used
121
120
  puts n.run_queue
122
121
 
@@ -347,8 +346,21 @@ ps = client.clear_permissions_of("/", "guest")
347
346
 
348
347
  ## Running Tests
349
348
 
350
- bundle install
351
- bundle exec rspec -cfd spec
349
+ Before running the test suites, run a script that will set up the local node:
350
+
351
+ ``` shell
352
+ export RUBY_RABBITMQ_HTTP_API_CLIENT_RABBITMQCTL="rabbitmqctl"
353
+ export RUBY_RABBITMQ_HTTP_API_CLIENT_RABBITMQ_PLUGINS="rabbitmq-plugins"
354
+
355
+ ./bin/ci/before_build.sh
356
+ ```
357
+
358
+ To run all specs:
359
+
360
+ ``` shell
361
+ bundle install
362
+ bundle exec rspec -cfd spec
363
+ ```
352
364
 
353
365
  The test suite assumes that RabbitMQ is running locally with stock settings
354
366
  and rabbitmq-management plugin enabled.
@@ -0,0 +1,70 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday/follow_redirects"
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/follow_redirects"
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,44 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday/follow_redirects"
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.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 do |i|
35
+ if i == []
36
+ Hashie::Mash.new()
37
+ else
38
+ Hashie::Mash.new(i)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,7 @@
1
1
  module RabbitMQ
2
2
  module HTTP
3
3
  class Client
4
- VERSION = "1.15.0"
4
+ VERSION = "3.0.0"
5
5
  end
6
6
  end
7
7
  end
@@ -1,10 +1,14 @@
1
1
  require "addressable/uri"
2
2
  require "hashie"
3
3
  require "faraday"
4
- require "faraday_middleware"
4
+ require "faraday/follow_redirects"
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|
@@ -168,8 +177,12 @@ module RabbitMQ
168
177
  decode_resource(response)
169
178
  end
170
179
 
171
- def delete_queue(vhost, name)
172
- decode_resource(@connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
180
+ def delete_queue(vhost, name, if_unused = false, if_empty = false)
181
+ response = @connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
182
+ req.params["if-unused"] = true if if_unused
183
+ req.params["if-empty"] = true if if_empty
184
+ end
185
+ decode_resource(response)
173
186
  end
174
187
 
175
188
  def list_queue_bindings(vhost, queue, query = {})
@@ -290,14 +303,51 @@ module RabbitMQ
290
303
  decode_resource(@connection.delete("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
291
304
  end
292
305
 
306
+ def list_topic_permissions(vhost = nil, query = {})
307
+ path = if vhost
308
+ "vhosts/#{encode_uri_path_segment(vhost)}/topic-permissions"
309
+ else
310
+ "topic-permissions"
311
+ end
312
+
313
+ decode_resource_collection(@connection.get(path, query))
314
+ end
315
+
316
+ def list_topic_permissions_of(vhost, user)
317
+ path = "topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"
318
+ decode_resource_collection(@connection.get(path))
319
+ end
320
+
321
+ def update_topic_permissions_of(vhost, user, attributes)
322
+ response = @connection.put("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
323
+ req.headers['Content-Type'] = "application/json"
324
+ req.body = MultiJson.dump(attributes)
325
+ end
326
+
327
+ nil
328
+ end
293
329
 
330
+ def delete_topic_permissions_of(vhost, user)
331
+ decode_resource(@connection.delete("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
332
+ end
294
333
 
295
334
  def list_users(query = {})
296
- decode_resource_collection(@connection.get("users", query))
335
+ results = decode_resource_collection(@connection.get("users", query))
336
+
337
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
338
+ results.map do |u|
339
+ u.tags = u.tags.split(",") if u.tags.is_a?(String)
340
+ u
341
+ end
297
342
  end
298
343
 
299
344
  def user_info(name)
300
- decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
345
+ result = decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
346
+
347
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
348
+ result.tags = result.tags.split(",") if result.tags.is_a?(String)
349
+
350
+ result
301
351
  end
302
352
 
303
353
  def update_user(name, attributes)
@@ -389,14 +439,6 @@ module RabbitMQ
389
439
  decode_resource(@connection.delete("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
390
440
  end
391
441
 
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
442
  protected
401
443
 
402
444
  def initialize_connection(endpoint, options = {})
@@ -405,11 +447,12 @@ module RabbitMQ
405
447
  user = uri.user || options.delete(:username) || "guest"
406
448
  password = uri.password || options.delete(:password) || "guest"
407
449
  options = options.merge(:url => uri.to_s)
408
- adapter = options.delete(:adapter) || Faraday.default_adapter
450
+ adapter = options.delete(:adapter) || Faraday.default_adapter || :httpclient
409
451
 
410
452
  @connection = Faraday.new(options) do |conn|
411
- conn.basic_auth user, password
412
- conn.use FaradayMiddleware::FollowRedirects, :limit => 3
453
+ conn.request :authorization, :basic, user, password
454
+
455
+ conn.use Faraday::FollowRedirects::Middleware, :limit => 3
413
456
  conn.use Faraday::Response::RaiseError
414
457
  conn.response :json, :content_type => /\bjson$/
415
458
 
@@ -418,25 +461,19 @@ module RabbitMQ
418
461
  end
419
462
 
420
463
  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)
464
+ @request_helper.encode_uri_path_segment(segment)
426
465
  end
427
466
 
428
467
  def decode_resource(response)
429
- if response.body.empty?
430
- Hashie::Mash.new
431
- else
432
- Hashie::Mash.new(response.body)
433
- end
468
+ @response_helper.decode_resource(response)
434
469
  end
435
470
 
436
- def decode_resource_collection(response)
437
- collection = response.body.is_a?(Array) ? response.body : response.body.fetch('items')
471
+ def decode_response_body(body)
472
+ @response_helper.decode_response_body(body)
473
+ end
438
474
 
439
- collection.map { |i| Hashie::Mash.new(i) }
475
+ def decode_resource_collection(response)
476
+ @response_helper.decode_resource_collection(response)
440
477
  end
441
478
  end # Client
442
479
  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: 3.0.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: 2024-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.3'
61
+ version: '2.9'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.3'
68
+ version: '2.9'
69
69
  - !ruby/object:Gem::Dependency
70
- name: faraday_middleware
70
+ name: faraday-follow_redirects
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.0'
75
+ version: '0.3'
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: '0.3'
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.5.9
116
119
  signing_key:
117
120
  specification_version: 4
118
121
  summary: RabbitMQ HTTP API client for Ruby