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 fb93375423798..35436d11ce691 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 @@ -316,8 +316,7 @@ export class AppMeshExtension extends ServiceExtension { // Now create a virtual service. Relationship goes like this: // virtual service -> virtual router -> virtual node this.virtualService = new appmesh.VirtualService(this.scope, `${this.parentService.id}-virtual-service`, { - mesh: this.mesh, - virtualRouter: this.virtualRouter, + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(this.virtualRouter), virtualServiceName: serviceName, }); } diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 2253b12d2987d..c400cbb0af05d 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -109,23 +109,21 @@ When creating a virtual service: Adding a virtual router as the provider: ```ts -mesh.addVirtualService('virtual-service', { - virtualRouter: router, - virtualServiceName: 'my-service.default.svc.cluster.local', +new appmesh.VirtualService('virtual-service', { + virtualServiceName: 'my-service.default.svc.cluster.local', // optional + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router), }); ``` Adding a virtual node as the provider: ```ts -mesh.addVirtualService('virtual-service', { - virtualNode: node, - virtualServiceName: `my-service.default.svc.cluster.local`, +new appmesh.VirtualService('virtual-service', { + virtualServiceName: `my-service.default.svc.cluster.local`, // optional + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node), }); ``` -**Note** that only one must of `virtualNode` or `virtualRouter` must be chosen. - ## Adding a VirtualNode A `virtual node` acts as a logical pointer to a particular task group, such as an Amazon ECS service or a Kubernetes deployment. diff --git a/packages/@aws-cdk/aws-appmesh/lib/mesh.ts b/packages/@aws-cdk/aws-appmesh/lib/mesh.ts index cc0596695aae2..a1cd5b49904a5 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/mesh.ts @@ -4,7 +4,6 @@ import { CfnMesh } from './appmesh.generated'; import { VirtualGateway, VirtualGatewayBaseProps } from './virtual-gateway'; import { VirtualNode, VirtualNodeBaseProps } from './virtual-node'; import { VirtualRouter, VirtualRouterBaseProps } from './virtual-router'; -import { VirtualService, VirtualServiceBaseProps } from './virtual-service'; /** * A utility enum defined for the egressFilter type property, the default of DROP_ALL, @@ -46,11 +45,6 @@ export interface IMesh extends cdk.IResource { */ addVirtualRouter(id: string, props?: VirtualRouterBaseProps): VirtualRouter; - /** - * Adds a VirtualService with the given id - */ - addVirtualService(id: string, props?: VirtualServiceBaseProps): VirtualService; - /** * Adds a VirtualNode to the Mesh */ @@ -86,16 +80,6 @@ abstract class MeshBase extends cdk.Resource implements IMesh { }); } - /** - * Adds a VirtualService with the given id - */ - public addVirtualService(id: string, props: VirtualServiceBaseProps = {}): VirtualService { - return new VirtualService(this, id, { - ...props, - mesh: this, - }); - } - /** * Adds a VirtualNode to the Mesh */ diff --git a/packages/@aws-cdk/aws-appmesh/lib/virtual-service.ts b/packages/@aws-cdk/aws-appmesh/lib/virtual-service.ts index 9ca5d5010b7f4..5685b8b08c1f8 100644 --- a/packages/@aws-cdk/aws-appmesh/lib/virtual-service.ts +++ b/packages/@aws-cdk/aws-appmesh/lib/virtual-service.ts @@ -36,9 +36,9 @@ export interface IVirtualService extends cdk.IResource { } /** - * The base properties which all classes in VirtualService will inherit from + * The properties applied to the VirtualService being defined */ -export interface VirtualServiceBaseProps { +export interface VirtualServiceProps { /** * The name of the VirtualService. * @@ -50,36 +50,17 @@ export interface VirtualServiceBaseProps { */ readonly virtualServiceName?: string; - /** - * The VirtualRouter which the VirtualService uses as provider - * - * @default - At most one of virtualRouter and virtualNode is allowed. - */ - readonly virtualRouter?: IVirtualRouter; - - /** - * The VirtualNode attached to the virtual service - * - * @default - At most one of virtualRouter and virtualNode is allowed. - */ - readonly virtualNode?: IVirtualNode; - /** * Client policy for this Virtual Service * * @default - none */ readonly clientPolicy?: ClientPolicy; -} -/** - * The properties applied to the VirtualService being define - */ -export interface VirtualServiceProps extends VirtualServiceBaseProps { /** - * The Mesh which the VirtualService belongs to + * The VirtualNode or VirtualRouter which the VirtualService uses as its provider */ - readonly mesh: IMesh; + readonly virtualServiceProvider: VirtualServiceProvider; } /** @@ -135,59 +116,35 @@ export class VirtualService extends cdk.Resource implements IVirtualService { public readonly clientPolicy?: ClientPolicy; - private readonly virtualServiceProvider?: CfnVirtualService.VirtualServiceProviderProperty; - constructor(scope: Construct, id: string, props: VirtualServiceProps) { super(scope, id, { physicalName: props.virtualServiceName || cdk.Lazy.string({ produce: () => cdk.Names.uniqueId(this) }), }); - if (props.virtualNode && props.virtualRouter) { - throw new Error('Must provide only one of virtualNode or virtualRouter for the provider'); - } - - this.mesh = props.mesh; this.clientPolicy = props.clientPolicy; - - // Check which provider to use node or router (or neither) - if (props.virtualRouter) { - this.virtualServiceProvider = this.addVirtualRouter(props.virtualRouter.virtualRouterName); - } - if (props.virtualNode) { - this.virtualServiceProvider = this.addVirtualNode(props.virtualNode.virtualNodeName); - } + const providerConfig = props.virtualServiceProvider.bind(this); + this.mesh = providerConfig.mesh; const svc = new CfnVirtualService(this, 'Resource', { meshName: this.mesh.meshName, virtualServiceName: this.physicalName, spec: { - provider: this.virtualServiceProvider, + provider: providerConfig.virtualNodeProvider || providerConfig.virtualRouterProvider + ? { + virtualNode: providerConfig.virtualNodeProvider, + virtualRouter: providerConfig.virtualRouterProvider, + } + : undefined, }, }); this.virtualServiceName = this.getResourceNameAttribute(svc.attrVirtualServiceName); this.virtualServiceArn = this.getResourceArnAttribute(svc.ref, { service: 'appmesh', - resource: `mesh/${props.mesh.meshName}/virtualService`, + resource: `mesh/${this.mesh.meshName}/virtualService`, resourceName: this.physicalName, }); } - - private addVirtualRouter(name: string): CfnVirtualService.VirtualServiceProviderProperty { - return { - virtualRouter: { - virtualRouterName: name, - }, - }; - } - - private addVirtualNode(name: string): CfnVirtualService.VirtualServiceProviderProperty { - return { - virtualNode: { - virtualNodeName: name, - }, - }; - } } /** @@ -211,3 +168,91 @@ export interface VirtualServiceAttributes { */ readonly clientPolicy?: ClientPolicy; } + +/** + * Properties for a VirtualService provider + */ +export interface VirtualServiceProviderConfig { + /** + * Virtual Node based provider + * + * @default - none + */ + readonly virtualNodeProvider?: CfnVirtualService.VirtualNodeServiceProviderProperty; + + /** + * Virtual Router based provider + * + * @default - none + */ + readonly virtualRouterProvider?: CfnVirtualService.VirtualRouterServiceProviderProperty; + + /** + * Mesh the Provider is using + * + * @default - none + */ + readonly mesh: IMesh; +} + +/** + * Represents the properties needed to define the provider for a VirtualService + */ +export abstract class VirtualServiceProvider { + /** + * Returns a VirtualNode based Provider for a VirtualService + */ + public static virtualNode(virtualNode: IVirtualNode): VirtualServiceProvider { + return new VirtualServiceProviderImpl(virtualNode, undefined); + } + + /** + * Returns a VirtualRouter based Provider for a VirtualService + */ + public static virtualRouter(virtualRouter: IVirtualRouter): VirtualServiceProvider { + return new VirtualServiceProviderImpl(undefined, virtualRouter); + } + + /** + * Returns an Empty Provider for a VirtualService. This provides no routing capabilities + * and should only be used as a placeholder + */ + public static none(mesh: IMesh): VirtualServiceProvider { + return new VirtualServiceProviderImpl(undefined, undefined, mesh); + } + + /** + * Enforces mutual exclusivity for VirtualService provider types. + */ + public abstract bind(_construct: Construct): VirtualServiceProviderConfig; +} + +class VirtualServiceProviderImpl extends VirtualServiceProvider { + private readonly virtualNode?: IVirtualNode; + private readonly virtualRouter?: IVirtualRouter; + private readonly mesh: IMesh; + + constructor(virtualNode?: IVirtualNode, virtualRouter?: IVirtualRouter, mesh?: IMesh) { + super(); + this.virtualNode = virtualNode; + this.virtualRouter = virtualRouter; + const providedMesh = this.virtualNode?.mesh ?? this.virtualRouter?.mesh ?? mesh!; + this.mesh = providedMesh; + } + + public bind(_construct: Construct): VirtualServiceProviderConfig { + return { + mesh: this.mesh, + virtualNodeProvider: this.virtualNode + ? { + virtualNodeName: this.virtualNode.virtualNodeName, + } + : undefined, + virtualRouterProvider: this.virtualRouter + ? { + virtualRouterName: this.virtualRouter.virtualRouterName, + } + : undefined, + }; + } +} 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 db9277d071432..5f4a9ca206725 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json @@ -625,41 +625,6 @@ } } }, - "meshserviceE06ECED5": { - "Type": "AWS::AppMesh::VirtualService", - "Properties": { - "MeshName": { - "Fn::GetAtt": [ - "meshACDFE68E", - "MeshName" - ] - }, - "Spec": { - "Provider": { - "VirtualRouter": { - "VirtualRouterName": { - "Fn::GetAtt": [ - "meshrouter81B8087E", - "VirtualRouterName" - ] - } - } - } - }, - "VirtualServiceName": "service1.domain.local" - } - }, - "cert56CA94EB": { - "Type": "AWS::CertificateManager::Certificate", - "Properties": { - "DomainName":"node1.domain.local", - "DomainValidationOptions": [{ - "DomainName":"node1.domain.local", - "ValidationDomain":"local" - }], - "ValidationMethod": "EMAIL" - } - }, "meshnode726C787D": { "Type": "AWS::AppMesh::VirtualNode", "Properties": { @@ -675,7 +640,7 @@ "VirtualService": { "VirtualServiceName": { "Fn::GetAtt": [ - "meshserviceE06ECED5", + "service6D174F83", "VirtualServiceName" ] } @@ -706,16 +671,6 @@ "PortMapping": { "Port": 8080, "Protocol": "http" - }, - "TLS": { - "Certificate": { - "ACM": { - "CertificateArn": { - "Ref": "cert56CA94EB" - } - } - }, - "Mode": "STRICT" } } ], @@ -743,8 +698,8 @@ "TLS": { "Validation": { "Trust": { - "ACM": { - "CertificateAuthorityArns": ["arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012"] + "File": { + "CertificateChain": "path/to/cert" } } } @@ -891,7 +846,7 @@ "VirtualService": { "VirtualServiceName": { "Fn::GetAtt": [ - "meshserviceE06ECED5", + "service6D174F83", "VirtualServiceName" ] } @@ -928,7 +883,7 @@ "VirtualService": { "VirtualServiceName": { "Fn::GetAtt": [ - "meshserviceE06ECED5", + "service6D174F83", "VirtualServiceName" ] } @@ -965,7 +920,7 @@ "VirtualService": { "VirtualServiceName": { "Fn::GetAtt": [ - "meshserviceE06ECED5", + "service6D174F83", "VirtualServiceName" ] } @@ -975,7 +930,7 @@ "Match": { "ServiceName": { "Fn::GetAtt": [ - "meshserviceE06ECED5", + "service6D174F83", "VirtualServiceName" ] } @@ -990,6 +945,30 @@ } } }, + "service6D174F83": { + "Type": "AWS::AppMesh::VirtualService", + "Properties": { + "MeshName": { + "Fn::GetAtt": [ + "meshACDFE68E", + "MeshName" + ] + }, + "Spec": { + "Provider": { + "VirtualRouter": { + "VirtualRouterName": { + "Fn::GetAtt": [ + "meshrouter81B8087E", + "VirtualRouterName" + ] + } + } + } + }, + "VirtualServiceName": "service1.domain.local" + } + }, "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 730418aef7970..90e54586f7f51 100644 --- a/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/integ.mesh.ts @@ -1,5 +1,3 @@ -import * as acmpca from '@aws-cdk/aws-acmpca'; -import * as acm from '@aws-cdk/aws-certificatemanager'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as cloudmap from '@aws-cdk/aws-servicediscovery'; import * as cdk from '@aws-cdk/core'; @@ -25,15 +23,11 @@ const router = mesh.addVirtualRouter('router', { ], }); -const virtualService = mesh.addVirtualService('service', { - virtualRouter: router, +const virtualService = new appmesh.VirtualService(stack, 'service', { + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router), virtualServiceName: 'service1.domain.local', }); -const cert = new acm.Certificate(stack, 'cert', { - domainName: `node1.${namespace.namespaceName}`, -}); - const node = mesh.addVirtualNode('node', { serviceDiscovery: appmesh.ServiceDiscovery.dns(`node1.${namespace.namespaceName}`), listeners: [appmesh.VirtualNodeListener.http({ @@ -41,10 +35,6 @@ const node = mesh.addVirtualNode('node', { healthyThreshold: 3, path: '/check-path', }, - tlsCertificate: appmesh.TlsCertificate.acm({ - certificate: cert, - tlsMode: appmesh.TlsMode.STRICT, - }), })], backends: [ virtualService, @@ -53,7 +43,7 @@ const node = mesh.addVirtualNode('node', { node.addBackend(new appmesh.VirtualService(stack, 'service-2', { virtualServiceName: 'service2.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }), ); @@ -75,8 +65,6 @@ router.addRoute('route-1', { }), }); -const certificateAuthorityArn = 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012'; - const node2 = mesh.addVirtualNode('node2', { serviceDiscovery: appmesh.ServiceDiscovery.dns(`node2.${namespace.namespaceName}`), listeners: [appmesh.VirtualNodeListener.http({ @@ -90,13 +78,13 @@ const node2 = mesh.addVirtualNode('node2', { unhealthyThreshold: 2, }, })], - backendsDefaultClientPolicy: appmesh.ClientPolicy.acmTrust({ - certificateAuthorities: [acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'certificate', certificateAuthorityArn)], + backendsDefaultClientPolicy: appmesh.ClientPolicy.fileTrust({ + certificateChain: 'path/to/cert', }), backends: [ new appmesh.VirtualService(stack, 'service-3', { virtualServiceName: 'service3.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }), ], }); diff --git a/packages/@aws-cdk/aws-appmesh/test/test.gateway-route.ts b/packages/@aws-cdk/aws-appmesh/test/test.gateway-route.ts index a741ec0b0d1d8..fed290d36a3e2 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.gateway-route.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.gateway-route.ts @@ -21,7 +21,7 @@ export = { }); const virtualService = new appmesh.VirtualService(stack, 'vs-1', { - mesh: mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), virtualServiceName: 'target.local', }); @@ -121,7 +121,9 @@ export = { meshName: 'test-mesh', }); - const virtualService = mesh.addVirtualService('testVirtualService'); + const virtualService = new appmesh.VirtualService(stack, 'testVirtualService', { + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), + }); test.throws(() => appmesh.GatewayRouteSpec.http({ routeTarget: virtualService, match: { diff --git a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts index c6d2fbfbbb294..ce50c1402a7c3 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.mesh.ts @@ -125,120 +125,6 @@ export = { test.done(); }, - 'When adding a VirtualService to a mesh': { - 'with VirtualRouter and VirtualNode as providers': { - 'should throw error'(test: Test) { - // GIVEN - const stack = new cdk.Stack(); - - // WHEN - const mesh = new appmesh.Mesh(stack, 'mesh', { - meshName: 'test-mesh', - }); - - const testNode = new appmesh.VirtualNode(stack, 'test-node', { - mesh, - serviceDiscovery: appmesh.ServiceDiscovery.dns('test-node'), - }); - - const testRouter = mesh.addVirtualRouter('router', { - listeners: [ - appmesh.VirtualRouterListener.http(), - ], - }); - - // THEN - test.throws(() => { - mesh.addVirtualService('service', { - virtualServiceName: 'test-service.domain.local', - virtualNode: testNode, - virtualRouter: testRouter, - }); - }); - - test.done(); - }, - }, - 'with single virtual router provider resource': { - 'should create service'(test: Test) { - // GIVEN - const stack = new cdk.Stack(); - - // WHEN - const mesh = new appmesh.Mesh(stack, 'mesh', { - meshName: 'test-mesh', - }); - - const testRouter = mesh.addVirtualRouter('test-router', { - listeners: [ - appmesh.VirtualRouterListener.http(), - ], - }); - - mesh.addVirtualService('service', { - virtualServiceName: 'test-service.domain.local', - virtualRouter: testRouter, - }); - - // THEN - expect(stack).to( - haveResource('AWS::AppMesh::VirtualService', { - Spec: { - Provider: { - VirtualRouter: { - VirtualRouterName: { - 'Fn::GetAtt': ['meshtestrouterF78D72DD', 'VirtualRouterName'], - }, - }, - }, - }, - }), - ); - - test.done(); - }, - }, - 'with single virtual node provider resource': { - 'should create service'(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', { - serviceDiscovery: appmesh.ServiceDiscovery.dns('test.domain.local'), - listeners: [appmesh.VirtualNodeListener.http({ - port: 8080, - })], - }); - - mesh.addVirtualService('service2', { - virtualServiceName: 'test-service.domain.local', - virtualNode: node, - }); - - // THEN - expect(stack).to( - haveResource('AWS::AppMesh::VirtualService', { - Spec: { - Provider: { - VirtualNode: { - VirtualNodeName: { - 'Fn::GetAtt': ['meshtestnodeF93946D4', 'VirtualNodeName'], - }, - }, - }, - }, - }), - ); - - test.done(); - }, - }, - }, 'When adding a VirtualNode to a mesh': { 'with empty default listeners and backends': { 'should create default resource'(test: Test) { @@ -376,7 +262,7 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); mesh.addVirtualNode('test-node', { @@ -415,8 +301,9 @@ export = { const stack2 = new cdk.Stack(); const mesh2 = appmesh.Mesh.fromMeshName(stack2, 'imported-mesh', 'abc'); - mesh2.addVirtualService('service', { + new appmesh.VirtualService(stack2, 'service', { virtualServiceName: 'test.domain.local', + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh2), }); // THEN diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-gateway.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-gateway.ts index 7b4a563c90d34..b9d3ed70cae43 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-gateway.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-gateway.ts @@ -306,7 +306,9 @@ export = { mesh: mesh, }); - const virtualService = mesh.addVirtualService('virtualService', {}); + const virtualService = new appmesh.VirtualService(stack, 'virtualService', { + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), + }); virtualGateway.addGatewayRoute('testGatewayRoute', { gatewayRouteName: 'test-gateway-route', @@ -324,7 +326,7 @@ export = { Target: { VirtualService: { VirtualServiceName: { - 'Fn::GetAtt': ['meshvirtualService93460D43', 'VirtualServiceName'], + 'Fn::GetAtt': ['virtualService03A04B87', 'VirtualServiceName'], }, }, }, @@ -349,7 +351,9 @@ export = { meshName: 'test-mesh', }); - const virtualService = mesh.addVirtualService('virtualService', {}); + const virtualService = new appmesh.VirtualService(stack, 'virtualService', { + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), + }); const virtualGateway = mesh.addVirtualGateway('gateway'); virtualGateway.addGatewayRoute('testGatewayRoute', { 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 9fb05931a2a44..4337973230854 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-node.ts @@ -19,11 +19,11 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const service2 = new appmesh.VirtualService(stack, 'service-2', { virtualServiceName: 'service2.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const node = new appmesh.VirtualNode(stack, 'test-node', { @@ -319,7 +319,7 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), clientPolicy: appmesh.ClientPolicy.fileTrust({ certificateChain: 'path-to-certificate', ports: [8080, 8081], 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 aafe3dff8ce7f..2732adb4cba17 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-router.ts @@ -101,7 +101,7 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const node = mesh.addVirtualNode('test-node', { @@ -170,11 +170,11 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const service2 = new appmesh.VirtualService(stack, 'service-2', { virtualServiceName: 'service2.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const node = mesh.addVirtualNode('test-node', { @@ -332,7 +332,7 @@ export = { const service1 = new appmesh.VirtualService(stack, 'service-1', { virtualServiceName: 'service1.domain.local', - mesh, + virtualServiceProvider: appmesh.VirtualServiceProvider.none(mesh), }); const node = mesh.addVirtualNode('test-node', { diff --git a/packages/@aws-cdk/aws-appmesh/test/test.virtual-service.ts b/packages/@aws-cdk/aws-appmesh/test/test.virtual-service.ts index c09c156ac75ea..c60c98f8e7b94 100644 --- a/packages/@aws-cdk/aws-appmesh/test/test.virtual-service.ts +++ b/packages/@aws-cdk/aws-appmesh/test/test.virtual-service.ts @@ -1,3 +1,4 @@ +import { expect, haveResource } from '@aws-cdk/assert'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; @@ -19,6 +20,7 @@ export = { test.done(); }, + 'Can import Virtual Services using attributes'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -34,6 +36,90 @@ export = { // THEN test.equal(virtualService.mesh.meshName, meshName); test.equal(virtualService.virtualServiceName, virtualServiceName); + test.done(); }, + + 'When adding a VirtualService to a mesh': { + 'with single virtual router provider resource': { + 'should create service'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const mesh = new appmesh.Mesh(stack, 'mesh', { + meshName: 'test-mesh', + }); + + const testRouter = mesh.addVirtualRouter('test-router', { + listeners: [ + appmesh.VirtualRouterListener.http(), + ], + }); + + new appmesh.VirtualService(stack, 'service', { + virtualServiceName: 'test-service.domain.local', + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(testRouter), + }); + + // THEN + expect(stack).to( + haveResource('AWS::AppMesh::VirtualService', { + Spec: { + Provider: { + VirtualRouter: { + VirtualRouterName: { + 'Fn::GetAtt': ['meshtestrouterF78D72DD', 'VirtualRouterName'], + }, + }, + }, + }, + }), + ); + + test.done(); + }, + }, + + 'with single virtual node provider resource': { + 'should create service'(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', { + serviceDiscovery: appmesh.ServiceDiscovery.dns('test.domain.local'), + listeners: [appmesh.VirtualNodeListener.http({ + port: 8080, + })], + }); + + new appmesh.VirtualService(stack, 'service2', { + virtualServiceName: 'test-service.domain.local', + virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node), + }); + + // THEN + expect(stack).to( + haveResource('AWS::AppMesh::VirtualService', { + Spec: { + Provider: { + VirtualNode: { + VirtualNodeName: { + 'Fn::GetAtt': ['meshtestnodeF93946D4', 'VirtualNodeName'], + }, + }, + }, + }, + }), + ); + + test.done(); + }, + }, + }, };