Use Case
If you include execution of a Lambda in your CloudFormation template and you update your Lambda Code, CloudFormation will not execute your Custom Resource again unless it detects that the template or parameters have been changed.
Workaround - Include a Parameter
A very easy way to execute the Custom Resource every time when your Lambda changed is to add a parameter to your Custom Resource (eg. a timestamp, which will always be different) - if this parameter changes, the custom resources will automatically be executed again.
Parameters:
LambdaExecutionTimestamp:
Type: String
Default: 201906010800
Resources:
ExecuteLambda:
Type: 'Custom::ExecuteLambda'
Properties:
ServiceToken: !GetAtt
- Lambda
- Arn
Timestamp: !Ref LambdaExecutionTimestamp
If you are creating custom resources with lambda, you will also need to notify cloudformation if your script has successfully done executing. The python module cfnresponse helps you in giving a response back to Cloudformation about successful execution of the script.
Consider the following python code for your reference:
import boto3, os, botocore, cfnresponse
from botocore.exceptions import ClientError
# USE S3 SERVICE
s3 = boto3.client('s3')
# SET LOGGER
log = logging.getLogger()
log.setLevel(logging.INFO)
def lambda_handler(event, context):
s3_bucket = os.environ['s3_bucket']
check_bucket(s3_bucket, event, context)
# VERIFY IF BUCKET EXISTS
def check_bucket(bucket, event, context):
try:
s3.head_bucket(Bucket=bucket)
log.info("Bucket Exists!")
responseData = {'Success': 'Bucket Exists!'}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
return True
except ClientError as e:
error_code = int(e.response['Error']['Code'])
if error_code == 403:
log.info("Private Bucket. Forbidden Access!")
return True
elif error_code == 404:
log.info("Bucket Does Not Exist!")
responseData = {'Failed': 'Bucket Does not exists!'}
cfnresponse.send(event, context, cfnresponse.FAILED, responseData)
The cfnresponse
module is natively supported for python2 on AWS lambda. In case if you are using python3 on AWS Lambda, you will need to package cfnresponse
module along with its dependencies. After packaging you can add your custom python script into the package and upload it to lambda to get it executed.
Run the following commands to create a cfnresponse
package in linux:
1. pip install cfnresponse
2. pip install --target ./package cfnresponse
3. cd package
4. zip -r9 ../package.zip .
Now add your custom lambda script to the package.zip file
5. zip -g package.zip your-python-file.py
Hope this gives you the idea of how to create custom lambda callouts and also how to properly respond to cloudformation about the successful execution of your lambda scripts.