我有一个带python脚本的lambda,可以在参数存储区中创建application.properties文件。我有一个cloudformation模板,该模板调用此lambda来创建application.properties。我的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参数(其路径为/myapp/dev/test/application.properties)的python脚本为:
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。仍然不确定如何进行这项工作。
答案 0 :(得分:2)
如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")