diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-dual.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-dual.ts index d39d972a868c3..43284a1aa796e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-dual.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-dual.ts @@ -14,14 +14,23 @@ vpc.isolatedSubnets.forEach((subnet, idx) => { cfnSubnet.addDependsOn(ipv6); }); +const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), + isFromLegacyInstanceProps: true, +}; new rds.DatabaseCluster(stack, 'DualstackCluster', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_0 }), credentials: rds.Credentials.fromUsername('admin', { password: cdk.SecretValue.unsafePlainText('7959866cacc02c2d243ecfe177464fe6') }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), - vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, - vpc, - }, + writer: rds.ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + rds.ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, + vpc, networkType: rds.NetworkType.DUAL, removalPolicy: cdk.RemovalPolicy.DESTROY, }); @@ -29,11 +38,16 @@ new rds.DatabaseCluster(stack, 'DualstackCluster', { new rds.DatabaseCluster(stack, 'Ipv4Cluster', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_0 }), credentials: rds.Credentials.fromUsername('admin', { password: cdk.SecretValue.unsafePlainText('7959866cacc02c2d243ecfe177464fe6') }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), - vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, - vpc, - }, + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, + vpc, + writer: rds.ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + rds.ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], networkType: rds.NetworkType.IPV4, removalPolicy: cdk.RemovalPolicy.DESTROY, }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json index 6256aa3105eec..a6d7a71f73597 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json @@ -1,7 +1,7 @@ { - "version": "30.1.0", + "version": "31.0.0", "files": { - "f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490": { + "a633d33a056f9a9a775353c3902b2da4fa8318b43707e565b45a591da0888305": { "source": { "path": "aws-cdk-rds-cluster-rotation.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490.json", + "objectKey": "a633d33a056f9a9a775353c3902b2da4fa8318b43707e565b45a591da0888305.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json index 0252e7533406a..dcf03b6f8e08a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json @@ -646,10 +646,12 @@ "Type": "AWS::RDS::DBCluster", "Properties": { "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql8.0", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", "MasterUsername": { "Fn::Join": [ "", @@ -692,11 +694,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora" + "Engine": "aurora-mysql" }, "DependsOn": [ "VPCPrivateSubnet1DefaultRouteAE1D6490", @@ -713,11 +715,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora" + "Engine": "aurora-mysql" }, "DependsOn": [ "VPCPrivateSubnet1DefaultRouteAE1D6490", @@ -964,10 +966,12 @@ "Type": "AWS::RDS::DBCluster", "Properties": { "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql8.0", "DBSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "Engine": "aurora", + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", "MasterUsername": { "Fn::Join": [ "", @@ -1010,11 +1014,11 @@ "DBClusterIdentifier": { "Ref": "CustomRotationOptions7CA9E132" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "Engine": "aurora" + "Engine": "aurora-mysql" }, "DependsOn": [ "VPCPrivateSubnet1DefaultRouteAE1D6490", @@ -1031,11 +1035,11 @@ "DBClusterIdentifier": { "Ref": "CustomRotationOptions7CA9E132" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "Engine": "aurora" + "Engine": "aurora-mysql" }, "DependsOn": [ "VPCPrivateSubnet1DefaultRouteAE1D6490", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out index b72fef144f05c..7925065efbcc4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.1.0"} \ No newline at end of file +{"version":"31.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json index 5bbe8121413b0..6bb0c26d856fa 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.1.0", + "version": "31.0.0", "testCases": { "integ.cluster-rotation.lit": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json index 0da5ccc5e746a..e7c77a659a445 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.1.0", + "version": "31.0.0", "artifacts": { "aws-cdk-rds-cluster-rotation.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a633d33a056f9a9a775353c3902b2da4fa8318b43707e565b45a591da0888305.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -234,19 +234,28 @@ "/aws-cdk-rds-cluster-rotation/Database/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseB269D8BB" + "data": "DatabaseB269D8BB", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/Database/Instance1": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseInstance1844F58FD" + "data": "DatabaseInstance1844F58FD", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/Database/Instance2": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseInstance2AA380DEE" + "data": "DatabaseInstance2AA380DEE", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/Database/RotationSingleUser/SecurityGroup/Resource": [ @@ -312,19 +321,28 @@ "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Resource": [ { "type": "aws:cdk:logicalId", - "data": "CustomRotationOptions7CA9E132" + "data": "CustomRotationOptions7CA9E132", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Instance1": [ { "type": "aws:cdk:logicalId", - "data": "CustomRotationOptionsInstance1D693E87C" + "data": "CustomRotationOptionsInstance1D693E87C", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Instance2": [ { "type": "aws:cdk:logicalId", - "data": "CustomRotationOptionsInstance2A21FADD8" + "data": "CustomRotationOptionsInstance2A21FADD8", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/RotationSingleUser/SARMapping": [ @@ -350,24 +368,6 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } - ], - "DatabaseSecretAttachmentPolicy5ACFE6CA": [ - { - "type": "aws:cdk:logicalId", - "data": "DatabaseSecretAttachmentPolicy5ACFE6CA", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" - ] - } - ], - "CustomRotationOptionsSecretAttachmentPolicyAB818C64": [ - { - "type": "aws:cdk:logicalId", - "data": "CustomRotationOptionsSecretAttachmentPolicyAB818C64", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" - ] - } ] }, "displayName": "aws-cdk-rds-cluster-rotation" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json index 5eefe4ba0e14b..49635bd17853e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json @@ -31,8 +31,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPC", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet1": { @@ -75,16 +75,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-cluster-rotation/VPC/PublicSubnet1/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -105,8 +105,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -124,8 +124,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -144,8 +144,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -164,8 +164,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -192,14 +192,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet2": { @@ -242,16 +242,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-cluster-rotation/VPC/PublicSubnet2/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -272,8 +272,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -291,8 +291,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -311,8 +311,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -331,8 +331,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -359,14 +359,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet1": { @@ -409,16 +409,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-cluster-rotation/VPC/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -439,8 +439,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -458,8 +458,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -478,14 +478,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet2": { @@ -528,16 +528,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-cluster-rotation/VPC/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -558,8 +558,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -577,8 +577,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -597,14 +597,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "IGW": { @@ -622,8 +622,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "VPCGW": { @@ -641,14 +641,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.Vpc", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SecurityGroup": { @@ -675,14 +675,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Endpoint": { @@ -741,14 +741,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -793,14 +793,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPCEndpoint", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.InterfaceVpcEndpoint", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Database": { @@ -829,14 +829,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBSubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.SubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SecurityGroup": { @@ -863,8 +863,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "from awscdkrdsclusterrotationDatabaseRotationSingleUserSecurityGroup0FFF34B1:{IndirectPort}": { @@ -902,14 +902,22 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "aws-cdk-rds-cluster-rotation/Database/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Secret": { @@ -942,8 +950,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Attachment": { @@ -966,8 +974,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnSecretTargetAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationSchedule": { @@ -995,20 +1003,20 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnRotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Policy": { @@ -1055,20 +1063,20 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -1078,10 +1086,12 @@ "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql8.0", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", "masterUsername": { "Fn::Join": [ "", @@ -1117,8 +1127,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance1Wrapper": { + "id": "Instance1Wrapper", + "path": "aws-cdk-rds-cluster-rotation/Database/Instance1Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance1": { @@ -1130,16 +1148,24 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora" + "engine": "aurora-mysql" } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance2Wrapper": { + "id": "Instance2Wrapper", + "path": "aws-cdk-rds-cluster-rotation/Database/Instance2Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance2": { @@ -1151,16 +1177,16 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora" + "engine": "aurora-mysql" } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationSingleUser": { @@ -1191,22 +1217,22 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SARMapping": { "id": "SARMapping", "path": "aws-cdk-rds-cluster-rotation/Database/RotationSingleUser/SARMapping", "constructInfo": { - "fqn": "@aws-cdk/core.CfnMapping", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -1277,28 +1303,28 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-sam.CfnApplication", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationLambda": { "id": "RotationLambda", "path": "aws-cdk-rds-cluster-rotation/Database/RotationSingleUser/RotationLambda", "constructInfo": { - "fqn": "@aws-cdk/aws-lambda.FunctionBase", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretRotation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "CustomRotationOptions": { @@ -1327,14 +1353,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBSubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.SubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SecurityGroup": { @@ -1361,8 +1387,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "from awscdkrdsclusterrotationSecurityGroupB986D266:{IndirectPort}": { @@ -1400,14 +1426,22 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Secret": { @@ -1440,8 +1474,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Attachment": { @@ -1464,8 +1498,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnSecretTargetAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationSchedule": { @@ -1493,20 +1527,20 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnRotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Policy": { @@ -1553,20 +1587,20 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -1576,10 +1610,12 @@ "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql8.0", "dbSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "engine": "aurora", + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", "masterUsername": { "Fn::Join": [ "", @@ -1615,8 +1651,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance1Wrapper": { + "id": "Instance1Wrapper", + "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Instance1Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance1": { @@ -1628,16 +1672,24 @@ "dbClusterIdentifier": { "Ref": "CustomRotationOptions7CA9E132" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "engine": "aurora" + "engine": "aurora-mysql" } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance2Wrapper": { + "id": "Instance2Wrapper", + "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Instance2Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance2": { @@ -1649,16 +1701,16 @@ "dbClusterIdentifier": { "Ref": "CustomRotationOptions7CA9E132" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, - "engine": "aurora" + "engine": "aurora-mysql" } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationSingleUser": { @@ -1669,8 +1721,8 @@ "id": "SARMapping", "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/RotationSingleUser/SARMapping", "constructInfo": { - "fqn": "@aws-cdk/core.CfnMapping", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -1745,50 +1797,50 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-sam.CfnApplication", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RotationLambda": { "id": "RotationLambda", "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/RotationSingleUser/RotationLambda", "constructInfo": { - "fqn": "@aws-cdk/aws-lambda.FunctionBase", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretRotation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "aws-cdk-rds-cluster-rotation/BootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "aws-cdk-rds-cluster-rotation/CheckBootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Tree": { @@ -1796,13 +1848,13 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.252" + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.App", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.ts index 0aaa529fb9b8e..00bde4a53f5cf 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-rotation.lit.ts @@ -13,22 +13,40 @@ const endpoint = new ec2.InterfaceVpcEndpoint(stack, 'Endpoint', { }); /// !show +const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), + isFromLegacyInstanceProps: true, +}; const cluster = new rds.DatabaseCluster(stack, 'Database', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpc, - }, + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), + vpc, + writer: rds.ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + rds.ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], }); cluster.addRotationSingleUser(); const clusterWithCustomRotationOptions = new rds.DatabaseCluster(stack, 'CustomRotationOptions', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpc, - }, + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), + vpc, + writer: rds.ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + rds.ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], }); clusterWithCustomRotationOptions.addRotationSingleUser({ automaticallyAfter: cdk.Duration.days(7), diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.assets.json index 49bd5c22f83d4..5118531d2bf72 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "31.0.0", "files": { - "8182c8bf4e17962cb28aa684c91f0d422b58d2f454a7088dc2ceebd8f32e89d7": { + "847a7253a365d747181fde2a1ce016fb160617357972f277a1dc32b6a4e60587": { "source": { "path": "aws-cdk-rds-s3-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8182c8bf4e17962cb28aa684c91f0d422b58d2f454a7088dc2ceebd8f32e89d7.json", + "objectKey": "847a7253a365d747181fde2a1ce016fb160617357972f277a1dc32b6a4e60587.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.template.json index 38bd36b82fa75..4e07f44f347c8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/aws-cdk-rds-s3-integ.template.json @@ -543,40 +543,7 @@ ] } ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "DatabaseS3ImportRoleDefaultPolicyA60A7342", - "Roles": [ - { - "Ref": "DatabaseS3ImportRole377BC9C0" - } - ] - } - }, - "DatabaseS3ExportRole9E328562": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "rds.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - } - } - }, - "DatabaseS3ExportRoleDefaultPolicy8FEADB68": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ + }, { "Action": [ "s3:Abort*", @@ -617,10 +584,10 @@ ], "Version": "2012-10-17" }, - "PolicyName": "DatabaseS3ExportRoleDefaultPolicy8FEADB68", + "PolicyName": "DatabaseS3ImportRoleDefaultPolicyA60A7342", "Roles": [ { - "Ref": "DatabaseS3ExportRole9E328562" + "Ref": "DatabaseS3ImportRole377BC9C0" } ] } @@ -628,20 +595,14 @@ "DatabaseClusterParameterGroupF2A52087": { "Type": "AWS::RDS::DBClusterParameterGroup", "Properties": { - "Description": "Cluster parameter group for aurora5.6", - "Family": "aurora5.6", + "Description": "Cluster parameter group for aurora-mysql8.0", + "Family": "aurora-mysql8.0", "Parameters": { - "aurora_load_from_s3_role": { + "aws_default_s3_role": { "Fn::GetAtt": [ "DatabaseS3ImportRole377BC9C0", "Arn" ] - }, - "aurora_select_into_s3_role": { - "Fn::GetAtt": [ - "DatabaseS3ExportRole9E328562", - "Arn" - ] } } } @@ -649,7 +610,6 @@ "DatabaseB269D8BB": { "Type": "AWS::RDS::DBCluster", "Properties": { - "Engine": "aurora", "AssociatedRoles": [ { "RoleArn": { @@ -658,14 +618,6 @@ "Arn" ] } - }, - { - "RoleArn": { - "Fn::GetAtt": [ - "DatabaseS3ExportRole9E328562", - "Arn" - ] - } } ], "CopyTagsToSnapshot": true, @@ -675,6 +627,8 @@ "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", "KmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -702,11 +656,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", "PubliclyAccessible": true }, "DependsOn": [ @@ -724,11 +678,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", "PubliclyAccessible": true }, "DependsOn": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/cdk.out index 588d7b269d34f..7925065efbcc4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"31.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/integ.json index ea9819fe78ff3..66199c33ae19e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "31.0.0", "testCases": { "integ.cluster-s3": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/manifest.json index caab81f394ff5..924980aa659b2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "31.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-rds-s3-integ.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8182c8bf4e17962cb28aa684c91f0d422b58d2f454a7088dc2ceebd8f32e89d7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/847a7253a365d747181fde2a1ce016fb160617357972f277a1dc32b6a4e60587.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -225,40 +219,40 @@ "data": "DatabaseS3ImportRoleDefaultPolicyA60A7342" } ], - "/aws-cdk-rds-s3-integ/Database/S3ExportRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "DatabaseS3ExportRole9E328562" - } - ], - "/aws-cdk-rds-s3-integ/Database/S3ExportRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "DatabaseS3ExportRoleDefaultPolicy8FEADB68" - } - ], "/aws-cdk-rds-s3-integ/Database/ClusterParameterGroup/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseClusterParameterGroupF2A52087" + "data": "DatabaseClusterParameterGroupF2A52087", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] } ], "/aws-cdk-rds-s3-integ/Database/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseB269D8BB" + "data": "DatabaseB269D8BB", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-s3-integ/Database/Instance1": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseInstance1844F58FD" + "data": "DatabaseInstance1844F58FD", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-s3-integ/Database/Instance2": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseInstance2AA380DEE" + "data": "DatabaseInstance2AA380DEE", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/aws-cdk-rds-s3-integ/BootstrapVersion": [ @@ -272,9 +266,33 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "DatabaseS3ExportRole9E328562": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseS3ExportRole9E328562", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "DatabaseS3ExportRoleDefaultPolicy8FEADB68": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseS3ExportRoleDefaultPolicy8FEADB68", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "aws-cdk-rds-s3-integ" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/tree.json index 729fe5d691188..01f4dd8f3a06b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-rds-s3-integ": { "id": "aws-cdk-rds-s3-integ", "path": "aws-cdk-rds-s3-integ", @@ -39,8 +31,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPC", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet1": { @@ -83,8 +75,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { @@ -92,7 +84,7 @@ "path": "aws-cdk-rds-s3-integ/VPC/PublicSubnet1/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" } }, "RouteTable": { @@ -113,8 +105,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -132,8 +124,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -152,8 +144,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -172,8 +164,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -200,14 +192,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet2": { @@ -250,8 +242,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { @@ -259,7 +251,7 @@ "path": "aws-cdk-rds-s3-integ/VPC/PublicSubnet2/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" } }, "RouteTable": { @@ -280,8 +272,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -299,8 +291,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -319,8 +311,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -339,8 +331,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -367,14 +359,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet1": { @@ -417,8 +409,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { @@ -426,7 +418,7 @@ "path": "aws-cdk-rds-s3-integ/VPC/PrivateSubnet1/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" } }, "RouteTable": { @@ -447,8 +439,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -466,8 +458,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -486,14 +478,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet2": { @@ -536,8 +528,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { @@ -545,7 +537,7 @@ "path": "aws-cdk-rds-s3-integ/VPC/PrivateSubnet2/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" } }, "RouteTable": { @@ -566,8 +558,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -585,8 +577,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -605,14 +597,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "IGW": { @@ -630,8 +622,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "VPCGW": { @@ -649,14 +641,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.Vpc", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DbSecurity": { @@ -700,14 +692,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-kms.CfnKey", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-kms.Key", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "ImportBucket": { @@ -722,14 +714,14 @@ "aws:cdk:cloudformation:props": {} }, "constructInfo": { - "fqn": "@aws-cdk/aws-s3.CfnBucket", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-s3.Bucket", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "ExportBucket": { @@ -744,14 +736,14 @@ "aws:cdk:cloudformation:props": {} }, "constructInfo": { - "fqn": "@aws-cdk/aws-s3.CfnBucket", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-s3.Bucket", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Database": { @@ -780,14 +772,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBSubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.SubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SecurityGroup": { @@ -814,8 +806,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "from 0.0.0.0_0:{IndirectPort}": { @@ -848,20 +840,28 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "S3ImportRole": { "id": "S3ImportRole", "path": "aws-cdk-rds-s3-integ/Database/S3ImportRole", "children": { + "ImportS3ImportRole": { + "id": "ImportS3ImportRole", + "path": "aws-cdk-rds-s3-integ/Database/S3ImportRole/ImportS3ImportRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-rds-s3-integ/Database/S3ImportRole/Resource", @@ -883,8 +883,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultPolicy": { @@ -928,76 +928,7 @@ ] } ] - } - ], - "Version": "2012-10-17" - }, - "policyName": "DatabaseS3ImportRoleDefaultPolicyA60A7342", - "roles": [ - { - "Ref": "DatabaseS3ImportRole377BC9C0" - } - ] - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnPolicy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Policy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Role", - "version": "0.0.0" - } - }, - "S3ExportRole": { - "id": "S3ExportRole", - "path": "aws-cdk-rds-s3-integ/Database/S3ExportRole", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-s3-integ/Database/S3ExportRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "rds.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnRole", - "version": "0.0.0" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "aws-cdk-rds-s3-integ/Database/S3ExportRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-s3-integ/Database/S3ExportRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ + }, { "Action": [ "s3:Abort*", @@ -1038,29 +969,37 @@ ], "Version": "2012-10-17" }, - "policyName": "DatabaseS3ExportRoleDefaultPolicy8FEADB68", + "policyName": "DatabaseS3ImportRoleDefaultPolicyA60A7342", "roles": [ { - "Ref": "DatabaseS3ExportRole9E328562" + "Ref": "DatabaseS3ImportRole377BC9C0" } ] } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "aws-cdk-rds-s3-integ/Database/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "ClusterParameterGroup": { @@ -1073,33 +1012,27 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBClusterParameterGroup", "aws:cdk:cloudformation:props": { - "description": "Cluster parameter group for aurora5.6", - "family": "aurora5.6", + "description": "Cluster parameter group for aurora-mysql8.0", + "family": "aurora-mysql8.0", "parameters": { - "aurora_load_from_s3_role": { + "aws_default_s3_role": { "Fn::GetAtt": [ "DatabaseS3ImportRole377BC9C0", "Arn" ] - }, - "aurora_select_into_s3_role": { - "Fn::GetAtt": [ - "DatabaseS3ExportRole9E328562", - "Arn" - ] } } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBClusterParameterGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.ParameterGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -1108,7 +1041,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { - "engine": "aurora", "associatedRoles": [ { "roleArn": { @@ -1117,14 +1049,6 @@ "Arn" ] } - }, - { - "roleArn": { - "Fn::GetAtt": [ - "DatabaseS3ExportRole9E328562", - "Arn" - ] - } } ], "copyTagsToSnapshot": true, @@ -1134,6 +1058,8 @@ "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", "kmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -1154,8 +1080,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance1Wrapper": { + "id": "Instance1Wrapper", + "path": "aws-cdk-rds-s3-integ/Database/Instance1Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance1": { @@ -1167,17 +1101,25 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", "publiclyAccessible": true } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance2Wrapper": { + "id": "Instance2Wrapper", + "path": "aws-cdk-rds-s3-integ/Database/Instance2Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance2": { @@ -1189,35 +1131,59 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", "publiclyAccessible": true } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-rds-s3-integ/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-rds-s3-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.270" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.mysql-8.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.mysql-8.ts index f47303d31f581..bb5b55aba0d19 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.mysql-8.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.mysql-8.ts @@ -18,8 +18,8 @@ new rds.DatabaseCluster(stack, 'Database', { credentials: rds.Credentials.fromUsername('admin', { password: cdk.SecretValue.plainText('7959866cacc02c2d243ecfe177464fe6'), }), - instances: 1, - instanceProps: { vpc }, + writer: rds.ClusterInstance.provisioned('Instance1', { isFromLegacyInstanceProps: true }), + vpc, s3ImportBuckets: [importExportBucket], s3ExportBuckets: [importExportBucket], }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.ts index 88f49e17d23fb..174df236c0b03 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-s3.ts @@ -2,7 +2,7 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as kms from 'aws-cdk-lib/aws-kms'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; -import { Credentials, DatabaseCluster, DatabaseClusterEngine } from 'aws-cdk-lib/aws-rds'; +import { AuroraMysqlEngineVersion, ClusterInstance, Credentials, DatabaseCluster, DatabaseClusterEngine } from 'aws-cdk-lib/aws-rds'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-rds-s3-integ'); @@ -14,14 +14,25 @@ const kmsKey = new kms.Key(stack, 'DbSecurity'); const importBucket = new s3.Bucket(stack, 'ImportBucket'); const exportBucket = new s3.Bucket(stack, 'ExportBucket'); +const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), + isFromLegacyInstanceProps: true, +}; const cluster = new DatabaseCluster(stack, 'Database', { - engine: DatabaseClusterEngine.AURORA, credentials: Credentials.fromUsername('admin', { password: cdk.SecretValue.unsafePlainText('7959866cacc02c2d243ecfe177464fe6') }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, - vpc, - }, + engine: DatabaseClusterEngine.auroraMysql({ + version: AuroraMysqlEngineVersion.VER_3_03_0, + }), + vpc, + writer: ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, storageEncryptionKey: kmsKey, s3ImportBuckets: [importBucket], s3ExportBuckets: [exportBucket], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/__entrypoint__.js new file mode 100644 index 0000000000000..c83ecebaaadac --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/__entrypoint__.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/index.js new file mode 100644 index 0000000000000..cf597f535efd3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd/index.js @@ -0,0 +1,81 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.handler = void 0; +// eslint-disable-next-line import/no-extraneous-dependencies +const aws_sdk_1 = require("aws-sdk"); +const ec2 = new aws_sdk_1.EC2(); +/** + * The default security group ingress rule. This can be used to both revoke and authorize the rules + */ +function ingressRuleParams(groupId, account) { + return { + GroupId: groupId, + IpPermissions: [{ + UserIdGroupPairs: [{ + GroupId: groupId, + UserId: account, + }], + IpProtocol: '-1', + }], + }; +} +/** + * The default security group egress rule. This can be used to both revoke and authorize the rules + */ +function egressRuleParams(groupId) { + return { + GroupId: groupId, + IpPermissions: [{ + IpRanges: [{ + CidrIp: '0.0.0.0/0', + }], + IpProtocol: '-1', + }], + }; +} +/** + * Process a custom resource request to restrict the default security group + * ingress & egress rules. + * + * When someone turns off the property then this custom resource will be deleted in which + * case we should add back the rules that were removed. + */ +async function handler(event) { + const securityGroupId = event.ResourceProperties.DefaultSecurityGroupId; + const account = event.ResourceProperties.Account; + switch (event.RequestType) { + case 'Create': + return revokeRules(securityGroupId, account); + case 'Update': + return onUpdate(event); + case 'Delete': + return authorizeRules(securityGroupId, account); + } +} +exports.handler = handler; +async function onUpdate(event) { + const oldSg = event.OldResourceProperties.DefaultSecurityGroupId; + const newSg = event.ResourceProperties.DefaultSecurityGroupId; + if (oldSg !== newSg) { + await authorizeRules(oldSg, event.ResourceProperties.Account); + await revokeRules(newSg, event.ResourceProperties.Account); + } + return; +} +/** + * Revoke both ingress and egress rules + */ +async function revokeRules(groupId, account) { + await ec2.revokeSecurityGroupEgress(egressRuleParams(groupId)).promise(); + await ec2.revokeSecurityGroupIngress(ingressRuleParams(groupId, account)).promise(); + return; +} +/** + * Authorize both ingress and egress rules + */ +async function authorizeRules(groupId, account) { + await ec2.authorizeSecurityGroupIngress(ingressRuleParams(groupId, account)).promise(); + await ec2.authorizeSecurityGroupEgress(egressRuleParams(groupId)).promise(); + return; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQThCO0FBRTlCLE1BQU0sR0FBRyxHQUFHLElBQUksYUFBRyxFQUFFLENBQUM7QUFFdEI7O0dBRUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLE9BQWUsRUFBRSxPQUFlO0lBQ3pELE9BQU87UUFDTCxPQUFPLEVBQUUsT0FBTztRQUNoQixhQUFhLEVBQUUsQ0FBQztnQkFDZCxnQkFBZ0IsRUFBRSxDQUFDO3dCQUNqQixPQUFPLEVBQUUsT0FBTzt3QkFDaEIsTUFBTSxFQUFFLE9BQU87cUJBQ2hCLENBQUM7Z0JBQ0YsVUFBVSxFQUFFLElBQUk7YUFDakIsQ0FBQztLQUNILENBQUM7QUFDSixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLE9BQWU7SUFDdkMsT0FBTztRQUNMLE9BQU8sRUFBRSxPQUFPO1FBQ2hCLGFBQWEsRUFBRSxDQUFDO2dCQUNkLFFBQVEsRUFBRSxDQUFDO3dCQUNULE1BQU0sRUFBRSxXQUFXO3FCQUNwQixDQUFDO2dCQUNGLFVBQVUsRUFBRSxJQUFJO2FBQ2pCLENBQUM7S0FDSCxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLHNCQUFzQixDQUFDO0lBQ3hFLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7SUFDakQsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUTtZQUNYLE9BQU8sV0FBVyxDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMvQyxLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPLGNBQWMsQ0FBQyxlQUFlLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDbkQ7QUFDSCxDQUFDO0FBWEQsMEJBV0M7QUFDRCxLQUFLLFVBQVUsUUFBUSxDQUFDLEtBQXdEO0lBQzlFLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxzQkFBc0IsQ0FBQztJQUNqRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsc0JBQXNCLENBQUM7SUFDOUQsSUFBSSxLQUFLLEtBQUssS0FBSyxFQUFFO1FBQ25CLE1BQU0sY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUQsTUFBTSxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUM1RDtJQUNELE9BQU87QUFDVCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsV0FBVyxDQUFDLE9BQWUsRUFBRSxPQUFlO0lBQ3pELE1BQU0sR0FBRyxDQUFDLHlCQUF5QixDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDekUsTUFBTSxHQUFHLENBQUMsMEJBQTBCLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsT0FBTztBQUNULENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxjQUFjLENBQUMsT0FBZSxFQUFFLE9BQWU7SUFDNUQsTUFBTSxHQUFHLENBQUMsNkJBQTZCLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDdkYsTUFBTSxHQUFHLENBQUMsNEJBQTRCLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM1RSxPQUFPO0FBQ1QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB7IEVDMiB9IGZyb20gJ2F3cy1zZGsnO1xuXG5jb25zdCBlYzIgPSBuZXcgRUMyKCk7XG5cbi8qKlxuICogVGhlIGRlZmF1bHQgc2VjdXJpdHkgZ3JvdXAgaW5ncmVzcyBydWxlLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGJvdGggcmV2b2tlIGFuZCBhdXRob3JpemUgdGhlIHJ1bGVzXG4gKi9cbmZ1bmN0aW9uIGluZ3Jlc3NSdWxlUGFyYW1zKGdyb3VwSWQ6IHN0cmluZywgYWNjb3VudDogc3RyaW5nKTogRUMyLlJldm9rZVNlY3VyaXR5R3JvdXBJbmdyZXNzUmVxdWVzdCB8IEVDMi5BdXRob3JpemVTZWN1cml0eUdyb3VwSW5ncmVzc1JlcXVlc3Qge1xuICByZXR1cm4ge1xuICAgIEdyb3VwSWQ6IGdyb3VwSWQsXG4gICAgSXBQZXJtaXNzaW9uczogW3tcbiAgICAgIFVzZXJJZEdyb3VwUGFpcnM6IFt7XG4gICAgICAgIEdyb3VwSWQ6IGdyb3VwSWQsXG4gICAgICAgIFVzZXJJZDogYWNjb3VudCxcbiAgICAgIH1dLFxuICAgICAgSXBQcm90b2NvbDogJy0xJyxcbiAgICB9XSxcbiAgfTtcbn1cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBzZWN1cml0eSBncm91cCBlZ3Jlc3MgcnVsZS4gVGhpcyBjYW4gYmUgdXNlZCB0byBib3RoIHJldm9rZSBhbmQgYXV0aG9yaXplIHRoZSBydWxlc1xuICovXG5mdW5jdGlvbiBlZ3Jlc3NSdWxlUGFyYW1zKGdyb3VwSWQ6IHN0cmluZyk6IEVDMi5SZXZva2VTZWN1cml0eUdyb3VwRWdyZXNzUmVxdWVzdCB8IEVDMi5BdXRob3JpemVTZWN1cml0eUdyb3VwRWdyZXNzUmVxdWVzdCB7XG4gIHJldHVybiB7XG4gICAgR3JvdXBJZDogZ3JvdXBJZCxcbiAgICBJcFBlcm1pc3Npb25zOiBbe1xuICAgICAgSXBSYW5nZXM6IFt7XG4gICAgICAgIENpZHJJcDogJzAuMC4wLjAvMCcsXG4gICAgICB9XSxcbiAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgfV0sXG4gIH07XG59XG5cbi8qKlxuICogUHJvY2VzcyBhIGN1c3RvbSByZXNvdXJjZSByZXF1ZXN0IHRvIHJlc3RyaWN0IHRoZSBkZWZhdWx0IHNlY3VyaXR5IGdyb3VwXG4gKiBpbmdyZXNzICYgZWdyZXNzIHJ1bGVzLlxuICpcbiAqIFdoZW4gc29tZW9uZSB0dXJucyBvZmYgdGhlIHByb3BlcnR5IHRoZW4gdGhpcyBjdXN0b20gcmVzb3VyY2Ugd2lsbCBiZSBkZWxldGVkIGluIHdoaWNoXG4gKiBjYXNlIHdlIHNob3VsZCBhZGQgYmFjayB0aGUgcnVsZXMgdGhhdCB3ZXJlIHJlbW92ZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHNlY3VyaXR5R3JvdXBJZCA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5EZWZhdWx0U2VjdXJpdHlHcm91cElkO1xuICBjb25zdCBhY2NvdW50ID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkFjY291bnQ7XG4gIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICBjYXNlICdDcmVhdGUnOlxuICAgICAgcmV0dXJuIHJldm9rZVJ1bGVzKHNlY3VyaXR5R3JvdXBJZCwgYWNjb3VudCk7XG4gICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgIHJldHVybiBvblVwZGF0ZShldmVudCk7XG4gICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgIHJldHVybiBhdXRob3JpemVSdWxlcyhzZWN1cml0eUdyb3VwSWQsIGFjY291bnQpO1xuICB9XG59XG5hc3luYyBmdW5jdGlvbiBvblVwZGF0ZShldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBvbGRTZyA9IGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcy5EZWZhdWx0U2VjdXJpdHlHcm91cElkO1xuICBjb25zdCBuZXdTZyA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5EZWZhdWx0U2VjdXJpdHlHcm91cElkO1xuICBpZiAob2xkU2cgIT09IG5ld1NnKSB7XG4gICAgYXdhaXQgYXV0aG9yaXplUnVsZXMob2xkU2csIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5BY2NvdW50KTtcbiAgICBhd2FpdCByZXZva2VSdWxlcyhuZXdTZywgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkFjY291bnQpO1xuICB9XG4gIHJldHVybjtcbn1cblxuLyoqXG4gKiBSZXZva2UgYm90aCBpbmdyZXNzIGFuZCBlZ3Jlc3MgcnVsZXNcbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmV2b2tlUnVsZXMoZ3JvdXBJZDogc3RyaW5nLCBhY2NvdW50OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgZWMyLnJldm9rZVNlY3VyaXR5R3JvdXBFZ3Jlc3MoZWdyZXNzUnVsZVBhcmFtcyhncm91cElkKSkucHJvbWlzZSgpO1xuICBhd2FpdCBlYzIucmV2b2tlU2VjdXJpdHlHcm91cEluZ3Jlc3MoaW5ncmVzc1J1bGVQYXJhbXMoZ3JvdXBJZCwgYWNjb3VudCkpLnByb21pc2UoKTtcbiAgcmV0dXJuO1xufVxuXG4vKipcbiAqIEF1dGhvcml6ZSBib3RoIGluZ3Jlc3MgYW5kIGVncmVzcyBydWxlc1xuICovXG5hc3luYyBmdW5jdGlvbiBhdXRob3JpemVSdWxlcyhncm91cElkOiBzdHJpbmcsIGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBlYzIuYXV0aG9yaXplU2VjdXJpdHlHcm91cEluZ3Jlc3MoaW5ncmVzc1J1bGVQYXJhbXMoZ3JvdXBJZCwgYWNjb3VudCkpLnByb21pc2UoKTtcbiAgYXdhaXQgZWMyLmF1dGhvcml6ZVNlY3VyaXR5R3JvdXBFZ3Jlc3MoZWdyZXNzUnVsZVBhcmFtcyhncm91cElkKSkucHJvbWlzZSgpO1xuICByZXR1cm47XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/cdk.out new file mode 100644 index 0000000000000..f0b901e7c06e5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"32.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.assets.json new file mode 100644 index 0000000000000..433c4a35e9762 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.assets.json @@ -0,0 +1,32 @@ +{ + "version": "32.0.0", + "files": { + "ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd": { + "source": { + "path": "asset.ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "bffc468fc464208b727e3300214b3102d30e6f4d749531331ef45d2da89cae51": { + "source": { + "path": "integ-aurora-serverlessv2-cluster.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bffc468fc464208b727e3300214b3102d30e6f4d749531331ef45d2da89cae51.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.template.json new file mode 100644 index 0000000000000..251ce03637f86 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ-aurora-serverlessv2-cluster.template.json @@ -0,0 +1,1146 @@ +{ + "Resources": { + "IntegVPC2FF1AB0E": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC" + } + ] + } + }, + "IntegVPCPublicSubnet1SubnetE05F7E7D": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "IntegVPCPublicSubnet1RouteTable622895C7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "IntegVPCPublicSubnet1RouteTableAssociation0E84800B": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPublicSubnet1RouteTable622895C7" + }, + "SubnetId": { + "Ref": "IntegVPCPublicSubnet1SubnetE05F7E7D" + } + } + }, + "IntegVPCPublicSubnet1DefaultRouteE885D95E": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPublicSubnet1RouteTable622895C7" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + }, + "DependsOn": [ + "IntegVPCVPCGW4DD476C7" + ] + }, + "IntegVPCPublicSubnet1EIP1AC057E9": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "IntegVPCPublicSubnet1NATGateway380AC0A0": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "IntegVPCPublicSubnet1SubnetE05F7E7D" + }, + "AllocationId": { + "Fn::GetAtt": [ + "IntegVPCPublicSubnet1EIP1AC057E9", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "IntegVPCPublicSubnet1DefaultRouteE885D95E", + "IntegVPCPublicSubnet1RouteTableAssociation0E84800B" + ] + }, + "IntegVPCPublicSubnet2Subnet9648DE97": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "IntegVPCPublicSubnet2RouteTableB79B3910": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "IntegVPCPublicSubnet2RouteTableAssociation831EA0CC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPublicSubnet2RouteTableB79B3910" + }, + "SubnetId": { + "Ref": "IntegVPCPublicSubnet2Subnet9648DE97" + } + } + }, + "IntegVPCPublicSubnet2DefaultRoute2FC4B163": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPublicSubnet2RouteTableB79B3910" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + }, + "DependsOn": [ + "IntegVPCVPCGW4DD476C7" + ] + }, + "IntegVPCPublicSubnet2EIPEA07DF99": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "IntegVPCPublicSubnet2NATGateway912800A3": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "IntegVPCPublicSubnet2Subnet9648DE97" + }, + "AllocationId": { + "Fn::GetAtt": [ + "IntegVPCPublicSubnet2EIPEA07DF99", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "IntegVPCPublicSubnet2DefaultRoute2FC4B163", + "IntegVPCPublicSubnet2RouteTableAssociation831EA0CC" + ] + }, + "IntegVPCPrivateSubnet1SubnetD5B61223": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1" + } + ] + } + }, + "IntegVPCPrivateSubnet1RouteTableF2678D77": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1" + } + ] + } + }, + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPrivateSubnet1RouteTableF2678D77" + }, + "SubnetId": { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + } + } + }, + "IntegVPCPrivateSubnet1DefaultRoute140D7A84": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPrivateSubnet1RouteTableF2678D77" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "IntegVPCPublicSubnet1NATGateway380AC0A0" + } + } + }, + "IntegVPCPrivateSubnet2SubnetFCC4EF23": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2" + } + ] + } + }, + "IntegVPCPrivateSubnet2RouteTable4132D373": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2" + } + ] + } + }, + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPrivateSubnet2RouteTable4132D373" + }, + "SubnetId": { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + } + }, + "IntegVPCPrivateSubnet2DefaultRouteAE44E307": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "IntegVPCPrivateSubnet2RouteTable4132D373" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "IntegVPCPublicSubnet2NATGateway912800A3" + } + } + }, + "IntegVPCIGW02FC78B6": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-aurora-serverlessv2-cluster/Integ-VPC" + } + ] + } + }, + "IntegVPCVPCGW4DD476C7": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "InternetGatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + } + }, + "IntegVPCRestrictDefaultSecurityGroupCustomResource42DF8AB1": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "IntegVPC2FF1AB0E", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "IntegVPC2FF1AB0E", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "ba598c1f1d84f7077ea9c16a6b921e4f8acf18e996100e72a8f17da980e64fdd.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": "nodejs16.x", + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + }, + "integauroraserverlessv20IntegClusterSubnets2462DA9D": { + "Type": "AWS::RDS::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "Subnets for Integ-Cluster database", + "SubnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "integauroraserverlessv20IntegClusterSecurityGroup0FF1F93F": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "RDS security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "integauroraserverlessv20IntegClusterSecretB9E432EB": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "GenerateSecretString": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\"username\":\"admin\"}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv20IntegClusterSecretAttachmentABF2342B": { + "Type": "AWS::SecretsManager::SecretTargetAttachment", + "Properties": { + "SecretId": { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + "TargetId": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + }, + "TargetType": "AWS::RDS::DBCluster" + } + }, + "integauroraserverlessv20IntegCluster5133790E": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql8.0", + "DBSubnetGroupName": { + "Ref": "integauroraserverlessv20IntegClusterSubnets2462DA9D" + }, + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", + "MasterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + ":SecretString:username::}}" + ] + ] + }, + "MasterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + ":SecretString:password::}}" + ] + ] + }, + "ServerlessV2ScalingConfiguration": { + "MaxCapacity": 2, + "MinCapacity": 0.5 + }, + "VpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv20IntegClusterSecurityGroup0FF1F93F", + "GroupId" + ] + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv20IntegClusterwriter68858AE9": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + }, + "DBInstanceClass": "db.serverless", + "Engine": "aurora-mysql", + "PromotionTier": 0 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv20capacity09BB04C7": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + } + } + ], + "MetricName": "ServerlessDatabaseCapacity", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 1.5 + } + }, + "integauroraserverlessv20alarmA67BFE09": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + } + } + ], + "MetricName": "ACUUtilization", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 90 + } + }, + "integauroraserverlessv21IntegClusterSubnetsAEE71920": { + "Type": "AWS::RDS::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "Subnets for Integ-Cluster database", + "SubnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "integauroraserverlessv21IntegClusterSecurityGroup483E60E7": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "RDS security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "integauroraserverlessv21IntegClusterSecretA8DA28CB": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "GenerateSecretString": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\"username\":\"admin\"}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv21IntegClusterSecretAttachmentB7E69BEA": { + "Type": "AWS::SecretsManager::SecretTargetAttachment", + "Properties": { + "SecretId": { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + "TargetId": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "TargetType": "AWS::RDS::DBCluster" + } + }, + "integauroraserverlessv21IntegClusterDFF12F00": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql8.0", + "DBSubnetGroupName": { + "Ref": "integauroraserverlessv21IntegClusterSubnetsAEE71920" + }, + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", + "MasterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + ":SecretString:username::}}" + ] + ] + }, + "MasterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + ":SecretString:password::}}" + ] + ] + }, + "ServerlessV2ScalingConfiguration": { + "MaxCapacity": 2, + "MinCapacity": 0.5 + }, + "VpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv21IntegClusterSecurityGroup483E60E7", + "GroupId" + ] + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv21IntegClusterwriterD87D3A20": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "DBInstanceClass": "db.t3.medium", + "Engine": "aurora-mysql", + "PromotionTier": 0 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv21IntegClusterFailoverReader595E72DE": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "DBInstanceClass": "db.serverless", + "Engine": "aurora-mysql", + "PromotionTier": 1 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv21IntegClusterOtherReaderBC649D9A": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "DBInstanceClass": "db.serverless", + "Engine": "aurora-mysql", + "PromotionTier": 2 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv21capacityAFD8D6D1": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + } + } + ], + "MetricName": "ServerlessDatabaseCapacity", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 1.5 + } + }, + "integauroraserverlessv21alarmE70B8A00": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + } + } + ], + "MetricName": "ACUUtilization", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 90 + } + }, + "integauroraserverlessv22IntegClusterSubnets241DB50C": { + "Type": "AWS::RDS::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "Subnets for Integ-Cluster database", + "SubnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "integauroraserverlessv22IntegClusterSecurityGroup0EDBBE37": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "RDS security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "integauroraserverlessv22IntegClusterSecretBF74DBA3": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "GenerateSecretString": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\"username\":\"admin\"}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv22IntegClusterSecretAttachment4864E40A": { + "Type": "AWS::SecretsManager::SecretTargetAttachment", + "Properties": { + "SecretId": { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + "TargetId": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "TargetType": "AWS::RDS::DBCluster" + } + }, + "integauroraserverlessv22IntegCluster1F86F0C6": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql8.0", + "DBSubnetGroupName": { + "Ref": "integauroraserverlessv22IntegClusterSubnets241DB50C" + }, + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", + "MasterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + ":SecretString:username::}}" + ] + ] + }, + "MasterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + ":SecretString:password::}}" + ] + ] + }, + "ServerlessV2ScalingConfiguration": { + "MaxCapacity": 2, + "MinCapacity": 0.5 + }, + "VpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv22IntegClusterSecurityGroup0EDBBE37", + "GroupId" + ] + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv22IntegClusterwriter4C20F6E7": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "DBInstanceClass": "db.serverless", + "Engine": "aurora-mysql", + "PromotionTier": 0 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv22IntegClusterFailoverReaderBB40FCA6": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "DBInstanceClass": "db.t3.medium", + "Engine": "aurora-mysql", + "PromotionTier": 1 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv22IntegClusterOtherReader63C2651D": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "DBInstanceClass": "db.serverless", + "Engine": "aurora-mysql", + "PromotionTier": 2 + }, + "DependsOn": [ + "IntegVPCPrivateSubnet1DefaultRoute140D7A84", + "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF", + "IntegVPCPrivateSubnet2DefaultRouteAE44E307", + "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "integauroraserverlessv22capacityCC6A400C": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + } + } + ], + "MetricName": "ServerlessDatabaseCapacity", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 1.5 + } + }, + "integauroraserverlessv22alarmA8DB3F10": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 3, + "Dimensions": [ + { + "Name": "DBClusterIdentifier", + "Value": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + } + } + ], + "MetricName": "ACUUtilization", + "Namespace": "AWS/RDS", + "Period": 600, + "Statistic": "Average", + "Threshold": 90 + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ.json new file mode 100644 index 0000000000000..fcf69e229cfef --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "32.0.0", + "testCases": { + "integ-test/DefaultTest": { + "stacks": [ + "integ-aurora-serverlessv2-cluster" + ], + "assertionStack": "integ-test/DefaultTest/DeployAssert", + "assertionStackName": "integtestDefaultTestDeployAssert24D5C536" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json new file mode 100644 index 0000000000000..4b008a0cae838 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json @@ -0,0 +1,19 @@ +{ + "version": "32.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestDefaultTestDeployAssert24D5C536.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/manifest.json new file mode 100644 index 0000000000000..3f10d394ec9e0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/manifest.json @@ -0,0 +1,435 @@ +{ + "version": "32.0.0", + "artifacts": { + "integ-aurora-serverlessv2-cluster.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-aurora-serverlessv2-cluster.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-aurora-serverlessv2-cluster": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-aurora-serverlessv2-cluster.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bffc468fc464208b727e3300214b3102d30e6f4d749531331ef45d2da89cae51.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-aurora-serverlessv2-cluster.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-aurora-serverlessv2-cluster.assets" + ], + "metadata": { + "/integ-aurora-serverlessv2-cluster/Integ-VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPC2FF1AB0E" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1SubnetE05F7E7D" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1RouteTable622895C7" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1RouteTableAssociation0E84800B" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1DefaultRouteE885D95E" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1EIP1AC057E9" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet1NATGateway380AC0A0" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2Subnet9648DE97" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2RouteTableB79B3910" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2RouteTableAssociation831EA0CC" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2DefaultRoute2FC4B163" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2EIPEA07DF99" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPublicSubnet2NATGateway912800A3" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet1SubnetD5B61223" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet1RouteTableF2678D77" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet1RouteTableAssociationAD4B0EBF" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet1DefaultRoute140D7A84" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet2RouteTable4132D373" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet2RouteTableAssociation9A15DAD6" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCPrivateSubnet2DefaultRouteAE44E307" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCIGW02FC78B6" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCVPCGW4DD476C7" + } + ], + "/integ-aurora-serverlessv2-cluster/Integ-VPC/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegVPCRestrictDefaultSecurityGroupCustomResource42DF8AB1" + } + ], + "/integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Subnets/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegClusterSubnets2462DA9D" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegClusterSecurityGroup0FF1F93F" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegClusterSecretB9E432EB" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret/Attachment/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegClusterSecretAttachmentABF2342B" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegCluster5133790E" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/writer/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20IntegClusterwriter68858AE9" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/capacity/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20capacity09BB04C7" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/alarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv20alarmA67BFE09" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Subnets/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterSubnetsAEE71920" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterSecurityGroup483E60E7" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret/Attachment/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterSecretAttachmentB7E69BEA" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterDFF12F00" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/writer/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterwriterD87D3A20" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/FailoverReader/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterFailoverReader595E72DE" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/OtherReader/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21IntegClusterOtherReaderBC649D9A" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/capacity/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21capacityAFD8D6D1" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/alarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv21alarmE70B8A00" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster": [ + { + "type": "aws:cdk:info", + "data": "..." + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Subnets/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterSubnets241DB50C" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterSecurityGroup0EDBBE37" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret/Attachment/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterSecretAttachment4864E40A" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegCluster1F86F0C6" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/writer/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterwriter4C20F6E7" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/FailoverReader/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterFailoverReaderBB40FCA6" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/OtherReader/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22IntegClusterOtherReader63C2651D" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/capacity/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22capacityCC6A400C" + } + ], + "/integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/alarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "integauroraserverlessv22alarmA8DB3F10" + } + ], + "/integ-aurora-serverlessv2-cluster/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-aurora-serverlessv2-cluster/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-aurora-serverlessv2-cluster" + }, + "integtestDefaultTestDeployAssert24D5C536.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestDefaultTestDeployAssert24D5C536.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestDefaultTestDeployAssert24D5C536": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestDefaultTestDeployAssert24D5C536.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "metadata": { + "/integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/tree.json new file mode 100644 index 0000000000000..2cb417f6456a3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.js.snapshot/tree.json @@ -0,0 +1,1887 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-aurora-serverlessv2-cluster": { + "id": "integ-aurora-serverlessv2-cluster", + "path": "integ-aurora-serverlessv2-cluster", + "children": { + "Integ-VPC": { + "id": "Integ-VPC", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPublicSubnet1RouteTable622895C7" + }, + "subnetId": { + "Ref": "IntegVPCPublicSubnet1SubnetE05F7E7D" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPublicSubnet1RouteTable622895C7" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "IntegVPCPublicSubnet1SubnetE05F7E7D" + }, + "allocationId": { + "Fn::GetAtt": [ + "IntegVPCPublicSubnet1EIP1AC057E9", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPublicSubnet2RouteTableB79B3910" + }, + "subnetId": { + "Ref": "IntegVPCPublicSubnet2Subnet9648DE97" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPublicSubnet2RouteTableB79B3910" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "IntegVPCPublicSubnet2Subnet9648DE97" + }, + "allocationId": { + "Fn::GetAtt": [ + "IntegVPCPublicSubnet2EIPEA07DF99", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPrivateSubnet1RouteTableF2678D77" + }, + "subnetId": { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPrivateSubnet1RouteTableF2678D77" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "IntegVPCPublicSubnet1NATGateway380AC0A0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPrivateSubnet2RouteTable4132D373" + }, + "subnetId": { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "IntegVPCPrivateSubnet2RouteTable4132D373" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "IntegVPCPublicSubnet2NATGateway912800A3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-aurora-serverlessv2-cluster/Integ-VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + }, + "internetGatewayId": { + "Ref": "IntegVPCIGW02FC78B6" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "integ-aurora-serverlessv2-cluster/Integ-VPC/RestrictDefaultSecurityGroupCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "integ-aurora-serverlessv2-cluster/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProvider", + "version": "0.0.0" + } + }, + "integ-aurora-serverlessv2-0": { + "id": "integ-aurora-serverlessv2-0", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0", + "children": { + "Integ-Cluster": { + "id": "Integ-Cluster", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster", + "children": { + "Subnets": { + "id": "Subnets", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Subnets", + "children": { + "Default": { + "id": "Default", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Subnets/Default", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBSubnetGroup", + "aws:cdk:cloudformation:props": { + "dbSubnetGroupDescription": "Subnets for Integ-Cluster database", + "subnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBSubnetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.SubnetGroup", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "RDS security group", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Secret": { + "id": "Secret", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "generateSecretString": { + "passwordLength": 30, + "secretStringTemplate": "{\"username\":\"admin\"}", + "generateStringKey": "password", + "excludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", + "version": "0.0.0" + } + }, + "Attachment": { + "id": "Attachment", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret/Attachment", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Secret/Attachment/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::SecretTargetAttachment", + "aws:cdk:cloudformation:props": { + "secretId": { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + "targetId": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + }, + "targetType": "AWS::RDS::DBCluster" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseSecret", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", + "aws:cdk:cloudformation:props": { + "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql8.0", + "dbSubnetGroupName": { + "Ref": "integauroraserverlessv20IntegClusterSubnets2462DA9D" + }, + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", + "masterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + ":SecretString:username::}}" + ] + ] + }, + "masterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv20IntegClusterSecretB9E432EB" + }, + ":SecretString:password::}}" + ] + ] + }, + "serverlessV2ScalingConfiguration": { + "minCapacity": 0.5, + "maxCapacity": 2 + }, + "vpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv20IntegClusterSecurityGroup0FF1F93F", + "GroupId" + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBCluster", + "version": "0.0.0" + } + }, + "writer": { + "id": "writer", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/writer", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/Integ-Cluster/writer/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + }, + "dbInstanceClass": "db.serverless", + "engine": "aurora-mysql", + "promotionTier": 0 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseCluster", + "version": "0.0.0" + } + }, + "capacity": { + "id": "capacity", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/capacity", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/capacity/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + } + } + ], + "metricName": "ServerlessDatabaseCapacity", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 1.5 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + }, + "alarm": { + "id": "alarm", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/alarm", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-0/alarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv20IntegCluster5133790E" + } + } + ], + "metricName": "ACUUtilization", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 90 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.26" + } + }, + "integ-aurora-serverlessv2-1": { + "id": "integ-aurora-serverlessv2-1", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1", + "children": { + "Integ-Cluster": { + "id": "Integ-Cluster", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster", + "children": { + "Subnets": { + "id": "Subnets", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Subnets", + "children": { + "Default": { + "id": "Default", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Subnets/Default", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBSubnetGroup", + "aws:cdk:cloudformation:props": { + "dbSubnetGroupDescription": "Subnets for Integ-Cluster database", + "subnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBSubnetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.SubnetGroup", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "RDS security group", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Secret": { + "id": "Secret", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "generateSecretString": { + "passwordLength": 30, + "secretStringTemplate": "{\"username\":\"admin\"}", + "generateStringKey": "password", + "excludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", + "version": "0.0.0" + } + }, + "Attachment": { + "id": "Attachment", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret/Attachment", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Secret/Attachment/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::SecretTargetAttachment", + "aws:cdk:cloudformation:props": { + "secretId": { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + "targetId": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "targetType": "AWS::RDS::DBCluster" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseSecret", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", + "aws:cdk:cloudformation:props": { + "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql8.0", + "dbSubnetGroupName": { + "Ref": "integauroraserverlessv21IntegClusterSubnetsAEE71920" + }, + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", + "masterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + ":SecretString:username::}}" + ] + ] + }, + "masterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv21IntegClusterSecretA8DA28CB" + }, + ":SecretString:password::}}" + ] + ] + }, + "serverlessV2ScalingConfiguration": { + "minCapacity": 0.5, + "maxCapacity": 2 + }, + "vpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv21IntegClusterSecurityGroup483E60E7", + "GroupId" + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBCluster", + "version": "0.0.0" + } + }, + "writer": { + "id": "writer", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/writer", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/writer/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "dbInstanceClass": "db.t3.medium", + "engine": "aurora-mysql", + "promotionTier": 0 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "FailoverReader": { + "id": "FailoverReader", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/FailoverReader", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/FailoverReader/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "dbInstanceClass": "db.serverless", + "engine": "aurora-mysql", + "promotionTier": 1 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "OtherReader": { + "id": "OtherReader", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/OtherReader", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/Integ-Cluster/OtherReader/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + }, + "dbInstanceClass": "db.serverless", + "engine": "aurora-mysql", + "promotionTier": 2 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseCluster", + "version": "0.0.0" + } + }, + "capacity": { + "id": "capacity", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/capacity", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/capacity/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + } + } + ], + "metricName": "ServerlessDatabaseCapacity", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 1.5 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + }, + "alarm": { + "id": "alarm", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/alarm", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-1/alarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv21IntegClusterDFF12F00" + } + } + ], + "metricName": "ACUUtilization", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 90 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.26" + } + }, + "integ-aurora-serverlessv2-2": { + "id": "integ-aurora-serverlessv2-2", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2", + "children": { + "Integ-Cluster": { + "id": "Integ-Cluster", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster", + "children": { + "Subnets": { + "id": "Subnets", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Subnets", + "children": { + "Default": { + "id": "Default", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Subnets/Default", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBSubnetGroup", + "aws:cdk:cloudformation:props": { + "dbSubnetGroupDescription": "Subnets for Integ-Cluster database", + "subnetIds": [ + { + "Ref": "IntegVPCPrivateSubnet1SubnetD5B61223" + }, + { + "Ref": "IntegVPCPrivateSubnet2SubnetFCC4EF23" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBSubnetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.SubnetGroup", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "RDS security group", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "IntegVPC2FF1AB0E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Secret": { + "id": "Secret", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "generateSecretString": { + "passwordLength": 30, + "secretStringTemplate": "{\"username\":\"admin\"}", + "generateStringKey": "password", + "excludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", + "version": "0.0.0" + } + }, + "Attachment": { + "id": "Attachment", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret/Attachment", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Secret/Attachment/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::SecretTargetAttachment", + "aws:cdk:cloudformation:props": { + "secretId": { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + "targetId": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "targetType": "AWS::RDS::DBCluster" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseSecret", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", + "aws:cdk:cloudformation:props": { + "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql8.0", + "dbSubnetGroupName": { + "Ref": "integauroraserverlessv22IntegClusterSubnets241DB50C" + }, + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", + "masterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + ":SecretString:username::}}" + ] + ] + }, + "masterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "integauroraserverlessv22IntegClusterSecretBF74DBA3" + }, + ":SecretString:password::}}" + ] + ] + }, + "serverlessV2ScalingConfiguration": { + "minCapacity": 0.5, + "maxCapacity": 2 + }, + "vpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "integauroraserverlessv22IntegClusterSecurityGroup0EDBBE37", + "GroupId" + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBCluster", + "version": "0.0.0" + } + }, + "writer": { + "id": "writer", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/writer", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/writer/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "dbInstanceClass": "db.serverless", + "engine": "aurora-mysql", + "promotionTier": 0 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "FailoverReader": { + "id": "FailoverReader", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/FailoverReader", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/FailoverReader/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "dbInstanceClass": "db.t3.medium", + "engine": "aurora-mysql", + "promotionTier": 1 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "OtherReader": { + "id": "OtherReader", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/OtherReader", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/Integ-Cluster/OtherReader/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + }, + "dbInstanceClass": "db.serverless", + "engine": "aurora-mysql", + "promotionTier": 2 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_rds.DatabaseCluster", + "version": "0.0.0" + } + }, + "capacity": { + "id": "capacity", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/capacity", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/capacity/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + } + } + ], + "metricName": "ServerlessDatabaseCapacity", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 1.5 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + }, + "alarm": { + "id": "alarm", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/alarm", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-aurora-serverlessv2-cluster/integ-aurora-serverlessv2-2/alarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "evaluationPeriods": 3, + "dimensions": [ + { + "name": "DBClusterIdentifier", + "value": { + "Ref": "integauroraserverlessv22IntegCluster1F86F0C6" + } + } + ], + "metricName": "ACUUtilization", + "namespace": "AWS/RDS", + "period": 600, + "statistic": "Average", + "threshold": 90 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.26" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-aurora-serverlessv2-cluster/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-aurora-serverlessv2-cluster/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integ-test": { + "id": "integ-test", + "path": "integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.26" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.26" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.ts new file mode 100644 index 0000000000000..6c1b87fc101f9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-serverless-v2.ts @@ -0,0 +1,72 @@ +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { App, Duration, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { Vpc } from 'aws-cdk-lib/aws-ec2'; +import * as rds from 'aws-cdk-lib/aws-rds'; +import { ClusterInstance } from 'aws-cdk-lib/aws-rds'; +import { Construct } from 'constructs'; + +interface TestCaseProps extends Pick { +} + +class TestCase extends Construct { + constructor(scope: Construct, id: string, props: TestCaseProps) { + super(scope, id); + const cluster = new rds.DatabaseCluster(this, 'Integ-Cluster', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_03_0 }), + writer: props.writer, + readers: props.readers, + removalPolicy: RemovalPolicy.DESTROY, + vpc: props.vpc, + }); + cluster.metricServerlessDatabaseCapacity({ + period: Duration.minutes(10), + }).createAlarm(this, 'capacity', { + threshold: 1.5, + evaluationPeriods: 3, + }); + cluster.metricACUUtilization({ + period: Duration.minutes(10), + }).createAlarm(this, 'alarm', { + evaluationPeriods: 3, + threshold: 90, + }); + } +} + +const testCases: TestCaseProps[] = [ + { + writer: ClusterInstance.serverlessV2('writer'), + }, + { + writer: ClusterInstance.provisioned('writer'), + readers: [ + ClusterInstance.serverlessV2('FailoverReader', { scaleWithWriter: true }), + ClusterInstance.serverlessV2('OtherReader'), + ], + }, + { + writer: ClusterInstance.serverlessV2('writer'), + readers: [ + ClusterInstance.provisioned('FailoverReader', { promotionTier: 1 }), + ClusterInstance.serverlessV2('OtherReader'), + ], + }, +]; + +export class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + const vpc = new Vpc(this, 'Integ-VPC'); + testCases.forEach((p: TestCaseProps, i) => + new TestCase(this, `integ-aurora-serverlessv2-${i}`, { + ...p, + vpc, + }), + ); + } +} + +const app = new App(); +new IntegTest(app, 'integ-test', { + testCases: [new TestStack(app, 'integ-aurora-serverlessv2-cluster')], +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-snapshot.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-snapshot.ts index 86e2ee1b5a186..be951e1398e23 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-snapshot.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster-snapshot.ts @@ -6,6 +6,7 @@ import { App, ArnFormat, CustomResource, RemovalPolicy, Stack, StackProps } from import * as cr from 'aws-cdk-lib/custom-resources'; import { Construct } from 'constructs'; import * as rds from 'aws-cdk-lib/aws-rds'; +import { ClusterInstance } from 'aws-cdk-lib/aws-rds'; class TestStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { @@ -13,12 +14,21 @@ class TestStack extends Stack { const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, natGateways: 1, restrictDefaultSecurityGroup: false }); + const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + isFromLegacyInstanceProps: true, + }; const cluster = new rds.DatabaseCluster(this, 'Cluster', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_10_2 }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpc, - }, + writer: ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], + vpc, removalPolicy: RemovalPolicy.DESTROY, }); @@ -31,10 +41,15 @@ class TestStack extends Stack { snapshotIdentifier: snapshoter.snapshotArn, snapshotCredentials: rds.SnapshotCredentials.fromGeneratedSecret('admin'), engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_10_2 }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpc, - }, + writer: ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], + vpc, removalPolicy: RemovalPolicy.DESTROY, }); fromSnapshot.addRotationSingleUser(); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json index 4d6cbf25c5121..97d5937dd81aa 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "29.0.0", + "version": "31.0.0", "files": { - "b62ee60990b0a14a4b10381d4d26d42ce50c164305fa81b2d9729e116480af0f": { + "ab8497529e7534d5574c621afdac85191ff049866873e461996dc3efa491f7cc": { "source": { "path": "aws-cdk-rds-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b62ee60990b0a14a4b10381d4d26d42ce50c164305fa81b2d9729e116480af0f.json", + "objectKey": "ab8497529e7534d5574c621afdac85191ff049866873e461996dc3efa491f7cc.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json index 072548b1fa549..30701ca89df87 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json @@ -395,7 +395,7 @@ "Type": "AWS::RDS::DBClusterParameterGroup", "Properties": { "Description": "A nice parameter group", - "Family": "aurora5.6", + "Family": "aurora-mysql8.0", "Parameters": { "character_set_database": "utf8mb4" } @@ -502,7 +502,8 @@ "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", + "EngineVersion": "8.0.mysql_aurora.3.03.0", "KmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -530,11 +531,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", "PubliclyAccessible": true }, "DependsOn": [ @@ -552,11 +553,11 @@ "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "DBInstanceClass": "db.t3.small", + "DBInstanceClass": "db.t3.medium", "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "Engine": "aurora", + "Engine": "aurora-mysql", "PubliclyAccessible": true }, "DependsOn": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out index d8b441d447f8a..7925065efbcc4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"29.0.0"} \ No newline at end of file +{"version":"31.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json index 553cd276a4bd3..4b5aeeec886d9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "31.0.0", "testCases": { "integ.cluster": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json index 0641f1a9bb191..28b0b77535d2b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "31.0.0", "artifacts": { "aws-cdk-rds-integ.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b62ee60990b0a14a4b10381d4d26d42ce50c164305fa81b2d9729e116480af0f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ab8497529e7534d5574c621afdac85191ff049866873e461996dc3efa491f7cc.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json index 1b5a2ae9b6bec..4134fb6be9e70 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json @@ -31,8 +31,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPC", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet1": { @@ -75,16 +75,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-integ/VPC/PublicSubnet1/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -105,8 +105,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -124,8 +124,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -144,8 +144,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -164,8 +164,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -192,14 +192,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PublicSubnet2": { @@ -242,16 +242,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-integ/VPC/PublicSubnet2/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -272,8 +272,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -291,8 +291,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -311,8 +311,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "EIP": { @@ -331,8 +331,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "NATGateway": { @@ -359,14 +359,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet1": { @@ -409,16 +409,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-integ/VPC/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -439,8 +439,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -458,8 +458,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -478,14 +478,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "PrivateSubnet2": { @@ -528,16 +528,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Acl": { "id": "Acl", "path": "aws-cdk-rds-integ/VPC/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTable": { @@ -558,8 +558,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "RouteTableAssociation": { @@ -577,8 +577,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultRoute": { @@ -597,14 +597,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "IGW": { @@ -622,8 +622,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "VPCGW": { @@ -641,14 +641,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.Vpc", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Params": { @@ -662,21 +662,21 @@ "aws:cdk:cloudformation:type": "AWS::RDS::DBClusterParameterGroup", "aws:cdk:cloudformation:props": { "description": "A nice parameter group", - "family": "aurora5.6", + "family": "aurora-mysql8.0", "parameters": { "character_set_database": "utf8mb4" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBClusterParameterGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.ParameterGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DbSecurity": { @@ -720,14 +720,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-kms.CfnKey", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-kms.Key", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Database": { @@ -756,14 +756,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBSubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.SubnetGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "SecurityGroup": { @@ -790,8 +790,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "from 0.0.0.0_0:{IndirectPort}": { @@ -824,14 +824,14 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -847,7 +847,8 @@ "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", + "engineVersion": "8.0.mysql_aurora.3.03.0", "kmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -868,8 +869,16 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance1Wrapper": { + "id": "Instance1Wrapper", + "path": "aws-cdk-rds-integ/Database/Instance1Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance1": { @@ -881,17 +890,25 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", "publiclyAccessible": true } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" + } + }, + "Instance2Wrapper": { + "id": "Instance2Wrapper", + "path": "aws-cdk-rds-integ/Database/Instance2Wrapper", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Instance2": { @@ -903,23 +920,23 @@ "dbClusterIdentifier": { "Ref": "DatabaseB269D8BB" }, - "dbInstanceClass": "db.t3.small", + "dbInstanceClass": "db.t3.medium", "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, - "engine": "aurora", + "engine": "aurora-mysql", "publiclyAccessible": true } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.CfnDBInstance", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-rds.DatabaseCluster", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "ClusterIamAccess": { @@ -930,8 +947,8 @@ "id": "ImportClusterIamAccess", "path": "aws-cdk-rds-integ/ClusterIamAccess/ImportClusterIamAccess", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Resource": { @@ -955,8 +972,8 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "DefaultPolicy": { @@ -1014,42 +1031,42 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "aws-cdk-rds-integ/BootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "aws-cdk-rds-integ/CheckBootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } }, "Tree": { @@ -1057,13 +1074,13 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.216" + "version": "10.1.270" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.App", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.1.270" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts index d40bd22de7955..5ce12d092d9eb 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts @@ -2,7 +2,7 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as kms from 'aws-cdk-lib/aws-kms'; import * as cdk from 'aws-cdk-lib'; -import { Credentials, DatabaseCluster, DatabaseClusterEngine, ParameterGroup } from 'aws-cdk-lib/aws-rds'; +import { AuroraMysqlEngineVersion, ClusterInstance, Credentials, DatabaseCluster, DatabaseClusterEngine, ParameterGroup } from 'aws-cdk-lib/aws-rds'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-rds-integ'); @@ -10,7 +10,9 @@ const stack = new cdk.Stack(app, 'aws-cdk-rds-integ'); const vpc = new ec2.Vpc(stack, 'VPC', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const params = new ParameterGroup(stack, 'Params', { - engine: DatabaseClusterEngine.AURORA, + engine: DatabaseClusterEngine.auroraMysql({ + version: AuroraMysqlEngineVersion.VER_3_03_0, + }), description: 'A nice parameter group', parameters: { character_set_database: 'utf8mb4', @@ -19,14 +21,25 @@ const params = new ParameterGroup(stack, 'Params', { const kmsKey = new kms.Key(stack, 'DbSecurity'); +const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM), + isFromLegacyInstanceProps: true, +}; const cluster = new DatabaseCluster(stack, 'Database', { - engine: DatabaseClusterEngine.AURORA, + engine: DatabaseClusterEngine.auroraMysql({ + version: AuroraMysqlEngineVersion.VER_3_03_0, + }), credentials: Credentials.fromUsername('admin', { password: cdk.SecretValue.unsafePlainText('7959866cacc02c2d243ecfe177464fe6') }), - instanceProps: { - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), - vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, - vpc, - }, + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + vpc, + writer: ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], parameterGroup: params, storageEncryptionKey: kmsKey, }); diff --git a/packages/aws-cdk-lib/aws-rds/README.md b/packages/aws-cdk-lib/aws-rds/README.md index f87c3531f4c87..1ed797a8a5683 100644 --- a/packages/aws-cdk-lib/aws-rds/README.md +++ b/packages/aws-cdk-lib/aws-rds/README.md @@ -12,19 +12,23 @@ To set up a clustered database (like Aurora), define a `DatabaseCluster`. You mu always launch a database in a VPC. Use the `vpcSubnets` attribute to control whether your instances will be launched privately or publicly: +You must specify the instance to use as the writer, along with an optional list +of readers (up to 15). + ```ts declare const vpc: ec2.Vpc; const cluster = new rds.DatabaseCluster(this, 'Database', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }), - credentials: rds.Credentials.fromGeneratedSecret('clusteradmin'), // Optional - will default to 'clusteradmin' username and generated password - instanceProps: { - // optional , defaults to t3.medium - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), - vpcSubnets: { - subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, - }, - vpc, + credentials: rds.Credentials.fromGeneratedSecret('clusteradmin'), // Optional - will default to 'admin' username and generated password + writer: rds.ClusterInstance.provisioned('writer', { + readers: [ + rds.ClusterInstance.provisioned('reader1', { promotionTier: 1 }), + rds.ClusterInstance.serverlessV2('reader2'), + ] + vpcSubnets: { + subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }, + vpc, }); ``` @@ -62,10 +66,10 @@ To use dual-stack mode, specify `NetworkType.DUAL` on the `networkType` property declare const vpc: ec2.Vpc; // VPC and subnets must have IPv6 CIDR blocks const cluster = new rds.DatabaseCluster(this, 'Database', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }), - instanceProps: { - vpc, + writer: rds.ClusterInstance.provisioned('writer', { publiclyAccessible: false, - }, + }), + vpc, networkType: rds.NetworkType.DUAL, }); ``` @@ -78,9 +82,8 @@ Use `DatabaseClusterFromSnapshot` to create a cluster from a snapshot: declare const vpc: ec2.Vpc; new rds.DatabaseClusterFromSnapshot(this, 'Database', { engine: rds.DatabaseClusterEngine.aurora({ version: rds.AuroraEngineVersion.VER_1_22_2 }), - instanceProps: { - vpc, - }, + writer: rds.ClusterInstance.provisioned('writer'), + vpc, snapshotIdentifier: 'mySnapshot', }); ``` @@ -97,12 +100,252 @@ Use `InstanceUpdateBehavior.BULK` to update all instances at once. declare const vpc: ec2.Vpc; const cluster = new rds.DatabaseCluster(this, 'Database', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }), + writer: rds.ClusterInstance.provisioned({ + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + }), + readers [rds.ClusterInstance.provisioned('reader')], + instanceUpdateBehaviour: rds.InstanceUpdateBehaviour.ROLLING, // Optional - defaults to rds.InstanceUpdateBehaviour.BULK + vpc, +}); +``` + +### Serverless V2 instances in a Cluster + +It is possible to create an RDS cluster with _both_ serverlessV2 and provisioned +instances. For example, this will create a cluster with a provisioned writer and +a serverless v2 reader. + +> *Note* Before getting starting with this type of cluster it is +> highly recommended that you read through the [Developer Guide](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html) +> which goes into much more detail on the things you need to take into +> consideration. + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }), + writer: rds.ClusterInstance.provisioned('writer'), + readers: [ + rds.ClusterInstance.serverlessV2('reader'), + ] + vpc, +}); +``` + +### Monitoring + +There are some CloudWatch metrics that are [important for Aurora Serverless +v2](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html#aurora-serverless-v2.viewing.monitoring). + +- `ServerlessDatabaseCapacity`: An instance-level metric that can also be + evaluated at the cluster level. At the cluster-level it represents the average + capacity of all the instances in the cluster. +- `ACUUtilization`: Value of the `ServerlessDatabaseCapacity`/ max ACU of the + cluster. + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }), + writer: rds.ClusterInstance.provisioned('writer'), + readers: [ + rds.ClusterInstance.serverlessV2('reader'), + ] + vpc, +}); + +cluster.metricServerlessDatabaseCapacity({ + period: Duration.minutes(10), +}).createAlarm(this, 'capacity', { + threshold: 1.5, + evaluationPeriods: 3, +}); +cluster.metricACUUtilization({ + period: Duration.minutes(10), +}).createAlarm(this, 'alarm', { + evaluationPeriods: 3, + threshold: 90, +}); +``` + +#### Capacity & Scaling + +There are some things to take into consideration with Aurora Serverless v2. + +To create a cluster that can support serverless v2 instances you configure a +minimum and maximum capacity range on the cluster. This is an example showing +the default values: + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }), + writer: rds.ClusterInstance.serverlessV2('writer'), + serverlessV2MinCapacity: 0.5, + serverlessV2MaxCapacity: 2, + vpc, +}); +``` + +The capacity is defined as a number of Aurora capacity units (ACUs). You can +specify in half-step increments (40, 40.5, 41, etc). Each serverless instance in +the cluster inherits the capacity that is defined on the cluster. It is not +possible to configure separate capacity at the instance level. + +The maximum capacity is mainly used for budget control since it allows you to +set a cap on how high your instance can scale. + +The minimum capacity is a little more involved. This controls a couple different +things. + +* The scale-up rate is proportional to the current capacity (larger instances + scale up faster) + * Adjust the minimum capacity to obtain a suitable scaling rate +* Network throughput is proportional to capacity + +> *Info* More complete details can be found [in the docs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html#aurora-serverless-v2-examples-setting-capacity-range-for-cluster) + +Another way that you control the capacity/scaling of your serverless v2 reader +instances is based on the [promotion tier](https://aws.amazon.com/blogs/aws/additional-failover-control-for-amazon-aurora/) +which can be between 0-15. Any serverless v2 instance in the 0-1 tiers will scale alongside the +writer even if the current read load does not require the capacity. This is +because instances in the 0-1 tier are first priority for failover and Aurora +wants to ensure that in the event of a failover the reader that gets promoted is +scaled to handle the write load. + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }), + writer: rds.ClusterInstance.serverlessV2('writer'), + readers: [ + // will be put in promotion tier 1 and will scale with the writer + rds.ClusterInstance.serverlessV2('reader1', { scaleWithWriter: true }), + // will be put in promotion tier 2 and will not scale with the writer + rds.ClusterInstance.serverlessV2('reader2'), + ] + vpc, +}); +``` + +* When the writer scales up, any readers in tier 0-1 will scale up to match +* Scaling for tier 2-15 is independent of what is happening on the writer +* Readers in tier 2-15 scale up based on read load against the individual reader + +When configuring your cluster it is important to take this into consideration +and ensure that in the event of a failover there is an instance that is scaled +up to take over. + +### Mixing Serverless v2 and Provisioned instances + +You are able to create a cluster that has both provisioned and serverless +instances. [This blog post](https://aws.amazon.com/blogs/database/evaluate-amazon-aurora-serverless-v2-for-your-provisioned-aurora-clusters/) +has an excellent guide on choosing between serverless and provisioned instances +based on use case. + +There are a couple of high level differences: + +* Engine Version (serverless only supports MySQL 8+ & PostgreSQL 13+) +* Memory up to 256GB can be supported by serverless + +#### Provisioned writer + +With a provisioned writer and serverless v2 readers, some of the serverless +readers will need to be configured to scale with the writer so they can act as +failover targets. You will need to determine the correct capacity based on the +provisioned instance type and it's utilization. + +As an example, if the CPU utilization for a db.r6g.4xlarge (128 GB) instance +stays at 10% most times, then the minimum ACUs may be set at 6.5 ACUs +(10% of 128 GB) and maximum may be set at 64 ACUs (64x2GB=128GB). Keep in mind +that the speed at which the serverless instance can scale up is determined by +the minimum capacity so if your cluster has spiky workloads you may need to set +a higher minimum capacity. + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }), + writer: rds.ClusterInstance.provisioned('writer', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.R6G, ec2.InstanceSize.XLARGE4), + }), + serverlessV2MinCapacity: 6.5, + serverlessV2MaxCapacity: 64, + readers: [ + // will be put in promotion tier 1 and will scale with the writer + rds.ClusterInstance.serverlessV2('reader1', { scaleWithWriter: true }), + // will be put in promotion tier 2 and will not scale with the writer + rds.ClusterInstance.serverlessV2('reader2'), + ] + vpc, +}); +``` + +In the above example `reader1` will scale with the writer based on the writer's +utilization. So if the writer were to go to `50%` utilization then `reader1` +would scale up to use `32` ACUs. If the read load stayed consistent then +`reader2` may remain at `6.5` since it is not configured to scale with the +writer. + +If one of your Aurora Serverless v2 DB instances consistently reaches the +limit of its maximum capacity, Aurora indicates this condition by setting the +DB instance to a status of `incompatible-parameters`. While the DB instance has +the incompatible-parameters status, some operations are blocked. For example, +you can't upgrade the engine version. + +### Migrating from instanceProps + +Creating instances in a `DatabaseCluster` using `instanceProps` & `instances` is +deprecated. To migrate to the new properties you can provide the +`isFromLegacyInstanceProps` property. + +For example, in order to migrate from this deprecated config: + +```ts +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(stack, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), instances: 2, instanceProps: { instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, vpc, }, - instanceUpdateBehaviour: rds.InstanceUpdateBehaviour.ROLLING, // Optional - defaults to rds.InstanceUpdateBehaviour.BULK +}); +``` + +You would need to migrate to this. The old method of providing `instanceProps` +and `instances` will create the number of `instances` that you provide. The +first instance will be the writer and the rest will be the readers. It's +important that the `id` that you provide is `Instance{NUMBER}`. The writer +should always be `Instance1` and the readers will increment from there. + +Make sure to run a `cdk diff` before deploying to make sure that all changes are +expected. **Always test the migration in a non-production environment first.** + +```ts +const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + isFromLegacyInstanceProps: true, +}; + +declare const vpc: ec2.Vpc; +const cluster = new rds.DatabaseCluster(stack, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + vpc, + writer: ClusterInstance.provisioned('Instance1', { + ...instanceProps, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...instanceProps, + }), + ], }); ``` @@ -240,7 +483,9 @@ new rds.DatabaseInstance(this, 'Instance', { // Setting public accessibility for DB cluster new rds.DatabaseCluster(this, 'DatabaseCluster', { - engine: rds.DatabaseClusterEngine.AURORA, + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), instanceProps: { vpc, vpcSubnets: { @@ -449,8 +694,11 @@ The following example shows granting connection access for RDS Proxy to an IAM r ```ts declare const vpc: ec2.Vpc; const cluster = new rds.DatabaseCluster(this, 'Database', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { vpc }, + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), + writer: rds.ClusterInstance.provisioned('writer'), + vpc, }); const proxy = new rds.DatabaseProxy(this, 'Proxy', { @@ -541,10 +789,11 @@ declare const vpc: ec2.Vpc; const importBucket = new s3.Bucket(this, 'importbucket'); const exportBucket = new s3.Bucket(this, 'exportbucket'); new rds.DatabaseCluster(this, 'dbcluster', { - engine: rds.DatabaseClusterEngine.AURORA, - instanceProps: { - vpc, - }, + engine: rds.DatabaseClusterEngine.auroraMysql({ + version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + }), + writer: rds.ClusterInstance.provisioned('writer'), + vpc, s3ImportBuckets: [importBucket], s3ExportBuckets: [exportBucket], }); @@ -587,9 +836,8 @@ const cluster = new rds.DatabaseCluster(this, 'Database', { engine: rds.DatabaseClusterEngine.aurora({ version: rds.AuroraEngineVersion.VER_1_17_9, // different version class for each engine type }), - instanceProps: { - vpc, - }, + writer: rds.ClusterInstance.provisioned('writer'), + vpc, cloudwatchLogsExports: ['error', 'general', 'slowquery', 'audit'], // Export all available MySQL-based logs cloudwatchLogsRetention: logs.RetentionDays.THREE_MONTHS, // Optional - default is to never expire logs cloudwatchLogsRetentionRole: myLogsPublishingRole, // Optional - a role will be created if not provided diff --git a/packages/aws-cdk-lib/aws-rds/adr/aurora-serverless-v2.md b/packages/aws-cdk-lib/aws-rds/adr/aurora-serverless-v2.md new file mode 100644 index 0000000000000..a4fd2de2da5ff --- /dev/null +++ b/packages/aws-cdk-lib/aws-rds/adr/aurora-serverless-v2.md @@ -0,0 +1,241 @@ +# Aurora Serverless V2 + +> **Note** recommended reading https://aws.amazon.com/blogs/database/evaluate-amazon-aurora-serverless-v2-for-your-provisioned-aurora-clusters/ + +## Status + +accepted + +## Context + +Recently RDS Aurora clusters added support for [Aurora Serverless +V2](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.html). +Prior to that there were two types of clusters that you could create. + +1. A Serverless v1 cluster +2. A provisioned cluster + +Each of these clusters only supported a single type of DB instance (serverless +or provisioned) and it was not possible to mix the two types of instances +together. With the addition of Serverless V2 it is now possible to create a +cluster which has _both_ provisioned instances and serverless v2 instances. + +### Current API + +With the current API you create a cluster and specify the number of instances to +create and the properties to apply to _all_ of the instances. You do not have +granular control over each individual instance. + +```ts +const cluster = new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }), + instances: 3, // default is 2 + instanceProps: { + // optional , defaults to t3.medium + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + }, +}); +``` + +### Serverless v2 + +#### Capacity & Scaling + +Some things to take into consideration with Aurora Serverless v2. + +To create a cluster that can support serverless v2 instance you configure a +minimum and maximum capacity range. This looks something like + +```json +{ + "MaxCapacity": 128, // max value + "MinCapacity": 0.5 // min value +} +``` + +The capacity is defined as a number of Aurora capacity units (ACUs). You can +specify in half-step increments (40, 40.5, 41, etc). + +The maximum capacity is mainly used for budget control since it allows you to +set a cap on how high your instance can scale. + +The minimum capacity is a little more involved. This controls a couple different +things. More complete details can be found [in the docs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html#aurora-serverless-v2-examples-setting-capacity-range-for-cluster) + +1. How low can the instance scale down. If there is no traffic to the cluster + this is the minimum capacity that is allowed. +2. How fast can the instance scale up. The scaling rate of an Aurora Serverless + v2 instance depends on its current capacity. The higher the current capacity, + the faster it can scale up. So for example, if you need to very quickly scale + up to high capacity, you might have to set the minimum higher to allow for + faster scaling. +3. If you have a higher amount of data in the buffer cache you may have to set + the minimum higher so that data is not evicted from the buffer cache when + then instances scale down. +4. Some features require certain minimums + - Performance insights - 2 ACUs + - Aurora global databases - 8 ACUs (in primary region) +5. For high write workloads with serverless v2 readers in tiers 2-15 (more on + tiers below), you may need to provision a higher minimum capacity to reduce + replica lag. + - When using a provisioned writer, you should set the minimum capacity to a + value that represents a comparable amount of memory and CPU to the + writer. (this is only if you notice replication lag) + + +Another way that you control the capacity/scaling of your serverless v2 reader +instances is based on the [promotion tier](https://aws.amazon.com/blogs/aws/additional-failover-control-for-amazon-aurora/) +which can be between 0-15. Previously with all provisioned clusters this didn't +matter too much (we set everything to 1), but with serverless v2 it starts to +matter. Any serverless v2 instance in the 0-1 tiers will scale alongside the +writer even if the current read load does not require the capacity. This is +because instances in the 0-1 tier are first priority for failover and Aurora +wants to ensure that in the event of a failover the reader that gets promoted is +scaled to handle the write load. + +- Serverless v2 readers in tier 0-1 scale with the writer +- Serverless v2 readers in tier 2-15 scale with the read load on itself. + +### Serverless v2 vs Provisioned + +Serverless v2 can go up to 256GB memory. Anything above that needs to be provisioned. + - For example, if the CPU utilization for a db.r6g.4xlarge (128 GB) + instance stays at 10% most times, then the minimum ACUs may be set + at 6.5 ACUs (10% of 128 GB) and maximum may be set at 64 ACUs (64x2GB=128GB). + - But if using a db.r6g.16xlarge (512 GB) a serverles v2 instance can't scale + to match + +Out of the 4 common usage patters (peaks & valleys, outliers, random, and +consistent), provisioned should be preferred for the consistent pattern. With +mixed use cluster you may have writers/readers that follow different patters. +For example, you may have a writer that follows the `consistent` pattern, but a +reader that follows the `outliers` pattern. In this case you may want to have a +provisioned instance as the writer along with a provisioned reader in tier 0-1 +(for failover) and then a serverless v2 reader in tier 2-15 (so it scales with the spotty reader) +writer). + +If you are currently using auto scaling with provisioned instances, you should +instead switch to instance scaling with serverless v2. This allows for a larger +pool of serverless readers with the appropriate cluster capacity range. Vertical +scaling at the serverless instance level is much faster compared to launching +new instances. For example, using the case above, using a single `db.r6g.4xlarge` +reader instance with auto scaling configured would add new `db.r6g.4xlarge` instances +when the cluster auto scaled. Alternatively you could provision a couple serverless reader instances +with min=6.5/max=64. These serverless instances would scale up faster (with the read load split between them) +than adding new provisioned instances. + +## Constraints + +Some of these are discussed in more detail above, but reposting here for +clarity. + +1. Max `MaxCapacity` of 128 (256GB) +2. Min `MinCapacity` of 0.5 (1GB) (*with some exceptions) +3. Supports engine version MySQL 8+ & PostgreSQL 13+ +4. Scaling rate depends on capacity and promotion tier + +## Decision + +The major decision is whether we should update the existing +`rds.DatabaseCluster` API to take into account all these new constraints or +create an entirely new API (i.e. `rds.DatabaseClusterV2`). I am proposing that +we update the existing API since this will allow existing users to migrate. + +The changes we would need to make is to switch the `instanceProps` property from +required to optional and deprecate it. Add a new property `clusterInstances` +which would look something like: + +_updates to core_ +```ts +interface DatabaseClusterBaseProps { + ... + /** + * @deprecated - use clusterInstances instead + */ + readonly instances?: number; + /** + * @deprecated - use clusterInstances instead + */ + readonly instanceProps?: InstanceProps; + readonly clusterInstances?: ClusterInstances; +} + +interface ClusterInstances { + readonly writer: IClusterInstance; + readonly readers?: IClusterInstance[]; +} + +class ClusterInstance implements IClusterInstance { + public static provisioned(id: string, props: ProvisionedClusterInstanceProps = {}): IClusterInstance { + return new ClusterInstance(id, { + ...props, + instanceType: ClusterInstanceType.provisioned(props.instanceType), + }); + } + + public static serverlessV2(id: string, props: ServerlessV2ClusterInstanceProps = {}): IClusterInstance { + return new ClusterInstance(id, { + ...props, + instanceType: ClusterInstanceType.serverlessV2(), + }); + } + private constructor(private id: string, private readonly props: ClusterInstanceProps = {}) { } + + public bind(scope: Construct, cluster: DatabaseCluster, props: ClusterInstanceBindOptions): IAuroraClusterInstance { + // new class to represent this concept + return new AuroraClusterInstance(scope, this.id, { + cluster, + ...this.props, + ...props, + }); + } +} +``` + +_user configuration_ (properties are not shown to focus on the API) +```ts +new rds.DatabaseCluster(this, 'Cluster', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_03_0 }), + // capacity applies to all serverless instances in the cluster + serverlessV2MaxCapacity: 1, + serverlessV2MinCapacity: 0.5, + writer: ClusterInstance.provisioned('writer', { ...props }), + readers: [ + // puts it in promition tier 0-1 + ClusterInstance.serverlessV2('reader1', { scaleWithWriter: true, ...additionalProps }), + ClusterInstance.serverlessV2('reader2'), + ClusterInstance.serverlessV2('reader3'), + // illustrating how it might be possible to add support for groups in the future. + // currently not supported by CFN + ClusterInstance.fromReaderGroup('analytics', { ...readerProps }), + }, +}); +``` + +We can also provide instructions on how to migrate from `instanceProps` to +`clusterInstances` which would just entail overwriting the logicalId of the +instances. We could also add something like `ClusterInstance.fromInstanceProps(props: InstanceProps)` +that allows customers to more easily migrate their existing configuration. + +## Alternatives + +The other alternative that was considered was to create an entirely new API +(i.e. `rds.DatabaseClusterV2`). This was considered because it would allow us to +create an API that was more tailored to the new functionality. Given all the +context above, it was also originally unclear whether or not it would be possible +to update the existing API while accounting for all the nuances with Serverless +V2. + +Ultimately this was discarded because it looks like we will be able to account +for the nuances and the benefit of allowing users to continue to use the +existing API outweigh any ergonomic benefits of a completely new API. + +## Consequences + +The main consequence of this decision is maybe just some confusion on how +to use the new properties vs the old ones and changing some property validation +from linter to runtime validation (`instanceProps` was required and would show +in the IDE if not provided. Now you will get a runtime error if you don't +provide `clusterInstances` or `instanceProps`). This would essentially make the +TypeScript experience match the experience of other languages. diff --git a/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts b/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts new file mode 100644 index 0000000000000..3b5a5ef8f2afc --- /dev/null +++ b/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts @@ -0,0 +1,529 @@ +import { Construct } from 'constructs'; +import { DatabaseCluster } from './cluster'; +import { IDatabaseCluster } from './cluster-ref'; +import { IParameterGroup, ParameterGroup } from './parameter-group'; +import { helperRemovalPolicy } from './private/util'; +import { PerformanceInsightRetention } from './props'; +import { CfnDBInstance } from './rds.generated'; +import { ISubnetGroup } from './subnet-group'; +import * as ec2 from '../../aws-ec2'; +import { IRole } from '../../aws-iam'; +import * as kms from '../../aws-kms'; +import { IResource, Resource, Duration, RemovalPolicy, ArnFormat } from '../../core'; + +/** + * Options for binding the instance to the cluster + */ +export interface ClusterInstanceBindOptions { + /** + * The interval, in seconds, between points when Amazon RDS collects enhanced + * monitoring metrics for the DB instances. + * + * @default no enhanced monitoring + */ + readonly monitoringInterval?: Duration; + + /** + * Role that will be used to manage DB instances monitoring. + * + * @default - A role is automatically created for you + */ + readonly monitoringRole?: IRole; + + /** + * The removal policy on the cluster + * + * @default - RemovalPolicy.DESTROY (cluster snapshot can restore) + */ + readonly removalPolicy?: RemovalPolicy; + + /** + * The promotion tier of the cluster instance + * + * This matters more for serverlessV2 instances. If a serverless + * instance is in tier 0-1 then it will scale with the writer. + * + * For provisioned instances this just determines the failover priority. + * If multiple instances have the same priority then one will be picked at random + * + * @default 2 + */ + readonly promotionTier?: number; + + /** + * Existing subnet group for the cluster. + * This is only needed when using the isFromLegacyInstanceProps + * + * @default - cluster subnet group is used + */ + readonly subnetGroup?: ISubnetGroup; +} + +/** + * The type of Aurora Cluster Instance. Can be either serverless v2 + * or provisioned + */ +export class ClusterInstanceType { + /** + * Aurora Serverless V2 instance type + * @see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.html + */ + public static serverlessV2(): ClusterInstanceType { + return new ClusterInstanceType('db.serverless', InstanceType.SERVERLESS_V2); + } + + /** + * Aurora Provisioned instance type + */ + public static provisioned(instanceType?: ec2.InstanceType): ClusterInstanceType { + return new ClusterInstanceType( + (instanceType ?? ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM)).toString(), + InstanceType.PROVISIONED, + ); + } + + constructor( + private readonly instanceType: string, + public readonly type: InstanceType, + ) { } + + /** + * String representation of the instance type that can be used in the CloudFormation resource + */ + public toString(): string { + return this.instanceType; + } +} + +/** + * Represents an Aurora cluster instance + * This can be either a provisioned instance or a serverless v2 instance + */ +export interface IClusterInstance { + /** + * Create the database instance within the provided cluster + */ + bind(scope: Construct, cluster: IDatabaseCluster, options: ClusterInstanceBindOptions): IAuroraClusterInstance; +} + +/** + * Options for creating a provisioned instance + */ +export interface ProvisionedClusterInstanceProps extends ClusterInstanceOptions { + /** + * The cluster instance type + * + * @default db.t3.medium + */ + readonly instanceType?: ec2.InstanceType; + + /** + * The promotion tier of the cluster instance + * + * Can be between 0-15 + * + * For provisioned instances this just determines the failover priority. + * If multiple instances have the same priority then one will be picked at random + * + * @default 2 + */ + readonly promotionTier?: number; + + /** + * Only used for migrating existing clusters from using `instanceProps` to `writer` and `readers` + * + * @example + * // existing cluster + * declare const vpc: ec2.Vpc; + * const cluster = new rds.DatabaseCluster(stack, 'Database', { + * engine: rds.DatabaseClusterEngine.auroraMysql({ + * version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + * }), + * instances: 2, + * instanceProps: { + * instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + * vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + * vpc, + * }, + * }); + * + * // migration + * + * const instanceProps = { + * instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL), + * isFromLegacyInstanceProps: true, + * }; + * + * declare const vpc: ec2.Vpc; + * const cluster = new rds.DatabaseCluster(stack, 'Database', { + * engine: rds.DatabaseClusterEngine.auroraMysql({ + * version: rds.AuroraMysqlEngineVersion.VER_3_03_0, + * }), + * vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + * vpc, + * writer: ClusterInstance.provisioned('Instance1', { + * ...instanceProps, + * }), + * readers: [ + * ClusterInstance.provisioned('Instance2', { + * ...instanceProps, + * }), + * ], + * }); + * + * @default false + */ + readonly isFromLegacyInstanceProps?: boolean; +} + +/** + * Options for creating a serverless v2 instance + */ +export interface ServerlessV2ClusterInstanceProps extends ClusterInstanceOptions { + /** + * Only applicable to reader instances. + * + * If this is true then the instance will be placed in promotion tier 1, otherwise + * it will be placed in promotion tier 2. + * + * For serverless v2 instances this means: + * - true: The serverless v2 reader will scale to match the writer instance (provisioned or serverless) + * - false: The serverless v2 reader will scale with the read workfload on the instance + * + * @default false + */ + readonly scaleWithWriter?: boolean; +} + +/** + * Common options for creating cluster instances (both serverless and provisioned) + */ +export interface ClusterInstanceProps extends ClusterInstanceOptions{ + /** + * The type of cluster instance to create. Can be either + * provisioned or serverless v2 + */ + readonly instanceType: ClusterInstanceType; + + /** + * The promotion tier of the cluster instance + * + * This matters more for serverlessV2 instances. If a serverless + * instance is in tier 0-1 then it will scale with the writer. + * + * For provisioned instances this just determines the failover priority. + * If multiple instances have the same priority then one will be picked at random + * + * @default 2 + */ + readonly promotionTier?: number; + + /** + * Only used for migrating existing clusters from using `instanceProps` to `writer` and `readers` + * + * @default false + */ + readonly isFromLegacyInstanceProps?: boolean; +} + +/** + * Common options for creating a cluster instance + */ +export interface ClusterInstanceOptions { + /** + * The identifier for the database instance + * + * @default - CloudFormation generated identifier + */ + readonly instanceIdentifier?: string; + + /** + * Whether to enable automatic upgrade of minor version for the DB instance. + * + * @default - true + */ + readonly autoMinorVersionUpgrade?: boolean; + + /** + * Whether to enable Performance Insights for the DB instance. + * + * @default - false, unless ``performanceInsightRentention`` or ``performanceInsightEncryptionKey`` is set. + */ + readonly enablePerformanceInsights?: boolean; + + /** + * The amount of time, in days, to retain Performance Insights data. + * + * @default 7 + */ + readonly performanceInsightRetention?: PerformanceInsightRetention; + + /** + * The AWS KMS key for encryption of Performance Insights data. + * + * @default - default master key + */ + readonly performanceInsightEncryptionKey?: kms.IKey; + + /** + * Indicates whether the DB instance is an internet-facing instance. + * + * @default - true if the instance is placed in a public subnet + */ + readonly publiclyAccessible?: boolean; + + /** + * The parameters in the DBParameterGroup to create automatically + * + * You can only specify parameterGroup or parameters but not both. + * You need to use a versioned engine to auto-generate a DBParameterGroup. + * + * @default - None + */ + readonly parameters?: { [key: string]: string }; + + /** + * Whether to allow upgrade of major version for the DB instance. + * + * @default - false + */ + readonly allowMajorVersionUpgrade?: boolean; + + /** + * The DB parameter group to associate with the instance. + * This is only needed if you need to configure different parameter + * groups for each individual instance, otherwise you should not + * provide this and just use the cluster parameter group + * + * @default the cluster parameter group is used + */ + readonly parameterGroup?: IParameterGroup; +} + +/** + * Create an RDS Aurora Cluster Instance. You can create either provisioned or + * serverless v2 instances. + * + * @example + * + * declare const vpc: ec2.Vpc; + * const cluster = new rds.DatabaseCluster(this, 'Database', { + * engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }), + * writer: rds.ClusterInstance.provisioned('writer', { + * instanceType: ec2.InstanceType.of(ec2.InstanceClass.R6G, ec2.InstanceSize.XLARGE4), + * }), + * serverlessV2MinCapacity: 6.5, + * serverlessV2MaxCapacity: 64, + * readers: [ + * // will be put in promotion tier 1 and will scale with the writer + * rds.ClusterInstance.serverlessV2('reader1', { scaleWithWriter: true }), + * // will be put in promotion tier 2 and will not scale with the writer + * rds.ClusterInstance.serverlessV2('reader2'), + * ] + * vpc, + * }); + */ +export class ClusterInstance implements IClusterInstance { + /** + * Add a provisioned instance to the cluster + * + * @example + * ClusterInstance.provisioned('ClusterInstance', { + * instanceType: ec2.InstanceType.of(ec2.InstanceClass.R6G, ec2.InstanceSize.XLARGE4), + * }); + */ + public static provisioned(id: string, props: ProvisionedClusterInstanceProps = {}): IClusterInstance { + return new ClusterInstance(id, { + ...props, + instanceType: ClusterInstanceType.provisioned(props.instanceType), + }); + } + + /** + * Add a serverless v2 instance to the cluster + * + * @example + * ClusterInstance.serverlessV2('ClusterInstance', { + * scaleWithWriter: true, + * }); + */ + public static serverlessV2(id: string, props: ServerlessV2ClusterInstanceProps = {}): IClusterInstance { + return new ClusterInstance(id, { + ...props, + promotionTier: props.scaleWithWriter ? 1 : 2, + instanceType: ClusterInstanceType.serverlessV2(), + }); + } + + private constructor(private id: string, private readonly props: ClusterInstanceProps) { } + + /** + * Add the ClusterInstance to the cluster + */ + public bind(scope: Construct, cluster: IDatabaseCluster, props: ClusterInstanceBindOptions): IAuroraClusterInstance { + return new AuroraClusterInstance(scope, this.id, { + cluster, + ...this.props, + ...props, + }); + } +} + +interface AuroraClusterInstanceProps extends ClusterInstanceProps, ClusterInstanceBindOptions { + readonly cluster: IDatabaseCluster; +} + +export enum InstanceType { + PROVISIONED = 'PROVISIONED', + SERVERLESS_V2 = 'SERVERLESS_V2', +} + +/** + * An Aurora Cluster Instance + */ +export interface IAuroraClusterInstance extends IResource { + /** + * The instance ARN + */ + readonly dbInstanceArn: string; + + /** + * The instance resource ID + */ + readonly dbiResourceId: string; + + /** + * The instance endpoint address + */ + readonly dbInstanceEndpointAddress: string; + + /** + * The instance identifier + */ + readonly instanceIdentifier: string; + + /** + * The instance type (provisioned vs serverless v2) + */ + readonly type: InstanceType; + + /** + * The instance size if the instance is a provisioned type + */ + readonly instanceSize?: string; + + /** + * Te promotion tier the instance was created in + */ + readonly tier: number; +} + +class AuroraClusterInstance extends Resource implements IAuroraClusterInstance { + public readonly dbInstanceArn: string; + public readonly dbiResourceId: string; + public readonly dbInstanceEndpointAddress: string; + public readonly instanceIdentifier: string; + public readonly type: InstanceType; + public readonly tier: number; + public readonly instanceSize?: string; + constructor(scope: Construct, id: string, props: AuroraClusterInstanceProps) { + super( + scope, + props.isFromLegacyInstanceProps ? `${id}Wrapper` : id, + { + physicalName: props.instanceIdentifier, + }); + this.tier = props.promotionTier ?? 2; + if (this.tier > 15) { + throw new Error('promotionTier must be between 0-15'); + } + + const isOwnedResource = Resource.isOwnedResource(props.cluster); + let internetConnected; + let publiclyAccessible = props.publiclyAccessible; + if (isOwnedResource) { + const ownedCluster = props.cluster as DatabaseCluster; + internetConnected = ownedCluster.vpc.selectSubnets(ownedCluster.vpcSubnets).internetConnectivityEstablished; + publiclyAccessible = ownedCluster.vpcSubnets && ownedCluster.vpcSubnets.subnetType === ec2.SubnetType.PUBLIC; + } + + // Get the actual subnet objects so we can depend on internet connectivity. + const instanceType = (props.instanceType ?? ClusterInstanceType.serverlessV2()); + this.type = instanceType.type; + this.instanceSize = this.type === InstanceType.PROVISIONED ? props.instanceType?.toString() : undefined; + + // engine is never undefined on a managed resource, i.e. DatabaseCluster + const engine = props.cluster.engine!; + const enablePerformanceInsights = props.enablePerformanceInsights + || props.performanceInsightRetention !== undefined || props.performanceInsightEncryptionKey !== undefined; + if (enablePerformanceInsights && props.enablePerformanceInsights === false) { + throw new Error('`enablePerformanceInsights` disabled, but `performanceInsightRetention` or `performanceInsightEncryptionKey` was set'); + } + + const instanceParameterGroup = props.parameterGroup ?? ( + props.parameters + ? new ParameterGroup(props.cluster, 'InstanceParameterGroup', { + engine: engine, + parameters: props.parameters, + }) + : undefined + ); + const instanceParameterGroupConfig = instanceParameterGroup?.bindToInstance({}); + const instance = new CfnDBInstance( + props.isFromLegacyInstanceProps ? scope : this, + props.isFromLegacyInstanceProps ? id : 'Resource', + { + // Link to cluster + engine: engine.engineType, + dbClusterIdentifier: props.cluster.clusterIdentifier, + promotionTier: props.isFromLegacyInstanceProps ? undefined : this.tier, + dbInstanceIdentifier: this.physicalName, + // Instance properties + dbInstanceClass: props.instanceType ? databaseInstanceType(instanceType) : undefined, + publiclyAccessible, + enablePerformanceInsights: enablePerformanceInsights || props.enablePerformanceInsights, // fall back to undefined if not set + performanceInsightsKmsKeyId: props.performanceInsightEncryptionKey?.keyArn, + performanceInsightsRetentionPeriod: enablePerformanceInsights + ? (props.performanceInsightRetention || PerformanceInsightRetention.DEFAULT) + : undefined, + // only need to supply this when migrating from legacy method. + // this is not applicable for aurora instances, but if you do provide it and then + // change it it will cause an instance replacement + dbSubnetGroupName: props.isFromLegacyInstanceProps ? props.subnetGroup?.subnetGroupName : undefined, + dbParameterGroupName: instanceParameterGroupConfig?.parameterGroupName, + monitoringInterval: props.monitoringInterval && props.monitoringInterval.toSeconds(), + monitoringRoleArn: props.monitoringRole && props.monitoringRole.roleArn, + autoMinorVersionUpgrade: props.autoMinorVersionUpgrade, + allowMajorVersionUpgrade: props.allowMajorVersionUpgrade, + }); + // For instances that are part of a cluster: + // + // Cluster DESTROY or SNAPSHOT -> DESTROY (snapshot is good enough to recreate) + // Cluster RETAIN -> RETAIN (otherwise cluster state will disappear) + instance.applyRemovalPolicy(helperRemovalPolicy(props.removalPolicy)); + + // We must have a dependency on the NAT gateway provider here to create + // things in the right order. + if (internetConnected) { + instance.node.addDependency(internetConnected); + } + + this.dbInstanceArn = this.getResourceArnAttribute(instance.attrDbInstanceArn, { + resource: 'db', + service: 'rds', + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + resourceName: this.physicalName, + }); + this.instanceIdentifier = this.getResourceNameAttribute(instance.ref); + this.dbiResourceId = instance.attrDbiResourceId; + this.dbInstanceEndpointAddress = instance.attrEndpointAddress; + } +} + +/** + * Turn a regular instance type into a database instance type + */ +function databaseInstanceType(instanceType: ClusterInstanceType) { + const type = instanceType.toString(); + return instanceType.type === InstanceType.SERVERLESS_V2 ? type : 'db.' + type; +} diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index a19a7e95fd771..1f7acddde80ae 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -1,4 +1,5 @@ import { Construct } from 'constructs'; +import { IAuroraClusterInstance, IClusterInstance, InstanceType } from './aurora-cluster-instance'; import { IClusterEngine } from './cluster-engine'; import { DatabaseClusterAttributes, IDatabaseCluster } from './cluster-ref'; import { DatabaseSecret } from './database-secret'; @@ -10,13 +11,14 @@ import { BackupProps, Credentials, InstanceProps, PerformanceInsightRetention, R import { DatabaseProxy, DatabaseProxyOptions, ProxyTarget } from './proxy'; import { CfnDBCluster, CfnDBClusterProps, CfnDBInstance } from './rds.generated'; import { ISubnetGroup, SubnetGroup } from './subnet-group'; +import * as cloudwatch from '../../aws-cloudwatch'; import * as ec2 from '../../aws-ec2'; import { IRole, ManagedPolicy, Role, ServicePrincipal } from '../../aws-iam'; import * as kms from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as secretsmanager from '../../aws-secretsmanager'; -import { Annotations, Duration, FeatureFlags, RemovalPolicy, Resource, Token } from '../../core'; +import { Annotations, Duration, FeatureFlags, Lazy, RemovalPolicy, Resource, Token } from '../../core'; import * as cxapi from '../../cx-api'; /** @@ -34,13 +36,74 @@ interface DatabaseClusterBaseProps { * Has to be at least 1. * * @default 2 + * @deprecated - use writer and readers instead */ readonly instances?: number; /** * Settings for the individual instances that are launched + * + * @deprecated - use writer and readers instead + */ + readonly instanceProps?: InstanceProps; + + /** + * The instance to use for the cluster writer + * + * @default required if instanceProps is not provided + */ + readonly writer?: IClusterInstance; + + /** + * A list of instances to create as cluster reader instances + * + * @default - no readers are created. The cluster will have a single writer/reader */ - readonly instanceProps: InstanceProps; + readonly readers?: IClusterInstance[]; + + /** + * The maximum number of Aurora capacity units (ACUs) for a DB instance in an Aurora Serverless v2 cluster. + * You can specify ACU values in half-step increments, such as 40, 40.5, 41, and so on. + * The largest value that you can use is 128 (256GB). + * + * The maximum capacity must be higher than 0.5 ACUs. + * @see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html#aurora-serverless-v2.max_capacity_considerations + * + * @default 2 + */ + readonly serverlessV2MaxCapacity?: number, + + /** + * The minimum number of Aurora capacity units (ACUs) for a DB instance in an Aurora Serverless v2 cluster. + * You can specify ACU values in half-step increments, such as 8, 8.5, 9, and so on. + * The smallest value that you can use is 0.5. + * + * @see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html#aurora-serverless-v2.max_capacity_considerations + * + * @default 0.5 + */ + readonly serverlessV2MinCapacity?: number; + + /** + * What subnets to run the RDS instances in. + * + * Must be at least 2 subnets in two different AZs. + */ + readonly vpc?: ec2.IVpc; + + /** + * Where to place the instances within the VPC + * + * @default - the Vpc default strategy if not specified. + */ + readonly vpcSubnets?: ec2.SubnetSelection; + + /** + * Security group. + * + * @default a new security group is created. + */ + readonly securityGroups?: ec2.ISecurityGroup[]; /** * The ordering of updates for instances @@ -436,16 +499,33 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { */ public readonly multiUserRotationApplication: secretsmanager.SecretRotationApplication; + protected readonly serverlessV2MinCapacity: number; + protected readonly serverlessV2MaxCapacity: number; + + protected hasServerlessInstance?: boolean; + constructor(scope: Construct, id: string, props: DatabaseClusterBaseProps) { super(scope, id); - this.vpc = props.instanceProps.vpc; - this.vpcSubnets = props.instanceProps.vpcSubnets; + if ((props.vpc && props.instanceProps?.vpc)) { + throw new Error('Provide either vpc or instanceProps.vpc, but not both'); + } else if (!props.vpc && !props.instanceProps?.vpc) { + throw new Error('If instanceProps is not provided then `vpc` must be provided.'); + } + if ((props.vpcSubnets && props.instanceProps?.vpcSubnets)) { + throw new Error('Provide either vpcSubnets or instanceProps.vpcSubnets, but not both'); + } + this.vpc = props.instanceProps?.vpc ?? props.vpc!; + this.vpcSubnets = props.instanceProps?.vpcSubnets ?? props.vpcSubnets; this.singleUserRotationApplication = props.engine.singleUserRotationApplication; this.multiUserRotationApplication = props.engine.multiUserRotationApplication; - const { subnetIds } = props.instanceProps.vpc.selectSubnets(props.instanceProps.vpcSubnets); + this.serverlessV2MaxCapacity = props.serverlessV2MaxCapacity ?? 2; + this.serverlessV2MinCapacity = props.serverlessV2MinCapacity ?? 0.5; + this.validateServerlessScalingConfig(); + + const { subnetIds } = this.vpc.selectSubnets(this.vpcSubnets); // Cannot test whether the subnets are in different AZs, but at least we can test the amount. if (subnetIds.length < 2) { @@ -454,15 +534,15 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { this.subnetGroup = props.subnetGroup ?? new SubnetGroup(this, 'Subnets', { description: `Subnets for ${id} database`, - vpc: props.instanceProps.vpc, - vpcSubnets: props.instanceProps.vpcSubnets, + vpc: this.vpc, + vpcSubnets: this.vpcSubnets, removalPolicy: renderUnless(helperRemovalPolicy(props.removalPolicy), RemovalPolicy.DESTROY), }); - this.securityGroups = props.instanceProps.securityGroups ?? [ + this.securityGroups = props.instanceProps?.securityGroups ?? props.securityGroups ?? [ new ec2.SecurityGroup(this, 'SecurityGroup', { description: 'RDS security group', - vpc: props.instanceProps.vpc, + vpc: this.vpc, }), ]; @@ -520,6 +600,17 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { deletionProtection: defaultDeletionProtection(props.deletionProtection, props.removalPolicy), enableIamDatabaseAuthentication: props.iamAuthentication, networkType: props.networkType, + serverlessV2ScalingConfiguration: Lazy.any({ + produce: () => { + if (this.hasServerlessInstance) { + return { + minCapacity: this.serverlessV2MinCapacity, + maxCapacity: this.serverlessV2MaxCapacity, + }; + } + return undefined; + }, + }), storageType: props.storageType?.toString(), // Admin backtrackWindow: props.backtrackWindow?.toSeconds(), @@ -536,6 +627,174 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { }; } + /** + * Create cluster instances + * + * @internal + */ + protected _createInstances(props: DatabaseClusterProps): InstanceConfig { + const instanceEndpoints: Endpoint[] = []; + const instanceIdentifiers: string[] = []; + const readers: IAuroraClusterInstance[] = []; + // need to create the writer first since writer is determined by what instance is first + const writer = props.writer!.bind(this, this, { + monitoringInterval: props.monitoringInterval, + monitoringRole: props.monitoringRole, + removalPolicy: props.removalPolicy ?? RemovalPolicy.SNAPSHOT, + subnetGroup: this.subnetGroup, + promotionTier: 0, // override the promotion tier so that writers are always 0 + }); + (props.readers ?? []).forEach(instance => { + const clusterInstance = instance.bind(this, this, { + monitoringInterval: props.monitoringInterval, + monitoringRole: props.monitoringRole, + removalPolicy: props.removalPolicy ?? RemovalPolicy.SNAPSHOT, + subnetGroup: this.subnetGroup, + }); + readers.push(clusterInstance); + + if (clusterInstance.tier < 2) { + this.validateReaderInstance(writer, clusterInstance); + } + instanceEndpoints.push(new Endpoint(clusterInstance.dbInstanceEndpointAddress, this.clusterEndpoint.port)); + instanceIdentifiers.push(clusterInstance.instanceIdentifier); + }); + this.validateClusterInstances(writer, readers); + + return { + instanceEndpoints, + instanceIdentifiers, + }; + } + + /** + * Perform validations on the cluster instances + */ + private validateClusterInstances(writer: IAuroraClusterInstance, readers: IAuroraClusterInstance[]): void { + if (writer.type === InstanceType.SERVERLESS_V2) { + this.hasServerlessInstance = true; + } + if (readers.length > 0) { + const sortedReaders = readers.sort((a, b) => a.tier - b.tier); + const highestTierReaders: IAuroraClusterInstance[] = []; + const highestTier = sortedReaders[0].tier; + let hasProvisionedReader = false; + let noFailoverTierInstances = true; + let serverlessInHighestTier = false; + let hasServerlessReader = false; + const someProvisionedReadersDontMatchWriter: IAuroraClusterInstance[] = []; + for (const reader of sortedReaders) { + if (reader.type === InstanceType.SERVERLESS_V2) { + hasServerlessReader = true; + this.hasServerlessInstance = true; + } else { + hasProvisionedReader = true; + if (reader.instanceSize !== writer.instanceSize) { + someProvisionedReadersDontMatchWriter.push(reader); + } + } + if (reader.tier === highestTier) { + if (reader.type === InstanceType.SERVERLESS_V2) { + serverlessInHighestTier = true; + } + highestTierReaders.push(reader); + } + if (reader.tier <= 1) { + noFailoverTierInstances = false; + } + } + const hasOnlyServerlessReaders = hasServerlessReader && !hasProvisionedReader; + if (hasOnlyServerlessReaders) { + if (noFailoverTierInstances) { + Annotations.of(this).addWarning( + `Cluster ${this.node.id} only has serverless readers and no reader is in promotion tier 0-1.`+ + 'Serverless readers in promotion tiers >= 2 will NOT scale with the writer, which can lead to '+ + 'availability issues if a failover event occurs. It is recommended that at least one reader '+ + 'has `scaleWithWriter` set to true', + ); + } + } else { + if (serverlessInHighestTier && highestTier > 1) { + Annotations.of(this).addWarning( + `There are serverlessV2 readers in tier ${highestTier}. Since there are no instances in a higher tier, `+ + 'any instance in this tier is a failover target. Since this tier is > 1 the serverless reader will not scale '+ + 'with the writer which could lead to availability issues during failover.', + ); + } + if (someProvisionedReadersDontMatchWriter.length > 0 && writer.type === InstanceType.PROVISIONED) { + Annotations.of(this).addWarning( + `There are provisioned readers in the highest promotion tier ${highestTier} that do not have the same `+ + 'InstanceSize as the writer. Any of these instances could be chosen as the new writer in the event '+ + 'of a failover.\n'+ + `Writer InstanceSize: ${writer.instanceSize}\n`+ + `Reader InstanceSizes: ${someProvisionedReadersDontMatchWriter.map(reader => reader.instanceSize).join(', ')}`, + ); + } + } + } + } + + /** + * Perform validations on the reader instance + */ + private validateReaderInstance(writer: IAuroraClusterInstance, reader: IAuroraClusterInstance): void { + if (writer.type === InstanceType.PROVISIONED) { + if (reader.type === InstanceType.SERVERLESS_V2) { + if (!instanceSizeSupportedByServerlessV2(writer.instanceSize!, this.serverlessV2MaxCapacity)) { + Annotations.of(this).addWarning( + 'For high availability any serverless instances in promotion tiers 0-1 '+ + 'should be able to scale to match the provisioned instance capacity.\n'+ + `Serverless instance ${reader.node.id} is in promotion tier ${reader.tier},\n`+ + `But can not scale to match the provisioned writer instance (${writer.instanceSize})`, + ); + } + } + } + } + + /** + * As a cluster-level metric, it represents the average of the ServerlessDatabaseCapacity + * values of all the Aurora Serverless v2 DB instances in the cluster. + */ + public metricServerlessDatabaseCapacity(props?: cloudwatch.MetricOptions) { + return this.metric('ServerlessDatabaseCapacity', { statistic: 'Average', ...props }); + } + + /** + * This value is represented as a percentage. It's calculated as the value of the + * ServerlessDatabaseCapacity metric divided by the maximum ACU value of the DB cluster. + * + * If this metric approaches a value of 100.0, the DB instance has scaled up as high as it can. + * Consider increasing the maximum ACU setting for the cluster. + */ + public metricACUUtilization(props?: cloudwatch.MetricOptions) { + return this.metric('ACUUtilization', { statistic: 'Average', ...props }); + } + + private validateServerlessScalingConfig(): void { + if (this.serverlessV2MaxCapacity > 128 || this.serverlessV2MaxCapacity < 0.5) { + throw new Error('serverlessV2MaxCapacity must be >= 0.5 & <= 128'); + } + + if (this.serverlessV2MinCapacity > 128 || this.serverlessV2MinCapacity < 0.5) { + throw new Error('serverlessV2MinCapacity must be >= 0.5 & <= 128'); + } + + if (this.serverlessV2MaxCapacity < this.serverlessV2MinCapacity) { + throw new Error('serverlessV2MaxCapacity must be greater than serverlessV2MinCapacity'); + } + + if (this.serverlessV2MaxCapacity === 0.5 && this.serverlessV2MinCapacity === 0.5) { + throw new Error('If serverlessV2MinCapacity === 0.5 then serverlessV2MaxCapacity must be >=1'); + } + const regexp = new RegExp(/^[0-9]+\.?5?$/); + if (!regexp.test(this.serverlessV2MaxCapacity.toString()) || !regexp.test(this.serverlessV2MinCapacity.toString())) { + throw new Error('serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments, received '+ + `min: ${this.serverlessV2MaxCapacity}, max: ${this.serverlessV2MaxCapacity}`); + + } + } + /** * Adds the single user rotation of the master password to this cluster. * See [Single user rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-one-user-one-password) @@ -721,10 +980,91 @@ export class DatabaseCluster extends DatabaseClusterNew { cluster.applyRemovalPolicy(props.removalPolicy ?? RemovalPolicy.SNAPSHOT); setLogRetention(this, props); - const createdInstances = createInstances(this, props, this.subnetGroup); + if ((props.writer || props.readers) && (props.instances || props.instanceProps)) { + throw new Error('Cannot provide writer or readers if instances or instanceProps are provided'); + } + + if (!props.instanceProps && !props.writer) { + throw new Error('writer must be provided'); + } + + const createdInstances = props.writer ? this._createInstances(props) : legacyCreateInstances(this, props, this.subnetGroup); this.instanceIdentifiers = createdInstances.instanceIdentifiers; this.instanceEndpoints = createdInstances.instanceEndpoints; } + +} + +/** + * Mapping of instance type to memory setting on the xlarge size + * The memory is predictable based on the xlarge size. For example + * if m5.xlarge has 16GB memory then + * - m5.2xlarge will have 32 (16*2) + * - m5.4xlarge will have 62 (16*4) + * - m5.24xlarge will have 384 (16*24) + */ +const INSTANCE_TYPE_XLARGE_MEMORY_MAPPING: { [instanceType: string]: number } = { + m5: 16, + m5d: 16, + m6g: 16, + t4g: 16, + t3: 16, + m4: 16, + r6g: 32, + r5: 32, + r5b: 32, + r5d: 32, + r4: 30.5, + x2g: 64, + x1e: 122, + x1: 61, + z1d: 32, +}; + +/** + * This validates that the instance size falls within the maximum configured serverless capacity. + * + * @param instanceSize the instance size of the provisioned writer, e.g. r5.xlarge + * @param serverlessV2MaxCapacity the maxCapacity configured on the cluster + * @returns true if the instance size is supported by serverless v2 instances + */ +function instanceSizeSupportedByServerlessV2(instanceSize: string, serverlessV2MaxCapacity: number): boolean { + + const serverlessMaxMem = serverlessV2MaxCapacity*2; + // i.e. r5.xlarge + const sizeParts = instanceSize.split('.'); + if (sizeParts.length === 2) { + const type = sizeParts[0]; + const size = sizeParts[1]; + const xlargeMem = INSTANCE_TYPE_XLARGE_MEMORY_MAPPING[type]; + if (size.endsWith('xlarge')) { + const instanceMem = size === 'xlarge' + ? xlargeMem + : Number(size.slice(0, -6))*xlargeMem; + if (instanceMem > serverlessMaxMem) { + return false; + } + // smaller than xlarge + } else { + return true; + } + } else { + // some weird non-standard instance types + // not sure how to add automation around this so for now + // just handling as one offs + const unSupportedSizes = [ + 'db.r5.2xlarge.tpc2.mem8x', + 'db.r5.4xlarge.tpc2.mem3x', + 'db.r5.4xlarge.tpc2.mem4x', + 'db.r5.6xlarge.tpc2.mem4x', + 'db.r5.8xlarge.tpc2.mem3x', + 'db.r5.12xlarge.tpc2.mem2x', + ]; + if (unSupportedSizes.includes(instanceSize)) { + return false; + } + } + return true; } /** @@ -842,7 +1182,10 @@ export class DatabaseClusterFromSnapshot extends DatabaseClusterNew { cluster.applyRemovalPolicy(props.removalPolicy ?? RemovalPolicy.SNAPSHOT); setLogRetention(this, props); - const createdInstances = createInstances(this, props, this.subnetGroup); + if ((props.writer || props.readers) && (props.instances || props.instanceProps)) { + throw new Error('Cannot provide clusterInstances if instances or instanceProps are provided'); + } + const createdInstances = props.writer ? this._createInstances(props) : legacyCreateInstances(this, props, this.subnetGroup); this.instanceIdentifiers = createdInstances.instanceIdentifiers; this.instanceEndpoints = createdInstances.instanceEndpoints; } @@ -882,7 +1225,7 @@ interface InstanceConfig { * A function rather than a protected method on ``DatabaseClusterNew`` to avoid exposing * ``DatabaseClusterNew`` and ``DatabaseClusterBaseProps`` in the API. */ -function createInstances(cluster: DatabaseClusterNew, props: DatabaseClusterBaseProps, subnetGroup: ISubnetGroup): InstanceConfig { +function legacyCreateInstances(cluster: DatabaseClusterNew, props: DatabaseClusterBaseProps, subnetGroup: ISubnetGroup): InstanceConfig { const instanceCount = props.instances != null ? props.instances : 2; const instanceUpdateBehaviour = props.instanceUpdateBehaviour ?? InstanceUpdateBehaviour.BULK; if (Token.isUnresolved(instanceCount)) { @@ -895,7 +1238,7 @@ function createInstances(cluster: DatabaseClusterNew, props: DatabaseClusterBase const instanceIdentifiers: string[] = []; const instanceEndpoints: Endpoint[] = []; const portAttribute = cluster.clusterEndpoint.port; - const instanceProps = props.instanceProps; + const instanceProps = props.instanceProps!; // Get the actual subnet objects so we can depend on internet connectivity. const internetConnected = instanceProps.vpc.selectSubnets(instanceProps.vpcSubnets).internetConnectivityEstablished; @@ -959,9 +1302,9 @@ function createInstances(cluster: DatabaseClusterNew, props: DatabaseClusterBase dbParameterGroupName: instanceParameterGroupConfig?.parameterGroupName, monitoringInterval: props.monitoringInterval && props.monitoringInterval.toSeconds(), monitoringRoleArn: monitoringRole && monitoringRole.roleArn, - autoMinorVersionUpgrade: props.instanceProps.autoMinorVersionUpgrade, - allowMajorVersionUpgrade: props.instanceProps.allowMajorVersionUpgrade, - deleteAutomatedBackups: props.instanceProps.deleteAutomatedBackups, + autoMinorVersionUpgrade: instanceProps.autoMinorVersionUpgrade, + allowMajorVersionUpgrade: instanceProps.allowMajorVersionUpgrade, + deleteAutomatedBackups: instanceProps.deleteAutomatedBackups, }); // For instances that are part of a cluster: diff --git a/packages/aws-cdk-lib/aws-rds/lib/index.ts b/packages/aws-cdk-lib/aws-rds/lib/index.ts index 0ce8e5fee4018..fd7e157de0745 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/index.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/index.ts @@ -13,6 +13,7 @@ export * from './instance'; export * from './proxy'; export * from './serverless-cluster'; export * from './subnet-group'; +export * from './aurora-cluster-instance'; // AWS::RDS CloudFormation Resources: export * from './rds.generated'; diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index c94632e3d23df..298dfec3352e0 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -5,12 +5,744 @@ import * as kms from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cdk from '../../core'; +import { RemovalPolicy, Stack } from '../../core'; import { AuroraEngineVersion, AuroraMysqlEngineVersion, AuroraPostgresEngineVersion, CfnDBCluster, Credentials, DatabaseCluster, DatabaseClusterEngine, DatabaseClusterFromSnapshot, ParameterGroup, PerformanceInsightRetention, SubnetGroup, DatabaseSecret, - DatabaseInstanceEngine, SqlServerEngineVersion, SnapshotCredentials, InstanceUpdateBehaviour, NetworkType, + DatabaseInstanceEngine, SqlServerEngineVersion, SnapshotCredentials, InstanceUpdateBehaviour, NetworkType, ClusterInstance, } from '../lib'; +describe('cluster new api', () => { + describe('errors are thrown', () => { + test('when old and new props are provided', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + }, + writer: ClusterInstance.serverlessV2('writer'), + iamAuthentication: true, + }); + // THEN + }).toThrow(/Cannot provide writer or readers if instances or instanceProps are provided/); + }); + + test('when no instances are provided', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + iamAuthentication: true, + }); + // THEN + }).toThrow(/writer must be provided/); + }); + + test('when vpc prop is not provided', () => { + // GIVEN + const stack = testStack(); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + writer: ClusterInstance.serverlessV2('writer'), + iamAuthentication: true, + }); + // THEN + }).toThrow(/If instanceProps is not provided then `vpc` must be provided./); + }); + + test('when both vpc and instanceProps.vpc are provided', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + }, + vpc, + iamAuthentication: true, + }); + // THEN + }).toThrow(/Provide either vpc or instanceProps.vpc, but not both/); + }); + + test('when both vpcSubnets and instanceProps.vpcSubnets are provided', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpcSubnets: vpc.selectSubnets( { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS } ), + vpc, + }, + vpcSubnets: vpc.selectSubnets( { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS } ), + iamAuthentication: true, + }); + // THEN + }).toThrow(/Provide either vpcSubnets or instanceProps.vpcSubnets, but not both/); + }); + + test.each([ + [0.5, 200, /serverlessV2MaxCapacity must be >= 0.5 & <= 128/], + [0.5, 0, /serverlessV2MaxCapacity must be >= 0.5 & <= 128/], + [0, 1, /serverlessV2MinCapacity must be >= 0.5 & <= 128/], + [200, 1, /serverlessV2MinCapacity must be >= 0.5 & <= 128/], + [0.5, 0.5, /If serverlessV2MinCapacity === 0.5 then serverlessV2MaxCapacity must be >=1/], + [10.1, 12, /serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments/], + [12, 12.1, /serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments/], + [5, 1, /serverlessV2MaxCapacity must be greater than serverlessV2MinCapacity/], + ])('when serverless capacity is incorrect', (minCapacity, maxCapacity, errorMessage) => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + expect(() => { + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + vpcSubnets: vpc.selectSubnets( { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS } ), + serverlessV2MaxCapacity: maxCapacity, + serverlessV2MinCapacity: minCapacity, + iamAuthentication: true, + }); + // THEN + }).toThrow(errorMessage); + }); + }); + + describe('cluster options', () => { + test('with serverless instances', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.serverlessV2('writer'), + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + // serverless scaling config is set + template.hasResourceProperties('AWS::RDS::DBCluster', Match.objectLike({ + ServerlessV2ScalingConfiguration: { + MinCapacity: 0.5, + MaxCapacity: 2, + }, + })); + + // subnets are set correctly + template.hasResourceProperties('AWS::RDS::DBSubnetGroup', { + DBSubnetGroupDescription: 'Subnets for Database database', + SubnetIds: [ + { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, + { Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A' }, + { Ref: 'VPCPrivateSubnet3Subnet3EDCD457' }, + ], + }); + }); + + test('vpcSubnets can be provided', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + vpcSubnets: vpc.selectSubnets({ subnetType: ec2.SubnetType.PUBLIC }), + writer: ClusterInstance.serverlessV2('writer'), + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + // serverless scaling config is set + template.hasResourceProperties('AWS::RDS::DBCluster', Match.objectLike({ + ServerlessV2ScalingConfiguration: { + MinCapacity: 0.5, + MaxCapacity: 2, + }, + })); + + // subnets are set correctly + template.hasResourceProperties('AWS::RDS::DBSubnetGroup', { + DBSubnetGroupDescription: 'Subnets for Database database', + SubnetIds: [ + { Ref: 'VPCPublicSubnet1SubnetB4246D30' }, + { Ref: 'VPCPublicSubnet2Subnet74179F39' }, + { Ref: 'VPCPublicSubnet3Subnet631C5E25' }, + ], + }); + }); + }); + + describe('migrate from instanceProps', () => { + test('template contains no changes', () => { + // GIVEN + const stack1 = testStack(); + const stack2 = testStack(); + + function createCase(stack: Stack) { + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + const pg = new ParameterGroup(stack, 'pg', { + engine: DatabaseClusterEngine.AURORA, + }); + const sg = new ec2.SecurityGroup(stack, 'sg', { + vpc, + }); + const instanceProps = { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + allowMajorVersionUpgrade: true, + autoMinorVersionUpgrade: true, + deleteAutomatedBackups: true, + enablePerformanceInsights: true, + parameterGroup: pg, + securityGroups: [sg], + }; + return instanceProps; + } + const test1 = createCase(stack1); + const test2 = createCase(stack2); + new DatabaseCluster(stack1, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: test1, + iamAuthentication: true, + }); + + new DatabaseCluster(stack2, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc: test2.vpc, + securityGroups: test2.securityGroups, + writer: ClusterInstance.provisioned('Instance1', { + ...test2, + isFromLegacyInstanceProps: true, + }), + readers: [ + ClusterInstance.provisioned('Instance2', { + ...test2, + isFromLegacyInstanceProps: true, + }), + ], + iamAuthentication: true, + }); + + // THEN + const test1Template = Template.fromStack(stack1).toJSON(); + // deleteAutomatedBackups is not needed on the instance, it is set on the cluster + delete test1Template.Resources.DatabaseInstance1844F58FD.Properties.DeleteAutomatedBackups; + delete test1Template.Resources.DatabaseInstance2AA380DEE.Properties.DeleteAutomatedBackups; + expect( + test1Template, + ).toEqual(Template.fromStack(stack2).toJSON()); + }); + }); + + describe('creates a writer instance', () => { + test('serverlessV2 writer', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.serverlessV2('writer'), + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + // only the writer gets created + template.resourceCountIs('AWS::RDS::DBInstance', 1); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + Engine: 'aurora', + PromotionTier: 0, + }); + }); + + test('serverlessV2 writer with config', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + removalPolicy: RemovalPolicy.RETAIN, + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.serverlessV2('writer', { + allowMajorVersionUpgrade: true, + autoMinorVersionUpgrade: true, + enablePerformanceInsights: true, + parameterGroup: new ParameterGroup(stack, 'pg', { engine: DatabaseClusterEngine.AURORA }), + }), + }); + + // THEN + const template = Template.fromStack(stack); + // only the writer gets created + template.resourceCountIs('AWS::RDS::DBInstance', 1); + template.hasResource('AWS::RDS::DBInstance', { + Properties: { + AllowMajorVersionUpgrade: true, + AutoMinorVersionUpgrade: true, + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + DBParameterGroupName: { Ref: 'pg749EE6ED' }, + EnablePerformanceInsights: true, + Engine: 'aurora', + PerformanceInsightsRetentionPeriod: 7, + PromotionTier: 0, + }, + UpdateReplacePolicy: 'Retain', + Type: 'AWS::RDS::DBInstance', + }); + }); + + test('provisioned writer', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer'), + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + // only the writer gets created + template.resourceCountIs('AWS::RDS::DBInstance', 1); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 0, + }); + }); + + test('provisioned writer with config', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + allowMajorVersionUpgrade: true, + autoMinorVersionUpgrade: true, + enablePerformanceInsights: true, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.C4, ec2.InstanceSize.LARGE ), + parameterGroup: new ParameterGroup(stack, 'pg', { engine: DatabaseClusterEngine.AURORA }), + }), + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + + // only the writer gets created + template.resourceCountIs('AWS::RDS::DBInstance', 1); + template.hasResourceProperties('AWS::RDS::DBInstance', { + AllowMajorVersionUpgrade: true, + AutoMinorVersionUpgrade: true, + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.c4.large', + DBParameterGroupName: { Ref: 'pg749EE6ED' }, + EnablePerformanceInsights: true, + Engine: 'aurora', + PerformanceInsightsRetentionPeriod: 7, + PromotionTier: 0, + }); + }); + }); + + describe('provisioned writer with serverless readers', () => { + test('serverless reader in promotion tier 2 throws warning', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + const cluster = new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer'), + readers: [ClusterInstance.serverlessV2('reader')], + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 2); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 0, + }); + + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + PromotionTier: 2, + }); + + Annotations.fromStack(stack).hasWarning('*', + `Cluster ${cluster.node.id} only has serverless readers and no reader is in promotion tier 0-1.`+ + 'Serverless readers in promotion tiers >= 2 will NOT scale with the writer, which can lead to '+ + 'availability issues if a failover event occurs. It is recommended that at least one reader '+ + 'has `scaleWithWriter` set to true', + ); + }); + + test('serverless reader in promotion tier 1', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer'), + readers: [ClusterInstance.serverlessV2('reader', { scaleWithWriter: true })], + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 2); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 0, + }); + + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + PromotionTier: 1, + }); + + Annotations.fromStack(stack).hasNoWarning('*', '*'); + }); + + test.each([ + [ + ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + undefined, + ], + [ + ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE ), + 4, + ], + ])('serverless reader cannot scale with writer, throw warning', (instanceType: ec2.InstanceType, maxCapacity?: number) => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + instanceType, + }), + serverlessV2MaxCapacity: maxCapacity, + readers: [ClusterInstance.serverlessV2('reader', { scaleWithWriter: true })], + iamAuthentication: true, + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 2); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: `db.${instanceType.toString()}`, + PromotionTier: 0, + }); + + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + PromotionTier: 1, + }); + + Annotations.fromStack(stack).hasWarning('*', + 'For high availability any serverless instances in promotion tiers 0-1 '+ + 'should be able to scale to match the provisioned instance capacity.\n'+ + 'Serverless instance reader is in promotion tier 1,\n'+ + `But can not scale to match the provisioned writer instance (${instanceType.toString()})`, + ); + }); + }); + + describe('provisioned writer and readers', () => { + test('single reader', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + // instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + readers: [ClusterInstance.provisioned('reader')], + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 2); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 0, + }); + + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 2, + }); + + Annotations.fromStack(stack).hasNoWarning('*', '*'); + }); + + test('throws warning if instance types do not match', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + readers: [ + ClusterInstance.provisioned('reader'), + ClusterInstance.provisioned('reader2', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE ), + }), + ], + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 3); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 0, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 2, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.xlarge', + PromotionTier: 2, + }); + + Annotations.fromStack(stack).hasWarning('*', + 'There are provisioned readers in the highest promotion tier 2 that do not have the same '+ + 'InstanceSize as the writer. Any of these instances could be chosen as the new writer in the event '+ + 'of a failover.\n'+ + 'Writer InstanceSize: m5.24xlarge\n'+ + 'Reader InstanceSizes: t3.medium, m5.xlarge', + ); + }); + + test('does not throw warning if highest tier matches', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + readers: [ + ClusterInstance.provisioned('reader'), + ClusterInstance.provisioned('reader2', { + promotionTier: 1, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + ], + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 3); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 0, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.t3.medium', + PromotionTier: 2, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 1, + }); + + Annotations.fromStack(stack).hasNoWarning('*', '*'); + }); + }); + + describe('mixed readers', () => { + test('no warnings', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + readers: [ + ClusterInstance.serverlessV2('reader'), + ClusterInstance.provisioned('reader2', { + promotionTier: 1, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + ], + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 3); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 0, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + PromotionTier: 2, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 1, + }); + + Annotations.fromStack(stack).hasNoWarning('*', '*'); + }); + + test('throws warning if not scaling with writer', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + vpc, + writer: ClusterInstance.provisioned('writer', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE24 ), + }), + readers: [ + ClusterInstance.serverlessV2('reader'), + ClusterInstance.provisioned('reader2', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.XLARGE ), + }), + ], + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::RDS::DBInstance', 3); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.24xlarge', + PromotionTier: 0, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.serverless', + PromotionTier: 2, + }); + template.hasResourceProperties('AWS::RDS::DBInstance', { + DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, + DBInstanceClass: 'db.m5.xlarge', + PromotionTier: 2, + }); + + Annotations.fromStack(stack).hasWarning('*', + 'There are serverlessV2 readers in tier 2. Since there are no instances in a higher tier, '+ + 'any instance in this tier is a failover target. Since this tier is > 1 the serverless reader will not scale '+ + 'with the writer which could lead to availability issues during failover.', + ); + + Annotations.fromStack(stack).hasWarning('*', + 'There are provisioned readers in the highest promotion tier 2 that do not have the same '+ + 'InstanceSize as the writer. Any of these instances could be chosen as the new writer in the event '+ + 'of a failover.\n'+ + 'Writer InstanceSize: m5.24xlarge\n'+ + 'Reader InstanceSizes: m5.xlarge', + ); + }); + }); +}); + describe('cluster', () => { test('creating a Cluster also creates 2 DB Instances', () => { // GIVEN