aws / chalice

Python Serverless Microframework for AWS
Apache License 2.0
10.67k stars 1.01k forks source link

chalice.cdk Chalice object with custom domain generates broken sam.json file #1640

Open gentili opened 3 years ago

gentili commented 3 years ago

Steps to reproduce

  1. chalice new-project
  2. test
  3. [CDK] Rest API with a DynamoDB table
  4. edit test/infrastructure/stacks/chaliceapp.py
        self.chalice = Chalice(
            self, 'ChaliceApp', source_dir=RUNTIME_SOURCE_DIR,
            stage_config={
                "api_gateway_custom_domain": {
                    "domain_name": "api.example.com",
                    "certificate_arn": "arn:aws:acm:us-east-1:1234567:certificate/00000-00000-000000",
                    },
                'environment_variables': {
                    'APP_TABLE_NAME': self.dynamodb_table.table_name
                }
            }
        )
  5. cdk synth

    output

    
    jsii.errors.JavaScriptError:
    Error: Element used in Ref expression with logical ID: 'RestAPI.Stage' not found
      at CfnParser.parseIfCfnIntrinsic (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/core/lib/cfn-parse.js:409:31)
      at CfnParser.parseValue (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/core/lib/cfn-parse.js:379:39)
      at CfnParser.parseValue (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/core/lib/cfn-parse.js:385:33)
      at Function._fromCloudFormation (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/aws-apigateway/lib/apigateway.generated.js:554:51)
      at CfnInclude.getOrCreateResource (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/cloudformation-include/lib/cfn-include.js:557:48)
      at new CfnInclude (/tmp/jsii-kernel-5AgLxw/node_modules/@aws-cdk/cloudformation-include/lib/cfn-include.js:66:18)
      at /tmp/tmpq4500vx5/lib/program.js:2700:58
      at Kernel._wrapSandboxCode (/tmp/tmpq4500vx5/lib/program.js:3128:24)
      at Kernel._create (/tmp/tmpq4500vx5/lib/program.js:2700:34)
      at Kernel.create (/tmp/tmpq4500vx5/lib/program.js:2441:29)

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "app.py", line 6, in ChaliceApp(app, 'cdktest') File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_runtime.py", line 83, in call inst = super().call(*args, kwargs) File "/mnt/c/Users/gentili/git/cdktest/infrastructure/stacks/chaliceapp.py", line 19, in init self.chalice = Chalice( File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_runtime.py", line 83, in call inst = super().call(*args, *kwargs) File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/chalice/cdk/construct.py", line 77, in init self.sam_template = cloudformation_include.CfnInclude( File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_runtime.py", line 83, in call inst = super().call(args, kwargs) File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/aws_cdk/cloudformation_include/init.py", line 396, in init jsii.create(CfnInclude, self, [scope, id, props]) File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_kernel/init.py", line 265, in create response = self.provider.create( File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_kernel/providers/process.py", line 347, in create return self._process.send(request, CreateResponse) File "/home/gentili/.virtualenvs/concursion-infrastructure/lib/python3.8/site-packages/jsii/_kernel/providers/process.py", line 329, in send raise JSIIError(resp.error) from JavaScriptError(resp.stack) jsii.errors.JSIIError: Element used in Ref expression with logical ID: 'RestAPI.Stage' not found

### Cause
package.py:730
```python
        template['Resources'][cfn_name + 'Mapping'] = {
            'Type': 'AWS::ApiGateway::BasePathMapping',
            'Properties': {
                'DomainName': {'Ref': 'ApiGatewayCustomDomain'},
                'RestApiId': {'Ref': 'RestAPI'},
                'BasePath': domain_name.api_mapping.mount_path,
                'Stage': {'Ref': 'RestAPI.Stage'},
            }
        }

The generated sam.json file references RestAPI.Stage when no corresponding AWS::ApiGateway::Stage resource has been specified.

Workaround

comment out 'Stage': {'Ref': 'RestAPI.Stage'},

gentili commented 3 years ago
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:        20.04
Codename:       focal

node.packages.txt python.packages.txt

jamesls commented 3 years ago

I believe this is due to the schema definition the CDK uses not being correct (https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/cfnspec/spec-source/000_sam.spec.json), or possibly in the way that it validates references (there is no Stage property on a AWS::Serverless::Api but you can reference MyApi.Stage).

The SAM template works if you deploy it on its own outside of the CDK, and the SAM documentation specifies how to reference the stage resource:

To reference the stage resource, use <api-logical-id>.Stage.

There's also more details in the docs for AWS CloudFormation resources generated when AWS::Serverless::Api is specified.

Ideally we can fix this upstream in the aws-cdk repo so I think it makes sense to file an issue there and see what they say.

jbourjeli commented 3 years ago

The workaround says to comment a line in package.py. Where can I find this file? Can you please elaborate? Any help appreciated.

Thanks

gentili commented 3 years ago

@jbourjeli The file is wherever you pip installed the chalice package. Mine is in my virtual environment in lib/python3.9/site-packages/chalice/package.py

mrmikemon commented 3 years ago

Thanks for noting this one. Its killing my cdk pipeline at the moment. Any resolution in sight?

noxjonas commented 2 years ago

also encountering this issue with cdk. the workaround indeed works, but perhaps someone found a different way that does not involve changing the source?

tried finding a way to reference RestAPI.Stage and adding dependency but with no success