From c0073e694157042c4cf910d81a38d50ebaf21a8d Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 5 Oct 2020 16:26:29 -0700 Subject: [PATCH 01/21] feat(aws-appmesh): adds listener timeout to Virtual Nodes --- .../aws-appmesh/lib/shared-interfaces.ts | 89 +++++++++++++++ .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 98 ++++++++++++++++- packages/@aws-cdk/aws-appmesh/package.json | 1 + .../aws-appmesh/test/integ.mesh.expected.json | 101 ++++++++++++++++++ .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 33 ++++++ .../aws-appmesh/test/test.virtual-node.ts | 43 ++++++++ 6 files changed, 364 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts index 7cd55df23565d..b212787c6c8e2 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts @@ -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; +} + +/** + * 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. */ @@ -98,6 +180,13 @@ export interface VirtualNodeListener { * @default - no healthcheck */ readonly healthCheck?: HealthCheck; + + /** + * Represents timeouts for different protocols. + * + * @default - none + */ + readonly timeout?: ListenerTimeout; } /** diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 233ad2d0f216c..2e624b19c8f19 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -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'; /** @@ -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) + .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 * diff --git a/packages/@aws-cdk/aws-appmesh/package.json b/packages/@aws-cdk/aws-appmesh/package.json index 94a4d5d7fe0b5..4543a142b1f1d 100644 --- a/packages/@aws-cdk/aws-appmesh/package.json +++ b/packages/@aws-cdk/aws-appmesh/package.json @@ -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", diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json index 5b1b1657f0e20..0e294ff4f5c00 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json @@ -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": { @@ -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": { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index df55025f1365c..372cdad982099 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -116,3 +116,36 @@ router.addRoute('route-3', { }, ], }); + +const router2 = mesh.addVirtualRouter('router2', { + listener: { + portMapping: { + port: 8080, + protocol: appmesh.Protocol.HTTP, + }, + }, +}); + +const node4 = mesh.addVirtualNode('node4', { + dnsHostName: `node4.${namespace.namespaceName}`, + listener: { + healthCheck: { + healthyThreshold: 3, + path: '/check-path4', + }, + timeout: { + http: { + idle: cdk.Duration.seconds(10), + }, + }, + }, +}); + +router2.addRoute('route-4', { + routeTargets: [ + { + virtualNode: node4, + weight: 100, + }, + ], +}); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 82589e2c52ac5..6a8b78c90ecec 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -101,6 +101,49 @@ export = { test.done(); }, }, + 'when a listerner timeout is added': { + 'should add the listener timeout to the resource'(test: Test) { + //GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + const node = mesh.addVirtualNode('test-node', { + dnsHostName: 'test', + }); + + node.addListeners({ + timeout: { + http: { + idle: cdk.Duration.seconds(10), + }, + }, + }); + + // THEN + expect(stack).to( + haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + Timeout: { + HTTP: { + Idle: { + Unit: 's', + Value: 10, + }, + }, + }, + }, + ], + }, + })); + test.done(); + }, + }, }, 'Can export and import VirtualNode and perform actions'(test: Test) { // GIVEN From 97e1275af04db44655f75fc87a68975aaed158d5 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Thu, 8 Oct 2020 10:54:48 -0700 Subject: [PATCH 02/21] Update README.md to include listener timeout for Virtual Nodes --- packages/@aws-cdk/aws-appmesh/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 1becd4cf81772..c8633b1178985 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -186,6 +186,12 @@ const node = new VirtualNode(this, 'node', { timeout: Duration.seconds(2), // min unhealthyThreshold: 2, }, + timeout: { + http: { + idle: Duration.seconds(5), + perRequest: Duration.seconds(5), + } + } }, accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); @@ -193,7 +199,7 @@ const node = new VirtualNode(this, 'node', { 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 From 03e012f001c42ceaf78a6577a3bf54c604d54d5f Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 12 Oct 2020 18:48:25 -0700 Subject: [PATCH 03/21] Added check to set timeout only for those protocol the listener uses --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 84 ++------ .../aws-appmesh/test/integ.mesh.expected.json | 202 +++++++++--------- .../aws-appmesh/test/test.virtual-node.ts | 55 ++++- 3 files changed, 177 insertions(+), 164 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 2e624b19c8f19..9ceceea90e694 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -149,7 +149,7 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { this.listeners.push({ portMapping, healthCheck: renderHealthCheck(listener.healthCheck, portMapping), - timeout: renderListenerTimeout(listener.timeout), + timeout: renderListenerTimeout(listener.timeout, portMapping), }); } } @@ -176,77 +176,39 @@ function getTimeUnitAndValue(time: cdk.Duration) { * * @param timeout */ -function renderListenerTimeout(timeout: ListenerTimeout | undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { +function renderListenerTimeout(timeout: ListenerTimeout | undefined, pm: PortMapping): CfnVirtualNode.ListenerTimeoutProperty | undefined { if (timeout===undefined) { return undefined; } let listenerTimeout:CfnVirtualNode.ListenerTimeoutProperty = {}; + let obj:any = {}; (Object.keys(timeout) as Array) - .filter((key) => timeout[key]!==undefined).map((key) => { + .filter((key) => timeout[key]!==undefined && key===pm.protocol).map((key) => { + let idle: any = timeout[key]?.idle; + let perRequest: any = {}; 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, - }, - }, - }; - } + perRequest = timeout[key]?.perRequest; + } + obj = { + [key]: {}, + }; + if (typeof idle === 'object' && idle !== null && Object.keys(idle).length) { + obj[key].idle = { + unit: getTimeUnitAndValue(idle as cdk.Duration).unit, + value: getTimeUnitAndValue(idle as cdk.Duration).value, + }; + } + if (typeof perRequest === 'object' && perRequest !== null && Object.keys(perRequest).length) { + obj[key].perRequest = { + unit: getTimeUnitAndValue(perRequest as cdk.Duration).unit, + value: getTimeUnitAndValue(perRequest as cdk.Duration).value, + }; } }); - + listenerTimeout = obj; return listenerTimeout; } diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json index 0e294ff4f5c00..64acc8860dc89 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json @@ -599,63 +599,6 @@ } } }, - "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": { @@ -680,50 +623,6 @@ "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": { @@ -873,6 +772,107 @@ "VirtualNodeName": "meshstackmeshnode3C5835BCB" } }, + "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" + ] + } + } + }, + "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" + } + }, "service27C65CF7D": { "Type": "AWS::AppMesh::VirtualService", "Properties": { diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 6a8b78c90ecec..ace88b2c8fb70 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -102,7 +102,7 @@ export = { }, }, 'when a listerner timeout is added': { - 'should add the listener timeout to the resource'(test: Test) { + 'should add the listener timeout for default portmapping (i.e. no given portmapping is present) to the resource'(test: Test) { //GIVEN const stack = new cdk.Stack(); @@ -140,7 +140,58 @@ export = { }, ], }, - })); + }), + ); + test.done(); + }, + 'should add the listener timeout for given portmapping to the resource'(test: Test) { + //GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + const node = mesh.addVirtualNode('test-node', { + dnsHostName: 'test', + }); + + node.addListeners({ + portMapping: { + port: 9090, + protocol: appmesh.Protocol.GRPC, + }, + timeout: { + grpc: { + idle: cdk.Duration.seconds(10), + }, + }, + }); + + // THEN + expect(stack).to( + haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + PortMapping: { + Port: 9090, + Protocol: 'grpc', + }, + Timeout: { + GRPC: { + Idle: { + Unit: 's', + Value: 10, + }, + }, + }, + }, + ], + }, + }), + ); test.done(); }, }, From 3d3e09f651258343ae9ce5caf6e66ce548cece73 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 19 Oct 2020 11:31:30 -0700 Subject: [PATCH 04/21] WIP - Adding VirtualNodeListener Class --- .../aws-appmesh/lib/shared-interfaces.ts | 63 +- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 618 ++++++++++++++---- packages/@aws-cdk/aws-appmesh/package.json | 10 +- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 12 +- .../aws-appmesh/test/test.health-check.ts | 70 +- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 46 +- .../@aws-cdk/aws-appmesh/test/test.route.ts | 10 +- .../aws-appmesh/test/test.virtual-node.ts | 193 +++++- .../aws-appmesh/test/test.virtual-router.ts | 51 +- 9 files changed, 784 insertions(+), 289 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts index b212787c6c8e2..5ac593ccde367 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts @@ -82,7 +82,7 @@ export interface PortMapping { } /** - * Represents timeouts for different protocols. + * Represents timeouts for HTTP protocols. */ export interface HttpTimeout { /** @@ -101,9 +101,9 @@ export interface HttpTimeout { } /** - * Represents timeouts for different protocols. + * Represents timeouts for HTTP2 protocols. */ -export interface GrpcTimeout { +export interface Http2Timeout { /** * Represents an idle timeout. The amount of time that a connection may be idle. * @@ -116,77 +116,38 @@ export interface GrpcTimeout { * * @default - 15 s */ - readonly perRequest?: cdk.Duration; } /** - * Represents timeouts for different protocols. + * Represents timeouts for GRPC protocols. */ -export interface TcpTimeout { +export interface GrpcTimeout { /** * Represents an idle timeout. The amount of time that a connection may be idle. * * @default - none */ readonly idle?: cdk.Duration; -} -/** - * 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. + * Represents per request timeout. * - * @default - none + * @default - 15 s */ - readonly tcp?: TcpTimeout; - + readonly perRequest?: cdk.Duration; } /** - * Represents the properties needed to define healthy and active listeners for nodes. + * Represents timeouts for TCP protocols. */ -export interface VirtualNodeListener { - /** - * Array of PortMappingProps for the listener - * - * @default - HTTP port 8080 - */ - readonly portMapping?: PortMapping; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - +export interface TcpTimeout { /** - * Represents timeouts for different protocols. + * Represents an idle timeout. The amount of time that a connection may be idle. * * @default - none */ - readonly timeout?: ListenerTimeout; + readonly idle?: cdk.Duration; } /** diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 9ceceea90e694..a668e31b7b112 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -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, ListenerTimeout, PortMapping, Protocol, VirtualNodeListener } from './shared-interfaces'; +import { AccessLog, HealthCheck, PortMapping, Protocol, HttpTimeout, Http2Timeout, TcpTimeout, GrpcTimeout } from './shared-interfaces'; import { IVirtualService } from './virtual-service'; /** @@ -33,12 +33,493 @@ export interface IVirtualNode extends cdk.IResource { */ addBackends(...props: IVirtualService[]): void; + /** + * NodeListener + */ + addListener(listener: VirtualNodeListener): void; + /** * Utility method to add Node Listeners for new or existing VirtualNodes */ - addListeners(...listeners: VirtualNodeListener[]): void; + addListeners(listeners: VirtualNodeListener[]): void; +} + +/** + * Represents the properties needed to define HTTP Listeners for a VirtualGateway + */ +export interface NodeListenerProps { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port?: number + + /** + * The health check information for the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; +} + +/** + * NodeListener + */ +export interface HttpNodeListenerProps extends NodeListenerProps { + /** + * Timeout + * + * @default - None + */ + + readonly timeout?: HttpTimeout; +} +/** + * NodeListener + */ +export interface Http2NodeListenerProps extends NodeListenerProps { + /** + * Timeout + * + * @default - None + */ + + readonly timeout?: Http2Timeout; +} +/** + * NodeListener + */ +export interface GrpcNodeListenerProps extends NodeListenerProps { + /** + * Timeout + * + * @default - None + */ + + readonly timeout?: GrpcTimeout; } +/** + * NodeListener + */ +export interface TcpNodeListenerProps extends NodeListenerProps { + /** + * Timeout + * + * @default - None + */ + + readonly timeout?: TcpTimeout; +} +/** + * NodeListener + */ +export abstract class VirtualNodeListener { + + /** + * NodeListener + */ + public static getTimeUnitAndValue(time: cdk.Duration) { + let timeObj: any = {}; + let timeUnit = time.toHumanString().split(' ')[1]; + if (timeUnit === 'seconds' || 'second') { + let timeValue: number = time.toSeconds(); + timeObj.unit = 's'; + timeObj.value = timeValue; + } else { + let timeValue: number = time.toMilliseconds(); + timeObj.unit = 'ms'; + timeObj.value = timeValue; + } + return timeObj; + } + + /** + * NodeListener + */ + public static renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { + const HEALTH_CHECK_PROPERTY_THRESHOLDS: {[key in (keyof CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { + healthyThreshold: [2, 10], + intervalMillis: [5000, 300000], + port: [1, 65535], + timeoutMillis: [2000, 60000], + unhealthyThreshold: [2, 10], + }; + if (hc === undefined) { return undefined; } + + if (hc.protocol === Protocol.TCP && hc.path) { + throw new Error('The path property cannot be set with Protocol.TCP'); + } + + if (hc.protocol === Protocol.GRPC && hc.path) { + throw new Error('The path property cannot be set with Protocol.GRPC'); + } + + const healthCheck: CfnVirtualNode.HealthCheckProperty = { + healthyThreshold: hc.healthyThreshold || 2, + intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min + path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), + port: hc.port || pm.port, + protocol: hc.protocol || pm.protocol, + timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), + unhealthyThreshold: hc.unhealthyThreshold || 2, + }; + + (Object.keys(healthCheck) as Array) + .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})`); + } + }); + + return healthCheck; + } + + /** + * NodeListener + */ + public static httpNodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { + return new HttpNodeListener(props); + } + + /** + * NodeListener + */ + public static http2NodeListener(props?: Http2NodeListenerProps): VirtualNodeListener { + return new Http2NodeListener(props); + } + + /** + * NodeListener + */ + public static grpcNodeListener(props?: GrpcNodeListenerProps): VirtualNodeListener { + return new GrpcNodeListener(props); + } + + /** + * NodeListener + */ + public static tcpNodeListener(props?: TcpNodeListenerProps): VirtualNodeListener { + return new TcpNodeListener(props); + } + + /** + * NodeListener + */ + public abstract bind(scope: cdk.Construct): CfnVirtualNode.ListenerProperty; +} + +/** + * NodeListener + */ +export class HttpNodeListener extends VirtualNodeListener { + /** + * NodeListener + */ + public static renderTimeout(tm: HttpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { + if (tm===undefined) { + return tm; + } + let httpTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; + let httpTypeObj: any = { + http: {}, + }; + let obj: any = {}; + if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { + obj.idle = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, + }; + } + if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { + obj.perRequest = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, + }; + } + httpTypeObj.http = obj; + httpTimeout = httpTypeObj; + return httpTimeout; + } + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + /** + * Timeout + * + * @default - none + */ + readonly timeout?: HttpTimeout; + constructor(props?: HttpNodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * NodeListener + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.HTTP, + }, + healthCheck: HttpNodeListener.renderHealthCheck({ + port: this.port, + protocol: Protocol.HTTP, + }, this.healthCheck), + timeout: HttpNodeListener.renderTimeout(this.timeout), + }; + } +} + +/** + * NodeListener + */ +export class Http2NodeListener extends VirtualNodeListener { + /** + * NodeListener + */ + public static renderTimeout(tm: Http2Timeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { + if (tm===undefined) { + return tm; + } + let http2Timeout: CfnVirtualNode.ListenerTimeoutProperty = {}; + let http2TypeObj: any = { + http2: {}, + }; + let obj: any = {}; + if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { + obj.idle = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, + }; + } + if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { + obj.perRequest = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, + }; + } + http2TypeObj.http2 = obj; + http2Timeout = http2TypeObj; + return http2Timeout; + } + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + /** + * Timeout + * + * @default - none + */ + readonly timeout?: Http2Timeout; + constructor(props?: Http2NodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * NodeListener + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.HTTP2, + }, + healthCheck: Http2NodeListener.renderHealthCheck({ + port: this.port, + protocol: Protocol.HTTP2, + }, this.healthCheck), + timeout: Http2NodeListener.renderTimeout(this.timeout), + }; + } +} + +/** + * NodeListener + */ +export class GrpcNodeListener extends VirtualNodeListener { + /** + * NodeListener + */ + public static renderTimeout(tm: GrpcTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { + if (tm===undefined) { + return tm; + } + let grpcTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; + let grpcTypeObj: any = { + grpc: {}, + }; + let obj: any = {}; + if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { + obj.idle = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, + }; + } + if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { + obj.perRequest = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, + }; + } + grpcTypeObj.grpc = obj; + grpcTimeout = grpcTypeObj; + return grpcTimeout; + } + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + /** + * Timeout + * + * @default - none + */ + readonly timeout?: GrpcTimeout; + constructor(props?: GrpcNodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * NodeListener + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.GRPC, + }, + healthCheck: GrpcNodeListener.renderHealthCheck({ + port: this.port, + protocol: Protocol.GRPC, + }, this.healthCheck), + timeout: GrpcNodeListener.renderTimeout(this.timeout), + }; + } +} +/** + * NodeListener + */ +export class TcpNodeListener extends VirtualNodeListener { + /** + * NodeListener + */ + public static renderTimeout(tm: TcpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { + if (tm===undefined) { + return tm; + } + let tcpTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; + let tcpTypeObj: any = { + tcp: {}, + }; + let obj: any = {}; + if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { + obj.idle = { + unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, + value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, + }; + } + tcpTypeObj.tcp = obj; + tcpTimeout = tcpTypeObj; + return tcpTimeout; + } + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + /** + * Timeout + * + * @default - none + */ + readonly timeout?: TcpTimeout; + constructor(props?: TcpNodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * NodeListener + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.TCP, + }, + healthCheck: TcpNodeListener.renderHealthCheck({ + port: this.port, + protocol: Protocol.TCP, + }, this.healthCheck), + timeout: TcpNodeListener.renderTimeout(this.timeout), + }; + } +} /** * Basic configuration properties for a VirtualNode */ @@ -89,7 +570,7 @@ export interface VirtualNodeBaseProps { * * @default - No listeners */ - readonly listener?: VirtualNodeListener; + readonly listeners?: VirtualNodeListener[]; /** * Access Logging Configuration for the virtual node @@ -139,131 +620,24 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { /** * Utility method to add an inbound listener for this virtual node */ - public addListeners(...listeners: VirtualNodeListener[]) { - if (this.listeners.length + listeners.length > 1) { + public addListeners(listeners: VirtualNodeListener[]) { + if (listeners.length + this.listeners.length > 1) { throw new Error('VirtualNode may have at most one listener'); } - for (const listener of listeners) { - const portMapping = listener.portMapping || { port: 8080, protocol: Protocol.HTTP }; - this.listeners.push({ - portMapping, - healthCheck: renderHealthCheck(listener.healthCheck, portMapping), - timeout: renderListenerTimeout(listener.timeout, portMapping), - }); + this.addListener(listener); } } -} -/** - * 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, pm: PortMapping): CfnVirtualNode.ListenerTimeoutProperty | undefined { - - if (timeout===undefined) { - return undefined; - } - - let listenerTimeout:CfnVirtualNode.ListenerTimeoutProperty = {}; - let obj:any = {}; - - (Object.keys(timeout) as Array) - .filter((key) => timeout[key]!==undefined && key===pm.protocol).map((key) => { - let idle: any = timeout[key]?.idle; - let perRequest: any = {}; - if (key!=='tcp') { - perRequest = timeout[key]?.perRequest; - } - obj = { - [key]: {}, - }; - if (typeof idle === 'object' && idle !== null && Object.keys(idle).length) { - obj[key].idle = { - unit: getTimeUnitAndValue(idle as cdk.Duration).unit, - value: getTimeUnitAndValue(idle as cdk.Duration).value, - }; - } - if (typeof perRequest === 'object' && perRequest !== null && Object.keys(perRequest).length) { - obj[key].perRequest = { - unit: getTimeUnitAndValue(perRequest as cdk.Duration).unit, - value: getTimeUnitAndValue(perRequest as cdk.Duration).value, - }; - } - }); - listenerTimeout = obj; - return listenerTimeout; -} - -/** - * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { - healthyThreshold: [2, 10], - intervalMillis: [5000, 300000], - port: [1, 65535], - timeoutMillis: [2000, 60000], - unhealthyThreshold: [2, 10], -}; - -function renderHealthCheck(hc: HealthCheck | undefined, pm: PortMapping): CfnVirtualNode.HealthCheckProperty | undefined { - if (hc === undefined) { return undefined; } - - if (hc.protocol === Protocol.TCP && hc.path) { - throw new Error('The path property cannot be set with Protocol.TCP'); - } - - if (hc.protocol === Protocol.GRPC && hc.path) { - throw new Error('The path property cannot be set with Protocol.GRPC'); + /** + * Utility method to add a single listener to this VirtualGateway + */ + public addListener(listener: VirtualNodeListener) { + if (this.listeners.length > 0) { + throw new Error('VirtualNode may have at most one listener'); + } + this.listeners.push(listener.bind(this)); } - - const healthCheck: CfnVirtualNode.HealthCheckProperty = { - healthyThreshold: hc.healthyThreshold || 2, - intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min - path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), - port: hc.port || pm.port, - protocol: hc.protocol || pm.protocol, - timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), - unhealthyThreshold: hc.unhealthyThreshold || 2, - }; - - (Object.keys(healthCheck) as Array) - .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})`); - } - }); - - return healthCheck; } /** @@ -316,7 +690,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(...props.listener ? [props.listener] : []); + this.addListeners(props.listeners ? props.listeners : [VirtualNodeListener.httpNodeListener()]); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { diff --git a/packages/@aws-cdk/aws-appmesh/package.json b/packages/@aws-cdk/aws-appmesh/package.json index 4543a142b1f1d..a3418fd8d8c9e 100644 --- a/packages/@aws-cdk/aws-appmesh/package.json +++ b/packages/@aws-cdk/aws-appmesh/package.json @@ -145,7 +145,15 @@ "props-default-doc:@aws-cdk/aws-appmesh.VirtualRouterAttributes.virtualRouterName", "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.HTTP", "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.HTTP2", - "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.GRPC" + "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.GRPC", + "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListener.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListener.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListener.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListener.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListenerProps.timeout" ] }, "stability": "experimental", diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index 372cdad982099..baf7321dec3c7 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,12 +34,12 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listener: { + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, path: '/check-path', }, - }, + })], backends: [ virtualService, ], @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listener: { + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -73,7 +73,7 @@ const node2 = mesh.addVirtualNode('node2', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }, + })], backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listener: { + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -94,7 +94,7 @@ const node3 = mesh.addVirtualNode('node3', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }, + })], accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 6f33658598efa..98be0d53cae15 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -4,13 +4,10 @@ import { Test } from 'nodeunit'; import * as appmesh from '../lib'; let idCounter = 0; -const getNode = (stack: cdk.Stack) => { - const mesh = new appmesh.Mesh(stack, `mesh-${++idCounter}`, { +const getMesh = (stack: cdk.Stack) => { + return new appmesh.Mesh(stack, `mesh-${++idCounter}`, { meshName: 'test-mesh', }); - return mesh.addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - }); }; export = { @@ -21,8 +18,11 @@ export = { const [min, max] = [5000, 300000]; // WHEN - const toThrow = (millis: number) => getNode(stack).addListeners({ - healthCheck: { interval: cdk.Duration.millis(millis) }, + const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { interval: cdk.Duration.millis(millis) }, + })], }); // THEN @@ -40,8 +40,11 @@ export = { const [min, max] = [2000, 60000]; // WHEN - const toThrow = (millis: number) => getNode(stack).addListeners({ - healthCheck: { timeout: cdk.Duration.millis(millis) }, + const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { timeout: cdk.Duration.millis(millis) }, + })], }); // THEN @@ -59,8 +62,11 @@ export = { const [min, max] = [1, 65535]; // WHEN - const toThrow = (port: number) => getNode(stack).addListeners({ - healthCheck: { port }, + const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { port }, + })], }); // THEN @@ -79,8 +85,11 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (healthyThreshold: number) => getNode(stack).addListeners({ - healthCheck: { healthyThreshold }, + const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { healthyThreshold }, + })], }); // THEN @@ -98,8 +107,11 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (unhealthyThreshold: number) => getNode(stack).addListeners({ - healthCheck: { unhealthyThreshold }, + const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { unhealthyThreshold }, + })], }); // THEN @@ -115,11 +127,14 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners({ - healthCheck: { - protocol, - path: '/', - }, + const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { + protocol, + path: '/', + }, + })], }); // THEN @@ -134,11 +149,14 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners({ - healthCheck: { - protocol, - path: '/', - }, + const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + healthCheck: { + protocol, + path: '/', + }, + })], }); // THEN @@ -148,4 +166,4 @@ export = { test.done(); }, -}; +}; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index f8e6ebcbb716d..783a4ba8019e5 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -221,12 +221,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: { - portMapping: { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], }); mesh.addVirtualService('service2', { @@ -275,7 +272,15 @@ export = { 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], }, Spec: { - // Specifically: no Listeners and Backends + // One listener is added by default. + Listeners: [ + { + PortMapping: { + Port: 8080, + Protocol: 'http', + }, + }, + ], ServiceDiscovery: { DNS: { Hostname: 'test.domain.local', @@ -300,12 +305,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: { - portMapping: { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], }); // THEN @@ -342,11 +344,8 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: { - portMapping: { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, healthCheck: { healthyThreshold: 3, path: '/', @@ -354,7 +353,7 @@ export = { timeout: cdk.Duration.seconds(2), // min unhealthyThreshold: 2, }, - }, + })], }); // THEN @@ -401,12 +400,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: { - portMapping: { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index 706a29a3552fc..d1af511c85e6b 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,13 +24,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index ace88b2c8fb70..b69f619cd58bc 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -28,7 +28,6 @@ export = { const node = new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: {}, backends: [service1], }); @@ -38,6 +37,12 @@ export = { expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { Spec: { + Listeners: [{ + PortMapping: { + Port: 8080, + Protocol: 'http', + }, + }], Backends: [ { VirtualService: { @@ -62,7 +67,7 @@ export = { }, }, 'when a single portmapping is added': { - 'should add the portmapping to the resoource'(test: Test) { + 'should add the portmapping to the resource'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -71,15 +76,12 @@ export = { meshName: 'test-mesh', }); - const node = mesh.addVirtualNode('test-node', { + new appmesh.VirtualNode(stack, 'test-node', { + mesh, dnsHostName: 'test', - }); - - node.addListeners({ - portMapping: { + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - protocol: appmesh.Protocol.TCP, - }, + })], }); // THEN @@ -90,7 +92,170 @@ export = { { PortMapping: { Port: 8081, + Protocol: 'http', + }, + }, + ], + }, + }), + ); + + test.done(); + }, + }, + 'when a listener is added with timeout': { + 'should add the listener timeout to the resource'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + new appmesh.VirtualNode(stack, 'test-node', { + mesh, + dnsHostName: 'test', + listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ + port: 80, + timeout: { + idle: cdk.Duration.seconds(10), + perRequest: cdk.Duration.seconds(10), + }, + })], + }); + + // THEN + expect(stack).to( + haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + PortMapping: { + Port: 80, + Protocol: 'grpc', + }, + Timeout: { + GRPC: { + Idle: { + Unit: 's', + Value: 10, + }, + PerRequest: { + Unit: 's', + Value: 10, + }, + }, + }, + }, + ], + }, + }), + ); + + test.done(); + }, + }, + 'when a listener is added with healthcheck ': { + 'should add a default listener healthcheck to the resource'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + new appmesh.VirtualNode(stack, 'test-node', { + mesh, + dnsHostName: 'test', + listeners: [appmesh.VirtualNodeListener.http2NodeListener({ + port: 80, + healthCheck: {}, + timeout: { idle: cdk.Duration.seconds(10) }, + })], + }); + + // THEN + expect(stack).to( + haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + HealthCheck: { + HealthyThreshold: 2, + IntervalMillis: 5000, + Port: 80, + Protocol: 'http2', + TimeoutMillis: 2000, + UnhealthyThreshold: 2, + }, + PortMapping: { + Port: 80, + Protocol: 'http2', + }, + Timeout: { + HTTP2: { + Idle: { + Unit: 's', + Value: 10, + }, + }, + }, + }, + ], + }, + }), + ); + + test.done(); + }, + }, + 'when a listener is added with healthcheck with user defined props': { + 'should add a listener healthcheck to the resource'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + new appmesh.VirtualNode(stack, 'test-node', { + mesh, + dnsHostName: 'test', + listeners: [appmesh.VirtualNodeListener.tcpNodeListener({ + port: 80, + healthCheck: { timeout: cdk.Duration.seconds(3) }, + timeout: { idle: cdk.Duration.seconds(10) }, + })], + }); + + // THEN + expect(stack).to( + haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + HealthCheck: { + HealthyThreshold: 2, + IntervalMillis: 5000, + Port: 80, Protocol: 'tcp', + TimeoutMillis: 3000, + UnhealthyThreshold: 2, + }, + PortMapping: { + Port: 80, + Protocol: 'tcp', + }, + Timeout: { + TCP: { + Idle: { + Unit: 's', + Value: 10, + }, + }, }, }, ], @@ -207,19 +372,15 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: {}, }); const stack2 = new cdk.Stack(); const node2 = appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); - node2.addListeners({ - portMapping: { - port: 8081, - protocol: appmesh.Protocol.TCP, - }, - }); + node2.addListeners([appmesh.VirtualNodeListener.httpNodeListener({ + port: 8081, + })]); // THEN expect(stack).to( diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index 47b59e0e39962..dd8f2f1aad52a 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,13 +24,10 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + healthCheck: {}, + })], backends: [service1], }); @@ -97,39 +94,27 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service1, ], }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service2, ], }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service1, ], @@ -255,13 +240,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: { - portMapping: - { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, + })], backends: [ service1, ], From 0046aa12cc10004c7e97f1c4164aca6a72baa508 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Sat, 24 Oct 2020 21:48:51 -0700 Subject: [PATCH 05/21] Added descriptive comments --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 239 +++++++----------- .../aws-appmesh/test/test.virtual-node.ts | 16 +- 2 files changed, 97 insertions(+), 158 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index a668e31b7b112..26a1f7a649559 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -34,7 +34,7 @@ export interface IVirtualNode extends cdk.IResource { addBackends(...props: IVirtualService[]): void; /** - * NodeListener + * Utility method to add a single node listener */ addListener(listener: VirtualNodeListener): void; @@ -45,9 +45,9 @@ export interface IVirtualNode extends cdk.IResource { } /** - * Represents the properties needed to define HTTP Listeners for a VirtualGateway + * Represents the properties needed to define a Listeners for a VirtualNode */ -export interface NodeListenerProps { +export interface VirtualNodeListenerProps { /** * Port to listen for connections on * @@ -64,11 +64,11 @@ export interface NodeListenerProps { } /** - * NodeListener + * Represent the HTTP Node Listener prorperty */ -export interface HttpNodeListenerProps extends NodeListenerProps { +export interface HttpNodeListenerProps extends VirtualNodeListenerProps { /** - * Timeout + * Timeout for HTTP protocol * * @default - None */ @@ -76,11 +76,11 @@ export interface HttpNodeListenerProps extends NodeListenerProps { readonly timeout?: HttpTimeout; } /** - * NodeListener + * Represent the HTTP2 Node Listener prorperty */ -export interface Http2NodeListenerProps extends NodeListenerProps { +export interface Http2NodeListenerProps extends VirtualNodeListenerProps { /** - * Timeout + * Timeout for HTTP2 protocol * * @default - None */ @@ -88,11 +88,11 @@ export interface Http2NodeListenerProps extends NodeListenerProps { readonly timeout?: Http2Timeout; } /** - * NodeListener + * Represent the GRPC Node Listener prorperty */ -export interface GrpcNodeListenerProps extends NodeListenerProps { +export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { /** - * Timeout + * Timeout for GRPC protocol * * @default - None */ @@ -101,11 +101,11 @@ export interface GrpcNodeListenerProps extends NodeListenerProps { } /** - * NodeListener + * Represent the TCP Node Listener prorperty */ -export interface TcpNodeListenerProps extends NodeListenerProps { +export interface TcpNodeListenerProps extends VirtualNodeListenerProps { /** - * Timeout + * Timeout for TCP protocol * * @default - None */ @@ -113,30 +113,11 @@ export interface TcpNodeListenerProps extends NodeListenerProps { readonly timeout?: TcpTimeout; } /** - * NodeListener + * Defines listener for a VirtualNode */ export abstract class VirtualNodeListener { - - /** - * NodeListener - */ - public static getTimeUnitAndValue(time: cdk.Duration) { - let timeObj: any = {}; - let timeUnit = time.toHumanString().split(' ')[1]; - if (timeUnit === 'seconds' || 'second') { - let timeValue: number = time.toSeconds(); - timeObj.unit = 's'; - timeObj.value = timeValue; - } else { - let timeValue: number = time.toMilliseconds(); - timeObj.unit = 'ms'; - timeObj.value = timeValue; - } - return timeObj; - } - /** - * NodeListener + * Returns an HealthCheck for a VirtualNode */ public static renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { const HEALTH_CHECK_PROPERTY_THRESHOLDS: {[key in (keyof CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { @@ -187,70 +168,59 @@ export abstract class VirtualNodeListener { } /** - * NodeListener + * Returns an HTTP Listener for a VirtualNode */ public static httpNodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { return new HttpNodeListener(props); } /** - * NodeListener + * Returns an HTTP2 Listener for a VirtualNode */ public static http2NodeListener(props?: Http2NodeListenerProps): VirtualNodeListener { return new Http2NodeListener(props); } /** - * NodeListener + * Returns an GRPC Listener for a VirtualNode */ public static grpcNodeListener(props?: GrpcNodeListenerProps): VirtualNodeListener { return new GrpcNodeListener(props); } /** - * NodeListener + * Returns an TCP Listener for a VirtualNode */ public static tcpNodeListener(props?: TcpNodeListenerProps): VirtualNodeListener { return new TcpNodeListener(props); } /** - * NodeListener - */ + * Binds the current object when adding Listener to a VirtualNode + */ public abstract bind(scope: cdk.Construct): CfnVirtualNode.ListenerProperty; } /** - * NodeListener + * Represents the properties required to define a HTTP Listener for a VirtualNode. */ export class HttpNodeListener extends VirtualNodeListener { - /** - * NodeListener +/** + * Returns the ListenerTimeoutProperty for HTTP protocol */ public static renderTimeout(tm: HttpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - if (tm===undefined) { - return tm; - } - let httpTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; - let httpTypeObj: any = { - http: {}, - }; - let obj: any = {}; - if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { - obj.idle = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, - }; - } - if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { - obj.perRequest = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, - }; - } - httpTypeObj.http = obj; - httpTimeout = httpTypeObj; - return httpTimeout; + return ( tm!==undefined ? { + http: { + idle: tm?.idle !== undefined ? { + unit: 'ms', + value: tm?.idle.toMilliseconds(), + } : undefined, + perRequest: tm?.perRequest !== undefined ? { + unit: 'ms', + value: tm?.perRequest.toMilliseconds(), + } : undefined, + }, + }: undefined); } /** * Port to listen for connections on @@ -280,8 +250,8 @@ export class HttpNodeListener extends VirtualNodeListener { } /** - * NodeListener - */ + * Return Listener for HTTP protocol when Listener is added to Virtual Node. + */ public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { return { portMapping: { @@ -298,36 +268,25 @@ export class HttpNodeListener extends VirtualNodeListener { } /** - * NodeListener + * Represents the properties required to define a HTTP Listener for a VirtualNode. */ export class Http2NodeListener extends VirtualNodeListener { - /** - * NodeListener +/** + * Returns the ListenerTimeoutProperty for HTTP2 protocol */ public static renderTimeout(tm: Http2Timeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - if (tm===undefined) { - return tm; - } - let http2Timeout: CfnVirtualNode.ListenerTimeoutProperty = {}; - let http2TypeObj: any = { - http2: {}, - }; - let obj: any = {}; - if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { - obj.idle = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, - }; - } - if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { - obj.perRequest = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, - }; - } - http2TypeObj.http2 = obj; - http2Timeout = http2TypeObj; - return http2Timeout; + return ( tm!==undefined ? { + http2: { + idle: tm?.idle !== undefined ? { + unit: 'ms', + value: tm?.idle.toMilliseconds(), + } : undefined, + perRequest: tm?.perRequest !== undefined ? { + unit: 'ms', + value: tm?.perRequest.toMilliseconds(), + } : undefined, + }, + } : undefined); } /** * Port to listen for connections on @@ -357,8 +316,8 @@ export class Http2NodeListener extends VirtualNodeListener { } /** - * NodeListener - */ + * Return Listener for HTTP2 protocol when Listener is added to Virtual Node. + */ public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { return { portMapping: { @@ -375,36 +334,25 @@ export class Http2NodeListener extends VirtualNodeListener { } /** - * NodeListener + * Represents the properties required to define a HTTP Listener for a VirtualNode. */ export class GrpcNodeListener extends VirtualNodeListener { - /** - * NodeListener +/** + * Returns the ListenerTimeoutProperty for GRPC protocol */ public static renderTimeout(tm: GrpcTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - if (tm===undefined) { - return tm; - } - let grpcTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; - let grpcTypeObj: any = { - grpc: {}, - }; - let obj: any = {}; - if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { - obj.idle = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, - }; - } - if (typeof tm?.perRequest === 'object' && tm?.perRequest !== null && Object.keys(tm?.perRequest).length) { - obj.perRequest = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.perRequest as cdk.Duration).value, - }; - } - grpcTypeObj.grpc = obj; - grpcTimeout = grpcTypeObj; - return grpcTimeout; + return (tm!==undefined ? { + grpc: { + idle: tm?.idle !== undefined ? { + unit: 'ms', + value: tm?.idle.toMilliseconds(), + } : undefined, + perRequest: tm?.perRequest !== undefined ? { + unit: 'ms', + value: tm?.perRequest.toMilliseconds(), + } : undefined, + }, + } : undefined); } /** * Port to listen for connections on @@ -434,8 +382,8 @@ export class GrpcNodeListener extends VirtualNodeListener { } /** - * NodeListener - */ + * Return Listener for GRPC protocol when Listener is added to Virtual Node. + */ public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { return { portMapping: { @@ -451,30 +399,21 @@ export class GrpcNodeListener extends VirtualNodeListener { } } /** - * NodeListener + * Represents the properties required to define a HTTP Listener for a VirtualNode. */ export class TcpNodeListener extends VirtualNodeListener { - /** - * NodeListener +/** + * Returns the ListenerTimeoutProperty for TCP protocol */ public static renderTimeout(tm: TcpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - if (tm===undefined) { - return tm; - } - let tcpTimeout: CfnVirtualNode.ListenerTimeoutProperty = {}; - let tcpTypeObj: any = { - tcp: {}, - }; - let obj: any = {}; - if (typeof tm?.idle === 'object' && tm?.idle !== null && Object.keys(tm?.idle).length) { - obj.idle = { - unit: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).unit, - value: VirtualNodeListener.getTimeUnitAndValue(tm.idle as cdk.Duration).value, - }; - } - tcpTypeObj.tcp = obj; - tcpTimeout = tcpTypeObj; - return tcpTimeout; + return ( tm!=undefined ? { + tcp: { + idle: tm?.idle !== undefined ? { + unit: 'ms', + value: tm?.idle.toMilliseconds(), + } : undefined, + }, + } : undefined ); } /** * Port to listen for connections on @@ -504,8 +443,8 @@ export class TcpNodeListener extends VirtualNodeListener { } /** - * NodeListener - */ + * Return Listener for TCP protocol when Listener is added to Virtual Node. + */ public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { return { portMapping: { @@ -618,7 +557,7 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { } /** - * Utility method to add an inbound listener for this virtual node + * Utility method to add an inbound listener for this VirtualNode */ public addListeners(listeners: VirtualNodeListener[]) { if (listeners.length + this.listeners.length > 1) { @@ -630,7 +569,7 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { } /** - * Utility method to add a single listener to this VirtualGateway + * Utility method to add a single listener to this VirtualNode */ public addListener(listener: VirtualNodeListener) { if (this.listeners.length > 0) { diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index b69f619cd58bc..2af500c1a4d2a 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -138,12 +138,12 @@ export = { Timeout: { GRPC: { Idle: { - Unit: 's', - Value: 10, + Unit: 'ms', + Value: 10000, }, PerRequest: { - Unit: 's', - Value: 10, + Unit: 'ms', + Value: 10000, }, }, }, @@ -197,8 +197,8 @@ export = { Timeout: { HTTP2: { Idle: { - Unit: 's', - Value: 10, + Unit: 'ms', + Value: 10000, }, }, }, @@ -252,8 +252,8 @@ export = { Timeout: { TCP: { Idle: { - Unit: 's', - Value: 10, + Unit: 'ms', + Value: 10000, }, }, }, From d4f136c87387f268aeefb778bef8346f7e7d90d7 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 26 Oct 2020 14:18:12 -0700 Subject: [PATCH 06/21] minor edits: added/updated comments and added/removed spaces where ever necessary --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 73 ++++++++++++------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 26a1f7a649559..4d6a46b85eddf 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -72,9 +72,9 @@ export interface HttpNodeListenerProps extends VirtualNodeListenerProps { * * @default - None */ - readonly timeout?: HttpTimeout; } + /** * Represent the HTTP2 Node Listener prorperty */ @@ -84,9 +84,9 @@ export interface Http2NodeListenerProps extends VirtualNodeListenerProps { * * @default - None */ - readonly timeout?: Http2Timeout; } + /** * Represent the GRPC Node Listener prorperty */ @@ -96,7 +96,6 @@ export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { * * @default - None */ - readonly timeout?: GrpcTimeout; } @@ -109,9 +108,9 @@ export interface TcpNodeListenerProps extends VirtualNodeListenerProps { * * @default - None */ - readonly timeout?: TcpTimeout; } + /** * Defines listener for a VirtualNode */ @@ -120,6 +119,11 @@ export abstract class VirtualNodeListener { * Returns an HealthCheck for a VirtualNode */ public static renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { + /** + * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { healthyThreshold: [2, 10], intervalMillis: [5000, 300000], @@ -127,6 +131,7 @@ export abstract class VirtualNodeListener { timeoutMillis: [2000, 60000], unhealthyThreshold: [2, 10], }; + if (hc === undefined) { return undefined; } if (hc.protocol === Protocol.TCP && hc.path) { @@ -208,8 +213,8 @@ export class HttpNodeListener extends VirtualNodeListener { /** * Returns the ListenerTimeoutProperty for HTTP protocol */ - public static renderTimeout(tm: HttpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - return ( tm!==undefined ? { + public static renderTimeout(tm: HttpTimeout): CfnVirtualNode.ListenerTimeoutProperty { + return ({ http: { idle: tm?.idle !== undefined ? { unit: 'ms', @@ -220,8 +225,9 @@ export class HttpNodeListener extends VirtualNodeListener { value: tm?.perRequest.toMilliseconds(), } : undefined, }, - }: undefined); + }); } + /** * Port to listen for connections on * @@ -235,12 +241,14 @@ export class HttpNodeListener extends VirtualNodeListener { * @default - no healthcheck */ readonly healthCheck?: HealthCheck; + /** - * Timeout + * Listener timeout property for HTTP protocol * * @default - none */ readonly timeout?: HttpTimeout; + constructor(props?: HttpNodeListenerProps) { super(); const checkedProps = props ?? {}; @@ -262,20 +270,20 @@ export class HttpNodeListener extends VirtualNodeListener { port: this.port, protocol: Protocol.HTTP, }, this.healthCheck), - timeout: HttpNodeListener.renderTimeout(this.timeout), + timeout: this.timeout ? HttpNodeListener.renderTimeout(this.timeout) : undefined, }; } } /** - * Represents the properties required to define a HTTP Listener for a VirtualNode. + * Represents the properties required to define a HTTP2 Listener for a VirtualNode. */ export class Http2NodeListener extends VirtualNodeListener { /** * Returns the ListenerTimeoutProperty for HTTP2 protocol */ - public static renderTimeout(tm: Http2Timeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - return ( tm!==undefined ? { + public static renderTimeout(tm: Http2Timeout): CfnVirtualNode.ListenerTimeoutProperty { + return ({ http2: { idle: tm?.idle !== undefined ? { unit: 'ms', @@ -286,8 +294,9 @@ export class Http2NodeListener extends VirtualNodeListener { value: tm?.perRequest.toMilliseconds(), } : undefined, }, - } : undefined); + }); } + /** * Port to listen for connections on * @@ -301,12 +310,14 @@ export class Http2NodeListener extends VirtualNodeListener { * @default - no healthcheck */ readonly healthCheck?: HealthCheck; + /** - * Timeout + * Listener timeout property for HTTP2 protocol * * @default - none */ readonly timeout?: Http2Timeout; + constructor(props?: Http2NodeListenerProps) { super(); const checkedProps = props ?? {}; @@ -328,20 +339,20 @@ export class Http2NodeListener extends VirtualNodeListener { port: this.port, protocol: Protocol.HTTP2, }, this.healthCheck), - timeout: Http2NodeListener.renderTimeout(this.timeout), + timeout: this.timeout ? Http2NodeListener.renderTimeout(this.timeout) : undefined, }; } } /** - * Represents the properties required to define a HTTP Listener for a VirtualNode. + * Represents the properties required to define a GRPC Listener for a VirtualNode. */ export class GrpcNodeListener extends VirtualNodeListener { /** * Returns the ListenerTimeoutProperty for GRPC protocol */ - public static renderTimeout(tm: GrpcTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - return (tm!==undefined ? { + public static renderTimeout(tm: GrpcTimeout): CfnVirtualNode.ListenerTimeoutProperty { + return ({ grpc: { idle: tm?.idle !== undefined ? { unit: 'ms', @@ -352,8 +363,9 @@ export class GrpcNodeListener extends VirtualNodeListener { value: tm?.perRequest.toMilliseconds(), } : undefined, }, - } : undefined); + }); } + /** * Port to listen for connections on * @@ -367,12 +379,14 @@ export class GrpcNodeListener extends VirtualNodeListener { * @default - no healthcheck */ readonly healthCheck?: HealthCheck; + /** - * Timeout + * Listener timeout property for GRPC protocol * * @default - none */ readonly timeout?: GrpcTimeout; + constructor(props?: GrpcNodeListenerProps) { super(); const checkedProps = props ?? {}; @@ -394,27 +408,29 @@ export class GrpcNodeListener extends VirtualNodeListener { port: this.port, protocol: Protocol.GRPC, }, this.healthCheck), - timeout: GrpcNodeListener.renderTimeout(this.timeout), + timeout: this.timeout ? GrpcNodeListener.renderTimeout(this.timeout) : undefined, }; } } + /** - * Represents the properties required to define a HTTP Listener for a VirtualNode. + * Represents the properties required to define a TCP Listener for a VirtualNode. */ export class TcpNodeListener extends VirtualNodeListener { /** * Returns the ListenerTimeoutProperty for TCP protocol */ - public static renderTimeout(tm: TcpTimeout| undefined): CfnVirtualNode.ListenerTimeoutProperty | undefined { - return ( tm!=undefined ? { + public static renderTimeout(tm: TcpTimeout): CfnVirtualNode.ListenerTimeoutProperty | undefined { + return ({ tcp: { idle: tm?.idle !== undefined ? { unit: 'ms', value: tm?.idle.toMilliseconds(), } : undefined, }, - } : undefined ); + } ); } + /** * Port to listen for connections on * @@ -428,12 +444,14 @@ export class TcpNodeListener extends VirtualNodeListener { * @default - no healthcheck */ readonly healthCheck?: HealthCheck; + /** - * Timeout + * Listener timeout property for TCP protocol * * @default - none */ readonly timeout?: TcpTimeout; + constructor(props?: TcpNodeListenerProps) { super(); const checkedProps = props ?? {}; @@ -455,10 +473,11 @@ export class TcpNodeListener extends VirtualNodeListener { port: this.port, protocol: Protocol.TCP, }, this.healthCheck), - timeout: TcpNodeListener.renderTimeout(this.timeout), + timeout: this.timeout ? TcpNodeListener.renderTimeout(this.timeout) : undefined, }; } } + /** * Basic configuration properties for a VirtualNode */ From c520b012dd2b77f35f80760fa6b6a6a22d7393ef Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 26 Oct 2020 15:03:20 -0700 Subject: [PATCH 07/21] Fixed test after cherry-pick --- .../aws-appmesh/test/integ.mesh.expected.json | 101 ------------------ .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 33 ------ .../aws-appmesh/test/test.virtual-node.ts | 94 ---------------- 3 files changed, 228 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json index 64acc8860dc89..5b1b1657f0e20 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json @@ -772,107 +772,6 @@ "VirtualNodeName": "meshstackmeshnode3C5835BCB" } }, - "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" - ] - } - } - }, - "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" - } - }, "service27C65CF7D": { "Type": "AWS::AppMesh::VirtualService", "Properties": { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index baf7321dec3c7..f0a0fe96ec518 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -116,36 +116,3 @@ router.addRoute('route-3', { }, ], }); - -const router2 = mesh.addVirtualRouter('router2', { - listener: { - portMapping: { - port: 8080, - protocol: appmesh.Protocol.HTTP, - }, - }, -}); - -const node4 = mesh.addVirtualNode('node4', { - dnsHostName: `node4.${namespace.namespaceName}`, - listener: { - healthCheck: { - healthyThreshold: 3, - path: '/check-path4', - }, - timeout: { - http: { - idle: cdk.Duration.seconds(10), - }, - }, - }, -}); - -router2.addRoute('route-4', { - routeTargets: [ - { - virtualNode: node4, - weight: 100, - }, - ], -}); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 2af500c1a4d2a..dd9c6855cf8a9 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -266,100 +266,6 @@ export = { test.done(); }, }, - 'when a listerner timeout is added': { - 'should add the listener timeout for default portmapping (i.e. no given portmapping is present) to the resource'(test: Test) { - //GIVEN - const stack = new cdk.Stack(); - - // WHEN - const mesh = new appmesh.Mesh(stack, 'mesh', { - meshName: 'test-mesh', - }); - - const node = mesh.addVirtualNode('test-node', { - dnsHostName: 'test', - }); - - node.addListeners({ - timeout: { - http: { - idle: cdk.Duration.seconds(10), - }, - }, - }); - - // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - Timeout: { - HTTP: { - Idle: { - Unit: 's', - Value: 10, - }, - }, - }, - }, - ], - }, - }), - ); - test.done(); - }, - 'should add the listener timeout for given portmapping to the resource'(test: Test) { - //GIVEN - const stack = new cdk.Stack(); - - // WHEN - const mesh = new appmesh.Mesh(stack, 'mesh', { - meshName: 'test-mesh', - }); - - const node = mesh.addVirtualNode('test-node', { - dnsHostName: 'test', - }); - - node.addListeners({ - portMapping: { - port: 9090, - protocol: appmesh.Protocol.GRPC, - }, - timeout: { - grpc: { - idle: cdk.Duration.seconds(10), - }, - }, - }); - - // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - PortMapping: { - Port: 9090, - Protocol: 'grpc', - }, - Timeout: { - GRPC: { - Idle: { - Unit: 's', - Value: 10, - }, - }, - }, - }, - ], - }, - }), - ); - test.done(); - }, - }, }, 'Can export and import VirtualNode and perform actions'(test: Test) { // GIVEN From b348e4262986d4f51bccbd3909e0115ca7f6fbec Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 26 Oct 2020 15:55:02 -0700 Subject: [PATCH 08/21] Fixed code to make sure the build does not fail. Updated coressponding test. --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 4 +-- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 12 ++++---- .../aws-appmesh/test/test.health-check.ts | 28 +++++++++---------- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 16 +++++------ .../@aws-cdk/aws-appmesh/test/test.route.ts | 4 +-- .../aws-appmesh/test/test.virtual-node.ts | 16 +++++------ .../aws-appmesh/test/test.virtual-router.ts | 20 ++++++------- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 4d6a46b85eddf..622dc372f126b 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -528,7 +528,7 @@ export interface VirtualNodeBaseProps { * * @default - No listeners */ - readonly listeners?: VirtualNodeListener[]; + readonly listener?: VirtualNodeListener; /** * Access Logging Configuration for the virtual node @@ -648,7 +648,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(props.listeners ? props.listeners : [VirtualNodeListener.httpNodeListener()]); + this.addListeners(props.listener ? [props.listener] : [VirtualNodeListener.httpNodeListener()]); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index f0a0fe96ec518..2eabd7ddedddb 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,12 +34,12 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, path: '/check-path', }, - })], + }), backends: [ virtualService, ], @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -73,7 +73,7 @@ const node2 = mesh.addVirtualNode('node2', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - })], + }), backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -94,7 +94,7 @@ const node3 = mesh.addVirtualNode('node3', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - })], + }), accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 98be0d53cae15..76eb8132ea435 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -20,9 +20,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { interval: cdk.Duration.millis(millis) }, - })], + }), }); // THEN @@ -42,9 +42,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { timeout: cdk.Duration.millis(millis) }, - })], + }), }); // THEN @@ -64,9 +64,9 @@ export = { // WHEN const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { port }, - })], + }), }); // THEN @@ -87,9 +87,9 @@ export = { // WHEN const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold }, - })], + }), }); // THEN @@ -109,9 +109,9 @@ export = { // WHEN const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { unhealthyThreshold }, - })], + }), }); // THEN @@ -129,12 +129,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - })], + }), }); // THEN @@ -151,12 +151,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - })], + }), }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index 783a4ba8019e5..a87a1c2a2ef21 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -221,9 +221,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), }); mesh.addVirtualService('service2', { @@ -305,9 +305,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), }); // THEN @@ -344,7 +344,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -353,7 +353,7 @@ export = { timeout: cdk.Duration.seconds(2), // min unhealthyThreshold: 2, }, - })], + }), }); // THEN @@ -400,9 +400,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index d1af511c85e6b..261fc86200672 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,9 +24,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index dd9c6855cf8a9..ab8a307350536 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -79,9 +79,9 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - })], + }), }); // THEN @@ -116,13 +116,13 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ + listener: appmesh.VirtualNodeListener.grpcNodeListener({ port: 80, timeout: { idle: cdk.Duration.seconds(10), perRequest: cdk.Duration.seconds(10), }, - })], + }), }); // THEN @@ -169,11 +169,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.http2NodeListener({ + listener: appmesh.VirtualNodeListener.http2NodeListener({ port: 80, healthCheck: {}, timeout: { idle: cdk.Duration.seconds(10) }, - })], + }), }); // THEN @@ -224,11 +224,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.tcpNodeListener({ + listener: appmesh.VirtualNodeListener.tcpNodeListener({ port: 80, healthCheck: { timeout: cdk.Duration.seconds(3) }, timeout: { idle: cdk.Duration.seconds(10) }, - })], + }), }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index dd8f2f1aad52a..ad5530befdc81 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,10 +24,10 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: {}, - })], + }), backends: [service1], }); @@ -94,27 +94,27 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service2, ], }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], @@ -240,9 +240,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], From 2fe07eb387f6a91ea854562e051c88cc1398c560 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 26 Oct 2020 15:55:02 -0700 Subject: [PATCH 09/21] Fixed code to make sure the build does not fail. --- .../ecs-service-extensions/lib/extensions/appmesh.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index dcf3f7ac73e56..eac1946c7191c 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -264,12 +264,9 @@ export class AppMeshExtension extends ServiceExtension { mesh: this.mesh, virtualNodeName: this.parentService.id, cloudMapService: service.cloudMapService, - listener: { - portMapping: { - port: containerextension.trafficPort, - protocol: this.protocol, - }, - }, + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + port: containerextension.trafficPort, + })], }); // Create a virtual router for this service. This allows for retries From 9d4f03b6cfbbaae645fbcb917d617181bc8f8381 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Tue, 27 Oct 2020 00:10:32 -0700 Subject: [PATCH 10/21] Revert "Fixed code to make sure the build does not fail." This reverts commit b348e4262986d4f51bccbd3909e0115ca7f6fbec. --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 4 +-- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 12 ++++---- .../aws-appmesh/test/test.health-check.ts | 28 +++++++++---------- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 16 +++++------ .../@aws-cdk/aws-appmesh/test/test.route.ts | 4 +-- .../aws-appmesh/test/test.virtual-node.ts | 16 +++++------ .../aws-appmesh/test/test.virtual-router.ts | 20 ++++++------- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 622dc372f126b..4d6a46b85eddf 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -528,7 +528,7 @@ export interface VirtualNodeBaseProps { * * @default - No listeners */ - readonly listener?: VirtualNodeListener; + readonly listeners?: VirtualNodeListener[]; /** * Access Logging Configuration for the virtual node @@ -648,7 +648,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(props.listener ? [props.listener] : [VirtualNodeListener.httpNodeListener()]); + this.addListeners(props.listeners ? props.listeners : [VirtualNodeListener.httpNodeListener()]); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index 2eabd7ddedddb..f0a0fe96ec518 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,12 +34,12 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, path: '/check-path', }, - }), + })], backends: [ virtualService, ], @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -73,7 +73,7 @@ const node2 = mesh.addVirtualNode('node2', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }), + })], backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -94,7 +94,7 @@ const node3 = mesh.addVirtualNode('node3', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }), + })], accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 76eb8132ea435..98be0d53cae15 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -20,9 +20,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { interval: cdk.Duration.millis(millis) }, - }), + })], }); // THEN @@ -42,9 +42,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { timeout: cdk.Duration.millis(millis) }, - }), + })], }); // THEN @@ -64,9 +64,9 @@ export = { // WHEN const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { port }, - }), + })], }); // THEN @@ -87,9 +87,9 @@ export = { // WHEN const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold }, - }), + })], }); // THEN @@ -109,9 +109,9 @@ export = { // WHEN const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { unhealthyThreshold }, - }), + })], }); // THEN @@ -129,12 +129,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - }), + })], }); // THEN @@ -151,12 +151,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - }), + })], }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index a87a1c2a2ef21..783a4ba8019e5 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -221,9 +221,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], }); mesh.addVirtualService('service2', { @@ -305,9 +305,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], }); // THEN @@ -344,7 +344,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -353,7 +353,7 @@ export = { timeout: cdk.Duration.seconds(2), // min unhealthyThreshold: 2, }, - }), + })], }); // THEN @@ -400,9 +400,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index 261fc86200672..d1af511c85e6b 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,9 +24,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index ab8a307350536..dd9c6855cf8a9 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -79,9 +79,9 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - }), + })], }); // THEN @@ -116,13 +116,13 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.grpcNodeListener({ + listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ port: 80, timeout: { idle: cdk.Duration.seconds(10), perRequest: cdk.Duration.seconds(10), }, - }), + })], }); // THEN @@ -169,11 +169,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.http2NodeListener({ + listeners: [appmesh.VirtualNodeListener.http2NodeListener({ port: 80, healthCheck: {}, timeout: { idle: cdk.Duration.seconds(10) }, - }), + })], }); // THEN @@ -224,11 +224,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.tcpNodeListener({ + listeners: [appmesh.VirtualNodeListener.tcpNodeListener({ port: 80, healthCheck: { timeout: cdk.Duration.seconds(3) }, timeout: { idle: cdk.Duration.seconds(10) }, - }), + })], }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index ad5530befdc81..dd8f2f1aad52a 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,10 +24,10 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: {}, - }), + })], backends: [service1], }); @@ -94,27 +94,27 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service2, ], }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], @@ -240,9 +240,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], From b012bbbd38f1140bc5f0ea3d9aa867934262ab3d Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Fri, 30 Oct 2020 05:32:44 -0700 Subject: [PATCH 11/21] addressed comments and removed dupilcations --- .../lib/extensions/appmesh.ts | 4 +- packages/@aws-cdk/aws-appmesh/README.md | 35 +- packages/@aws-cdk/aws-appmesh/lib/index.ts | 1 + .../aws-appmesh/lib/shared-interfaces.ts | 19 - .../aws-appmesh/lib/virtual-listener.ts | 338 +++++++++++++ .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 445 +----------------- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 12 +- .../aws-appmesh/test/test.health-check.ts | 28 +- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 16 +- .../@aws-cdk/aws-appmesh/test/test.route.ts | 4 +- .../aws-appmesh/test/test.virtual-node.ts | 20 +- .../aws-appmesh/test/test.virtual-router.ts | 20 +- 12 files changed, 410 insertions(+), 532 deletions(-) create mode 100644 packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index eac1946c7191c..929d7e39dba1c 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -264,9 +264,9 @@ export class AppMeshExtension extends ServiceExtension { mesh: this.mesh, virtualNodeName: this.parentService.id, cloudMapService: service.cloudMapService, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: containerextension.trafficPort, - })], + }), }); // Create a virtual router for this service. This allows for retries diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index c8633b1178985..78e5046c67feb 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -146,11 +146,8 @@ const service = namespace.createService('Svc'); const node = mesh.addVirtualNode('virtual-node', { dnsHostName: 'node-a', cloudMapService: service, - listener: { - portMapping: { - port: 8081, - protocol: Protocol.HTTP, - }, + listener: appmesh.VirtualNodeListener.httpNodeListener({ + port: 8081, healthCheck: { healthyThreshold: 3, interval: Duration.seconds(5), // minimum @@ -160,9 +157,9 @@ const node = mesh.addVirtualNode('virtual-node', { timeout: Duration.seconds(2), // minimum unhealthyThreshold: 2, }, - }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), -}) + accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + }), +}); ``` Create a `VirtualNode` with the the constructor and add tags. @@ -172,11 +169,8 @@ const node = new VirtualNode(this, 'node', { mesh, dnsHostName: 'node-1', cloudMapService: service, - listener: { - portMapping: { - port: 8080, - protocol: Protocol.HTTP, - }, + listener: appmesh.VirtualNodeListener.httpNodeListener({ + port: 8080, healthCheck: { healthyThreshold: 3, interval: Duration.seconds(5), // min @@ -185,21 +179,18 @@ const node = new VirtualNode(this, 'node', { protocol: Protocol.HTTP, timeout: Duration.seconds(2), // min unhealthyThreshold: 2, - }, + }, timeout: { - http: { - idle: Duration.seconds(5), - perRequest: Duration.seconds(5), - } - } - }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + idle: cdk.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` and `timeout` properties are optional but if specifying a listener, the `portMappings` must contain at least one property. +A default httpListener is added when listener property is left blank. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `port` must be added. ## Adding a Route diff --git a/packages/@aws-cdk/aws-appmesh/lib/index.ts b/packages/@aws-cdk/aws-appmesh/lib/index.ts index ff36676e2ec1d..16aae7554ce70 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/index.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/index.ts @@ -6,3 +6,4 @@ export * from './shared-interfaces'; export * from './virtual-node'; export * from './virtual-router'; export * from './virtual-service'; +export * from './virtual-listener'; diff --git a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts index 5ac593ccde367..88cf1642d39c8 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts @@ -100,25 +100,6 @@ export interface HttpTimeout { readonly perRequest?: cdk.Duration; } -/** - * Represents timeouts for HTTP2 protocols. - */ -export interface Http2Timeout { - /** - * 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 GRPC protocols. */ diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts new file mode 100644 index 0000000000000..4bb0b3b63cc75 --- /dev/null +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts @@ -0,0 +1,338 @@ +import * as cdk from '@aws-cdk/core'; +import { CfnVirtualNode } from './appmesh.generated'; +import { HealthCheck, HttpTimeout, TcpTimeout, Protocol, GrpcTimeout, PortMapping } from './shared-interfaces'; + +/** + * Defines listener for a VirtualNode + */ +export abstract class VirtualNodeListener { + /** + * Returns an HTTP Listener for a VirtualNode + */ + public static httpNodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { + return new HttpNodeListener(props); + } + + /** + * Returns an HTTP2 Listener for a VirtualNode + */ + public static http2NodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { + return new HttpNodeListener(props, Protocol.HTTP2); + } + + /** + * Returns an GRPC Listener for a VirtualNode + */ + public static grpcNodeListener(props?: GrpcNodeListenerProps): VirtualNodeListener { + return new GrpcNodeListener(props); + } + + /** + * Returns an TCP Listener for a VirtualNode + */ + public static tcpNodeListener(props?: TcpNodeListenerProps): VirtualNodeListener { + return new TcpNodeListener(props); + } + + /** + * Binds the current object when adding Listener to a VirtualNode + */ + public abstract bind(scope: cdk.Construct): CfnVirtualNode.ListenerProperty; +} + +/** + * Represents the properties required to define a HTTP Listener for a VirtualNode. + */ +class HttpNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for HTTP protocol + * + * @default - none + */ + readonly timeout?: HttpTimeout; + + /** + * Listener timeout property for HTTP protocol + * + * @default - none + */ + readonly protocol?: Protocol; + + constructor(props?: HttpNodeListenerProps, protocol?: Protocol) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.protocol = protocol; + this.timeout = checkedProps.timeout; + } + + /** + * Return Listener for HTTP protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: this.protocol ? this.protocol : Protocol.HTTP, + }, + healthCheck: renderHealthCheck({ + port: this.port, + protocol: this.protocol ? this.protocol : Protocol.HTTP, + }, this.healthCheck), + timeout: this.timeout ? renderTimeout(this.timeout, this.protocol ? this.protocol : Protocol.HTTP) : undefined, + }; + } +} + +/** + * Represents the properties required to define a GRPC Listener for a VirtualNode. + */ +class GrpcNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for GRPC protocol + * + * @default - none + */ + readonly timeout?: GrpcTimeout; + + constructor(props?: GrpcNodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * Return Listener for GRPC protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.GRPC, + }, + healthCheck: renderHealthCheck({ + port: this.port, + protocol: Protocol.GRPC, + }, this.healthCheck), + timeout: this.timeout ? renderTimeout(this.timeout, Protocol.GRPC) : undefined, + }; + } +} + +/** + * Represents the properties required to define a TCP Listener for a VirtualNode. + */ +class TcpNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for TCP protocol + * + * @default - none + */ + readonly timeout?: TcpTimeout; + + constructor(props?: TcpNodeListenerProps) { + super(); + const checkedProps = props ?? {}; + this.port = checkedProps.port ? checkedProps.port : 8080; + this.healthCheck = checkedProps.healthCheck; + this.timeout = checkedProps.timeout; + } + + /** + * Return Listener for TCP protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { + return { + portMapping: { + port: this.port, + protocol: Protocol.TCP, + }, + healthCheck: renderHealthCheck({ + port: this.port, + protocol: Protocol.TCP, + }, this.healthCheck), + timeout: this.timeout ? renderTimeout(this.timeout, Protocol.TCP) : undefined, + }; + } +} + +/** + * Represents the properties needed to define a Listeners for a VirtualNode + */ +interface VirtualNodeListenerProps { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port?: number + + /** + * The health check information for the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; +} + +/** + * Represent the HTTP Node Listener prorperty + */ +export interface HttpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Protocol + * + * @default - HTTP + */ + readonly protocol?: Protocol; + /** + * Timeout for HTTP protocol + * + * @default - None + */ + readonly timeout?: HttpTimeout; +} + +/** + * Represent the GRPC Node Listener prorperty + */ +export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for GRPC protocol + * + * @default - None + */ + readonly timeout?: GrpcTimeout; +} + +/** + * Represent the TCP Node Listener prorperty + */ +export interface TcpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for TCP protocol + * + * @default - None + */ + readonly timeout?: TcpTimeout; +} + +/** + * Returns an HealthCheck for a VirtualNode + */ +function renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { + /** + * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { + healthyThreshold: [2, 10], + intervalMillis: [5000, 300000], + port: [1, 65535], + timeoutMillis: [2000, 60000], + unhealthyThreshold: [2, 10], + }; + + if (hc === undefined) { return undefined; } + + if (hc.protocol === Protocol.TCP && hc.path) { + throw new Error('The path property cannot be set with Protocol.TCP'); + } + + if (hc.protocol === Protocol.GRPC && hc.path) { + throw new Error('The path property cannot be set with Protocol.GRPC'); + } + + const healthCheck: CfnVirtualNode.HealthCheckProperty = { + healthyThreshold: hc.healthyThreshold || 2, + intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min + path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), + port: hc.port || pm.port, + protocol: hc.protocol || pm.protocol, + timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), + unhealthyThreshold: hc.unhealthyThreshold || 2, + }; + + (Object.keys(healthCheck) as Array) + .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})`); + } + }); + + return healthCheck; +} + +/** + * Returns the ListenerTimeoutProperty for HTTP protocol + */ +function renderTimeout(tm: any, pr: Protocol): CfnVirtualNode.ListenerTimeoutProperty { + return ({ + [pr]: { + idle: tm?.idle !== undefined ? { + unit: 'ms', + value: tm?.idle.toMilliseconds(), + } : undefined, + perRequest: tm?.perRequest !== undefined ? { + unit: 'ms', + value: tm?.perRequest.toMilliseconds(), + } : undefined, + }, + }); +} diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 4d6a46b85eddf..18823f5268edf 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -3,7 +3,8 @@ 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, HttpTimeout, Http2Timeout, TcpTimeout, GrpcTimeout } from './shared-interfaces'; +import { AccessLog } from './shared-interfaces'; +import { VirtualNodeListener } from './virtual-listener'; import { IVirtualService } from './virtual-service'; /** @@ -41,441 +42,7 @@ export interface IVirtualNode extends cdk.IResource { /** * Utility method to add Node Listeners for new or existing VirtualNodes */ - addListeners(listeners: VirtualNodeListener[]): void; -} - -/** - * Represents the properties needed to define a Listeners for a VirtualNode - */ -export interface VirtualNodeListenerProps { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port?: number - - /** - * The health check information for the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; -} - -/** - * Represent the HTTP Node Listener prorperty - */ -export interface HttpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for HTTP protocol - * - * @default - None - */ - readonly timeout?: HttpTimeout; -} - -/** - * Represent the HTTP2 Node Listener prorperty - */ -export interface Http2NodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for HTTP2 protocol - * - * @default - None - */ - readonly timeout?: Http2Timeout; -} - -/** - * Represent the GRPC Node Listener prorperty - */ -export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for GRPC protocol - * - * @default - None - */ - readonly timeout?: GrpcTimeout; -} - -/** - * Represent the TCP Node Listener prorperty - */ -export interface TcpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for TCP protocol - * - * @default - None - */ - readonly timeout?: TcpTimeout; -} - -/** - * Defines listener for a VirtualNode - */ -export abstract class VirtualNodeListener { - /** - * Returns an HealthCheck for a VirtualNode - */ - public static renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { - /** - * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { - healthyThreshold: [2, 10], - intervalMillis: [5000, 300000], - port: [1, 65535], - timeoutMillis: [2000, 60000], - unhealthyThreshold: [2, 10], - }; - - if (hc === undefined) { return undefined; } - - if (hc.protocol === Protocol.TCP && hc.path) { - throw new Error('The path property cannot be set with Protocol.TCP'); - } - - if (hc.protocol === Protocol.GRPC && hc.path) { - throw new Error('The path property cannot be set with Protocol.GRPC'); - } - - const healthCheck: CfnVirtualNode.HealthCheckProperty = { - healthyThreshold: hc.healthyThreshold || 2, - intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min - path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), - port: hc.port || pm.port, - protocol: hc.protocol || pm.protocol, - timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), - unhealthyThreshold: hc.unhealthyThreshold || 2, - }; - - (Object.keys(healthCheck) as Array) - .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})`); - } - }); - - return healthCheck; - } - - /** - * Returns an HTTP Listener for a VirtualNode - */ - public static httpNodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { - return new HttpNodeListener(props); - } - - /** - * Returns an HTTP2 Listener for a VirtualNode - */ - public static http2NodeListener(props?: Http2NodeListenerProps): VirtualNodeListener { - return new Http2NodeListener(props); - } - - /** - * Returns an GRPC Listener for a VirtualNode - */ - public static grpcNodeListener(props?: GrpcNodeListenerProps): VirtualNodeListener { - return new GrpcNodeListener(props); - } - - /** - * Returns an TCP Listener for a VirtualNode - */ - public static tcpNodeListener(props?: TcpNodeListenerProps): VirtualNodeListener { - return new TcpNodeListener(props); - } - - /** - * Binds the current object when adding Listener to a VirtualNode - */ - public abstract bind(scope: cdk.Construct): CfnVirtualNode.ListenerProperty; -} - -/** - * Represents the properties required to define a HTTP Listener for a VirtualNode. - */ -export class HttpNodeListener extends VirtualNodeListener { -/** - * Returns the ListenerTimeoutProperty for HTTP protocol - */ - public static renderTimeout(tm: HttpTimeout): CfnVirtualNode.ListenerTimeoutProperty { - return ({ - http: { - idle: tm?.idle !== undefined ? { - unit: 'ms', - value: tm?.idle.toMilliseconds(), - } : undefined, - perRequest: tm?.perRequest !== undefined ? { - unit: 'ms', - value: tm?.perRequest.toMilliseconds(), - } : undefined, - }, - }); - } - - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - readonly timeout?: HttpTimeout; - - constructor(props?: HttpNodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for HTTP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.HTTP, - }, - healthCheck: HttpNodeListener.renderHealthCheck({ - port: this.port, - protocol: Protocol.HTTP, - }, this.healthCheck), - timeout: this.timeout ? HttpNodeListener.renderTimeout(this.timeout) : undefined, - }; - } -} - -/** - * Represents the properties required to define a HTTP2 Listener for a VirtualNode. - */ -export class Http2NodeListener extends VirtualNodeListener { -/** - * Returns the ListenerTimeoutProperty for HTTP2 protocol - */ - public static renderTimeout(tm: Http2Timeout): CfnVirtualNode.ListenerTimeoutProperty { - return ({ - http2: { - idle: tm?.idle !== undefined ? { - unit: 'ms', - value: tm?.idle.toMilliseconds(), - } : undefined, - perRequest: tm?.perRequest !== undefined ? { - unit: 'ms', - value: tm?.perRequest.toMilliseconds(), - } : undefined, - }, - }); - } - - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for HTTP2 protocol - * - * @default - none - */ - readonly timeout?: Http2Timeout; - - constructor(props?: Http2NodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for HTTP2 protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.HTTP2, - }, - healthCheck: Http2NodeListener.renderHealthCheck({ - port: this.port, - protocol: Protocol.HTTP2, - }, this.healthCheck), - timeout: this.timeout ? Http2NodeListener.renderTimeout(this.timeout) : undefined, - }; - } -} - -/** - * Represents the properties required to define a GRPC Listener for a VirtualNode. - */ -export class GrpcNodeListener extends VirtualNodeListener { -/** - * Returns the ListenerTimeoutProperty for GRPC protocol - */ - public static renderTimeout(tm: GrpcTimeout): CfnVirtualNode.ListenerTimeoutProperty { - return ({ - grpc: { - idle: tm?.idle !== undefined ? { - unit: 'ms', - value: tm?.idle.toMilliseconds(), - } : undefined, - perRequest: tm?.perRequest !== undefined ? { - unit: 'ms', - value: tm?.perRequest.toMilliseconds(), - } : undefined, - }, - }); - } - - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for GRPC protocol - * - * @default - none - */ - readonly timeout?: GrpcTimeout; - - constructor(props?: GrpcNodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for GRPC protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.GRPC, - }, - healthCheck: GrpcNodeListener.renderHealthCheck({ - port: this.port, - protocol: Protocol.GRPC, - }, this.healthCheck), - timeout: this.timeout ? GrpcNodeListener.renderTimeout(this.timeout) : undefined, - }; - } -} - -/** - * Represents the properties required to define a TCP Listener for a VirtualNode. - */ -export class TcpNodeListener extends VirtualNodeListener { -/** - * Returns the ListenerTimeoutProperty for TCP protocol - */ - public static renderTimeout(tm: TcpTimeout): CfnVirtualNode.ListenerTimeoutProperty | undefined { - return ({ - tcp: { - idle: tm?.idle !== undefined ? { - unit: 'ms', - value: tm?.idle.toMilliseconds(), - } : undefined, - }, - } ); - } - - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for TCP protocol - * - * @default - none - */ - readonly timeout?: TcpTimeout; - - constructor(props?: TcpNodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for TCP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.TCP, - }, - healthCheck: TcpNodeListener.renderHealthCheck({ - port: this.port, - protocol: Protocol.TCP, - }, this.healthCheck), - timeout: this.timeout ? TcpNodeListener.renderTimeout(this.timeout) : undefined, - }; - } + addListeners(...listeners: VirtualNodeListener[]): void; } /** @@ -528,7 +95,7 @@ export interface VirtualNodeBaseProps { * * @default - No listeners */ - readonly listeners?: VirtualNodeListener[]; + readonly listener?: VirtualNodeListener; /** * Access Logging Configuration for the virtual node @@ -578,7 +145,7 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { /** * Utility method to add an inbound listener for this VirtualNode */ - public addListeners(listeners: VirtualNodeListener[]) { + public addListeners(...listeners: VirtualNodeListener[]) { if (listeners.length + this.listeners.length > 1) { throw new Error('VirtualNode may have at most one listener'); } @@ -648,7 +215,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(props.listeners ? props.listeners : [VirtualNodeListener.httpNodeListener()]); + this.addListeners(...props.listener ? [props.listener] : [VirtualNodeListener.httpNodeListener()]); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index f0a0fe96ec518..2eabd7ddedddb 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,12 +34,12 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, path: '/check-path', }, - })], + }), backends: [ virtualService, ], @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -73,7 +73,7 @@ const node2 = mesh.addVirtualNode('node2', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - })], + }), backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -94,7 +94,7 @@ const node3 = mesh.addVirtualNode('node3', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - })], + }), accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 98be0d53cae15..76eb8132ea435 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -20,9 +20,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { interval: cdk.Duration.millis(millis) }, - })], + }), }); // THEN @@ -42,9 +42,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { timeout: cdk.Duration.millis(millis) }, - })], + }), }); // THEN @@ -64,9 +64,9 @@ export = { // WHEN const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { port }, - })], + }), }); // THEN @@ -87,9 +87,9 @@ export = { // WHEN const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold }, - })], + }), }); // THEN @@ -109,9 +109,9 @@ export = { // WHEN const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { unhealthyThreshold }, - })], + }), }); // THEN @@ -129,12 +129,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - })], + }), }); // THEN @@ -151,12 +151,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - })], + }), }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index 783a4ba8019e5..a87a1c2a2ef21 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -221,9 +221,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), }); mesh.addVirtualService('service2', { @@ -305,9 +305,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), }); // THEN @@ -344,7 +344,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -353,7 +353,7 @@ export = { timeout: cdk.Duration.seconds(2), // min unhealthyThreshold: 2, }, - })], + }), }); // THEN @@ -400,9 +400,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index d1af511c85e6b..261fc86200672 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,9 +24,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index dd9c6855cf8a9..82c19e5b3198c 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -79,9 +79,9 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - })], + }), }); // THEN @@ -116,13 +116,13 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ + listener: appmesh.VirtualNodeListener.grpcNodeListener({ port: 80, timeout: { idle: cdk.Duration.seconds(10), perRequest: cdk.Duration.seconds(10), }, - })], + }), }); // THEN @@ -169,11 +169,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.http2NodeListener({ + listener: appmesh.VirtualNodeListener.http2NodeListener({ port: 80, healthCheck: {}, timeout: { idle: cdk.Duration.seconds(10) }, - })], + }), }); // THEN @@ -224,11 +224,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.tcpNodeListener({ + listener: appmesh.VirtualNodeListener.tcpNodeListener({ port: 80, healthCheck: { timeout: cdk.Duration.seconds(3) }, timeout: { idle: cdk.Duration.seconds(10) }, - })], + }), }); // THEN @@ -284,9 +284,9 @@ export = { const node2 = appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); - node2.addListeners([appmesh.VirtualNodeListener.httpNodeListener({ + node2.addListeners(appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - })]); + })); // THEN expect(stack).to( diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index dd8f2f1aad52a..ad5530befdc81 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,10 +24,10 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: {}, - })], + }), backends: [service1], }); @@ -94,27 +94,27 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service2, ], }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], @@ -240,9 +240,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listener: appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - })], + }), backends: [ service1, ], From 8c8c2adf48495c2575638196fa1f2dbf9f93fe86 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 2 Nov 2020 13:06:02 -0800 Subject: [PATCH 12/21] addressed comment --- packages/@aws-cdk/aws-appmesh/README.md | 14 +- packages/@aws-cdk/aws-appmesh/lib/index.ts | 2 +- .../aws-appmesh/lib/virtual-listener.ts | 338 ---------------- .../aws-appmesh/lib/virtual-node-listener.ts | 375 ++++++++++++++++++ .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 36 +- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 12 +- .../aws-appmesh/test/test.health-check.ts | 28 +- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 25 +- .../@aws-cdk/aws-appmesh/test/test.route.ts | 4 +- .../aws-appmesh/test/test.virtual-node.ts | 45 +-- .../aws-appmesh/test/test.virtual-router.ts | 20 +- 11 files changed, 445 insertions(+), 454 deletions(-) delete mode 100644 packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts create mode 100644 packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 78e5046c67feb..8bb82054497d8 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -146,7 +146,7 @@ const service = namespace.createService('Svc'); const node = mesh.addVirtualNode('virtual-node', { dnsHostName: 'node-a', cloudMapService: service, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, healthCheck: { healthyThreshold: 3, @@ -157,8 +157,8 @@ const node = mesh.addVirtualNode('virtual-node', { timeout: Duration.seconds(2), // minimum unhealthyThreshold: 2, }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), - }), + })], + accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); ``` @@ -169,7 +169,7 @@ const node = new VirtualNode(this, 'node', { mesh, dnsHostName: 'node-1', cloudMapService: service, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -183,14 +183,14 @@ const node = new VirtualNode(this, 'node', { timeout: { idle: cdk.Duration.seconds(5), }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), - }), + })], + accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); cdk.Tag.add(node, 'Environment', 'Dev'); ``` -A default httpListener is added when listener property is left blank. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `port` must be added. +The listeners property can be left blank and added later with the `node.addListeners()` method. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `port` must be added. ## Adding a Route diff --git a/packages/@aws-cdk/aws-appmesh/lib/index.ts b/packages/@aws-cdk/aws-appmesh/lib/index.ts index 16aae7554ce70..052752592b19e 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/index.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/index.ts @@ -6,4 +6,4 @@ export * from './shared-interfaces'; export * from './virtual-node'; export * from './virtual-router'; export * from './virtual-service'; -export * from './virtual-listener'; +export * from './virtual-node-listener'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts deleted file mode 100644 index 4bb0b3b63cc75..0000000000000 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-listener.ts +++ /dev/null @@ -1,338 +0,0 @@ -import * as cdk from '@aws-cdk/core'; -import { CfnVirtualNode } from './appmesh.generated'; -import { HealthCheck, HttpTimeout, TcpTimeout, Protocol, GrpcTimeout, PortMapping } from './shared-interfaces'; - -/** - * Defines listener for a VirtualNode - */ -export abstract class VirtualNodeListener { - /** - * Returns an HTTP Listener for a VirtualNode - */ - public static httpNodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { - return new HttpNodeListener(props); - } - - /** - * Returns an HTTP2 Listener for a VirtualNode - */ - public static http2NodeListener(props?: HttpNodeListenerProps): VirtualNodeListener { - return new HttpNodeListener(props, Protocol.HTTP2); - } - - /** - * Returns an GRPC Listener for a VirtualNode - */ - public static grpcNodeListener(props?: GrpcNodeListenerProps): VirtualNodeListener { - return new GrpcNodeListener(props); - } - - /** - * Returns an TCP Listener for a VirtualNode - */ - public static tcpNodeListener(props?: TcpNodeListenerProps): VirtualNodeListener { - return new TcpNodeListener(props); - } - - /** - * Binds the current object when adding Listener to a VirtualNode - */ - public abstract bind(scope: cdk.Construct): CfnVirtualNode.ListenerProperty; -} - -/** - * Represents the properties required to define a HTTP Listener for a VirtualNode. - */ -class HttpNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - readonly timeout?: HttpTimeout; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - readonly protocol?: Protocol; - - constructor(props?: HttpNodeListenerProps, protocol?: Protocol) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.protocol = protocol; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for HTTP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: this.protocol ? this.protocol : Protocol.HTTP, - }, - healthCheck: renderHealthCheck({ - port: this.port, - protocol: this.protocol ? this.protocol : Protocol.HTTP, - }, this.healthCheck), - timeout: this.timeout ? renderTimeout(this.timeout, this.protocol ? this.protocol : Protocol.HTTP) : undefined, - }; - } -} - -/** - * Represents the properties required to define a GRPC Listener for a VirtualNode. - */ -class GrpcNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for GRPC protocol - * - * @default - none - */ - readonly timeout?: GrpcTimeout; - - constructor(props?: GrpcNodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for GRPC protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.GRPC, - }, - healthCheck: renderHealthCheck({ - port: this.port, - protocol: Protocol.GRPC, - }, this.healthCheck), - timeout: this.timeout ? renderTimeout(this.timeout, Protocol.GRPC) : undefined, - }; - } -} - -/** - * Represents the properties required to define a TCP Listener for a VirtualNode. - */ -class TcpNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for TCP protocol - * - * @default - none - */ - readonly timeout?: TcpTimeout; - - constructor(props?: TcpNodeListenerProps) { - super(); - const checkedProps = props ?? {}; - this.port = checkedProps.port ? checkedProps.port : 8080; - this.healthCheck = checkedProps.healthCheck; - this.timeout = checkedProps.timeout; - } - - /** - * Return Listener for TCP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): CfnVirtualNode.ListenerProperty { - return { - portMapping: { - port: this.port, - protocol: Protocol.TCP, - }, - healthCheck: renderHealthCheck({ - port: this.port, - protocol: Protocol.TCP, - }, this.healthCheck), - timeout: this.timeout ? renderTimeout(this.timeout, Protocol.TCP) : undefined, - }; - } -} - -/** - * Represents the properties needed to define a Listeners for a VirtualNode - */ -interface VirtualNodeListenerProps { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port?: number - - /** - * The health check information for the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; -} - -/** - * Represent the HTTP Node Listener prorperty - */ -export interface HttpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Protocol - * - * @default - HTTP - */ - readonly protocol?: Protocol; - /** - * Timeout for HTTP protocol - * - * @default - None - */ - readonly timeout?: HttpTimeout; -} - -/** - * Represent the GRPC Node Listener prorperty - */ -export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for GRPC protocol - * - * @default - None - */ - readonly timeout?: GrpcTimeout; -} - -/** - * Represent the TCP Node Listener prorperty - */ -export interface TcpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for TCP protocol - * - * @default - None - */ - readonly timeout?: TcpTimeout; -} - -/** - * Returns an HealthCheck for a VirtualNode - */ -function renderHealthCheck(pm: PortMapping, hc: HealthCheck | undefined): CfnVirtualNode.HealthCheckProperty | undefined { - /** - * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { - healthyThreshold: [2, 10], - intervalMillis: [5000, 300000], - port: [1, 65535], - timeoutMillis: [2000, 60000], - unhealthyThreshold: [2, 10], - }; - - if (hc === undefined) { return undefined; } - - if (hc.protocol === Protocol.TCP && hc.path) { - throw new Error('The path property cannot be set with Protocol.TCP'); - } - - if (hc.protocol === Protocol.GRPC && hc.path) { - throw new Error('The path property cannot be set with Protocol.GRPC'); - } - - const healthCheck: CfnVirtualNode.HealthCheckProperty = { - healthyThreshold: hc.healthyThreshold || 2, - intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min - path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), - port: hc.port || pm.port, - protocol: hc.protocol || pm.protocol, - timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), - unhealthyThreshold: hc.unhealthyThreshold || 2, - }; - - (Object.keys(healthCheck) as Array) - .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})`); - } - }); - - return healthCheck; -} - -/** - * Returns the ListenerTimeoutProperty for HTTP protocol - */ -function renderTimeout(tm: any, pr: Protocol): CfnVirtualNode.ListenerTimeoutProperty { - return ({ - [pr]: { - idle: tm?.idle !== undefined ? { - unit: 'ms', - value: tm?.idle.toMilliseconds(), - } : undefined, - perRequest: tm?.perRequest !== undefined ? { - unit: 'ms', - value: tm?.perRequest.toMilliseconds(), - } : undefined, - }, - }); -} diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts new file mode 100644 index 0000000000000..7702e87202b93 --- /dev/null +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts @@ -0,0 +1,375 @@ +import * as cdk from '@aws-cdk/core'; +import { CfnVirtualNode } from './appmesh.generated'; +import { HealthCheck, HttpTimeout, TcpTimeout, Protocol, GrpcTimeout } from './shared-interfaces'; + +/** + * Properties for a VirtualNode listener + */ +export interface VirtualNodeListenerConfig { + /** + * Single listener config for a VirtualNode + */ + readonly listener: CfnVirtualNode.ListenerProperty, +} + +/** + * Defines listener for a VirtualNode + */ +export abstract class VirtualNodeListener { + /** + * Returns an HTTP Listener for a VirtualNode + */ + public static httpNodeListener(props: HttpNodeListenerProps = {}): VirtualNodeListener { + return new HttpNodeListener(props); + } + + /** + * Returns an HTTP2 Listener for a VirtualNode + */ + public static http2NodeListener(props: HttpNodeListenerProps = {}): VirtualNodeListener { + return new Http2NodeListener(props); + } + + /** + * Returns an GRPC Listener for a VirtualNode + */ + public static grpcNodeListener(props: GrpcNodeListenerProps = {}): VirtualNodeListener { + return new GrpcNodeListener(props); + } + + /** + * Returns an TCP Listener for a VirtualNode + */ + public static tcpNodeListener(props: TcpNodeListenerProps = {}): VirtualNodeListener { + return new TcpNodeListener(props); + } + + /** + * Protocol the listener implements + */ + protected abstract protocol: Protocol; + + /** + * Port to listen for connections on + */ + protected abstract port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + */ + protected abstract healthCheck?: HealthCheck; + + /** + * Binds the current object when adding Listener to a VirtualNode + */ + public abstract bind(scope: cdk.Construct): VirtualNodeListenerConfig; + + /** + * Returns an HealthCheck for a VirtualNode + */ + protected renderHealthCheck(hc: HealthCheck): CfnVirtualNode.HealthCheckProperty | undefined { + /** + * 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 CfnVirtualNode.HealthCheckProperty)]?: [number, number]} = { + healthyThreshold: [2, 10], + intervalMillis: [5000, 300000], + port: [1, 65535], + timeoutMillis: [2000, 60000], + unhealthyThreshold: [2, 10], + }; + + if (hc === undefined) { return undefined; } + + if (hc.protocol === Protocol.TCP && hc.path) { + throw new Error('The path property cannot be set with Protocol.TCP'); + } + + if (hc.protocol === Protocol.GRPC && hc.path) { + throw new Error('The path property cannot be set with Protocol.GRPC'); + } + + const healthCheck: CfnVirtualNode.HealthCheckProperty = { + healthyThreshold: hc.healthyThreshold || 2, + intervalMillis: (hc.interval || cdk.Duration.seconds(5)).toMilliseconds(), // min + path: hc.path || (hc.protocol === Protocol.HTTP ? '/' : undefined), + port: hc.port || this.port, + protocol: hc.protocol || this.protocol, + timeoutMillis: (hc.timeout || cdk.Duration.seconds(2)).toMilliseconds(), + unhealthyThreshold: hc.unhealthyThreshold || 2, + }; + + (Object.keys(healthCheck) as Array) + .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})`); + } + }); + + return healthCheck; + } + + /** + * Returns the ListenerTimeoutProperty based on protocol + */ + protected renderTimeout(timeout: any): CfnVirtualNode.ListenerTimeoutProperty { + return ({ + [this.protocol]: { + idle: timeout?.idle !== undefined ? { + unit: 'ms', + value: timeout?.idle.toMilliseconds(), + } : undefined, + perRequest: timeout?.perRequest !== undefined ? { + unit: 'ms', + value: timeout?.perRequest.toMilliseconds(), + } : undefined, + }, + }); + } +} + +/** + * Represents the properties required to define a HTTP Listener for a VirtualNode. + */ +class HttpNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for HTTP protocol + * + * @default - none + */ + readonly timeout?: HttpTimeout; + + /** + * Listener timeout property for HTTP protocol + * + * @default - none + */ + protected protocol: Protocol = Protocol.HTTP; + + constructor(props: HttpNodeListenerProps = {}) { + super(); + this.port = props.port ? props.port : 8080; + this.healthCheck = props.healthCheck; + this.timeout = props.timeout; + } + + /** + * Return Listener for HTTP protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { + return { + listener: { + portMapping: { + port: this.port, + protocol: this.protocol, + }, + healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, + timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, + }, + }; + } +} + +/** +* Represents the properties needed to define an HTTP2 Listener for a VirtualGateway +*/ +class Http2NodeListener extends HttpNodeListener { + constructor(props: HttpNodeListenerProps = {}) { + super(props); + this.protocol = Protocol.HTTP2; + } +} + +/** + * Represents the properties required to define a GRPC Listener for a VirtualNode. + */ +class GrpcNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for GRPC protocol + * + * @default - none + */ + readonly timeout?: GrpcTimeout; + + /** + * Listener timeout property for GRPC protocol + * + * @default - none + */ + protected protocol: Protocol = Protocol.GRPC; + + constructor(props: GrpcNodeListenerProps = {}) { + super(); + this.port = props.port ? props.port : 8080; + this.healthCheck = props.healthCheck; + this.timeout = props.timeout; + } + + /** + * Return Listener for GRPC protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { + return { + listener: { + portMapping: { + port: this.port, + protocol: Protocol.GRPC, + }, + healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, + timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, + }, + }; + } +} + +/** + * Represents the properties required to define a TCP Listener for a VirtualNode. + */ +class TcpNodeListener extends VirtualNodeListener { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port: number; + + /** + * Health checking strategy upstream nodes should use when communicating with the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; + + /** + * Listener timeout property for TCP protocol + * + * @default - none + */ + readonly timeout?: TcpTimeout; + + /** + * Listener timeout property for HTTP protocol + * + * @default - none + */ + protected protocol: Protocol = Protocol.TCP; + + constructor(props: TcpNodeListenerProps = {}) { + super(); + this.port = props.port ? props.port : 8080; + this.healthCheck = props.healthCheck; + this.timeout = props.timeout; + } + + /** + * Return Listener for TCP protocol when Listener is added to Virtual Node. + */ + public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { + return { + listener: { + portMapping: { + port: this.port, + protocol: Protocol.TCP, + }, + healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, + timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, + }, + }; + } +} + +/** + * Represents the properties needed to define a Listeners for a VirtualNode + */ +interface VirtualNodeListenerProps { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port?: number + + /** + * The health check information for the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; +} + +/** + * Represent the HTTP Node Listener prorperty + */ +export interface HttpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for HTTP protocol + * + * @default - None + */ + readonly timeout?: HttpTimeout; +} + +/** + * Represent the GRPC Node Listener prorperty + */ +export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for GRPC protocol + * + * @default - None + */ + readonly timeout?: GrpcTimeout; +} + +/** + * Represent the TCP Node Listener prorperty + */ +export interface TcpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for TCP protocol + * + * @default - None + */ + readonly timeout?: TcpTimeout; +} + diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 18823f5268edf..4aeb6501f7c31 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -4,7 +4,7 @@ import { Construct } from 'constructs'; import { CfnVirtualNode } from './appmesh.generated'; import { IMesh } from './mesh'; import { AccessLog } from './shared-interfaces'; -import { VirtualNodeListener } from './virtual-listener'; +import { VirtualNodeListener, VirtualNodeListenerConfig } from './virtual-node-listener'; import { IVirtualService } from './virtual-service'; /** @@ -34,15 +34,10 @@ export interface IVirtualNode extends cdk.IResource { */ addBackends(...props: IVirtualService[]): void; - /** - * Utility method to add a single node listener - */ - addListener(listener: VirtualNodeListener): void; - /** * Utility method to add Node Listeners for new or existing VirtualNodes */ - addListeners(...listeners: VirtualNodeListener[]): void; + addListeners(listeners: VirtualNodeListener[]): void; } /** @@ -95,7 +90,7 @@ export interface VirtualNodeBaseProps { * * @default - No listeners */ - readonly listener?: VirtualNodeListener; + readonly listeners?: VirtualNodeListener[]; /** * Access Logging Configuration for the virtual node @@ -127,7 +122,7 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { public abstract readonly virtualNodeArn: string; protected readonly backends = new Array(); - protected readonly listeners = new Array(); + protected readonly listeners = new Array(); /** * Add a Virtual Services that this node is expected to send outbound traffic to @@ -145,23 +140,8 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { /** * Utility method to add an inbound listener for this VirtualNode */ - public addListeners(...listeners: VirtualNodeListener[]) { - if (listeners.length + this.listeners.length > 1) { - throw new Error('VirtualNode may have at most one listener'); - } - for (const listener of listeners) { - this.addListener(listener); - } - } - - /** - * Utility method to add a single listener to this VirtualNode - */ - public addListener(listener: VirtualNodeListener) { - if (this.listeners.length > 0) { - throw new Error('VirtualNode may have at most one listener'); - } - this.listeners.push(listener.bind(this)); + public addListeners(listeners: VirtualNodeListener[]) { + listeners.forEach(listener => this.listeners.push(listener.bind(this))); } } @@ -215,7 +195,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(...props.listener ? [props.listener] : [VirtualNodeListener.httpNodeListener()]); + this.addListeners(props.listeners ? props.listeners : []); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { @@ -223,7 +203,7 @@ export class VirtualNode extends VirtualNodeBase { meshName: this.mesh.meshName, spec: { backends: cdk.Lazy.anyValue({ produce: () => this.backends }, { omitEmptyArray: true }), - listeners: cdk.Lazy.anyValue({ produce: () => this.listeners }, { omitEmptyArray: true }), + listeners: cdk.Lazy.anyValue({ produce: () => this.listeners.map(listener => listener.listener) }, { omitEmptyArray: true }), serviceDiscovery: { dns: props.dnsHostName !== undefined ? { hostname: props.dnsHostName } : undefined, awsCloudMap: props.cloudMapService !== undefined ? { diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index 2eabd7ddedddb..f0a0fe96ec518 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,12 +34,12 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, path: '/check-path', }, - }), + })], backends: [ virtualService, ], @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -73,7 +73,7 @@ const node2 = mesh.addVirtualNode('node2', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }), + })], backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -94,7 +94,7 @@ const node3 = mesh.addVirtualNode('node3', { timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }, - }), + })], accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 76eb8132ea435..98be0d53cae15 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -20,9 +20,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { interval: cdk.Duration.millis(millis) }, - }), + })], }); // THEN @@ -42,9 +42,9 @@ export = { // WHEN const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { timeout: cdk.Duration.millis(millis) }, - }), + })], }); // THEN @@ -64,9 +64,9 @@ export = { // WHEN const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { port }, - }), + })], }); // THEN @@ -87,9 +87,9 @@ export = { // WHEN const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { healthyThreshold }, - }), + })], }); // THEN @@ -109,9 +109,9 @@ export = { // WHEN const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { unhealthyThreshold }, - }), + })], }); // THEN @@ -129,12 +129,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - }), + })], }); // THEN @@ -151,12 +151,12 @@ export = { // WHEN const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { dnsHostName: 'test-node', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ healthCheck: { protocol, path: '/', }, - }), + })], }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index a87a1c2a2ef21..4f8ceef7f3076 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -221,9 +221,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], }); mesh.addVirtualService('service2', { @@ -272,15 +272,6 @@ export = { 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], }, Spec: { - // One listener is added by default. - Listeners: [ - { - PortMapping: { - Port: 8080, - Protocol: 'http', - }, - }, - ], ServiceDiscovery: { DNS: { Hostname: 'test.domain.local', @@ -305,9 +296,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], }); // THEN @@ -344,7 +335,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -353,7 +344,7 @@ export = { timeout: cdk.Duration.seconds(2), // min unhealthyThreshold: 2, }, - }), + })], }); // THEN @@ -400,9 +391,9 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index 261fc86200672..d1af511c85e6b 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,9 +24,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 82c19e5b3198c..db6de57cc9a8f 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -37,12 +37,6 @@ export = { expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { Spec: { - Listeners: [{ - PortMapping: { - Port: 8080, - Protocol: 'http', - }, - }], Backends: [ { VirtualService: { @@ -79,9 +73,9 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8081, - }), + })], }); // THEN @@ -116,13 +110,13 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.grpcNodeListener({ + listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ port: 80, timeout: { idle: cdk.Duration.seconds(10), perRequest: cdk.Duration.seconds(10), }, - }), + })], }); // THEN @@ -169,11 +163,11 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.http2NodeListener({ + listeners: [appmesh.VirtualNodeListener.http2NodeListener({ port: 80, healthCheck: {}, timeout: { idle: cdk.Duration.seconds(10) }, - }), + })], }); // THEN @@ -221,16 +215,17 @@ export = { meshName: 'test-mesh', }); - new appmesh.VirtualNode(stack, 'test-node', { + const node = new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.tcpNodeListener({ - port: 80, - healthCheck: { timeout: cdk.Duration.seconds(3) }, - timeout: { idle: cdk.Duration.seconds(10) }, - }), }); + node.addListeners([appmesh.VirtualNodeListener.tcpNodeListener({ + port: 80, + healthCheck: { timeout: cdk.Duration.seconds(3) }, + timeout: { idle: cdk.Duration.seconds(10) }, + })]); + // THEN expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { @@ -282,11 +277,7 @@ export = { const stack2 = new cdk.Stack(); - const node2 = appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); - - node2.addListeners(appmesh.VirtualNodeListener.httpNodeListener({ - port: 8081, - })); + appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); // THEN expect(stack).to( @@ -295,14 +286,6 @@ export = { 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], }, Spec: { - Listeners: [ - { - PortMapping: { - Port: 8080, - Protocol: 'http', - }, - }, - ], ServiceDiscovery: { DNS: { Hostname: 'test.domain.local', diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index ad5530befdc81..dd8f2f1aad52a 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,10 +24,10 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, healthCheck: {}, - }), + })], backends: [service1], }); @@ -94,27 +94,27 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service2, ], }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], @@ -240,9 +240,9 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listener: appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.httpNodeListener({ port: 8080, - }), + })], backends: [ service1, ], From 8373e3c87d5c0c8078e8ba7c9fd7e6641c33474b Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 2 Nov 2020 13:16:45 -0800 Subject: [PATCH 13/21] Updated appmesh.ts to add listener based on protocol --- .../lib/extensions/appmesh.ts | 25 ++++++++++++++++--- .../aws-appmesh/test/cdk.code-workspace | 7 ++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index 929d7e39dba1c..521b43fc15a6c 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -259,14 +259,33 @@ export class AppMeshExtension extends ServiceExtension { throw new Error('You must add a CloudMap namespace to the ECS cluster in order to use the AppMesh extension'); } + function addListener(protocol: appmesh.Protocol, port: number) { + if (protocol === appmesh.Protocol.HTTP2) { + return appmesh.VirtualNodeListener.http2NodeListener({ + port: port, + }); + } + if (protocol === appmesh.Protocol.TCP) { + return appmesh.VirtualNodeListener.tcpNodeListener({ + port: port, + }); + } + if (protocol === appmesh.Protocol.GRPC) { + return appmesh.VirtualNodeListener.grpcNodeListener({ + port: port, + }); + } else { + return appmesh.VirtualNodeListener.httpNodeListener({ + port: port, + }); + } + } // Create a virtual node for the name service this.virtualNode = new appmesh.VirtualNode(this.scope, `${this.parentService.id}-virtual-node`, { mesh: this.mesh, virtualNodeName: this.parentService.id, cloudMapService: service.cloudMapService, - listener: appmesh.VirtualNodeListener.httpNodeListener({ - port: containerextension.trafficPort, - }), + listeners: [addListener(this.protocol, containerextension.trafficPort)], }); // Create a virtual router for this service. This allows for retries diff --git a/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace b/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace new file mode 100644 index 0000000000000..596ef7a482b42 --- /dev/null +++ b/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace @@ -0,0 +1,7 @@ +{ + "folders": [ + { + "path": "../../../.." + } + ] +} \ No newline at end of file From f220debd562ae009bf66c080edb351f27f0601dd Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 2 Nov 2020 13:23:01 -0800 Subject: [PATCH 14/21] Removing unused file from directory --- packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace diff --git a/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace b/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace deleted file mode 100644 index 596ef7a482b42..0000000000000 --- a/packages/@aws-cdk/aws-appmesh/test/cdk.code-workspace +++ /dev/null @@ -1,7 +0,0 @@ -{ - "folders": [ - { - "path": "../../../.." - } - ] -} \ No newline at end of file From 03b4c1f0b38554ebce8850b7f63b4a52c2c3e362 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Thu, 5 Nov 2020 11:45:15 -0800 Subject: [PATCH 15/21] - Updated test to remove unnecessary changes. - Removed empty listeners as we will not have a default listener. Listeners can be added to a node after the node is created. --- .../lib/extensions/appmesh.ts | 33 ++-- .../aws-appmesh/lib/shared-interfaces.ts | 50 ------ .../aws-appmesh/lib/virtual-node-listener.ts | 170 +++++++++++------- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 6 +- .../aws-appmesh/test/test.health-check.ts | 82 ++++----- .../@aws-cdk/aws-appmesh/test/test.mesh.ts | 11 +- .../@aws-cdk/aws-appmesh/test/test.route.ts | 2 +- .../aws-appmesh/test/test.virtual-node.ts | 24 +-- .../aws-appmesh/test/test.virtual-router.ts | 11 +- 9 files changed, 185 insertions(+), 204 deletions(-) diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index 2705099985067..328bee495fd90 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -259,27 +259,22 @@ export class AppMeshExtension extends ServiceExtension { throw new Error('You must add a CloudMap namespace to the ECS cluster in order to use the AppMesh extension'); } - function addListener(protocol: appmesh.Protocol, port: number) { - if (protocol === appmesh.Protocol.HTTP2) { - return appmesh.VirtualNodeListener.http2NodeListener({ - port: port, - }); - } - if (protocol === appmesh.Protocol.TCP) { - return appmesh.VirtualNodeListener.tcpNodeListener({ - port: port, - }); - } - if (protocol === appmesh.Protocol.GRPC) { - return appmesh.VirtualNodeListener.grpcNodeListener({ - port: port, - }); - } else { - return appmesh.VirtualNodeListener.httpNodeListener({ - port: port, - }); + function addListener(protocol: appmesh.Protocol, port: number): appmesh.VirtualNodeListener { + switch (protocol) { + case appmesh.Protocol.HTTP : + return appmesh.VirtualNodeListener.http({ port }); + + case appmesh.Protocol.HTTP2 : + return appmesh.VirtualNodeListener.http2({ port }); + + case appmesh.Protocol.GRPC : + return appmesh.VirtualNodeListener.grpc({ port }); + + case appmesh.Protocol.TCP : + return appmesh.VirtualNodeListener.tcp({ port }); } } + // Create a virtual node for the name service this.virtualNode = new appmesh.VirtualNode(this.scope, `${this.parentService.id}-virtual-node`, { mesh: this.mesh, diff --git a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts index 9b51e96ceb82a..cc07484f32cfa 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts @@ -87,56 +87,6 @@ export interface PortMapping { readonly protocol: Protocol; } -/** - * Represents timeouts for HTTP 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 GRPC 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 TCP protocols. - */ -export interface TcpTimeout { - /** - * Represents an idle timeout. The amount of time that a connection may be idle. - * - * @default - none - */ - readonly idle?: cdk.Duration; -} - /** * All Properties for Envoy Access logs for mesh endpoints */ diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts index 69b6cb378891a..9b85510b5bb37 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts @@ -1,7 +1,7 @@ import * as cdk from '@aws-cdk/core'; import { CfnVirtualNode } from './appmesh.generated'; import { validateHealthChecks } from './private/utils'; -import { HealthCheck, HttpTimeout, TcpTimeout, Protocol, GrpcTimeout } from './shared-interfaces'; +import { HealthCheck, Protocol } from './shared-interfaces'; /** * Properties for a VirtualNode listener @@ -13,6 +13,111 @@ export interface VirtualNodeListenerConfig { readonly listener: CfnVirtualNode.ListenerProperty, } +/** + * Represents the properties needed to define a Listeners for a VirtualNode + */ +interface VirtualNodeListenerProps { + /** + * Port to listen for connections on + * + * @default - 8080 + */ + readonly port?: number + + /** + * The health check information for the listener + * + * @default - no healthcheck + */ + readonly healthCheck?: HealthCheck; +} + +/** + * Represent the HTTP Node Listener prorperty + */ +export interface HttpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for HTTP protocol + * + * @default - None + */ + readonly timeout?: HttpTimeout; +} + +/** + * Represent the GRPC Node Listener prorperty + */ +export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for GRPC protocol + * + * @default - None + */ + readonly timeout?: GrpcTimeout; +} + +/** + * Represent the TCP Node Listener prorperty + */ +export interface TcpNodeListenerProps extends VirtualNodeListenerProps { + /** + * Timeout for TCP protocol + * + * @default - None + */ + readonly timeout?: TcpTimeout; +} + +/** + * Represents timeouts for HTTP 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 GRPC 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 TCP protocols. + */ +export interface TcpTimeout { + /** + * Represents an idle timeout. The amount of time that a connection may be idle. + * + * @default - none + */ + readonly idle?: cdk.Duration; +} + /** * Defines listener for a VirtualNode */ @@ -20,28 +125,28 @@ export abstract class VirtualNodeListener { /** * Returns an HTTP Listener for a VirtualNode */ - public static httpNodeListener(props: HttpNodeListenerProps = {}): VirtualNodeListener { + public static http(props: HttpNodeListenerProps = {}): VirtualNodeListener { return new HttpNodeListener(props); } /** * Returns an HTTP2 Listener for a VirtualNode */ - public static http2NodeListener(props: HttpNodeListenerProps = {}): VirtualNodeListener { + public static http2(props: HttpNodeListenerProps = {}): VirtualNodeListener { return new Http2NodeListener(props); } /** * Returns an GRPC Listener for a VirtualNode */ - public static grpcNodeListener(props: GrpcNodeListenerProps = {}): VirtualNodeListener { + public static grpc(props: GrpcNodeListenerProps = {}): VirtualNodeListener { return new GrpcNodeListener(props); } /** * Returns an TCP Listener for a VirtualNode */ - public static tcpNodeListener(props: TcpNodeListenerProps = {}): VirtualNodeListener { + public static tcp(props: TcpNodeListenerProps = {}): VirtualNodeListener { return new TcpNodeListener(props); } @@ -291,58 +396,3 @@ class TcpNodeListener extends VirtualNodeListener { } } -/** - * Represents the properties needed to define a Listeners for a VirtualNode - */ -interface VirtualNodeListenerProps { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port?: number - - /** - * The health check information for the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; -} - -/** - * Represent the HTTP Node Listener prorperty - */ -export interface HttpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for HTTP protocol - * - * @default - None - */ - readonly timeout?: HttpTimeout; -} - -/** - * Represent the GRPC Node Listener prorperty - */ -export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for GRPC protocol - * - * @default - None - */ - readonly timeout?: GrpcTimeout; -} - -/** - * Represent the TCP Node Listener prorperty - */ -export interface TcpNodeListenerProps extends VirtualNodeListenerProps { - /** - * Timeout for TCP protocol - * - * @default - None - */ - readonly timeout?: TcpTimeout; -} - diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index f1e064140b4ed..7865f209a4efe 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -34,7 +34,7 @@ const virtualService = mesh.addVirtualService('service', { const node = mesh.addVirtualNode('node', { dnsHostName: `node1.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ healthCheck: { healthyThreshold: 3, path: '/check-path', @@ -63,7 +63,7 @@ router.addRoute('route-1', { const node2 = mesh.addVirtualNode('node2', { dnsHostName: `node2.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), @@ -84,7 +84,7 @@ const node2 = mesh.addVirtualNode('node2', { const node3 = mesh.addVirtualNode('node3', { dnsHostName: `node3.${namespace.namespaceName}`, - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ healthCheck: { healthyThreshold: 3, interval: cdk.Duration.seconds(5), diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 98be0d53cae15..8f2a99b141b15 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -4,10 +4,13 @@ import { Test } from 'nodeunit'; import * as appmesh from '../lib'; let idCounter = 0; -const getMesh = (stack: cdk.Stack) => { - return new appmesh.Mesh(stack, `mesh-${++idCounter}`, { +const getNode = (stack: cdk.Stack) => { + const mesh = new appmesh.Mesh(stack, `mesh-${++idCounter}`, { meshName: 'test-mesh', }); + return mesh.addVirtualNode(`virtual-node-${idCounter}`, { + dnsHostName: 'test-node', + }); }; export = { @@ -18,12 +21,9 @@ export = { const [min, max] = [5000, 300000]; // WHEN - const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { interval: cdk.Duration.millis(millis) }, - })], - }); + const toThrow = (millis: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http2({ + healthCheck: { interval: cdk.Duration.millis(millis) }, + })]); // THEN test.doesNotThrow(() => toThrow(min)); @@ -40,12 +40,9 @@ export = { const [min, max] = [2000, 60000]; // WHEN - const toThrow = (millis: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { timeout: cdk.Duration.millis(millis) }, - })], - }); + const toThrow = (millis: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http2({ + healthCheck: { timeout: cdk.Duration.millis(millis) }, + })]); // THEN test.doesNotThrow(() => toThrow(min)); @@ -62,12 +59,9 @@ export = { const [min, max] = [1, 65535]; // WHEN - const toThrow = (port: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { port }, - })], - }); + const toThrow = (port: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + healthCheck: { port }, + })]); // THEN test.doesNotThrow(() => toThrow(min)); @@ -85,12 +79,9 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (healthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { healthyThreshold }, - })], - }); + const toThrow = (healthyThreshold: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + healthCheck: { healthyThreshold }, + })]); // THEN test.doesNotThrow(() => toThrow(min)); @@ -107,12 +98,9 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (unhealthyThreshold: number) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { unhealthyThreshold }, - })], - }); + const toThrow = (unhealthyThreshold: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + healthCheck: { unhealthyThreshold }, + })]); // THEN test.doesNotThrow(() => toThrow(min)); @@ -127,15 +115,12 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { - protocol, - path: '/', - }, - })], - }); + const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + healthCheck: { + protocol, + path: '/', + }, + })]); // THEN test.doesNotThrow(() => toThrow(appmesh.Protocol.HTTP)); @@ -149,15 +134,12 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getMesh(stack).addVirtualNode(`virtual-node-${idCounter}`, { - dnsHostName: 'test-node', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - healthCheck: { - protocol, - path: '/', - }, - })], - }); + const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + healthCheck: { + protocol, + path: '/', + }, + })]); // THEN test.doesNotThrow(() => toThrow(appmesh.Protocol.HTTP)); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index 4f8ceef7f3076..78e342db1253f 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -57,7 +57,7 @@ export = { 'When adding a Virtual Router to existing mesh': { 'with at least one complete port mappings': { - 'shoulld create proper router'(test: Test) { + 'should create proper router'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -221,7 +221,7 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], }); @@ -272,6 +272,7 @@ export = { 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], }, Spec: { + // Specifically: no Listeners and Backends ServiceDiscovery: { DNS: { Hostname: 'test.domain.local', @@ -296,7 +297,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], }); @@ -335,7 +336,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, healthCheck: { healthyThreshold: 3, @@ -391,7 +392,7 @@ export = { mesh.addVirtualNode('test-node', { dnsHostName: 'test.domain.local', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ diff --git a/packages/@aws-cdk/aws-appmesh/test/test.route.ts b/packages/@aws-cdk/aws-appmesh/test/test.route.ts index d1af511c85e6b..94659bfeb9595 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.route.ts @@ -24,7 +24,7 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index db6de57cc9a8f..61c2a25af4a05 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -70,14 +70,14 @@ export = { meshName: 'test-mesh', }); - new appmesh.VirtualNode(stack, 'test-node', { - mesh, + const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ - port: 8081, - })], }); + node.addListeners([appmesh.VirtualNodeListener.tcp({ + port: 8081, + })]); + // THEN expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { @@ -86,7 +86,7 @@ export = { { PortMapping: { Port: 8081, - Protocol: 'http', + Protocol: 'tcp', }, }, ], @@ -110,7 +110,7 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.grpcNodeListener({ + listeners: [appmesh.VirtualNodeListener.grpc({ port: 80, timeout: { idle: cdk.Duration.seconds(10), @@ -163,7 +163,7 @@ export = { new appmesh.VirtualNode(stack, 'test-node', { mesh, dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.http2NodeListener({ + listeners: [appmesh.VirtualNodeListener.http2({ port: 80, healthCheck: {}, timeout: { idle: cdk.Duration.seconds(10) }, @@ -220,7 +220,7 @@ export = { dnsHostName: 'test', }); - node.addListeners([appmesh.VirtualNodeListener.tcpNodeListener({ + node.addListeners([appmesh.VirtualNodeListener.tcp({ port: 80, healthCheck: { timeout: cdk.Duration.seconds(3) }, timeout: { idle: cdk.Duration.seconds(10) }, @@ -277,7 +277,11 @@ export = { const stack2 = new cdk.Stack(); - appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); + const node2 = appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); + + node2.addListeners([appmesh.VirtualNodeListener.tcp({ + port: 8081, + })]); // THEN expect(stack).to( diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts index dd8f2f1aad52a..c3c51c4a88f4a 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -24,9 +24,8 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, - healthCheck: {}, })], backends: [service1], }); @@ -94,7 +93,7 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ @@ -103,7 +102,7 @@ export = { }); const node2 = mesh.addVirtualNode('test-node2', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ @@ -112,7 +111,7 @@ export = { }); const node3 = mesh.addVirtualNode('test-node3', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ @@ -240,7 +239,7 @@ export = { const node = mesh.addVirtualNode('test-node', { dnsHostName: 'test', - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + listeners: [appmesh.VirtualNodeListener.http({ port: 8080, })], backends: [ From 6ff4b82f01bb762b8677571fc5a8e8ec18357249 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Thu, 5 Nov 2020 18:08:34 -0800 Subject: [PATCH 16/21] - Moved bind implementation to VirtualNodeListener. - Renamed Interface from *Props to *Options. --- .../aws-appmesh/lib/virtual-node-listener.ts | 92 ++++++------------- packages/@aws-cdk/aws-appmesh/package.json | 8 +- 2 files changed, 34 insertions(+), 66 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts index 9b85510b5bb37..0b9635518792f 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts @@ -16,7 +16,7 @@ export interface VirtualNodeListenerConfig { /** * Represents the properties needed to define a Listeners for a VirtualNode */ -interface VirtualNodeListenerProps { +interface VirtualNodeListenerOptions { /** * Port to listen for connections on * @@ -35,7 +35,7 @@ interface VirtualNodeListenerProps { /** * Represent the HTTP Node Listener prorperty */ -export interface HttpNodeListenerProps extends VirtualNodeListenerProps { +export interface HttpNodeListenerOptions extends VirtualNodeListenerOptions { /** * Timeout for HTTP protocol * @@ -47,7 +47,7 @@ export interface HttpNodeListenerProps extends VirtualNodeListenerProps { /** * Represent the GRPC Node Listener prorperty */ -export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { +export interface GrpcNodeListenerOptions extends VirtualNodeListenerOptions { /** * Timeout for GRPC protocol * @@ -59,7 +59,7 @@ export interface GrpcNodeListenerProps extends VirtualNodeListenerProps { /** * Represent the TCP Node Listener prorperty */ -export interface TcpNodeListenerProps extends VirtualNodeListenerProps { +export interface TcpNodeListenerOptions extends VirtualNodeListenerOptions { /** * Timeout for TCP protocol * @@ -125,28 +125,28 @@ export abstract class VirtualNodeListener { /** * Returns an HTTP Listener for a VirtualNode */ - public static http(props: HttpNodeListenerProps = {}): VirtualNodeListener { + public static http(props: HttpNodeListenerOptions = {}): VirtualNodeListener { return new HttpNodeListener(props); } /** * Returns an HTTP2 Listener for a VirtualNode */ - public static http2(props: HttpNodeListenerProps = {}): VirtualNodeListener { + public static http2(props: HttpNodeListenerOptions = {}): VirtualNodeListener { return new Http2NodeListener(props); } /** * Returns an GRPC Listener for a VirtualNode */ - public static grpc(props: GrpcNodeListenerProps = {}): VirtualNodeListener { + public static grpc(props: GrpcNodeListenerOptions = {}): VirtualNodeListener { return new GrpcNodeListener(props); } /** * Returns an TCP Listener for a VirtualNode */ - public static tcp(props: TcpNodeListenerProps = {}): VirtualNodeListener { + public static tcp(props: TcpNodeListenerOptions = {}): VirtualNodeListener { return new TcpNodeListener(props); } @@ -165,10 +165,26 @@ export abstract class VirtualNodeListener { */ protected abstract healthCheck?: HealthCheck; + /** + * Represents Listener Timeout + */ + protected abstract timeout?: HttpTimeout; + /** * Binds the current object when adding Listener to a VirtualNode */ - public abstract bind(scope: cdk.Construct): VirtualNodeListenerConfig; + public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { + return { + listener: { + portMapping: { + port: this.port, + protocol: this.protocol, + }, + healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, + timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, + }, + }; + } /** * Returns an HealthCheck for a VirtualNode @@ -202,7 +218,7 @@ export abstract class VirtualNodeListener { /** * Returns the ListenerTimeoutProperty based on protocol */ - protected renderTimeout(timeout: any): CfnVirtualNode.ListenerTimeoutProperty { + private renderTimeout(timeout: HttpTimeout): CfnVirtualNode.ListenerTimeoutProperty { return ({ [this.protocol]: { idle: timeout?.idle !== undefined ? { @@ -250,35 +266,19 @@ class HttpNodeListener extends VirtualNodeListener { */ protected protocol: Protocol = Protocol.HTTP; - constructor(props: HttpNodeListenerProps = {}) { + constructor(props: HttpNodeListenerOptions = {}) { super(); this.port = props.port ? props.port : 8080; this.healthCheck = props.healthCheck; this.timeout = props.timeout; } - - /** - * Return Listener for HTTP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { - return { - listener: { - portMapping: { - port: this.port, - protocol: this.protocol, - }, - healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, - timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, - }, - }; - } } /** * Represents the properties needed to define an HTTP2 Listener for a VirtualGateway */ class Http2NodeListener extends HttpNodeListener { - constructor(props: HttpNodeListenerProps = {}) { + constructor(props: HttpNodeListenerOptions = {}) { super(props); this.protocol = Protocol.HTTP2; } @@ -316,28 +316,12 @@ class GrpcNodeListener extends VirtualNodeListener { */ protected protocol: Protocol = Protocol.GRPC; - constructor(props: GrpcNodeListenerProps = {}) { + constructor(props: GrpcNodeListenerOptions = {}) { super(); this.port = props.port ? props.port : 8080; this.healthCheck = props.healthCheck; this.timeout = props.timeout; } - - /** - * Return Listener for GRPC protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { - return { - listener: { - portMapping: { - port: this.port, - protocol: Protocol.GRPC, - }, - healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, - timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, - }, - }; - } } /** @@ -372,27 +356,11 @@ class TcpNodeListener extends VirtualNodeListener { */ protected protocol: Protocol = Protocol.TCP; - constructor(props: TcpNodeListenerProps = {}) { + constructor(props: TcpNodeListenerOptions = {}) { super(); this.port = props.port ? props.port : 8080; this.healthCheck = props.healthCheck; this.timeout = props.timeout; } - - /** - * Return Listener for TCP protocol when Listener is added to Virtual Node. - */ - public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { - return { - listener: { - portMapping: { - port: this.port, - protocol: Protocol.TCP, - }, - healthCheck: this.healthCheck ? this.renderHealthCheck(this.healthCheck) : undefined, - timeout: this.timeout ? this.renderTimeout(this.timeout) : undefined, - }, - }; - } } diff --git a/packages/@aws-cdk/aws-appmesh/package.json b/packages/@aws-cdk/aws-appmesh/package.json index ac8c0616a59c7..91e110e042f07 100644 --- a/packages/@aws-cdk/aws-appmesh/package.json +++ b/packages/@aws-cdk/aws-appmesh/package.json @@ -175,13 +175,13 @@ "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.HTTP2", "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.GRPC", "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListenerOptions.timeout", "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListenerOptions.timeout", "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListenerProps.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListenerOptions.timeout", "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListenerProps.timeout" + "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListenerOptions.timeout" ] }, "stability": "experimental", From a167ae8f2b2821e9a20ecb1eeed813a37636e0a1 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Fri, 6 Nov 2020 15:34:50 -0800 Subject: [PATCH 17/21] Removed addListeners and moved addListener and addBackends from IVirtualNode to VirtualNode. --- .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 51 ++++++++----------- .../aws-appmesh/test/test.health-check.ts | 28 +++++----- .../aws-appmesh/test/test.virtual-node.ts | 14 ++--- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 2e4488c8381a3..829b0bafd1464 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -29,15 +29,6 @@ export interface IVirtualNode extends cdk.IResource { */ readonly virtualNodeArn: string; - /** - * Utility method to add backends for existing or new VirtualNodes - */ - addBackends(...props: IVirtualService[]): void; - - /** - * Utility method to add Node Listeners for new or existing VirtualNodes - */ - addListeners(listeners: VirtualNodeListener[]): void; } /** @@ -123,26 +114,6 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { protected readonly backends = new Array(); protected readonly listeners = new Array(); - - /** - * Add a Virtual Services that this node is expected to send outbound traffic to - */ - public addBackends(...props: IVirtualService[]) { - for (const s of props) { - this.backends.push({ - virtualService: { - virtualServiceName: s.virtualServiceName, - }, - }); - } - } - - /** - * Utility method to add an inbound listener for this VirtualNode - */ - public addListeners(listeners: VirtualNodeListener[]) { - listeners.forEach(listener => this.listeners.push(listener.bind(this))); - } } /** @@ -195,7 +166,7 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; this.addBackends(...props.backends || []); - this.addListeners(props.listeners ? props.listeners : []); + this.addListener(...props.listeners ? props.listeners : []); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { @@ -225,6 +196,26 @@ export class VirtualNode extends VirtualNodeBase { resourceName: this.physicalName, }); } + + /** + * Utility method to add an inbound listener for this VirtualNode + */ + public addListener(...listeners: VirtualNodeListener[]) { + listeners.forEach(listener => this.listeners.push(listener.bind(this))); + } + + /** + * Add a Virtual Services that this node is expected to send outbound traffic to + */ + public addBackends(...props: IVirtualService[]) { + for (const s of props) { + this.backends.push({ + virtualService: { + virtualServiceName: s.virtualServiceName, + }, + }); + } + } } function renderAttributes(attrs?: {[key: string]: string}) { diff --git a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts index 8f2a99b141b15..d65177a124b70 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.health-check.ts @@ -21,9 +21,9 @@ export = { const [min, max] = [5000, 300000]; // WHEN - const toThrow = (millis: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http2({ + const toThrow = (millis: number) => getNode(stack).addListener(appmesh.VirtualNodeListener.http2({ healthCheck: { interval: cdk.Duration.millis(millis) }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(min)); @@ -40,9 +40,9 @@ export = { const [min, max] = [2000, 60000]; // WHEN - const toThrow = (millis: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http2({ + const toThrow = (millis: number) => getNode(stack).addListener(appmesh.VirtualNodeListener.http2({ healthCheck: { timeout: cdk.Duration.millis(millis) }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(min)); @@ -59,9 +59,9 @@ export = { const [min, max] = [1, 65535]; // WHEN - const toThrow = (port: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + const toThrow = (port: number) => getNode(stack).addListener(appmesh.VirtualNodeListener.http({ healthCheck: { port }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(min)); @@ -79,9 +79,9 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (healthyThreshold: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + const toThrow = (healthyThreshold: number) => getNode(stack).addListener(appmesh.VirtualNodeListener.http({ healthCheck: { healthyThreshold }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(min)); @@ -98,9 +98,9 @@ export = { const [min, max] = [2, 10]; // WHEN - const toThrow = (unhealthyThreshold: number) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + const toThrow = (unhealthyThreshold: number) => getNode(stack).addListener(appmesh.VirtualNodeListener.http({ healthCheck: { unhealthyThreshold }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(min)); @@ -115,12 +115,12 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListener(appmesh.VirtualNodeListener.http({ healthCheck: { protocol, path: '/', }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(appmesh.Protocol.HTTP)); @@ -134,12 +134,12 @@ export = { const stack = new cdk.Stack(); // WHEN - const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListeners([appmesh.VirtualNodeListener.http({ + const toThrow = (protocol: appmesh.Protocol) => getNode(stack).addListener(appmesh.VirtualNodeListener.http({ healthCheck: { protocol, path: '/', }, - })]); + })); // THEN test.doesNotThrow(() => toThrow(appmesh.Protocol.HTTP)); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 61c2a25af4a05..4d2a3cccbb3fb 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -74,9 +74,9 @@ export = { dnsHostName: 'test', }); - node.addListeners([appmesh.VirtualNodeListener.tcp({ + node.addListener(appmesh.VirtualNodeListener.tcp({ port: 8081, - })]); + })); // THEN expect(stack).to( @@ -220,11 +220,11 @@ export = { dnsHostName: 'test', }); - node.addListeners([appmesh.VirtualNodeListener.tcp({ + node.addListener(appmesh.VirtualNodeListener.tcp({ port: 80, healthCheck: { timeout: cdk.Duration.seconds(3) }, timeout: { idle: cdk.Duration.seconds(10) }, - })]); + })); // THEN expect(stack).to( @@ -277,11 +277,7 @@ export = { const stack2 = new cdk.Stack(); - const node2 = appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); - - node2.addListeners([appmesh.VirtualNodeListener.tcp({ - port: 8081, - })]); + appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); // THEN expect(stack).to( From 588b56bdd4212e7e9a0921f319932bca1a813a86 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 9 Nov 2020 15:51:54 -0800 Subject: [PATCH 18/21] Create addListener() and addBackend() method to accept a single listener and backend service respectively --- .../lib/extensions/appmesh.ts | 2 +- packages/@aws-cdk/aws-appmesh/README.md | 2 +- .../aws-appmesh/lib/virtual-node-listener.ts | 189 ++------------ .../@aws-cdk/aws-appmesh/lib/virtual-node.ts | 28 +-- packages/@aws-cdk/aws-appmesh/package.json | 12 +- .../@aws-cdk/aws-appmesh/test/integ.mesh.ts | 2 +- .../aws-appmesh/test/test.virtual-node.ts | 237 +++++++++--------- 7 files changed, 156 insertions(+), 316 deletions(-) diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index 328bee495fd90..17cebc49a85aa 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -340,6 +340,6 @@ export class AppMeshExtension extends ServiceExtension { // Next update the app mesh config so that the local Envoy // proxy on this service knows how to route traffic to // nodes from the other service. - this.virtualNode.addBackends(otherAppMesh.virtualService); + this.virtualNode.addBackend(otherAppMesh.virtualService); } } diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 665b5a01bc0cf..c3552d04efcd8 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -186,7 +186,7 @@ const node = new VirtualNode(this, 'node', { cdk.Tag.add(node, 'Environment', 'Dev'); ``` -The listeners property can be left blank and added later with the `node.addListeners()` method. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `port` must be added. +The `listeners` property can be left blank and added later with the `node.addListener()` method. The `healthcheck` and `timeout` properties are optional but if specifying a listener, the `port` must be added. ## Adding a Route diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts index 0b9635518792f..e3e433d8e25d8 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node-listener.ts @@ -16,7 +16,7 @@ export interface VirtualNodeListenerConfig { /** * Represents the properties needed to define a Listeners for a VirtualNode */ -interface VirtualNodeListenerOptions { +interface VirtualNodeListenerCommonOptions { /** * Port to listen for connections on * @@ -35,7 +35,7 @@ interface VirtualNodeListenerOptions { /** * Represent the HTTP Node Listener prorperty */ -export interface HttpNodeListenerOptions extends VirtualNodeListenerOptions { +export interface HttpVirtualNodeListenerOptions extends VirtualNodeListenerCommonOptions { /** * Timeout for HTTP protocol * @@ -47,7 +47,7 @@ export interface HttpNodeListenerOptions extends VirtualNodeListenerOptions { /** * Represent the GRPC Node Listener prorperty */ -export interface GrpcNodeListenerOptions extends VirtualNodeListenerOptions { +export interface GrpcVirtualNodeListenerOptions extends VirtualNodeListenerCommonOptions { /** * Timeout for GRPC protocol * @@ -59,7 +59,7 @@ export interface GrpcNodeListenerOptions extends VirtualNodeListenerOptions { /** * Represent the TCP Node Listener prorperty */ -export interface TcpNodeListenerOptions extends VirtualNodeListenerOptions { +export interface TcpVirtualNodeListenerOptions extends VirtualNodeListenerCommonOptions { /** * Timeout for TCP protocol * @@ -125,54 +125,44 @@ export abstract class VirtualNodeListener { /** * Returns an HTTP Listener for a VirtualNode */ - public static http(props: HttpNodeListenerOptions = {}): VirtualNodeListener { - return new HttpNodeListener(props); + public static http(props: HttpVirtualNodeListenerOptions = {}): VirtualNodeListener { + return new VirtualNodeListenerImpl(Protocol.HTTP, props.healthCheck, props.timeout, props.port); } /** * Returns an HTTP2 Listener for a VirtualNode */ - public static http2(props: HttpNodeListenerOptions = {}): VirtualNodeListener { - return new Http2NodeListener(props); + public static http2(props: HttpVirtualNodeListenerOptions = {}): VirtualNodeListener { + return new VirtualNodeListenerImpl(Protocol.HTTP2, props.healthCheck, props.timeout, props.port); } /** * Returns an GRPC Listener for a VirtualNode */ - public static grpc(props: GrpcNodeListenerOptions = {}): VirtualNodeListener { - return new GrpcNodeListener(props); + public static grpc(props: GrpcVirtualNodeListenerOptions = {}): VirtualNodeListener { + return new VirtualNodeListenerImpl(Protocol.GRPC, props.healthCheck, props.timeout, props.port); } /** * Returns an TCP Listener for a VirtualNode */ - public static tcp(props: TcpNodeListenerOptions = {}): VirtualNodeListener { - return new TcpNodeListener(props); + public static tcp(props: TcpVirtualNodeListenerOptions = {}): VirtualNodeListener { + return new VirtualNodeListenerImpl(Protocol.TCP, props.healthCheck, props.timeout, props.port); } /** - * Protocol the listener implements - */ - protected abstract protocol: Protocol; - - /** - * Port to listen for connections on + * Binds the current object when adding Listener to a VirtualNode */ - protected abstract port: number; + public abstract bind(scope: cdk.Construct): VirtualNodeListenerConfig; - /** - * Health checking strategy upstream nodes should use when communicating with the listener - */ - protected abstract healthCheck?: HealthCheck; +} - /** - * Represents Listener Timeout - */ - protected abstract timeout?: HttpTimeout; +class VirtualNodeListenerImpl extends VirtualNodeListener { + constructor(private readonly protocol: Protocol, + private readonly healthCheck: HealthCheck | undefined, + private readonly timeout: HttpTimeout | undefined, + private readonly port: number = 8080) { super(); } - /** - * Binds the current object when adding Listener to a VirtualNode - */ public bind(_scope: cdk.Construct): VirtualNodeListenerConfig { return { listener: { @@ -186,10 +176,7 @@ export abstract class VirtualNodeListener { }; } - /** - * Returns an HealthCheck for a VirtualNode - */ - protected renderHealthCheck(hc: HealthCheck): CfnVirtualNode.HealthCheckProperty | undefined { + private renderHealthCheck(hc: HealthCheck): CfnVirtualNode.HealthCheckProperty | undefined { if (hc === undefined) { return undefined; } if (hc.protocol === Protocol.TCP && hc.path) { @@ -215,9 +202,6 @@ export abstract class VirtualNodeListener { return healthCheck; } - /** - * Returns the ListenerTimeoutProperty based on protocol - */ private renderTimeout(timeout: HttpTimeout): CfnVirtualNode.ListenerTimeoutProperty { return ({ [this.protocol]: { @@ -233,134 +217,3 @@ export abstract class VirtualNodeListener { }); } } - -/** - * Represents the properties required to define a HTTP Listener for a VirtualNode. - */ -class HttpNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - readonly timeout?: HttpTimeout; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - protected protocol: Protocol = Protocol.HTTP; - - constructor(props: HttpNodeListenerOptions = {}) { - super(); - this.port = props.port ? props.port : 8080; - this.healthCheck = props.healthCheck; - this.timeout = props.timeout; - } -} - -/** -* Represents the properties needed to define an HTTP2 Listener for a VirtualGateway -*/ -class Http2NodeListener extends HttpNodeListener { - constructor(props: HttpNodeListenerOptions = {}) { - super(props); - this.protocol = Protocol.HTTP2; - } -} - -/** - * Represents the properties required to define a GRPC Listener for a VirtualNode. - */ -class GrpcNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for GRPC protocol - * - * @default - none - */ - readonly timeout?: GrpcTimeout; - - /** - * Listener timeout property for GRPC protocol - * - * @default - none - */ - protected protocol: Protocol = Protocol.GRPC; - - constructor(props: GrpcNodeListenerOptions = {}) { - super(); - this.port = props.port ? props.port : 8080; - this.healthCheck = props.healthCheck; - this.timeout = props.timeout; - } -} - -/** - * Represents the properties required to define a TCP Listener for a VirtualNode. - */ -class TcpNodeListener extends VirtualNodeListener { - /** - * Port to listen for connections on - * - * @default - 8080 - */ - readonly port: number; - - /** - * Health checking strategy upstream nodes should use when communicating with the listener - * - * @default - no healthcheck - */ - readonly healthCheck?: HealthCheck; - - /** - * Listener timeout property for TCP protocol - * - * @default - none - */ - readonly timeout?: TcpTimeout; - - /** - * Listener timeout property for HTTP protocol - * - * @default - none - */ - protected protocol: Protocol = Protocol.TCP; - - constructor(props: TcpNodeListenerOptions = {}) { - super(); - this.port = props.port ? props.port : 8080; - this.healthCheck = props.healthCheck; - this.timeout = props.timeout; - } -} - diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 829b0bafd1464..20ee35e79d7f6 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -111,9 +111,6 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode { * The Amazon Resource Name belonging to the VirtualNdoe */ public abstract readonly virtualNodeArn: string; - - protected readonly backends = new Array(); - protected readonly listeners = new Array(); } /** @@ -158,6 +155,9 @@ export class VirtualNode extends VirtualNodeBase { */ public readonly mesh: IMesh; + protected readonly backends = new Array(); + protected readonly listeners = new Array(); + constructor(scope: Construct, id: string, props: VirtualNodeProps) { super(scope, id, { physicalName: props.virtualNodeName || cdk.Lazy.stringValue({ produce: () => this.node.uniqueId }), @@ -165,8 +165,8 @@ export class VirtualNode extends VirtualNodeBase { this.mesh = props.mesh; - this.addBackends(...props.backends || []); - this.addListener(...props.listeners ? props.listeners : []); + props.backends?.forEach(backend => this.addBackend(backend)); + props.listeners?.forEach(listener => this.addListener(listener)); const accessLogging = props.accessLog?.bind(this); const node = new CfnVirtualNode(this, 'Resource', { @@ -200,21 +200,19 @@ export class VirtualNode extends VirtualNodeBase { /** * Utility method to add an inbound listener for this VirtualNode */ - public addListener(...listeners: VirtualNodeListener[]) { - listeners.forEach(listener => this.listeners.push(listener.bind(this))); + public addListener(listener: VirtualNodeListener) { + this.listeners.push(listener.bind(this)); } /** * Add a Virtual Services that this node is expected to send outbound traffic to */ - public addBackends(...props: IVirtualService[]) { - for (const s of props) { - this.backends.push({ - virtualService: { - virtualServiceName: s.virtualServiceName, - }, - }); - } + public addBackend(props: IVirtualService) { + this.backends.push({ + virtualService: { + virtualServiceName: props.virtualServiceName, + }, + }); } } diff --git a/packages/@aws-cdk/aws-appmesh/package.json b/packages/@aws-cdk/aws-appmesh/package.json index 91e110e042f07..6b58c9981965a 100644 --- a/packages/@aws-cdk/aws-appmesh/package.json +++ b/packages/@aws-cdk/aws-appmesh/package.json @@ -174,14 +174,10 @@ "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.HTTP", "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.HTTP2", "docs-public-apis:@aws-cdk/aws-appmesh.Protocol.GRPC", - "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.GrpcNodeListenerOptions.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.HttpNodeListenerOptions.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.Http2NodeListenerOptions.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListener.timeout", - "duration-prop-type:@aws-cdk/aws-appmesh.TcpNodeListenerOptions.timeout" + "duration-prop-type:@aws-cdk/aws-appmesh.GrpcVirtualNodeListenerOptions.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.HttpVirtualNodeListenerOptions.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.Http2VirtualNodeListenerOptions.timeout", + "duration-prop-type:@aws-cdk/aws-appmesh.TcpVirtualNodeListenerOptions.timeout" ] }, "stability": "experimental", diff --git a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts index 7865f209a4efe..26fbbfcbe92de 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -45,7 +45,7 @@ const node = mesh.addVirtualNode('node', { ], }); -node.addBackends(new appmesh.VirtualService(stack, 'service-2', { +node.addBackend(new appmesh.VirtualService(stack, 'service-2', { virtualServiceName: 'service2.domain.local', mesh, }), diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index 4d2a3cccbb3fb..496001b93f179 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -31,35 +31,34 @@ export = { backends: [service1], }); - node.addBackends(service2); + node.addBackend(service2); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Backends: [ - { - VirtualService: { - VirtualServiceName: { - 'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'], - }, + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Backends: [ + { + VirtualService: { + VirtualServiceName: { + 'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'], }, }, - { - VirtualService: { - VirtualServiceName: { - 'Fn::GetAtt': ['service27C65CF7D', 'VirtualServiceName'], - }, + }, + { + VirtualService: { + VirtualServiceName: { + 'Fn::GetAtt': ['service27C65CF7D', 'VirtualServiceName'], }, }, - ], - }, - }), - ); + }, + ], + }, + })); test.done(); }, }, + 'when a single portmapping is added': { 'should add the portmapping to the resource'(test: Test) { // GIVEN @@ -79,24 +78,23 @@ export = { })); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - PortMapping: { - Port: 8081, - Protocol: 'tcp', - }, + expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + PortMapping: { + Port: 8081, + Protocol: 'tcp', }, - ], - }, - }), - ); + }, + ], + }, + })); test.done(); }, }, + 'when a listener is added with timeout': { 'should add the listener timeout to the resource'(test: Test) { // GIVEN @@ -120,36 +118,35 @@ export = { }); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - PortMapping: { - Port: 80, - Protocol: 'grpc', - }, - Timeout: { - GRPC: { - Idle: { - Unit: 'ms', - Value: 10000, - }, - PerRequest: { - Unit: 'ms', - Value: 10000, - }, + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + PortMapping: { + Port: 80, + Protocol: 'grpc', + }, + Timeout: { + GRPC: { + Idle: { + Unit: 'ms', + Value: 10000, + }, + PerRequest: { + Unit: 'ms', + Value: 10000, }, }, }, - ], - }, - }), - ); + }, + ], + }, + })); test.done(); }, }, + 'when a listener is added with healthcheck ': { 'should add a default listener healthcheck to the resource'(test: Test) { // GIVEN @@ -171,40 +168,39 @@ export = { }); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - HealthCheck: { - HealthyThreshold: 2, - IntervalMillis: 5000, - Port: 80, - Protocol: 'http2', - TimeoutMillis: 2000, - UnhealthyThreshold: 2, - }, - PortMapping: { - Port: 80, - Protocol: 'http2', - }, - Timeout: { - HTTP2: { - Idle: { - Unit: 'ms', - Value: 10000, - }, + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + HealthCheck: { + HealthyThreshold: 2, + IntervalMillis: 5000, + Port: 80, + Protocol: 'http2', + TimeoutMillis: 2000, + UnhealthyThreshold: 2, + }, + PortMapping: { + Port: 80, + Protocol: 'http2', + }, + Timeout: { + HTTP2: { + Idle: { + Unit: 'ms', + Value: 10000, }, }, }, - ], - }, - }), - ); + }, + ], + }, + })); test.done(); }, }, + 'when a listener is added with healthcheck with user defined props': { 'should add a listener healthcheck to the resource'(test: Test) { // GIVEN @@ -227,41 +223,40 @@ export = { })); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - Spec: { - Listeners: [ - { - HealthCheck: { - HealthyThreshold: 2, - IntervalMillis: 5000, - Port: 80, - Protocol: 'tcp', - TimeoutMillis: 3000, - UnhealthyThreshold: 2, - }, - PortMapping: { - Port: 80, - Protocol: 'tcp', - }, - Timeout: { - TCP: { - Idle: { - Unit: 'ms', - Value: 10000, - }, + expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Listeners: [ + { + HealthCheck: { + HealthyThreshold: 2, + IntervalMillis: 5000, + Port: 80, + Protocol: 'tcp', + TimeoutMillis: 3000, + UnhealthyThreshold: 2, + }, + PortMapping: { + Port: 80, + Protocol: 'tcp', + }, + Timeout: { + TCP: { + Idle: { + Unit: 'ms', + Value: 10000, }, }, }, - ], - }, - }), - ); + }, + ], + }, + })); test.done(); }, }, }, + 'Can export and import VirtualNode and perform actions'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -280,21 +275,19 @@ export = { appmesh.VirtualNode.fromVirtualNodeName(stack2, 'imported-node', mesh.meshName, node.virtualNodeName); // THEN - expect(stack).to( - haveResourceLike('AWS::AppMesh::VirtualNode', { - MeshName: { - 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], - }, - Spec: { - ServiceDiscovery: { - DNS: { - Hostname: 'test.domain.local', - }, + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { + MeshName: { + 'Fn::GetAtt': ['meshACDFE68E', 'MeshName'], + }, + Spec: { + ServiceDiscovery: { + DNS: { + Hostname: 'test.domain.local', }, }, - VirtualNodeName: 'meshtestnode428A9479', - }), - ); + }, + VirtualNodeName: 'meshtestnode428A9479', + })); test.done(); }, From b67d48ebc81a26af1514404d274bc7b596bf88a1 Mon Sep 17 00:00:00 2001 From: Shivam Verma Date: Mon, 9 Nov 2020 19:07:54 -0800 Subject: [PATCH 19/21] Removed unnecessary whitespaces --- packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts index f150710ef8148..75c7d0579e71b 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -78,7 +78,7 @@ export = { })); // THEN - expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { Spec: { Listeners: [ { @@ -223,7 +223,7 @@ export = { })); // THEN - expect(stack).to( haveResourceLike('AWS::AppMesh::VirtualNode', { + expect(stack).to(haveResourceLike('AWS::AppMesh::VirtualNode', { Spec: { Listeners: [ { From a2138cd0356e13640933e49a093ff6311241fa80 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Tue, 10 Nov 2020 09:00:09 -0800 Subject: [PATCH 20/21] Make the fields in VirtualNode private instead of protected --- packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index d05591c38b900..8e4e701cc228a 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -174,8 +174,8 @@ export class VirtualNode extends VirtualNodeBase { */ public readonly mesh: IMesh; - protected readonly backends = new Array(); - protected readonly listeners = new Array(); + private readonly backends = new Array(); + private readonly listeners = new Array(); constructor(scope: Construct, id: string, props: VirtualNodeProps) { super(scope, id, { @@ -226,10 +226,10 @@ export class VirtualNode extends VirtualNodeBase { /** * Add a Virtual Services that this node is expected to send outbound traffic to */ - public addBackend(props: IVirtualService) { + public addBackend(virtualService: IVirtualService) { this.backends.push({ virtualService: { - virtualServiceName: props.virtualServiceName, + virtualServiceName: virtualService.virtualServiceName, }, }); } From d35705f855fc3c967a370126dc229fd236f5e1a0 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Tue, 10 Nov 2020 15:39:40 -0800 Subject: [PATCH 21/21] Revert unnecessarily removed empty line in virtual-node.ts --- packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts index 8e4e701cc228a..fd8b2cadc87db 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts @@ -6,6 +6,7 @@ import { IMesh, Mesh } from './mesh'; import { AccessLog } from './shared-interfaces'; import { VirtualNodeListener, VirtualNodeListenerConfig } from './virtual-node-listener'; import { IVirtualService } from './virtual-service'; + /** * Interface which all VirtualNode based classes must implement */