aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 56 forks source link

AWS::CloudFront::InvalildateCache #665

Closed deleugpn closed 1 year ago

deleugpn commented 4 years ago

2. Scope of request

Support for CloudFront Cache Invalidation through CloudFormation

3. Expected behavior

Whenever CloudFormation sees a AWS::CloudFront::InvalildateCache, I would expect it to:

In Create, CloudFormation sees the resource, sends out a request for cache invalidation and does not store the resource. In Update, since CloudFormation did not store the resource, it would see it as a brand new Resource that has to be created, meaning we get to invalidate the same cache on every update. Nothing happens on Delete as there's no actual resource to delete on CloudFormation.

4. Suggest specific test cases

Common use case: When deploying CloudFront via AWS CodePipeline with CloudFormation, every new deployment will automatically invalidate CloudFront's cache according to developer instructions.

5. Helpful Links to speed up research and evaluation

https://stackoverflow.com/questions/57033968/what-is-best-way-to-create-invalidation-after-cloud-formation-created-cloud-fron

6. Category

Networking & Content Delivery CloudFront CloudFormation Coverage

7. Any additional context

One way I'm avoiding this problem is to create the CloudFront distribution inside the same template that creates AWS CodePipeline. That means I get to pass CloudFront distribution (!Ref) into AWS CodeBuild step and setup invalidation using AWS CLI. However, that means I don't have a deployment template that I can change on my Git Repository which would get automatically updated on every deployment. Instead, every change needs to happen inside the same AWS CodePipeline template, which I have to manually update before every deployment.

jk2l commented 4 years ago

Correct me if I am wrong, but I think CloudFormation resource does not control the create/update state, it is the CloudFormation service check it first before trigger. So I think this suggestion is impossible to achive.

benbridts commented 4 years ago

Doing this as described is indeed impossible, an invalidation either exists or doesn't for CloudFormation (even if the invalidation completed).

One way to achieve this, without having to add a new invalidation resource and remove the old one every time is to have a Serial (or other input) like an IAM AccessKey. That way you can trigger the same invalidation without replacing the Logical resource (by changing the Serial and that triggers a replacement).


As a side note: I do believe that invalidations on deployment should be avoided in general. In most cases, there are better ways to solve updates behind a cache

benkehoe commented 4 years ago

Since you are already using CodePipeline, I would also suggest that a Lambda action in your pipeline could take care of invalidating the cache (and any other imperative actions that you need as part of your process).

deleugpn commented 3 years ago

@benkehoe A Lambda will have the same chicken-egg issue that I already face with CodeBuild. CodePipeline is being provisioned by a CFN stack. My deployment is another CFN. I can't know from my CodePipeline stack what will be my CloudFront Distribution ID if that Distribution is provisioned inside the Deploy Stack.

@benbridts I've done everything I could in terms of trying to make it so CloudFront never caches the index.html file but it always lead to cache problems after deployments without invalidation

benkehoe commented 3 years ago

You would use the DescribeStackResource CloudFormation API in a Lambda action after your deployment action, to look up the PhysicalResourceId for your distribution resource, which is the distribution id (the physical resource id is the value returned by Ref).

jk2l commented 3 years ago

@benkehoe A Lambda will have the same chicken-egg issue that I already face with CodeBuild. CodePipeline is being provisioned by a CFN stack. My deployment is another CFN. I can't know from my CodePipeline stack what will be my CloudFront Distribution ID if that Distribution is provisioned inside the Deploy Stack.

@benbridts I've done everything I could in terms of trying to make it so CloudFront never caches the index.html file but it always lead to cache problems after deployments without invalidation

@deleugpn if your CodePipeline also deploy the CNF. you can use OutputArtifact to get the Cfn return the outputs, then pass the outputs to your lambda step and let your lambda load it.

also you can update your lambda to fetch the Cfn stack via stack name and describe the output/resources

deleugpn commented 3 years ago

@jk2l That doesn't work. I can't !ImportValue on the CodePipeline Stack a value that has not been created yet by it's Deployment stage.

jk2l commented 3 years ago

@jk2l That doesn't work. I can't !ImportValue on the CodePipeline Stack a value that has not been created yet by it's Deployment stage.

I think you misunderstand what I mean. you can take Cfn's output pass it down as CodePipeline artefact and then from there read the artefact by your lambda's input artifact

TheDanBlanco commented 1 year ago

as described, this can't be achieved, and there are much better solutions.