Skip to content

Latest commit

 

History

History
254 lines (192 loc) · 7.2 KB

File metadata and controls

254 lines (192 loc) · 7.2 KB

Include CloudFormation templates in the CDK


cdk-constructs: Experimental

The APIs of higher level constructs in this module are experimental and under active development. They are subject to non-backward compatible changes or removal in any future version. These are not subject to the Semantic Versioning model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package.


This module contains a set of classes whose goal is to facilitate working with existing CloudFormation templates in the CDK. It can be thought of as an extension of the capabilities of the CfnInclude class.

Basic usage

Assume we have a file with an existing template. It could be in JSON format, in a file my-template.json:

{
  "Resources": {
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": "some-bucket-name"
      }
    }
  }
}

Or it could by in YAML format, in a file my-template.yaml:

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: some-bucket-name

It can be included in a CDK application with the following code:

import * as cfn_inc from '@aws-cdk/cloudformation-include';

const cfnTemplate = new cfn_inc.CfnInclude(this, 'Template', {
  templateFile: 'my-template.json',
});

Or, if your template uses YAML:

const cfnTemplate = new cfn_inc.CfnInclude(this, 'Template', {
  templateFile: 'my-template.yaml',
});

This will add all resources from my-template.json / my-template.yaml into the CDK application, preserving their original logical IDs from the template file.

Any resource from the included template can be retrieved by referring to it by its logical ID from the template. If you know the class of the CDK object that corresponds to that resource, you can cast the returned object to the correct type:

import * as s3 from '@aws-cdk/aws-s3';

const cfnBucket = cfnTemplate.getResource('Bucket') as s3.CfnBucket;
// cfnBucket is of type s3.CfnBucket

Note that any resources not present in the latest version of the CloudFormation schema at the time of publishing the version of this module that you depend on, including Custom Resources, will be returned as instances of the class CfnResource, and so cannot be cast to a different resource type.

Any modifications made to that resource will be reflected in the resulting CDK template; for example, the name of the bucket can be changed:

cfnBucket.bucketName = 'my-bucket-name';

You can also refer to the resource when defining other constructs, including the higher-level ones (those whose name does not start with Cfn), for example:

import * as iam from '@aws-cdk/aws-iam';

const role = new iam.Role(this, 'Role', {
  assumedBy: new iam.AnyPrincipal(),
});
role.addToPolicy(new iam.PolicyStatement({
  actions: ['s3:*'],
  resources: [cfnBucket.attrArn],
}));

If you need, you can also convert the CloudFormation resource to a higher-level resource by importing it:

const bucket = s3.Bucket.fromBucketName(this, 'L2Bucket', cfnBucket.ref);
// bucket is of type s3.IBucket

Parameters

If your template uses CloudFormation Parameters, you can retrieve them from your template:

import * as core from '@aws-cdk/core';

const param: core.CfnParameter = cfnTemplate.getParameter('MyParameter');

The CfnParameter object is mutable, and any changes you make to it will be reflected in the resulting template:

param.default = 'MyDefault';

You can also provide values for them when including the template:

new inc.CfnInclude(stack, 'includeTemplate', {
  templateFile: 'path/to/my/template'
  parameters: {
    'MyParam': 'my-value',
  },
});

This will replace all references to MyParam with the string 'my-value', and MyParam will be removed from the Parameters section of the template.

Conditions

If your template uses CloudFormation Conditions, you can retrieve them from your template:

import * as core from '@aws-cdk/core';

const condition: core.CfnCondition = cfnTemplate.getCondition('MyCondition');

The CfnCondition object is mutable, and any changes you make to it will be reflected in the resulting template:

condition.expression = core.Fn.conditionEquals(1, 2);

Outputs

If your template uses CloudFormation Outputs, you can retrieve them from your template:

import * as core from '@aws-cdk/core';

const output: core.CfnOutput = cfnTemplate.getOutput('MyOutput');

The CfnOutput object is mutable, and any changes you make to it will be reflected in the resulting template:

output.value = cfnBucket.attrArn;

Nested Stacks

This module also support templates that use nested stacks.

For example, if you have the following parent template:

{
  "Resources": {
    "ChildStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/child-stack.json"
      }
    }
  }
}

where the child template pointed to by https://my-s3-template-source.s3.amazonaws.com/child-stack.json is:

{
  "Resources": {
    "MyBucket": {
      "Type": "AWS::S3::Bucket"
    }
  }
}

You can include both the parent stack and the nested stack in your CDK application as follows:

const parentTemplate = new inc.CfnInclude(stack, 'ParentStack', {
  templateFile: 'path/to/my-parent-template.json',
  nestedStacks: {
    'ChildStack': {
      templateFile: 'path/to/my-nested-template.json',
    },
  },
});

The included nested stack can be accessed with the getNestedStack method:

const includedChildStack = parentTemplate.getNestedStack('ChildStack');
const childStack: core.NestedStack = includedChildStack.stack;
const childTemplate: cfn_inc.CfnInclude = includedChildStack.includedTemplate;

Now you can reference resources from ChildStack and modify them like any other included template:

const cfnBucket = childTemplate.getResource('MyBucket') as s3.CfnBucket;
cfnBucket.bucketName = 'my-new-bucket-name';

const role = new iam.Role(childStack, 'MyRole', {
  assumedBy: new iam.AccountRootPrincipal(),
});

role.addToPolicy(new iam.PolicyStatement({
  actions: [
    's3:GetObject*',
    's3:GetBucket*',
    's3:List*',
  ],
  resources: [cfnBucket.attrArn],
}));