All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awscdk.cloudformation.include.package-info Maven / Gradle / Ivy

/**
 * 

Include CloudFormation templates in the CDK

*

* --- *

* cdk-constructs: Stable *

*


*

* *

* 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: *

*

 * CfnInclude cfnTemplate = CfnInclude.Builder.create(this, "Template")
 *         .templateFile("my-template.json")
 *         .build();
 * 
*

* Or, if your template uses YAML: *

*

 * CfnInclude cfnTemplate = CfnInclude.Builder.create(this, "Template")
 *         .templateFile("my-template.yaml")
 *         .build();
 * 
*

* Note: different YAML parsers sometimes don't agree on what exactly constitutes valid YAML. * If you get a YAML exception when including your template, * try converting it to JSON, and including that file instead. * If you're downloading your template from the CloudFormation AWS Console, * you can easily get it in JSON format by clicking the 'View in Designer' * button on the 'Template' tab - * once in Designer, select JSON in the "Choose template language" * radio buttons on the bottom pane. *

* 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. *

* Note that this including process will not execute any * CloudFormation transforms - * including the Serverless transform. *

* 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: *

*

 * CfnInclude cfnTemplate;
 * 
 * CfnBucket cfnBucket = (CfnBucket)cfnTemplate.getResource("Bucket");
 * 
*

* 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: *

*

 * CfnInclude cfnTemplate;
 * 
 * CfnBucket cfnBucket = (CfnBucket)cfnTemplate.getResource("Bucket");
 * cfnBucket.getBucketName() = "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: *

*

 * CfnInclude cfnTemplate;
 * 
 * CfnBucket cfnBucket = (CfnBucket)cfnTemplate.getResource("Bucket");
 * 
 * Role role = Role.Builder.create(this, "Role")
 *         .assumedBy(new AnyPrincipal())
 *         .build();
 * role.addToPolicy(PolicyStatement.Builder.create()
 *         .actions(List.of("s3:*"))
 *         .resources(List.of(cfnBucket.getAttrArn()))
 *         .build());
 * 
*

*

Converting L1 resources to L2

*

* The resources the getResource method returns are what the CDK calls * Layer 1 resources * (like CfnBucket). * However, in many places in the Construct Library, * the CDK requires so-called Layer 2 resources, like IBucket. * There are two ways of going from an L1 to an L2 resource. *

*

UsingfromCfn*() methods

*

* This is the preferred method of converting an L1 resource to an L2. * It works by invoking a static method of the class of the L2 resource * whose name starts with fromCfn - * for example, for KMS Keys, that would be the Kms.fromCfnKey() method - * and passing the L1 instance as an argument: *

*

 * CfnInclude cfnTemplate;
 * 
 * CfnKey cfnKey = (CfnKey)cfnTemplate.getResource("Key");
 * IKey key = Key.fromCfnKey(cfnKey);
 * 
*

* This returns an instance of the kms.IKey type that can be passed anywhere in the CDK an IKey is expected. * What is more, that IKey instance will be mutable - * which means calling any mutating methods on it, * like addToResourcePolicy(), * will be reflected in the resulting template. *

* Note that, in some cases, the fromCfn*() method might not be able to create an L2 from the underlying L1. * This can happen when the underlying L1 heavily uses CloudFormation functions. * For example, if you tried to create an L2 IKey * from an L1 represented as this CloudFormation template: *

*

 * {
 *   "Resources": {
 *     "Key": {
 *       "Type": "AWS::KMS::Key",
 *       "Properties": {
 *         "KeyPolicy": {
 *           "Statement": [
 *             {
 *               "Fn::If": [
 *                 "Condition",
 *                 {
 *                   "Action": "kms:if-action",
 *                   "Resource": "*",
 *                   "Principal": "*",
 *                   "Effect": "Allow"
 *                 },
 *                 {
 *                   "Action": "kms:else-action",
 *                   "Resource": "*",
 *                   "Principal": "*",
 *                   "Effect": "Allow"
 *                 }
 *               ]
 *             }
 *           ],
 *           "Version": "2012-10-17"
 *         }
 *       }
 *     }
 *   }
 * }
 * 
*

* The Key.fromCfnKey() method does not know how to translate that into CDK L2 concepts, * and would throw an exception. *

* In those cases, you need the use the second method of converting an L1 to an L2. *

*

Using from*Name/Arn/Attributes() methods

*

* If the resource you need does not have a fromCfn*() method, * or if it does, but it throws an exception for your particular L1, * you need to use the second method of converting an L1 resource to L2. *

* Each L2 class has static factory methods with names like from*Name(), * from*Arn(), and/or from*Attributes(). * You can obtain an L2 resource from an L1 by passing the correct properties of the L1 as the arguments to those methods: *

*

 * CfnInclude cfnTemplate;
 * 
 * // using from*Attributes()
 * CfnSubnet privateCfnSubnet1;
 * CfnSubnet privateCfnSubnet2;
 * 
 * 
 * // using from*Name()
 * CfnBucket cfnBucket = (CfnBucket)cfnTemplate.getResource("Bucket");
 * IBucket bucket = Bucket.fromBucketName(this, "L2Bucket", cfnBucket.getRef());
 * 
 * // using from*Arn()
 * CfnKey cfnKey = (CfnKey)cfnTemplate.getResource("Key");
 * IKey key = Key.fromKeyArn(this, "L2Key", cfnKey.getAttrArn());
 * CfnVPC cfnVpc = (CfnVPC)cfnTemplate.getResource("Vpc");
 * IVpc vpc = Vpc.fromVpcAttributes(this, "L2Vpc", VpcAttributes.builder()
 *         .vpcId(cfnVpc.getRef())
 *         .availabilityZones(Fn.getAzs())
 *         .privateSubnetIds(List.of(privateCfnSubnet1.getRef(), privateCfnSubnet2.getRef()))
 *         .build());
 * 
*

* As long as they just need to be referenced, * and not changed in any way, everything should work; * however, note that resources returned from those methods, * unlike those returned by fromCfn*() methods, * are immutable, which means calling any mutating methods on them will have no effect. * You will have to mutate the underlying L1 in order to change them. *

*

Non-resource template elements

*

* In addition to resources, * you can also retrieve and mutate all other template elements: *

*

    *
  • Parameters: *

    *

     * CfnInclude cfnTemplate;
     * 
     * CfnParameter param = cfnTemplate.getParameter("MyParameter");
     * 
     * // mutating the parameter
     * param.getDefault() = "MyDefault";
     * 
  • *
  • Conditions: *

    *

     * CfnInclude cfnTemplate;
     * 
     * CfnCondition condition = cfnTemplate.getCondition("MyCondition");
     * 
     * // mutating the condition
     * condition.getExpression() = Fn.conditionEquals(1, 2);
     * 
  • *
  • Mappings: *

    *

     * CfnInclude cfnTemplate;
     * 
     * CfnMapping mapping = cfnTemplate.getMapping("MyMapping");
     * 
     * // mutating the mapping
     * mapping.setValue("my-region", "AMI", "ami-04681a1dbd79675a5");
     * 
  • *
  • Service Catalog template Rules: *

    *

     * CfnInclude cfnTemplate;
     * 
     * // mutating the rule
     * CfnParameter myParameter;
     * 
     * CfnRule rule = cfnTemplate.getRule("MyRule");
     * rule.addAssertion(Fn.conditionContains(List.of("m1.small"), myParameter.getValueAsString()), "MyParameter has to be m1.small");
     * 
  • *
  • Outputs: *

    *

     * CfnInclude cfnTemplate;
     * 
     * // mutating the output
     * CfnBucket cfnBucket;
     * 
     * CfnOutput output = cfnTemplate.getOutput("MyOutput");
     * output.getValue() = cfnBucket.getAttrArn();
     * 
  • *
  • Hooks for blue-green deployments: *

    *

     * CfnInclude cfnTemplate;
     * 
     * // mutating the hook
     * Role myRole;
     * 
     * CfnHook hook = cfnTemplate.getHook("MyOutput");
     * CfnCodeDeployBlueGreenHook codeDeployHook = (CfnCodeDeployBlueGreenHook)hook;
     * codeDeployHook.getServiceRole() = myRole.getRoleArn();
     * 
  • *
*

*

Parameter replacement

*

* If your existing template uses CloudFormation Parameters, * you may want to remove them in favor of build-time values. * You can do that using the parameters property: *

*

 * CfnInclude.Builder.create(this, "includeTemplate")
 *         .templateFile("path/to/my/template")
 *         .parameters(Map.of(
 *                 "MyParam", "my-value"))
 *         .build();
 * 
*

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

*

Nested Stacks

*

* This module also supports 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: *

*

 * CfnInclude parentTemplate = CfnInclude.Builder.create(this, "ParentStack")
 *         .templateFile("path/to/my-parent-template.json")
 *         .loadNestedStacks(Map.of(
 *                 "ChildStack", CfnIncludeProps.builder()
 *                         .templateFile("path/to/my-nested-template.json")
 *                         .build()))
 *         .build();
 * 
*

* Here, path/to/my-nested-template.json * represents the path on disk to the downloaded template file from the original template URL of the nested stack * (https://my-s3-template-source.s3.amazonaws.com/child-stack.json). * In the CDK application, * this file will be turned into an Asset, * and the TemplateURL property of the nested stack resource * will be modified to point to that asset. *

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

*

 * CfnInclude parentTemplate;
 * 
 * 
 * IncludedNestedStack includedChildStack = parentTemplate.getNestedStack("ChildStack");
 * NestedStack childStack = includedChildStack.getStack();
 * CfnInclude childTemplate = includedChildStack.getIncludedTemplate();
 * 
*

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

*

 * CfnInclude childTemplate;
 * 
 * 
 * CfnBucket cfnBucket = (CfnBucket)childTemplate.getResource("MyBucket");
 * cfnBucket.getBucketName() = "my-new-bucket-name";
 * 
 * Role role = Role.Builder.create(this, "MyRole")
 *         .assumedBy(new AccountRootPrincipal())
 *         .build();
 * 
 * role.addToPolicy(PolicyStatement.Builder.create()
 *         .actions(List.of("s3:GetObject*", "s3:GetBucket*", "s3:List*"))
 *         .resources(List.of(cfnBucket.getAttrArn()))
 *         .build());
 * 
*

* You can also include the nested stack after the CfnInclude object was created, * instead of doing it on construction: *

*

 * CfnInclude parentTemplate;
 * 
 * IncludedNestedStack includedChildStack = parentTemplate.loadNestedStack("ChildTemplate", CfnIncludeProps.builder()
 *         .templateFile("path/to/my-nested-template.json")
 *         .build());
 * 
*

*

Vending CloudFormation templates as Constructs

*

* In many cases, there are existing CloudFormation templates that are not entire applications, * but more like specialized fragments, implementing a particular pattern or best practice. * If you have templates like that, * you can use the CfnInclude class to vend them as CDK Constructs: *

*

 * import software.constructs.Construct;
 * import software.amazon.awscdk.cloudformation.include.*;
 * import path.*;
 * 
 * public class MyConstruct extends Construct {
 *     public MyConstruct(Construct scope, String id) {
 *         super(scope, id);
 * 
 *         // include a template inside the Construct
 *         // include a template inside the Construct
 *         CfnInclude.Builder.create(this, "MyConstruct")
 *                 .templateFile(join(__dirname, "my-template.json"))
 *                 .preserveLogicalIds(false)
 *                 .build();
 *     }
 * }
 * 
*

* Notice the preserveLogicalIds parameter - * it makes sure the logical IDs of all the included template elements are re-named using CDK's algorithm, * guaranteeing they are unique within your application. * Without that parameter passed, * instantiating MyConstruct twice in the same Stack would result in duplicated logical IDs. */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) package software.amazon.awscdk.cloudformation.include;





© 2015 - 2024 Weber Informatics LLC | Privacy Policy