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

(Route53): HostedZone name_servers cannot be an automatic export with self.export_value #32420

Open
1 task
Cameronsplaze opened this issue Dec 9, 2024 · 0 comments
Labels
@aws-cdk/aws-route53 Related to Amazon Route 53 bug This issue is a bug. needs-triage This issue or PR still needs to be triaged.

Comments

@Cameronsplaze
Copy link

Cameronsplaze commented Dec 9, 2024

Describe the bug

If you have two stacks, and want to pass name servers from stack A to stack B, CDK will create the automatic import/export to help. There's no way to set self.export_value on the hosted zone's nameservers export, to keep it declared when re-deploying. (This also blocks removing automatic cross stack references)

Regression Issue

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

Last Known Working CDK Version

No response

Expected Behavior

If you add self.export_value(hosted_zone.hosted_zone_name_servers) on a export that already exists, it becomes apart of the stack and you can deploy again.

Current Behavior

The main error is it sees the nameserver as a list, which it is. It must be a string:

Template format error: Every Value member must be a string.

I found a way to change it to the string it's expecting in the next section, but since I transformed the object, it no longer can reference the same object/export.

Reproduction Steps

With the following App:

#!/usr/bin/env python3
import os
import aws_cdk as cdk
from example_stacks.example_stacks import ExampleStackA, ExampleStackB

app = cdk.App()
stack_a = ExampleStackA(app, "ExampleStackA")

stack_b = ExampleStackB(
    app, "ExampleStackB",
    hosted_zone=stack_a.hosted_zone,
    imported_hosted_zone=stack_a.imported_hosted_zone,
)

app.synth()

And inside ./example_stacks/example_stacks.py:

from aws_cdk import (
    Stack,
    aws_route53 as route53,
)
from constructs import Construct

class ExampleStackA(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        # Normally I import this with `from_hosted_zone_attributes`, but for a contained example:
        self.imported_hosted_zone = route53.PublicHostedZone(
            self,
            "ImportedHostedZone",
            zone_name="hopefully.does.not.exist.com",
        )
        # https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.PublicHostedZone.html
        self.hosted_zone = route53.PublicHostedZone(
            self,
            "HostedZone",
            zone_name="hopefully.does.not.exist.com",
        )


class ExampleStackB(Stack):

    def __init__(self, scope: Construct, construct_id: str, hosted_zone, imported_hosted_zone, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        self.ns_record = route53.NsRecord(
            self,
            "NsRecord",
            zone=imported_hosted_zone,
            values=hosted_zone.hosted_zone_name_servers,
            record_name=f"testing.{hosted_zone.zone_name}",
        )

The self.imported_hosted_zone is a domain bought from AWS, so that hosted zone doesn't live in any stack.

Deploy both stacks to your account:

cdk deploy ExampleStackA
cdk deploy ExampleStackB

Then comment out ExampleStackB inside app.py, and deploy A again. (cdk deploy ExampleStackA). You'll get

Delete canceled. Cannot delete export ExampleStackA:ExportsOutputRefImportedHostedZone5BCE6932C2366AAA as it is in use by ExampleStackB.

(Commenting out B because in the normal architecture, I have a one-to-many with one A, and many B's. Sometimes I need to only deploy A too, it's shared resources for everything. BUT more basically, if both stacks in different apps, that'd also hit this).

The normal way to fix this issue, is to add self.export_value(resource) to the end of stack A. When I try to do that with the hosted_zone_name_servers (with self.export_value(self.hosted_zone.hosted_zone_name_servers)):

  1. Add self.export_value(self.hosted_zone.hosted_zone_name_servers) to the end of stack A
  2. Uncomment B and deploy, so the change can deploy out. (cdk deploy ExampleStackB)

You'll get an error Template format error: Every Value member must be a string.. It's a list of one item.

You can change it away from a list with self.export_value(Fn.join("||", self.hosted_zone.hosted_zone_name_servers)), but then it doesn't recognize it as the same export as before. You'll get:

RuntimeError: Error: exportValue: either supply 'name' or make sure to export a resource attribute (like 'bucket.bucketName')

Even if you set the name and somehow match it to the generated one, it'll complain about duplicates and fail.

And if you import the self.hosted_zone itself from A to B with route53.PublicHostedZone.from_hosted_zone_attributes, then zone.hosted_zone_name_servers is None (which is expected, the docs say so).


The only solution I've found so far, is to manually export/import it. This avoids CDK creating the automatic one that's blocking the stack_a deployments:

# Inside Stack A:
        self.export_value(
            Fn.join("||", self.hosted_zone.hosted_zone_name_servers),
            name=f"{construct_id}-HostedZoneNameServers",
        )
# Inside Stack B:
        # Must be a list, that's what `values` is expecting.
        hosted_zone_name_servers = [Fn.import_value(f"{stack_a.stack_name}-HostedZoneNameServers")]

Possible Solution

Ideally to make self.export_value(nameserver) work like all the other objects I can call self.export_value on.

Additional Information/Context

No response

CDK CLI Version

2.171.1 (build a95560c)

Framework Version

No response

Node.js Version

v22.11.0

OS

Fedora 41

Language

Python

Language Version

Python 3.13.0

Other information

No response

@Cameronsplaze Cameronsplaze added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Dec 9, 2024
@github-actions github-actions bot added the @aws-cdk/aws-route53 Related to Amazon Route 53 label Dec 9, 2024
@Cameronsplaze Cameronsplaze changed the title (Route53): HostedZone name_servers cannot be output param with self.export_value (Route53): HostedZone name_servers cannot be automatic exports with self.export_value Dec 9, 2024
@Cameronsplaze Cameronsplaze changed the title (Route53): HostedZone name_servers cannot be automatic exports with self.export_value (Route53): HostedZone name_servers cannot be an automatic export with self.export_value Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-route53 Related to Amazon Route 53 bug This issue is a bug. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

1 participant