Signaling Results

Signaling Success and Failure Back to CloudFormation

Test a handler with saved requests. This is the Create call CloudFormation 24 would send, except that its ResponseURL is an object in LocalStack 63,725 's S3 24 , which accepts unsigned PUTs:

infra/events/seed-create.json: a Create request, as CloudFormation sends itJSON
{"RequestType": "Create", "RequestId": "req-0001", "LogicalResourceId": "SeedBooks",
 "StackId": "arn:aws:cloudformation:us-east-1:000000000000:stack/booknest-seed/manual",
 "ResponseURL": "http://s3.localhost.localstack.cloud:4566/booknest-templates/responses/req-0001",
 "ResourceType": "Custom::BookSeed", "ResourceProperties": {"TableName": "booknest-seeded-books"}}
Invoking the provider with a Create request, then with a missing tableShell
aws lambda invoke --function-name booknest-seeder --cli-binary-format raw-in-base64-out \
  --payload file://events/seed-create.json /dev/null --query StatusCode
aws s3 cp s3://booknest-templates/responses/req-0001 - | jq -c '{Status, PhysicalResourceId, Data}'
BAD=$(jq -c '.RequestId = "req-0002" | .ResponseURL |= sub("0001"; "0002")
  | .ResourceProperties.TableName = "booknest-missing"' events/seed-create.json)
aws lambda invoke --function-name booknest-seeder --cli-binary-format raw-in-base64-out \
  --payload "$BAD" /dev/null --query StatusCode
aws s3 cp s3://booknest-templates/responses/req-0002 - | jq -c '{Status, Reason}'
Output
200
{"Status":"SUCCESS","PhysicalResourceId":"seed-booknest-seeded-books","Data":{"Count":6}}
200
{"Status":"FAILED","Reason":"ResourceNotFoundException: Cannot do operations on a non-existent
  table"}

The first call seeded the books and answered SUCCESS with the Count behind !GetAtt SeedBooks.Count. The second failed at DynamoDB 24 , yet Lambda 24 returned 200: the catch turned the error into a FAILED answer whose Reason appears in the stack events. That catch matters most: a handler that throws or times out before respond() sends nothing, and the stack waits out the full ServiceTimeout. Also handle a Delete for a resource whose Create failed, since rollback still sends one, and keep every request idempotent, since CloudFormation may repeat it.