aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 54 forks source link

Create a "DefaultStackName" Section #1764

Open ccharland opened 1 year ago

ccharland commented 1 year ago

Name of the resource

Other

Resource name

Template anatomy

Description

I'd like to include a Default Stack Name in the template and allow it to use some Pseudo Parameters

For example:

Description: SampleStack with a default stackname

DefaultStackName:
  !Sub: "MyStack-$(AWS::Account}-${AWS::Region}" 

Resources:
   <.....>

Some of the benefits would be:

  1. Consistency in naming when deploying to multiple accounts and regions.
  2. Improved development speed and testing of new templates by having one less thing to type.

Other Details

Here are a couple of other people that have requested this feature:

https://stackoverflow.com/questions/51828313/is-it-possible-to-statically-specify-awsstackname-inside-a-cloudformation-temp

https://www.reddit.com/r/aws/comments/oix0wj/specify_stack_name_within_cloudformation_template/

benkehoe commented 1 year ago

I disagree strongly with this. The stack name doesn't belong inside the template; that defeats the purpose of it being a template. And it's especially bad to have the stack name only resolved after the CreateStack call has been made. I often see people pushing in this direction, but it shouldn't be a goal that CreateStack only has one parameter (i.e., the template).

If someone really wants to do this, I think it's better to do it in a custom way using the Metadata section, in a way that's specific to your process and requirements. As an example:

Metadata:
    DefaultStackName: "MyStack-${Account}-${Region}"
Resources:
    MyTopic:
        Type: AWS::SNS::Topic
        Properties: {}

and then process it as part of your deployment:

#!/bin/env python3

import string
import sys
import argparse

import boto3
import yaml

parser = argparse.ArgumentParser()
parser.add_argument("--profile")
parser.add_argument("template", type=argparse.FileType())

args = parser.parse_args()

data = yaml.safe_load(args.template)

stack_name_template = string.Template(data["Metadata"]["DefaultStackName"])

session = boto3.Session(profile_name=args.profile)

caller_identity = session.client("sts").get_caller_identity()

account = caller_identity["Account"]
region = session.region_name

stack_name = stack_name_template.substitute(Account=account, Region=region)

print(stack_name)
JohnPreston commented 1 year ago

Same as @benkehoe here, I understand and appreciate the intent, but without setting the stack name in the API call that makes your template usable only once per account per region. There might be use-cases for this, in a kind of "one-time use" sort of use case but I think it's very easy already to have something in place to script names per regions. Plus the stack name doesn't even have to change per region :shrug:

ccharland commented 1 year ago

Thanks for your comments, and I think the comments about regions is my own form of “scope creep.” My main use case is to deploy stacks that won’t get duplicated, such as SSO configuration, CloudTrail, or billing reporting

I work for a MSP where we create or take over “many” accounts, and with many different orgs, with some that we don’t control.
My main use case is to give our clients or my onboarding team a one page summary on how to do to install our three core stacks that set up our billing reporting, CloudTrail, and SSO authentications and minimize having inconsistent stack names.

My simplified steps are:

  1. Go to CloudFormation in your AWS console.
  2. Click on deploy stack.
  3. Paste in a S3 signed url for the template source.
  4. Click next until you have to select the capabilities checkboxes.

Yes, I could give them a CloudShell command to cut and paste, but that doesn’t work for everyone.