Skip to content

Commit

Permalink
chore: forward merge 'master' into 'v2-main' (#14601)
Browse files Browse the repository at this point in the history
* chore(cloudfront): remove the use of calculateFunctionHash (#14583)

`calculateFunctionHash()` was used to compute the 'refresh token' of the
custom resource for the EdgeFunction construct.

This method is private to the lambda module and is deemed to be changed.
Instead, use the lambda function version's logical id.

The logical id of the version includes computing the function hash (among
others) and is a more reliable determinant of whether the underlying
function version changed.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*

* feat(cloudwatch): validate parameters for a metric dimensions (closes #3116) (#14365)

As per #3116, the changes in this PR validate metric dimension values (length, and checking if the value is null or undefined) and throw errors if the values are not valid. I've also corrected a comment in the metric-types.ts to use the correct method name

* feat(appmesh): change HealthChecks to use protocol-specific union-like classes (#14432)

BREAKING CHANGE: HealthChecks require use of static factory methods

fixes #11640

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*

Co-authored-by: Niranjan Jayakar <nija@amazon.com>
Co-authored-by: OksanaH <34384274+OksanaH@users.noreply.github.com>
Co-authored-by: Dominic Fezzie <fezzid@amazon.com>
Co-authored-by: Elad Ben-Israel <benisrae@amazon.com>
  • Loading branch information
5 people authored May 11, 2021
1 parent 998fe72 commit b125113
Show file tree
Hide file tree
Showing 19 changed files with 363 additions and 286 deletions.
26 changes: 10 additions & 16 deletions packages/@aws-cdk/aws-appmesh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,13 @@ const node = mesh.addVirtualNode('virtual-node', {
}),
listeners: [appmesh.VirtualNodeListener.httpNodeListener({
port: 8081,
healthCheck: {
healthCheck: appmesh.HealthCheck.http({
healthyThreshold: 3,
interval: Duration.seconds(5), // minimum
path: `/health-check-path`,
port: 8080,
protocol: Protocol.HTTP,
timeout: Duration.seconds(2), // minimum
unhealthyThreshold: 2,
},
}),
})],
accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
});
Expand All @@ -173,15 +171,13 @@ const node = new VirtualNode(this, 'node', {
}),
listeners: [appmesh.VirtualNodeListener.httpNodeListener({
port: 8080,
healthCheck: {
healthCheck: appmesh.HealthCheck.http({
healthyThreshold: 3,
interval: Duration.seconds(5), // min
path: '/ping',
port: 8080,
protocol: Protocol.HTTP,
timeout: Duration.seconds(2), // min
unhealthyThreshold: 2,
},
}),
timeout: {
idle: cdk.Duration.seconds(5),
},
Expand All @@ -207,15 +203,13 @@ const node = new VirtualNode(this, 'node', {
}),
listeners: [appmesh.VirtualNodeListener.httpNodeListener({
port: 8080,
healthCheck: {
healthCheck: appmesh.HealthCheck.http({
healthyThreshold: 3,
interval: Duration.seconds(5), // min
path: '/ping',
port: 8080,
protocol: Protocol.HTTP,
timeout: Duration.seconds(2), // min
unhealthyThreshold: 2,
},
}),
timeout: {
idle: cdk.Duration.seconds(5),
},
Expand Down Expand Up @@ -494,9 +488,9 @@ const gateway = new appmesh.VirtualGateway(stack, 'gateway', {
mesh: mesh,
listeners: [appmesh.VirtualGatewayListener.http({
port: 443,
healthCheck: {
healthCheck: appmesh.HealthCheck.http({
interval: cdk.Duration.seconds(10),
},
}),
})],
backendDefaults: {
clientPolicy: appmesh.ClientPolicy.acmTrust({
Expand All @@ -517,9 +511,9 @@ const gateway = mesh.addVirtualGateway('gateway', {
virtualGatewayName: 'virtualGateway',
listeners: [appmesh.VirtualGatewayListener.http({
port: 443,
healthCheck: {
healthCheck: appmesh.HealthCheck.http({
interval: cdk.Duration.seconds(10),
},
}),
})],
});
```
Expand Down
189 changes: 189 additions & 0 deletions packages/@aws-cdk/aws-appmesh/lib/health-checks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import * as cdk from '@aws-cdk/core';
import { CfnVirtualGateway, CfnVirtualNode } from './appmesh.generated';
import { Protocol } from './shared-interfaces';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct } from 'constructs';

/**
* Properties used to define healthchecks.
*/
interface HealthCheckCommonOptions {
/**
* The number of consecutive successful health checks that must occur before declaring listener healthy.
*
* @default 2
*/
readonly healthyThreshold?: number;

/**
* The time period between each health check execution.
*
* @default Duration.seconds(5)
*/
readonly interval?: cdk.Duration;

/**
* The amount of time to wait when receiving a response from the health check.
*
* @default Duration.seconds(2)
*/
readonly timeout?: cdk.Duration;

/**
* The number of consecutive failed health checks that must occur before declaring a listener unhealthy.
*
* @default - 2
*/
readonly unhealthyThreshold?: number;
}

/**
* Properties used to define HTTP Based healthchecks.
*/
export interface HttpHealthCheckOptions extends HealthCheckCommonOptions {
/**
* The destination path for the health check request.
*
* @default /
*/
readonly path?: string;
}

/**
* Properties used to define GRPC Based healthchecks.
*/
export interface GrpcHealthCheckOptions extends HealthCheckCommonOptions { }

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

/**
* All Properties for Health Checks for mesh endpoints
*/
export interface HealthCheckConfig {
/**
* VirtualNode CFN configuration for Health Checks
*
* @default - no health checks
*/
readonly virtualNodeHealthCheck?: CfnVirtualNode.HealthCheckProperty;

/**
* VirtualGateway CFN configuration for Health Checks
*
* @default - no health checks
*/
readonly virtualGatewayHealthCheck?: CfnVirtualGateway.VirtualGatewayHealthCheckPolicyProperty;
}

/**
* Options used for creating the Health Check object
*/
export interface HealthCheckBindOptions {
/**
* Port for Health Check interface
*
* @default - no default port is provided
*/
readonly defaultPort?: number;
}


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

/**
* Construct a HTTP2 health check
*/
public static http2(options: HttpHealthCheckOptions = {}): HealthCheck {
return new HealthCheckImpl(Protocol.HTTP2, options.healthyThreshold, options.unhealthyThreshold, options.interval, options.timeout, options.path);
}

/**
* Construct a GRPC health check
*/
public static grpc(options: GrpcHealthCheckOptions = {}): HealthCheck {
return new HealthCheckImpl(Protocol.GRPC, options.healthyThreshold, options.unhealthyThreshold, options.interval, options.timeout);
}

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

/**
* Called when the AccessLog type is initialized. Can be used to enforce
* mutual exclusivity with future properties
*/
public abstract bind(scope: Construct, options: HealthCheckBindOptions): HealthCheckConfig;
}

class HealthCheckImpl extends HealthCheck {
constructor(
private readonly protocol: Protocol,
private readonly healthyThreshold: number = 2,
private readonly unhealthyThreshold: number = 2,
private readonly interval: cdk.Duration = cdk.Duration.seconds(5),
private readonly timeout: cdk.Duration = cdk.Duration.seconds(2),
private readonly path?: string) {
super();
if (healthyThreshold < 2 || healthyThreshold > 10) {
throw new Error('healthyThreshold must be between 2 and 10');
}

if (unhealthyThreshold < 2 || unhealthyThreshold > 10) {
throw new Error('unhealthyThreshold must be between 2 and 10');
}

if (interval.toMilliseconds() < 5000 || interval.toMilliseconds() > 300_000) {
throw new Error('interval must be between 5 seconds and 300 seconds');
}

if (timeout.toMilliseconds() < 2000 || timeout.toMilliseconds() > 60_000) {
throw new Error('timeout must be between 2 seconds and 60 seconds');
}

// Default to / for HTTP Health Checks
if (path === undefined && (protocol === Protocol.HTTP || protocol === Protocol.HTTP2)) {
this.path = '/';
}
}

public bind(_scope: Construct, options: HealthCheckBindOptions): HealthCheckConfig {
return {
virtualNodeHealthCheck: {
protocol: this.protocol,
healthyThreshold: this.healthyThreshold,
unhealthyThreshold: this.unhealthyThreshold,
intervalMillis: this.interval.toMilliseconds(),
timeoutMillis: this.timeout.toMilliseconds(),
path: this.path,
port: options.defaultPort,
},
virtualGatewayHealthCheck: {
protocol: this.protocol,
healthyThreshold: this.healthyThreshold,
unhealthyThreshold: this.unhealthyThreshold,
intervalMillis: this.interval.toMilliseconds(),
timeoutMillis: this.timeout.toMilliseconds(),
path: this.path,
port: options.defaultPort,
},
};
}

}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-appmesh/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './virtual-gateway-listener';
export * from './gateway-route';
export * from './gateway-route-spec';
export * from './client-policy';
export * from './health-checks';
42 changes: 0 additions & 42 deletions packages/@aws-cdk/aws-appmesh/lib/private/utils.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,3 @@
import * as cdk from '@aws-cdk/core';
import { CfnVirtualGateway, CfnVirtualNode } from '../appmesh.generated';

type AppMeshHealthCheck = CfnVirtualNode.HealthCheckProperty | CfnVirtualGateway.VirtualGatewayHealthCheckPolicyProperty

/**
* Validates health check properties, throws an error if they are misconfigured.
*
* @param healthCheck Healthcheck property from a Virtual Node or Virtual Gateway
*/
export function validateHealthChecks(healthCheck: AppMeshHealthCheck) {
(Object.keys(healthCheck) as Array<keyof AppMeshHealthCheck>)
.filter((key) =>
HEALTH_CHECK_PROPERTY_THRESHOLDS[key] &&
typeof healthCheck[key] === 'number' &&
!cdk.Token.isUnresolved(healthCheck[key]),
).map((key) => {
const [min, max] = HEALTH_CHECK_PROPERTY_THRESHOLDS[key]!;
const value = healthCheck[key]!;

if (value < min) {
throw new Error(`The value of '${key}' is below the minimum threshold (expected >=${min}, got ${value})`);
}
if (value > max) {
throw new Error(`The value of '${key}' is above the maximum threshold (expected <=${max}, got ${value})`);
}
});
}

/**
* Minimum and maximum thresholds for HeathCheck numeric properties
*
* @see https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HealthCheckPolicy.html
*/
const HEALTH_CHECK_PROPERTY_THRESHOLDS: {[key in (keyof AppMeshHealthCheck)]?: [number, number]} = {
healthyThreshold: [2, 10],
intervalMillis: [5000, 300000],
port: [1, 65535],
timeoutMillis: [2000, 60000],
unhealthyThreshold: [2, 10],
};

/**
* Generated Connection pool config
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-appmesh/lib/route-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnRoute } from './appmesh.generated';
import { Protocol, HttpTimeout, GrpcTimeout, TcpTimeout } from './shared-interfaces';
import { HttpTimeout, GrpcTimeout, Protocol, TcpTimeout } from './shared-interfaces';
import { IVirtualNode } from './virtual-node';

/**
Expand Down
Loading

0 comments on commit b125113

Please sign in to comment.