![](/img/trans.png)
[英]How to reference a dynamodb stream arn from an existing table in cloudformation?
[英]AWS CloudFormation: How to get stream ARN of DynamoDB GlobalTable replica?
我想通過 CloudFormation 在 eu-west-1 區域部署一個 DynamoDB 全局表,並在 ap-northeast-1 中有一個副本。 在每個區域中,我希望有一個 Lambda 來處理來自相應區域副本的事件。
我有興趣避免手動硬編碼 ap-northeast-1 中的 StreamArn 值。
我想出了以下模板(為清楚起見,僅顯示相關細節):
Conditions:
IsMainRegionCondition: !Equals [ !Ref AWS::Region, "eu-west-1" ]
Resources:
MyDynamoDB:
Condition: IsMainRegionCondition
Type: AWS::DynamoDB::GlobalTable
Properties:
Replicas:
- Region: eu-west-1
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
- Region: ap-northeast-1
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
DynamoToESFunction:
Type: AWS::Serverless::Function
Properties:
Events:
RawDynamoDBEvent:
Type: DynamoDB
Properties:
Stream: !GetAtt MyDynamoDB.StreamArn
這在 eu-west-1 中運行良好,但在 ap-northeast-1 中,我得到: Template format error: Unresolved resource dependencies [MyDynamoDB] in the Resources block of the template
。
我明白上面的方法不起作用,因為資源 MyDynamoDB 不是在 ap-northeast-1 中創建的。 但是,我想知道在不需要對 ARN 進行硬編碼的情況下,讓這個設置工作的最佳方法是什么。
我目前的想法是將我的 CloudFormation 堆棧拆分為 2:首先使用 DynamoDB 表部署一個堆棧,然后在第二個中引用(沒有硬編碼)副本的 StreamArn。
來自Global DynamoDB CloudFormation 文檔(在 Return values - StreamArn 下): The StreamArn returned is that of the replica in the region the stack is deployed to
。 因此,就我而言,這意味着它只能訪問 eu-west-1 中的值。
是否可以引用副本區域 (ap-northeast-1) 的 StreamArn 值而無需對其值進行硬編碼?
提前致謝。
在此博客條目的幫助下,我提出了使用自定義資源的以下解決方案。
簡而言之,我將我的堆棧分成 2 個:在一個中,我部署了DynamoDB::GlobalTable
以及一個Serverless::Function
,它將負責為我們獲取 ARN。 另一方面,我有 rest 的組件。
第一個堆棧的模板如下所示:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
DynamoTableName:
Type: "String"
Default: TableNameExample
MainRegion:
Type: "String"
Default: "eu-west-1"
Conditions:
IsMainRegionCondition: !Equals [ !Ref AWS::Region, !Ref MainRegion ]
Resources:
DynamoTable:
Condition: IsMainRegionCondition # Note: Deployed only in one region, replicated in others
Type: AWS::DynamoDB::GlobalTable
Properties:
TableName: !Ref DynamoTableName
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: entity_id
KeyType: HASH
- AttributeName: language
KeyType: RANGE
AttributeDefinitions:
- AttributeName: entity_id
AttributeType: S
- AttributeName: language
AttributeType: S
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
Replicas:
- Region: eu-west-1
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
- Region: us-east-1
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
GetGlobalTableStreamFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
TABLE_NAME: !Ref DynamoTableName
MemorySize: 256
CodeUri: functions/dynamo_db_stream/
Handler: app.lambda_handler
Runtime: python3.7
Policies:
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:DescribeTable
Resource: '*'
Outputs:
GetGlobalTableStreamFunctionArn:
Value: !GetAtt GetGlobalTableStreamFunction.Arn
Export:
Name: "get-global-table-stream-function-arn"
Lambda 的代碼如下(注意您需要沿 Lambda 打包crhelper
依賴項)。
import logging
import os
import boto3
from crhelper import CfnResource
TABLE_NAME = os.environ["TABLE_NAME"]
logger = logging.getLogger(__name__)
helper = CfnResource(
json_logging=False,
log_level='DEBUG',
boto_level='CRITICAL'
)
dynamo_db_client = boto3.client("dynamodb")
def lambda_handler(event, context):
helper(event, context)
def get_table_stream_arn():
logger.info(f"Getting stream ARN for table '{TABLE_NAME}'...")
response = dynamo_db_client.describe_table(
TableName=TABLE_NAME
)
logger.debug(f"Describe table response: {response}")
stream_arn = response["Table"]["LatestStreamArn"]
logger.info(f"ARN for table {TABLE_NAME}: {stream_arn}")
return stream_arn
@helper.create
def create(event, context):
logger.info("Received a 'Create' event")
stream_arn = get_table_stream_arn()
# This will make the stream ARN accessible via Cfn
# `!GetAtt DynamoTableStreamArnGetter.StreamArn`
helper.Data.update({"StreamArn": stream_arn})
return stream_arn
@helper.update
def update(event, context):
logger.info("Received an 'Update' event, doing nothing")
@helper.delete
def delete(event, context):
logger.info("Received a 'Delete' event, doing nothing")
然后,在第二個堆棧中,我們需要創建自定義資源。
Resources:
[...]
DynamoTableStreamArnGetter:
Type: 'Custom::DynamoTableStreamArnFunction'
Version: '1.0'
Properties:
ServiceToken: !ImportValue "get-global-table-stream-function-arn"
最后,您可以通過以下方式獲取/引用副本區域(在第二個堆棧模板中)中的 stream ARN:
!GetAtt DynamoTableStreamArnGetter.StreamArn
關於此解決方案的一些說明:
create(...)
function 中return stream_arn
。Resource: '*'
)。 但是,您無法在此處引用DynamoTable
資源,因為它不會存在於副本區域中。 如果有人知道將其限制在該表中的更好方法,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.