在 AWS CloudFormation 模板中引用 !Ref DynamoDB 表名
Posted
技术标签:
【中文标题】在 AWS CloudFormation 模板中引用 !Ref DynamoDB 表名【英文标题】:Referencing !Ref DynamoDB table name in a AWS CloudFormation template 【发布时间】:2019-12-13 13:29:38 【问题描述】:我正在尝试在本地测试传递我的 CloudFormation 模板文件中声明的 DynamoDB 表的表名。
从我阅读的所有文档中,我应该能够使用 !Ref
内在函数引用 DynamoDB 资源的 TableName
属性值。但是,当我在本地对此进行测试时,该属性是未定义的。
考虑以下示例:
Transform: 'AWS::Serverless-2016-10-31'
Resources:
ServerlessFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs10.x
Handler: index.handler
Environment:
Variables:
TABLE_NAME: !Ref DynamoDBTable # <- returning undefined
Events:
GetCocktails:
Type: Api
Properties:
Path: /
Method: get
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: DynamoDBTableName
AttributeDefinitions:
- AttributeName: ID
AttributeType: S
KeySchema:
- AttributeName: ID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
我希望 TABLE_NAME
环境变量为 DynamoDBTableName
但它返回未定义。如何让模板按预期工作?
【问题讨论】:
我刚刚修复了您的问题以引用 CloudFormation,因为您的问题与 CloudFormation 相关,而不是 SAM。也就是说,经过简短的查看后,它应该可以按您的预期工作。您能否在尝试访问环境变量的地方添加您的 AWS Lambda 函数的代码? 我正在寻找如何做同样的事情并在这里找到了您的问题。你所做的事情对我有用。无论如何,谢谢你在这里问。 谁能提供 JSON 格式的 cloudformation 模板的答案/解决方案? 【参考方案1】:正如其他人所说,AWS::DynamoDB::Table 公开的唯一属性是:
Arn
和 StreamArn
(参见 AWS CloudFormation DynamoDB Documentation)。
提供了 DynamoDB 的 arn
s 的语法,您可以通过以下方式检索表名:
Environment:
Variables:
TABLE_NAME: !Select [1, !Split ['/', !GetAtt DynamoDBTable.Arn]]
这将返回DynamoDBTableName
。
【讨论】:
您是正确的,公开的属性是 Arn 和 StreamArn。即调用 !GetAttr 但调用 !Ref 返回表名 "对于逻辑 ID 为 myDynamoDBTable 的资源,Ref 将返回 DynamoDB 表名。" 即Ref returns the name of the table【参考方案2】:!Ref
通过“逻辑名称”返回资源名称,应该适用于您的情况。但是资源(您的表)在您引用它之前应该存在,因此您有 2 个选项:
在模板的前面声明你的表资源(在你引用它之前)
在你的 lambda 上使用 DependsOn
属性
ServerlessFunction:
Type: AWS::Serverless::Function
DependsOn: DynamoDBTable
至于使用Fn::GetAtt
:
基于AWS Documentation,当您创建AWS::DynamoDB::Table
类型的资源时,Fn::GetAtt
只有两个属性可用:
Arn
StreamArn
这意味着在当前版本的 CloudFormation 中,无法使用 Fn::GetAtt
获取 DynamoDB 表的 TableName
属性。
【讨论】:
仅供参考:DependsOn 属性是隐式使用 !Ref (docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…)【参考方案3】:我也遇到了同样的问题,您似乎无法访问 TableName。
我正在做的解决方法是使用相同的表名调用 tamplate.yml 中的资源...
在template.yml中:
Globals:
Function:
Runtime: nodejs12.x
...
Environment:
Variables:
DYNAMODB_TABLE: !Ref MyDynamoTable
MyDynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: MyDynamoTable
AttributeDefinitions:
- AttributeName: PK
AttributeType: S
- AttributeName: SK
AttributeType: S
然后,在我的 .js 组件中:
const tableName = process.env.DYNAMODB_TABLE;
我希望他们能尽快解决这个问题......这种方式并不理想。 干杯!
【讨论】:
【参考方案4】:您能否通过查看控制台中的 lambda 函数并验证环境变量不低于应有的位置来验证这不起作用?
【讨论】:
【参考方案5】:即使 !Ref 确实返回了资源的逻辑 ID,在本例中为 DyanmoDB 表名,您需要在引用它之前确保该资源存在。
据我在您的代码中看到,函数创建不依赖于首先创建的 Dynamo 表
ServerlessFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs10.x
Handler: index.handler
Environment:
Variables:
TABLE_NAME: !Ref DynamoDBTable
Events:
GetCocktails:
Type: Api
Properties:
Path: /
Method: get
在这种情况下,CFN 将从上到下创建资源,这意味着 lambda 函数将在 DyanoDb 表之前创建,导致 !Ref 未定义,因为该表尚不存在。您可以通过添加对 lambda 资源的依赖项来解决此问题,如下所示:
ServerlessFunction:
DependsOn: DyanamoDBTable # <- will not be created before the dyanmoDB table
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs10.x
Handler: index.handler
Environment:
Variables:
TABLE_NAME: !Ref DynamoDBTable
Events:
GetCocktails:
Type: Api
Properties:
Path: /
Method: get
这将确保无论如何,首先创建您的表,然后不会取消定义资源的 !Ref,因为该表已经存在并且可以被引用
【讨论】:
可以参考这里资源的返回值docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…【参考方案6】:!Ref DynamoDBTable
从您的资源中返回 ARN,因此您会得到如下参考响应:
arn:aws:dynamodb:us-east-1:123456789012:table/testddbstack-myDynamoDBTable-012A1SL7SMP5Q/stream/2015-11-30T20:10:00.000
。
相反,您只需要提供名称DynamoDBTableName
,因此我的建议是使用!GetAtt CloudFormation 内部函数并获取名称:
!GetAtt DynamoDBTable.TableName
【讨论】:
我收到An error occurred (ValidationError) when calling the CreateChangeSet operation: Template error: resource myDynamoDbTable does not support attribute type TableName in Fn::GetAtt
实际上,AWS DynamoDB 资源的 !Ref
函数返回的是表名,而不是 ARN。尝试使用!GetAtt
时,我遇到了与上述评论相同的错误。我没有使用环境变量,但我可以使用!Ref
获取我的 DynamoDB 资源的表名。以上是关于在 AWS CloudFormation 模板中引用 !Ref DynamoDB 表名的主要内容,如果未能解决你的问题,请参考以下文章
AWS Inspector 的 AWS CloudFormation 模板能否添加 SNS 主题
如何使用 aws cloudformation 模板在 aws cognito 用户池中设置所需属性?
如何在 AWS CloudFormation YAML 模板中转义策略变量
AWS::ElasticBeanstalk::ConfigurationTemplate 的 AWS CloudFormation 模板失败