rabbitmq / rabbitmq-server

Open source RabbitMQ: core server and tier 1 (built-in) plugins
https://www.rabbitmq.com/
Other
11.83k stars 3.9k forks source link

AMQP 1.0 Shovels: expose additional capabilities needed for successful connection to some AMQP 1.0 brokers #10752

Open madmalkav opened 3 months ago

madmalkav commented 3 months ago

When connecting to some AMQP 1.0 brokers, we cannot set capabilities on the shovel, so in some scenarios we are unable to give the shovel the proper configuration. In example, for IBM MQ , if you want to use a queue but don't set capabilities to queue, it will default to believe the object name provided is for a topic:

imagen

This is documented on IBM website:

imagen

I was able to replicate this same behavior with QPid Proton and this code sample, this code doesn't set capabilities so the same behavior happens:

from __future__ import print_function, unicode_literals
from proton import Message
from proton.handlers import MessagingHandler
from proton.reactor import Container

class HelloWorld(MessagingHandler):
    def __init__(self, server, address):
        super(HelloWorld, self).__init__()
        self.server = server
        self.address = address

    def on_start(self, event):
        print("connecting ...")
        conn = event.container.connect(self.server, sasl_enabled=True, allowed_mechs="PLAIN", allow_insecure_mechs=True, user="app", password="passw0rd")
        event.container.create_sender(conn, self.address)

    def on_sendable(self, event):
        print("sending command")
        event.sender.send(Message(body="Hello World!", address="DEV.QUEUE.2", content_type="text/plain"))
        event.sender.close()
        event.connection.close()

Container(HelloWorld("queue://172.17.0.2:5672", "DEV.QUEUE.2")).run()

This code set capabilities so it works OK:

from __future__ import print_function, unicode_literals
from proton import Message, symbol
from proton.handlers import MessagingHandler
from proton.reactor import Container, SenderOption

class HelloWorld(MessagingHandler):
    def __init__(self, server, address):
        super(HelloWorld, self).__init__()
        self.server = server
        self.address = address

    def on_start(self, event):
        print("connecting ...")
        conn = event.container.connect(self.server, sasl_enabled=True, allowed_mechs="PLAIN", allow_insecure_mechs=True, user="app", password="passw0rd")
        event.container.create_sender(conn, self.address, options=CapabilityOptions())

    def on_sendable(self, event):
        print("sending command")
        event.sender.send(Message(body="Hello World!", address="DEV.QUEUE.2", content_type="text/plain"))
        event.sender.close()
        event.connection.close()

class CapabilityOptions(SenderOption):
    def apply(self, sender):
        sender.target.capabilities.put_object(symbol("queue"))

Container(HelloWorld("amqp://172.17.0.2:5672", "DEV.QUEUE.2")).run()

Describe the solution you'd like

Some way to be able to set those capabilities on the shovel configuration.

Describe alternatives you've considered

No response

Additional context

No response

ansd commented 3 months ago

Hey @madmalkav, if that's what IBM MQ requires, feel free to create PR to add a capabilities field to the shovel configuration and pass that value through to the AMQP 1.0 Erlang client when it sends the ATTACH frame.

madmalkav commented 3 months ago

I have no knowledge of coding in general or Erlang in particular (I’m still surprised I got those Python samples to work…), so sending a PR is way above my skillset 😅

michaelklishin commented 3 months ago

Thank you for providing enough details and executable versions. It's a fair feature to request, we certainly would like to have a more complete Shovel support for IBM MQ targets. However, we cannot promise any particular ETA date.