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):
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:
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 <module>
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:
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. Code is stored in the next order:
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
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).
UPDATE 19.03.2023
I discovered that the actual issue was that i wanted to keep the same chalice stage name for all Chalice constructs, so i set as scope for them the same stack. It seems chalice construct requires to be single per stack.
I tried to do so because now in chalice construct you cant set what chalice stage name from config file to use. It would be very nice to have such possibility, because now you have to set stage name based on stack full name, what is not very friedly if you migrate the existing app to cdk.
For ex. in my case i have next path dev/RestApi/App1 as chalice stage name. I will include that in the issues in project repository
Also, I ran some tests and discovered strage behavior, even though i succeeded to deploy different lambdas, it seems that CDK creates different APIs but with the same path&methods structure as in the first Chalice construct it happens when I deploy all stack at once (--all flag). Strange is that it maps these identical APIGateway (different ids but same path&methods definition) to different lambdas. It seems for API endpoints (for APIGateway) definition in all chalice projects is used always the first chalice project.