serverless: Cloudformation custom resources' functions are not run on subsequent deploys
This is a Bug Report
Description
For bug reports:
-
What went wrong? I created a cloudformation custom resource and set its handler to a serverless function (see steps to reproduce below). This is surprisingly easy to setup, and seems to work well on first deploy. I can confirm that the custom resource causes the lambda to run and its data property is received through cloudformation logs. Problem is that if I now change the function (e.g. have it return something else), and redeploy (
sls deploy), the custom resource is not triggered again, and the reference to the custom resource value (Fn::GetAtt: [MyCustomResource, test]) remains the old value and not the updated value. There are no more logs in cloudformation, i.e. the function never run. -
What did you expect should have happened? On subsequent deploys, I expect the function to be run again as it was updated and therefore the custom resource to now expose updated attributes as returned by the updated function.
-
What was the config you used?
serverless.yml
service: simple-cr
provider:
name: aws
runtime: nodejs6.10
memorySize: 512
timeout: 10
stage: ${opt:stage, 'dev'}
region: ${opt:region, 'eu-west-2'}
custom:
customResourceValue:
Fn::GetAtt: [MyCustomResource, test]
functions:
customResource:
handler: custom.handler
resources:
Resources:
MyCustomResource:
Type: Custom::MyCustomResource
Properties:
ServiceToken:
Fn::GetAtt: [CustomResourceLambdaFunction, Arn]
custom.js
const response = require('cfn-response');
exports.handler = function(event, context) {
console.log('sending hello as custom resource lambda function handler response');
return response.send(event, context, response.SUCCESS, {
test: 'hello'
});
};
- What stacktrace or error message from your provider did you see?
Similar or dependent issues:
Steps to reproduce
- create above 2 files
serverless.ymlandcustom.js - run
npm install --save cfn-response - run
sls deploy - confirm that cloudwatch has log entries for the lambda function, i.e. the custom resource works
- change the output of the function from
test: 'hello'to something else, liketest: 'goodbye' - run
sls deploy - notice that there are no cloudwatch entries and that the custom value
Fn::GetAtt: [MyCustomResource, test]still refers to the old value returned by the previous function
Additional Data
- Serverless Framework Version you’re using: 1.24.1
- Operating System: OSX
- Stack Trace:
- Provider Error messages:
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 4
- Comments: 19 (7 by maintainers)
@simlu not really… I worked around it with a somewhat ugly hack, forcing it to recreate on each deploy using a unique parameter UUID:
serverless.yml
uuid.js
You can set
SomeRandomProperty: ${env:RANDOM}whereas set the env var firstexport RANDOM=$(date +%s).$RANDOM will then be the current timestamp. Not nice. But there is no other fix currently, right? Custom resource seems to work in pure CF. Why not here?@simlu we could, but I am afraid this might be considered as a “feature” by them.
I believe that Cloudformation creates an internal state, and then if the resource is already created once, it won’t be created again unless you previously deleted it. If you then change the parameters of the resource, it will be run again with the
Updateevent.RequestType.But this does not make sense for custom resources that need to perform a certain check on each deploy. In that case perhaps the most pragmatic way would be to use a unique ID in the parameters?
One behavior I do not understand is that currently cloudformation seems to send a
Deleterequest type after creating the resource, as if it wants to clean it up again. The challenge then becomes to distinguish between a “cleanup” delete and a “permanent” delete (i.e. one where the resource is removed from the stack or the stack itself is deleted).You can see this strange delete behavior from the update stack progress:
Question is why the DELETE_IN_PROGRESS ever starts when the custom resource is in the stack.
Update: seems the above delete behavior is due to not passing in a physical resource ID. To be confirmed, but highly likely.