Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow External TemplateURL for NestedStack #4990

Closed
2 tasks
nate-biles opened this issue Nov 12, 2019 · 5 comments
Closed
2 tasks

Allow External TemplateURL for NestedStack #4990

nate-biles opened this issue Nov 12, 2019 · 5 comments
Assignees
Labels
@aws-cdk/core Related to core CDK functionality feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged.

Comments

@nate-biles
Copy link

We have a large amount of cloud formation that we need to migrate to CDK. I want to migrate my teams cloud formation to the cdk, but other teams cloud formation (which we import in nested stacks using TemplateURL Property) need to remain as cloud formation.

Whenever I do a "cdk synth" the TemplateURL Property generated for the nested stack is never affected by anything I set.

Specifically I tried overriding NestedStack.getTemplateUrl() to return the template URL that I want cdk to late bind to (to use the external template as is, via reference). This is ignored.

I also looked to see if there is a way to specify the TemplateURL via properties passed into the constructor, or by overriding some method - don't see a way to force it to use the existing external templateUrl.

Use Case

From my perspective, CDK can be used purely as a way to generate cloud formation - this is how we intend to use it. Therefore I hope we can dynamically generate portions of the cloud formation using CDK api, while pulling in and binding to other portions of cloud formation statically. In the end, after running "cdk synth" I expect the end result to be cloud formation that I can give to other internal teams to deploy/host in their account - so why doesn't cdk allow a way to bind to existing template scripts to support partial migrations from legacy cloud formation to a hybrid cdk and cloud formation approach?

Proposed Solution

Most people using the CDK will be coming from a background in cloud formation. It's normal to be able to create a nested custom stack that simply references an external .json or yaml template file and defines properties and outputs. Solution should be intuitive for a Java developer trying to migrate existing templates.

One solution is to allow passing the Properties in on the NestedStack constructor, and honor the TemplateURL property if found. Even better, would be to have a NestedStackPropertiesBuilder that has specific methods on it for building existing Properties like TemplateURL. Another solution is to indicate (using Javadoc) which methods on NestedStack are intended to be overridden by consumers and for what purpose - or if they are strictly for internal use.

If this is already possible / supported, then it would be good to see a working Java example. I'd also like to see example for python if it already exists.

Other

  • 👋 I may be able to implement this feature request
  • ⚠️ This feature might incur a breaking change

This is a 🚀 Feature Request

@nate-biles nate-biles added feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged. labels Nov 12, 2019
@nate-biles nate-biles changed the title Honor Nested stack TemplateURL Honor NestedStack TemplateURL Nov 12, 2019
@nate-biles nate-biles changed the title Honor NestedStack TemplateURL Allow External TemplateURL for NestedStack.TemplateURL Nov 12, 2019
@nate-biles nate-biles changed the title Allow External TemplateURL for NestedStack.TemplateURL Allow External TemplateURL for NestedStack Nov 12, 2019
@ekzGuille
Copy link

I wanted to make something similar with NestedStacks but I figured out that It was better for me to use CfnStack insted of NestedStack.
Here is where I posted the comment asking for some advice: #239 (comment)

@SomayaB SomayaB added the @aws-cdk/core Related to core CDK functionality label Nov 15, 2019
@eladb
Copy link
Contributor

eladb commented Nov 17, 2019

Like @ekzGuille said, using @aws-cdk/aws-cloudformation.CfnStack is probably what you are after. It gives you full control over the synthesized AWS::CloudFormation::Stack resource, including specifying the template URL:

import { Stack, Construct, StackProps } from '@aws-cdk/core';
import * as cfn from '@aws-cdk/aws-cloudformation';

export class AppStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props);
    
        new cfn.CfnStack(this, 'MyNestedStack', {
          templateUrl: 'https://find-me-a-template'
        });
    }
}

Outputs:

Resources:
  MyNestedStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://find-me-a-template

Created with play-with-cdk.com

@ekzGuille @nate-biles please reopen this if this doesn't address your use case.

@eladb eladb closed this as completed Nov 17, 2019
@matef
Copy link

matef commented Sep 23, 2020

I had investigated this issue and I came up with a hackish way to solve it.

Context: I have a similar situation where I wanted to generate all the artifacts with the right references using CDK synth then upload them manually by my pipeline to the designated destination.

CDK/CF logic: Nested stacks by definition are reusable artifacts which means they need to be placed somewhere in an S3 bucket to be referred to in your main stack, which couldn't be known in CDK synth time. so a unique hash key is placed as a reference to your final location.

Note: If you use synthesizer=DefaultStackSynthesizer() in your main stack constructor, or in cdk.json you added

"context": {
    "@aws-cdk/core:newStyleStackSynthesis": true
  }

An asset file will be generated for you which contains the hash codes and the corresponding template names, which should be used by CDK deploy in order to place your nested template in the right places.

Solution: I wrote a simple python script that takes the asset file, the main stack file, and templates upload location
python fix_template_url.py asset_file main_stack_template upload_location. Basically, it reads the asset file to build a dictionary of hashes/template_name, then uses it to replace TemplateURL in the main_stack_template with a concrete URL calculated from upload_location+template_name. The deployment pipeline will take care of the files upload and template submission afterwords. I hope this can save someone's day.

https://gist.github.com/matef/9c1626ce6549a86894187901d5c85ee7

@edisongustavo
Copy link
Contributor

edisongustavo commented Nov 5, 2020

I wanted to leave this here if someone also needs it:

You can use the "escape hatches" feature of CDK to override the TemplateURL parameter of a CfnStack.

To obtain a CfnStack object from a NestedStack and override its TemplateURL parameter, this is what you do:

nested_stack = NestedStack(parent, id)
cfn_stack = nested_stack.nested_stack_resource
cfn_stack.add_property_override("TemplateURL", "http://...")

PS: It's Python, but it's easy to see how to translate into other languages.

There is another downside where when you create a NestedStack, CDK adds an Asset to the Stack. If you're using the legacy synthesizer, then you need to also deal with extra Parameters on the Stack template. I couldn't find a way to override those though, so I also wrote a script to remove them.

@mirskiy
Copy link
Contributor

mirskiy commented Feb 2, 2021

@edisongustavo
For the legacy synth, hack to avoid the generated parameters.

export class NS extends NestedStack {
  constructor(scope: Construct, id: string, props?: NestedStackProps) {
    super(scope, id, props);
    // @ts-ignore
    this._templateUrl = "http://..."
  }
}

https://play-with-cdk.com?s=461d508da215174722b9d68ef11c164c

If you need the name of the generated template file, you can get it from this.templateFile.

FYI, I deploy my templates manually, I have no idea if this will cause any side effects with cdk deploy. Also, I used to use the CfnStack method mentioned above, but switched to this to facilitate outputs from nested stacks - without using NestedStack, the cdk will use imports and exports, which didn't work for me.
Also, my build time went up from 15 seconds to 3 minutes after switching to nested templates (regardless of whether I used this hack for the url). I'm on cdk version 1.51.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/core Related to core CDK functionality feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

7 participants