Skip to content

Commit

Permalink
add: bindings endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
rhblind committed Dec 17, 2024
1 parent db27885 commit 3e50567
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Read the full documentation [here](https://hexdocs.pm/ex_rabbitmq_admin/readme.h
- [x] Virtual host endpoints
- [x] Queue endpoints
- [x] Exchange endpoints
- [ ] Bindings endpoints
- [x] Bindings endpoints
- [ ] Parameters
- [ ] Policies endpoints
- [ ] Operator endpoints
Expand Down
119 changes: 119 additions & 0 deletions lib/ex_rabbitmq_admin/binding.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
defmodule ExRabbitMQAdmin.Binding do
@moduledoc """
RabbitMQ Bindings.
"""
import ExRabbitMQAdmin.Options,
only: [
create_exchange_binding_definition: 0,
format_error: 1
]

@api_namespace "/api/bindings"

@doc """
List all bindings on the RabbitMQ cluster.
"""
@spec list_bindings(client :: Tesla.Client.t()) :: {:ok, Tesla.Env.t()} | {:error, term()}
def list_bindings(client), do: Tesla.get(client, @api_namespace)

@doc """
List all bindings in a given virtual host.
### Params
* `client` - Tesla client used to perform the request.
* `vhost` - type: `string`, required: `true`
"""
@spec list_vhost_bindings(client :: Tesla.Client.t(), vhost :: String.t()) ::
{:ok, Tesla.Env.t()} | {:error, term()}
def list_vhost_bindings(client, vhost), do: Tesla.get(client, "#{@api_namespace}/#{vhost}")

@doc """
List all bindings between an exchange and a queue in a given virtual host.
"""
@spec list_exchange_queue_bindings(
client :: Tesla.Client.t(),
vhost :: String.t(),
exchange :: String.t(),
queue :: String.t()
) :: {:ok, Tesla.Env.t()} | {:error, term()}
def list_exchange_queue_bindings(client, vhost, exchange, queue),
do: Tesla.get(client, "#{@api_namespace}/#{vhost}/e/#{exchange}/q/#{queue}")

@doc """
Create a binding between an exchange and a queue in a given virtual host.
### Params
* `client` - Tesla client used to perform the request.
* `vhost` - type: `string`, required: `true`
* `exchange` - type: `string`, required: `true`
* `queue` - type: `string`, required: `true`
#{NimbleOptions.docs(create_exchange_binding_definition())}
The response will contain a `Location` header with the URI of the newly created binding.
"""
@spec create_exchange_queue_binding(
client :: Tesla.Client.t(),
vhost :: String.t(),
exchange :: String.t(),
queue :: String.t(),
opts :: Keyword.t()
) :: {:ok, Tesla.Env.t()} | no_return()
def create_exchange_queue_binding(client, vhost, exchange, queue, opts) do
case NimbleOptions.validate(opts, create_exchange_binding_definition()) do
{:error, error} ->
raise ArgumentError, format_error(error)

{:ok, params} ->
client
|> Tesla.post(
"#{@api_namespace}/#{vhost}/e/#{exchange}/q/#{queue}",
Enum.into(params, %{})
)
end
end

@doc """
List all bindings between two exchanges in a given virtual host.
"""
@spec list_exchange_exchange_bindings(
client :: Tesla.Client.t(),
vhost :: String.t(),
src :: String.t(),
dest :: String.t()
) :: {:ok, Tesla.Env.t()} | {:error, term()}
def list_exchange_exchange_bindings(client, vhost, src, dest),
do: Tesla.get(client, "#{@api_namespace}/#{vhost}/e/#{src}/e/#{dest}")

@doc """
Create a binding between two exchanges in a given virtual host.
### Params
* `client` - Tesla client used to perform the request.
* `vhost` - type: `string`, required: `true`
* `src` - type: `string`, required: `true`
* `dest` - type: `string`, required: `true`
#{NimbleOptions.docs(create_exchange_binding_definition())}
The response will contain a `Location` header with the URI of the newly created binding.
"""
@spec create_exchange_exchange_binding(
client :: Tesla.Client.t(),
vhost :: String.t(),
src :: String.t(),
dest :: String.t(),
opts :: Keyword.t()
) :: {:ok, Tesla.Env.t()} | no_return()
def create_exchange_exchange_binding(client, vhost, src, dest, opts) do
case NimbleOptions.validate(opts, create_exchange_binding_definition()) do
{:error, error} ->
raise ArgumentError, format_error(error)

{:ok, params} ->
client
|> Tesla.post("#{@api_namespace}/#{vhost}/e/#{src}/e/#{dest}", Enum.into(params, %{}))
end
end
end
21 changes: 21 additions & 0 deletions lib/ex_rabbitmq_admin/options.ex
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,27 @@ defmodule ExRabbitMQAdmin.Options do
]
end

def create_exchange_binding_definition do
[
routing_key: [
doc: """
The routing key used to route the message to its destination.
""",
type: :string,
required: true
],
arguments: [
doc: """
Optional binding arguments passed to RabbitMQ when creating the binding.
Please consult the official documentation for supported arguments (as they can vary
for exchange type).
""",
type: {:map, :string, :any},
required: false
]
]
end

def format_error(%ValidationError{keys_path: [], message: message}), do: message

def format_error(%ValidationError{keys_path: keys_path, message: message}) do
Expand Down
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule ExRabbitMQAdmin.MixProject do
use Mix.Project

@version "0.1.3"
@version "0.1.4"
@description "A Http client library for RabbitMQ Web API"
@source_url "https://github.com/Intility/ex_rabbitmq_admin"

Expand Down Expand Up @@ -50,7 +50,7 @@ defmodule ExRabbitMQAdmin.MixProject do

defp deps do
[
{:ex_doc, "~> 0.30", only: [:dev, :test], runtime: false},
{:ex_doc, "~> 0.35", only: [:dev, :test], runtime: false},
{:excoveralls, "~> 0.18", only: :test},
{:hackney, "~> 1.18", optional: true},
{:jason, "~> 1.4"},
Expand Down
22 changes: 11 additions & 11 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
%{
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
"excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"},
"earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"},
"ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"},
"excoveralls": {:hex, :excoveralls, "0.18.3", "bca47a24d69a3179951f51f1db6d3ed63bca9017f476fe520eb78602d45f7756", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "746f404fcd09d5029f1b211739afb8fb8575d775b21f6a3908e7ce3e640724c6"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.3", "d684f4bac8690e70b06eb52dad65d26de2eefa44cd19d64a8095e1417df7c8fd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"},
"tesla": {:hex, :tesla, "1.13.2", "85afa342eb2ac0fee830cf649dbd19179b6b359bec4710d02a3d5d587f016910", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "960609848f1ef654c3cdfad68453cd84a5febecb6ed9fed9416e36cd9cd724f9"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
}
30 changes: 30 additions & 0 deletions test/ex_rabbitmq_admin/binding_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule ExRabbitMQAdmin.BindingTest do
use ExRabbitMQAdmin.TestCase, async: true
alias ExRabbitMQAdmin.Binding

setup do
mock(fn
%{method: :get, url: "https://rabbitmq.example.com:5672/api/bindings"} ->
%Tesla.Env{status: 200, body: read_json("list_bindings.json")}
end)
end

test "can list bindings" do
assert {:ok,
%Tesla.Env{
status: 200,
body: [
%{
"arguments" => %{},
"destination" => "dumpster-fire",
"destination_type" => "queue",
"properties_key" => "dumpster-fire",
"routing_key" => "dumpster-fire",
"source" => "",
"vhost" => "my-vhost"
}
| _rest
]
}} = Client.client() |> Binding.list_bindings()
end
end
20 changes: 20 additions & 0 deletions test/support/fixtures/list_bindings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"arguments": {},
"destination": "dumpster-fire",
"destination_type": "queue",
"properties_key": "dumpster-fire",
"routing_key": "dumpster-fire",
"source": "",
"vhost": "my-vhost"
},
{
"arguments": {},
"destination": "dumpster-fire",
"destination_type": "queue",
"properties_key": "idle-avocet",
"routing_key": "idle-avocet",
"source": "amq.direct",
"vhost": "my-vhost"
}
]

0 comments on commit 3e50567

Please sign in to comment.