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

(core): exportValue fails on Intrinsics #19537

Closed
lxop opened this issue Mar 24, 2022 · 2 comments · Fixed by #19818
Closed

(core): exportValue fails on Intrinsics #19537

lxop opened this issue Mar 24, 2022 · 2 comments · Fixed by #19818
Assignees
Labels
@aws-cdk/core Related to core CDK functionality bug This issue is a bug. effort/small Small work item – less than a day of effort needs-triage This issue or PR still needs to be triaged. p1

Comments

@lxop
Copy link

lxop commented Mar 24, 2022

What is the problem?

When attempting to use Stack.exportValue to fix an inter-stack dependency, I found that it fails on the endpoint port of an RDS serverless cluster:

self.export_value(serverless_cluster.cluster_endpoint.port)

It works well on the other attributes I needed, only this one fails to synthesise.

Reproduction Steps

#!/usr/bin/env python3
from aws_cdk import (
    core as cdk,
    aws_rds as rds,
    aws_ec2 as ec2,
)


class Stack1(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str):
        super().__init__(scope, construct_id)

        old_cluster = rds.ServerlessCluster(
            self,
            "AuroraCluster",
            engine=rds.DatabaseClusterEngine.aurora_postgres(
                version=rds.AuroraPostgresEngineVersion.VER_13_4
            ),
            vpc=ec2.Vpc(self, "VPC"),
        )

        self.export_value(old_cluster.cluster_identifier)
        self.export_value(old_cluster.secret.secret_arn)
        self.export_value(old_cluster.cluster_endpoint.port)


app = cdk.App()
Stack1(app, "stack1")
app.synth()

What did you expect to happen?

The application should synthesise, and the cloudassembly should include exports for the cluster identifier, the secret ARN, and the cluster endpoint port.

What actually happened?

The application fails to synthesise with this error:

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

occurring on the line that exports the endpoint port.

CDK CLI Version

1.142.0 (build 5dd8e50)

Framework Version

No response

Node.js Version

v14.17.5

OS

OS X (Monterey)

Language

Python

Language Version

Python 3.8.12

Other information

From some experiments in the debugger, I've identified the source of the problem:

    const resolvable = Tokenization.reverse(exportedValue);
    if (!resolvable || !Reference.isReference(resolvable)) {
      throw new Error('exportValue: either supply \'name\' or make sure to export a resource attribute (like \'bucket.bucketName\')');
    }

The isReference() response is false, because the port is not a Reference, it's an Intrinsic. Skipping this check and carrying on with the rest of the logic worked just fine, so I'm not sure if the check simply needs to be changed to also accept Intrinsics or whether there is something special about this port attribute compared to other Intrinsics.

@lxop lxop added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Mar 24, 2022
@github-actions github-actions bot added the @aws-cdk/core Related to core CDK functionality label Mar 24, 2022
@ryparker ryparker added p1 effort/small Small work item – less than a day of effort labels Mar 25, 2022
rix0rrr added a commit that referenced this issue Apr 8, 2022
Number attributes go through two levels of encoding:

- L1: because of lack of type information, all attributes are assumed to
  be `string`s, so we do `Token.asString(new CfnReference(...))`.
- L2: we recast select attributes to numbers by doing `Token.asNumber()`.

The end result is a Token that looks like:

```ts
asNumber(Intrinsic(asString(CfnReference({ 'Fn::GetAtt': [...] }))))
```

When we do `Tokenization.reverse()` on the number, we only reverse
the *first* encoding one layer, leaving us with an `Intrinsic` instead
of the original `CfnReference`. `exportValue()` then rejects the value
as not being the right type of token.

Solution: before encoding, try to decode the given value so we always
encode the innermost token, and not any of the inbetween ones.

Fixes #19537.
@mergify mergify bot closed this as completed in #19818 Apr 8, 2022
mergify bot pushed a commit that referenced this issue Apr 8, 2022
Number attributes go through two levels of encoding:

- L1: because of lack of type information, all attributes are assumed to
  be `string`s, so we do `Token.asString(new CfnReference(...))`.
- L2: we recast select attributes to numbers by doing `Token.asNumber()`.

The end result is a Token that looks like:

```ts
asNumber(Intrinsic(asString(CfnReference({ 'Fn::GetAtt': [...] }))))
```

When we do `Tokenization.reverse()` on the number, we only reverse
the *first* encoding one layer, leaving us with an `Intrinsic` instead
of the original `CfnReference`. `exportValue()` then rejects the value
as not being the right type of token.

Solution: before encoding, try to decode the given value so we always
encode the innermost token, and not any of the inbetween ones.

Fixes #19537.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

github-actions bot commented Apr 8, 2022

⚠️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.

otaviomacedo pushed a commit that referenced this issue Apr 11, 2022
Number attributes go through two levels of encoding:

- L1: because of lack of type information, all attributes are assumed to
  be `string`s, so we do `Token.asString(new CfnReference(...))`.
- L2: we recast select attributes to numbers by doing `Token.asNumber()`.

The end result is a Token that looks like:

```ts
asNumber(Intrinsic(asString(CfnReference({ 'Fn::GetAtt': [...] }))))
```

When we do `Tokenization.reverse()` on the number, we only reverse
the *first* encoding one layer, leaving us with an `Intrinsic` instead
of the original `CfnReference`. `exportValue()` then rejects the value
as not being the right type of token.

Solution: before encoding, try to decode the given value so we always
encode the innermost token, and not any of the inbetween ones.

Fixes #19537.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
StevePotter pushed a commit to StevePotter/aws-cdk that referenced this issue Apr 27, 2022
Number attributes go through two levels of encoding:

- L1: because of lack of type information, all attributes are assumed to
  be `string`s, so we do `Token.asString(new CfnReference(...))`.
- L2: we recast select attributes to numbers by doing `Token.asNumber()`.

The end result is a Token that looks like:

```ts
asNumber(Intrinsic(asString(CfnReference({ 'Fn::GetAtt': [...] }))))
```

When we do `Tokenization.reverse()` on the number, we only reverse
the *first* encoding one layer, leaving us with an `Intrinsic` instead
of the original `CfnReference`. `exportValue()` then rejects the value
as not being the right type of token.

Solution: before encoding, try to decode the given value so we always
encode the innermost token, and not any of the inbetween ones.

Fixes aws#19537.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@kingakimbrel
Copy link

We're facing this issue when trying to do

this.certificate = new DnsValidatedCertificate(this, "ApiCertificate", {
  domainName: zonalHostedZoneName,
  hostedZone: this.zonalHostedZone,
  region: props.env.region,
});

this.exportValue(this.certificate.certificateArn)
Error: exportValue: either supply 'name' or make sure to export a resource attribute (like 'bucket.bucketName')
    at OrchestratorDnsStack.resolveExportedValue (/workplace/avjocely/EROS/src/AmsEventRouterCDK/node_modules/aws-cdk-lib/core/lib/stack.js:1:16682)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/core Related to core CDK functionality bug This issue is a bug. effort/small Small work item – less than a day of effort needs-triage This issue or PR still needs to be triaged. p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants