Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(appmesh): Move Client Policy from Virtual Service to backend structure #12943

Merged
merged 12 commits into from
Mar 12, 2021
Merged
92 changes: 92 additions & 0 deletions packages/@aws-cdk/aws-appmesh/lib/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this motion 🙂.

import { CfnVirtualNode } from './appmesh.generated';
import { ClientPolicy } from './client-policy';
import { IVirtualService } from './virtual-service';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct } from '@aws-cdk/core';

/**
* Represents the properties needed to define backend defaults
*/
export interface BackendDefaultsOptions {
/**
* Client policy for backend defaults
*
* @default none
*/
readonly clientPolicy?: ClientPolicy;
}

/**
* Represents the properties needed to define a backend
*/
export interface BackendOptions {
/**
* The Virtual Service this backend points to
*/
readonly virtualService: IVirtualService;
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a newline between comments and previous variable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this motion 🙂.

* Client policy for a backend
*
* @default none
*/
readonly clientPolicy?: ClientPolicy;
}

/**
* Provides static factory methods to generate backend API structures
*/
export class Backends {
/**
* Creates a backend defaults
*/
public static backendDefaults(props: BackendDefaultsOptions): BackendDefaults {
return new BackendDefaults(props.clientPolicy);
}
/**
* Creates a named backend
*/
public static backend(props: BackendOptions): Backend {
return new Backend(props.virtualService, props.clientPolicy);
}
}

/**
* Represents all the backends that aren't specifically defined using the backend .
*/
export class BackendDefaults {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could just make this an interface. I'm trying to think of a situation where we would need to enforce mutual exclusivity for this field and I'm not sure if we would need this. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I'm following. Do you mean both Backend and BackendDefaults would implement an interface that enforces a method to get the client policy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like, just defining BackendDefaults as an interface type

interface BackendDefaults {
      readonly clientPolicy?: ClientPolicy;
}

and then instead of having to call Backends.backendDefaults you could just create a new object like:

new VirtualNode(stack, 'VirtualNode', {
    ...
    backendDefaults: {
        clientPolicy: appmesh.ClientPolicy.acm({ ... }),
    }
);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is the bind() methods are used to enforce exclusivity. Like you cannot define both file and acm types for ClientPolicies. For backend defaults, I don't see us needing to enforce this mutual exclusivity

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree. It doesn't seem like the bind() pattern is buying us anything here.

Maybe something like this is what we need?

export interface BackendDefaults {
  readonly clientPolicy?: ClientPolicy;
}

export interface Backend {
  readonly clientPolicy?: ClientPolicy;

  readonly virtualService: IVirtualService;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would hesitate to remove to remove the bind() pattern for the backend itself. I could see there being other targets in the future that might not be a IVirtualService. We don't have any immediate plans for this, but adding a different type here is within the realm of reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I defer to the expert(s) here 🙂.


constructor (private readonly clientPolicy: ClientPolicy | undefined) {}

/**
* Return backend defaults config
*/
public bind(_scope: Construct): CfnVirtualNode.BackendDefaultsProperty {
return {
clientPolicy: this.clientPolicy?.bind(_scope).clientPolicy,
};
}
}

/**
* Represents the backend that a virtual node will send outbound traffic to
*/
export class Backend {

constructor (private readonly virtualService: IVirtualService,
private readonly clientPolicy: ClientPolicy | undefined) {}

/**
* Return backend config
*/
public bind(_scope: Construct): CfnVirtualNode.BackendProperty {
return {
virtualService: {
virtualServiceName: this.virtualService.virtualServiceName,
clientPolicy: this.clientPolicy?.bind(_scope).clientPolicy,
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-appmesh/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './virtual-gateway-listener';
export * from './gateway-route';
export * from './gateway-route-spec';
export * from './client-policy';
export * from './backend';
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-appmesh/lib/virtual-gateway.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnVirtualGateway } from './appmesh.generated';
import { ClientPolicy } from './client-policy';
import { BackendDefaults } from './backend';
import { GatewayRoute, GatewayRouteBaseProps } from './gateway-route';
import { IMesh, Mesh } from './mesh';
import { AccessLog } from './shared-interfaces';
Expand Down Expand Up @@ -66,7 +66,7 @@ export interface VirtualGatewayBaseProps {
*
* @default - No Config
*/
readonly backendsDefaultClientPolicy?: ClientPolicy;
readonly backendDefaults?: BackendDefaults;
}

/**
Expand Down Expand Up @@ -180,7 +180,7 @@ export class VirtualGateway extends VirtualGatewayBase {
meshName: this.mesh.meshName,
spec: {
listeners: this.listeners.map(listener => listener.listener),
backendDefaults: props.backendsDefaultClientPolicy?.bind(this),
backendDefaults: props.backendDefaults?.bind(this),
logging: accessLogging !== undefined ? {
accessLog: accessLogging.virtualGatewayAccessLog,
} : undefined,
Expand Down
18 changes: 6 additions & 12 deletions packages/@aws-cdk/aws-appmesh/lib/virtual-node.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnVirtualNode } from './appmesh.generated';
import { ClientPolicy } from './client-policy';
import { Backend, BackendDefaults } from './backend';
import { IMesh, Mesh } from './mesh';
import { ServiceDiscovery } from './service-discovery';
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
Expand Down Expand Up @@ -61,7 +60,7 @@ export interface VirtualNodeBaseProps {
*
* @default - No backends
*/
readonly backends?: IVirtualService[];
readonly backends?: Backend[];

/**
* Initial listener for the virtual node
Expand All @@ -82,7 +81,7 @@ export interface VirtualNodeBaseProps {
*
* @default - No Config
*/
readonly backendsDefaultClientPolicy?: ClientPolicy;
readonly backendDefaults?: BackendDefaults;
}

/**
Expand Down Expand Up @@ -185,7 +184,7 @@ export class VirtualNode extends VirtualNodeBase {
spec: {
backends: cdk.Lazy.anyValue({ produce: () => this.backends }, { omitEmptyArray: true }),
listeners: cdk.Lazy.anyValue({ produce: () => this.listeners.map(listener => listener.listener) }, { omitEmptyArray: true }),
backendDefaults: props.backendsDefaultClientPolicy?.bind(this),
backendDefaults: props.backendDefaults?.bind(this),
serviceDiscovery: {
dns: serviceDiscovery?.dns,
awsCloudMap: serviceDiscovery?.cloudmap,
Expand Down Expand Up @@ -214,13 +213,8 @@ export class VirtualNode extends VirtualNodeBase {
/**
* Add a Virtual Services that this node is expected to send outbound traffic to
*/
public addBackend(virtualService: IVirtualService) {
this.backends.push({
virtualService: {
virtualServiceName: virtualService.virtualServiceName,
clientPolicy: virtualService.clientPolicy?.bind(this).clientPolicy,
},
});
public addBackend(backend: Backend) {
this.backends.push(backend.bind(this));
}
}

Expand Down
24 changes: 0 additions & 24 deletions packages/@aws-cdk/aws-appmesh/lib/virtual-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnVirtualService } from './appmesh.generated';
import { ClientPolicy } from './client-policy';
import { IMesh, Mesh } from './mesh';
import { IVirtualNode } from './virtual-node';
import { IVirtualRouter } from './virtual-router';
Expand All @@ -28,11 +27,6 @@ export interface IVirtualService extends cdk.IResource {
* The Mesh which the VirtualService belongs to
*/
readonly mesh: IMesh;

/**
* Client policy for this Virtual Service
*/
readonly clientPolicy?: ClientPolicy;
}

/**
Expand All @@ -50,13 +44,6 @@ export interface VirtualServiceProps {
*/
readonly virtualServiceName?: string;

/**
* Client policy for this Virtual Service
*
* @default - none
*/
readonly clientPolicy?: ClientPolicy;

/**
* The VirtualNode or VirtualRouter which the VirtualService uses as its provider
*/
Expand Down Expand Up @@ -90,7 +77,6 @@ export class VirtualService extends cdk.Resource implements IVirtualService {
return new class extends cdk.Resource implements IVirtualService {
readonly virtualServiceName = attrs.virtualServiceName;
readonly mesh = attrs.mesh;
readonly clientPolicy = attrs.clientPolicy;
readonly virtualServiceArn = cdk.Stack.of(this).formatArn({
service: 'appmesh',
resource: `mesh/${attrs.mesh.meshName}/virtualService`,
Expand All @@ -114,14 +100,11 @@ export class VirtualService extends cdk.Resource implements IVirtualService {
*/
public readonly mesh: IMesh;

public readonly clientPolicy?: ClientPolicy;

constructor(scope: Construct, id: string, props: VirtualServiceProps) {
super(scope, id, {
physicalName: props.virtualServiceName || cdk.Lazy.string({ produce: () => cdk.Names.uniqueId(this) }),
});

this.clientPolicy = props.clientPolicy;
const providerConfig = props.virtualServiceProvider.bind(this);
this.mesh = providerConfig.mesh;

Expand Down Expand Up @@ -160,13 +143,6 @@ export interface VirtualServiceAttributes {
* The Mesh which the VirtualService belongs to
*/
readonly mesh: IMesh;

/**
* Client policy for this Virtual Service
*
* @default - none
*/
readonly clientPolicy?: ClientPolicy;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-appmesh/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"dotnet": {
"namespace": "Amazon.CDK.AWS.AppMesh",
"packageId": "Amazon.CDK.AWS.AppMesh",
"iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png"
"iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png",
"signAssembly": true,
"assemblyOriginatorKeyFile": "../../key.snk"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We got rid of this - if you merge from master, you should be able to remove the "signAssembly" and "assemblyOriginatorKeyFile" keys.

},
"java": {
"package": "software.amazon.awscdk.services.appmesh",
Expand Down
14 changes: 7 additions & 7 deletions packages/@aws-cdk/aws-appmesh/test/integ.mesh.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"service16B72496E",
"VirtualServiceName"
]
}
Expand All @@ -650,7 +650,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service27C65CF7D",
alexbrjo marked this conversation as resolved.
Show resolved Hide resolved
"service2B2862B6B",
"VirtualServiceName"
]
}
Expand Down Expand Up @@ -711,7 +711,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service3859EB104",
"service3529E2EB1",
"VirtualServiceName"
]
}
Expand Down Expand Up @@ -846,7 +846,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"service16B72496E",
"VirtualServiceName"
]
}
Expand Down Expand Up @@ -883,7 +883,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"service16B72496E",
"VirtualServiceName"
]
}
Expand Down Expand Up @@ -920,7 +920,7 @@
"VirtualService": {
"VirtualServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"service16B72496E",
"VirtualServiceName"
]
}
Expand All @@ -930,7 +930,7 @@
"Match": {
"ServiceName": {
"Fn::GetAtt": [
"service6D174F83",
"service16B72496E",
"VirtualServiceName"
]
}
Expand Down
Loading