Deploy a CloudFormation stack containing an autopublished CloudFront function without updating the associated CloudFront distribution if the function is unchanged

0

I am using AWS CloudFormation to deploy a stack containing a CloudFront distribution using a CloudFront function. The template contains the following entries:

CloudFrontFunction:
  Type: "AWS::CloudFront::Function"
  Properties:
    Name: "my-function"
    AutoPublish: true
    FunctionConfig:
      Comment: "My function"
      Runtime: "cloudfront-js-1.0"
    FunctionCode: |
      function handler(event) { /* ommitted for brievity */ }
CloudFrontDistribution:
  Type: "AWS::CloudFront::Distribution"
  Properties:
    ...
    DefaultCacheBehavior:
      FunctionAssociations:
        - EventType: "viewer-request"
          FunctionARN:
            "Fn::GetAtt": "CloudFrontFunction.FunctionARN"

Each time I deploy the stack using this template, CloudFormation updates the CloudFront function even if the function has not changed (I suspect this is caused by AutoPublish: true, but I need this setting to be enabled).

This results in CloudFormation also updating the distribution, which takes several minutes, and often simply fails (my guess is that the CloudFront API is not very reliable during peak traffic hours), resulting in our CD pipeline also failing.

Is there a way to avoid this behavior (e.g. do not publish the function if it has not changed)? I might put the function in another template/stack and keep this stack outside of our CD pipeline, but it's tedious to have to handle the function updates manually.

1 Answer
0
  CloudFrontFunction:
    Type: "AWS::CloudFront::Function"
    Properties:
      Name: "my-function"
      AutoPublish: true
      FunctionConfig:
        Comment: "My function"
        Runtime: "cloudfront-js-1.0"
      FunctionCode: !Sub |
        function handler(event) {
            var request = event.request;

            var response = "string"; // Create the response object here,
                                // using the request properties if needed.

            return response;
        }

Hi there,

I understand that you suspect the AutoPublish: true[1] caused the CFN stack triggers the update on this resource every time a stack update operation triggered.

It is not the case and I confirmed with code snippet above, when there is no literal changes to the AWS::CloudFront::Function, it will not be updated. How a property is defined in a resource type has nothing to do with how CloudFormation judge if there are changes to make in next operation, unless you have addition Transform features integrated into the template. Based on your code snippet, looks like you are using inline code for the CF-Function, please scrutinize if there are changes made between two stack update operations.

To decide a resource in the stack requires update or not, CFN service simple performs "create changeset" mechanism before stack operation, only literal changes detected for a resource so it will be put in to the changeset-resources require update.

If no obvious changes you can observe, please consider:

  1. Do you have Transform in the template
  2. Does the inline code referring to a Parameter or other resources that require update each operation

If still struggle, please consider create a support ticket to AWS support for stack in-depth check.

References: [1] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-function.html#aws-resource-cloudfront-function-properties

AWS
answered 2 years ago
  • There is no change in the template file (it is being executed from a CD pipeline so it's easy to check), but we are indeed using a transform and the sam deploy CLI to deploy the stack. The stack contains a lambda + API gateway which is used as an origin in the same CloudFront distribution in a cache behavior unrelated to the one using the CloudFront function. Only the lambda's code is being updated, but CloudFormation actually updates the CloudFront function and this operation alone takes ~ 3 minutes on each deploy and is blocking the distribution update.

  • Thanks for confirming there is a SAM transform in the template, and if it is in a CD pipeline and I am sure there are changes to your template otherwise CD will tell you cannot create a changeset if you follow the best practice with "create change set action" before execute changeset.

    While you mention you are using SAM Deploy CLI means actually you are deploying the stack in build stage?

  • Like I said, if there is no change to the CloudFront Function after transformed template, stack will not put that resource into the change set actions. You can easily create the stand alone AWS::CloudFront::Function in a stack to test.

    Having said that, I don't have full picture of your template and the stack history, if you find it is difficult to investigate yourself, create a support ticket can have an engineer assist you effectively.

  • When we use the sam deploy CLI command, the cloudformation template goes through 3 states: first, we provide the input template to the CLI ; then the CLI inserts various things in the template, such as code URIs for lambda functions ; then the template is transformed by cloudformation and can be processed. What I meant by "no change in the template" is "no change in the template we provide to the CLI". The CLI does generate a modified template at step 2 because the code URI of the lambdas it contains are updated. This should be the only change in the template at this stage, though.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions