Search code examples
python-2.7mockingamazon-sqsamazon-snsmoto

Should I be able to subscribe a moto SNS notification to a moto SQS queue?


I'm using python 2.7, boto(2) and moto server, and I use the BOTO_CONFIG environment variable to point to my local moto server. I can properly mock everything up until the publish method.

I create 2 separate processes, one for sqs and one for sns using

moto_server sqs -p5001
moto_server sns -p5002

I create my queues, topic, and subscription and it works great

127.0.0.1 - - [21/Jun/2018 19:19:05] "GET http://queue.amazonaws.com/?Action=CreateQueue&QueueName=my_local_queue&Version=2012-11-05 HTTP/1.1" 200 -
127.0.0.1 - - [21/Jun/2018 19:19:05] "GET http://sns.us-east-1.amazonaws.com/?Action=CreateTopic&ContentType=JSON&Name=my_local_topic&Version=2010-03-31 HTTP/1.1" 200 -
127.0.0.1 - - [21/Jun/2018 19:19:05] "GET http://sns.us-east-1.amazonaws.com/?Action=Subscribe&ContentType=JSON&Endpoint=arn%3Aaws%3Asqs%3Aus-east-1%3A123456789012%3Amy_local_queue&Protocol=sqs&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A123456789012%3Amy_local_topic&Version=2010-03-31 HTTP/1.1" 200 -
127.0.0.1 - - [21/Jun/2018 19:19:05] "GET http://queue.amazonaws.com/123456789012/my_local_queue?Action=GetQueueAttributes&AttributeName=Policy&Version=2012-11-05 HTTP/1.1" 200 -
127.0.0.1 - - [21/Jun/2018 19:19:05] "GET http://queue.amazonaws.com/123456789012/my_local_queue?Action=SetQueueAttributes&Attribute.Name=Policy&Attribute.Value=%7B%22Version%22%3A%20%222008-10-17%22%2C%20%22Statement%22%3A%20%5B%7B%22Resource%22%3A%20%22arn%3Aaws%3Asqs%3Aus-east-1%3A123456789012%3Amy_local_queue%22%2C%20%22Effect%22%3A%20%22Allow%22%2C%20%22Sid%22%3A%20%223ca50596674e991d6a8a04932ab998ac%22%2C%20%22Action%22%3A%20%22SQS%3ASendMessage%22%2C%20%22Condition%22%3A%20%7B%22StringLike%22%3A%20%7B%22aws%3ASourceArn%22%3A%20%22arn%3Aaws%3Asns%3Aus-east-1%3A123456789012%3Amy_local_topic%22%7D%7D%2C%20%22Principal%22%3A%20%7B%22AWS%22%3A%20%22%2A%22%7D%7D%5D%7D&Version=2012-11-05 HTTP/1.1" 200 -

But when I publish a message to SNS, I get this error

127.0.0.1 - - [21/Jun/2018 19:22:08] "POST http://sns.us-east-1.amazonaws.com/ HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
  File "/_venv/lib/python2.7/site-packages/werkzeug/serving.py", line 270, in run_wsgi
    execute(self.server.app)
  File "/_venv/lib/python2.7/site-packages/werkzeug/serving.py", line 258, in execute
    application_iter = app(environ, start_response)
  File "/_venv/lib/python2.7/site-packages/moto/server.py", line 93, in __call__
    return backend_app(environ, start_response)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/_venv/lib/python2.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/_venv/lib/python2.7/site-packages/moto/core/utils.py", line 139, in __call__
    result = self.callback(request, request.url, {})
  File "/_venv/lib/python2.7/site-packages/moto/core/responses.py", line 116, in dispatch
    return cls()._dispatch(*args, **kwargs)
  File "/_venv/lib/python2.7/site-packages/moto/core/responses.py", line 199, in _dispatch
    return self.call_action()
  File "/_venv/lib/python2.7/site-packages/moto/core/responses.py", line 273, in call_action
    response = method()
  File "/_venv/lib/python2.7/site-packages/moto/sns/responses.py", line 274, in publish
    message_attributes=message_attributes)
  File "/_venv/lib/python2.7/site-packages/moto/sns/models.py", line 325, in publish
    message_attributes=message_attributes)
  File "/_venv/lib/python2.7/site-packages/moto/sns/models.py", line 50, in publish
    message_attributes=message_attributes)
  File "/_venv/lib/python2.7/site-packages/moto/sns/models.py", line 97, in publish
    sqs_backends[region].send_message(queue_name, enveloped_message)
  File "/_venv/lib/python2.7/site-packages/moto/sqs/models.py", line 405, in send_message
    queue = self.get_queue(queue_name)
  File "/_venv/lib/python2.7/site-packages/moto/sqs/models.py", line 390, in get_queue
    raise QueueDoesNotExist()
QueueDoesNotExist

I'm lost and I feel I'm missing something obvious but can't find it, I checked that BOTO_CONFIG gets copied into the SNS subprocess (I assume that uses boto as well and would point to my local moto SQS also, but maybe here lies my misunderstanding of the situation)

Any pointers or ideas would be greatly appreciated!

Here's a snippet of the code I use setting everything up, the call to publish is trivial and so not included

# (...)
self.__events_queue = self.get_queue()
SNSConnection.get_instance().get_sns_connection().create_topic(topic=conf.aws.sns_topic_arn.split(':')[5])
SNSConnection.get_instance().get_sns_connection().subscribe_sqs_queue(conf.aws.sns_topic_arn, self.__events_queue)

def get_queue(self):
    conf = config.Config.get_instance()
    conn = boto.sqs.connect_to_region(
        conf.aws.region,
        aws_access_key_id=conf.aws.access_key_id,
        aws_secret_access_key=conf.aws.secret_access_key
    )
    q = conn.get_queue(conf.aws.sqs_queue_name)
    if not q:
        q = conn.create_queue(conf.aws.sqs_queue_name)
    return q

I also posted this to the project's github, but I may have more luck here


Solution

  • I always suspected the problem was having two different moto processes but didn't know you can run two different moto services in the same process.
    Apparently that's possible!

    If you start the process like the moto docker file, everything works as expected

    moto_server -H 0.0.0.0