Cloudformation 自定义资源 "Response is not valid JSON"

Cloudformation CustomResource "Response is not valid JSON"

我第一次尝试实现 Custom Resource。每当我尝试部署包含堆栈时,自定义资源的创建都会失败并显示“响应无效 JSON”,但我不确定为什么。

我的自定义资源代码如下:

import json
import os
import requests

import logging
# 
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


def handler(event, context):
    try:
        log.debug(f'DEBUG - called!')
        log.info(f'Event: {event}')
        if event['RequestType'] in ['Create', 'Update']:
          pass
          # I _will_ have logic here eventually - when this is working!
        else:
            log.info('Non-create/update RequestType')

        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html
        responseData = dict(
            {
                'Status': 'SUCCESS',
                'PhysicalResourceId': event['PhysicalResourceId']
                    if 'PhysicalResourceId' in event
                    else context.log_stream_name
            },
            **{key: event[key] for key in
               ['StackId', 'RequestId', 'LogicalResourceId']}
        )
        log.debug(f'Response data: {responseData}')
        requests.put(event['ResponseURL'], data=responseData)
    except Exception as e:
        log.error(f'Lambda failed! {e}')
        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html
        responseData = dict(
            {
                'Status': 'FAILED',
                'Reason': f'See logs in {context["logStreamName"]}',
                'PhysicalResourceId': event['PhysicalResourceId']
                    if 'PhysicalResourceId' in event
                    else context.log_stream_name,
            },
            **{key: event.get(key, '') for key in
               ['StackId', 'RequestId', 'LogicalResourceId']}
        )
        log.debug(f'Response data: {responseData}')
        requests.put(event['ResponseURL'], data=responseData)

来自 Create/Delete 循环的一些示例日志消息如下:

START RequestId: f151f270-acc6-4cff-b4c0-0eafaf4e5fef Version: $LATEST
[DEBUG] 2021-03-22T19:29:09.33Z f151f270-acc6-4cff-b4c0-0eafaf4e5fef    DEBUG - called!
[INFO]  2021-03-22T19:29:09.33Z f151f270-acc6-4cff-b4c0-0eafaf4e5fef    Event: {'RequestType': 'Create', 'ServiceToken': 'arn:aws:lambda:us-east-1:119281758091:function:prod-stage-ApplicationSta-FetchCommitHistoryFuncti-T7Z15V6TDZSO', 'ResponseURL': 'https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A119281758091%3Astack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1%7CFetchCommitsCustomResource%7C1d80a8f0-f72c-4e50-8039-6c0509dd24ee?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20210322T192907Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=AKIA6L7Q4OWT3GW5BT7K%2F20210322%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=4cc0d2590330f42e8928bdfc2bf5a30c31bfb6228d681e11acf25ef17b8dde2c', 'StackId': 'arn:aws:cloudformation:us-east-1:119281758091:stack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1', 'RequestId': '1d80a8f0-f72c-4e50-8039-6c0509dd24ee', 'LogicalResourceId': 'FetchCommitsCustomResource', 'ResourceType': 'AWS::CloudFormation::CustomResource', 'ResourceProperties': {'ServiceToken': 'arn:aws:lambda:us-east-1:119281758091:function:prod-stage-ApplicationSta-FetchCommitHistoryFuncti-T7Z15V6TDZSO'}}
[DEBUG] 2021-03-22T19:29:09.293Z    f151f270-acc6-4cff-b4c0-0eafaf4e5fef    Response data: {'Status': 'SUCCESS', 'PhysicalResourceId': '2021/03/22/[$LATEST]8801d1d794c04d25ad31fa43223cbe93', 'StackId': 'arn:aws:cloudformation:us-east-1:119281758091:stack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1', 'RequestId': '1d80a8f0-f72c-4e50-8039-6c0509dd24ee', 'LogicalResourceId': 'FetchCommitsCustomResource'}
END RequestId: f151f270-acc6-4cff-b4c0-0eafaf4e5fef
REPORT RequestId: f151f270-acc6-4cff-b4c0-0eafaf4e5fef  Duration: 444.73 ms Billed Duration: 445 ms Memory Size: 128 MB Max Memory Used: 61 MB  Init Duration: 463.55 ms    
START RequestId: 616f7c98-1d76-4459-96d3-6257c5620a99 Version: $LATEST
[DEBUG] 2021-03-22T19:29:20.640Z    616f7c98-1d76-4459-96d3-6257c5620a99    DEBUG - called!
[INFO]  2021-03-22T19:29:20.640Z    616f7c98-1d76-4459-96d3-6257c5620a99    Event: {'RequestType': 'Delete', 'ServiceToken': 'arn:aws:lambda:us-east-1:119281758091:function:prod-stage-ApplicationSta-FetchCommitHistoryFuncti-T7Z15V6TDZSO', 'ResponseURL': 'https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A119281758091%3Astack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1%7CFetchCommitsCustomResource%7C85da252d-1d0d-4fe5-84eb-755f1e6dc646?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20210322T192920Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=AKIA6L7Q4OWT3GW5BT7K%2F20210322%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=0bd2e0a28783980b9014289cd852bf02252cdf5cd11f4405d00707002e6e39e9', 'StackId': 'arn:aws:cloudformation:us-east-1:119281758091:stack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1', 'RequestId': '85da252d-1d0d-4fe5-84eb-755f1e6dc646', 'LogicalResourceId': 'FetchCommitsCustomResource', 'PhysicalResourceId': 'prod-stage-ApplicationStack-FetchCommitsCustomResource-1VTI0Q0VKIJDM', 'ResourceType': 'AWS::CloudFormation::CustomResource', 'ResourceProperties': {'ServiceToken': 'arn:aws:lambda:us-east-1:119281758091:function:prod-stage-ApplicationSta-FetchCommitHistoryFuncti-T7Z15V6TDZSO'}}
[INFO]  2021-03-22T19:29:20.640Z    616f7c98-1d76-4459-96d3-6257c5620a99    Non-create/update RequestType
[DEBUG] 2021-03-22T19:29:20.640Z    616f7c98-1d76-4459-96d3-6257c5620a99    Response data: {'Status': 'SUCCESS', 'PhysicalResourceId': 'prod-stage-ApplicationStack-FetchCommitsCustomResource-1VTI0Q0VKIJDM', 'StackId': 'arn:aws:cloudformation:us-east-1:119281758091:stack/prod-stage-ApplicationStack/94d24fa0-8b44-11eb-a285-0ec6977a61f1', 'RequestId': '85da252d-1d0d-4fe5-84eb-755f1e6dc646', 'LogicalResourceId': 'FetchCommitsCustomResource'}
END RequestId: 616f7c98-1d76-4459-96d3-6257c5620a99
REPORT RequestId: 616f7c98-1d76-4459-96d3-6257c5620a99  Duration: 174.97 ms Billed Duration: 175 ms Memory Size: 128 MB Max Memory Used: 61 MB  

JSON 对我来说是有效的(特别是,PhysicalResourceId 是非空的,这是我第一次使用 event['PhysicalResourceId'] 获取它时的一个问题。问题是什么?

我认为您可能需要在 requests.put.

中将字典转换为 json 字符串

试试这样的东西:

requests.put(event['ResponseURL'], data=json.dumps(responseData))