python3(lambda 函数)无法将响应发送回云形成模板
python3(lambda function) failing to send response back to cloud formation template
我已经使用lambda创建了一个用于跨s3-bucket对象复制的云形成模板,它是用python编写的,下面是lambda代码。
import json
import logging
import signal
import boto3
from urllib.request import *
s3 = boto3.resource('s3')
s3client = boto3.client('s3')
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)
def lambda_handler(event, context):
sourcebucketname = event['ResourceProperties']['SourceBucketName']
destinationbucketname = event['ResourceProperties']['DestinationBucketName']
accountid = boto3.client('sts').get_caller_identity()['Account']
try:
LOGGER.info('REQUEST RECEIVED:\n %s', event)
LOGGER.info('REQUEST RECEIVED:\n %s', context)
if event['RequestType'] == 'Create':
LOGGER.info('CREATE!')
response = s3client.list_objects(Bucket=sourcebucketname)
print(response)
for record in response['Contents']:
key = record['Key']
dest_key = key
copy_source = {'Bucket': sourcebucketname, 'Key': key}
destbucket = s3.Bucket(destinationbucketname)
response = destbucket.copy(copy_source, dest_key, ExtraArgs={'ACL':'bucket-owner-full-control'})
print(response)
print('{} transferred to destination bucket'.format(key))
send_response(event, context, "SUCCESS",
{"Message": "Resource creation successful!"})
elif event['RequestType'] == 'Update':
LOGGER.info('UPDATE!')
send_response(event, context, "SUCCESS",
{"Message": "Resource update successful!"})
elif event['RequestType'] == 'Delete':
LOGGER.info('DELETE!')
send_response(event, context, "SUCCESS",
{"Message": "Resource deletion successful!"})
else:
LOGGER.info('FAILED!')
send_response(event, context, "FAILED",
{"Message": "Unexpected event received from CloudFormation"})
except: #pylint: disable=W0702
LOGGER.info('FAILED!')
send_response(event, context, "FAILED", {
"Message": "Exception during processing"})
def send_response(event, context, response_status, response_data):
'''Send a resource manipulation status response to CloudFormation'''
response_body = json.dumps({
"Status": response_status,
"Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
"PhysicalResourceId": context.log_stream_name,
"StackId": event['StackId'],
"RequestId": event['RequestId'],
"LogicalResourceId": event['LogicalResourceId'],
"Data": response_data
})
response_bdy=response_body.encode('utf-8')
LOGGER.info('ResponseURL: %s', event['ResponseURL'])
LOGGER.info('ResponseBody: %s', response_body)
opener = build_opener(HTTPHandler)
request = Request(event['ResponseURL'], data=response_bdy)
request.add_header('Content-Type', '')
request.add_header('Content-Length', len(response_body))
request.get_method = lambda: 'PUT'
response = opener.open(request)
LOGGER.info("Status code: %s", response.getcode())
LOGGER.info("Status message: %s", response.msg)
s3 对象已成功复制到目标存储桶,但 lambda 函数无法将事件响应发送回云形成。下面是我得到的错误。
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
Traceback (most recent call last):
File "/var/task/index.py", line 47, in lambda_handler
send_response(event, context, "FAILED", {
File "/var/task/index.py", line 69, in send_response
response = opener.open(request)
File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open
req = meth(req)
File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_
raise TypeError(msg)
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str. Traceback (most recent call last): File "/var/task/index.py", line 47, in lambda_handler send_response(event, context, "FAILED", { File "/var/task/index.py", line 69, in send_response response = opener.open(request) File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open req = meth(req) File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_ raise TypeError(msg)
send_response 函数因上述错误而失败,请帮助哪里出错了。
错误消息告诉你出了什么问题。
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
在您的代码中,response_body
是一个 str
。您可以通过 response_body.encode('utf-8')
.
将其转换为 bytes
我已经使用lambda创建了一个用于跨s3-bucket对象复制的云形成模板,它是用python编写的,下面是lambda代码。
import json
import logging
import signal
import boto3
from urllib.request import *
s3 = boto3.resource('s3')
s3client = boto3.client('s3')
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)
def lambda_handler(event, context):
sourcebucketname = event['ResourceProperties']['SourceBucketName']
destinationbucketname = event['ResourceProperties']['DestinationBucketName']
accountid = boto3.client('sts').get_caller_identity()['Account']
try:
LOGGER.info('REQUEST RECEIVED:\n %s', event)
LOGGER.info('REQUEST RECEIVED:\n %s', context)
if event['RequestType'] == 'Create':
LOGGER.info('CREATE!')
response = s3client.list_objects(Bucket=sourcebucketname)
print(response)
for record in response['Contents']:
key = record['Key']
dest_key = key
copy_source = {'Bucket': sourcebucketname, 'Key': key}
destbucket = s3.Bucket(destinationbucketname)
response = destbucket.copy(copy_source, dest_key, ExtraArgs={'ACL':'bucket-owner-full-control'})
print(response)
print('{} transferred to destination bucket'.format(key))
send_response(event, context, "SUCCESS",
{"Message": "Resource creation successful!"})
elif event['RequestType'] == 'Update':
LOGGER.info('UPDATE!')
send_response(event, context, "SUCCESS",
{"Message": "Resource update successful!"})
elif event['RequestType'] == 'Delete':
LOGGER.info('DELETE!')
send_response(event, context, "SUCCESS",
{"Message": "Resource deletion successful!"})
else:
LOGGER.info('FAILED!')
send_response(event, context, "FAILED",
{"Message": "Unexpected event received from CloudFormation"})
except: #pylint: disable=W0702
LOGGER.info('FAILED!')
send_response(event, context, "FAILED", {
"Message": "Exception during processing"})
def send_response(event, context, response_status, response_data):
'''Send a resource manipulation status response to CloudFormation'''
response_body = json.dumps({
"Status": response_status,
"Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
"PhysicalResourceId": context.log_stream_name,
"StackId": event['StackId'],
"RequestId": event['RequestId'],
"LogicalResourceId": event['LogicalResourceId'],
"Data": response_data
})
response_bdy=response_body.encode('utf-8')
LOGGER.info('ResponseURL: %s', event['ResponseURL'])
LOGGER.info('ResponseBody: %s', response_body)
opener = build_opener(HTTPHandler)
request = Request(event['ResponseURL'], data=response_bdy)
request.add_header('Content-Type', '')
request.add_header('Content-Length', len(response_body))
request.get_method = lambda: 'PUT'
response = opener.open(request)
LOGGER.info("Status code: %s", response.getcode())
LOGGER.info("Status message: %s", response.msg)
s3 对象已成功复制到目标存储桶,但 lambda 函数无法将事件响应发送回云形成。下面是我得到的错误。
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
Traceback (most recent call last):
File "/var/task/index.py", line 47, in lambda_handler
send_response(event, context, "FAILED", {
File "/var/task/index.py", line 69, in send_response
response = opener.open(request)
File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open
req = meth(req)
File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_
raise TypeError(msg)
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str. Traceback (most recent call last): File "/var/task/index.py", line 47, in lambda_handler send_response(event, context, "FAILED", { File "/var/task/index.py", line 69, in send_response response = opener.open(request) File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open req = meth(req) File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_ raise TypeError(msg)
send_response 函数因上述错误而失败,请帮助哪里出错了。
错误消息告诉你出了什么问题。
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
在您的代码中,response_body
是一个 str
。您可以通过 response_body.encode('utf-8')
.
bytes