【问题标题】:AWS CloudFormation event hanging in CREATE_IN_PROGRESS state after custom resource (lambda) invocation调用自定义资源 (lambda) 后,AWS CloudFormation 事件以 CREATE_IN_PROGRESS 状态挂起
【发布时间】:2020-02-13 04:35:30
【问题描述】:

我有一个 lambda,它有一个 python 脚本来在参数存储中创建一个 application.properties 文件。我有一个调用此 lambda 以创建 application.properties 的 cloudformation 模板。我的 cloudformation 模板如下所示:

{
   "Description": "Create SSM Parameter",
   "Resources": {
      "primerinvoke": {
         "Type": "AWS::CloudFormation::CustomResource",
         "Properties": {
            "Handler": "lambda_function.lambda_handler",
            "ServiceToken": "arn:aws:lambda:us-east-1:1234:function:test_lambda",
            "FunctionName": "test_lambda"
         }
      }
   }
}

我创建SSM参数的python脚本(路径是:/myapp/dev/test/application.properties)是:

import boto3
import os

region = os.environ['AWS_REGION']
client = boto3.client('ssm')
def ssm_create():
    response = client.put_parameter(Name='/myapp/'
                                    + os.environ['environment']
                                    + '/test/application.properties',
                                    Description='string',
                                    Value='APPLICATION_NAME=myapp',
                                    Type='SecureString', Overwrite=True)
    return response
def lambda_handler(event, context):
    PutParameterResult = ssm_create()

我按照AWS lambda: No module named 'cfnresponse' 中的建议使用了import cfnresponse,但是导入不起作用,我不知道如何在 lambda 外部安装 cfnresponse 库。

代码成功运行,这意味着 cloudformation 模板能够调用 lambda 及其脚本并创建 SSM 参数,但在我的脚本中的 ssm_create() 函数完成后挂起。我不知道如何将“SUCCESS”状态从我的脚本返回到 cloudformation 堆栈,以防止它挂在CREATE_IN_PROGRESS 状态。

任何帮助将不胜感激!谢谢。

EDIT1:我将代码更新为:

responseStatus = 'SUCCESS'
responseBody={}
def sendResponse(event, context, responseStatus):
            responseBody = {'Status': responseStatus,
                            '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'],
                            }
            print 'RESPONSE BODY:n' + json.dumps(responseBody)
def lambda_handler(event, context):
                logger.info(event)
                test_ssm_create()
                try:
                    req = requests.put(event['ResponseURL'], data=json.dumps(sendResponse(event, context, responseStatus)))
                    if req.status_code != 200:
                        print req.text
                        raise Exception('Recieved non 200 response while sending response to CFN.')
                except requests.exceptions.RequestException as e:
                    print e
                    raise
                return
                print("COMPLETE")

req.status_code 给出 200,但 cloudformation 堆栈再次卡在 CREATE_IN_PROGRESS。仍然不确定如何使这项工作。

【问题讨论】:

    标签: python aws-lambda amazon-cloudformation


    【解决方案1】:

    如 CloudFormation 文档中所述,CloudFormation 期望您的 Lambda 函数在完成操作后回调它; CloudFormation 将暂停执行,直到收到此回调。 CloudFormation 向您的 Lambda 函数发送的事件包含回调 URL (ResponseURL),如下例所示:

    {
       "RequestType" : "Create",
       "ResponseURL" : "http://pre-signed-S3-url-for-response",
       "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/stack-name/guid",
       "RequestId" : "unique id for this create request",
       "ResourceType" : "Custom::TestResource",
       "LogicalResourceId" : "MyTestResource",
       "ResourceProperties" : {
          "Name" : "Value",
          "List" : [ "1", "2", "3" ]
       }
    }
    

    如果您无法导入cfnresponse 模块,这似乎是python2 代码,您应该可以使用python3 进行模拟。尝试在 lambda_handler 函数中添加类似此代码的内容。请注意,this AWS documentation page 中详述了响应中的必需键(即 PhysicalResourceId、StackId、RequestId、LogicalResourceId,这些键可以直接添加,请参阅文档)。

    import requests
    import json
    import uuid
    
    status = {'Status': 'SUCCESS',
              'PhysicalResourceId': 'MyResource_' + str(uuid.uuid1()),
              'StackId': event['StackId'],
              'RequestId': event['RequestId'],
              'LogicalResourceId': event['LogicalResourceId']
             }
    r = requests.put(event['ResponseURL'], data=json.dumps(status))
    

    所以要编辑您问题中的代码:

    responseStatus = 'SUCCESS'
    
    def getResponse(event, context, responseStatus):
                responseBody = {'Status': responseStatus,
                                'PhysicalResourceId': context.log_stream_name,
                                'StackId': event['StackId'],
                                'RequestId': event['RequestId'],
                                'LogicalResourceId': event['LogicalResourceId'],
                                }
                responseBody = json.dumps(responseBody)
                print 'RESPONSE BODY:n' + responseBody
    
                return responseBody
    
    def lambda_handler(event, context):
                    logger.info(event)
                    test_ssm_create()
                    try:
                        req = requests.put(event['ResponseURL'], data=getResponse(event, context, responseStatus))
                        if req.status_code != 200:
                            print req.text
                            raise Exception('Received non 200 response while sending response to CFN.')
                    except requests.exceptions.RequestException as e:
                        print e
                        raise
                    return
                    print("COMPLETE")
    

    【讨论】:

    • 堆栈从CREATE_IN _PROGRESS 向前移动到CREATE_FAILED,在那里它给出了一个错误,指出无效的 PhysicalResourceId。我通过提供r.PhysicalResourceID = context.LogStreamName 尝试了此解决方案链接,但不确定如何将其提供给 cloudformation 堆栈。请告诉我。
    • @nikitakakra 看起来我错过了响应中的一些必填字段。这应该很容易解决。看这里,当我走到电脑前时,我会编辑我的答案。 docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…
    • 我遵循了您共享的文档,但堆栈仍然卡住。您能在帖子中看到我的编辑以及我编写的新代码吗?我可能在那里做错了什么,但不确定是什么
    • @nikitakakra 我认为您遇到的问题是变量范围,我将根据您的最新代码发布我的答案更新。
    • @nikitakakra 太棒了,请不要忘记接受答案。
    猜你喜欢
    • 2020-07-11
    • 1970-01-01
    • 2023-04-11
    • 2022-01-23
    • 2016-07-17
    • 2017-07-23
    • 2021-10-24
    • 2021-10-27
    • 2021-05-11
    相关资源
    最近更新 更多