amit suthar
amit suthar

Reputation: 31

Reusing Existing API gateway (Created in another stack) and adding resources and methods to it. Update Stage of deployment

We have a CDK for our ApiGateway which has a root resource-path . We have many lambda functions: we want Lambda-cdk's to add resource paths to existing resource paths, whether they are created by this lambda's CDK stack, or another lambda's CDK stack.

e.g. /user, /account etc.

If another Stack creates an Api Deployment, the ApiGateway Stage should point to these new deployments

Use Case CdkApiGateway

adds resource path /v1 deploy : true stage: DEV


Problem: We are able to import the API gateway using (python cdk) api = apigateway.RestApi.from_rest_api_attributes(self, 'company_api_id-dev', rest_api_id=api_gateway_id, root_resource_id=api_gateway_root_id) `

Newly added resources are reflecting in "resources" in API gateway console but not in already deployed stage "dev".


Any way to achieve this as I don't want to create different API gateway for each service and its resources and use it like "services.company.com/user/" "services.company.com/account/"


Tried: As mentioned in AWS CDK documentation, Adding a new deployment along with including dependencies is still not able to update the stage.

`       test_resource = root_resource.add_resource("test1")

        deployment = apigateway.Deployment(self, f'root-deploy-{env_name}', api=api)
        deployment.node.add_dependency(test_resource)
        deployment.add_to_logical_id(timestamp)`

Do I have to create a new staging too ? though I want it in the existing stage. Tried it like below: apigateway.Stage(self, f'user-stage-{env_name}', deployment=deployment, stage_name=env_name)

But it is throwing error mentioning "dev" stage already exist, which make sense.


References used: https://github.com/aws/aws-cdk/issues/12755 https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_apigateway/RestApiAttributes.html

Upvotes: 3

Views: 1493

Answers (1)

Joseph
Joseph

Reputation: 1091

I've solved this issue by doing the following:

  1. Import my Api Gateway with the RestApi.fromRestApiAttributes
  2. Add this code in the stack constructor:
    const deployment = new apigateway.Deployment(this, 'APIGatewayDeployment', {
      api: this.gatewayResource,
      retainDeployments: true,
    });
    
    (deployment as any).resource.stageName = this.stage; // as any to use the private property
    
    this.gatewayResource.deploymentStage = deployment.api.deploymentStage;
    
    this.deployment = deployment; 
  1. Every time I add a new method to the API gateway resources, I also call this function:
    public addApiDeploymentDependency(method: Method) {
        this.deployment._addMethodDependency(method);
        (this.deployment.node.defaultChild as CfnResource)?.addDependency(
      method.node.defaultChild as CfnResource,
    );
        this.logicalId = `${this.logicalId}${JSON.stringify({
          path: method.resource.path,
          method: method.httpMethod,
          id: method.methodId,
          arn: method.methodArn,
          string: method.toString(),
        })}`;
        this.deployment.addToLogicalId(this.logicalId);
      }

The _addMethodDependency is used to make the deployment wait for the methods to be created before deploying. At the same time, the logicalId is needed to let the deployment understand when the resources change.

I hope this will help you too

Upvotes: 3

Related Questions