我正在尝试通过 AWS CDK Python Workshop 来提高自己的技能,我按照 WorkShop Guide 中的说明编写了以下代码,但在创建 DynamoDB 表的条目时卡住了。
AWS CDK 研讨会指南链接
代码
hitcount.py文件中的代码
import json
import os
import boto3
ddb = boto3.resource("dynamodb")
table = ddb.Table(os.environ["HITS_TABLE_NAME"])
_lambda = boto3.client("lambda")
def handler(event, context):
print("request : {}".format(json.dumps(event)))
table.update_item(
key = {"path": event["path"]},
UpdateExpression = "ADD hits: incr",
ExpressionAttributeValues = {":incr": 1}
)
resp = _lambda.invoke(
FunctionName= os.environ["DOWNSTREAM_FUNCTION_NAME"],
Payload = json.dumps(event),
)
body = resp["Payload"].read()
print("Downstream Response: {}".format(body))
return json.loads(body)
hitcounter.py文件中的代码
from constructs import Construct
from aws_cdk import (
aws_lambda as _lambda,
aws_dynamodb as ddb,
)
class HitCounter(Construct):
@property # need to check what is the purpose of this decorator and the two lines of code.
def handler(self):
return self._handler
def __init__(self, scope:Construct, id:str, downstream: _lambda.IFunction, **kwargs):
super().__init__(scope, id, **kwargs)
table = ddb.Table(
self, 'Hits',
partition_key={'name': 'path', 'type': ddb.AttributeType.STRING}
)
self._handler = _lambda.Function(
self,'HitCountHandler',
runtime= _lambda.Runtime.PYTHON_3_10,
handler='hitcount.handler',
code = _lambda.Code.from_asset("lambda"),
environment={
"DOWNSTREAM_FUNCTION_NAME": downstream.function_name,
"HITS_TABLE_NAME": table.table_name,
}
)
table.grant_read_write_data(self._handler)
downstream.grant_invoke(self._handler)
cdk_workshop_stack.py 文件中的代码
from constructs import Construct
from aws_cdk import (
Duration,
Stack,
aws_lambda as _lambda,
aws_apigateway as apigw,
)
from .hitcounter import HitCounter
class CdkWorkshopStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Defines an AWS Lamdba resource
my_lambda = _lambda.Function(
self,
"HelloHandler",
runtime= _lambda.Runtime.PYTHON_3_10,
code= _lambda.Code.from_asset("lambda"),
handler="hello.handler",
)
# apigw.LambdaRestApi(
# self, "Endpoint",
# handler= my_lambda,
# )
hello_with_counter = HitCounter(
self, 'HelloHitCounter',
downstream= my_lambda,
)
apigw.LambdaRestApi(
self, 'EndPoint',
handler= hello_with_counter.handler,
)
我在 Cloud watch 日志中看到错误
[ERROR] ParamValidationError: Parameter validation failed:
Missing required parameter in input: "Key"
Unknown parameter in input: "key", must be one of: TableName, Key, AttributeUpdates, Expected, ConditionalOperator, ReturnValues, ReturnConsumedCapacity, ReturnItemCollectionMetrics, UpdateExpression, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues, ReturnValuesOnConditionCheckFailure
Traceback (most recent call last):
File "/var/task/hitcount.py", line 12, in handler
table.update_item(
File "/var/runtime/boto3/resources/factory.py", line 581, in do_action
response = action(self, *args, **kwargs)
File "/var/runtime/boto3/resources/action.py", line 88, in __call__
response = getattr(parent.meta.client, operation_name)(*args, **params)
File "/var/runtime/botocore/client.py", line 565, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 974, in _make_api_call
request_dict = self._convert_to_request_dict(
File "/var/runtime/botocore/client.py", line 1048, in _convert_to_request_dict
request_dict = self._serializer.serialize_to_request(
File "/var/runtime/botocore/validate.py", line 381, in serialize_to_request
raise ParamValidationError(report=report.generate_report())
我期待在 DynamoDB 中创建一个条目
在您共享的代码中,密钥为小写
k
,而按照 CDK 研讨会中的定义,它应该为大写:
import json
import os
import boto3
ddb = boto3.resource('dynamodb')
table = ddb.Table(os.environ['HITS_TABLE_NAME'])
_lambda = boto3.client('lambda')
def handler(event, context):
print('request: {}'.format(json.dumps(event)))
table.update_item(
Key={'path': event['path']}, # Upper case K for Key
UpdateExpression='ADD hits :incr',
ExpressionAttributeValues={':incr': 1}
)
resp = _lambda.invoke(
FunctionName=os.environ['DOWNSTREAM_FUNCTION_NAME'],
Payload=json.dumps(event),
)
body = resp['Payload'].read()
print('downstream response: {}'.format(body))
return json.loads(body)