-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Describe the bug
Calling cluster.addAsgCapacityProvider(provider)
does two things that cause a circular dependency, and this causes issues when the Cluster and the Capacity Provider are in different Cloudformation stacks:
- Add the clusterName to the autoscaling group's userData:
provider.autoScalingGroup.addUserData(
`cluster = "${this.clusterName}"`,
)
- Add the capacity provider to the cluster's list:
cluster._capacityProviderNames.push(provider.capacityProviderName);
This creates a circular dependency that manifests on the following error when running yarn cdk synth:
ValidationError: 'CapacityProviderStack' depends on 'ComputeStack' (CapacityProviderStack -> ComputeStack/Cluster/Resource.Arn). Adding this dependency (ComputeStack -> CapacityProviderStack/CapacityProvider/CapacityProvider.Ref) would create a cyclic reference.
at path [ComputeStack] in aws-cdk-lib.Stack
So, these two resources (cluster and provider) must be in the same stack for addAsgCapacityProvider
to work, which is not documented and not compatible with our setup.
For this to be addressed the necessary change is quite small, since the only thing the capacity provider needs to know about the stack is it's name, not anything that is actually computed at runtime.
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Library Version
No response
Expected Behavior
cluster.addAsgCapacityProvider(provider)
should not introduce a circular dependency between cluster
and provider
. It should just make cluster
depend on provider
Current Behavior
cluster.addAsgCapacityProvider(provider)
introduces a circular dependency.
Reproduction Steps
The following will create two stacks. One with the autoscaling group and another with the capacity provider and the ecs cluster. This will lead to the error.
import { Stack } from "aws-cdk-lib";
import * as autoscaling from "aws-cdk-lib/aws-autoscaling";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import { Construct } from "constructs";
class CapacityProviderStack extends Stack {
autoScalingGroup: autoscaling.AutoScalingGroup;
constructor(scope: Construct) {
super(scope, "CapacityProviderStack");
this.autoScalingGroup = new autoscaling.AutoScalingGroup(
this,
"AutoScalingGroup",
{
vpc: new ec2.Vpc(this, "Vpc"),
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T4G,
ec2.InstanceSize.SMALL
),
}
);
}
}
class ComputeStack extends Stack {
constructor(
scope: Construct,
autoScalingGroup: autoscaling.AutoScalingGroup
) {
super(scope, "ComputeStack");
const cluster = new ecs.Cluster(this, "Cluster");
const capacityProvider = new ecs.AsgCapacityProvider(
this,
"CapacityProvider",
{
autoScalingGroup,
}
);
cluster.addAsgCapacityProvider(capacityProvider);
}
}
export default function reproIssue(scope: Construct) {
const capacityProviderStack = new CapacityProviderStack(scope);
new ComputeStack(scope, capacityProviderStack.autoScalingGroup);
}
Possible Solution
Reimplement the addAsgCapacityProvider
function to support this, e.g. by taking in the cluster name as a parameter and not introduce the Cfn dependency.
Additional Information/Context
It doesn't matter in which of the two stacks the AsgCapacityProvider is created. As long as the cluster and the ASG are in different cloudformation stacks, this happens.
AWS CDK Library version (aws-cdk-lib)
AWS CDK CLI version
2.1023.0 (build 45ceb89)
Node.js Version
v22.17.1
OS
MacOS 15.6
Language
TypeScript
Language Version
No response
Other information
No response