-
Notifications
You must be signed in to change notification settings - Fork 4k
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
feat(autoscaling): add new HealthChecks
for multiple health check types, including EBS and VPC_LATTICE types
#31286
Conversation
HealthChecks
instead of old HealthCheck
HealthChecks
instead of old HealthCheck
HealthChecks
for multiple health check types, including EBS and VPC_LATTICE types
/** | ||
* Additional Health Check Type | ||
*/ | ||
export enum AdditionalHealthCheckType { | ||
/** | ||
* ELB Health Check | ||
*/ | ||
ELB = 'ELB', | ||
/** | ||
* EBS Health Check | ||
*/ | ||
EBS = 'EBS', | ||
/** | ||
* VPC LATTICE Health Check | ||
*/ | ||
VPC_LATTICE = 'VPC_LATTICE', | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EC2 had to be excluded because specifying EC2 and other types together would result in a CFn error.
Resource handler returned message: "Specifying EC2 in addition to other health check types is not supported. Remove EC2 from HealthCheckType and try again. (Service: AutoScaling, Status Code: 400, Request ID: ...
* @default Duration.seconds(0) | ||
* @see https://docs.aws.amazon.com/autoscaling/ec2/userguide/health-check-grace-period.html | ||
*/ | ||
readonly grace?: Duration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The grace
has to be specified in the existing ELB options, but this is not necessary now. (I actually deployed the configuration without the grace
successfully).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @go-to-k for the contribution. Left some minor comments with some recommendations and for my understanding.
|
||
// THEN | ||
Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { | ||
HealthCheckType: 'EBS,ELB,VPC_LATTICE', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
qq: Since EC2 healthcheck is default and can't be disabled, shouldn't it be present in the HealthCheckType along with the additional types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifying those types with EC2 will result in a CFn error.
In other words, the following patterns can be allowed:
EC2
only- Other types without
EC2
- e.g.
EBS,ELB
- Actually includes EC2 health check internally.
- e.g.
export enum AdditionalHealthCheckType { | ||
/** | ||
* ELB Health Check | ||
*/ | ||
ELB = 'ELB', | ||
/** | ||
* EBS Health Check | ||
*/ | ||
EBS = 'EBS', | ||
/** | ||
* VPC LATTICE Health Check | ||
*/ | ||
VPC_LATTICE = 'VPC_LATTICE', | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add EBS
and VPC_LATTICE
to existing enum HealthCheckType
instead of creating new one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing HealthCheckType
has EC2 as a type. However, that makes it look like EC2 can be specified with other types, but in fact EC2 cannot be specified when other types are specified.
That's why I have a new type to specify something other than EC2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for claryfing. While creating a separate enum for additional health check types is a valid strategy and makes sense, I believe we can achieve the same functionality and enforce the validation in the existing enum withim the HealthChecks constructor. However I'm ok creating a new enum without EC2, but it would be good if we can rename this enum for better clarity and maintainablity. Let me know if it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. But I'm still not sure and would like to sort this out again.
In static ec2()
, the user does not specify any types (the EC2 type), and the EC2 type is automatically specified internally. In static withAdditionalChecks()
, the user must not choose the EC2 type.
This means that the user never gets a chance to use the EC2 type. Therefore, I'm not sure that there is reason for EC2 to appear in the enum. (The existing old enum was not exported and only used internally, whereas the new enum is different in that it is exported.)
I considered allowing the EC2 type to be specified, and then internally excluding the EC2 if it was specified, but I thought that users might be confused when they looked at the generated CFn template and realised that the EC2 was missing.
Is there any reason why the EC2 type should still be included in the enum? Please let me know if I have misunderstood something fundamental.
Also, the method name has been changed to withAdditionalChecks()
, but the name AdditionalHealthCheckType
for the type name is still unnatural?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered allowing the EC2 type to be specified, and then internally excluding the EC2 if it was specified, but I thought that users might be confused when they looked at the generated CFn template and realised that the EC2 was missing.
I thought it would be good to use the EC2 enum in the ec2 method below instead of specifiying it as string. But I agree and makes sense that it might confuse users of having EC2 in the enum when it can't be used.
public static ec2(options: Ec2HealthChecksOptions = {}): HealthChecks {
return new HealthChecks(['EC2'], options.gracePeriod);
}
Also, the method name has been changed to withAdditionalChecks(), but the name AdditionalHealthCheckType for the type name is still unnatural?
I think should be ok since with withAdditionalChecks
it is more clearer.
public static addition(options: AdditionalHealthChecksOptions): HealthChecks { | ||
return new HealthChecks(options.additionalTypes, options.grace); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think would be good to rename this method to combine
public static combine(options: HealthChecksOptions): HealthChecks {
return new HealthChecks(options);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that this would allow EC2 to be specified as well. I would suggest putting in the nuance of "in addition to" EC2, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the intention. However addition
, additionalTypes
doesn't sound like a better naming and unclear.
I would recommend as extendedChecks
or withAdditionalChecks
. What do you think?
HealthChecks.extendedChecks({ types: [HealthCheckType.ELB, HealthCheckType.EBS] })
HealthChecks.withAdditionalChecks({ types: [HealthCheckType.ELB, HealthCheckType.EBS] })
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also would be good to have consistent name for gracePeriod prop
. I see in healthchecks constructor we use as gracePeriod
and in other places as grace
. Would be good to use either of. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend as extendedChecks or withAdditionalChecks. What do you think?
I would prefer withAdditionalChecks
, I changed the name to it.
Also would be good to have consistent name for gracePeriod prop. I see in healthchecks constructor we use as gracePeriod and in other places as grace. Would be good to use either of. What do you think?
That's right. (The existing class did that, so I had copied them...)
Changed it with gracePeriod
.
/** | ||
* Health check settings for multiple types | ||
*/ | ||
export class HealthChecks { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to propose something like below for the new property and healthchecks class. Let me know if it makes sense
//new property
readonly healthChecks?: HealthChecks;
export interface HealthChecksOptions {
readonly types: HealthCheckType[];
readonly gracePeriod?: Duration;
}
export class HealthChecks {
private constructor(public readonly options: HealthChecksOptions) {}
/**
* Configure one or more health check types
*/
public static combine(options: HealthChecksOptions): HealthChecks {
return new HealthChecks(options);
}
/**
* EC2 health check
*/
public static ec2(options: Ec2HealthChecksOptions = {}): HealthChecks {
return new HealthChecks({
types: [HealthCheckType.EC2],
gracePeriod: options.grace,
});
}
Example useage:
// Single health check (backward compatible style)
new autoscaling.AutoScalingGroup(stack, 'MyFleet1', {
// ... other properties ...
healthChecks: HealthChecks.ec2(),
});
// Multiple health checks
new autoscaling.AutoScalingGroup(stack, 'MyFleet2', {
// ... other properties ...
healthChecks: HealthChecks.combine({
types: [HealthCheckType.ELB, HealthCheckType.EBS],
gracePeriod: Duration.minutes(15),
}),
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would allow HealthCheckType
s (types: HealthCheckType[];
) to be passed in the static ec2
argument. However, when specifying an EC2, no other type should be passed, so extra validation would have to be implemented. Also it would be easier for the user to use if nothing of any type could be specified.
Therefore I think it would be good as it is, what do you think?
packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts
Outdated
Show resolved
Hide resolved
packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your review!
Could you please take a look at some of the comments I have returned?
|
||
// THEN | ||
Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { | ||
HealthCheckType: 'EBS,ELB,VPC_LATTICE', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifying those types with EC2 will result in a CFn error.
In other words, the following patterns can be allowed:
EC2
only- Other types without
EC2
- e.g.
EBS,ELB
- Actually includes EC2 health check internally.
- e.g.
/** | ||
* Health check settings for multiple types | ||
*/ | ||
export class HealthChecks { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would allow HealthCheckType
s (types: HealthCheckType[];
) to be passed in the static ec2
argument. However, when specifying an EC2, no other type should be passed, so extra validation would have to be implemented. Also it would be easier for the user to use if nothing of any type could be specified.
Therefore I think it would be good as it is, what do you think?
public static addition(options: AdditionalHealthChecksOptions): HealthChecks { | ||
return new HealthChecks(options.additionalTypes, options.grace); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that this would allow EC2 to be specified as well. I would suggest putting in the nuance of "in addition to" EC2, what do you think?
export enum AdditionalHealthCheckType { | ||
/** | ||
* ELB Health Check | ||
*/ | ||
ELB = 'ELB', | ||
/** | ||
* EBS Health Check | ||
*/ | ||
EBS = 'EBS', | ||
/** | ||
* VPC LATTICE Health Check | ||
*/ | ||
VPC_LATTICE = 'VPC_LATTICE', | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing HealthCheckType
has EC2 as a type. However, that makes it look like EC2 can be specified with other types, but in fact EC2 cannot be specified when other types are specified.
That's why I have a new type to specify something other than EC2.
packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts
Outdated
Show resolved
Hide resolved
packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts
Outdated
Show resolved
Hide resolved
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #31286 +/- ##
=======================================
Coverage 82.21% 82.21%
=======================================
Files 119 119
Lines 6876 6876
Branches 1162 1162
=======================================
Hits 5653 5653
Misses 1120 1120
Partials 103 103
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @go-to-k for addressing the earlier comments. Left some followup comments with suggestions and for my understanding.
public static addition(options: AdditionalHealthChecksOptions): HealthChecks { | ||
return new HealthChecks(options.additionalTypes, options.grace); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the intention. However addition
, additionalTypes
doesn't sound like a better naming and unclear.
I would recommend as extendedChecks
or withAdditionalChecks
. What do you think?
HealthChecks.extendedChecks({ types: [HealthCheckType.ELB, HealthCheckType.EBS] })
HealthChecks.withAdditionalChecks({ types: [HealthCheckType.ELB, HealthCheckType.EBS] })
public static addition(options: AdditionalHealthChecksOptions): HealthChecks { | ||
return new HealthChecks(options.additionalTypes, options.grace); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also would be good to have consistent name for gracePeriod prop
. I see in healthchecks constructor we use as gracePeriod
and in other places as grace
. Would be good to use either of. What do you think?
export enum AdditionalHealthCheckType { | ||
/** | ||
* ELB Health Check | ||
*/ | ||
ELB = 'ELB', | ||
/** | ||
* EBS Health Check | ||
*/ | ||
EBS = 'EBS', | ||
/** | ||
* VPC LATTICE Health Check | ||
*/ | ||
VPC_LATTICE = 'VPC_LATTICE', | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for claryfing. While creating a separate enum for additional health check types is a valid strategy and makes sense, I believe we can achieve the same functionality and enforce the validation in the existing enum withim the HealthChecks constructor. However I'm ok creating a new enum without EC2, but it would be good if we can rename this enum for better clarity and maintainablity. Let me know if it makes sense.
public static ec2(options: Ec2HealthChecksOptions = {}): HealthChecks { | ||
return new HealthChecks(['EC2'], options.grace); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding, since ec2 is a default type which is implictly enabled, I assume this method is for configuring the default EC2 healthcheck like gracePeriod?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but does it mean that the method name or the arg name should be changed to gracePeriod
?
For the former, I use the method name ec2
for the exclusive choice of whether it is EC2 or an additional type as a union-like class (partly because that was the way it was in the old class).
About the latter, the reason why the argument is the options instead of a stand-alone gracePeriod prop is because I thought about the possibility of adding new properties in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification. Yes it makes sense to pass the options as argument to have the possibilites of adding new properties in future.
I've returned some comments and I hope you'll take a look at them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @go-to-k for addressing the comments and for the contribution. LGTM.
export enum AdditionalHealthCheckType { | ||
/** | ||
* ELB Health Check | ||
*/ | ||
ELB = 'ELB', | ||
/** | ||
* EBS Health Check | ||
*/ | ||
EBS = 'EBS', | ||
/** | ||
* VPC LATTICE Health Check | ||
*/ | ||
VPC_LATTICE = 'VPC_LATTICE', | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered allowing the EC2 type to be specified, and then internally excluding the EC2 if it was specified, but I thought that users might be confused when they looked at the generated CFn template and realised that the EC2 was missing.
I thought it would be good to use the EC2 enum in the ec2 method below instead of specifiying it as string. But I agree and makes sense that it might confuse users of having EC2 in the enum when it can't be used.
public static ec2(options: Ec2HealthChecksOptions = {}): HealthChecks {
return new HealthChecks(['EC2'], options.gracePeriod);
}
Also, the method name has been changed to withAdditionalChecks(), but the name AdditionalHealthCheckType for the type name is still unnatural?
I think should be ok since with withAdditionalChecks
it is more clearer.
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Comments on closed issues and PRs are hard for our team to see. |
Issue # (if applicable)
Closes #31289 .
Reason for this change
Only ONE HealthCheckType can be selected for an existing healthCheck property: EC2 or ELB.
https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts#L233
https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts#L2232-L2258
However, the current CFn specification allows multiple health check types to be specified, separated by commas.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-autoscalinggroup.html#cfn-autoscaling-autoscalinggroup-healthchecktype
Also, besides EC2 and ELB, EBS and VPC_LATTICE can now be configured.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-autoscalinggroup.html#cfn-autoscaling-autoscalinggroup-healthchecktype
If it was just EC2 and ELB, there would not be a need for multiple specifications. (Because specifying EC2 and another type at the same time would result in a CFn error. This means that when specifying an ELB, it is a single specification.)
But the increase in the number of these property types makes multiple specifications necessary. Therefore, it is good to support the specification of multiple health check types and the addition of new types at the same time.
See the docs for more details.
https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-health-checks.html
Description of changes
So, I add a new
HealthChecks
class andhealthChecks
property.And I deprecated the existing
healthCheck
property.Description of how you validated changes
Unit and integ tests.
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license