Race condition in CF template for custom domain mapping
- 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).

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.

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
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