DEV Community

Cover image for How to Share Resources Across Stacks in AWS CDK
Danny Steenman for AWS Community Builders

Posted on • Originally published at towardsthecloud.com on

How to Share Resources Across Stacks in AWS CDK

When building a CDK App, there is a good chance you want to structurize your project and set up multiple stacks when creating the Infrastructure. Therefore it's good to know how you can reference resources across stacks in AWS CDK.

For the example in this blog post we're going to create two stacks:

  • SharedInfraStack, which contains the VPC resource
  • RdsStack which will import the VPC from the SharedInfraStack

Note: if you're still a beginner with AWS CDK. Then I would first recommend you to read my article on What is the AWS CDK?.

To be able to share resources between stacks in AWS CDK we need to:

Create SharedInfraStack which provisions the VPC

In the example below I share the share infra stack which provisions the VPC resource including subnets and routing.

```typescript showLineNumbers
// file: lib/shared-infra-stack.ts
import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2';

export class SharedInfraStack extends cdk.Stack {
public readonly vpc: ec2.Vpc;
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// assign a VPC to the class property SharedInfraStack
this.vpc = new ec2.Vpc(this, 'TheVPC', {
  cidr: '10.0.0.0/16',
  natGateways: 1,
  maxAzs: 3,
  subnetConfiguration: [
    {
      cidrMask: 20,
      name: 'public',
      subnetType: ec2.SubnetType.PUBLIC,
    },
    {
      cidrMask: 20,
      name: 'application',
      subnetType: ec2.SubnetType.PRIVATE,
    },
    {
      cidrMask: 20,
      name: 'data',
      subnetType: ec2.SubnetType.ISOLATED,
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

}
}




If you generate the CloudFormation template by running `cdk synth` you'll see that the following VPC resources are being exported.



```yaml
# Generated CloudFormation template of the SharedInfraStack
Outputs:
  ExportsOutputRefTheVPCdataSubnet1Subnet62F6C85A8DFF3A46:
    Value:
      Ref: TheVPCdataSubnet1Subnet62F6C85A
    Export:
      Name: SharedInfraStack:ExportsOutputRefTheVPCdataSubnet1Subnet62F6C85A8DFF3A46
  ExportsOutputRefTheVPCdataSubnet2SubnetAE4EF5CAD340846A:
    Value:
      Ref: TheVPCdataSubnet2SubnetAE4EF5CA
    Export:
      Name: SharedInfraStack:ExportsOutputRefTheVPCdataSubnet2SubnetAE4EF5CAD340846A
  ExportsOutputRefTheVPC92636AB00B2A4A70:
    Value:
      Ref: TheVPC92636AB0
    Export:
      Name: SharedInfraStack:ExportsOutputRefTheVPC92636AB00B2A4A70
Enter fullscreen mode Exit fullscreen mode

Pass the props of the VPC to the RdsStack that we instantiate

In the bin folder where we instantiate the CDK app, we also declare the CDK stacks.

Here we make sure to pass the props we just created from the VPC stack and pass them to the new RdsStack that we're going to create.

```typescript showLineNumbers
// file: bin/index.ts
import * as cdk from '@aws-cdk/core';
import { SharedInfraStack } from '../lib/shared-infra-stack';
import { RdsStack } from '../lib/rds-stack';

const app = new cdk.App();

// created the SharedInfraStack with the VPC resource that we're going to share by making a variable
const infra = new SharedInfraStack(app, 'SharedInfraStack');

// pass the vpc resource from the SharedInfraStack to the RdsStack
new RdsStack(app, 'RdsStack', {
vpc: infra.vpc,
});




## Create the `RdsStack` and import the VPC as prop

Now we'll create the `RdsStack` that provisions the RDS with the VPC resource we shared across stacks in the previous two steps.



```typescript showLineNumbers
// file: lib/rds-stack.ts
import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as rds from '@aws-cdk/aws-rds';

// extend the props of the stack by adding the vpc type from the SharedInfraStack
export interface RDSStackProps extends cdk.StackProps {
  vpc: ec2.Vpc;
}

export class RdsStack extends cdk.Stack {
  readonly postgreSQLinstance: rds.DatabaseInstance;
  private vpc: ec2.Vpc;
  constructor(scope: cdk.Construct, id: string, props: RDSStackProps) {
    super(scope, id, props);

    // make the vpc variable accessible
    const vpc = props.vpc;

    const cluster = new rds.DatabaseCluster(this, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_2_08_1,
      }),
      credentials: rds.Credentials.fromGeneratedSecret('clusteradmin'), // Optional - will default to 'admin' username and generated password
      instanceProps: {
        // optional , defaults to t3.medium
        instanceType: ec2.InstanceType.of(
          ec2.InstanceClass.BURSTABLE2,
          ec2.InstanceSize.SMALL
        ),
        vpcSubnets: {
          subnetType: ec2.SubnetType.ISOLATED,
        },
        // select the vpc we imported to define the subnets for the RDS
        vpc,
      },
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

This is what the end result looks like when we generate the CloudFormation template with cdk synth command:

```yaml showLineNumbers
DatabaseSubnets56F17B9A:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnets for Database database
SubnetIds:
- Fn::ImportValue: SharedInfraStack:ExportsOutputRefTheVPCdataSubnet1Subnet62F6C85A8DFF3A46
- Fn::ImportValue: SharedInfraStack:ExportsOutputRefTheVPCdataSubnet2SubnetAE4EF5CAD340846A
Metadata:
aws:cdk:path: RdsStack/Database/Subnets/Default
DatabaseB269D8BB:
Type: AWS::RDS::DBCluster
Properties:
Engine: aurora-mysql
DBClusterParameterGroupName: default.aurora-mysql5.7
DBSubnetGroupName:
Ref: DatabaseSubnets56F17B9A
EngineVersion: 5.7.mysql_aurora.2.08.1
MasterUsername: clusteradmin
MasterUserPassword:
Fn::Join:
- ''
- - '{{resolve:secretsmanager:'
- Ref: RdsStackDatabaseSecretECD539873fdaad7efa858a3daf9490cf0a702aeb
- :SecretString:password::}}
VpcSecurityGroupIds:
- Fn::GetAtt:
- DatabaseSecurityGroup5C91FDCB
- GroupId
UpdateReplacePolicy: Snapshot
DeletionPolicy: Snapshot
Metadata:
aws:cdk:path: RdsStack/Database/Resource




As you can see in the CloudFormation template we import the VPC value in the `RdsStack` that we've exported from the `SharedInfraStack` template.

## TL;DR give me the code!

The code for this article is available on [GitHub](https://github.com/towardsthecloud/aws-cdk-examples/tree/main/share-resources-across-stacks)

## Conclusion

You've created the following after reading this article:

* [A `SharedInfraStack` which provisions the VPC](#create-sharedinfrastack-which-provisions-the-vpc)
* [Passed the props of the VPC to the `RdsStack` that we instantiated](#pass-the-props-of-the-vpc-to-the-rdsstack-we-instantiate)
* [Created the `RdsStack` and imported the VPC as a prop](#create-the-rdsstack-and-import-the-vpc-as-prop)

Now you know how to structurize your project and instantiate resources in a base stack which can then be used in other stacks by passing its prop.

## Elevate Your AWS CDK App with Expert Review & Guidance

Unlock the full potential of your AWS CDK app with our Expert AWS CDK App Code Review Service, conveniently delivered through AWS IQ.

Gain invaluable insights, minimize risks, and set a clear path forward for your project's success.

[Schedule Your CDK Review Now](/services/aws-cdk-review)

---
> Join my [newsletter](https://towardsthecloud.com/newsletter?ref=devto) for real-world insights, actionable strategies, and lessons learned the hard way on my journey building a successful [AWS Cloud Consulting business](https://towardsthecloud.com?ref=devto), delivered to your inbox.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)