You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Moto模拟CloudFormation创建堆栈时AWS::SNS::Subscription未生成的问题咨询

Moto模拟CloudFormation创建堆栈时AWS::SNS::Subscription未生成的问题咨询

我来帮你分析下可能的原因和排查步骤,你可以逐一尝试:

1. 先确认堆栈是否完全创建完成,订阅资源是否真的被触发创建

Moto的CloudFormation模拟虽然是同步的,但有时候资源创建的事件可能需要确认状态。你可以先检查堆栈的状态,以及堆栈事件里有没有订阅资源的创建记录:

import boto3

cfn = boto3.client('cloudformation')
# 检查堆栈状态
stack_info = cfn.describe_stacks(StackName="test-stack-1")['Stacks'][0]
print(f"堆栈状态: {stack_info['StackStatus']}")

# 查看所有堆栈事件,找订阅资源的状态
events = cfn.describe_stack_events(StackName="test-stack-1")
for event in reversed(events['StackEvents']):
    if event['LogicalResourceId'] == 'SQSToSNSSubscription':
        print(f"订阅资源状态: {event['ResourceStatus']} - {event.get('ResourceStatusReason', '无备注')}")

如果看到订阅资源的状态是CREATE_FAILED,那就能直接定位问题原因;如果压根没找到这个资源的事件,那可能是CloudFormation模板的解析有问题。

2. 尝试移除Serverless Transform

你的模板里用了AWS::Serverless-2016-10-31这个Transform,但你的资源都是基础的AWS服务(DynamoDB、SNS、SQS),完全不需要依赖Serverless Transform。这个Transform可能会对资源的创建逻辑做额外处理,而Moto对这个Transform的支持可能存在疏漏。

你可以把模板里的Transform段删掉,重新创建堆栈试试:

# 删掉这段
# Transform:
#   - AWS::Serverless-2016-10-31

3. 检查Moto版本并升级

虽然你说没找到文档说明不支持,但Moto的某些旧版本可能确实存在CloudFormation创建SNS订阅的bug。建议升级到最新稳定版再测试:

pip install --upgrade moto

4. 对比手动创建订阅的情况

你可以手动用SNS客户端创建相同的订阅,看看是否能正常出现在list_subscriptions的结果里,以此排除是SNS模拟本身的问题:

import boto3

sns = boto3.client('sns')
sqs = boto3.client('sqs')

# 获取已创建的主题和队列信息
topic_arn = sns.list_topics()['Topics'][0]['TopicArn']
queue_url = sqs.get_queue_url(QueueName="test-queue")['QueueUrl']
queue_arn = sqs.get_queue_attributes(QueueUrl=queue_url, AttributeNames=['QueueArn'])['Attributes']['QueueArn']

# 手动创建订阅
response = sns.subscribe(
    TopicArn=topic_arn,
    Protocol='sqs',
    Endpoint=queue_arn,
    RawMessageDelivery=True
)

# 查看订阅
print("手动创建的订阅:", sns.list_subscriptions())

如果手动创建能正常查到订阅,但CloudFormation创建不行,那基本可以确定是Moto对AWS::SNS::Subscription的CloudFormation资源支持存在问题,这时候你可以去Moto的GitHub仓库提交Issue,附上你的模板和测试代码,让官方修复。

5. 检查模板里的订阅参数是否正确

你的模板里的订阅参数看起来是对的,但可以再确认下:

  • Endpoint用Fn::GetAtt: SQSQueue.Arn是正确的,因为SQS的Arn必须通过GetAtt获取
  • Protocol设为sqs没问题
  • RawMessageDelivery: true也是合法参数

暂时想到这些方向,你可以先从检查堆栈状态和移除Transform开始排查,应该能找到问题所在。

备注:内容来源于stack exchange,提问作者Martin Macak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 09:44:51