是否可以在 AppSync 解析器中引用 CloudFormation 资源名称?

Is it possible to reference a CloudFormation resource name in an AppSync resolver?

我有一些 DynamoDB table 资源,我在我的 CloudFormation 模板(用 YAML 编写)中配置,并在模板的其他地方配置 AppSync 端点。

我没有指定 table 的名称,而是让 CloudFormation 为它们生成名称。每当我需要指定 table 名称时,我都会使用

!Ref TableName

我想在 AppSync 中使用 DynamoDB Batch 解析器,这需要我列出 table 的名称,但是“!Ref TableName”不会转换为 table 当我更新堆栈时。解析器以“!Ref TableName”作为 table 名称结束。

有没有办法将 CloudFormation 生成的 table 的名称获取到 AppSync 模板语言中?

下面是我的 CloudFormation 模板,经过相关性修剪:

conversationsTable:
Type: "AWS::DynamoDB::Table"
Properties:
  AttributeDefinitions:
    -
      AttributeName: "id"
      AttributeType: "S"
  KeySchema:
    -
      AttributeName: "id"
      KeyType: "HASH"
  ProvisionedThroughput:
    ReadCapacityUnits: "1"
    WriteCapacityUnits: "1"

userConversationsTable:
Type: "AWS::DynamoDB::Table"
Properties:
  AttributeDefinitions:
    -
      AttributeName: "userId"
      AttributeType: "S"
    -
      AttributeName: "conversationId"
      AttributeType: "S"
  KeySchema:
    -
      AttributeName: "userId"
      KeyType: "HASH"
    -
      AttributeName: "conversationId"
      KeyType: "RANGE"
  ProvisionedThroughput:
    ReadCapacityUnits: "1"
    WriteCapacityUnits: "1"

...

createConversationMutationResolver:
Type: "AWS::AppSync::Resolver"
Properties:
  ApiId: !GetAtt chatQLApi.ApiId
  TypeName: "Mutation"
  FieldName: "createConversation"
  DataSourceName: !GetAtt conversationsTableDataSource.Name
  RequestMappingTemplate: |
    {
      "version" : "2018-05-29",
      "operation" : "BatchPutItem",
      "tables": {
        !Ref conversationsTable : $util.toJson($convoList),
        !Ref userConversationsTable : $util.toJson($users)
      }
    }
  ResponseMappingTemplate: |
    #if($context.error)
      $util.appendError($context.error.message, $context.error.message)
    #end
    {
      "conversation": $util.toJson("${context.result.data}!Ref conversationTable")
      "userConversations": $util.toJson("${context.result.data}!Ref userConversationsTable")
    }

阅读有关 intrinsic functions, I was able to achieve my goal using the Sub and Join 函数的 CloudFormation 文档后。

在 RequestMapping 模板中,我使用 Fn::Sub 将两个 VTL 变量设置为 table 的名称,然后我使用 Fn::Join 将带有替换的字符串连接到模板字符串的其余部分。

在 ResponseMapping 模板中,我在模板代码中为所有需要 table 名称的内容放置了占位符,并将这些占位符与 Fn::Sub 相匹配。然后,为了将 table 名称附加到上下文对象路径,我使用 Fn::Join 完全使用 CloudFormation 模板构建该路径,并将其放入 Fn::Sub 使用的替换映射中。

下面是我上面的模板,有变化

createConversationMutationResolver:
Type: "AWS::AppSync::Resolver"
Properties:
  ApiId: !GetAtt chatQLApi.ApiId
  TypeName: "Mutation"
  FieldName: "createConversation"
  DataSourceName: !GetAtt conversationsTableDataSource.Name
  RequestMappingTemplate:
    !Join
      - ''
      - - !Sub
           - |
             #set($conversationTable = "${conversationsTable}")
             #set($userConversationTable = "${userConversationsTable}")
           - { conversationTable: !Ref conversationsTable, userConversationTable: !Ref userConversationsTable }
        - |
          {
            "version" : "2018-05-29",
            "operation" : "BatchPutItem",
            "tables": {
              "${conversationTable}" : $util.toJson($convoList),
              "${userConversationTable}" : $util.toJson($users)
            }
          }
  ResponseMappingTemplate:
    !Sub
      - |
        #if($context.error)
          $util.appendError($context.error.message, $context.error.message)
        #end
        {
          "${conversation}": $util.toJson(${conversationContext})
          "${userConversations}": $util.toJson(${userConversationContext})
        }
      - {
          conversation: !Ref conversationsTable,
          userConversations: !Ref userConversationsTable,
          conversationContext: !Join [ '.', ["$context.result.data", !Ref conversationsTable]],
          userConversationContext: !Join [ '.', ["$context.result.data", !Ref userConversationsTable]]
        }