Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolution error: Cannot use resource 'x' in a cross-environment fashion, the resource's physical name must be explicit set

I'm trying to pass an ecs cluster from one stack to another stack.

I get this error: Error: Resolution error: Resolution error: Resolution error: Cannot use resource 'BackendAPIStack/BackendAPICluster' in a cross-environment fashion, the resource's physical name must be explicit set or use `PhysicalName.GENERATE_IF_NEEDED`.

The cluster is defined as below in BackendAPIStack:

this.cluster = new ecs.Cluster(this, 'BackendAPICluster', {
   vpc: this.vpc
});

The stacks are defined as follows:

 const backendAPIStack = new BackendAPIStack(app, `BackendAPIStack${settingsForThisEnv.stackVersion}`, {
    env: {
      account: process.env.CDK_DEFAULT_ACCOUNT,
      region: process.env.CDK_DEFAULT_REGION
    },
    digicallPolicyQueue: digicallPolicyQueue,
    environmentName,
    ...settingsForThisEnv
  });

  const metabaseStack = new MetabaseStack(app, 'MetabaseStack', backendAPIStack.vpc, backendAPIStack.cluster, {
    vpc: backendAPIStack.vpc,
    cluster: backendAPIStack.cluster
  });

  metabaseStack.addDependency(backendAPIStack);

Here's the constructor for metabaseStack:

constructor(scope: cdk.Construct, id: string, vpc: ec2.Vpc, cluster: ecs.Cluster, props: MetabaseStackProps) {
        super(scope, id, props);

        console.log('cluster', cluster)

        this.vpc = vpc;
        this.cluster = cluster;

        this.setupMetabase()
    }

and then I'm using the cluster here:

      const metabaseService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Metabase', {
            assignPublicIp: false,
            cluster: this.cluster,
...

I can't find documentation on how to do what I'm trying to do.

like image 908
jeznag Avatar asked Dec 13 '22 08:12

jeznag


1 Answers

You're creating a Region/Account-specific Stack with BackendAPIStack because you're binding the stack to a specific account and region via the env prop value.

Then you're creating a Region/Account-agnostic stack by creating the MetabaseStack without any env prop value.

In general, having two independent stacks like this is fine, but here you're linking them together by passing a reference from the BackendAPIStack to the MetabaseStack, which won't work.

This is a problem because CDK normally links Stacks together by performing Stack Exports and Imports of values, but CloudFormation does not support cross-region or cross-account Stack references

So, your possible solutions are:

  • (A) Set up your MetabaseStack to use the same account/region as your BackendAPIStack
    • Under the hood this will setup the Cluster's ARN to be a Stack export from BackendAPICluster and then MetabaseStack will be able to import it.
  • (B1) Create BackendAPICluster with a clusterName that you pick.
    • i.e. new Cluster(..., {vpc: this.vpc, clusterName: 'backendCluster' })
    • By not providing a name, you're using the default of "CloudFormation-generated name" which is the basis of the issue that CDK is reporting, albeit it in a confusing way.
    • When you do provide a name, then the ARN for the cluster is deterministic (not picked by CloudFormation at deployment time) so CDK then has enough information at build time to determine what the Cluster's ARN will be and can provide that to your MetabaseStack.
  • (B2) Create BackendAPICluster with a clusterName and let CDK pick
    • This is done by setting the clusterName to PhysicalName.GENERATE_IF_NEEDED
      • i.e. new Cluster(..., {clusterName: PhysicalName.GENERATE_IF_NEEDED })
    • PhysicalName.GENERATE_IF_NEEDED is a marker that indicates that a physical (name) will only be generated by the CDK if it is needed for cross-environment references. Otherwise, it will be allocated by CloudFormation.
    • This is what the error is trying to tell you, but I didn't understand it either...

If possible, I would go with (A). I suspect it was just an oversight anyway that you weren't passing the same env values to the MetabaseStack and you probably want both of these stacks in the same region to reduce latency and all that.

If not, then I would personally then go with (B2) next because I try to not give any of my resources explicit names unless they are part of some contract with another group. I.e. Assume the role named 'ServiceWorker' in Account XYZ or Download the data from Bucket 'ABC'.

like image 97
Matt Klein Avatar answered May 16 '23 06:05

Matt Klein