Ссылка! Ссылка на имя таблицы DynamoDB в шаблоне AWS CloudFormation

Я пытаюсь локально протестировать передачу имени таблицы DynamoDB, как указано в моем файле шаблона CloudFormation.

Из всей документации, которую я прочитал, я должен иметь возможность ссылаться на значение свойства 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, однако она возвращает значение undefined. Как заставить шаблон работать должным образом?


person McShaman    schedule 06.08.2019    source источник
comment
Я исправил ваш вопрос, указав на CloudFormation, потому что ваша проблема связана с CloudFormation, а не с SAM. Тем не менее, после беглого взгляда он должен работать так, как вы этого ожидаете. Не могли бы вы также добавить код своей функции AWS Lambda, в которой вы пытаетесь получить доступ к переменной среды?   -  person Dunedan    schedule 06.08.2019
comment
Я искал, как сделать то же самое, и нашел здесь ваш вопрос. То, что вы сделали, сработало для меня как есть. В любом случае спасибо, что спросили об этом здесь.   -  person Rami Yampolsky    schedule 29.12.2019
comment
Может ли кто-нибудь предоставить ответ / решение для шаблонов облачной информации в формате JSON?   -  person Sam Jett    schedule 03.06.2021


Ответы (6)


Как заявил кто-то другой, AWS :: DynamoDB :: Table предоставляет только следующие атрибуты: Arn и StreamArn (см. Документация по AWS CloudFormation DynamoDB).

Учитывая синтаксис arns DynamoDB, вы можете получить имя таблицы следующим образом:

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

который вернет DynamoDBTableName.

person Lord of the Goo    schedule 26.12.2019
comment
Вы правы, выставленные атрибуты - это Arn и StreamArn. то есть вызов! GetAttr, но один вызов! Ref возвращается имя таблицы - person Jason; 19.04.2020
comment
Для ресурса с логическим идентификатором myDynamoDBTable Ref вернет имя таблицы DynamoDB. т.е. Ref возвращает имя стол - person Samuel Prevost; 16.07.2020

!Ref возвращает имя ресурса по «логическому имени» и должно работать в вашей ситуации. Однако ресурс (ваша таблица) должен существовать до того, как вы на него ссылаетесь, поэтому у вас есть 2 варианта:

  • объявить ресурс таблицы ранее в шаблоне (перед тем, как ссылаться на него)

  • используйте свойство DependsOn в своей лямбде, например

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

Что касается использования Fn::GetAtt:

На основе Документация AWS при создании ресурса типа AWS::DynamoDB::Table для Fn::GetAtt доступны только 2 атрибута:

  • Arn
  • StreamArn

это означает, что в текущей версии CloudFormation невозможно получить атрибут TableName для таблицы DynamoDB с Fn::GetAtt.

person Andrew Kovalenko    schedule 18.12.2019
comment
К вашему сведению: атрибут DependsOn неявно используется с использованием! Ref (docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/) - person Fredrik Meyer; 26.02.2021

Не могли бы вы убедиться, что это не работает, посмотрев на лямбда-функцию в консоли и проверив переменную среды не ниже того места, где она должна быть?

person Nick Littrell    schedule 07.08.2019

Я боролся с тем же самым, похоже, вы не можете получить доступ к 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;

Надеюсь, они скоро решат эту проблему .... этот способ не идеален. Ваше здоровье!

person Nacho    schedule 31.03.2021

Несмотря на то, что! Ref действительно возвращает логический идентификатор ресурса, в данном случае имя таблицы 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 будет создавать ресурсы сверху вниз, что означает, что лямбда-функция будет создана перед таблицей DyanoDb, в результате чего! Ref будет неопределенным, учитывая тот факт, что таблица еще не существует. Вы можете исправить это, добавив зависимость от лямбда-ресурса следующим образом:

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

Это гарантирует, что несмотря ни на что, ваша таблица будет создана первой, а затем ссылка на ресурс не будет неопределенной, поскольку таблица уже существует и на нее можно ссылаться.

person ElRuncho    schedule 26.09.2019
comment
вы можете сослаться на возвращаемые значения ресурса здесь docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/ - person ElRuncho; 26.09.2019

!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

person Alfonso Ledesma    schedule 24.09.2019
comment
Я получаю An error occurred (ValidationError) when calling the CreateChangeSet operation: Template error: resource myDynamoDbTable does not support attribute type TableName in Fn::GetAtt - person Defozo; 02.12.2019
comment
Фактически функция !Ref для ресурса AWS DynamoDB возвращает имя таблицы, а не ARN. Я получал ту же ошибку, что и комментарий выше, при попытке использовать !GetAtt. Я не работаю с переменными среды, но я могу получить имя таблицы моего ресурса DynamoDB с помощью !Ref. - person david-ojeda; 04.12.2019