From dd01a409a0225c436dbba5699531d8ea3b4f4be9 Mon Sep 17 00:00:00 2001 From: wplucinsky Date: Fri, 26 Nov 2021 10:37:21 -0800 Subject: [PATCH] allow the virtualServiceName field for virtual node backends to be supplied as a string --- packages/@aws-cdk/aws-appmesh/README.md | 8 ++-- .../aws-appmesh/lib/shared-interfaces.ts | 36 +++++++++++++++ .../aws-appmesh/test/virtual-node.test.ts | 45 +++++++++++++++++++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 54bc79fade4c3..65a974a2fe7ad 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -203,6 +203,7 @@ declare const mesh: appmesh.Mesh; declare const router: appmesh.VirtualRouter; declare const service: cloudmap.Service; +const virtualServiceName = 'service1.domain.local'; const node = new appmesh.VirtualNode(this, 'node', { mesh, serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service), @@ -218,21 +219,20 @@ const node = new appmesh.VirtualNode(this, 'node', { timeout: { idle: cdk.Duration.seconds(5), }, + backends: [appmesh.Backend.virtualServiceName(virtualServiceName)] })], accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), }); const virtualService = new appmesh.VirtualService(this, 'service-1', { virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router), - virtualServiceName: 'service1.domain.local', + virtualServiceName, }); - -node.addBackend(appmesh.Backend.virtualService(virtualService)); ``` The `listeners` property can be left blank and added later with the `node.addListener()` method. The `serviceDiscovery` property must be specified when specifying a listener. -The `backends` property can be added with `node.addBackend()`. In the example, we define a virtual service and add it to the virtual node to allow egress traffic to other nodes. +The `backends` property can be added in the constructor or with `node.addBackend()`. In the example, we define a virtual service and add it to the virtual node to allow egress traffic to other nodes. The `backendDefaults` property is added to the node while creating the virtual node. These are the virtual node's default settings for all backends. diff --git a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts index 8e672ac535bdc..0a7bc9b6a86b7 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts @@ -215,6 +215,13 @@ export abstract class Backend { return new VirtualServiceBackend(virtualService, props.tlsClientPolicy); } + /** + * Construct a Virtual Service backend via a Virtual Service name + */ + public static virtualServiceName(virtualServiceName: string, props: VirtualServiceBackendOptions = {}): Backend { + return new VirtualServiceNameBackend(virtualServiceName, props.tlsClientPolicy); + } + /** * Return backend config */ @@ -250,6 +257,35 @@ class VirtualServiceBackend extends Backend { } } +/** + * Represents the properties needed to define a Virtual Service backend via a Virtual Service name + */ +class VirtualServiceNameBackend extends Backend { + + constructor (private readonly virtualServiceName: string, + private readonly tlsClientPolicy: TlsClientPolicy | undefined) { + super(); + } + + /** + * Return config for a Virtual Service backend + */ + public bind(scope: Construct): BackendConfig { + return { + virtualServiceBackend: { + virtualService: { + virtualServiceName: this.virtualServiceName, + clientPolicy: this.tlsClientPolicy + ? { + tls: renderTlsClientPolicy(scope, this.tlsClientPolicy), + } + : undefined, + }, + }, + }; + } +} + /** * Connection pool properties for HTTP listeners */ diff --git a/packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts b/packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts index 82bc98c6267ef..43c015fc1328e 100644 --- a/packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts +++ b/packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts @@ -57,8 +57,53 @@ describe('virtual node', () => { }, MeshOwner: ABSENT, }); + }); + + test('should add resource with service backends via virtual service names', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + const service1Name = 'service1.domain.local'; + new appmesh.VirtualService(stack, 'service-1', { + virtualServiceName: service1Name, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), + }); + const service2Name = 'service2.domain.local'; + new appmesh.VirtualService(stack, 'service-2', { + virtualServiceName: service2Name, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), + }); + + const node = new appmesh.VirtualNode(stack, 'test-node', { + mesh, + serviceDiscovery: appmesh.ServiceDiscovery.dns('test'), + backends: [appmesh.Backend.virtualServiceName(service1Name)], + }); + node.addBackend(appmesh.Backend.virtualServiceName(service2Name)); + // THEN + expect(stack).toHaveResourceLike('AWS::AppMesh::VirtualNode', { + Spec: { + Backends: [ + { + VirtualService: { + VirtualServiceName: service1Name, + }, + }, + { + VirtualService: { + VirtualServiceName: service2Name, + }, + }, + ], + }, + }); }); });