Skip to content

Commit 272b6b1

Browse files
authored
fix(appmesh): allow a Virtual Node have as a backend a Virtual Service whose provider is that Node (#18265)
Addresses a circular dependency issue between Virtual Nodes and Virtual Services that works for Virtual Services created with a defined `virtualServiceName` and a randomly generated name. One such example of this problem was a case where a Virtual Node had a backend that is a Virtual Service whose provider was given as the same Virtual Node. This led to the Virtual Node being dependent on the creation of the Virtual Service, and the Virtual Service being dependent on the creation of the Virtual Node. Fixes #17322 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 9da0780 commit 272b6b1

File tree

6 files changed

+103
-51
lines changed

6 files changed

+103
-51
lines changed

packages/@aws-cdk-containers/ecs-service-extensions/test/integ.all-service-addons.expected.json

+2-12
Original file line numberDiff line numberDiff line change
@@ -3185,22 +3185,12 @@
31853185
"Backends": [
31863186
{
31873187
"VirtualService": {
3188-
"VirtualServiceName": {
3189-
"Fn::GetAtt": [
3190-
"namevirtualservice3DDDDF1E",
3191-
"VirtualServiceName"
3192-
]
3193-
}
3188+
"VirtualServiceName": "name.production"
31943189
}
31953190
},
31963191
{
31973192
"VirtualService": {
3198-
"VirtualServiceName": {
3199-
"Fn::GetAtt": [
3200-
"greetingvirtualservice60AD3AD9",
3201-
"VirtualServiceName"
3202-
]
3203-
}
3193+
"VirtualServiceName": "greeting.production"
32043194
}
32053195
}
32063196
],

packages/@aws-cdk/aws-appmesh/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,24 @@ The `backends` property can be added with `node.addBackend()`. In the example, w
236236

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

239+
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:
240+
241+
```ts
242+
declare const mesh: appmesh.Mesh;
243+
244+
const node = new appmesh.VirtualNode(this, 'node', {
245+
mesh,
246+
serviceDiscovery: appmesh.ServiceDiscovery.dns('node'),
247+
});
248+
249+
const virtualService = new appmesh.VirtualService(this, 'service-1', {
250+
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
251+
virtualServiceName: 'service1.domain.local',
252+
});
253+
254+
node.addBackend(appmesh.Backend.virtualService(virtualService));
255+
```
256+
239257
### Adding TLS to a listener
240258

241259
The `tls` property specifies TLS configuration when creating a listener for a virtual node or a virtual gateway.

packages/@aws-cdk/aws-appmesh/lib/shared-interfaces.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,14 @@ class VirtualServiceBackend extends Backend {
238238
return {
239239
virtualServiceBackend: {
240240
virtualService: {
241-
virtualServiceName: this.virtualService.virtualServiceName,
241+
/**
242+
* We want to use the name of the Virtual Service here directly instead of
243+
* a `{ 'Fn::GetAtt' }` CFN expression. This avoids a circular dependency in
244+
* the case where this Virtual Node is the Virtual Service's provider.
245+
*/
246+
virtualServiceName: cdk.Token.isUnresolved(this.virtualService.virtualServiceName)
247+
? (this.virtualService as any).physicalName
248+
: this.virtualService.virtualServiceName,
242249
clientPolicy: this.tlsClientPolicy
243250
? {
244251
tls: renderTlsClientPolicy(scope, this.tlsClientPolicy),

packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json

+4-24
Original file line numberDiff line numberDiff line change
@@ -1040,22 +1040,12 @@
10401040
"Backends": [
10411041
{
10421042
"VirtualService": {
1043-
"VirtualServiceName": {
1044-
"Fn::GetAtt": [
1045-
"service6D174F83",
1046-
"VirtualServiceName"
1047-
]
1048-
}
1043+
"VirtualServiceName": "service1.domain.local"
10491044
}
10501045
},
10511046
{
10521047
"VirtualService": {
1053-
"VirtualServiceName": {
1054-
"Fn::GetAtt": [
1055-
"service27C65CF7D",
1056-
"VirtualServiceName"
1057-
]
1058-
}
1048+
"VirtualServiceName": "service2.domain.local"
10591049
}
10601050
}
10611051
],
@@ -1111,12 +1101,7 @@
11111101
"Backends": [
11121102
{
11131103
"VirtualService": {
1114-
"VirtualServiceName": {
1115-
"Fn::GetAtt": [
1116-
"service3859EB104",
1117-
"VirtualServiceName"
1118-
]
1119-
}
1104+
"VirtualServiceName": "service3.domain.local"
11201105
}
11211106
}
11221107
],
@@ -1241,12 +1226,7 @@
12411226
"Backends": [
12421227
{
12431228
"VirtualService": {
1244-
"VirtualServiceName": {
1245-
"Fn::GetAtt": [
1246-
"service4983B61EE",
1247-
"VirtualServiceName"
1248-
]
1249-
}
1229+
"VirtualServiceName": "service4.domain.local"
12501230
}
12511231
}
12521232
],

packages/@aws-cdk/aws-appmesh/test/mesh.test.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,7 @@ describe('mesh', () => {
314314
Backends: [
315315
{
316316
VirtualService: {
317-
VirtualServiceName: {
318-
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
319-
},
317+
VirtualServiceName: 'service1.domain.local',
320318
},
321319
},
322320
],

packages/@aws-cdk/aws-appmesh/test/virtual-node.test.ts

+70-11
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,18 @@ describe('virtual node', () => {
4141
Backends: [
4242
{
4343
VirtualService: {
44-
VirtualServiceName: {
45-
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
46-
},
44+
VirtualServiceName: 'service1.domain.local',
4745
},
4846
},
4947
{
5048
VirtualService: {
51-
VirtualServiceName: {
52-
'Fn::GetAtt': ['service27C65CF7D', 'VirtualServiceName'],
53-
},
49+
VirtualServiceName: 'service2.domain.local',
5450
},
5551
},
5652
],
5753
},
5854
MeshOwner: ABSENT,
5955
});
60-
61-
6256
});
6357
});
6458

@@ -458,9 +452,7 @@ describe('virtual node', () => {
458452
Backends: [
459453
{
460454
VirtualService: {
461-
VirtualServiceName: {
462-
'Fn::GetAtt': ['service1A48078CF', 'VirtualServiceName'],
463-
},
455+
VirtualServiceName: 'service1.domain.local',
464456
ClientPolicy: {
465457
TLS: {
466458
Ports: [8080, 8081],
@@ -478,8 +470,75 @@ describe('virtual node', () => {
478470
],
479471
},
480472
});
473+
});
474+
475+
test('you can add a Virtual Service as a backend to a Virtual Node which is the provider for that Virtual Service', () => {
476+
// GIVEN
477+
const stack = new cdk.Stack();
478+
479+
// WHEN
480+
const mesh = new appmesh.Mesh(stack, 'mesh', {
481+
meshName: 'test-mesh',
482+
});
483+
484+
const node = new appmesh.VirtualNode(stack, 'test-node', {
485+
mesh,
486+
serviceDiscovery: appmesh.ServiceDiscovery.dns('test'),
487+
});
488+
489+
const myVirtualService = new appmesh.VirtualService(stack, 'service-1', {
490+
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
491+
virtualServiceName: 'service1.domain.local',
492+
});
493+
494+
node.addBackend(appmesh.Backend.virtualService(myVirtualService));
495+
496+
// THEN
497+
expect(stack).toHaveResourceLike('AWS::AppMesh::VirtualNode', {
498+
Spec: {
499+
Backends: [
500+
{
501+
VirtualService: {
502+
VirtualServiceName: 'service1.domain.local',
503+
},
504+
},
505+
],
506+
},
507+
});
508+
});
509+
510+
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, ', () => {
511+
// GIVEN
512+
const stack = new cdk.Stack();
481513

514+
// WHEN
515+
const mesh = new appmesh.Mesh(stack, 'mesh', {
516+
meshName: 'test-mesh',
517+
});
482518

519+
const node = new appmesh.VirtualNode(stack, 'test-node', {
520+
mesh,
521+
serviceDiscovery: appmesh.ServiceDiscovery.dns('test'),
522+
});
523+
524+
const myVirtualService = new appmesh.VirtualService(stack, 'service-1', {
525+
virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
526+
});
527+
528+
node.addBackend(appmesh.Backend.virtualService(myVirtualService));
529+
530+
// THEN
531+
expect(stack).toHaveResourceLike('AWS::AppMesh::VirtualNode', {
532+
Spec: {
533+
Backends: [
534+
{
535+
VirtualService: {
536+
VirtualServiceName: 'service1',
537+
},
538+
},
539+
],
540+
},
541+
});
483542
});
484543
});
485544

0 commit comments

Comments
 (0)