Reputation: 3985
I am trying to locally test passing the table name of a DynamoDB table as declared in my CloudFormation template file.
From all the documentation I have read, I should be able to reference the the TableName
property value of a DynamoDB resource using the !Ref
intrinsic function. However when I test this locally the property is undefined.
Consider the following example:
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
I expect the TABLE_NAME
environment variable to be DynamoDBTableName
however it returns undefined. How do I get the template to work as expected?
Upvotes: 18
Views: 15918
Reputation: 119
I was struggling with the same, it looks like you can't access the TableName.
The workaround I'm doing is to call the resource in the tamplate.yml with the same table name...
In 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
Then, in my .js component:
const tableName = process.env.DYNAMODB_TABLE;
I hope they solve this soon.... this way is not ideal. Cheers!
Upvotes: 5
Reputation: 1287
As stated by someone else the only attributes exposed by an AWS::DynamoDB::Table are:
Arn
and StreamArn
(See AWS CloudFormation DynamoDB Documentation).
Provided the syntax of the DynamoDB's arn
s you can retrieve the table name in the following way:
Environment:
Variables:
TABLE_NAME: !Select [1, !Split ['/', !GetAtt DynamoDBTable.Arn]]
which will return DynamoDBTableName
.
Upvotes: 17
Reputation: 6710
!Ref
returns a name of the resource by "logical name" and should work for your situation. However resource (your table) should exists before you reference it, so you have 2 options:
declare you table resource earlier in the template (before you reference it)
use DependsOn
property on your lambda like
ServerlessFunction:
Type: AWS::Serverless::Function
DependsOn: DynamoDBTable
As for using Fn::GetAtt
:
Based on AWS Documentation when you create a resource of type AWS::DynamoDB::Table
there are only 2 attributes available for Fn::GetAtt
:
Arn
StreamArn
which means there is no way to get TableName
attribute for DynamoDB table with Fn::GetAtt
in current version of CloudFormation.
Upvotes: 1
Reputation: 29
Even though !Ref does return the Logical id of the resource, in this case the DyanmoDB table name, you need to make sure that the resource exist before referencing it.
As far as I can see in your code the function creation is not dependent on the Dynamo table beign created first
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
In this case CFN will create resources from top to bottom meaning the lambda function will be created before the DyanoDb table causing the !Ref to be undefined given the fact that the table does not exist yet. You can fix this by adding a dependency on the lambda resource like so:
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
This will make sure that no matter what, your table is created first and then the !Ref to the resource will not be undefined since the table already exist and can be referenced
Upvotes: -2
Reputation: 1
The !Ref DynamoDBTable
returns the ARN from your resource so, you get your reference response like this:
arn:aws:dynamodb:us-east-1:123456789012:table/testddbstack-myDynamoDBTable-012A1SL7SMP5Q/stream/2015-11-30T20:10:00.000
.
Instead you only need to provide the name DynamoDBTableName
so, my suggestion is to use !GetAtt CloudFormation intrinsic function and get the name:
!GetAtt DynamoDBTable.TableName
Upvotes: -5