无法通过LocalStack中的Cloudformation创建对SNS主题的SQS订阅

时间:2019-03-12 14:30:24

标签: amazon-cloudformation amazon-sns atlassian-localstack

我正在使用localstack创建一个执行以下操作的模板:

  1. 创建一个SNS主题
  2. 创建SQS队列
  3. 创建一个将SQS队列订阅到SNS主题的订阅。

我的docker-compose文件如下:

version: '3'

services:

  localstack:
    image: localstack/localstack
    container_name: localstack
    environment:
      - SERVICES=sns,sqs,cloudformation
      - DEBUG=1
      - PORT_WEB_UI=${PORT_WEB_UI- }
      - HOSTNAME=localstack
      - AWS_DEFAULT_REGION=eu-west-2
      - AWS_ACCESS_KEY_ID=XX
      - AWS_SECRET_ACCESS_KEY=XX
    ports:
      - "4575:4575"
      - "4576:4576"
      - "4581:4581"
      - "8080:8080"
    volumes:
      - ./config/formation.yml:/usr/stuff/formation.yml
      - ./config/init.sh:/docker-entrypoint-initaws.d/init.sh

我的init.sh文件如下:

#!/bin/bash
aws cloudformation create-stack --stack-name fincorestack --template-body file:///usr/stuff/formation.yml --endpoint-url=http://localstack:4581

最后,我的Cloudformation文件如下所示:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Test'
Resources:
  MySnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: MySnsTopic
  MySnsTopicSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: sqs
      TopicArn: !Ref MySnsTopic
      Endpoint: !GetAtt
        - MySqsQueue
        - QueueArn
  MySqsQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: MySqsQueue

这会产生非常模糊的 500 Internal Server Error 。由于这是localstack,并且我知道arns是相当静态的,因此我尝试用以下内容替换订阅ymlTopcArn的{​​{1}}文件的内容:

Endpoint

这次,我没有收到错误,但是没有创建订阅。从TopicArn: arn:aws:sns:eu-west-2:123456789012:MySnsTopic Endpoint: arn:aws:sqs:elasticmq:000000000000:MySqsQueue 的调试输出中可以看到:

enter image description here

并且未创建订阅。 localstack的{​​{1}}实现中是否不支持此功能,或者我做错了什么?

3 个答案:

答案 0 :(得分:2)

在 cli 中使用 docker 和 localstack...

启动你的本地堆栈

创建主题:

AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --endpoint-url=http://dc-localstack:4566 --region us-east-1 sns create-topic --name jensTopic`

回复:

{
    "SubscriptionArn": "arn:aws:sns:us-east-1:000000000000:jensTopic:9bf7628e-ee36-49c1-8216-ed5cf5aea1ed"
}

创建队列:

AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --endpoint=http://dc-localstack:4566 --region us-east-1 sqs create-queue --queue-name jensQueue

获取队列 arn 属性:

AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --endpoint-url=http://dc-localstack:4566 --region us-east-1 sqs get-queue-attributes --queue-url http://localhost:4566/queue/jensQueue --attribute-names QueueArn

回复:

{
    "Attributes": {
        "QueueArn": "arn:aws:sqs:us-east-1:000000000000:jensQueue"
    }
}

订阅队列主题:

AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --endpoint-url=http://dc-localstack:4566 --region us-east-1 sns subscribe --topic-arn "arn:aws:sns:us-east-1:000000000000:jensTopic" --protocol sqs --notification-endpoint "arn:aws:sqs:us-east-1:000000000000:jensQueue"

健全性检查:

AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --endpoint-url=http://dc-localstack:4566 --region us-east-1 sns list-subscriptions

回复:

{
    "Subscriptions": [
        {
            "SubscriptionArn": "arn:aws:sns:us-east-1:000000000000:jensTopic:9bf7628e-ee36-49c1-8216-ed5cf5aea1ed",
            "Owner": "",
            "Protocol": "sqs",
            "Endpoint": "arn:aws:sqs:us-east-1:000000000000:jensQueue",
            "TopicArn": "arn:aws:sns:us-east-1:000000000000:jensTopic"
        }
    ]
}

答案 1 :(得分:0)

找到了一种解决方法,以便在其他人需要时发布。我感觉localstack根本不支持将订阅创建为资源,因此我在定义SNS Topic资源时创建了订阅。将yml文件更改为以下内容可以达到目的:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Test'
Resources:
  MySqsQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: MySqsQueue

  MySqsQueue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: MySqsQueue
      Subscription:
        - Protocol: sqs
          Endpoint:
            "Fn::GetAtt": ["MySqsQueue", "Arn"]
          RawMessageDelivery: 'true'

编辑:

不幸的是,以这种方式创建预订不允许设置属性。就我而言,我需要RawMessageDelivery=true不受支持(请参阅here)。很烦人...

答案 2 :(得分:0)

此问题现已解决:https://github.com/localstack/localstack/issues/1191

尽管def is_matched(text, pos, chars='?|!'): return text[:pos].rstrip()[-1] in chars is_matched('blah? test', pos=6) #True is_matched('blah? test', pos=7) #False TopcArn仍需要进行硬编码。