diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts index a25200ac22205..9fb5bf08ccf3a 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts @@ -154,6 +154,7 @@ interface MysqlClusterEngineBaseProps { } abstract class MySqlClusterEngineBase extends ClusterEngineBase { + public readonly engineFamily = 'MYSQL'; public readonly supportedLogTypes: string[] = ['error', 'general', 'slowquery', 'audit']; constructor(props: MysqlClusterEngineBaseProps) { @@ -493,6 +494,7 @@ class AuroraPostgresClusterEngine extends ClusterEngineBase { */ private static readonly S3_EXPORT_FEATURE_NAME = 's3Export'; + public readonly engineFamily = 'POSTGRESQL'; public readonly supportedLogTypes: string[] = ['postgresql']; constructor(version?: AuroraPostgresEngineVersion) { diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-ref.ts b/packages/@aws-cdk/aws-rds/lib/cluster-ref.ts index a464e2a0fd5c0..de1f89bd3dafa 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-ref.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-ref.ts @@ -1,6 +1,7 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import { IResource } from '@aws-cdk/core'; +import { IClusterEngine } from './cluster-engine'; import { Endpoint } from './endpoint'; import { DatabaseProxy, DatabaseProxyOptions } from './proxy'; @@ -35,6 +36,12 @@ export interface IDatabaseCluster extends IResource, ec2.IConnectable, secretsma */ readonly instanceEndpoints: Endpoint[]; + /** + * The engine of this Cluster. + * May be not known for imported Clusters if it wasn't provided explicitly. + */ + readonly engine?: IClusterEngine; + /** * Add a new db proxy to this cluster. */ @@ -92,4 +99,11 @@ export interface DatabaseClusterAttributes { * @default - no instance endpoints */ readonly instanceEndpointAddresses?: string[]; + + /** + * The engine of the existing Cluster. + * + * @default - the imported Cluster's engine is unknown + */ + readonly engine?: IClusterEngine; } diff --git a/packages/@aws-cdk/aws-rds/lib/cluster.ts b/packages/@aws-cdk/aws-rds/lib/cluster.ts index a4d01868ba5fb..3ba13451e8731 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster.ts @@ -281,7 +281,11 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC * Abstract base for ``DatabaseCluster`` and ``DatabaseClusterFromSnapshot`` */ abstract class DatabaseClusterNew extends DatabaseClusterBase { - + /** + * The engine for this Cluster. + * Never undefined. + */ + public readonly engine?: IClusterEngine; public readonly instanceIdentifiers: string[] = []; public readonly instanceEndpoints: Endpoint[] = []; @@ -331,6 +335,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { const clusterParameterGroup = props.parameterGroup ?? clusterEngineBindConfig.parameterGroup; const clusterParameterGroupConfig = clusterParameterGroup?.bindToCluster({}); + this.engine = props.engine; this.newCfnProps = { // Basic @@ -359,6 +364,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { class ImportedDatabaseCluster extends DatabaseClusterBase implements IDatabaseCluster { public readonly clusterIdentifier: string; public readonly connections: ec2.Connections; + public readonly engine?: IClusterEngine; private readonly _clusterEndpoint?: Endpoint; private readonly _clusterReadEndpoint?: Endpoint; @@ -375,6 +381,7 @@ class ImportedDatabaseCluster extends DatabaseClusterBase implements IDatabaseCl securityGroups: attrs.securityGroups, defaultPort, }); + this.engine = attrs.engine; this._clusterEndpoint = (attrs.clusterEndpointAddress && attrs.port) ? new Endpoint(attrs.clusterEndpointAddress, attrs.port) : undefined; this._clusterReadEndpoint = (attrs.readerEndpointAddress && attrs.port) ? new Endpoint(attrs.readerEndpointAddress, attrs.port) : undefined; diff --git a/packages/@aws-cdk/aws-rds/lib/engine.ts b/packages/@aws-cdk/aws-rds/lib/engine.ts index b1ccef4084c87..2feced9927ca2 100644 --- a/packages/@aws-cdk/aws-rds/lib/engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/engine.ts @@ -28,4 +28,15 @@ export interface IEngine { * (which means the major version of the engine is also not known) */ readonly parameterGroupFamily?: string; + + /** + * The family this engine belongs to, + * like "MYSQL", or "POSTGRESQL". + * This property is used when creating a Database Proxy. + * Most engines don't belong to any family + * (and because of that, you can't create Database Proxies for their Clusters or Instances). + * + * @default - the engine doesn't belong to any family + */ + readonly engineFamily?: string; } diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index 3b2310212dbf8..25370706664c7 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -109,6 +109,7 @@ interface InstanceEngineBaseProps { readonly multiUserRotationApplication: secretsmanager.SecretRotationApplication; readonly version?: EngineVersion; readonly parameterGroupFamily?: string; + readonly engineFamily?: string; readonly features?: InstanceEngineFeatures; } @@ -118,6 +119,7 @@ abstract class InstanceEngineBase implements IInstanceEngine { public readonly parameterGroupFamily?: string; public readonly singleUserRotationApplication: secretsmanager.SecretRotationApplication; public readonly multiUserRotationApplication: secretsmanager.SecretRotationApplication; + public readonly engineFamily?: string; private readonly features?: InstanceEngineFeatures; @@ -129,6 +131,7 @@ abstract class InstanceEngineBase implements IInstanceEngine { this.engineVersion = props.version; this.parameterGroupFamily = props.parameterGroupFamily ?? (this.engineVersion ? `${this.engineType}${this.engineVersion.majorVersion}` : undefined); + this.engineFamily = props.engineFamily; } public bindToInstance(_scope: core.Construct, options: InstanceEngineBindOptions): InstanceEngineConfig { @@ -391,6 +394,7 @@ class MySqlInstanceEngine extends InstanceEngineBase { majorVersion: version.mysqlMajorVersion, } : undefined, + engineFamily: 'MYSQL', }); } } @@ -586,6 +590,7 @@ class PostgresInstanceEngine extends InstanceEngineBase { } : undefined, features: version ? version?._features : { s3Import: 's3Import' }, + engineFamily: 'POSTGRESQL', }); } } diff --git a/packages/@aws-cdk/aws-rds/lib/instance.ts b/packages/@aws-cdk/aws-rds/lib/instance.ts index fa08049df2f97..bfc5ac47f1b24 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance.ts @@ -50,6 +50,13 @@ export interface IDatabaseInstance extends IResource, ec2.IConnectable, secretsm */ readonly instanceEndpoint: Endpoint; + /** + * The engine of this database Instance. + * May be not known for imported Instances if it wasn't provided explicitly, + * or for read replicas. + */ + readonly engine?: IInstanceEngine; + /** * Add a new db proxy to this instance. */ @@ -90,6 +97,13 @@ export interface DatabaseInstanceAttributes { * The security groups of the instance. */ readonly securityGroups: ec2.ISecurityGroup[]; + + /** + * The engine of the existing database Instance. + * + * @default - the imported Instance's engine is unknown + */ + readonly engine?: IInstanceEngine; } /** @@ -110,6 +124,7 @@ export abstract class DatabaseInstanceBase extends Resource implements IDatabase public readonly dbInstanceEndpointAddress = attrs.instanceEndpointAddress; public readonly dbInstanceEndpointPort = attrs.port.toString(); public readonly instanceEndpoint = new Endpoint(attrs.instanceEndpointAddress, attrs.port); + public readonly engine = attrs.engine; protected enableIamAuthentication = true; } @@ -769,6 +784,7 @@ export interface DatabaseInstanceSourceProps extends DatabaseInstanceNewProps { * A new source database instance (not a read replica) */ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDatabaseInstance { + public readonly engine?: IInstanceEngine; /** * The AWS Secrets Manager secret attached to the instance. */ @@ -785,6 +801,7 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa this.singleUserRotationApplication = props.engine.singleUserRotationApplication; this.multiUserRotationApplication = props.engine.multiUserRotationApplication; + this.engine = props.engine; let { s3ImportRole, s3ExportRole } = setupS3ImportExport(this, props, true); const engineConfig = props.engine.bindToInstance(this, { diff --git a/packages/@aws-cdk/aws-rds/lib/private/util.ts b/packages/@aws-cdk/aws-rds/lib/private/util.ts index 0caf78551b88d..a8439b652abc9 100644 --- a/packages/@aws-cdk/aws-rds/lib/private/util.ts +++ b/packages/@aws-cdk/aws-rds/lib/private/util.ts @@ -1,7 +1,7 @@ import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import { Construct, CfnDeletionPolicy, CfnResource, RemovalPolicy } from '@aws-cdk/core'; -import { IInstanceEngine } from '../instance-engine'; +import { IEngine } from '../engine'; /** Common base of `DatabaseInstanceProps` and `DatabaseClusterBaseProps` that has only the S3 props */ export interface DatabaseS3ImportExportProps { @@ -56,7 +56,7 @@ export function setupS3ImportExport( return { s3ImportRole, s3ExportRole }; } -export function engineDescription(engine: IInstanceEngine) { +export function engineDescription(engine: IEngine) { return engine.engineType + (engine.engineVersion?.fullVersion ? `-${engine.engineVersion.fullVersion}` : ''); } diff --git a/packages/@aws-cdk/aws-rds/lib/proxy.ts b/packages/@aws-cdk/aws-rds/lib/proxy.ts index 7109202019c2f..dec7df1443723 100644 --- a/packages/@aws-cdk/aws-rds/lib/proxy.ts +++ b/packages/@aws-cdk/aws-rds/lib/proxy.ts @@ -3,8 +3,10 @@ import * as iam from '@aws-cdk/aws-iam'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as cdk from '@aws-cdk/core'; import { IDatabaseCluster } from './cluster-ref'; +import { IEngine } from './engine'; import { IDatabaseInstance } from './instance'; -import { CfnDBCluster, CfnDBInstance, CfnDBProxy, CfnDBProxyTargetGroup } from './rds.generated'; +import { engineDescription } from './private/util'; +import { CfnDBProxy, CfnDBProxyTargetGroup } from './rds.generated'; /** * SessionPinningFilter @@ -47,7 +49,7 @@ export class ProxyTarget { * @param instance RDS database instance */ public static fromInstance(instance: IDatabaseInstance): ProxyTarget { - return new ProxyTarget(instance); + return new ProxyTarget(instance, undefined); } /** @@ -59,34 +61,26 @@ export class ProxyTarget { return new ProxyTarget(undefined, cluster); } - private constructor(private readonly dbInstance?: IDatabaseInstance, private readonly dbCluster?: IDatabaseCluster) {} + private constructor( + private readonly dbInstance: IDatabaseInstance | undefined, + private readonly dbCluster: IDatabaseCluster | undefined) { + } /** * Bind this target to the specified database proxy. */ public bind(_: DatabaseProxy): ProxyTargetConfig { - let engine: string | undefined; - if (this.dbCluster && this.dbInstance) { - throw new Error('Proxy cannot target both database cluster and database instance.'); - } else if (this.dbCluster) { - engine = (this.dbCluster.node.defaultChild as CfnDBCluster).engine; - } else if (this.dbInstance) { - engine = (this.dbInstance.node.defaultChild as CfnDBInstance).engine; + const engine: IEngine | undefined = this.dbInstance?.engine ?? this.dbCluster?.engine; + + if (!engine) { + const errorResource = this.dbCluster ?? this.dbInstance; + throw new Error(`Could not determine engine for proxy target '${errorResource?.node.path}'. ` + + 'Please provide it explicitly when importing the resource'); } - let engineFamily; - switch (engine) { - case 'aurora': - case 'aurora-mysql': - case 'mysql': - engineFamily = 'MYSQL'; - break; - case 'aurora-postgresql': - case 'postgres': - engineFamily = 'POSTGRESQL'; - break; - default: - throw new Error(`Unsupported engine type - ${engine}`); + const engineFamily = engine.engineFamily; + if (!engineFamily) { + throw new Error(`Engine '${engineDescription(engine)}' does not support proxies`); } return { @@ -105,12 +99,14 @@ export interface ProxyTargetConfig { * The engine family of the database instance or cluster this proxy connects with. */ readonly engineFamily: string; + /** * The database instances to which this proxy connects. * Either this or `dbClusters` will be set and the other `undefined`. * @default - `undefined` if `dbClusters` is set. */ readonly dbInstances?: IDatabaseInstance[]; + /** * The database clusters to which this proxy connects. * Either this or `dbInstances` will be set and the other `undefined`. diff --git a/packages/@aws-cdk/aws-rds/test/test.proxy.ts b/packages/@aws-cdk/aws-rds/test/test.proxy.ts index 7fa03684fa53b..db57aaf4d8b93 100644 --- a/packages/@aws-cdk/aws-rds/test/test.proxy.ts +++ b/packages/@aws-cdk/aws-rds/test/test.proxy.ts @@ -1,17 +1,25 @@ -import { ABSENT, expect, haveResource, ResourcePart } from '@aws-cdk/assert'; +import { ABSENT, expect, haveResourceLike } from '@aws-cdk/assert'; import * as ec2 from '@aws-cdk/aws-ec2'; +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as rds from '../lib'; +let stack: cdk.Stack; +let vpc: ec2.IVpc; + export = { + 'setUp'(cb: () => void) { + stack = new cdk.Stack(); + vpc = new ec2.Vpc(stack, 'VPC'); + + cb(); + }, + 'create a DB proxy from an instance'(test: Test) { // GIVEN - const stack = new cdk.Stack(); - const vpc = new ec2.Vpc(stack, 'VPC'); const instance = new rds.DatabaseInstance(stack, 'Instance', { engine: rds.DatabaseInstanceEngine.MYSQL, - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), vpc, }); @@ -23,68 +31,59 @@ export = { }); // THEN - expect(stack).to(haveResource('AWS::RDS::DBProxy', { - Properties: { - Auth: [ - { - AuthScheme: 'SECRETS', - IAMAuth: 'DISABLED', - SecretArn: { - Ref: 'InstanceSecretAttachment83BEE581', - }, + expect(stack).to(haveResourceLike('AWS::RDS::DBProxy', { + Auth: [ + { + AuthScheme: 'SECRETS', + IAMAuth: 'DISABLED', + SecretArn: { + Ref: 'InstanceSecretAttachment83BEE581', }, - ], - DBProxyName: 'Proxy', - EngineFamily: 'MYSQL', - RequireTLS: true, - RoleArn: { - 'Fn::GetAtt': [ - 'ProxyIAMRole2FE8AB0F', - 'Arn', - ], }, - VpcSubnetIds: [ - { - Ref: 'VPCPrivateSubnet1Subnet8BCA10E0', - }, - { - Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A', - }, + ], + DBProxyName: 'Proxy', + EngineFamily: 'MYSQL', + RequireTLS: true, + RoleArn: { + 'Fn::GetAtt': [ + 'ProxyIAMRole2FE8AB0F', + 'Arn', ], }, - }, ResourcePart.CompleteDefinition)); + VpcSubnetIds: [ + { + Ref: 'VPCPrivateSubnet1Subnet8BCA10E0', + }, + { + Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A', + }, + ], + })); // THEN - expect(stack).to(haveResource('AWS::RDS::DBProxyTargetGroup', { - Properties: { - DBProxyName: { - Ref: 'ProxyCB0DFB71', - }, - ConnectionPoolConfigurationInfo: {}, - DBInstanceIdentifiers: [ - { - Ref: 'InstanceC1063A87', - }, - ], - TargetGroupName: 'default', + expect(stack).to(haveResourceLike('AWS::RDS::DBProxyTargetGroup', { + DBProxyName: { + Ref: 'ProxyCB0DFB71', }, - }, ResourcePart.CompleteDefinition)); + ConnectionPoolConfigurationInfo: {}, + DBInstanceIdentifiers: [ + { + Ref: 'InstanceC1063A87', + }, + ], + TargetGroupName: 'default', + })); test.done(); }, 'create a DB proxy from a cluster'(test: Test) { // GIVEN - const stack = new cdk.Stack(); - const vpc = new ec2.Vpc(stack, 'VPC'); const cluster = new rds.DatabaseCluster(stack, 'Database', { engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_10_7, }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), - vpc, - }, + instanceProps: { vpc }, }); // WHEN @@ -95,106 +94,132 @@ export = { }); // THEN - expect(stack).to(haveResource('AWS::RDS::DBProxy', { - Properties: { - Auth: [ - { - AuthScheme: 'SECRETS', - IAMAuth: 'DISABLED', - SecretArn: { - Ref: 'DatabaseSecretAttachmentE5D1B020', - }, + expect(stack).to(haveResourceLike('AWS::RDS::DBProxy', { + Auth: [ + { + AuthScheme: 'SECRETS', + IAMAuth: 'DISABLED', + SecretArn: { + Ref: 'DatabaseSecretAttachmentE5D1B020', }, - ], - DBProxyName: 'Proxy', - EngineFamily: 'POSTGRESQL', - RequireTLS: true, - RoleArn: { - 'Fn::GetAtt': [ - 'ProxyIAMRole2FE8AB0F', - 'Arn', - ], }, - VpcSubnetIds: [ - { - Ref: 'VPCPrivateSubnet1Subnet8BCA10E0', - }, - { - Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A', - }, + ], + DBProxyName: 'Proxy', + EngineFamily: 'POSTGRESQL', + RequireTLS: true, + RoleArn: { + 'Fn::GetAtt': [ + 'ProxyIAMRole2FE8AB0F', + 'Arn', ], }, - }, ResourcePart.CompleteDefinition)); + VpcSubnetIds: [ + { + Ref: 'VPCPrivateSubnet1Subnet8BCA10E0', + }, + { + Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A', + }, + ], + })); // THEN - expect(stack).to(haveResource('AWS::RDS::DBProxyTargetGroup', { - Properties: { - DBProxyName: { - Ref: 'ProxyCB0DFB71', - }, - ConnectionPoolConfigurationInfo: {}, - DBClusterIdentifiers: [ - { - Ref: 'DatabaseB269D8BB', - }, - ], - TargetGroupName: 'default', + expect(stack).to(haveResourceLike('AWS::RDS::DBProxyTargetGroup', { + DBProxyName: { + Ref: 'ProxyCB0DFB71', }, - }, ResourcePart.CompleteDefinition)); + ConnectionPoolConfigurationInfo: {}, + DBClusterIdentifiers: [ + { + Ref: 'DatabaseB269D8BB', + }, + ], + DBInstanceIdentifiers: ABSENT, + TargetGroupName: 'default', + })); test.done(); }, - 'Cannot specify both dbInstanceIdentifiers and dbClusterIdentifiers'(test: Test) { + 'One or more secrets are required.'(test: Test) { // GIVEN - const stack = new cdk.Stack(); - const vpc = new ec2.Vpc(stack, 'VPC'); const cluster = new rds.DatabaseCluster(stack, 'Database', { - engine: rds.DatabaseClusterEngine.auroraPostgres({ - version: rds.AuroraPostgresEngineVersion.VER_10_7, - }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), - vpc, - }, + engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_10_7 }), + instanceProps: { vpc }, }); // WHEN - test.doesNotThrow(() => { + test.throws(() => { new rds.DatabaseProxy(stack, 'Proxy', { proxyTarget: rds.ProxyTarget.fromCluster(cluster), - secrets: [cluster.secret!], + secrets: [], // No secret vpc, }); - }, /Cannot specify both dbInstanceIdentifiers and dbClusterIdentifiers/); - - expect(stack).to(haveResource('AWS::RDS::DBProxyTargetGroup', { - DBInstanceIdentifiers: ABSENT, - }, ResourcePart.Properties)); + }, 'One or more secrets are required.'); test.done(); }, - 'One or more secrets are required.'(test: Test) { - // GIVEN - const stack = new cdk.Stack(); - const vpc = new ec2.Vpc(stack, 'VPC'); - const cluster = new rds.DatabaseCluster(stack, 'Database', { - engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_10_7 }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + 'fails when trying to create a proxy for a target without an engine'(test: Test) { + const importedCluster = rds.DatabaseCluster.fromDatabaseClusterAttributes(stack, 'Cluster', { + clusterIdentifier: 'my-cluster', + }); + + test.throws(() => { + new rds.DatabaseProxy(stack, 'Proxy', { + proxyTarget: rds.ProxyTarget.fromCluster(importedCluster), vpc, - }, + secrets: [new secretsmanager.Secret(stack, 'Secret')], + }); + }, /Could not determine engine for proxy target 'Default\/Cluster'\. Please provide it explicitly when importing the resource/); + + test.done(); + }, + + "fails when trying to create a proxy for a target with an engine that doesn't have engineFamily"(test: Test) { + const importedInstance = rds.DatabaseInstance.fromDatabaseInstanceAttributes(stack, 'Cluster', { + instanceIdentifier: 'my-instance', + instanceEndpointAddress: 'instance-address', + port: 5432, + securityGroups: [], + engine: rds.DatabaseInstanceEngine.mariaDb({ + version: rds.MariaDbEngineVersion.VER_10_0_24, + }), }); - // WHEN test.throws(() => { new rds.DatabaseProxy(stack, 'Proxy', { - proxyTarget: rds.ProxyTarget.fromCluster(cluster), - secrets: [], // No secret + proxyTarget: rds.ProxyTarget.fromInstance(importedInstance), vpc, + secrets: [new secretsmanager.Secret(stack, 'Secret')], }); - }, 'One or more secrets are required.'); + }, /Engine 'mariadb-10\.0\.24' does not support proxies/); + + test.done(); + }, + + 'correctly creates a proxy for an imported Cluster if its engine is known'(test: Test) { + const importedCluster = rds.DatabaseCluster.fromDatabaseClusterAttributes(stack, 'Cluster', { + clusterIdentifier: 'my-cluster', + engine: rds.DatabaseClusterEngine.auroraPostgres({ + version: rds.AuroraPostgresEngineVersion.VER_9_6_11, + }), + }); + + new rds.DatabaseProxy(stack, 'Proxy', { + proxyTarget: rds.ProxyTarget.fromCluster(importedCluster), + vpc, + secrets: [new secretsmanager.Secret(stack, 'Secret')], + }); + + expect(stack).to(haveResourceLike('AWS::RDS::DBProxy', { + EngineFamily: 'POSTGRESQL', + })); + expect(stack).to(haveResourceLike('AWS::RDS::DBProxyTargetGroup', { + DBClusterIdentifiers: [ + 'my-cluster', + ], + })); test.done(); },