0

I am trying to initialize an Exchange using Powershell. I need to define a DLQ, so I am trying the following syntax:

$exchangeURL = $apiURL + "/exchanges/myHost/myExchange";
$body = "{""type"":""fanout"",""auto_delete"":false,""durable"":true,""arguments"":[{""x-dead-letter-exchange"": ""myExchangeDLQ""}]}"
$response = Invoke-WebRequest -Uri $exchangeURL -Headers $headers -Method Put -ContentType "application/json" -Body $body

I get this error:

Invoke-WebRequest :
{"error":"bad_request","reason":["unhandled_type",["x-dead-letter-exchange","myExchangeDLQ"]]}
+ $response = Invoke-WebRequest -Uri $exchangeURL -Headers $headers -Method Put -C ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

I see at this link that maybe it is not that easy:

arguments fields are ignored everywhere. You cannot create a queue, exchange or binding with arguments. Queues, exchanges or bindings with arguments won't show those arguments

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
ab_732
  • 3,639
  • 6
  • 45
  • 61

3 Answers3

1

Exchanges do not get bound to a DLX (Dead-letter exchange), queues do. It should work if you do the following:

  1. Create the exchange with empty args list:

    $body = "{""type"":""fanout"",""auto_delete"":false,""durable"":true,""arguments"":[]}"

  2. Create the queue with the DLX

  3. Bind the exchange to the queue
jhilden
  • 12,207
  • 5
  • 53
  • 76
  • thanks for your answer. Unfortunately it gives the same error – ab_732 Feb 18 '15 at 19:34
  • Here is a gist I created from my working setup script. It's doing more than what you need but it all works so you can take what you need. https://gist.github.com/jayhilden/e60b26a94cdc7599a0ab – jhilden Feb 19 '15 at 15:33
  • Oh I got it. That basically sets the policy on the broker so that the dead letter exchange is valid for every queue. Interesting – ab_732 Feb 19 '15 at 17:07
  • Correct. You could easily update it to setup different DLX on different queues but I didn't need that. I set it up globally so that I didn't have to mess with it on each queue. – jhilden Feb 19 '15 at 17:36
  • You're welcome. Another note: we used to initialize our rabbit queues and exchanges this way but have since moved to putting the code in C# and running it on application startup. If the queues already exist then the code does nothing, otherwise it created everything automatically. It was a better solution for us than doing it in powershell. Good luck. – jhilden Feb 19 '15 at 20:07
1

For RabbitMQClient version 3.5.5 the arguments parameter for QueueDeclare has changed from an IDictionary to IDictionary<string,object> so the queueArgs parameter definition provided by abx78 needs to be changed slightly or you get a cryptic argument count mismatch error thrown by powershell

OLD WAY for version 3.1.5

$queueArgs = @{"x-dead-letter-exchange"="charges_deadletter_exchange";};

NEW WAY

$queueArgs= New-Object "System.Collections.Generic.Dictionary``2[System.String,System.Object]"
$queueArgs.Add("x-dead-letter-exchange", "charges_deadletter_exchange")
Ricky Keane
  • 1,540
  • 2
  • 15
  • 21
0

This a pure PowerShell alternative I found in a Pluralsight course - Michael Stephenson, RabbitMQ for Developers Part 2.

$RabbitDllPath = "packages\RabbitMQ.Client.3.1.5\lib\net30\RabbitMQ.Client.dll"

$RabbitDllPath = Resolve-Path $RabbitDllPath 
Write-Host "Rabbit DLL Path: " 
Write-Host $RabbitDllPath -foregroundcolor green

set-ExecutionPolicy Unrestricted

$absoluteRabbitDllPath = Resolve-Path $RabbitDllPath

Write-Host "Absolute Rabbit DLL Path: " 
Write-Host $absoluteRabbitDllPath -foregroundcolor green

[Reflection.Assembly]::LoadFile($absoluteRabbitDllPath)

Write-Host "Setting up RabbitMQ Connection Factory"
$factory = new-object RabbitMQ.Client.ConnectionFactory
$hostNameProp = [RabbitMQ.Client.ConnectionFactory].GetField(“HostName”)
$hostNameProp.SetValue($factory, “localhost”)

$usernameProp = [RabbitMQ.Client.ConnectionFactory].GetField(“UserName”)
$usernameProp.SetValue($factory, “guest”)

$passwordProp = [RabbitMQ.Client.ConnectionFactory].GetField(“Password”)
$passwordProp.SetValue($factory, “guest”)

$createConnectionMethod = [RabbitMQ.Client.ConnectionFactory].GetMethod(“CreateConnection”, [Type]::EmptyTypes)
$connection = $createConnectionMethod.Invoke($factory, “instance,public”, $null, $null, $null)

Write-Host "Setting up RabbitMQ Model"
$model = $connection.CreateModel()

Write-Host "Create Dead Letter Exchange"
$exchangeType = [RabbitMQ.Client.ExchangeType]::Fanout
$model.ExchangeDeclare("DeadLetterExchange", $exchangeType, $true)

Write-Host "Creating Dead Letter Queue"
$model.QueueDeclare(“DeadLetter”, $true, $false, $false, $null)
$model.QueueBind("DeadLetter", "DeadLetterExchange", "")

Write-Host "Creating Queue"
$args = @{"x-dead-letter-exchange"="DeadLetterExchange";};
$model.QueueDeclare(“Normal”, $true, $false, $false, $args)

Write-Host "Setup complete"

This approach takes advantage of the C# client.

ab_732
  • 3,639
  • 6
  • 45
  • 61