aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.59k stars 3.89k forks source link

HostedZone: Referencing array attributes cross-stack breaks with Template Format Error #22846

Closed surecloud-meason closed 1 year ago

surecloud-meason commented 1 year ago

Describe the bug

When referencing a HostedZoneNameServer from another stack the Output created is invalid and on deployment errors with: "Template format error: Every Value member must be a string."

CDK Synth Cloudformation Snippet Generated:

Outputs:
  ExportsOutputFnGetAttprodukdnshostedzone423B3F93NameServers1C276690:
    Value:
      Fn::GetAtt:
        - produkdnshostedzone423B3F93
        - NameServers
    Export:
      Name: prod-uk-dns:ExportsOutputFnGetAttprodukdnshostedzone423B3F93NameServers1C276690

Expected Behavior

The auto created output handles lists correctly for use within another stack.

Current Behavior

The deploy fails due to an cloudformation format error .

Reproduction Steps

DNS Stack:

import {Construct} from 'constructs';
import {StackProps} from 'aws-cdk-lib';
import {PublicHostedZone} from 'aws-cdk-lib/aws-route53';

export interface DnsStackProps extends StackProps {
    zoneName: string;
}

export class Dns1Stack extends Stack {

    public readonly hostedZone: PublicHostedZone;

    constructor(scope: Construct, id: string, props: DnsStackProps) {
        super(scope, id, props);

        this.hostedZone = new PublicHostedZone(this, `${this.stackName}-hosted-zone`, {
                zoneName: props.zoneName,
            }
        );

    }
}

Stack Referencing the above stack

import {Construct} from 'constructs';
import {Duration, StackProps} from 'aws-cdk-lib';
import {PublicHostedZone} from 'aws-cdk-lib/aws-route53';

export interface DnsStackProps extends StackProps {
    zoneName: string;
    dnsHostedZone: PublicHostedZone;
}

export class Dns2Stack extends Stack {
    constructor(scope: Construct, id: string, props: DnsStackProps) {
        super(scope, id, props);

        const timeToLiveMinutes = 5;

        new NsRecord(this, `${this.stackName}-prod-env-ns-record-set`, {
            zone: hostedZone,
            recordName: props.dnsHostedZone.zoneName,
            values: props.dnsHostedZone.hostedZoneNameServers as string[],
            ttl: Duration.minutes(timeToLiveMinutes),
        });

    }
}

Stack Instantiations

const Dns1Stack = new Dns1Stack(app, `dns1`, {
    zoneName: `${deploymentType}.somedomain.com`,
    env: {
        region: 'us-east-1',
    },
});

const Dns2Stack = new Dns2Stack(app, `dns2`, {
    zoneName: 'somedomain.com',
    dnsHostedZone: Dns1Stack.hostedZone,
    env: {
        region: 'us-east-1',
    },
});

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.50.0

Framework Version

No response

Node.js Version

v16.18.0

OS

Ubuntu 20.04

Language

Typescript

Language Version

No response

Other information

No response

peterwoodworth commented 1 year ago

Thanks for reporting this @surecloud-meason, I was able to reproduce this.

I'm pretty stumped why this is occurring. Everything in the template is formatted correctly, there should be no validation errors occurring here.

I've created a ticket for CloudFormation (P75318355), hopefully they'll be able to help out here. I'll let you know if there are any updates. Thanks!

peterwoodworth commented 1 year ago

Ah, the issue is due to the result of the output HostedZone.NameServers being a list of strings. Here is how the template could look instead:

Outputs:
  HZNameServer:
    Value: !Join ["", !GetAtt myHostedZone.NameServers]

You could work around this for now by creating your own CfnOutput and referencing it directly in the other stack when needed

comcalvi commented 1 year ago

Is this still an issue? Pretty sure this has been fixed by #22873

peterwoodworth commented 1 year ago

Yeah we can probably close this, I tested this prior to the change linked

github-actions[bot] commented 1 year ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

kbrownlees commented 3 months ago

@peterwoodworth I just hit this with the latest version of CDK (2.147.2 (build f4b0897)) FYI. Basically the same setup - create a hosted zone in my main stack and trying to reference .hostedZoneNameServers when creating a ZoneDelegationRecord in another Stack.

adminy commented 1 month ago

image

As you can see in the docs @kbrownlees, it says that it will be undefined if its imported from another stack.

I wish this was different, because It feels pretty dumb.