Using AWS CDK & Chalice construct received duplicated lambdas in synthed sam template
- Dominant language
- Python
- Stars
- 11.1k
- Forks
- 1k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 2
Description
Hi,
on project we had single Chalice project for the whole API + pure lambdas (cloudwatch events, triggers etc) and as the project had grown, lambdas generated by project became bigger and bigger. We decided to split it into several chalice project that will be combined to single API under Custom domain name. For easy management&deploy we decided to put them in CDK project.
As a result I created next stack that contains declaration of all chalice constructs (component_with_stack_declaration.py):
```python
class RestApi(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
...
code_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "src")
app1 = Chalice(self, "App1", source_dir=os.path.join(code_dir, "app1"))
app2= Chalice(self, "App2", source_dir=os.path.join(code_dir, "app2"))
...
```
When I ran `cdk synth` I got next traceback:
```shell
Creating deployment package.
Creating deployment package.
jsii.errors.JavaScriptError:
@jsii/kernel.RuntimeError: Error: section 'Resources' already contains 'Lambda1LogicalID'
at Kernel._ensureSync (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:10364:27)
at Kernel.invoke (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:9764:34)
at KernelHost.processRequest (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:11539:36)
at KernelHost.run (C:\Users\....\Local\Temp\tmpgg97w2wj\lib\program.js:11499:22)
at Immediate._onImmediate (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:11500:46)
at processImmediate (node:internal/timers:466:21)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "B:\...\cdk_app\app.py", line 15, in
app.synth()
File "B:\....\cdk_app\venv\lib\site-packages\aws_cdk\__init__.py", line 20043, in synth
return typing.cast(_CloudAssembly_c693643e, jsii.invoke(self, "synth", [options]))
File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\__init__.py", line 149, in wrapped
return _recursize_dereference(kernel, fn(kernel, *args, **kwargs))
File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\__init__.py", line 399, in invoke
response = self.provider.invoke(
File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\providers\process.py", line 377, in invoke
return self._process.send(request, InvokeResponse)
File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\providers\process.py", line 339, in send
raise RuntimeError(resp.error) from JavaScriptError(resp.stack)
RuntimeError: Error: section 'Resources' already contains 'Lambda1LogicalID'
```
When I looked in the generated in cdk.out and chalice.out templates i saw that this lambda is actually declared twice.
Example from .sam_with_assets.json files in generated chalice.out folder:
```shell
Chalice app1
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Outputs": {},
"Resources": {
"Lambda1LogicalID": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Runtime": "python3.9",
"Handler": "chalicelib.app1.handler.lambda1",
"CodeUri": {
"Bucket": "cdk-hnb659fds-assets-XXXXXXXXXXXX-us-east-1",
"Key": "963f64d496d61b07c0f89b0c476f7ff9a0ebdc17e4f8b80484a4f957eecca97e.zip"
},
"Tags": {
"aws-chalice": "version=1.27.3:stage=dev/RestApi:app=app1"
},
...
Chalice app2
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Outputs": {},
"Resources": {
"Lambda1LogicalID": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Runtime": "python3.9",
"Handler": "chalicelib.app1.handler.lambda1",
"CodeUri": {
"Bucket": "cdk-hnb659fds-assets-XXXXXXXXXXXX-us-east-1",
"Key": "972986e72385367de3787cc5004baa8efe91c8c98335a070ee636b9f7519afd7.zip"
},
"Tags": {
"aws-chalice": "version=1.27.3:stage=dev/RestApi:app=app2"
},
...
```
As you can see they are identical apart `aws-chalice` tag and key in bucket. I checked several times within generated .zip assets, they contained correct 2 different chalice project code, but for some reason template of second chalice project (app2) contains all the same lambdas as in the first project (app1) and doesnt contain any lambdas that are declared in code of the .zip archive that is created for it.
I tried to place Chalice constructs in separate inner stacks of RestApi stack, but got the same result - differect assets with code but same template with same lambdas' resources (apart tags).
Code is stored in the next order:
```shell
cdk_app
| - app.py
| - restapi_stack
| - component_with_stack_declaration.py
| - src
| - app1
| | - .chalice
| chalicelib
| app.py
| - app2
| - .chalice
chalicelib
app.py
```
Maybe someone had similar issue? I would be happy to receive your feedback
Contributor guide
Research direction
Start with restapi_stack/component_with_stack_declaration.py and reproduce the issue with cdk synth. Compare the generated chalice.out .sam_with_assets.json files for app1 and app2, then trace how each Chalice construct contributes its SAM resources. Done means both projects retain their distinct Lambda resources and synthesis no longer fails with duplicate Lambda1LogicalID.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python
- Domain
- cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100