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 doesn't respect overridelogicalId #14335

Closed
liamfd opened this issue Apr 22, 2021 · 3 comments · Fixed by #20560
Closed

(core): exportValue doesn't respect overridelogicalId #14335

liamfd opened this issue Apr 22, 2021 · 3 comments · Fixed by #20560
Assignees
Labels
@aws-cdk/core Related to core CDK functionality bug This issue is a bug. effort/medium Medium work item – several days of effort p1

Comments

@liamfd
Copy link

liamfd commented Apr 22, 2021

If we create a stack like:

import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
import * as iam from '@aws-cdk/aws-iam';

/**
 * Stack that defines the bucket
 */
class Producer extends cdk.Stack {
  public readonly myBucket: s3.Bucket;

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

    const bucket = new s3.Bucket(this, 'MyBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });
    this.myBucket = bucket;

    this.exportValue(bucket.bucketArn);

    const cfnResource = bucket.node.defaultChild as s3.CfnBucket;
    cfnResource.overrideLogicalId('OVERRIDE_LOGICAL_ID');
  }
}

interface ConsumerProps extends cdk.StackProps {
  userBucket: s3.IBucket;
}

/**
 * Stack that consumes the bucket
 */
class Consumer extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: ConsumerProps) {
    super(scope, id, props);

    const user = new iam.User(this, 'MyUser');
    props.userBucket.grantReadWrite(user);
  }
}

const app = new cdk.App();
const producer = new Producer(app, 'ProducerStack');
new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket });

If we synth that, we get this in Producer:

    "ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58": {
      "Value": {
        "Fn::GetAtt": [
          "OVERRIDE_LOGICAL_ID",
          "Arn"
        ]
      },
      "Export": {
        "Name": "ProducerStack:ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58"
      }
    },
    "ExportsOutputFnGetAttOVERRIDELOGICALIDArn49941B8D": {
      "Value": {
        "Fn::GetAtt": [
          "OVERRIDE_LOGICAL_ID",
          "Arn"
        ]
      },
      "Export": {
        "Name": "ProducerStack:ExportsOutputFnGetAttOVERRIDELOGICALIDArn49941B8D"
      }
    }

As you can see, both of these have the same value, but different names. Consumer uses the output with the overridden ID:

                {
                  "Fn::ImportValue": "ProducerStack:ExportsOutputFnGetAttOVERRIDELOGICALIDArn49941B8D"
                },

Some other cases:

  • If we comment out overrideLogicalId we get only ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58 in both stacks
  • If we keep the override but remove the reference in Consumer we get only theExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58 Output in Producer
  • If we move the exportValue after the overrideLogicalId we get only ExportsOutputFnGetAttOVERRIDELOGICALIDArn49941B8D in both stacks

So, basically, it seems like exportValue creates the name for the initial logicalId and that doesn't change when it gets overridden. References in other stacks will create Outputs based on the new logicalId, ignoring the ones created by exportValue.

I believe this makes it a bit harder to use exportValue to avoid the deadly embrace, because the Outputs it generates in this case aren't the ones imported in a dependent's stack.

Reproduction Steps

I just created a file with the above and passed it to a cdk synth --app 'yarn babel-node my-file.ts'.

What did you expect to happen?

I'd expect just a single Output.

What actually happened?

Two Outputs get created, Consumer does not reference the Output created with createExports, it references a lazily created Output that includes the overridden logicalId in its name.

Environment

  • CDK CLI Version : 1.91.0 and 1.100.0
  • Framework Version: 1.91.0 and 1.100.0
  • Node.js Version: v10.19.0
  • OS : MacOS 10.15.7
  • Language (Version): TypeScript (4.0.2)

Other

It's worth noting that this is pretty easy to work around - you just have to call exportValue after overrideLogicalId.


This is 🐛 Bug Report

@liamfd liamfd added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Apr 22, 2021
@github-actions github-actions bot added the @aws-cdk/core Related to core CDK functionality label Apr 22, 2021
@rix0rrr rix0rrr changed the title (core): overrideLogicalId changes Output created by exportValue's name (core): exportValue doesn't respect overridelogicalId May 10, 2021
@rix0rrr rix0rrr added effort/medium Medium work item – several days of effort p1 labels May 10, 2021
@NGL321 NGL321 removed the needs-triage This issue or PR still needs to be triaged. label Jun 2, 2021
@NGL321
Copy link
Contributor

NGL321 commented Jun 2, 2021

Hey @liamfd,

Thank you for reporting this, this does look concerning. If you want to implement and submit a fix yourself, that would be welcomed, otherwise someone from the dev team will take a look as soon as time permits.

If you want to increase visibility with 👍 to the issue we may bump it up on our priority list.

😸 😷

@corymhall corymhall self-assigned this May 25, 2022
@corymhall
Copy link
Contributor

I don't think this is something that we can improve upon. When you call Stack.exportValue it creates a CfnOutput with a resolved id. This id has to be resolved when you call exportValue which is why it does not/cannot know the updated logicalId.

if (!output) {
new CfnOutput(exportsScope, id, { value: Token.asString(exportable), exportName });
}

We could potentially add a validation that will throw an error if the ids pre/post synthesis are different with instructions on how to fix.

Not sure if you have any other thoughts @rix0rrr

@mergify mergify bot closed this as completed in #20560 Jun 1, 2022
mergify bot pushed a commit that referenced this issue Jun 1, 2022
When using `Stack.exportValue` to manually create a CloudFormation
export, the logicalId of the referenced resource is used to generate the
logicalId of the `CfnExport`. Because `exportValue` creates a
`CfnExport` _and_ returns an `importValue` it needs to _resolve_ the
logicalId at call time. If the user later overrides the logicalId of the
referenced resource, that override is reflected in the export/import
that was created earlier.

There doesn't seem to be a way to solve this without incurring a
breaking change so this PR attempts to smooth a rough edge by "locking"
the `logicalId` when `exportValue` is called. If the user attempts to
override the id _after_ that point, an error message will be thrown

closes #14335


----

### All Submissions:

* [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/master/INTEGRATION_TESTS.md)?
	* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*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 Jun 1, 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.

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/medium Medium work item – several days of effort p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants