'AWS CDK | Create a REST API spanning multiple CDK Stacks

We are using AWS CDK to create our Serverless REST API. However, there are a large number of endpoints and sometimes we have to destroy and redeploy our stack. To prevent the REST API URL from changing with each deployment, I am planning to create the API GATEWAY in one stack and add methods and resources in a separate stack. How can I refer the created rest API in a separate stack?

Tried to implement something from https://github.com/aws/aws-cdk/issues/3705, but all of the resources(API Gateway, resource and methods) are being pushed in a single stack instead of API Gateway in one stack and the resources in other stack.

Relevant codes snippets are provided below:

bts-app-cdk.ts

const first = new FirstStack(app, 'FirstStack', {
    env: {
        region: 'us-east-1',
        account: '1234567890',
    }
    });

const second = new SecondStack(app, 'SecondStack', {
    apiGateway: first.apiGateway,
    env: {
        region: 'us-east-1',
        account: '1234567890',
    }
});

second.addDependency(first)

first-stack.ts

export class FirstStack extends cdk.Stack {

    public readonly apiGateway: apig.IResource;

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const apiGateway = new apig.RestApi(this, 'BooksAPI', {
            restApiName:'Books API',
        })
        apiGateway.root.addMethod('GET');

        this.apiGateway = apiGateway.root;
    }
}

second-stack

export interface SecondStackProps extends cdk.StackProps {
    readonly apiGateway: apig.IResource;
}

export class SecondStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props: SecondStackProps) {
        super(scope, id, props);

        props.apiGateway.addMethod('ANY')

    }
}


Solution 1:[1]

Seems that there is no way at the moment except using Cfn constructs, here's the github issue to track https://github.com/aws/aws-cdk/issues/1477

Solution 2:[2]

You have to set the deploy prop to false when instantiating your api-gw. Then you can pass the restApiId and rootResourceId as enviroment variables to stacks.
Finally you can use a Deployment to deploy everything.

interface ResourceNestedStackProps extends NestedStackProps {
  readonly restApiId: string;
  readonly rootResourceId: string;
}

export class FirstStack extends cdk.Stack {

    public readonly methods: Method[];

    constructor(scope: cdk.Construct, props: ResourceNestedStackProps) {
        super(scope, 'first-stack', props);

        // get a hold of the rest api from attributes
        const api = RestApi.fromRestApiAttributes(this, 'RestApi', {
            restApiId: props.restApiId,
            rootResourceId: props.rootResourceId,
        })
       
        // REPEAT THIS FOR METHODS
        const method = api.root.addMethod('GET');
        this.methods.push(method)
        // ---
    }
}

Then in the root stack file,

class RootStack extends Stack {
  constructor(scope: Construct) {
    const restApi = new RestApi(this, 'RestApi', {
      deploy: false,
    });
    restApi.root.addMethod('ANY');

    const firstStack = new FirstStack(this, {
      restApiId: restApi.restApiId,
      rootResourceId: restApi.restApiRootResourceId,
    });

    new DeployStack(this, {
      restApiId: restApi.restApiId,
      methods: [...firstStack.methods],
    })
  }
}

The deploy stack is where you deploy your API:

interface DeployStackProps extends NestedStackProps {
  readonly restApiId: string;

  readonly methods?: Method[];
}

class DeployStack extends NestedStack {
  constructor(scope: Construct, props: DeployStackProps) {
    super(scope, 'deploy-stack', props);

    const deployment = new Deployment(this, 'Deployment', {
      api: RestApi.fromRestApiId(this, 'RestApi', props.restApiId),
    });
    if (props.methods) {
      for (const method of props.methods) {
        deployment.node.addDependency(method);
      }
    }
    new Stage(this, 'Stage', { deployment });
  }
}

Refer this for more details: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 gafi
Solution 2 Akshay Kumar