eclipse-hono / hono

Eclipse Hono™ Project
https://eclipse.dev/hono
Eclipse Public License 2.0
453 stars 137 forks source link

Trying to call sandbox tenant API #3587

Closed borrosjim closed 1 year ago

borrosjim commented 1 year ago

Hello, I'm exploring around Hono's functionalities and I was wondering if it's possible to interact with Hono's core APIS using the sandbox. I've made a script in python that tries to connect to AMQP 1.0 broker and following https://eclipse.dev/hono/docs/api/tenant/ Not sure if I got something wrong or it's just not permitted, it seems like I don't have credits from the server so I can't even publish a message (I've tried calling it directly without connecting to /tenant but I can't get the connection to work). I've put the user "hono-client@HONO". Here's my script

import optparse
from proton import Message, SSLDomain
from proton.handlers import MessagingHandler
from proton.reactor import Container, Selector, AtMostOnce

# Hono tenant service details
service_host = "hono.eclipseprojects.io"
service_port = 15671  # Default AMQP 1.0 port for Hono
service_schema = "amqps"

tenant_id = "DEFAULT_TENANT"

addr = "tenant"
subject = "get"

# Hono credentials for consumer demo (TBD)
user = "hono-client@HONO"
passw = "secret"

class AmqpMessageSender(MessagingHandler):
    def __init__(self, server, address, tenant_id, username, password, subject):
        super(AmqpMessageSender, self).__init__()
        self.server = server
        self.address = address
        self.tenant_id = tenant_id
        self.username = username
        self.password = password
        self.subject = subject

    def on_start(self, event):
        print("Connecting to the Hono service...")
        try:
            conn = event.container.connect(
                url=self.server,
                sasl_enabled=True,
                allowed_mechs="PLAIN",
                allow_insecure_mechs=True,
                user=self.username,
                password=self.password
            )
            print("Connection established")

            # Creating sender and receiver
            sender = event.container.create_sender(context=conn, target=self.address,name="sender", options=AtMostOnce())#
            receiver = event.container.create_receiver(context=conn, source=f"{self.address}/123", target=self.address,dynamic=True, name="receiver")

            print(f"Sender and receiver created:\nSender\t: {sender.name}\nReceiver:\t{receiver.name}")

        except Exception as e:
            self.handle_error(f"Error during connection: {e}")

    def on_sendable(self, event):
        print("Sending request message...")
        try:
            request_message = Message(
                subject=self.subject,
                body=str({"tenant-id": f"{self.tenant_id}"}),
                address=self.address,
                content_type="application/json",
                reply_to=f"{self.address}/123"
            )
            event.sender.send(request_message)
            event.sender.close()
            print("Request message sent")

        except Exception as e:
            self.handle_error(f"Error during sending request: {e}")

    def on_connection_error(self, event):
        self.handle_error("Connection Error")

    def on_link_error(self, event):
        print("Link Error:")
        print(f"  Condition: {event.link.remote_condition}")
        print(f"  Description: {event.link.remote_condition.description}")
        self.handle_error("Link Error")

    def on_transport_error(self, event):
        print("Transport Error")
        print(f"  Condition: {event.transport.condition}")
        self.handle_error("Transport Error")

    def on_message(self, event):
        print(f"Received response: {event.message.body}")
        event.receiver.close()
        event.connection.close()

    def handle_error(self, message):
        print(f"Error: {message}")

    def on_link_opened(self, event):
        print(f"Link opened successfully {event.type.name}")
        if event.receiver:
            print(f"Receiver: {event.receiver.name}, \nremote source address: {event.receiver.remote_source.address}")

    def on_accepted(self, event):
        print("Request accepted.")

    def on_disconnected(self, event):
        print(f"Disconnected: {event}")
        print("Attempting to reconnect...")

    def on_link_remote_open(self, event):
        print ("Link Remote Opened")

Container(AmqpMessageSender(f'{service_schema}://{service_host}:{service_port}', addr, tenant_id, user, passw, subject)).run()

Would you mind taking a look at it? Thanks in advance! B

sophokles73 commented 1 year ago

The Tenant API is supposed to be used by Hono's protocol adapters, not external components. The Sandbox therefore does not expose the corresponding API endpoint(s) to the outside world. In your script you are connecting to Hono's north bound AMQP 1.0 endpoint. This endpoint only supports the Telemetry, Event and Command & Control APIs. Would you mind explaining why you need to access the Tenant API via AMQP 1.0?

borrosjim commented 1 year ago

The Tenant API is supposed to be used by Hono's protocol adapters, not external components. The Sandbox therefore does not expose the corresponding API endpoint(s) to the outside world. In your script you are connecting to Hono's north bound AMQP 1.0 endpoint. This endpoint only supports the Telemetry, Event and Command & Control APIs. Would you mind explaining why you need to access the Tenant API via AMQP 1.0?

Hello @sophokles73 and thanks for your support. I was trying to see if it's possible to create a custom protocol adapter directly (rather than using a software gateway) with python. Best regards, B

sophokles73 commented 1 year ago

That is definitely possible but the Sandbox does not expose the API to components outside of the k3s cluster it is deployed to. You can, of course, create a custom adapter and deploy it to your own Hono installation ...

borrosjim commented 1 year ago

I wanted to do that, but somehow I'm finding it difficult to deploy it in a mac m1 machine, that's why I was experimenting on hono directly; but I'll definitely have a look into it :) Thanks again for your support, B