Skip to content

Commit

Permalink
fix(appmesh): fix circular dependency by removing virtual service nam…
Browse files Browse the repository at this point in the history
…e reference for virtual node backends
  • Loading branch information
wplucinsky committed Jan 5, 2022
1 parent 26ee826 commit 98c481c
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 39 deletions.
18 changes: 18 additions & 0 deletions packages/@aws-cdk/aws-appmesh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,24 @@ The `backends` property can be added with `node.addBackend()`. In the example, w

The `backendDefaults` property is added to the node while creating the virtual node. These are the virtual node's default settings for all backends.

The `VirtualNode.addBackend()` method is especially useful if you want to create a circular traffic flow by having a Virtual Service as a backend whose provider is that same Virtual Node:

```ts
declare const mesh: appmesh.Mesh;

const node = new appmesh.VirtualNode(this, 'node', {
mesh,
serviceDiscovery: appmesh.ServiceDiscovery.dns('node'),
});

const virtualService = new appmesh.VirtualService(this, 'service-1', {
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
virtualServiceName: 'service1.domain.local',
});

node.addBackend(appmesh.Backend.virtualService(virtualService));
```

### Adding TLS to a listener

The `tls` property specifies TLS configuration when creating a listener for a virtual node or a virtual gateway.
Expand Down
9 changes: 8 additions & 1 deletion packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,14 @@ class VirtualServiceBackend extends Backend {
return {
virtualServiceBackend: {
virtualService: {
virtualServiceName: this.virtualService.virtualServiceName,
/**
* We want to use the name of the Virtual Service here directly instead of
* a `{ 'Fn::GetAtt' }` CFN expression. This avoids a circular dependency in
* the case where this Virtual Node is the Virtual Service's provider.
*/
virtualServiceName: cdk.Token.isUnresolved(this.virtualService.virtualServiceName)
? (this.virtualService as any).physicalName
: this.virtualService.virtualServiceName,
clientPolicy: this.tlsClientPolicy
? {
tls: renderTlsClientPolicy(scope, this.tlsClientPolicy),
Expand Down
28 changes: 4 additions & 24 deletions packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -1040,22 +1040,12 @@
"Backends": [
{
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"VirtualServiceName"
]
}
"VirtualServiceName": "service1.domain.local"
}
},
{
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service27C65CF7D",
"VirtualServiceName"
]
}
"VirtualServiceName": "service2.domain.local"
}
}
],
Expand Down Expand Up @@ -1111,12 +1101,7 @@
"Backends": [
{
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service3859EB104",
"VirtualServiceName"
]
}
"VirtualServiceName": "service3.domain.local"
}
}
],
Expand Down Expand Up @@ -1241,12 +1226,7 @@
"Backends": [
{
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service4983B61EE",
"VirtualServiceName"
]
}
"VirtualServiceName": "service4.domain.local"
}
}
],
Expand Down
4 changes: 1 addition & 3 deletions packages/@aws-cdk/aws-appmesh/test/mesh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,7 @@ describe('mesh', () => {
Backends: [
{
VirtualService: {
VirtualServiceName: {
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
},
VirtualServiceName: 'service1.domain.local',
},
},
],
Expand Down
81 changes: 70 additions & 11 deletions packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,18 @@ describe('virtual node', () => {
Backends: [
{
VirtualService: {
VirtualServiceName: {
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
},
VirtualServiceName: 'service1.domain.local',
},
},
{
VirtualService: {
VirtualServiceName: {
'Fn::GetAtt': ['service27C65CF7D', 'VirtualServiceName'],
},
VirtualServiceName: 'service2.domain.local',
},
},
],
},
MeshOwner: ABSENT,
});


});
});

Expand Down Expand Up @@ -458,9 +452,7 @@ describe('virtual node', () => {
Backends: [
{
VirtualService: {
VirtualServiceName: {
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
},
VirtualServiceName: 'service1.domain.local',
ClientPolicy: {
TLS: {
Ports: [8080, 8081],
Expand All @@ -478,8 +470,75 @@ describe('virtual node', () => {
],
},
});
});

test('you can add a Virtual Service as a backend to a Virtual Node which is the provider for that Virtual Service', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const mesh = new appmesh.Mesh(stack, 'mesh', {
meshName: 'test-mesh',
});

const node = new appmesh.VirtualNode(stack, 'test-node', {
mesh,
serviceDiscovery: appmesh.ServiceDiscovery.dns('test'),
});

const myVirtualService = new appmesh.VirtualService(stack, 'service-1', {
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
virtualServiceName: 'service1.domain.local',
});

node.addBackend(appmesh.Backend.virtualService(myVirtualService));

// THEN
expect(stack).toHaveResourceLike('AWS::AppMesh::VirtualNode', {
Spec: {
Backends: [
{
VirtualService: {
VirtualServiceName: 'service1.domain.local',
},
},
],
},
});
});

test('you can add a Virtual Service with an automated name as a backend to a Virtual Node which is the provider for that Virtual Service, ', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const mesh = new appmesh.Mesh(stack, 'mesh', {
meshName: 'test-mesh',
});

const node = new appmesh.VirtualNode(stack, 'test-node', {
mesh,
serviceDiscovery: appmesh.ServiceDiscovery.dns('test'),
});

const myVirtualService = new appmesh.VirtualService(stack, 'service-1', {
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
});

node.addBackend(appmesh.Backend.virtualService(myVirtualService));

// THEN
expect(stack).toHaveResourceLike('AWS::AppMesh::VirtualNode', {
Spec: {
Backends: [
{
VirtualService: {
VirtualServiceName: 'service1',
},
},
],
},
});
});
});

Expand Down

0 comments on commit 98c481c

Please sign in to comment.