apigateway: Unable to import existing API Gateway with Stage (`Stage.from_stage_attributes` returns `__StageBaseProxy`)
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
Hello folks,
We previously deployed a Stack with an API Gateway via the Serverless framework, and decided to switch to CDK and hence rewrote the Stack configuration in CDK.
We managed to let CDK recognize most of the existing resources by overriding the logical IDs, e.g.
```python
rest_api = aws_apigateway.RestApi(...)
rest_api.node.default_child.override_logical_id("")
```
This way CDK recognizes (or imports) the resources in the already existing Stack and updates them (if required) instead of deleting and re-creating. This works well for the RestApi. However, we also have a Stage that already exists for the RestApi, and doing the same with the existing Stage leads to the error `Stage already exists`. Here it seems that CDK is not able to recognize the existing Stage and just import it, but attempts to create a new one with the same name instead.
Hence, we attempted to just reference the existing Stage using `aws_apigateway.Stage.from_stage_attributes` as
```python
rest_api = aws_apigateway.RestApi(
scope=scope,
id="RestApi",
rest_api_name="name",
deploy=False,
)
# Explicitly set logical ID to import existing RestApi previously deployed by Serverless
rest_api.node.default_child.override_logical_id("RestApi")
deployment = aws_apigateway.Deployment(
scope=scope,
id="Deployment",
api=rest_api,
stage_name="dev",
)
stage = aws_apigateway.Stage.from_stage_attributes(
scope=scope,
id="Stage",
rest_api=rest_api,
stage_name="dev",
)
# Since `aws_apigateway.RestApi` has `deploy=False`, we need to explicitly set this attribute.
rest_api.deployment_stage = stage
```
and this then fails because
```
TypeError: type of argument value must be aws_cdk.aws_apigateway.Stage; got aws_cdk.aws_apigateway._StageBaseProxy instead
```
According to the [docs](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_apigateway/Stage.html#aws_cdk.aws_apigateway.Stage.from_stage_attributes) `aws_apigateway.Stage.from_stage_attributes` should return `IStage`, but apparently it seems to return `_StageBaseProxy` instead.
Thanks for the help in advance!
Moving from Serverless to CDK has generally been a great experience, at least from the point where we discovered the `override_logical_id` "hack", since that allowed us to import all previously existing resources that were part of the stacks, and didn't require `cdk import`.
### Expected Behavior
`aws_cdk.aws_apigateway.Stage.from_stage_attributes` returns `aws_cdk.aws_apigateway.IStage`
### Current Behavior
`aws_cdk.aws_apigateway.Stage.from_stage_attributes` returns `aws_cdk.aws_apigateway._StageBaseProxy`
### Reproduction Steps
```python
import aws_cdk
import aws_cdk.aws_apigateway as aws_apigateway
import constructs
class Stack(aws_cdk.Stack):
def __init__(
self,
scope: constructs.Construct,
**kwargs,
) -> None:
super().__init__(
scope=scope,
id="Stack",
**kwargs,
)
rest_api = aws_apigateway.RestApi(
scope=self,
id="RestApi",
rest_api_name="name",
deploy=False,
)
stage = aws_apigateway.Stage.from_stage_attributes(
scope=self,
id="Stage",
rest_api=rest_api,
stage_name="dev",
)
# Since `aws_apigateway.RestApi` has `deploy=False`, we need to explicitly set this attribute.
rest_api.deployment_stage = stage
app = aws_cdk.App()
Stack(scope=app)
```
then `cdk synth`
### Possible Solution
_No response_
### Additional Information/Context
It is also worth mentioning that the Stage (and its corresponding Deployment) do currently _not_ appear as a Resource of the Stack as of the state Serverless created! It just exists in the AWS API Gateway Console (or area, idk how to describe it). It seems that it was previously implicitly created by setting `Stage` attributes in Serverless, e.g.
```yaml
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: "name"
Domain:
Type: 'AWS::ApiGateway::DomainName'
Properties:
CertificateArn: ""
DomainName: ""
EndpointConfiguration:
Types:
- EDGE
ApiBasePathMapping:
Type: 'AWS::ApiGateway::BasePathMapping'
Properties:
DomainName: !Ref Domain
RestApiId: !Ref RestApi
Stage: "dev"
```
### CDK CLI Version
2.138.0 (build 6b41c8b)
### Framework Version
_No response_
### Node.js Version
v21.7.3
### OS
Ubuntu 22.04 LTS
### Language
Python
### Language Version
3.12.0
### Other information
```
Traceback (most recent call last):
File "/home/user/engine/app.py", line 16, in
stack.Stack(
File "/home/user/.cache/pypoetry/virtualenvs/engine-2aWaQfPc-py3.12/lib/python3.12/site-packages/jsii/_runtime.py", line 118, in __call__
inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/engine/stack.py", line 37, in __init__
engine_api_gateway, engine_api_gateway_v1 = apigateway.create_resources(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/engine/apigateway.py", line 58, in create_resources
rest_api.deployment_stage = stage
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/.cache/pypoetry/virtualenvs/engine-2aWaQfPc-py3.12/lib/python3.12/site-packages/aws_cdk/aws_apigateway/__init__.py", line 23101, in deployment_stage
check_type(argname="argument value", value=value, expected_type=type_hints["value"])
File "/home/user/.cache/pypoetry/virtualenvs/engine-2aWaQfPc-py3.12/lib/python3.12/site-packages/typeguard/__init__.py", line 785, in check_type
raise TypeError(
TypeError: type of argument value must be aws_cdk.aws_apigateway.Stage; got aws_cdk.aws_apigateway._StageBaseProxy instead
```
Contributor guide
Research direction
Start with the reproduction using Stage.from_stage_attributes and the RestApi.deployment_stage assignment, then inspect the Stage and IStage entry points and their generated Python bindings. Done means the imported stage can be assigned as the deployment stage without the _StageBaseProxy type error and the example synthesizes successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python, typescript
- Domain
- backend-api-design, cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100