AWS cloudformation 错误:模板验证错误:模板错误:资源 NotificationsTopic 不支持 Fn::GetAtt 中的属性类型 Arn
Posted
技术标签:
【中文标题】AWS cloudformation 错误:模板验证错误:模板错误:资源 NotificationsTopic 不支持 Fn::GetAtt 中的属性类型 Arn【英文标题】:AWS cloudformation error: Template validation error: Template error: resource NotificationsTopic does not support attribute type Arn in Fn::GetAtt 【发布时间】:2019-04-26 16:52:05 【问题描述】:我正在尝试使用 yaml 模板创建 AWS cloudformation 堆栈。 目标是为一些通知创建一个 sns 主题。 我想输出主题 arn,以便能够通过指定主题 arn 来订阅该主题的多个函数。
但是,当我尝试从 aws 控制台创建堆栈时出现错误:
“模板验证错误:模板错误:资源NotificationsTopic不支持Fn::GetAtt中的属性类型Arn”
我对 s3 存储桶、dynamodb 表进行了完全相同的操作,并且一切正常,但由于某种原因,对于 SNS 主题,我无法获得 ARN。
我想避免在所有订阅的函数中对主题 arn 进行硬编码。因为如果有一天 ARN 主题发生变化,我需要更改所有函数,而不是我想在所有函数中导入主题 arn 并使用它。这样,如果将来出于任何原因我有新的 arn 主题,我将无需修改任何内容。
这是模板:
Parameters:
stage:
Type: String
Default: dev
AllowedValues:
- dev
- int
- uat
- prod
Resources:
NotificationsTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub 'notifications-$stage'
Subscription:
- SNS Subscription
TopicName: !Sub 'notifications-$stage'
Outputs:
NotificationsTopicArn:
Description: The notifications topic Arn.
Value: !GetAtt NotificationsTopic.Arn
Export:
Name: !Sub '$AWS::StackName-NotificationsTopicArn'
NotificationsTopicName:
Description: Notifications topic name.
Value: !Sub 'notifications-$stage'
Export:
Name: !Sub '$AWS::StackName-NotificationsTopicName'
【问题讨论】:
【参考方案1】:并非所有资源都相同。始终检查特定资源的文档。它具有“返回值”部分,您可以轻松验证 SNS 主题将 ARN 作为 Ref
值,因此您不必使用 GetAtt
函数
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html
编辑:感谢您指出并非每个资源都提供其 ARN 的评论。一个值得注意的例子是 Autoscaling 组。当然,我的回答中的关键是“检查每个资源的文档”,这是一个例子,不是每个资源都有每个属性。 话虽如此,ASG 输出缺少 ARN 是一件非常奇怪的事情。它也不容易构造,因为 ARN 还包含 GroupId,它是一个随机散列。至少对于 ECS 容量提供程序 https://github.com/aws-cloudformation/aws-cloudformation-coverage-roadmap/issues/548 和 https://github.com/aws/containers-roadmap/issues/631#issuecomment-648377011 的用例,可能需要付出一些努力来解决这个问题,但我认为这是一个足够重要的问题,应该在这里提及。
【讨论】:
您如何处理 !GetAtt 和 !Ref 都不支持的属性?喜欢HostedZone.Name
:docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…
好吧,我不能代表 AWS 争论,但 CF 不是一种综合性脚本语言,你有区域 ID,你可以将它传递给 lambda/ec2,然后你就可以调用以 id 作为参数描述区域并从那里开始。
返回值,当然!我实际上试图用Fn::GetAttr
定位资源的名称,这个答案帮助我看到TargetGroup.Name
实际上应该是TargetGroup.TargetGroupName
。这很有帮助,谢谢。
此答案仅在目标资源在由Ref
调用时返回 ARN 时才有用。它没有解释如何为 Ref
未返回其 ARN 的资源获取 ARN。以AWS::AutoScaling::AutoScalingGroup
- Ref
不返回 ARN,但通常需要它的 ARN(即,作为 AWS::ECS::CapacityProvider AutoScalingGroupProvider.AutoScalingGroupArn
的值)docs。
@teuber789 感谢您的评论。我没有遇到这个问题,因为我们确实在需要时使用了 Fargate。但这确实是一个非常奇怪的怪癖。我发现有人努力解决这个问题 github.com/aws-cloudformation/… ,但我现在能看到的唯一解决方法是使用 lambda 的自定义 CF 资源,它可以描述 ASG 并返回其 ARN。好吧,没有什么是完美的。【参考方案2】:
对于不直接返回 ARN 的资源,我找到了一种解决方法,包括自己构建 ARN。
例如,要获取我的代码管道的 ARN:
!Join [ ':', [ "arn:aws:codepipeline", !Ref AWS::Region, !Ref AWS::AccountId, !Ref StackDeletePipeline ] ]
【讨论】:
AWS::Partition
以防万一:***.com/a/59362496/4122849以上是关于AWS cloudformation 错误:模板验证错误:模板错误:资源 NotificationsTopic 不支持 Fn::GetAtt 中的属性类型 Arn的主要内容,如果未能解决你的问题,请参考以下文章
Aws cloudformation validate-template 一直报错(模板格式错误)
AWS CloudFormation:结合 ImportValue 和 Sub 函数会导致错误
如何修复与 AWS::CloudFormation::Init 一起创建 EC2 的 cloudformation 模板