Skip to content

(Core): unexpected logical id change for CdkJsonStringify when order of stack changed #31345

@tonnico

Description

@tonnico

Describe the bug

The logical id of a CdkJsonStringify will change for different stacks, when the order of stacks will change.

Regression Issue

  • Select this option if this issue appears to be a regression.

Last Known Working CDK Version

No response

Expected Behavior

Order of stack shouldn't change the logical id.

Current Behavior

The logical id in CdkJsonStringify<id> is stack order dependend.

Reproduction Steps

Synth the following app twice:

Python app
#!/usr/bin/env python3

import os
import aws_cdk as cdk

from aws_cdk import (
    CfnOutput,
    Fn,
    Stack,
    custom_resources as cr,
    aws_ec2 as ec2,
)
from constructs import Construct


class CdkMinimalStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        vpc = ec2.Vpc.from_lookup(self, "Vpc", vpc_name="VPC1-VPC")

        vpc_endpoint = ec2.InterfaceVpcEndpoint(
            self,
            "VpcEndpoint",
            vpc=vpc,
            service=ec2.InterfaceVpcEndpointAwsService.APIGATEWAY,
        )

        eni_ids = vpc_endpoint.vpc_endpoint_network_interface_ids
        output_paths = [f"NetworkInterfaces.{id}.PrivateIpAddress" for id in range(3)]

        describe_network_interfaces_response = cr.AwsCustomResource(
            self,
            "DescribeEnis",
            on_update=cr.AwsSdkCall(
                api_version="v3",
                service="ec2",
                action="describeNetworkInterfaces",
                output_paths=output_paths,
                parameters={"NetworkInterfaceIds": eni_ids},
                physical_resource_id=cr.PhysicalResourceId.of(Fn.join("-", eni_ids)),
            ),
            policy=cr.AwsCustomResourcePolicy.from_sdk_calls(
                resources=cr.AwsCustomResourcePolicy.ANY_RESOURCE
            ),
        )
        ips = [
            describe_network_interfaces_response.get_response_field(op)
            for op in output_paths
        ]

        CfnOutput(
            self,
            "Ips",
            value=Fn.join(
                ",",
                ips,
            ),
        )


app = cdk.App()

if os.getenv("DEFAULT", "true") == "true":
    CdkMinimalStack(
        app,
        "Stack1",
        env=cdk.Environment(account="111122223333", region="eu-central-1"),
    )
CdkMinimalStack(
    app,
    "Stack2",
    env=cdk.Environment(account="222233334444", region="eu-central-1"),
)
if os.getenv("DEFAULT", "false") != "true":
        CdkMinimalStack(
        app,
        "Stack1",
        env=cdk.Environment(account="111122223333", region="eu-central-1"),
    )
app.synth()
DEFAULT=true cdk synth
grep CdkJsonStringify -r cdk.out
DEFAULT=true
cdk.out/Stack2.template.json:         "CdkJsonStringify2",
cdk.out/Stack2.template.json:         "CdkJsonStringify2",
cdk.out/Stack2.template.json:  "CdkJsonStringify2": {
cdk.out/Stack2.template.json:    "aws:cdk:path": "Stack2/CdkJsonStringify2/Default"
cdk.out/Stack1.template.json:         "CdkJsonStringify1",
cdk.out/Stack1.template.json:         "CdkJsonStringify1",
cdk.out/Stack1.template.json:  "CdkJsonStringify1": {
cdk.out/Stack1.template.json:    "aws:cdk:path": "Stack1/CdkJsonStringify1/Default"
cdk.out/manifest.json:        "/Stack1/CdkJsonStringify1/Default": [
cdk.out/manifest.json:            "data": "CdkJsonStringify1"
cdk.out/manifest.json:        "/Stack2/CdkJsonStringify2/Default": [
cdk.out/manifest.json:            "data": "CdkJsonStringify2"
cdk.out/tree.json:          "CdkJsonStringify1": {
cdk.out/tree.json:            "id": "CdkJsonStringify1",
cdk.out/tree.json:            "path": "Stack1/CdkJsonStringify1",
cdk.out/tree.json:                "path": "Stack1/CdkJsonStringify1/Default",
cdk.out/tree.json:          "CdkJsonStringify2": {
cdk.out/tree.json:            "id": "CdkJsonStringify2",
cdk.out/tree.json:            "path": "Stack2/CdkJsonStringify2",
cdk.out/tree.json:                "path": "Stack2/CdkJsonStringify2/Default",
DEFAULT=false cdk synth
grep CdkJsonStringify -r cdk.out
DEFAULT=false
cdk.out/Stack2.template.json:         "CdkJsonStringify1",
cdk.out/Stack2.template.json:         "CdkJsonStringify1",
cdk.out/Stack2.template.json:  "CdkJsonStringify1": {
cdk.out/Stack2.template.json:    "aws:cdk:path": "Stack2/CdkJsonStringify1/Default"
cdk.out/Stack1.template.json:         "CdkJsonStringify2",
cdk.out/Stack1.template.json:         "CdkJsonStringify2",
cdk.out/Stack1.template.json:  "CdkJsonStringify2": {
cdk.out/Stack1.template.json:    "aws:cdk:path": "Stack1/CdkJsonStringify2/Default"
cdk.out/manifest.json:        "/Stack2/CdkJsonStringify1/Default": [
cdk.out/manifest.json:            "data": "CdkJsonStringify1"
cdk.out/manifest.json:        "/Stack1/CdkJsonStringify2/Default": [
cdk.out/manifest.json:            "data": "CdkJsonStringify2"
cdk.out/tree.json:          "CdkJsonStringify1": {
cdk.out/tree.json:            "id": "CdkJsonStringify1",
cdk.out/tree.json:            "path": "Stack2/CdkJsonStringify1",
cdk.out/tree.json:                "path": "Stack2/CdkJsonStringify1/Default",
cdk.out/tree.json:          "CdkJsonStringify2": {
cdk.out/tree.json:            "id": "CdkJsonStringify2",
cdk.out/tree.json:            "path": "Stack1/CdkJsonStringify2",
cdk.out/tree.json:                "path": "Stack1/CdkJsonStringify2/Default",

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.156.0 (build 2966832)

Framework Version

No response

Node.js Version

v20.17.0

OS

macOS 14.6.1

Language

Python

Language Version

3.12.5

Other information

No response

Metadata

Metadata

Assignees

Labels

@aws-cdk/coreRelated to core CDK functionalitybugThis issue is a bug.effort/mediumMedium work item – several days of effortp1

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions