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 模板

使用CloudFormation模板更新AWS Athena工作组

aws cloudformation 弹性搜索堆栈

使用带反斜杠的sed命令时出现AWS CloudFormation模板验证错误