aws / aws/chalice

Race condition in CF template for custom domain mapping

Open
#1,735 14 comments 6 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
11.1k
Forks
1k
Avg merge
1d 22h
Merged PRs (30d)
2

Description

The way the `api_gateway_custom_domain` feature is represented in the CFN template generated by `chalice package` is currently prone to a race condition, but it’s relatively easy to fix.

**Issue**
Currently, the `ApiCustomDomainMapping` resource (I guess that’s of type `AWS::ApiGateway::BasePathMapping`) doesn’t wait until the `RestAPI`’s Stage resource has been created -- however, if that happens, its creation fails (as in the screenshot below).

![reproduction](https://user-images.githubusercontent.com/5318120/118348195-84a40780-b4fd-11eb-9696-5ee78f143d13.png)

That stage resource isn’t explicit in the template generated by Chalice because it’s only injected by the Serverless transform, and it’s then named `RestAPIStage` (in my screenshot it’s called `RestAPIv1Stage` because my stage is called `v1`); that's as per SAM [docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-generated-resources-api.html).

Fortunately the `RestAPI` (the `AWS::Serverless::Api`) has an attribute that conveniently serves to help with exactly that issue, namely `Stage` (i.e. `RestAPI.Stage`). That expression gets replaced by the SAM transform by the actual logical name of the stage resource that it injects. That is, the `!Ref RestAPI.Stage` becomes `!Ref RestAPIv1Stage` if the stage were called `v1` (also mentioned on the same SAM doc [page](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-generated-resources-api.html) where it says _Referenceable property_). And finally the `!Ref RestAPIv1Stage` resolves to the name of the stage (here `v1`), which is documented [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-stage.html) under Return Values. So the technique comes down to using `!Ref RestAPI.Stage` instead of the literal stage name (`v1` for me), which creates an explicit dependency of the base path mapping on the stage resource, and thus delays its creation until the stage has been created. That technique is also described in [this](https://github.com/aws/serverless-application-model/issues/192#issuecomment-520893111) git issue comment. With that fix, the stack creation succeeds as in the below screenshot.

![CF-dependencies](https://user-images.githubusercontent.com/5318120/118346876-9c768e00-b4f3-11eb-8cfc-147ec4c265d3.png)

At least one person commented that it the old (broken) behavior be non-deterministic, although in our stack the old version seems to fail pretty much every time (the new version always succeeds).

I made a PR that implements that, it’s basically 1 line and another line in the unit test. (for the record, one could also use a `DependsOn` and I had tried that too and it works too, but it’s addressed more concisely by simply referencing the .Stage attribute).

**Edit:** Concise rewrite of the issue description so it’s easier to follow.

Contributor guide

Open the contributing guide

Research direction

Start at the chalice package path that generates the CloudFormation template and inspect the ApiCustomDomainMapping resource and its unit test. Verify that the mapping waits for the generated API stage through the RestAPI Stage reference, then run the relevant unit test to confirm the dependency is represented correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, python
Domain
api, cloud
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.