问题描述
我需要创建一个 DynamoDB 表,这是它作为参数在 CloudFormation 模板中传递的属性值之一:
DynamoDB 表应如下所示:
PhoneNumber | OrderNumber
223546421 11545154
784578745 11547854
223458784 11547487
XXXXXXXXX 11578451
属性值“XXXXXXXXX”需要作为 CloudFormation 模板中的参数传递,以便创建 DynamoDB 表并填充上述信息。
这是构建 DynamoDB 表的当前 CF 模板:
{
"AWstemplateFormatVersion": "2010-09-09","Resources": {
"OrdersTable": {
"Type": "AWS::DynamoDB::Table","Properties": {
"TableName": "ClientOrders","AttributeDeFinitions": [
{
"AttributeName": "PhoneNumber","AttributeType": "S"
},{
"AttributeName": "OrderNumber","AttributeType": "S"
}
],"KeySchema": [
{
"AttributeName": "PhoneNumber","KeyType": "HASH"
},"KeyType": "RANGE"
}
],"TimetoLiveSpecification": {
"AttributeName": "ExpirationTime","Enabled": true
},"ProvisionedThroughput": {
"ReadCapacityUnits": "10","WriteCapacityUnits": "5"
}
},"DependsOn": [
"DynamoDBQueryPolicy"
]
},"DynamoDBQueryPolicy": {
"Type": "AWS::IAM::Policy","Properties": {
"PolicyName": "DynamoDBQueryPolicy","PolicyDocument": {
"Version": "2012-10-17","Statement": [
{
"Effect": "Allow","Action": "dynamodb:Query","Resource": "*"
}
]
},"Roles": [
{
"Ref": "OrdersTableQueryRole"
}
]
}
},"OrdersTableQueryRole": {
"Type": "AWS::IAM::Role","Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17","Principal": {
"Service": [
"dynamodb.amazonaws.com"
]
},"Action": [
"sts:AssumeRole"
]
}
]
},"Path": "/"
}
}
}
}
我需要帮助来用上面提到的值填充表格以及如何将提到的属性值作为参数传递。
对此的任何帮助将不胜感激。
谢谢
解决方法
我们需要 custom cloudformation 资源才能将条目添加到 Dynamo 表中。
来自文档:
使用 Lambda 函数和自定义资源,您可以在 响应堆栈事件(创建、更新和删除)。
此自定义资源调用 Lambda 函数并将 StackName 属性作为输入发送给它。该函数使用此属性从适当的堆栈中获取输出。
这是我为 1 个键创建的示例,需要一些小的更改:
我们需要两件事。
一个,一个保存 Lambda 函数的堆栈。有了这个,我们没有一个 cloudformation 资源,当我们添加/删除/更新资源时,它会在幕后调用这个 Lambda。这通常一起进入单独的堆栈。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DynamoCfnLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: '/'
Policies:
- PolicyName: dynamodbAccessRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:*
Resource: '*'
- Effect: Allow
Action:
- logs:*
Resource: '*'
CfnCrtUpdDltDynamodbDocumentLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: 'cfn-crt-upd-dlt-dynamodb-document'
Code:
ZipFile: >
const AWS = require("aws-sdk");
const response = require("./cfn-response");
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event,context) {
console.log(JSON.stringify(event,null,2));
var item = JSON.parse(event.ResourceProperties.DynamoItem);
var keyProperty = event.ResourceProperties.DynamoKeyProperty;
var tableName = event.ResourceProperties.DynamoTableName;
if (event.RequestType == "Create" || event.RequestType == "Update") {
console.log("item:",item);
var params = {
TableName: tableName,Item: item
};
console.log("Creating or Updating Document");
docClient.put(params,function(err,data) {
if (err) {
console.log('error creating/updating document',err);
response.send(event,context,"FAILED",{},tableName + '_' + item[keyProperty]);
} else {
response.send(event,"SUCCESS",tableName + '_' + item[keyProperty]);
}
});
}
if (event.RequestType == "Delete") {
console.log("Deleting a Document");
var params = {
TableName: tableName,Key: {
[keyProperty]: item[keyProperty]
}
};
docClient.delete(params,data) {
if (err) {
response.send(event,{});
} else {
response.send(event,{});
}
});
}
};
Handler: index.handler
Role: !GetAtt DynamoCfnLambdaRole.Arn
Runtime: nodejs10.x
Timeout: 60
其次,我们需要添加资源块 Custom::ThisCouldBeAnything
,其中 ServiceToken
指向我们上面创建的 Lambda Arn。每当我们
- 在任何 cloudformation 中添加一个新块,Lambda 将通过 Create 调用,从而在 Dynamo 表中创建一个条目。
- 从 Cloudformation 中删除块,将使用 Delete 调用 Lambda,从 Dynamo 表中删除条目。
- 更改资源块中的某些内容,例如更改 DynamoItem 中的某些内容,Lambda 将通过 Update 调用。
对于需要插入 Dynamo 的每条记录,我们都需要一个资源块。
Resources:
MyPhone223546421:
Type: Custom::CrtUpdDltDynamodbDocumentLambda
Properties:
ServiceToken: !GetAtt CfnCrtUpdDltDynamodbDocumentLambda.Arn
DynamoTableName: My-Table
DynamoKeyProperty: 'PhoneNumber'
DynamoItem: |
{
"PhoneNumber": "223546421","OrderNumber": "11545154","someKey": "someValue"
}
MyPhone784578745:
Type: Custom::CrtUpdDltDynamodbDocumentLambda
Properties:
ServiceToken: !GetAtt CfnCrtUpdDltDynamodbDocumentLambda.Arn
DynamoTableName: My-Table
DynamoKeyProperty: 'PhoneNumber'
DynamoItem: |
{
"PhoneNumber": "784578745","OrderNumber": "11547854","someKey": "someValue"
}
,
本机无法通过 CloudFormation 向 DynamoDB 表添加行。 CloudFormation 是一种旨在创建/管理基础设施而非数据的工具。我建议在一个单独的过程中这样做。例如,如果您通过 CodePipeline 进行部署,您可以有一个在创建 CloudFormation 后运行的 CodeBuild 作业。该代码几乎可以做任何你想让它做的事情。
可以选择创建 custom resource 或 resource provider,但虽然有可能,但我认为这不符合其预期目的。