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(appmesh): add listener timeout to Virtual Nodes #10793

Merged
merged 27 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c0073e6
feat(aws-appmesh): adds listener timeout to Virtual Nodes
sshver Oct 5, 2020
97e1275
Update README.md to include listener timeout for Virtual Nodes
sshver Oct 8, 2020
03e012f
Added check to set timeout only for those protocol the listener uses
sshver Oct 13, 2020
3d3e09f
WIP - Adding VirtualNodeListener Class
sshver Oct 19, 2020
0046aa1
Added descriptive comments
sshver Oct 25, 2020
d4f136c
minor edits: added/updated comments and added/removed spaces where ev…
sshver Oct 26, 2020
c520b01
Fixed test after cherry-pick
sshver Oct 26, 2020
b348e42
Fixed code to make sure the build does not fail.
sshver Oct 26, 2020
2fe07eb
Fixed code to make sure the build does not fail.
sshver Oct 26, 2020
9d4f03b
Revert "Fixed code to make sure the build does not fail."
sshver Oct 27, 2020
b012bbb
addressed comments and removed dupilcations
sshver Oct 30, 2020
8c8c2ad
addressed comment
sshver Nov 2, 2020
8373e3c
Updated appmesh.ts to add listener based on protocol
sshver Nov 2, 2020
f220deb
Removing unused file from directory
sshver Nov 2, 2020
ae6ad41
Merge remote-tracking branch 'upstream/master' into feature/listenert…
sshver Nov 3, 2020
03b4c1f
- Updated test to remove unnecessary changes.
sshver Nov 5, 2020
6ff4b82
- Moved bind implementation to VirtualNodeListener.
sshver Nov 6, 2020
a167ae8
Removed addListeners and moved addListener and addBackends from IVirt…
sshver Nov 6, 2020
588b56b
Create addListener() and addBackend() method to accept a single liste…
sshver Nov 9, 2020
0d70cd7
Merge remote-tracking branch 'upstream/master' into feature/listenert…
sshver Nov 10, 2020
b67d48e
Removed unnecessary whitespaces
sshver Nov 10, 2020
a2138cd
Make the fields in VirtualNode private instead of protected
skinny85 Nov 10, 2020
caf3e7c
Merge branch 'master' into feature/listenertimeout
sshver Nov 10, 2020
be69829
Merge branch 'master' into feature/listenertimeout
skinny85 Nov 10, 2020
d35705f
Revert unnecessarily removed empty line in virtual-node.ts
skinny85 Nov 10, 2020
d8b049c
Merge branch 'master' into feature/listenertimeout
skinny85 Nov 11, 2020
cf15f6e
Merge branch 'master' into feature/listenertimeout
mergify[bot] Nov 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/@aws-cdk/aws-appmesh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,20 @@ const node = new VirtualNode(this, 'node', {
timeout: Duration.seconds(2), // min
unhealthyThreshold: 2,
},
timeout: {
skinny85 marked this conversation as resolved.
Show resolved Hide resolved
http: {
idle: Duration.seconds(5),
perRequest: Duration.seconds(5),
}
}
},
accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
});

cdk.Tag.add(node, 'Environment', 'Dev');
```

The listeners property can be left blank and added later with the `mesh.addListeners()` method. The `healthcheck` property is optional but if specifying a listener, the `portMappings` must contain at least one property.
The listeners property can be left blank and added later with the `mesh.addListeners()` method. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `portMappings` must contain at least one property.

## Adding a Route

Expand Down
89 changes: 89 additions & 0 deletions packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,88 @@ export interface PortMapping {
readonly protocol: Protocol;
}

/**
* Represents timeouts for different protocols.
*/
export interface HttpTimeout {
/**
* Represents an idle timeout. The amount of time that a connection may be idle.
*
* @default - none
*/
readonly idle?: cdk.Duration;

/**
* Represents per request timeout.
*
* @default - 15 s
*/
readonly perRequest?: cdk.Duration;
}

/**
* Represents timeouts for different protocols.
*/
export interface GrpcTimeout {
/**
* Represents an idle timeout. The amount of time that a connection may be idle.
*
* @default - none
*/
readonly idle?: cdk.Duration;

/**
* Represents per request timeout.
*
* @default - 15 s
*/

readonly perRequest?: cdk.Duration;
}

/**
* Represents timeouts for different protocols.
*/
export interface TcpTimeout {
/**
* Represents an idle timeout. The amount of time that a connection may be idle.
*
* @default - none
*/
readonly idle?: cdk.Duration;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe all these types are used only in the virtual-node-listener.ts file. Can you move them there please?

}

/**
* Represents timeouts for different protocols.
*/
export interface ListenerTimeout {
/**
* Represents GrpcTimeout type.
*
* @default - none
*/
readonly grpc?: GrpcTimeout;
/**
* Represents HttpTimeout type.
*
* @default - none
*/
readonly http?: HttpTimeout;
/**
* Represents HttpTimeout type.
*
* @default - none
*/
readonly http2?: HttpTimeout;
/**
* Represents TCPTimeout type.
*
* @default - none
*/
readonly tcp?: TcpTimeout;

}

/**
* Represents the properties needed to define healthy and active listeners for nodes.
*/
Expand All @@ -98,6 +180,13 @@ export interface VirtualNodeListener {
* @default - no healthcheck
*/
readonly healthCheck?: HealthCheck;

/**
* Represents timeouts for different protocols.
*
* @default - none
*/
readonly timeout?: ListenerTimeout;
}

skinny85 marked this conversation as resolved.
Show resolved Hide resolved
/**
Expand Down
98 changes: 97 additions & 1 deletion packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnVirtualNode } from './appmesh.generated';
import { IMesh } from './mesh';
import { AccessLog, HealthCheck, PortMapping, Protocol, VirtualNodeListener } from './shared-interfaces';
import { AccessLog, HealthCheck, ListenerTimeout, PortMapping, Protocol, VirtualNodeListener } from './shared-interfaces';
import { IVirtualService } from './virtual-service';

/**
Expand Down Expand Up @@ -149,11 +149,107 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode {
this.listeners.push({
portMapping,
healthCheck: renderHealthCheck(listener.healthCheck, portMapping),
timeout: renderListenerTimeout(listener.timeout),
});
}
}
}

/**
* Utility method to extract time unit and value.
*
* @param time
*/
function getTimeUnitAndValue(time: cdk.Duration) {
let timeUnit = time.toHumanString().split(' ')[1];
if (timeUnit === 'seconds' || 'second') {
let timeValue: number = time.toSeconds();
return { value: timeValue, unit: 's' };
} else {
let timeValue: number = time.toMilliseconds();
return { value: timeValue, unit: 'ms' };
}
}

/**
* Method to create ListenerTimeoutProperty object based on available timeout protocol
*
* @param timeout
*/
function renderListenerTimeout(timeout: ListenerTimeout | undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined {

if (timeout===undefined) {
return undefined;
}

let listenerTimeout:CfnVirtualNode.ListenerTimeoutProperty = {};

(Object.keys(timeout) as Array<keyof CfnVirtualNode.ListenerTimeoutProperty>)
.filter((key) => timeout[key]!==undefined).map((key) => {
if (key!=='tcp') {
let idle: unknown = timeout[key]?.idle;
let perRequest: unknown = timeout[key]?.perRequest;
if (idle===undefined && perRequest===undefined) {
listenerTimeout = {
[key]: {},
};
}
if (idle===undefined && perRequest!==undefined) {
listenerTimeout = {
[key]: {
perRequest: {
unit: getTimeUnitAndValue(perRequest as cdk.Duration).unit,
value: getTimeUnitAndValue(perRequest as cdk.Duration).value,
},
},
};
}
if (perRequest==undefined && idle!==undefined) {
listenerTimeout = {
[key]: {
idle: {
unit: getTimeUnitAndValue(idle as cdk.Duration).unit,
value: getTimeUnitAndValue(idle as cdk.Duration).value,
},
},
};
}
if (perRequest!==undefined && idle!==undefined) {
listenerTimeout = {
[key]: {
idle: {
unit: getTimeUnitAndValue(idle as cdk.Duration).unit,
value: getTimeUnitAndValue(idle as cdk.Duration).value,
},
perRequest: {
unit: getTimeUnitAndValue(perRequest as cdk.Duration).unit,
value: getTimeUnitAndValue(perRequest as cdk.Duration).value,
},
},
};
}
} else {
let idle: unknown = timeout[key]?.idle;
if (idle===undefined) {
listenerTimeout = {
[key]: {},
};
} else {
listenerTimeout = {
[key]: {
idle: {
unit: getTimeUnitAndValue(idle as cdk.Duration).unit,
value: getTimeUnitAndValue(idle as cdk.Duration).value,
},
},
};
}
}
});

return listenerTimeout;
}

/**
* Minimum and maximum thresholds for HeathCheck numeric properties
*
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-appmesh/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"resource-attribute:@aws-cdk/aws-appmesh.Route.routeUid",
"resource-attribute:@aws-cdk/aws-appmesh.Route.routeVirtualRouterName",
"resource-attribute:@aws-cdk/aws-appmesh.VirtualNode.virtualNodeMeshName",
"duration-prop-type:@aws-cdk/aws-appmesh.VirtualNodeListener.timeout",
"resource-attribute:@aws-cdk/aws-appmesh.VirtualNode.virtualNodeMeshOwner",
"resource-attribute:@aws-cdk/aws-appmesh.VirtualNode.virtualNodeResourceOwner",
"resource-attribute:@aws-cdk/aws-appmesh.VirtualNode.virtualNodeUid",
Expand Down
101 changes: 101 additions & 0 deletions packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,63 @@
}
}
},
"meshrouter2F830E97F": {
"Type": "AWS::AppMesh::VirtualRouter",
"Properties": {
"MeshName": {
"Fn::GetAtt": [
"meshACDFE68E",
"MeshName"
]
},
"Spec": {
"Listeners": [
{
"PortMapping": {
"Port": 8080,
"Protocol": "http"
}
}
]
},
"VirtualRouterName": "meshstackmeshrouter2BDE08990"
}
},
"meshrouter2route4030DB01D": {
"Type": "AWS::AppMesh::Route",
"Properties": {
"MeshName": {
"Fn::GetAtt": [
"meshACDFE68E",
"MeshName"
]
},
"RouteName": "route-4",
"Spec": {
"TcpRoute": {
"Action": {
"WeightedTargets": [
{
"VirtualNode": {
"Fn::GetAtt": [
"meshnode4AE87F692",
"VirtualNodeName"
]
},
"Weight": 100
}
]
}
}
},
"VirtualRouterName": {
"Fn::GetAtt": [
"meshrouter2F830E97F",
"VirtualRouterName"
]
}
}
},
"meshserviceE06ECED5": {
"Type": "AWS::AppMesh::VirtualService",
"Properties": {
Expand All @@ -623,6 +680,50 @@
"VirtualServiceName": "service1.domain.local"
}
},
"meshnode4AE87F692": {
"Type": "AWS::AppMesh::VirtualNode",
"Properties": {
"MeshName": {
"Fn::GetAtt": [
"meshACDFE68E",
"MeshName"
]
},
"Spec": {
"Listeners": [
{
"HealthCheck": {
"HealthyThreshold": 3,
"IntervalMillis": 5000,
"Path": "/check-path4",
"Port": 8080,
"Protocol": "http",
"TimeoutMillis": 2000,
"UnhealthyThreshold": 2
},
"PortMapping": {
"Port": 8080,
"Protocol": "http"
},
"Timeout": {
"HTTP": {
"Idle": {
"Unit": "s",
"Value": 10
}
}
}
}
],
"ServiceDiscovery": {
"DNS": {
"Hostname": "node4.domain.local"
}
}
},
"VirtualNodeName": "meshstackmeshnode404B014E7"
}
},
"meshnode726C787D": {
"Type": "AWS::AppMesh::VirtualNode",
"Properties": {
Expand Down
Loading