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

feat(apprunner): add HealthCheckConfiguration property in Service #27029

Merged
merged 15 commits into from
Sep 27, 2023
22 changes: 22 additions & 0 deletions packages/@aws-cdk/aws-apprunner-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,25 @@ const service = new apprunner.Service(stack, 'Service', {

service.addSecret('LATER_SECRET', apprunner.Secret.fromSecretsManager(secret, 'field'));
```

## HealthCheck

To configure the health check for the service, use the `healthCheck` attribute.

You can specify it by static methods `HealthCheck.http` or `HealthCheck.tcp`.

```ts
new apprunner.Service(this, 'Service', {
source: apprunner.Source.fromEcrPublic({
imageConfiguration: { port: 8000 },
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
healthCheck: apprunner.HealthCheck.http({
healthyThreshold: 5,
interval: Duration.seconds(10),
path: '/',
timeout: Duration.seconds(10),
unhealthyThreshold: 10,
}),
});
```
151 changes: 151 additions & 0 deletions packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,15 @@ export interface ServiceProps {
* @default - no VPC connector, uses the DEFAULT egress type instead
*/
readonly vpcConnector?: IVpcConnector;

/**
* Settings for the health check that AWS App Runner performs to monitor the health of a service.
*
* You can specify it by static methods `HealthCheck.http` or `HealthCheck.tcp`.
*
* @default - no health check configuration
*/
readonly healthCheck?: HealthCheck;
}

/**
Expand Down Expand Up @@ -848,6 +857,145 @@ export class GitHubConnection {
}
}

/**
* The health check protocol type
*/
export enum HealthCheckProtocolType {
/**
* HTTP protocol
*/
HTTP = 'HTTP',

/**
* TCP protocol
*/
TCP = 'TCP',
}

/**
* Describes the settings for the health check that AWS App Runner performs to monitor the health of a service.
*/
interface HealthCheckCommonOptions {
/**
* The number of consecutive checks that must succeed before App Runner decides that the service is healthy.
*
* @default 1
*/
readonly healthyThreshold?: number;

/**
* The time interval, in seconds, between health checks.
*
* @default Duration.seconds(5)
*/
readonly interval?: cdk.Duration;

/**
* The time, in seconds, to wait for a health check response before deciding it failed.
*
* @default Duration.seconds(2)
*/
readonly timeout?: cdk.Duration;

/**
* The number of consecutive checks that must fail before App Runner decides that the service is unhealthy.
*
* @default 5
*/
readonly unhealthyThreshold?: number;
}

/**
* Properties used to define HTTP Based healthchecks.
*/
export interface HttpHealthCheckOptions extends HealthCheckCommonOptions {
/**
* The URL that health check requests are sent to.
*
* @default /
*/
readonly path?: string;
}

/**
* Properties used to define TCP Based healthchecks.
*/
export interface TcpHealthCheckOptions extends HealthCheckCommonOptions { }

/**
* Contains static factory methods for creating health checks for different protocols
*/
export class HealthCheck {
/**
* Construct a HTTP health check
*/
public static http(options: HttpHealthCheckOptions = {}): HealthCheck {
return new HealthCheck(
HealthCheckProtocolType.HTTP,
options.healthyThreshold,
options.interval,
options.timeout,
options.unhealthyThreshold,
options.path,
);
}

/**
* Construct a TCP health check
*/
public static tcp(options: TcpHealthCheckOptions = {}): HealthCheck {
return new HealthCheck(
HealthCheckProtocolType.TCP,
options.healthyThreshold,
options.interval,
options.timeout,
options.unhealthyThreshold,
);
}

private constructor(
public readonly healthCheckProtocolType: HealthCheckProtocolType,
public readonly healthyThreshold: number = 1,
public readonly interval: cdk.Duration = cdk.Duration.seconds(5),
public readonly timeout: cdk.Duration = cdk.Duration.seconds(2),
public readonly unhealthyThreshold: number = 5,
public readonly path?: string,
) {
if (this.healthCheckProtocolType === HealthCheckProtocolType.HTTP) {
if (this.path !== undefined && this.path.length === 0) {
throw new Error('path length must be greater than 0');
}
if (this.path === undefined) {
this.path = '/';
}
}

if (this.healthyThreshold < 1 || this.healthyThreshold > 20) {
throw new Error(`healthyThreshold must be between 1 and 20, got ${this.healthyThreshold}`);
}
if (this.unhealthyThreshold < 1 || this.unhealthyThreshold > 20) {
throw new Error(`unhealthyThreshold must be between 1 and 20, got ${this.unhealthyThreshold}`);
}
if (this.interval.toSeconds() < 1 || this.interval.toSeconds() > 20) {
throw new Error(`interval must be between 1 and 20 seconds, got ${this.interval.toSeconds()}`);
}
if (this.timeout.toSeconds() < 1 || this.timeout.toSeconds() > 20) {
throw new Error(`timeout must be between 1 and 20 seconds, got ${this.timeout.toSeconds()}`);
}
}

public bind(): CfnService.HealthCheckConfigurationProperty {
return {
healthyThreshold: this.healthyThreshold,
interval: this.interval?.toSeconds(),
path: this.path,
protocol: this.healthCheckProtocolType,
timeout: this.timeout?.toSeconds(),
unhealthyThreshold: this.unhealthyThreshold,
};
}
}

/**
* Attributes for the App Runner Service
*/
Expand Down Expand Up @@ -1097,6 +1245,9 @@ export class Service extends cdk.Resource implements iam.IGrantable {
vpcConnectorArn: this.props.vpcConnector?.vpcConnectorArn,
},
},
healthCheckConfiguration: this.props.healthCheck ?
this.props.healthCheck.bind() :
undefined,
});

// grant required privileges for the role
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Fixture with packages imported, but nothing else
import { Stack, SecretValue } from 'aws-cdk-lib';
import { Duration, Stack, SecretValue } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as apprunner from '@aws-cdk/aws-apprunner-alpha';
import * as path from 'path';
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"Resources": {
"ServiceInstanceRoleDFA90CEC": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"ServiceDBC79909": {
"Type": "AWS::AppRunner::Service",
"Properties": {
"HealthCheckConfiguration": {
"HealthyThreshold": 5,
"Interval": 10,
"Path": "/",
"Protocol": "HTTP",
"Timeout": 10,
"UnhealthyThreshold": 10
},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"ServiceInstanceRoleDFA90CEC",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
}
},
"SourceConfiguration": {
"AuthenticationConfiguration": {},
"ImageRepository": {
"ImageConfiguration": {
"Port": "8000"
},
"ImageIdentifier": "public.ecr.aws/aws-containers/hello-app-runner:latest",
"ImageRepositoryType": "ECR_PUBLIC"
}
}
}
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
"Default": "/cdk-bootstrap/hnb659fds/version",
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
}
},
"Rules": {
"CheckBootstrapVersion": {
"Assertions": [
{
"Assert": {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5"
],
{
"Ref": "BootstrapVersion"
}
]
}
]
},
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
}
]
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading