in src/experimental/patterns/ec2-app.ts [131:193]
public visit(construct: IConstruct) {
if (construct instanceof CfnScalingPolicy) {
const { node } = construct;
const { scopes, path } = node;
/*
Requiring a `CfnScalingPolicy` to be created in the scope of a `GuAutoScalingGroup`
is the most reliable way to associate the two together.
Though the `autoScalingGroupName` property is passed to a `CfnScalingPolicy` when instantiating,
this does not create a concrete link as AWS CDK sets the value to be the ASG's `Ref`.
That is, it is a `Token` until it is synthesised.
This is even if the ASG has an explicit name set.
See also:
- https://docs.aws.amazon.com/cdk/v2/guide/tokens.html
- https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-autoscalinggroup.html#aws-resource-autoscaling-autoscalinggroup-return-values
- https://github.com/aws/aws-cdk/blob/f6b649d47f8bc30ca741fbb7a4852d51e8275002/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts#L1560
*/
const autoScalingGroup = scopes.find((_): _ is GuAutoScalingGroup => _ instanceof GuAutoScalingGroup);
if (!autoScalingGroup) {
throw new Error(
`Failed to detect the autoscaling group relating to the scaling policy on path ${path}. Was it created in the scope of a GuAutoScalingGroup?`,
);
}
const cfnAutoScalingGroup = autoScalingGroup.node.defaultChild as CfnAutoScalingGroup;
const currentRollingUpdate = cfnAutoScalingGroup.cfnOptions.updatePolicy?.autoScalingRollingUpdate;
if (currentRollingUpdate) {
/*
An autoscaling group that horizontally scales should not explicitly set `Desired`,
as a rolling update will set the current `Desired` back to the template version,
undoing any changes that a scale-out event may have done.
*/
cfnAutoScalingGroup.desiredCapacity = undefined;
const asgNodeId = autoScalingGroup.node.id;
if (!this.asgToParamMap.has(asgNodeId)) {
const cfnParameterName = getAsgRollingUpdateCfnParameterName(autoScalingGroup);
this.asgToParamMap.set(
asgNodeId,
new CfnParameter(this.stack, cfnParameterName, {
type: "Number",
default: parseInt(cfnAutoScalingGroup.minSize),
maxValue: parseInt(cfnAutoScalingGroup.maxSize) - 1,
}),
);
}
const minInstancesInService = this.asgToParamMap.get(asgNodeId)!;
cfnAutoScalingGroup.cfnOptions.updatePolicy = {
autoScalingRollingUpdate: {
...currentRollingUpdate,
minInstancesInService: minInstancesInService.valueAsNumber,
},
};
}
}
}