This is the AWS CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023.
Import resources from an AWS CloudFormation template into your AWS Cloud Development Kit (AWS CDK) applications by using the cloudformation-include.CfnInclude
construct to convert resources to L1 constructs.
After import, you can work with these resources in your app in the same way that you would if they were originally defined in AWS CDK code. You can also use these L1 constructs within higher-level AWS CDK constructs. For example, this can let you use the L2 permission grant methods with the resources they define.
The cloudformation-include.CfnInclude
construct essentially adds an AWS CDK API wrapper to any resource in
your AWS CloudFormation template. Use this capability to import your existing AWS CloudFormation templates to the AWS CDK a piece at a time. By doing
this, you can manage your existing resources using AWS CDK constructs to utilize the benefits of higher-level abstractions.
You can also use this feature to vend your AWS CloudFormation templates to AWS CDK developers by providing an AWS CDK construct
API.
Note
AWS CDK v1 also included aws-cdk-lib.CfnInclude
, which was previously used for the same general purpose. However, it
lacks much of the functionality of cloudformation-include.CfnInclude
.
Topics
Import an AWS CloudFormation template
The following is a sample AWS CloudFormation template that we will use to provide examples in this topic. Copy and save the
template as my-template.json
to follow along. After working through these examples, you can
explore further by using any of your existing deployed AWS CloudFormation templates. You can obtain them from the AWS CloudFormation
console.
{
"Resources": {
"amzn-s3-demo-bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "amzn-s3-demo-bucket",
}
}
}
}
You can work with either JSON or YAML templates. We recommend JSON if available since YAML parsers can vary slightly in what they accept.
The following is an example of how to import the sample template into your AWS CDK app using
cloudformation-include
. Templates are imported within the context of an CDK stack.
import * as cdk from 'aws-cdk-lib';
import * as cfninc from 'aws-cdk-lib/cloudformation-include';
import { Construct } from 'constructs';
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
});
}
}
By default, importing a resource preserves the resource's original logical ID from the template. This behavior is suitable for importing an AWS CloudFormation template into the AWS CDK, where logical IDs must be retained. AWS CloudFormation needs this information to recognize these imported resources as the same resources from the AWS CloudFormation template.
If you are developing an AWS CDK construct wrapper for the template so that it can be used by other AWS CDK developers,
have the AWS CDK generate new resource IDs instead. By doing this, the construct can be used multiple times in a stack
without name conflicts. To do this, set the preserveLogicalIds
property to false
when
importing the template. The following is an example:
const template = new cfninc.CfnInclude(this, 'MyConstruct', {
templateFile: 'my-template.json',
preserveLogicalIds: false
});
To put imported resources under the control of your AWS CDK app, add the stack to the App
:
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-stack';
const app = new cdk.App();
new MyStack(app, 'MyStack');
To verify that there won't be any unintended changes to the AWS resources in the stack, you can perform a diff.
Use the AWS CDK CLI
cdk diff
command and omit any AWS CDK-specific metadata. The following is an example:
cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata
After you import an AWS CloudFormation template, the AWS CDK app should become the source of truth for your imported resources. To make changes to your resources, modify them in your AWS CDK app and deploy with the AWS CDK CLI cdk deploy command.
Access imported resources
The name template
in the example code represents the imported AWS CloudFormation template. To access a resource
from it, use the object's getResource()
method. To access the returned resource as a specific kind of resource, cast
the result to the desired type. This isn't necessary in Python or JavaScript. The following is an example:
const cfnBucket = template.getResource('amzn-s3-demo-bucket') as s3.CfnBucket;
From this example, cfnBucket
is now an instance of the aws-s3.CfnBucket
class. This is an L1
construct that represents the corresponding AWS CloudFormation resource. You can treat it like any other resource of its type. For
example, you can get its ARN value with the bucket.attrArn
property.
To wrap the L1 CfnBucket
resource in an L2 aws-s3.Bucket
instance instead, use the
static methods fromBucketArn()
, fromBucketAttributes()
, or fromBucketName()
. Usually, the fromBucketName()
method is most convenient. The
following is an example:
const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref);
Other L2 constructs have similar methods for creating the construct from an existing resource.
When you wrap an L1 construct in an L2 construct, it doesn't create a new resource. From our example, we are not
creating a second S3; bucket. Instead, the new Bucket
instance encapsulates the existing
CfnBucket
.
From the example, the bucket
is now an L2 Bucket
construct that behaves like any other L2
construct. For example, you can grant an AWS Lambda function write access to the bucket by using the bucket's convenient
grantWrite()
method. You don't have to define the necessary AWS Identity and Access Management (IAM) policy
manually. The following is an example:
bucket.grantWrite(lambdaFunc);
Replace parameters
If your AWS CloudFormation template contains parameters, you can replace them with build time values at import by using the
parameters
property. In the following example, we replace the UploadBucket
parameter with
the ARN of a bucket defined elsewhere in our AWS CDK code.
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
parameters: {
'UploadBucket': bucket.bucketArn,
},
});
Import other template elements
You can import any AWS CloudFormation template element, not just resources. The imported elements become a part of the AWS CDK
stack. To import these elements, use the following methods of the CfnInclude
object:
-
getCondition()
– AWS CloudFormation conditions. -
getHook()
– AWS CloudFormation hooks for blue/green deployments. -
getMapping()
– AWS CloudFormation mappings. -
getOutput()
– AWS CloudFormation outputs. -
getParameter()
– AWS CloudFormation parameters. -
getRule()
– AWS CloudFormation rules for AWS Service Catalog templates.
Each of these methods return an instance of a class that represents the specific type of AWS CloudFormation element. These objects are mutable. Changes that you make to them will appear in the template that gets generated from the AWS CDK stack. The following is an example that imports a parameter from the template and modifies its default value:
const param = template.getParameter('MyParameter');
param.default = "AWS CDK"
Import nested stacks
You can import nested stacks by specifying them either when you import their main template, or at some later point. The
nested template must be stored in a local file, but referenced as a NestedStack
resource in the main
template. Also, the resource name used in the AWS CDK code must match the name used for the nested stack in the main
template.
Given this resource definition in the main template, the following code shows how to import the referenced nested stack both ways.
"NestedStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json"
}
// include nested stack when importing main stack
const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', {
templateFile: 'main-template.json',
loadNestedStacks: {
'NestedStack': {
templateFile: 'nested-template.json',
},
},
});
// or add it some time after importing the main stack
const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', {
templateFile: 'nested-template.json',
});
You can import multiple nested stacks with either methods. When importing the main template, you provide a mapping
between the resource name of each nested stack and its template file. This mapping can contain any number of entries.
To do it after the initial import, call loadNestedStack()
once for each nested stack.
After importing a nested stack, you can access it using the main template's getNestedStack()
method.
const nestedStack = mainTemplate.getNestedStack('NestedStack').stack;
The getNestedStack()
method returns an IncludedNestedStack
instance. From this instance, you can access the AWS CDK NestedStack
instance via
the stack
property, as shown in the example. You can also access the original AWS CloudFormation template object via
includedTemplate
, from which you can load resources and other AWS CloudFormation elements.