在AWS CloudFormation模板中引用!Ref DynamoDB表名称

时间:2019-08-06 03:23:44

标签: amazon-cloudformation aws-sam

我正在尝试在本地测试传递CloudFormation模板文件中声明的DynamoDB表的表名。

从我阅读的所有文档中,我应该能够使用TableName内在函数来引用DynamoDB资源的!Ref属性值。但是,当我在本地测试此属性时,该属性未定义。

考虑以下示例:

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,但是它返回未定义的值。如何使模板按预期工作?

6 个答案:

答案 0 :(得分:1)

您是否可以通过在控制台中查看lambda函数并在不应该位于其预期位置的下方验证环境变量来验证其是否无效?

答案 1 :(得分:0)

!Ref通过“逻辑名称”返回资源的名称,并且应该适合您的情况。但是,资源(您的表)在引用之前应该已经存在,因此您有2个选择:

  • 在模板的较早位置(在引用之前)声明您的表资源

  • 在您的lambda上使用DependsOn属性,例如

ServerlessFunction:
    Type: AWS::Serverless::Function
    DependsOn: DynamoDBTable

关于使用Fn::GetAtt

基于AWS Documentation,当您创建类型为AWS::DynamoDB::Table的资源时,Fn::GetAtt只有2个属性可用:

  • Arn
  • StreamArn

,这意味着在当前版本的CloudFormation中,无法使用TableName获取DynamoDB表的Fn::GetAtt属性。

答案 2 :(得分:0)

如其他人所述,AWS :: DynamoDB :: Table公开的唯一属性是: ArnStreamArn(请参阅AWS CloudFormation DynamoDB Documentation)。

提供了DynamoDB arn的语法,您可以通过以下方式检索表名:

      Environment: 
        Variables:
          TABLE_NAME: !Select [1, !Split ['/', !GetAtt DynamoDBTable.Arn]] 

这将返回DynamoDBTableName

答案 3 :(得分:0)

我也遇到了同样的问题,您似乎无法访问 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 :(得分:-1)

!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

答案 5 :(得分:-2)

即使!Ref确实返回了资源的逻辑ID,在本例中为DyanmoDB表名,您仍需要在引用之前确保该资源存在。

据我在您的代码中看到的那样,函数的创建不依赖于首先创建的Dynamo表beign

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进行定义,因为该表已经存在并且可以被引用