Generating consistent stack identifiers for multiple stacks within AWS CDK

Is there a way to ensure that when running npx cdk synth in an AWS CDK application consisting of multiple stacks intended for deployment in various environments, the stack names are displayed in a more user-friendly manner?

#!/usr/bin/env node
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
import * as lambda from '@aws-cdk/aws-lambda';


class PersistenceStack extends cdk.Stack {
    public readonly bucket: s3.Bucket;
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        this.bucket = new s3.Bucket(this, 'bucket');
    }
}


interface ApplicationStackProps extends cdk.StackProps {
    bucket: s3.Bucket;
}


class ApplicationStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props: ApplicationStackProps) {
        super(scope, id, props);
        const myLambda = new lambda.Function(this, 'my-lambda', {
            runtime: lambda.Runtime.NODEJS_12_X,
            code: new lambda.AssetCode('my-lambda'),
            handler: 'index.handler'
        });
        props.bucket.grantReadWrite(myLambda);
    }
}


class MyApp extends cdk.Construct {

    constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
        super(scope, id);

        const persistenceStack = new PersistenceStack(this, 'persistence-stack', {
            ...props,
            description: 'persistence stack',
            stackName: `${id}-persistence-stack`,
        });

        const applicationStack = new ApplicationStack(this, 'application-stack', {
            ...props,
            description: 'application stack',
            stackName: `${id}-application-stack`,
            bucket: persistenceStack.bucket,
        });
        applicationStack.addDependency(persistenceStack);
    }
}


const app = new cdk.App();

new MyApp(app, `test`, { env: { account: '111111111111', region: 'eu-west-1' } });
new MyApp(app, `prod`, { env: { account: '222222222222', region: 'eu-west-1' } });

The issue I encountered is that it generates outputs like:

Successfully synthesized to [...]/my-app/cdk.out
Supply a stack id (prodpersistencestackFE36DF49, testpersistencestack6C35C777, prodapplicationstackA0A96586, testapplicationstackE19450AB) to display its template.

My expectation was to have "nice" stack names (as I specified the stackName properties during the constructors):

Successfully synthesized to [...]/my-app/cdk.out
Supply a stack id (prodpersistencestack, testpersistencestack, prodapplicationstack, testapplicationstack) to display its template.

Motivation: I require "nice" (or at least consistent) stack names for our CI/CD pipeline to seamlessly deploy the CDK app.

AWS CDK version: 1.21.1

Answer №1

The issue related to AWS CDK discussed in this thread provides insight into the design choice of stack ids, which can be duplicated across different environments.

To utilize stack names as deployment parameters, a reverse lookup of the cdk.out/manifest.json file can be implemented to access the mapping between stack ids and names. Here is an example of how this lookup can be executed using jq:

# Specify the stack name, e.g. test-persistence-stack, prod-persistence-stack, test-application-stack or prod-application-stack
stackName=

# Extract the stack id from ./cdk.out/manifest.json
stackId=$(jq -r --arg stackName "$stackName" \
   '.artifacts
   | to_entries[]
   | select(.value.properties.stackName == $stackName)
   | .key
   ' \
   < "./cdk.out/manifest.json" \
   )

# Trigger cdk deploy with the stack id as a parameter
npx cdk deploy \
  --app cdk.out \
  --require-approval never \
  "$stackId"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to locate the next/google/font module in my Typescript project

Issue With Import Syntax for Font Types The documentation here provides an example: import { <font-name> } from 'next/google/font'; This code compiles successfully, but throws a "module not found" error at runtime. However, in this disc ...

Error message: "Incompatible types in Typescript"

As I delve into learning TypeScript, I have encountered two errors that are causing me some trouble. We have a problem with the following lines of code: Type 'string | null | undefined' is not assignable to type 'string | RegExp | QuerySelec ...

Generate a data type automatically based on an Array

Imagine having an imaginary api that provides color values based on user selections. Consider the following arrays with string values: const Colors1 = ['red', 'blue', 'purple']; const Colors2 = ['blue', 'white& ...

The parameter 'users | undefined' is not compatible with the argument type 'users'. Please note that 'undefined' cannot be assigned to type 'users'

Can anyone please help me with creating a put method using TYPEORM? I am facing an error that requests a typeof, but my users have a value. (I am a newbie, so not sure). Any guidance on how to fix this issue would be greatly appreciated. Here is the snip ...

Guide on Implementing a New Method into a React Functional Component

I have a component that looks like this: const Abc: React.FC<AbcTypes> = ({...}) => {...} Abc.getLayout = () => {...} I am not sure how to properly define or extend the method getLayout on the Abc component in TypeScript? ...

Risky assignment of an 'any' value" encountered while implementing react-transition-group in TypeScript

Encountering @typescript-eslint errors while implementing the Transition component from react-transition-group. Implemented the official React Transition Group example for JS in a TypeScript + ESLint project, resulting in the error message: Unsafe assignm ...

Implement a feature that allows users to easily reset applied filters by clicking a button, but currently experiencing issues with the functionality

How to create an HTML button <button id="styleButton" class="ml-2 refreshButton" (click)="removeAllFilters(appliedFilters)" > <i class="fas fa-sync-alt"></i> </button> JavaScript functi ...

What is the most effective way to determine the data type of a value associated with a key in an interface?

In my TypeScript interface, I have defined the following structure: MyInterface { 'key1': number | string; 'key2': string; 'key3': SomeOtherInterface; } I am looking to create a new type that utilizes the properties of ...

Capture individual frames from angular video footage

Trying to extract frames from a video using Angular has been quite challenging for me. While browsing through Stack Overflow, I came across this helpful post here. I attempted to implement the first solution suggested in the post, but unfortunately, I was ...

Astro component experiencing script tag malfunction within content collection

I'm trying to create something using a script tag, but for some reason the script doesn't seem to be working properly. Below is my content collection: --- title: Essay Similarity stakeholder: THESIS articleDate: 05 Feb 2023 projectStart: 2022-08 ...

Uploading Files through Reactive Forms in Angular

I tried following a tutorial on integrating file upload functionality into my reactive form, which can be found at the following link: . However, I've encountered an issue where I'm getting an error message stating "this.onChange is not a functio ...

Leveraging angular2-material with systemjs for Angular2 development

After completing the TUTORIAL: TOUR OF HEROES on this link, I attempted to integrate angular2-material into my project. Unfortunately, I am having issues with the CSS not displaying correctly. Can anyone provide insight into what I may be missing or doing ...

Tips on deactivating a div when a checkbox is selected

I am currently working with a checkbox element in my code: <md-checkbox checked.bind="addEventCommand.allDay" change.delegate="allday()">All Day</md-checkbox> When the above checkbox is true, I want to disable the following ...

The `$refs` variable in Vue can be used to reference a specific Vue component within a class-st

Would it be possible to access this.$refs.label? I am using the package vue-property-decorator. Below is the content of the component: <template> <div> <label ref="label">asd</label> </div> </template> <scr ...

Having trouble uploading an image to AWS using Angular and NodeJS?

I am currently working on a Node/Express application and I need to gather file information for uploading from an Angular/Ionic front end. To achieve this, I have created a separate Service in Angular that successfully retrieves the Image name. However, my ...

Transferring files from one azure blob container to another

I am currently utilizing the @azure/storage-blob package to manage files within Azure. Within the same Azure storage account, I have two storage containers - one for source files and the other for destination files. My objective is to copy a file from th ...

The error message "Type 'null' cannot be assigned to type 'Element | DocumentFragment'" occurs when using Nextjs/React createPortal

I am completely new to typescript. Currently, I'm working on a project that has a lot of pre-configured react components in JavaScript files (.js). My task now is to convert everything to TypeScript (.tsx) without triggering any ESLint errors. Unfort ...

Ignore a directory during TypeScript compilation

When writing code in Atom, the use of tsconfig.json to include and exclude folders is essential. For optimal intellisense functionality, the node_modules folder must be included. However, when compiling to js, the node_modules should not be compiled. To ac ...

The issue arising from utilizing the export class function in Angular 8

Hey there! I'm working on an Angular application and just getting started with it. My current version is Angular 8, and I've encountered an issue that I need help with. In my project, I have a shared model named "Client" which is defined in a fi ...

Different categories of properties within a generic function

I'm attempting to modify certain fields of my object using field names. Here is the code snippet I have written: interface Foo { a: number[], b: string[], } type Bar = { [T in keyof Foo] : (arg : Foo[T]) => Foo[T] } function test<T ex ...