@go-to-k/cdkd 0.59.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/cli.js +2363 -337
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.60.0.tgz +0 -0
- package/dist/index.js +51 -1
- package/dist/index.js.map +2 -2
- package/package.json +3 -1
- package/dist/go-to-k-cdkd-0.59.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -653,7 +653,7 @@ var destroyOptions = [
|
|
|
653
653
|
),
|
|
654
654
|
new Option(
|
|
655
655
|
"--remove-protection",
|
|
656
|
-
"Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DynamoDB::Table, AWS::EC2::Instance, and AWS::ElasticLoadBalancingV2::LoadBalancer."
|
|
656
|
+
"Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, and AWS::ElasticLoadBalancingV2::LoadBalancer."
|
|
657
657
|
).default(false)
|
|
658
658
|
];
|
|
659
659
|
|
|
@@ -738,6 +738,32 @@ var FALLBACK_NAME_RULES = {
|
|
|
738
738
|
nameProperty: "DBInstanceIdentifier",
|
|
739
739
|
options: { maxLength: 63, lowercase: true }
|
|
740
740
|
},
|
|
741
|
+
// DocumentDB — RDS-shaped API; same name constraints.
|
|
742
|
+
"AWS::DocDB::DBSubnetGroup": {
|
|
743
|
+
nameProperty: "DBSubnetGroupName",
|
|
744
|
+
options: { maxLength: 255, lowercase: true }
|
|
745
|
+
},
|
|
746
|
+
"AWS::DocDB::DBCluster": {
|
|
747
|
+
nameProperty: "DBClusterIdentifier",
|
|
748
|
+
options: { maxLength: 63, lowercase: true }
|
|
749
|
+
},
|
|
750
|
+
"AWS::DocDB::DBInstance": {
|
|
751
|
+
nameProperty: "DBInstanceIdentifier",
|
|
752
|
+
options: { maxLength: 63, lowercase: true }
|
|
753
|
+
},
|
|
754
|
+
// Neptune — RDS-shaped API; same name constraints.
|
|
755
|
+
"AWS::Neptune::DBSubnetGroup": {
|
|
756
|
+
nameProperty: "DBSubnetGroupName",
|
|
757
|
+
options: { maxLength: 255, lowercase: true }
|
|
758
|
+
},
|
|
759
|
+
"AWS::Neptune::DBCluster": {
|
|
760
|
+
nameProperty: "DBClusterIdentifier",
|
|
761
|
+
options: { maxLength: 63, lowercase: true }
|
|
762
|
+
},
|
|
763
|
+
"AWS::Neptune::DBInstance": {
|
|
764
|
+
nameProperty: "DBInstanceIdentifier",
|
|
765
|
+
options: { maxLength: 63, lowercase: true }
|
|
766
|
+
},
|
|
741
767
|
"AWS::ElasticLoadBalancingV2::LoadBalancer": {
|
|
742
768
|
nameProperty: "Name",
|
|
743
769
|
options: { maxLength: 32 }
|
|
@@ -5713,7 +5739,10 @@ import { GetFunctionUrlConfigCommand } from "@aws-sdk/client-lambda";
|
|
|
5713
5739
|
|
|
5714
5740
|
// src/deployment/intrinsic-function-resolver.ts
|
|
5715
5741
|
import { GetCallerIdentityCommand as GetCallerIdentityCommand3 } from "@aws-sdk/client-sts";
|
|
5716
|
-
import {
|
|
5742
|
+
import {
|
|
5743
|
+
DescribeAvailabilityZonesCommand as DescribeAvailabilityZonesCommand2,
|
|
5744
|
+
DescribeLaunchTemplatesCommand
|
|
5745
|
+
} from "@aws-sdk/client-ec2";
|
|
5717
5746
|
import { GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
|
|
5718
5747
|
import { GetParameterCommand as GetParameterCommand2 } from "@aws-sdk/client-ssm";
|
|
5719
5748
|
init_aws_clients();
|
|
@@ -6189,6 +6218,27 @@ var IntrinsicFunctionResolver = class {
|
|
|
6189
6218
|
return physicalId;
|
|
6190
6219
|
}
|
|
6191
6220
|
}
|
|
6221
|
+
if (resourceType === "AWS::EC2::LaunchTemplate") {
|
|
6222
|
+
if (attributeName === "LatestVersionNumber" || attributeName === "DefaultVersionNumber") {
|
|
6223
|
+
try {
|
|
6224
|
+
const clients = getAwsClients();
|
|
6225
|
+
const response = await clients.ec2.send(
|
|
6226
|
+
new DescribeLaunchTemplatesCommand({ LaunchTemplateIds: [physicalId] })
|
|
6227
|
+
);
|
|
6228
|
+
const lt = response.LaunchTemplates?.[0];
|
|
6229
|
+
const value = attributeName === "LatestVersionNumber" ? lt?.LatestVersionNumber : lt?.DefaultVersionNumber;
|
|
6230
|
+
if (value !== void 0 && value !== null) {
|
|
6231
|
+
return String(value);
|
|
6232
|
+
}
|
|
6233
|
+
} catch (err) {
|
|
6234
|
+
this.logger.warn(
|
|
6235
|
+
`DescribeLaunchTemplates(${physicalId}) failed for ${attributeName}: ${err instanceof Error ? err.message : String(err)}`
|
|
6236
|
+
);
|
|
6237
|
+
}
|
|
6238
|
+
return attributeName === "LatestVersionNumber" ? "$Latest" : "$Default";
|
|
6239
|
+
}
|
|
6240
|
+
return physicalId;
|
|
6241
|
+
}
|
|
6192
6242
|
this.logger.warn(
|
|
6193
6243
|
`Unknown attribute ${attributeName} for resource type ${resourceType}, returning physical ID`
|
|
6194
6244
|
);
|
|
@@ -29995,70 +30045,89 @@ var RDSProvider = class {
|
|
|
29995
30045
|
}
|
|
29996
30046
|
};
|
|
29997
30047
|
|
|
29998
|
-
// src/provisioning/providers/
|
|
30048
|
+
// src/provisioning/providers/docdb-provider.ts
|
|
29999
30049
|
import {
|
|
30000
|
-
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
|
|
30005
|
-
|
|
30006
|
-
|
|
30007
|
-
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
|
|
30011
|
-
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
} from "@aws-sdk/client-
|
|
30017
|
-
var
|
|
30018
|
-
|
|
30050
|
+
DocDBClient,
|
|
30051
|
+
CreateDBClusterCommand as CreateDBClusterCommand2,
|
|
30052
|
+
DeleteDBClusterCommand as DeleteDBClusterCommand2,
|
|
30053
|
+
ModifyDBClusterCommand as ModifyDBClusterCommand2,
|
|
30054
|
+
DescribeDBClustersCommand as DescribeDBClustersCommand2,
|
|
30055
|
+
CreateDBInstanceCommand as CreateDBInstanceCommand2,
|
|
30056
|
+
DeleteDBInstanceCommand as DeleteDBInstanceCommand2,
|
|
30057
|
+
ModifyDBInstanceCommand as ModifyDBInstanceCommand2,
|
|
30058
|
+
DescribeDBInstancesCommand as DescribeDBInstancesCommand2,
|
|
30059
|
+
CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand2,
|
|
30060
|
+
DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand2,
|
|
30061
|
+
DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand2,
|
|
30062
|
+
ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand2,
|
|
30063
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand11,
|
|
30064
|
+
AddTagsToResourceCommand as AddTagsToResourceCommand3,
|
|
30065
|
+
RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand3
|
|
30066
|
+
} from "@aws-sdk/client-docdb";
|
|
30067
|
+
var DocDBProvider = class {
|
|
30068
|
+
docdbClient;
|
|
30019
30069
|
providerRegion = process.env["AWS_REGION"];
|
|
30020
|
-
logger = getLogger().child("
|
|
30070
|
+
logger = getLogger().child("DocDBProvider");
|
|
30021
30071
|
handledProperties = /* @__PURE__ */ new Map([
|
|
30022
30072
|
[
|
|
30023
|
-
"AWS::
|
|
30024
|
-
/* @__PURE__ */ new Set(["
|
|
30073
|
+
"AWS::DocDB::DBSubnetGroup",
|
|
30074
|
+
/* @__PURE__ */ new Set(["DBSubnetGroupName", "DBSubnetGroupDescription", "SubnetIds", "Tags"])
|
|
30025
30075
|
],
|
|
30026
30076
|
[
|
|
30027
|
-
"AWS::
|
|
30077
|
+
"AWS::DocDB::DBCluster",
|
|
30028
30078
|
/* @__PURE__ */ new Set([
|
|
30029
|
-
"
|
|
30030
|
-
"
|
|
30031
|
-
"
|
|
30032
|
-
"
|
|
30033
|
-
"
|
|
30034
|
-
"
|
|
30035
|
-
"
|
|
30036
|
-
"
|
|
30037
|
-
"
|
|
30038
|
-
"
|
|
30039
|
-
"
|
|
30040
|
-
"
|
|
30041
|
-
"
|
|
30042
|
-
"
|
|
30043
|
-
"
|
|
30079
|
+
"DBClusterIdentifier",
|
|
30080
|
+
"EngineVersion",
|
|
30081
|
+
"MasterUsername",
|
|
30082
|
+
"MasterUserPassword",
|
|
30083
|
+
"Port",
|
|
30084
|
+
"VpcSecurityGroupIds",
|
|
30085
|
+
"DBSubnetGroupName",
|
|
30086
|
+
"StorageEncrypted",
|
|
30087
|
+
"KmsKeyId",
|
|
30088
|
+
"BackupRetentionPeriod",
|
|
30089
|
+
"PreferredBackupWindow",
|
|
30090
|
+
"PreferredMaintenanceWindow",
|
|
30091
|
+
"DBClusterParameterGroupName",
|
|
30092
|
+
"DeletionProtection",
|
|
30093
|
+
"Tags"
|
|
30094
|
+
])
|
|
30095
|
+
],
|
|
30096
|
+
[
|
|
30097
|
+
"AWS::DocDB::DBInstance",
|
|
30098
|
+
// DocDB DBInstance does NOT support DeletionProtection (verified
|
|
30099
|
+
// against the @aws-sdk/client-docdb CreateDBInstanceMessage type —
|
|
30100
|
+
// the field is absent). Cluster-level DeletionProtection covers the
|
|
30101
|
+
// common case anyway; instance deletes are gated by the cluster's
|
|
30102
|
+
// protection flag in normal use.
|
|
30103
|
+
/* @__PURE__ */ new Set([
|
|
30104
|
+
"DBInstanceIdentifier",
|
|
30105
|
+
"DBInstanceClass",
|
|
30106
|
+
"DBClusterIdentifier",
|
|
30107
|
+
"AvailabilityZone",
|
|
30108
|
+
"PreferredMaintenanceWindow",
|
|
30109
|
+
"AutoMinorVersionUpgrade",
|
|
30110
|
+
"Tags"
|
|
30044
30111
|
])
|
|
30045
30112
|
]
|
|
30046
30113
|
]);
|
|
30047
30114
|
getClient() {
|
|
30048
|
-
if (!this.
|
|
30049
|
-
this.
|
|
30115
|
+
if (!this.docdbClient) {
|
|
30116
|
+
this.docdbClient = new DocDBClient(
|
|
30050
30117
|
this.providerRegion ? { region: this.providerRegion } : {}
|
|
30051
30118
|
);
|
|
30052
30119
|
}
|
|
30053
|
-
return this.
|
|
30120
|
+
return this.docdbClient;
|
|
30054
30121
|
}
|
|
30055
30122
|
// ─── Dispatch ─────────────────────────────────────────────────────
|
|
30056
30123
|
async create(logicalId, resourceType, properties) {
|
|
30057
30124
|
switch (resourceType) {
|
|
30058
|
-
case "AWS::
|
|
30059
|
-
return this.
|
|
30060
|
-
case "AWS::
|
|
30061
|
-
return this.
|
|
30125
|
+
case "AWS::DocDB::DBSubnetGroup":
|
|
30126
|
+
return this.createDBSubnetGroup(logicalId, resourceType, properties);
|
|
30127
|
+
case "AWS::DocDB::DBCluster":
|
|
30128
|
+
return this.createDBCluster(logicalId, resourceType, properties);
|
|
30129
|
+
case "AWS::DocDB::DBInstance":
|
|
30130
|
+
return this.createDBInstance(logicalId, resourceType, properties);
|
|
30062
30131
|
default:
|
|
30063
30132
|
throw new ProvisioningError(
|
|
30064
30133
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -30067,12 +30136,32 @@ var Route53Provider = class {
|
|
|
30067
30136
|
);
|
|
30068
30137
|
}
|
|
30069
30138
|
}
|
|
30070
|
-
async update(logicalId, physicalId, resourceType, properties,
|
|
30139
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
30071
30140
|
switch (resourceType) {
|
|
30072
|
-
case "AWS::
|
|
30073
|
-
return this.
|
|
30074
|
-
|
|
30075
|
-
|
|
30141
|
+
case "AWS::DocDB::DBSubnetGroup":
|
|
30142
|
+
return this.updateDBSubnetGroup(
|
|
30143
|
+
logicalId,
|
|
30144
|
+
physicalId,
|
|
30145
|
+
resourceType,
|
|
30146
|
+
properties,
|
|
30147
|
+
previousProperties
|
|
30148
|
+
);
|
|
30149
|
+
case "AWS::DocDB::DBCluster":
|
|
30150
|
+
return this.updateDBCluster(
|
|
30151
|
+
logicalId,
|
|
30152
|
+
physicalId,
|
|
30153
|
+
resourceType,
|
|
30154
|
+
properties,
|
|
30155
|
+
previousProperties
|
|
30156
|
+
);
|
|
30157
|
+
case "AWS::DocDB::DBInstance":
|
|
30158
|
+
return this.updateDBInstance(
|
|
30159
|
+
logicalId,
|
|
30160
|
+
physicalId,
|
|
30161
|
+
resourceType,
|
|
30162
|
+
properties,
|
|
30163
|
+
previousProperties
|
|
30164
|
+
);
|
|
30076
30165
|
default:
|
|
30077
30166
|
throw new ProvisioningError(
|
|
30078
30167
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -30082,12 +30171,14 @@ var Route53Provider = class {
|
|
|
30082
30171
|
);
|
|
30083
30172
|
}
|
|
30084
30173
|
}
|
|
30085
|
-
async delete(logicalId, physicalId, resourceType,
|
|
30174
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
30086
30175
|
switch (resourceType) {
|
|
30087
|
-
case "AWS::
|
|
30088
|
-
return this.
|
|
30089
|
-
case "AWS::
|
|
30090
|
-
return this.
|
|
30176
|
+
case "AWS::DocDB::DBSubnetGroup":
|
|
30177
|
+
return this.deleteDBSubnetGroup(logicalId, physicalId, resourceType, context);
|
|
30178
|
+
case "AWS::DocDB::DBCluster":
|
|
30179
|
+
return this.deleteDBCluster(logicalId, physicalId, resourceType, context);
|
|
30180
|
+
case "AWS::DocDB::DBInstance":
|
|
30181
|
+
return this.deleteDBInstance(logicalId, physicalId, resourceType, context);
|
|
30091
30182
|
default:
|
|
30092
30183
|
throw new ProvisioningError(
|
|
30093
30184
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -30097,123 +30188,74 @@ var Route53Provider = class {
|
|
|
30097
30188
|
);
|
|
30098
30189
|
}
|
|
30099
30190
|
}
|
|
30100
|
-
|
|
30101
|
-
|
|
30102
|
-
|
|
30103
|
-
|
|
30104
|
-
default:
|
|
30105
|
-
return void 0;
|
|
30106
|
-
}
|
|
30107
|
-
}
|
|
30108
|
-
// ─── AWS::Route53::HostedZone ──────────────────────────────────────
|
|
30109
|
-
async createHostedZone(logicalId, resourceType, properties) {
|
|
30110
|
-
this.logger.debug(`Creating Route 53 hosted zone ${logicalId}`);
|
|
30111
|
-
const name = properties["Name"];
|
|
30112
|
-
if (!name) {
|
|
30113
|
-
throw new ProvisioningError(
|
|
30114
|
-
`Name is required for hosted zone ${logicalId}`,
|
|
30115
|
-
resourceType,
|
|
30116
|
-
logicalId
|
|
30117
|
-
);
|
|
30118
|
-
}
|
|
30191
|
+
// ─── DBSubnetGroup ────────────────────────────────────────────────
|
|
30192
|
+
async createDBSubnetGroup(logicalId, resourceType, properties) {
|
|
30193
|
+
this.logger.debug(`Creating DocDB DBSubnetGroup ${logicalId}`);
|
|
30194
|
+
const dbSubnetGroupName = properties["DBSubnetGroupName"] || generateResourceName(logicalId, { maxLength: 255, lowercase: true });
|
|
30119
30195
|
try {
|
|
30120
|
-
const
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
...hostedZoneConfig && hostedZoneConfig["Comment"] ? {
|
|
30128
|
-
HostedZoneConfig: {
|
|
30129
|
-
Comment: hostedZoneConfig["Comment"],
|
|
30130
|
-
// When VPCs are specified, this is a private hosted zone
|
|
30131
|
-
...firstVpc ? { PrivateZone: true } : {}
|
|
30132
|
-
}
|
|
30133
|
-
} : firstVpc ? { HostedZoneConfig: { PrivateZone: true } } : {},
|
|
30134
|
-
...firstVpc ? {
|
|
30135
|
-
VPC: {
|
|
30136
|
-
VPCId: firstVpc["VPCId"],
|
|
30137
|
-
VPCRegion: firstVpc["VPCRegion"]
|
|
30138
|
-
}
|
|
30139
|
-
} : {}
|
|
30196
|
+
const tags = this.buildTags(properties);
|
|
30197
|
+
await this.getClient().send(
|
|
30198
|
+
new CreateDBSubnetGroupCommand2({
|
|
30199
|
+
DBSubnetGroupName: dbSubnetGroupName,
|
|
30200
|
+
DBSubnetGroupDescription: properties["DBSubnetGroupDescription"] || `Subnet group for ${logicalId}`,
|
|
30201
|
+
SubnetIds: properties["SubnetIds"],
|
|
30202
|
+
...tags.length > 0 && { Tags: tags }
|
|
30140
30203
|
})
|
|
30141
30204
|
);
|
|
30142
|
-
|
|
30143
|
-
|
|
30144
|
-
|
|
30145
|
-
}
|
|
30146
|
-
const zoneId = hostedZone.Id.replace("/hostedzone/", "");
|
|
30147
|
-
if (vpcs && vpcs.length > 1) {
|
|
30148
|
-
for (let i = 1; i < vpcs.length; i++) {
|
|
30149
|
-
const additionalVpc = vpcs[i];
|
|
30150
|
-
this.logger.debug(
|
|
30151
|
-
`Associating additional VPC ${String(additionalVpc["VPCId"])} with hosted zone ${zoneId}`
|
|
30152
|
-
);
|
|
30153
|
-
await this.getClient().send(
|
|
30154
|
-
new AssociateVPCWithHostedZoneCommand({
|
|
30155
|
-
HostedZoneId: zoneId,
|
|
30156
|
-
VPC: {
|
|
30157
|
-
VPCId: additionalVpc["VPCId"],
|
|
30158
|
-
VPCRegion: additionalVpc["VPCRegion"]
|
|
30159
|
-
}
|
|
30160
|
-
})
|
|
30161
|
-
);
|
|
30162
|
-
}
|
|
30163
|
-
}
|
|
30164
|
-
await this.applyHostedZoneTags(zoneId, properties, logicalId);
|
|
30165
|
-
await this.applyQueryLoggingConfig(zoneId, properties, logicalId);
|
|
30166
|
-
const nameServers = response.DelegationSet?.NameServers ?? [];
|
|
30167
|
-
this.logger.debug(`Successfully created hosted zone ${logicalId}: ${zoneId}`);
|
|
30205
|
+
this.logger.debug(
|
|
30206
|
+
`Successfully created DocDB DBSubnetGroup ${logicalId}: ${dbSubnetGroupName}`
|
|
30207
|
+
);
|
|
30168
30208
|
return {
|
|
30169
|
-
physicalId:
|
|
30209
|
+
physicalId: dbSubnetGroupName,
|
|
30170
30210
|
attributes: {
|
|
30171
|
-
|
|
30172
|
-
NameServers: nameServers.join(",")
|
|
30211
|
+
DBSubnetGroupName: dbSubnetGroupName
|
|
30173
30212
|
}
|
|
30174
30213
|
};
|
|
30175
30214
|
} catch (error) {
|
|
30176
|
-
if (error instanceof ProvisioningError)
|
|
30177
|
-
throw error;
|
|
30178
30215
|
const cause = error instanceof Error ? error : void 0;
|
|
30179
30216
|
throw new ProvisioningError(
|
|
30180
|
-
`Failed to create
|
|
30217
|
+
`Failed to create DocDB DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30181
30218
|
resourceType,
|
|
30182
30219
|
logicalId,
|
|
30183
|
-
|
|
30220
|
+
dbSubnetGroupName,
|
|
30184
30221
|
cause
|
|
30185
30222
|
);
|
|
30186
30223
|
}
|
|
30187
30224
|
}
|
|
30188
|
-
async
|
|
30189
|
-
this.logger.debug(`Updating
|
|
30225
|
+
async updateDBSubnetGroup(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
30226
|
+
this.logger.debug(`Updating DocDB DBSubnetGroup ${logicalId}: ${physicalId}`);
|
|
30190
30227
|
try {
|
|
30191
|
-
const
|
|
30192
|
-
const
|
|
30193
|
-
|
|
30194
|
-
|
|
30195
|
-
|
|
30196
|
-
|
|
30197
|
-
|
|
30228
|
+
const subnetIds = properties["SubnetIds"];
|
|
30229
|
+
const sendSubnetIds = subnetIds !== void 0 && subnetIds.length > 0;
|
|
30230
|
+
const modifyInput = {
|
|
30231
|
+
DBSubnetGroupName: physicalId,
|
|
30232
|
+
DBSubnetGroupDescription: properties["DBSubnetGroupDescription"],
|
|
30233
|
+
...sendSubnetIds && { SubnetIds: subnetIds }
|
|
30234
|
+
};
|
|
30235
|
+
await this.getClient().send(new ModifyDBSubnetGroupCommand2(modifyInput));
|
|
30236
|
+
const desc = await this.getClient().send(
|
|
30237
|
+
new DescribeDBSubnetGroupsCommand2({ DBSubnetGroupName: physicalId })
|
|
30198
30238
|
);
|
|
30199
|
-
|
|
30200
|
-
|
|
30201
|
-
|
|
30202
|
-
|
|
30203
|
-
|
|
30204
|
-
|
|
30239
|
+
const arn = desc.DBSubnetGroups?.[0]?.DBSubnetGroupArn;
|
|
30240
|
+
if (arn) {
|
|
30241
|
+
await this.applyTagDiff(
|
|
30242
|
+
arn,
|
|
30243
|
+
previousProperties["Tags"],
|
|
30244
|
+
properties["Tags"]
|
|
30245
|
+
);
|
|
30246
|
+
}
|
|
30247
|
+
this.logger.debug(`Successfully updated DocDB DBSubnetGroup ${logicalId}`);
|
|
30205
30248
|
return {
|
|
30206
30249
|
physicalId,
|
|
30207
30250
|
wasReplaced: false,
|
|
30208
30251
|
attributes: {
|
|
30209
|
-
|
|
30210
|
-
NameServers: nameServers.join(",")
|
|
30252
|
+
DBSubnetGroupName: physicalId
|
|
30211
30253
|
}
|
|
30212
30254
|
};
|
|
30213
30255
|
} catch (error) {
|
|
30214
30256
|
const cause = error instanceof Error ? error : void 0;
|
|
30215
30257
|
throw new ProvisioningError(
|
|
30216
|
-
`Failed to update
|
|
30258
|
+
`Failed to update DocDB DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30217
30259
|
resourceType,
|
|
30218
30260
|
logicalId,
|
|
30219
30261
|
physicalId,
|
|
@@ -30221,14 +30263,17 @@ var Route53Provider = class {
|
|
|
30221
30263
|
);
|
|
30222
30264
|
}
|
|
30223
30265
|
}
|
|
30224
|
-
async
|
|
30225
|
-
this.logger.debug(`Deleting
|
|
30266
|
+
async deleteDBSubnetGroup(logicalId, physicalId, resourceType, context) {
|
|
30267
|
+
this.logger.debug(`Deleting DocDB DBSubnetGroup ${logicalId}: ${physicalId}`);
|
|
30226
30268
|
try {
|
|
30227
|
-
await this.
|
|
30228
|
-
|
|
30229
|
-
|
|
30269
|
+
await this.getClient().send(
|
|
30270
|
+
new DeleteDBSubnetGroupCommand2({
|
|
30271
|
+
DBSubnetGroupName: physicalId
|
|
30272
|
+
})
|
|
30273
|
+
);
|
|
30274
|
+
this.logger.debug(`Successfully deleted DocDB DBSubnetGroup ${logicalId}`);
|
|
30230
30275
|
} catch (error) {
|
|
30231
|
-
if (error
|
|
30276
|
+
if (this.isNotFoundError(error, "DBSubnetGroupNotFoundFault")) {
|
|
30232
30277
|
const clientRegion = await this.getClient().config.region();
|
|
30233
30278
|
assertRegionMatch(
|
|
30234
30279
|
clientRegion,
|
|
@@ -30237,12 +30282,12 @@ var Route53Provider = class {
|
|
|
30237
30282
|
logicalId,
|
|
30238
30283
|
physicalId
|
|
30239
30284
|
);
|
|
30240
|
-
this.logger.debug(`
|
|
30285
|
+
this.logger.debug(`DocDB DBSubnetGroup ${physicalId} does not exist, skipping deletion`);
|
|
30241
30286
|
return;
|
|
30242
30287
|
}
|
|
30243
30288
|
const cause = error instanceof Error ? error : void 0;
|
|
30244
30289
|
throw new ProvisioningError(
|
|
30245
|
-
`Failed to delete
|
|
30290
|
+
`Failed to delete DocDB DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30246
30291
|
resourceType,
|
|
30247
30292
|
logicalId,
|
|
30248
30293
|
physicalId,
|
|
@@ -30250,98 +30295,111 @@ var Route53Provider = class {
|
|
|
30250
30295
|
);
|
|
30251
30296
|
}
|
|
30252
30297
|
}
|
|
30253
|
-
|
|
30254
|
-
|
|
30255
|
-
|
|
30256
|
-
|
|
30257
|
-
case "NameServers": {
|
|
30258
|
-
const response = await this.getClient().send(new GetHostedZoneCommand2({ Id: physicalId }));
|
|
30259
|
-
return (response.DelegationSet?.NameServers ?? []).join(",");
|
|
30260
|
-
}
|
|
30261
|
-
default:
|
|
30262
|
-
return void 0;
|
|
30263
|
-
}
|
|
30264
|
-
}
|
|
30265
|
-
// ─── AWS::Route53::RecordSet ───────────────────────────────────────
|
|
30266
|
-
async createRecordSet(logicalId, resourceType, properties) {
|
|
30267
|
-
this.logger.debug(`Creating Route 53 record set ${logicalId}`);
|
|
30268
|
-
const hostedZoneId = await this.resolveHostedZoneId(properties, logicalId, resourceType);
|
|
30269
|
-
const recordName = properties["Name"];
|
|
30270
|
-
const recordType = properties["Type"];
|
|
30298
|
+
// ─── DBCluster ────────────────────────────────────────────────────
|
|
30299
|
+
async createDBCluster(logicalId, resourceType, properties) {
|
|
30300
|
+
this.logger.debug(`Creating DocDB DBCluster ${logicalId}`);
|
|
30301
|
+
const dbClusterIdentifier = properties["DBClusterIdentifier"] || generateResourceName(logicalId, { maxLength: 63, lowercase: true });
|
|
30271
30302
|
try {
|
|
30272
|
-
const
|
|
30273
|
-
const
|
|
30274
|
-
|
|
30275
|
-
|
|
30276
|
-
|
|
30277
|
-
|
|
30278
|
-
|
|
30279
|
-
|
|
30280
|
-
|
|
30281
|
-
|
|
30282
|
-
|
|
30283
|
-
|
|
30284
|
-
|
|
30285
|
-
|
|
30303
|
+
const tags = this.buildTags(properties);
|
|
30304
|
+
const response = await this.getClient().send(
|
|
30305
|
+
new CreateDBClusterCommand2({
|
|
30306
|
+
DBClusterIdentifier: dbClusterIdentifier,
|
|
30307
|
+
// DocDB engine value is fixed: only `docdb` is accepted.
|
|
30308
|
+
Engine: "docdb",
|
|
30309
|
+
EngineVersion: properties["EngineVersion"],
|
|
30310
|
+
MasterUsername: properties["MasterUsername"],
|
|
30311
|
+
MasterUserPassword: properties["MasterUserPassword"],
|
|
30312
|
+
Port: properties["Port"] != null ? Number(properties["Port"]) : void 0,
|
|
30313
|
+
VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
|
|
30314
|
+
DBSubnetGroupName: properties["DBSubnetGroupName"],
|
|
30315
|
+
StorageEncrypted: properties["StorageEncrypted"],
|
|
30316
|
+
KmsKeyId: properties["KmsKeyId"],
|
|
30317
|
+
BackupRetentionPeriod: properties["BackupRetentionPeriod"] != null ? Number(properties["BackupRetentionPeriod"]) : void 0,
|
|
30318
|
+
PreferredBackupWindow: properties["PreferredBackupWindow"],
|
|
30319
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
30320
|
+
DBClusterParameterGroupName: properties["DBClusterParameterGroupName"],
|
|
30321
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
30322
|
+
...tags.length > 0 && { Tags: tags }
|
|
30286
30323
|
})
|
|
30287
30324
|
);
|
|
30288
|
-
const
|
|
30289
|
-
|
|
30325
|
+
const cluster = response.DBCluster;
|
|
30326
|
+
if (!cluster) {
|
|
30327
|
+
throw new Error("CreateDBCluster did not return DBCluster");
|
|
30328
|
+
}
|
|
30329
|
+
this.logger.debug(
|
|
30330
|
+
`Successfully created DocDB DBCluster ${logicalId}: ${dbClusterIdentifier}`
|
|
30331
|
+
);
|
|
30332
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") {
|
|
30333
|
+
await this.waitForClusterAvailable(dbClusterIdentifier);
|
|
30334
|
+
}
|
|
30335
|
+
const described = await this.describeDBCluster(dbClusterIdentifier);
|
|
30290
30336
|
return {
|
|
30291
|
-
physicalId:
|
|
30292
|
-
attributes: {
|
|
30337
|
+
physicalId: dbClusterIdentifier,
|
|
30338
|
+
attributes: {
|
|
30339
|
+
"Endpoint.Address": described?.Endpoint ?? "",
|
|
30340
|
+
"Endpoint.Port": String(described?.Port ?? ""),
|
|
30341
|
+
"ReadEndpoint.Address": described?.ReaderEndpoint ?? "",
|
|
30342
|
+
Arn: described?.DBClusterArn ?? "",
|
|
30343
|
+
ClusterResourceId: described?.DbClusterResourceId ?? ""
|
|
30344
|
+
}
|
|
30293
30345
|
};
|
|
30294
30346
|
} catch (error) {
|
|
30295
30347
|
if (error instanceof ProvisioningError)
|
|
30296
30348
|
throw error;
|
|
30297
30349
|
const cause = error instanceof Error ? error : void 0;
|
|
30298
30350
|
throw new ProvisioningError(
|
|
30299
|
-
`Failed to create
|
|
30351
|
+
`Failed to create DocDB DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30300
30352
|
resourceType,
|
|
30301
30353
|
logicalId,
|
|
30302
|
-
|
|
30354
|
+
dbClusterIdentifier,
|
|
30303
30355
|
cause
|
|
30304
30356
|
);
|
|
30305
30357
|
}
|
|
30306
30358
|
}
|
|
30307
|
-
async
|
|
30308
|
-
this.logger.debug(`Updating
|
|
30309
|
-
const hostedZoneId = await this.resolveHostedZoneId(
|
|
30310
|
-
properties,
|
|
30311
|
-
logicalId,
|
|
30312
|
-
resourceType,
|
|
30313
|
-
physicalId
|
|
30314
|
-
);
|
|
30315
|
-
const recordName = properties["Name"];
|
|
30316
|
-
const recordType = properties["Type"];
|
|
30359
|
+
async updateDBCluster(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
30360
|
+
this.logger.debug(`Updating DocDB DBCluster ${logicalId}: ${physicalId}`);
|
|
30317
30361
|
try {
|
|
30318
|
-
const
|
|
30319
|
-
const
|
|
30362
|
+
const vpcSgIds = properties["VpcSecurityGroupIds"];
|
|
30363
|
+
const sendVpcSgIds = vpcSgIds !== void 0 && vpcSgIds.length > 0;
|
|
30320
30364
|
await this.getClient().send(
|
|
30321
|
-
new
|
|
30322
|
-
|
|
30323
|
-
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
|
|
30329
|
-
|
|
30330
|
-
|
|
30331
|
-
|
|
30365
|
+
new ModifyDBClusterCommand2({
|
|
30366
|
+
DBClusterIdentifier: physicalId,
|
|
30367
|
+
EngineVersion: properties["EngineVersion"],
|
|
30368
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
30369
|
+
BackupRetentionPeriod: properties["BackupRetentionPeriod"] != null ? Number(properties["BackupRetentionPeriod"]) : void 0,
|
|
30370
|
+
PreferredBackupWindow: properties["PreferredBackupWindow"],
|
|
30371
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
30372
|
+
DBClusterParameterGroupName: properties["DBClusterParameterGroupName"],
|
|
30373
|
+
...sendVpcSgIds && { VpcSecurityGroupIds: vpcSgIds },
|
|
30374
|
+
MasterUserPassword: properties["MasterUserPassword"],
|
|
30375
|
+
Port: properties["Port"] != null ? Number(properties["Port"]) : void 0,
|
|
30376
|
+
ApplyImmediately: true
|
|
30332
30377
|
})
|
|
30333
30378
|
);
|
|
30334
|
-
|
|
30335
|
-
|
|
30379
|
+
this.logger.debug(`Successfully updated DocDB DBCluster ${logicalId}`);
|
|
30380
|
+
const described = await this.describeDBCluster(physicalId);
|
|
30381
|
+
if (described?.DBClusterArn) {
|
|
30382
|
+
await this.applyTagDiff(
|
|
30383
|
+
described.DBClusterArn,
|
|
30384
|
+
previousProperties["Tags"],
|
|
30385
|
+
properties["Tags"]
|
|
30386
|
+
);
|
|
30387
|
+
}
|
|
30336
30388
|
return {
|
|
30337
|
-
physicalId
|
|
30389
|
+
physicalId,
|
|
30338
30390
|
wasReplaced: false,
|
|
30339
|
-
attributes: {
|
|
30391
|
+
attributes: {
|
|
30392
|
+
"Endpoint.Address": described?.Endpoint ?? "",
|
|
30393
|
+
"Endpoint.Port": String(described?.Port ?? ""),
|
|
30394
|
+
"ReadEndpoint.Address": described?.ReaderEndpoint ?? "",
|
|
30395
|
+
Arn: described?.DBClusterArn ?? "",
|
|
30396
|
+
ClusterResourceId: described?.DbClusterResourceId ?? ""
|
|
30397
|
+
}
|
|
30340
30398
|
};
|
|
30341
30399
|
} catch (error) {
|
|
30342
30400
|
const cause = error instanceof Error ? error : void 0;
|
|
30343
30401
|
throw new ProvisioningError(
|
|
30344
|
-
`Failed to update
|
|
30402
|
+
`Failed to update DocDB DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30345
30403
|
resourceType,
|
|
30346
30404
|
logicalId,
|
|
30347
30405
|
physicalId,
|
|
@@ -30349,44 +30407,39 @@ var Route53Provider = class {
|
|
|
30349
30407
|
);
|
|
30350
30408
|
}
|
|
30351
30409
|
}
|
|
30352
|
-
async
|
|
30353
|
-
this.logger.debug(`Deleting
|
|
30354
|
-
const parts = physicalId.split("|");
|
|
30355
|
-
if (parts.length !== 3) {
|
|
30356
|
-
throw new ProvisioningError(
|
|
30357
|
-
`Invalid record set physical ID format: ${physicalId}`,
|
|
30358
|
-
resourceType,
|
|
30359
|
-
logicalId,
|
|
30360
|
-
physicalId
|
|
30361
|
-
);
|
|
30362
|
-
}
|
|
30363
|
-
const [hostedZoneId] = parts;
|
|
30364
|
-
if (!properties) {
|
|
30365
|
-
throw new ProvisioningError(
|
|
30366
|
-
`Properties required to delete record set ${logicalId}`,
|
|
30367
|
-
resourceType,
|
|
30368
|
-
logicalId,
|
|
30369
|
-
physicalId
|
|
30370
|
-
);
|
|
30371
|
-
}
|
|
30410
|
+
async deleteDBCluster(logicalId, physicalId, resourceType, context) {
|
|
30411
|
+
this.logger.debug(`Deleting DocDB DBCluster ${logicalId}: ${physicalId}`);
|
|
30372
30412
|
try {
|
|
30373
|
-
|
|
30374
|
-
|
|
30375
|
-
|
|
30376
|
-
|
|
30377
|
-
|
|
30378
|
-
|
|
30379
|
-
|
|
30380
|
-
|
|
30381
|
-
|
|
30382
|
-
|
|
30383
|
-
|
|
30413
|
+
if (context?.removeProtection === true) {
|
|
30414
|
+
try {
|
|
30415
|
+
await this.getClient().send(
|
|
30416
|
+
new ModifyDBClusterCommand2({
|
|
30417
|
+
DBClusterIdentifier: physicalId,
|
|
30418
|
+
DeletionProtection: false,
|
|
30419
|
+
ApplyImmediately: true
|
|
30420
|
+
})
|
|
30421
|
+
);
|
|
30422
|
+
this.logger.debug(
|
|
30423
|
+
`Disabled DeletionProtection on DocDB DBCluster ${logicalId} before delete`
|
|
30424
|
+
);
|
|
30425
|
+
} catch (disableError) {
|
|
30426
|
+
if (!this.isNotFoundError(disableError, "DBClusterNotFoundFault")) {
|
|
30427
|
+
this.logger.debug(
|
|
30428
|
+
`Could not disable deletion protection for ${physicalId}: ${disableError instanceof Error ? disableError.message : String(disableError)}`
|
|
30429
|
+
);
|
|
30384
30430
|
}
|
|
30431
|
+
}
|
|
30432
|
+
}
|
|
30433
|
+
await this.getClient().send(
|
|
30434
|
+
new DeleteDBClusterCommand2({
|
|
30435
|
+
DBClusterIdentifier: physicalId,
|
|
30436
|
+
SkipFinalSnapshot: true
|
|
30385
30437
|
})
|
|
30386
30438
|
);
|
|
30387
|
-
this.logger.debug(`Successfully
|
|
30439
|
+
this.logger.debug(`Successfully initiated deletion of DocDB DBCluster ${logicalId}`);
|
|
30440
|
+
await this.waitForClusterDeleted(physicalId);
|
|
30388
30441
|
} catch (error) {
|
|
30389
|
-
if (
|
|
30442
|
+
if (this.isNotFoundError(error, "DBClusterNotFoundFault")) {
|
|
30390
30443
|
const clientRegion = await this.getClient().config.region();
|
|
30391
30444
|
assertRegionMatch(
|
|
30392
30445
|
clientRegion,
|
|
@@ -30395,18 +30448,12 @@ var Route53Provider = class {
|
|
|
30395
30448
|
logicalId,
|
|
30396
30449
|
physicalId
|
|
30397
30450
|
);
|
|
30398
|
-
this.logger.debug(`
|
|
30399
|
-
return;
|
|
30400
|
-
}
|
|
30401
|
-
if (error instanceof Error && error.name === "NoSuchHostedZone") {
|
|
30402
|
-
this.logger.debug(
|
|
30403
|
-
`Hosted zone for record set ${physicalId} does not exist, skipping deletion`
|
|
30404
|
-
);
|
|
30451
|
+
this.logger.debug(`DocDB DBCluster ${physicalId} does not exist, skipping deletion`);
|
|
30405
30452
|
return;
|
|
30406
30453
|
}
|
|
30407
30454
|
const cause = error instanceof Error ? error : void 0;
|
|
30408
30455
|
throw new ProvisioningError(
|
|
30409
|
-
`Failed to delete
|
|
30456
|
+
`Failed to delete DocDB DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30410
30457
|
resourceType,
|
|
30411
30458
|
logicalId,
|
|
30412
30459
|
physicalId,
|
|
@@ -30414,49 +30461,2011 @@ var Route53Provider = class {
|
|
|
30414
30461
|
);
|
|
30415
30462
|
}
|
|
30416
30463
|
}
|
|
30417
|
-
// ───
|
|
30418
|
-
|
|
30419
|
-
|
|
30420
|
-
|
|
30421
|
-
|
|
30422
|
-
|
|
30423
|
-
|
|
30424
|
-
|
|
30425
|
-
|
|
30426
|
-
|
|
30427
|
-
|
|
30428
|
-
|
|
30429
|
-
|
|
30430
|
-
|
|
30431
|
-
|
|
30432
|
-
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
|
|
30436
|
-
|
|
30437
|
-
|
|
30438
|
-
|
|
30439
|
-
|
|
30440
|
-
|
|
30441
|
-
|
|
30442
|
-
|
|
30443
|
-
if (
|
|
30444
|
-
|
|
30445
|
-
}
|
|
30446
|
-
|
|
30447
|
-
|
|
30448
|
-
|
|
30449
|
-
|
|
30450
|
-
|
|
30451
|
-
|
|
30452
|
-
|
|
30453
|
-
|
|
30454
|
-
|
|
30455
|
-
|
|
30456
|
-
|
|
30457
|
-
|
|
30458
|
-
|
|
30459
|
-
|
|
30464
|
+
// ─── DBInstance ───────────────────────────────────────────────────
|
|
30465
|
+
async createDBInstance(logicalId, resourceType, properties) {
|
|
30466
|
+
this.logger.debug(`Creating DocDB DBInstance ${logicalId}`);
|
|
30467
|
+
const dbInstanceIdentifier = properties["DBInstanceIdentifier"] || generateResourceName(logicalId, { maxLength: 63, lowercase: true });
|
|
30468
|
+
try {
|
|
30469
|
+
const tags = this.buildTags(properties);
|
|
30470
|
+
const response = await this.getClient().send(
|
|
30471
|
+
new CreateDBInstanceCommand2({
|
|
30472
|
+
DBInstanceIdentifier: dbInstanceIdentifier,
|
|
30473
|
+
DBInstanceClass: properties["DBInstanceClass"],
|
|
30474
|
+
// DocDB engine value is fixed: only `docdb` is accepted.
|
|
30475
|
+
Engine: "docdb",
|
|
30476
|
+
DBClusterIdentifier: properties["DBClusterIdentifier"],
|
|
30477
|
+
AvailabilityZone: properties["AvailabilityZone"],
|
|
30478
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
30479
|
+
AutoMinorVersionUpgrade: properties["AutoMinorVersionUpgrade"],
|
|
30480
|
+
...tags.length > 0 && { Tags: tags }
|
|
30481
|
+
})
|
|
30482
|
+
);
|
|
30483
|
+
const instance = response.DBInstance;
|
|
30484
|
+
if (!instance) {
|
|
30485
|
+
throw new Error("CreateDBInstance did not return DBInstance");
|
|
30486
|
+
}
|
|
30487
|
+
this.logger.debug(
|
|
30488
|
+
`Successfully created DocDB DBInstance ${logicalId}: ${dbInstanceIdentifier}`
|
|
30489
|
+
);
|
|
30490
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") {
|
|
30491
|
+
await this.waitForInstanceAvailable(dbInstanceIdentifier);
|
|
30492
|
+
}
|
|
30493
|
+
const described = await this.describeDBInstance(dbInstanceIdentifier);
|
|
30494
|
+
return {
|
|
30495
|
+
physicalId: dbInstanceIdentifier,
|
|
30496
|
+
attributes: {
|
|
30497
|
+
"Endpoint.Address": described?.Endpoint?.Address ?? "",
|
|
30498
|
+
"Endpoint.Port": String(described?.Endpoint?.Port ?? ""),
|
|
30499
|
+
Arn: described?.DBInstanceArn ?? ""
|
|
30500
|
+
}
|
|
30501
|
+
};
|
|
30502
|
+
} catch (error) {
|
|
30503
|
+
if (error instanceof ProvisioningError)
|
|
30504
|
+
throw error;
|
|
30505
|
+
const cause = error instanceof Error ? error : void 0;
|
|
30506
|
+
throw new ProvisioningError(
|
|
30507
|
+
`Failed to create DocDB DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30508
|
+
resourceType,
|
|
30509
|
+
logicalId,
|
|
30510
|
+
dbInstanceIdentifier,
|
|
30511
|
+
cause
|
|
30512
|
+
);
|
|
30513
|
+
}
|
|
30514
|
+
}
|
|
30515
|
+
async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
30516
|
+
this.logger.debug(`Updating DocDB DBInstance ${logicalId}: ${physicalId}`);
|
|
30517
|
+
try {
|
|
30518
|
+
await this.getClient().send(
|
|
30519
|
+
new ModifyDBInstanceCommand2({
|
|
30520
|
+
DBInstanceIdentifier: physicalId,
|
|
30521
|
+
DBInstanceClass: properties["DBInstanceClass"],
|
|
30522
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
30523
|
+
AutoMinorVersionUpgrade: properties["AutoMinorVersionUpgrade"],
|
|
30524
|
+
ApplyImmediately: true
|
|
30525
|
+
})
|
|
30526
|
+
);
|
|
30527
|
+
this.logger.debug(`Successfully updated DocDB DBInstance ${logicalId}`);
|
|
30528
|
+
const described = await this.describeDBInstance(physicalId);
|
|
30529
|
+
if (described?.DBInstanceArn) {
|
|
30530
|
+
await this.applyTagDiff(
|
|
30531
|
+
described.DBInstanceArn,
|
|
30532
|
+
previousProperties["Tags"],
|
|
30533
|
+
properties["Tags"]
|
|
30534
|
+
);
|
|
30535
|
+
}
|
|
30536
|
+
return {
|
|
30537
|
+
physicalId,
|
|
30538
|
+
wasReplaced: false,
|
|
30539
|
+
attributes: {
|
|
30540
|
+
"Endpoint.Address": described?.Endpoint?.Address ?? "",
|
|
30541
|
+
"Endpoint.Port": String(described?.Endpoint?.Port ?? ""),
|
|
30542
|
+
Arn: described?.DBInstanceArn ?? ""
|
|
30543
|
+
}
|
|
30544
|
+
};
|
|
30545
|
+
} catch (error) {
|
|
30546
|
+
const cause = error instanceof Error ? error : void 0;
|
|
30547
|
+
throw new ProvisioningError(
|
|
30548
|
+
`Failed to update DocDB DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30549
|
+
resourceType,
|
|
30550
|
+
logicalId,
|
|
30551
|
+
physicalId,
|
|
30552
|
+
cause
|
|
30553
|
+
);
|
|
30554
|
+
}
|
|
30555
|
+
}
|
|
30556
|
+
async deleteDBInstance(logicalId, physicalId, resourceType, context) {
|
|
30557
|
+
this.logger.debug(`Deleting DocDB DBInstance ${logicalId}: ${physicalId}`);
|
|
30558
|
+
try {
|
|
30559
|
+
await this.getClient().send(
|
|
30560
|
+
new DeleteDBInstanceCommand2({
|
|
30561
|
+
DBInstanceIdentifier: physicalId
|
|
30562
|
+
})
|
|
30563
|
+
);
|
|
30564
|
+
this.logger.debug(`Successfully initiated deletion of DocDB DBInstance ${logicalId}`);
|
|
30565
|
+
await this.waitForInstanceDeleted(physicalId);
|
|
30566
|
+
} catch (error) {
|
|
30567
|
+
if (this.isNotFoundError(error, "DBInstanceNotFoundFault")) {
|
|
30568
|
+
const clientRegion = await this.getClient().config.region();
|
|
30569
|
+
assertRegionMatch(
|
|
30570
|
+
clientRegion,
|
|
30571
|
+
context?.expectedRegion,
|
|
30572
|
+
resourceType,
|
|
30573
|
+
logicalId,
|
|
30574
|
+
physicalId
|
|
30575
|
+
);
|
|
30576
|
+
this.logger.debug(`DocDB DBInstance ${physicalId} does not exist, skipping deletion`);
|
|
30577
|
+
return;
|
|
30578
|
+
}
|
|
30579
|
+
const cause = error instanceof Error ? error : void 0;
|
|
30580
|
+
throw new ProvisioningError(
|
|
30581
|
+
`Failed to delete DocDB DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
30582
|
+
resourceType,
|
|
30583
|
+
logicalId,
|
|
30584
|
+
physicalId,
|
|
30585
|
+
cause
|
|
30586
|
+
);
|
|
30587
|
+
}
|
|
30588
|
+
}
|
|
30589
|
+
// ─── Helpers ──────────────────────────────────────────────────────
|
|
30590
|
+
/**
|
|
30591
|
+
* Apply a diff between old and new CFn-shape Tags arrays via DocDB's
|
|
30592
|
+
* `AddTagsToResource` / `RemoveTagsFromResource` APIs (keyed by
|
|
30593
|
+
* `ResourceName=arn`).
|
|
30594
|
+
*/
|
|
30595
|
+
async applyTagDiff(arn, oldTagsRaw, newTagsRaw) {
|
|
30596
|
+
const toMap = (tags) => {
|
|
30597
|
+
const m = /* @__PURE__ */ new Map();
|
|
30598
|
+
for (const t of tags ?? []) {
|
|
30599
|
+
if (t.Key !== void 0 && t.Value !== void 0)
|
|
30600
|
+
m.set(t.Key, t.Value);
|
|
30601
|
+
}
|
|
30602
|
+
return m;
|
|
30603
|
+
};
|
|
30604
|
+
const oldMap = toMap(oldTagsRaw);
|
|
30605
|
+
const newMap = toMap(newTagsRaw);
|
|
30606
|
+
const tagsToAdd = [];
|
|
30607
|
+
for (const [k, v] of newMap) {
|
|
30608
|
+
if (oldMap.get(k) !== v)
|
|
30609
|
+
tagsToAdd.push({ Key: k, Value: v });
|
|
30610
|
+
}
|
|
30611
|
+
const tagsToRemove = [];
|
|
30612
|
+
for (const k of oldMap.keys()) {
|
|
30613
|
+
if (!newMap.has(k))
|
|
30614
|
+
tagsToRemove.push(k);
|
|
30615
|
+
}
|
|
30616
|
+
if (tagsToRemove.length > 0) {
|
|
30617
|
+
await this.getClient().send(
|
|
30618
|
+
new RemoveTagsFromResourceCommand3({ ResourceName: arn, TagKeys: tagsToRemove })
|
|
30619
|
+
);
|
|
30620
|
+
this.logger.debug(`Removed ${tagsToRemove.length} tag(s) from DocDB resource ${arn}`);
|
|
30621
|
+
}
|
|
30622
|
+
if (tagsToAdd.length > 0) {
|
|
30623
|
+
await this.getClient().send(
|
|
30624
|
+
new AddTagsToResourceCommand3({ ResourceName: arn, Tags: tagsToAdd })
|
|
30625
|
+
);
|
|
30626
|
+
this.logger.debug(`Added/updated ${tagsToAdd.length} tag(s) on DocDB resource ${arn}`);
|
|
30627
|
+
}
|
|
30628
|
+
}
|
|
30629
|
+
buildTags(properties) {
|
|
30630
|
+
if (!properties["Tags"])
|
|
30631
|
+
return [];
|
|
30632
|
+
return properties["Tags"];
|
|
30633
|
+
}
|
|
30634
|
+
isNotFoundError(error, faultName) {
|
|
30635
|
+
if (!(error instanceof Error))
|
|
30636
|
+
return false;
|
|
30637
|
+
const name = error.name ?? "";
|
|
30638
|
+
const message = error.message.toLowerCase();
|
|
30639
|
+
return name === faultName || message.includes("not found") || message.includes("does not exist");
|
|
30640
|
+
}
|
|
30641
|
+
async describeDBCluster(dbClusterIdentifier) {
|
|
30642
|
+
const response = await this.getClient().send(
|
|
30643
|
+
new DescribeDBClustersCommand2({
|
|
30644
|
+
DBClusterIdentifier: dbClusterIdentifier
|
|
30645
|
+
})
|
|
30646
|
+
);
|
|
30647
|
+
return response.DBClusters?.[0];
|
|
30648
|
+
}
|
|
30649
|
+
async describeDBInstance(dbInstanceIdentifier) {
|
|
30650
|
+
const response = await this.getClient().send(
|
|
30651
|
+
new DescribeDBInstancesCommand2({
|
|
30652
|
+
DBInstanceIdentifier: dbInstanceIdentifier
|
|
30653
|
+
})
|
|
30654
|
+
);
|
|
30655
|
+
return response.DBInstances?.[0];
|
|
30656
|
+
}
|
|
30657
|
+
/**
|
|
30658
|
+
* Wait for a DBCluster to become available. DocDB's SDK does not ship a
|
|
30659
|
+
* `waitUntilDBClusterAvailable` waiter (only DBInstance has waiters),
|
|
30660
|
+
* so we poll Status manually with exponential backoff.
|
|
30661
|
+
*/
|
|
30662
|
+
async waitForClusterAvailable(dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
30663
|
+
const startTime = Date.now();
|
|
30664
|
+
let delay = 5e3;
|
|
30665
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
30666
|
+
const cluster = await this.describeDBCluster(dbClusterIdentifier);
|
|
30667
|
+
const status = cluster?.Status;
|
|
30668
|
+
this.logger.debug(`DocDB DBCluster ${dbClusterIdentifier} status: ${status}`);
|
|
30669
|
+
if (status === "available")
|
|
30670
|
+
return;
|
|
30671
|
+
await this.sleep(delay);
|
|
30672
|
+
delay = Math.min(delay * 2, 3e4);
|
|
30673
|
+
}
|
|
30674
|
+
throw new Error(
|
|
30675
|
+
`Timed out waiting for DocDB DBCluster ${dbClusterIdentifier} to become available`
|
|
30676
|
+
);
|
|
30677
|
+
}
|
|
30678
|
+
/**
|
|
30679
|
+
* Wait for a DBCluster to be deleted (no SDK waiter — manual poll).
|
|
30680
|
+
*/
|
|
30681
|
+
async waitForClusterDeleted(dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
30682
|
+
const startTime = Date.now();
|
|
30683
|
+
let delay = 5e3;
|
|
30684
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
30685
|
+
try {
|
|
30686
|
+
const cluster = await this.describeDBCluster(dbClusterIdentifier);
|
|
30687
|
+
const status = cluster?.Status;
|
|
30688
|
+
this.logger.debug(`DocDB DBCluster ${dbClusterIdentifier} status: ${status}`);
|
|
30689
|
+
if (!cluster)
|
|
30690
|
+
return;
|
|
30691
|
+
} catch (error) {
|
|
30692
|
+
if (this.isNotFoundError(error, "DBClusterNotFoundFault")) {
|
|
30693
|
+
return;
|
|
30694
|
+
}
|
|
30695
|
+
throw error;
|
|
30696
|
+
}
|
|
30697
|
+
await this.sleep(delay);
|
|
30698
|
+
delay = Math.min(delay * 2, 3e4);
|
|
30699
|
+
}
|
|
30700
|
+
throw new Error(`Timed out waiting for DocDB DBCluster ${dbClusterIdentifier} to be deleted`);
|
|
30701
|
+
}
|
|
30702
|
+
/**
|
|
30703
|
+
* Wait for a DBInstance to become available (manual poll — matches RDS).
|
|
30704
|
+
*/
|
|
30705
|
+
async waitForInstanceAvailable(dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
30706
|
+
const startTime = Date.now();
|
|
30707
|
+
let delay = 1e4;
|
|
30708
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
30709
|
+
const instance = await this.describeDBInstance(dbInstanceIdentifier);
|
|
30710
|
+
const status = instance?.DBInstanceStatus;
|
|
30711
|
+
this.logger.debug(`DocDB DBInstance ${dbInstanceIdentifier} status: ${status}`);
|
|
30712
|
+
if (status === "available")
|
|
30713
|
+
return;
|
|
30714
|
+
await this.sleep(delay);
|
|
30715
|
+
delay = Math.min(delay * 2, 3e4);
|
|
30716
|
+
}
|
|
30717
|
+
throw new Error(
|
|
30718
|
+
`Timed out waiting for DocDB DBInstance ${dbInstanceIdentifier} to become available`
|
|
30719
|
+
);
|
|
30720
|
+
}
|
|
30721
|
+
async waitForInstanceDeleted(dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
30722
|
+
const startTime = Date.now();
|
|
30723
|
+
let delay = 1e4;
|
|
30724
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
30725
|
+
try {
|
|
30726
|
+
const instance = await this.describeDBInstance(dbInstanceIdentifier);
|
|
30727
|
+
const status = instance?.DBInstanceStatus;
|
|
30728
|
+
this.logger.debug(`DocDB DBInstance ${dbInstanceIdentifier} status: ${status}`);
|
|
30729
|
+
if (!instance)
|
|
30730
|
+
return;
|
|
30731
|
+
} catch (error) {
|
|
30732
|
+
if (this.isNotFoundError(error, "DBInstanceNotFoundFault")) {
|
|
30733
|
+
return;
|
|
30734
|
+
}
|
|
30735
|
+
throw error;
|
|
30736
|
+
}
|
|
30737
|
+
await this.sleep(delay);
|
|
30738
|
+
delay = Math.min(delay * 2, 3e4);
|
|
30739
|
+
}
|
|
30740
|
+
throw new Error(`Timed out waiting for DocDB DBInstance ${dbInstanceIdentifier} to be deleted`);
|
|
30741
|
+
}
|
|
30742
|
+
sleep(ms) {
|
|
30743
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
30744
|
+
}
|
|
30745
|
+
/**
|
|
30746
|
+
* Adopt an existing DocDB resource into cdkd state.
|
|
30747
|
+
*
|
|
30748
|
+
* Supported types: `AWS::DocDB::DBInstance`, `AWS::DocDB::DBCluster`,
|
|
30749
|
+
* `AWS::DocDB::DBSubnetGroup`. Identifier name properties (`DBInstance
|
|
30750
|
+
* Identifier` / `DBClusterIdentifier` / `DBSubnetGroupName`) are usually
|
|
30751
|
+
* present in CDK templates; fall back to `aws:cdk:path` tag lookup via
|
|
30752
|
+
* the corresponding `Describe*` + `ListTagsForResource` pair otherwise.
|
|
30753
|
+
*/
|
|
30754
|
+
async import(input) {
|
|
30755
|
+
switch (input.resourceType) {
|
|
30756
|
+
case "AWS::DocDB::DBInstance":
|
|
30757
|
+
return this.importDBInstance(input);
|
|
30758
|
+
case "AWS::DocDB::DBCluster":
|
|
30759
|
+
return this.importDBCluster(input);
|
|
30760
|
+
case "AWS::DocDB::DBSubnetGroup":
|
|
30761
|
+
return this.importDBSubnetGroup(input);
|
|
30762
|
+
default:
|
|
30763
|
+
return null;
|
|
30764
|
+
}
|
|
30765
|
+
}
|
|
30766
|
+
/**
|
|
30767
|
+
* Read the AWS-current DocDB resource configuration in CFn-property shape.
|
|
30768
|
+
*
|
|
30769
|
+
* Each branch surfaces only the keys cdkd's `create()` accepts. Sensitive
|
|
30770
|
+
* fields like `MasterUserPassword` are NEVER surfaced (DocDB does not
|
|
30771
|
+
* return them in the Describe responses). `Tags` are surfaced via a
|
|
30772
|
+
* follow-up `ListTagsForResource(ResourceName=arn)` call.
|
|
30773
|
+
*
|
|
30774
|
+
* Returns `undefined` when the resource is gone (`*NotFoundFault`).
|
|
30775
|
+
*/
|
|
30776
|
+
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
30777
|
+
switch (resourceType) {
|
|
30778
|
+
case "AWS::DocDB::DBInstance":
|
|
30779
|
+
return this.readCurrentStateDBInstance(physicalId);
|
|
30780
|
+
case "AWS::DocDB::DBCluster":
|
|
30781
|
+
return this.readCurrentStateDBCluster(physicalId);
|
|
30782
|
+
case "AWS::DocDB::DBSubnetGroup":
|
|
30783
|
+
return this.readCurrentStateDBSubnetGroup(physicalId);
|
|
30784
|
+
default:
|
|
30785
|
+
return void 0;
|
|
30786
|
+
}
|
|
30787
|
+
}
|
|
30788
|
+
async readCurrentStateDBInstance(physicalId) {
|
|
30789
|
+
let inst;
|
|
30790
|
+
try {
|
|
30791
|
+
inst = await this.describeDBInstance(physicalId);
|
|
30792
|
+
} catch (err) {
|
|
30793
|
+
if (this.isNotFoundError(err, "DBInstanceNotFoundFault"))
|
|
30794
|
+
return void 0;
|
|
30795
|
+
throw err;
|
|
30796
|
+
}
|
|
30797
|
+
if (!inst)
|
|
30798
|
+
return void 0;
|
|
30799
|
+
const result = {};
|
|
30800
|
+
if (inst.DBInstanceIdentifier !== void 0) {
|
|
30801
|
+
result["DBInstanceIdentifier"] = inst.DBInstanceIdentifier;
|
|
30802
|
+
}
|
|
30803
|
+
if (inst.DBInstanceClass !== void 0)
|
|
30804
|
+
result["DBInstanceClass"] = inst.DBInstanceClass;
|
|
30805
|
+
if (inst.DBClusterIdentifier !== void 0) {
|
|
30806
|
+
result["DBClusterIdentifier"] = inst.DBClusterIdentifier;
|
|
30807
|
+
}
|
|
30808
|
+
if (inst.AvailabilityZone !== void 0)
|
|
30809
|
+
result["AvailabilityZone"] = inst.AvailabilityZone;
|
|
30810
|
+
if (inst.PreferredMaintenanceWindow !== void 0) {
|
|
30811
|
+
result["PreferredMaintenanceWindow"] = inst.PreferredMaintenanceWindow;
|
|
30812
|
+
}
|
|
30813
|
+
if (inst.AutoMinorVersionUpgrade !== void 0) {
|
|
30814
|
+
result["AutoMinorVersionUpgrade"] = inst.AutoMinorVersionUpgrade;
|
|
30815
|
+
}
|
|
30816
|
+
if (inst.DBInstanceArn)
|
|
30817
|
+
await this.attachTags(result, inst.DBInstanceArn);
|
|
30818
|
+
return result;
|
|
30819
|
+
}
|
|
30820
|
+
async readCurrentStateDBCluster(physicalId) {
|
|
30821
|
+
let cluster;
|
|
30822
|
+
try {
|
|
30823
|
+
cluster = await this.describeDBCluster(physicalId);
|
|
30824
|
+
} catch (err) {
|
|
30825
|
+
if (this.isNotFoundError(err, "DBClusterNotFoundFault"))
|
|
30826
|
+
return void 0;
|
|
30827
|
+
throw err;
|
|
30828
|
+
}
|
|
30829
|
+
if (!cluster)
|
|
30830
|
+
return void 0;
|
|
30831
|
+
const result = {};
|
|
30832
|
+
if (cluster.DBClusterIdentifier !== void 0) {
|
|
30833
|
+
result["DBClusterIdentifier"] = cluster.DBClusterIdentifier;
|
|
30834
|
+
}
|
|
30835
|
+
if (cluster.EngineVersion !== void 0)
|
|
30836
|
+
result["EngineVersion"] = cluster.EngineVersion;
|
|
30837
|
+
if (cluster.MasterUsername !== void 0)
|
|
30838
|
+
result["MasterUsername"] = cluster.MasterUsername;
|
|
30839
|
+
if (cluster.Port !== void 0)
|
|
30840
|
+
result["Port"] = cluster.Port;
|
|
30841
|
+
result["VpcSecurityGroupIds"] = (cluster.VpcSecurityGroups ?? []).map((sg) => sg.VpcSecurityGroupId).filter((id) => !!id);
|
|
30842
|
+
if (cluster.DBSubnetGroup !== void 0)
|
|
30843
|
+
result["DBSubnetGroupName"] = cluster.DBSubnetGroup;
|
|
30844
|
+
if (cluster.StorageEncrypted !== void 0) {
|
|
30845
|
+
result["StorageEncrypted"] = cluster.StorageEncrypted;
|
|
30846
|
+
}
|
|
30847
|
+
if (cluster.KmsKeyId !== void 0)
|
|
30848
|
+
result["KmsKeyId"] = cluster.KmsKeyId;
|
|
30849
|
+
if (cluster.BackupRetentionPeriod !== void 0) {
|
|
30850
|
+
result["BackupRetentionPeriod"] = cluster.BackupRetentionPeriod;
|
|
30851
|
+
}
|
|
30852
|
+
if (cluster.PreferredBackupWindow !== void 0) {
|
|
30853
|
+
result["PreferredBackupWindow"] = cluster.PreferredBackupWindow;
|
|
30854
|
+
}
|
|
30855
|
+
if (cluster.PreferredMaintenanceWindow !== void 0) {
|
|
30856
|
+
result["PreferredMaintenanceWindow"] = cluster.PreferredMaintenanceWindow;
|
|
30857
|
+
}
|
|
30858
|
+
if (cluster.DBClusterParameterGroup !== void 0) {
|
|
30859
|
+
result["DBClusterParameterGroupName"] = cluster.DBClusterParameterGroup;
|
|
30860
|
+
}
|
|
30861
|
+
if (cluster.DeletionProtection !== void 0) {
|
|
30862
|
+
result["DeletionProtection"] = cluster.DeletionProtection;
|
|
30863
|
+
}
|
|
30864
|
+
if (cluster.DBClusterArn)
|
|
30865
|
+
await this.attachTags(result, cluster.DBClusterArn);
|
|
30866
|
+
return result;
|
|
30867
|
+
}
|
|
30868
|
+
async readCurrentStateDBSubnetGroup(physicalId) {
|
|
30869
|
+
let resp;
|
|
30870
|
+
try {
|
|
30871
|
+
resp = await this.getClient().send(
|
|
30872
|
+
new DescribeDBSubnetGroupsCommand2({ DBSubnetGroupName: physicalId })
|
|
30873
|
+
);
|
|
30874
|
+
} catch (err) {
|
|
30875
|
+
if (this.isNotFoundError(err, "DBSubnetGroupNotFoundFault"))
|
|
30876
|
+
return void 0;
|
|
30877
|
+
throw err;
|
|
30878
|
+
}
|
|
30879
|
+
const sg = resp.DBSubnetGroups?.[0];
|
|
30880
|
+
if (!sg)
|
|
30881
|
+
return void 0;
|
|
30882
|
+
const result = {};
|
|
30883
|
+
if (sg.DBSubnetGroupName !== void 0)
|
|
30884
|
+
result["DBSubnetGroupName"] = sg.DBSubnetGroupName;
|
|
30885
|
+
if (sg.DBSubnetGroupDescription !== void 0) {
|
|
30886
|
+
result["DBSubnetGroupDescription"] = sg.DBSubnetGroupDescription;
|
|
30887
|
+
}
|
|
30888
|
+
result["SubnetIds"] = (sg.Subnets ?? []).map((s) => s.SubnetIdentifier).filter((id) => !!id);
|
|
30889
|
+
if (sg.DBSubnetGroupArn)
|
|
30890
|
+
await this.attachTags(result, sg.DBSubnetGroupArn);
|
|
30891
|
+
return result;
|
|
30892
|
+
}
|
|
30893
|
+
/**
|
|
30894
|
+
* Fetch tags via `ListTagsForResource(ResourceName=arn)` and merge them
|
|
30895
|
+
* into the result under `Tags` (CFn shape, `aws:*` filtered out, omitted
|
|
30896
|
+
* when empty). Best-effort: tag-fetch failures are logged at debug and
|
|
30897
|
+
* the key is simply left out — drift detection on configuration is more
|
|
30898
|
+
* important than fail-closing on a missing tag permission.
|
|
30899
|
+
*/
|
|
30900
|
+
async attachTags(result, arn) {
|
|
30901
|
+
try {
|
|
30902
|
+
const tagsResp = await this.getClient().send(
|
|
30903
|
+
new ListTagsForResourceCommand11({ ResourceName: arn })
|
|
30904
|
+
);
|
|
30905
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
30906
|
+
result["Tags"] = tags;
|
|
30907
|
+
} catch (err) {
|
|
30908
|
+
this.logger.debug(
|
|
30909
|
+
`DocDB ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
30910
|
+
);
|
|
30911
|
+
}
|
|
30912
|
+
}
|
|
30913
|
+
async importDBInstance(input) {
|
|
30914
|
+
const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
|
|
30915
|
+
if (explicit) {
|
|
30916
|
+
try {
|
|
30917
|
+
await this.getClient().send(
|
|
30918
|
+
new DescribeDBInstancesCommand2({ DBInstanceIdentifier: explicit })
|
|
30919
|
+
);
|
|
30920
|
+
return { physicalId: explicit, attributes: {} };
|
|
30921
|
+
} catch (err) {
|
|
30922
|
+
if (err.name === "DBInstanceNotFoundFault")
|
|
30923
|
+
return null;
|
|
30924
|
+
throw err;
|
|
30925
|
+
}
|
|
30926
|
+
}
|
|
30927
|
+
if (!input.cdkPath)
|
|
30928
|
+
return null;
|
|
30929
|
+
let marker;
|
|
30930
|
+
do {
|
|
30931
|
+
const list = await this.getClient().send(
|
|
30932
|
+
new DescribeDBInstancesCommand2({ ...marker && { Marker: marker } })
|
|
30933
|
+
);
|
|
30934
|
+
for (const inst of list.DBInstances ?? []) {
|
|
30935
|
+
if (!inst.DBInstanceIdentifier || !inst.DBInstanceArn)
|
|
30936
|
+
continue;
|
|
30937
|
+
const tagsResp = await this.getClient().send(
|
|
30938
|
+
new ListTagsForResourceCommand11({ ResourceName: inst.DBInstanceArn })
|
|
30939
|
+
);
|
|
30940
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
30941
|
+
return { physicalId: inst.DBInstanceIdentifier, attributes: {} };
|
|
30942
|
+
}
|
|
30943
|
+
}
|
|
30944
|
+
marker = list.Marker;
|
|
30945
|
+
} while (marker);
|
|
30946
|
+
return null;
|
|
30947
|
+
}
|
|
30948
|
+
async importDBCluster(input) {
|
|
30949
|
+
const explicit = resolveExplicitPhysicalId(input, "DBClusterIdentifier");
|
|
30950
|
+
if (explicit) {
|
|
30951
|
+
try {
|
|
30952
|
+
await this.getClient().send(
|
|
30953
|
+
new DescribeDBClustersCommand2({ DBClusterIdentifier: explicit })
|
|
30954
|
+
);
|
|
30955
|
+
return { physicalId: explicit, attributes: {} };
|
|
30956
|
+
} catch (err) {
|
|
30957
|
+
if (err.name === "DBClusterNotFoundFault")
|
|
30958
|
+
return null;
|
|
30959
|
+
throw err;
|
|
30960
|
+
}
|
|
30961
|
+
}
|
|
30962
|
+
if (!input.cdkPath)
|
|
30963
|
+
return null;
|
|
30964
|
+
let marker;
|
|
30965
|
+
do {
|
|
30966
|
+
const list = await this.getClient().send(
|
|
30967
|
+
new DescribeDBClustersCommand2({ ...marker && { Marker: marker } })
|
|
30968
|
+
);
|
|
30969
|
+
for (const c of list.DBClusters ?? []) {
|
|
30970
|
+
if (!c.DBClusterIdentifier || !c.DBClusterArn)
|
|
30971
|
+
continue;
|
|
30972
|
+
const tagsResp = await this.getClient().send(
|
|
30973
|
+
new ListTagsForResourceCommand11({ ResourceName: c.DBClusterArn })
|
|
30974
|
+
);
|
|
30975
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
30976
|
+
return { physicalId: c.DBClusterIdentifier, attributes: {} };
|
|
30977
|
+
}
|
|
30978
|
+
}
|
|
30979
|
+
marker = list.Marker;
|
|
30980
|
+
} while (marker);
|
|
30981
|
+
return null;
|
|
30982
|
+
}
|
|
30983
|
+
async importDBSubnetGroup(input) {
|
|
30984
|
+
const explicit = resolveExplicitPhysicalId(input, "DBSubnetGroupName");
|
|
30985
|
+
if (explicit) {
|
|
30986
|
+
try {
|
|
30987
|
+
await this.getClient().send(
|
|
30988
|
+
new DescribeDBSubnetGroupsCommand2({ DBSubnetGroupName: explicit })
|
|
30989
|
+
);
|
|
30990
|
+
return { physicalId: explicit, attributes: {} };
|
|
30991
|
+
} catch (err) {
|
|
30992
|
+
if (err.name === "DBSubnetGroupNotFoundFault")
|
|
30993
|
+
return null;
|
|
30994
|
+
throw err;
|
|
30995
|
+
}
|
|
30996
|
+
}
|
|
30997
|
+
if (!input.cdkPath)
|
|
30998
|
+
return null;
|
|
30999
|
+
let marker;
|
|
31000
|
+
do {
|
|
31001
|
+
const list = await this.getClient().send(
|
|
31002
|
+
new DescribeDBSubnetGroupsCommand2({ ...marker && { Marker: marker } })
|
|
31003
|
+
);
|
|
31004
|
+
for (const sg of list.DBSubnetGroups ?? []) {
|
|
31005
|
+
if (!sg.DBSubnetGroupName || !sg.DBSubnetGroupArn)
|
|
31006
|
+
continue;
|
|
31007
|
+
const tagsResp = await this.getClient().send(
|
|
31008
|
+
new ListTagsForResourceCommand11({ ResourceName: sg.DBSubnetGroupArn })
|
|
31009
|
+
);
|
|
31010
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
31011
|
+
return { physicalId: sg.DBSubnetGroupName, attributes: {} };
|
|
31012
|
+
}
|
|
31013
|
+
}
|
|
31014
|
+
marker = list.Marker;
|
|
31015
|
+
} while (marker);
|
|
31016
|
+
return null;
|
|
31017
|
+
}
|
|
31018
|
+
};
|
|
31019
|
+
|
|
31020
|
+
// src/provisioning/providers/neptune-provider.ts
|
|
31021
|
+
import {
|
|
31022
|
+
NeptuneClient,
|
|
31023
|
+
CreateDBClusterCommand as CreateDBClusterCommand3,
|
|
31024
|
+
DeleteDBClusterCommand as DeleteDBClusterCommand3,
|
|
31025
|
+
ModifyDBClusterCommand as ModifyDBClusterCommand3,
|
|
31026
|
+
DescribeDBClustersCommand as DescribeDBClustersCommand3,
|
|
31027
|
+
CreateDBInstanceCommand as CreateDBInstanceCommand3,
|
|
31028
|
+
DeleteDBInstanceCommand as DeleteDBInstanceCommand3,
|
|
31029
|
+
ModifyDBInstanceCommand as ModifyDBInstanceCommand3,
|
|
31030
|
+
DescribeDBInstancesCommand as DescribeDBInstancesCommand3,
|
|
31031
|
+
CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand3,
|
|
31032
|
+
DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand3,
|
|
31033
|
+
DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand3,
|
|
31034
|
+
ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand3,
|
|
31035
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand12,
|
|
31036
|
+
AddTagsToResourceCommand as AddTagsToResourceCommand4,
|
|
31037
|
+
RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand4
|
|
31038
|
+
} from "@aws-sdk/client-neptune";
|
|
31039
|
+
var NeptuneProvider = class {
|
|
31040
|
+
neptuneClient;
|
|
31041
|
+
providerRegion = process.env["AWS_REGION"];
|
|
31042
|
+
logger = getLogger().child("NeptuneProvider");
|
|
31043
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
31044
|
+
[
|
|
31045
|
+
"AWS::Neptune::DBSubnetGroup",
|
|
31046
|
+
/* @__PURE__ */ new Set(["DBSubnetGroupName", "DBSubnetGroupDescription", "SubnetIds", "Tags"])
|
|
31047
|
+
],
|
|
31048
|
+
[
|
|
31049
|
+
"AWS::Neptune::DBCluster",
|
|
31050
|
+
/* @__PURE__ */ new Set([
|
|
31051
|
+
"DBClusterIdentifier",
|
|
31052
|
+
"EngineVersion",
|
|
31053
|
+
"Port",
|
|
31054
|
+
"VpcSecurityGroupIds",
|
|
31055
|
+
"DBSubnetGroupName",
|
|
31056
|
+
"StorageEncrypted",
|
|
31057
|
+
"KmsKeyId",
|
|
31058
|
+
"BackupRetentionPeriod",
|
|
31059
|
+
"PreferredBackupWindow",
|
|
31060
|
+
"PreferredMaintenanceWindow",
|
|
31061
|
+
"DBClusterParameterGroupName",
|
|
31062
|
+
"IamAuthEnabled",
|
|
31063
|
+
"DeletionProtection",
|
|
31064
|
+
"Tags"
|
|
31065
|
+
])
|
|
31066
|
+
],
|
|
31067
|
+
[
|
|
31068
|
+
"AWS::Neptune::DBInstance",
|
|
31069
|
+
/* @__PURE__ */ new Set([
|
|
31070
|
+
"DBInstanceIdentifier",
|
|
31071
|
+
"DBInstanceClass",
|
|
31072
|
+
"DBClusterIdentifier",
|
|
31073
|
+
"DBSubnetGroupName",
|
|
31074
|
+
"DBParameterGroupName",
|
|
31075
|
+
"AvailabilityZone",
|
|
31076
|
+
"PreferredMaintenanceWindow",
|
|
31077
|
+
"AutoMinorVersionUpgrade",
|
|
31078
|
+
"DeletionProtection",
|
|
31079
|
+
"Tags"
|
|
31080
|
+
])
|
|
31081
|
+
]
|
|
31082
|
+
]);
|
|
31083
|
+
getClient() {
|
|
31084
|
+
if (!this.neptuneClient) {
|
|
31085
|
+
this.neptuneClient = new NeptuneClient(
|
|
31086
|
+
this.providerRegion ? { region: this.providerRegion } : {}
|
|
31087
|
+
);
|
|
31088
|
+
}
|
|
31089
|
+
return this.neptuneClient;
|
|
31090
|
+
}
|
|
31091
|
+
// ─── Dispatch ─────────────────────────────────────────────────────
|
|
31092
|
+
async create(logicalId, resourceType, properties) {
|
|
31093
|
+
switch (resourceType) {
|
|
31094
|
+
case "AWS::Neptune::DBSubnetGroup":
|
|
31095
|
+
return this.createDBSubnetGroup(logicalId, resourceType, properties);
|
|
31096
|
+
case "AWS::Neptune::DBCluster":
|
|
31097
|
+
return this.createDBCluster(logicalId, resourceType, properties);
|
|
31098
|
+
case "AWS::Neptune::DBInstance":
|
|
31099
|
+
return this.createDBInstance(logicalId, resourceType, properties);
|
|
31100
|
+
default:
|
|
31101
|
+
throw new ProvisioningError(
|
|
31102
|
+
`Unsupported resource type: ${resourceType}`,
|
|
31103
|
+
resourceType,
|
|
31104
|
+
logicalId
|
|
31105
|
+
);
|
|
31106
|
+
}
|
|
31107
|
+
}
|
|
31108
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
31109
|
+
switch (resourceType) {
|
|
31110
|
+
case "AWS::Neptune::DBSubnetGroup":
|
|
31111
|
+
return this.updateDBSubnetGroup(
|
|
31112
|
+
logicalId,
|
|
31113
|
+
physicalId,
|
|
31114
|
+
resourceType,
|
|
31115
|
+
properties,
|
|
31116
|
+
previousProperties
|
|
31117
|
+
);
|
|
31118
|
+
case "AWS::Neptune::DBCluster":
|
|
31119
|
+
return this.updateDBCluster(
|
|
31120
|
+
logicalId,
|
|
31121
|
+
physicalId,
|
|
31122
|
+
resourceType,
|
|
31123
|
+
properties,
|
|
31124
|
+
previousProperties
|
|
31125
|
+
);
|
|
31126
|
+
case "AWS::Neptune::DBInstance":
|
|
31127
|
+
return this.updateDBInstance(
|
|
31128
|
+
logicalId,
|
|
31129
|
+
physicalId,
|
|
31130
|
+
resourceType,
|
|
31131
|
+
properties,
|
|
31132
|
+
previousProperties
|
|
31133
|
+
);
|
|
31134
|
+
default:
|
|
31135
|
+
throw new ProvisioningError(
|
|
31136
|
+
`Unsupported resource type: ${resourceType}`,
|
|
31137
|
+
resourceType,
|
|
31138
|
+
logicalId,
|
|
31139
|
+
physicalId
|
|
31140
|
+
);
|
|
31141
|
+
}
|
|
31142
|
+
}
|
|
31143
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
31144
|
+
switch (resourceType) {
|
|
31145
|
+
case "AWS::Neptune::DBSubnetGroup":
|
|
31146
|
+
return this.deleteDBSubnetGroup(logicalId, physicalId, resourceType, context);
|
|
31147
|
+
case "AWS::Neptune::DBCluster":
|
|
31148
|
+
return this.deleteDBCluster(logicalId, physicalId, resourceType, context);
|
|
31149
|
+
case "AWS::Neptune::DBInstance":
|
|
31150
|
+
return this.deleteDBInstance(logicalId, physicalId, resourceType, context);
|
|
31151
|
+
default:
|
|
31152
|
+
throw new ProvisioningError(
|
|
31153
|
+
`Unsupported resource type: ${resourceType}`,
|
|
31154
|
+
resourceType,
|
|
31155
|
+
logicalId,
|
|
31156
|
+
physicalId
|
|
31157
|
+
);
|
|
31158
|
+
}
|
|
31159
|
+
}
|
|
31160
|
+
// ─── DBSubnetGroup ────────────────────────────────────────────────
|
|
31161
|
+
async createDBSubnetGroup(logicalId, resourceType, properties) {
|
|
31162
|
+
this.logger.debug(`Creating Neptune DBSubnetGroup ${logicalId}`);
|
|
31163
|
+
const dbSubnetGroupName = properties["DBSubnetGroupName"] || generateResourceName(logicalId, { maxLength: 255, lowercase: true });
|
|
31164
|
+
try {
|
|
31165
|
+
const tags = this.buildTags(properties);
|
|
31166
|
+
await this.getClient().send(
|
|
31167
|
+
new CreateDBSubnetGroupCommand3({
|
|
31168
|
+
DBSubnetGroupName: dbSubnetGroupName,
|
|
31169
|
+
DBSubnetGroupDescription: properties["DBSubnetGroupDescription"] || `Subnet group for ${logicalId}`,
|
|
31170
|
+
SubnetIds: properties["SubnetIds"],
|
|
31171
|
+
...tags.length > 0 && { Tags: tags }
|
|
31172
|
+
})
|
|
31173
|
+
);
|
|
31174
|
+
this.logger.debug(
|
|
31175
|
+
`Successfully created Neptune DBSubnetGroup ${logicalId}: ${dbSubnetGroupName}`
|
|
31176
|
+
);
|
|
31177
|
+
return {
|
|
31178
|
+
physicalId: dbSubnetGroupName,
|
|
31179
|
+
attributes: {
|
|
31180
|
+
DBSubnetGroupName: dbSubnetGroupName
|
|
31181
|
+
}
|
|
31182
|
+
};
|
|
31183
|
+
} catch (error) {
|
|
31184
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31185
|
+
throw new ProvisioningError(
|
|
31186
|
+
`Failed to create Neptune DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31187
|
+
resourceType,
|
|
31188
|
+
logicalId,
|
|
31189
|
+
dbSubnetGroupName,
|
|
31190
|
+
cause
|
|
31191
|
+
);
|
|
31192
|
+
}
|
|
31193
|
+
}
|
|
31194
|
+
async updateDBSubnetGroup(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
31195
|
+
this.logger.debug(`Updating Neptune DBSubnetGroup ${logicalId}: ${physicalId}`);
|
|
31196
|
+
try {
|
|
31197
|
+
const subnetIds = properties["SubnetIds"];
|
|
31198
|
+
const sendSubnetIds = subnetIds !== void 0 && subnetIds.length > 0;
|
|
31199
|
+
const modifyInput = {
|
|
31200
|
+
DBSubnetGroupName: physicalId,
|
|
31201
|
+
DBSubnetGroupDescription: properties["DBSubnetGroupDescription"],
|
|
31202
|
+
...sendSubnetIds && { SubnetIds: subnetIds }
|
|
31203
|
+
};
|
|
31204
|
+
await this.getClient().send(new ModifyDBSubnetGroupCommand3(modifyInput));
|
|
31205
|
+
const desc = await this.getClient().send(
|
|
31206
|
+
new DescribeDBSubnetGroupsCommand3({ DBSubnetGroupName: physicalId })
|
|
31207
|
+
);
|
|
31208
|
+
const arn = desc.DBSubnetGroups?.[0]?.DBSubnetGroupArn;
|
|
31209
|
+
if (arn) {
|
|
31210
|
+
await this.applyTagDiff(
|
|
31211
|
+
arn,
|
|
31212
|
+
previousProperties["Tags"],
|
|
31213
|
+
properties["Tags"]
|
|
31214
|
+
);
|
|
31215
|
+
}
|
|
31216
|
+
this.logger.debug(`Successfully updated Neptune DBSubnetGroup ${logicalId}`);
|
|
31217
|
+
return {
|
|
31218
|
+
physicalId,
|
|
31219
|
+
wasReplaced: false,
|
|
31220
|
+
attributes: {
|
|
31221
|
+
DBSubnetGroupName: physicalId
|
|
31222
|
+
}
|
|
31223
|
+
};
|
|
31224
|
+
} catch (error) {
|
|
31225
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31226
|
+
throw new ProvisioningError(
|
|
31227
|
+
`Failed to update Neptune DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31228
|
+
resourceType,
|
|
31229
|
+
logicalId,
|
|
31230
|
+
physicalId,
|
|
31231
|
+
cause
|
|
31232
|
+
);
|
|
31233
|
+
}
|
|
31234
|
+
}
|
|
31235
|
+
async deleteDBSubnetGroup(logicalId, physicalId, resourceType, context) {
|
|
31236
|
+
this.logger.debug(`Deleting Neptune DBSubnetGroup ${logicalId}: ${physicalId}`);
|
|
31237
|
+
try {
|
|
31238
|
+
await this.getClient().send(
|
|
31239
|
+
new DeleteDBSubnetGroupCommand3({
|
|
31240
|
+
DBSubnetGroupName: physicalId
|
|
31241
|
+
})
|
|
31242
|
+
);
|
|
31243
|
+
this.logger.debug(`Successfully deleted Neptune DBSubnetGroup ${logicalId}`);
|
|
31244
|
+
} catch (error) {
|
|
31245
|
+
if (this.isNotFoundError(error, "DBSubnetGroupNotFoundFault")) {
|
|
31246
|
+
const clientRegion = await this.getClient().config.region();
|
|
31247
|
+
assertRegionMatch(
|
|
31248
|
+
clientRegion,
|
|
31249
|
+
context?.expectedRegion,
|
|
31250
|
+
resourceType,
|
|
31251
|
+
logicalId,
|
|
31252
|
+
physicalId
|
|
31253
|
+
);
|
|
31254
|
+
this.logger.debug(`Neptune DBSubnetGroup ${physicalId} does not exist, skipping deletion`);
|
|
31255
|
+
return;
|
|
31256
|
+
}
|
|
31257
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31258
|
+
throw new ProvisioningError(
|
|
31259
|
+
`Failed to delete Neptune DBSubnetGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31260
|
+
resourceType,
|
|
31261
|
+
logicalId,
|
|
31262
|
+
physicalId,
|
|
31263
|
+
cause
|
|
31264
|
+
);
|
|
31265
|
+
}
|
|
31266
|
+
}
|
|
31267
|
+
// ─── DBCluster ────────────────────────────────────────────────────
|
|
31268
|
+
async createDBCluster(logicalId, resourceType, properties) {
|
|
31269
|
+
this.logger.debug(`Creating Neptune DBCluster ${logicalId}`);
|
|
31270
|
+
const dbClusterIdentifier = properties["DBClusterIdentifier"] || generateResourceName(logicalId, { maxLength: 63, lowercase: true });
|
|
31271
|
+
try {
|
|
31272
|
+
const tags = this.buildTags(properties);
|
|
31273
|
+
const response = await this.getClient().send(
|
|
31274
|
+
new CreateDBClusterCommand3({
|
|
31275
|
+
DBClusterIdentifier: dbClusterIdentifier,
|
|
31276
|
+
// Neptune engine value is fixed: only `neptune` is accepted.
|
|
31277
|
+
Engine: "neptune",
|
|
31278
|
+
EngineVersion: properties["EngineVersion"],
|
|
31279
|
+
Port: properties["Port"] != null ? Number(properties["Port"]) : void 0,
|
|
31280
|
+
VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
|
|
31281
|
+
DBSubnetGroupName: properties["DBSubnetGroupName"],
|
|
31282
|
+
StorageEncrypted: properties["StorageEncrypted"],
|
|
31283
|
+
KmsKeyId: properties["KmsKeyId"],
|
|
31284
|
+
BackupRetentionPeriod: properties["BackupRetentionPeriod"] != null ? Number(properties["BackupRetentionPeriod"]) : void 0,
|
|
31285
|
+
PreferredBackupWindow: properties["PreferredBackupWindow"],
|
|
31286
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
31287
|
+
DBClusterParameterGroupName: properties["DBClusterParameterGroupName"],
|
|
31288
|
+
EnableIAMDatabaseAuthentication: properties["IamAuthEnabled"],
|
|
31289
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
31290
|
+
...tags.length > 0 && { Tags: tags }
|
|
31291
|
+
})
|
|
31292
|
+
);
|
|
31293
|
+
const cluster = response.DBCluster;
|
|
31294
|
+
if (!cluster) {
|
|
31295
|
+
throw new Error("CreateDBCluster did not return DBCluster");
|
|
31296
|
+
}
|
|
31297
|
+
this.logger.debug(
|
|
31298
|
+
`Successfully created Neptune DBCluster ${logicalId}: ${dbClusterIdentifier}`
|
|
31299
|
+
);
|
|
31300
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") {
|
|
31301
|
+
await this.waitForClusterAvailable(dbClusterIdentifier);
|
|
31302
|
+
}
|
|
31303
|
+
const described = await this.describeDBCluster(dbClusterIdentifier);
|
|
31304
|
+
return {
|
|
31305
|
+
physicalId: dbClusterIdentifier,
|
|
31306
|
+
attributes: {
|
|
31307
|
+
"Endpoint.Address": described?.Endpoint ?? "",
|
|
31308
|
+
"Endpoint.Port": String(described?.Port ?? ""),
|
|
31309
|
+
"ReadEndpoint.Address": described?.ReaderEndpoint ?? "",
|
|
31310
|
+
ClusterResourceId: described?.DbClusterResourceId ?? ""
|
|
31311
|
+
}
|
|
31312
|
+
};
|
|
31313
|
+
} catch (error) {
|
|
31314
|
+
if (error instanceof ProvisioningError)
|
|
31315
|
+
throw error;
|
|
31316
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31317
|
+
throw new ProvisioningError(
|
|
31318
|
+
`Failed to create Neptune DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31319
|
+
resourceType,
|
|
31320
|
+
logicalId,
|
|
31321
|
+
dbClusterIdentifier,
|
|
31322
|
+
cause
|
|
31323
|
+
);
|
|
31324
|
+
}
|
|
31325
|
+
}
|
|
31326
|
+
async updateDBCluster(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
31327
|
+
this.logger.debug(`Updating Neptune DBCluster ${logicalId}: ${physicalId}`);
|
|
31328
|
+
try {
|
|
31329
|
+
const vpcSgIds = properties["VpcSecurityGroupIds"];
|
|
31330
|
+
const sendVpcSgIds = vpcSgIds !== void 0 && vpcSgIds.length > 0;
|
|
31331
|
+
await this.getClient().send(
|
|
31332
|
+
new ModifyDBClusterCommand3({
|
|
31333
|
+
DBClusterIdentifier: physicalId,
|
|
31334
|
+
EngineVersion: properties["EngineVersion"],
|
|
31335
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
31336
|
+
BackupRetentionPeriod: properties["BackupRetentionPeriod"] != null ? Number(properties["BackupRetentionPeriod"]) : void 0,
|
|
31337
|
+
PreferredBackupWindow: properties["PreferredBackupWindow"],
|
|
31338
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
31339
|
+
DBClusterParameterGroupName: properties["DBClusterParameterGroupName"],
|
|
31340
|
+
EnableIAMDatabaseAuthentication: properties["IamAuthEnabled"],
|
|
31341
|
+
...sendVpcSgIds && { VpcSecurityGroupIds: vpcSgIds },
|
|
31342
|
+
Port: properties["Port"] != null ? Number(properties["Port"]) : void 0,
|
|
31343
|
+
ApplyImmediately: true
|
|
31344
|
+
})
|
|
31345
|
+
);
|
|
31346
|
+
this.logger.debug(`Successfully updated Neptune DBCluster ${logicalId}`);
|
|
31347
|
+
const described = await this.describeDBCluster(physicalId);
|
|
31348
|
+
if (described?.DBClusterArn) {
|
|
31349
|
+
await this.applyTagDiff(
|
|
31350
|
+
described.DBClusterArn,
|
|
31351
|
+
previousProperties["Tags"],
|
|
31352
|
+
properties["Tags"]
|
|
31353
|
+
);
|
|
31354
|
+
}
|
|
31355
|
+
return {
|
|
31356
|
+
physicalId,
|
|
31357
|
+
wasReplaced: false,
|
|
31358
|
+
attributes: {
|
|
31359
|
+
"Endpoint.Address": described?.Endpoint ?? "",
|
|
31360
|
+
"Endpoint.Port": String(described?.Port ?? ""),
|
|
31361
|
+
"ReadEndpoint.Address": described?.ReaderEndpoint ?? "",
|
|
31362
|
+
ClusterResourceId: described?.DbClusterResourceId ?? ""
|
|
31363
|
+
}
|
|
31364
|
+
};
|
|
31365
|
+
} catch (error) {
|
|
31366
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31367
|
+
throw new ProvisioningError(
|
|
31368
|
+
`Failed to update Neptune DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31369
|
+
resourceType,
|
|
31370
|
+
logicalId,
|
|
31371
|
+
physicalId,
|
|
31372
|
+
cause
|
|
31373
|
+
);
|
|
31374
|
+
}
|
|
31375
|
+
}
|
|
31376
|
+
async deleteDBCluster(logicalId, physicalId, resourceType, context) {
|
|
31377
|
+
this.logger.debug(`Deleting Neptune DBCluster ${logicalId}: ${physicalId}`);
|
|
31378
|
+
try {
|
|
31379
|
+
if (context?.removeProtection === true) {
|
|
31380
|
+
try {
|
|
31381
|
+
await this.getClient().send(
|
|
31382
|
+
new ModifyDBClusterCommand3({
|
|
31383
|
+
DBClusterIdentifier: physicalId,
|
|
31384
|
+
DeletionProtection: false,
|
|
31385
|
+
ApplyImmediately: true
|
|
31386
|
+
})
|
|
31387
|
+
);
|
|
31388
|
+
this.logger.debug(
|
|
31389
|
+
`Disabled DeletionProtection on Neptune DBCluster ${logicalId} before delete`
|
|
31390
|
+
);
|
|
31391
|
+
} catch (disableError) {
|
|
31392
|
+
if (!this.isNotFoundError(disableError, "DBClusterNotFoundFault")) {
|
|
31393
|
+
this.logger.debug(
|
|
31394
|
+
`Could not disable deletion protection for ${physicalId}: ${disableError instanceof Error ? disableError.message : String(disableError)}`
|
|
31395
|
+
);
|
|
31396
|
+
}
|
|
31397
|
+
}
|
|
31398
|
+
}
|
|
31399
|
+
await this.getClient().send(
|
|
31400
|
+
new DeleteDBClusterCommand3({
|
|
31401
|
+
DBClusterIdentifier: physicalId,
|
|
31402
|
+
SkipFinalSnapshot: true
|
|
31403
|
+
})
|
|
31404
|
+
);
|
|
31405
|
+
this.logger.debug(`Successfully initiated deletion of Neptune DBCluster ${logicalId}`);
|
|
31406
|
+
await this.waitForClusterDeleted(physicalId);
|
|
31407
|
+
} catch (error) {
|
|
31408
|
+
if (this.isNotFoundError(error, "DBClusterNotFoundFault")) {
|
|
31409
|
+
const clientRegion = await this.getClient().config.region();
|
|
31410
|
+
assertRegionMatch(
|
|
31411
|
+
clientRegion,
|
|
31412
|
+
context?.expectedRegion,
|
|
31413
|
+
resourceType,
|
|
31414
|
+
logicalId,
|
|
31415
|
+
physicalId
|
|
31416
|
+
);
|
|
31417
|
+
this.logger.debug(`Neptune DBCluster ${physicalId} does not exist, skipping deletion`);
|
|
31418
|
+
return;
|
|
31419
|
+
}
|
|
31420
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31421
|
+
throw new ProvisioningError(
|
|
31422
|
+
`Failed to delete Neptune DBCluster ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31423
|
+
resourceType,
|
|
31424
|
+
logicalId,
|
|
31425
|
+
physicalId,
|
|
31426
|
+
cause
|
|
31427
|
+
);
|
|
31428
|
+
}
|
|
31429
|
+
}
|
|
31430
|
+
// ─── DBInstance ───────────────────────────────────────────────────
|
|
31431
|
+
async createDBInstance(logicalId, resourceType, properties) {
|
|
31432
|
+
this.logger.debug(`Creating Neptune DBInstance ${logicalId}`);
|
|
31433
|
+
const dbInstanceIdentifier = properties["DBInstanceIdentifier"] || generateResourceName(logicalId, { maxLength: 63, lowercase: true });
|
|
31434
|
+
try {
|
|
31435
|
+
const tags = this.buildTags(properties);
|
|
31436
|
+
const response = await this.getClient().send(
|
|
31437
|
+
new CreateDBInstanceCommand3({
|
|
31438
|
+
DBInstanceIdentifier: dbInstanceIdentifier,
|
|
31439
|
+
DBInstanceClass: properties["DBInstanceClass"],
|
|
31440
|
+
// Neptune engine value is fixed: only `neptune` is accepted.
|
|
31441
|
+
Engine: "neptune",
|
|
31442
|
+
DBClusterIdentifier: properties["DBClusterIdentifier"],
|
|
31443
|
+
DBSubnetGroupName: properties["DBSubnetGroupName"],
|
|
31444
|
+
DBParameterGroupName: properties["DBParameterGroupName"],
|
|
31445
|
+
AvailabilityZone: properties["AvailabilityZone"],
|
|
31446
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
31447
|
+
AutoMinorVersionUpgrade: properties["AutoMinorVersionUpgrade"],
|
|
31448
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
31449
|
+
...tags.length > 0 && { Tags: tags }
|
|
31450
|
+
})
|
|
31451
|
+
);
|
|
31452
|
+
const instance = response.DBInstance;
|
|
31453
|
+
if (!instance) {
|
|
31454
|
+
throw new Error("CreateDBInstance did not return DBInstance");
|
|
31455
|
+
}
|
|
31456
|
+
this.logger.debug(
|
|
31457
|
+
`Successfully created Neptune DBInstance ${logicalId}: ${dbInstanceIdentifier}`
|
|
31458
|
+
);
|
|
31459
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") {
|
|
31460
|
+
await this.waitForInstanceAvailable(dbInstanceIdentifier);
|
|
31461
|
+
}
|
|
31462
|
+
const described = await this.describeDBInstance(dbInstanceIdentifier);
|
|
31463
|
+
return {
|
|
31464
|
+
physicalId: dbInstanceIdentifier,
|
|
31465
|
+
attributes: {
|
|
31466
|
+
"Endpoint.Address": described?.Endpoint?.Address ?? "",
|
|
31467
|
+
"Endpoint.Port": String(described?.Endpoint?.Port ?? "")
|
|
31468
|
+
}
|
|
31469
|
+
};
|
|
31470
|
+
} catch (error) {
|
|
31471
|
+
if (error instanceof ProvisioningError)
|
|
31472
|
+
throw error;
|
|
31473
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31474
|
+
throw new ProvisioningError(
|
|
31475
|
+
`Failed to create Neptune DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31476
|
+
resourceType,
|
|
31477
|
+
logicalId,
|
|
31478
|
+
dbInstanceIdentifier,
|
|
31479
|
+
cause
|
|
31480
|
+
);
|
|
31481
|
+
}
|
|
31482
|
+
}
|
|
31483
|
+
async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
31484
|
+
this.logger.debug(`Updating Neptune DBInstance ${logicalId}: ${physicalId}`);
|
|
31485
|
+
try {
|
|
31486
|
+
await this.getClient().send(
|
|
31487
|
+
new ModifyDBInstanceCommand3({
|
|
31488
|
+
DBInstanceIdentifier: physicalId,
|
|
31489
|
+
DBInstanceClass: properties["DBInstanceClass"],
|
|
31490
|
+
DBParameterGroupName: properties["DBParameterGroupName"],
|
|
31491
|
+
PreferredMaintenanceWindow: properties["PreferredMaintenanceWindow"],
|
|
31492
|
+
AutoMinorVersionUpgrade: properties["AutoMinorVersionUpgrade"],
|
|
31493
|
+
DeletionProtection: properties["DeletionProtection"],
|
|
31494
|
+
ApplyImmediately: true
|
|
31495
|
+
})
|
|
31496
|
+
);
|
|
31497
|
+
this.logger.debug(`Successfully updated Neptune DBInstance ${logicalId}`);
|
|
31498
|
+
const described = await this.describeDBInstance(physicalId);
|
|
31499
|
+
if (described?.DBInstanceArn) {
|
|
31500
|
+
await this.applyTagDiff(
|
|
31501
|
+
described.DBInstanceArn,
|
|
31502
|
+
previousProperties["Tags"],
|
|
31503
|
+
properties["Tags"]
|
|
31504
|
+
);
|
|
31505
|
+
}
|
|
31506
|
+
return {
|
|
31507
|
+
physicalId,
|
|
31508
|
+
wasReplaced: false,
|
|
31509
|
+
attributes: {
|
|
31510
|
+
"Endpoint.Address": described?.Endpoint?.Address ?? "",
|
|
31511
|
+
"Endpoint.Port": String(described?.Endpoint?.Port ?? "")
|
|
31512
|
+
}
|
|
31513
|
+
};
|
|
31514
|
+
} catch (error) {
|
|
31515
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31516
|
+
throw new ProvisioningError(
|
|
31517
|
+
`Failed to update Neptune DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31518
|
+
resourceType,
|
|
31519
|
+
logicalId,
|
|
31520
|
+
physicalId,
|
|
31521
|
+
cause
|
|
31522
|
+
);
|
|
31523
|
+
}
|
|
31524
|
+
}
|
|
31525
|
+
async deleteDBInstance(logicalId, physicalId, resourceType, context) {
|
|
31526
|
+
this.logger.debug(`Deleting Neptune DBInstance ${logicalId}: ${physicalId}`);
|
|
31527
|
+
try {
|
|
31528
|
+
if (context?.removeProtection === true) {
|
|
31529
|
+
try {
|
|
31530
|
+
await this.getClient().send(
|
|
31531
|
+
new ModifyDBInstanceCommand3({
|
|
31532
|
+
DBInstanceIdentifier: physicalId,
|
|
31533
|
+
DeletionProtection: false,
|
|
31534
|
+
ApplyImmediately: true
|
|
31535
|
+
})
|
|
31536
|
+
);
|
|
31537
|
+
this.logger.debug(
|
|
31538
|
+
`Disabled DeletionProtection on Neptune DBInstance ${logicalId} before delete`
|
|
31539
|
+
);
|
|
31540
|
+
} catch (disableError) {
|
|
31541
|
+
if (!this.isNotFoundError(disableError, "DBInstanceNotFoundFault")) {
|
|
31542
|
+
this.logger.debug(
|
|
31543
|
+
`Could not disable deletion protection for ${physicalId}: ${disableError instanceof Error ? disableError.message : String(disableError)}`
|
|
31544
|
+
);
|
|
31545
|
+
}
|
|
31546
|
+
}
|
|
31547
|
+
}
|
|
31548
|
+
await this.getClient().send(
|
|
31549
|
+
new DeleteDBInstanceCommand3({
|
|
31550
|
+
DBInstanceIdentifier: physicalId,
|
|
31551
|
+
SkipFinalSnapshot: true
|
|
31552
|
+
})
|
|
31553
|
+
);
|
|
31554
|
+
this.logger.debug(`Successfully initiated deletion of Neptune DBInstance ${logicalId}`);
|
|
31555
|
+
await this.waitForInstanceDeleted(physicalId);
|
|
31556
|
+
} catch (error) {
|
|
31557
|
+
if (this.isNotFoundError(error, "DBInstanceNotFoundFault")) {
|
|
31558
|
+
const clientRegion = await this.getClient().config.region();
|
|
31559
|
+
assertRegionMatch(
|
|
31560
|
+
clientRegion,
|
|
31561
|
+
context?.expectedRegion,
|
|
31562
|
+
resourceType,
|
|
31563
|
+
logicalId,
|
|
31564
|
+
physicalId
|
|
31565
|
+
);
|
|
31566
|
+
this.logger.debug(`Neptune DBInstance ${physicalId} does not exist, skipping deletion`);
|
|
31567
|
+
return;
|
|
31568
|
+
}
|
|
31569
|
+
const cause = error instanceof Error ? error : void 0;
|
|
31570
|
+
throw new ProvisioningError(
|
|
31571
|
+
`Failed to delete Neptune DBInstance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
31572
|
+
resourceType,
|
|
31573
|
+
logicalId,
|
|
31574
|
+
physicalId,
|
|
31575
|
+
cause
|
|
31576
|
+
);
|
|
31577
|
+
}
|
|
31578
|
+
}
|
|
31579
|
+
// ─── Helpers ──────────────────────────────────────────────────────
|
|
31580
|
+
/**
|
|
31581
|
+
* Apply a diff between old and new CFn-shape Tags arrays via Neptune's
|
|
31582
|
+
* `AddTagsToResource` / `RemoveTagsFromResource` APIs (keyed by
|
|
31583
|
+
* `ResourceName=arn`).
|
|
31584
|
+
*/
|
|
31585
|
+
async applyTagDiff(arn, oldTagsRaw, newTagsRaw) {
|
|
31586
|
+
const toMap = (tags) => {
|
|
31587
|
+
const m = /* @__PURE__ */ new Map();
|
|
31588
|
+
for (const t of tags ?? []) {
|
|
31589
|
+
if (t.Key !== void 0 && t.Value !== void 0)
|
|
31590
|
+
m.set(t.Key, t.Value);
|
|
31591
|
+
}
|
|
31592
|
+
return m;
|
|
31593
|
+
};
|
|
31594
|
+
const oldMap = toMap(oldTagsRaw);
|
|
31595
|
+
const newMap = toMap(newTagsRaw);
|
|
31596
|
+
const tagsToAdd = [];
|
|
31597
|
+
for (const [k, v] of newMap) {
|
|
31598
|
+
if (oldMap.get(k) !== v)
|
|
31599
|
+
tagsToAdd.push({ Key: k, Value: v });
|
|
31600
|
+
}
|
|
31601
|
+
const tagsToRemove = [];
|
|
31602
|
+
for (const k of oldMap.keys()) {
|
|
31603
|
+
if (!newMap.has(k))
|
|
31604
|
+
tagsToRemove.push(k);
|
|
31605
|
+
}
|
|
31606
|
+
if (tagsToRemove.length > 0) {
|
|
31607
|
+
await this.getClient().send(
|
|
31608
|
+
new RemoveTagsFromResourceCommand4({ ResourceName: arn, TagKeys: tagsToRemove })
|
|
31609
|
+
);
|
|
31610
|
+
this.logger.debug(`Removed ${tagsToRemove.length} tag(s) from Neptune resource ${arn}`);
|
|
31611
|
+
}
|
|
31612
|
+
if (tagsToAdd.length > 0) {
|
|
31613
|
+
await this.getClient().send(
|
|
31614
|
+
new AddTagsToResourceCommand4({ ResourceName: arn, Tags: tagsToAdd })
|
|
31615
|
+
);
|
|
31616
|
+
this.logger.debug(`Added/updated ${tagsToAdd.length} tag(s) on Neptune resource ${arn}`);
|
|
31617
|
+
}
|
|
31618
|
+
}
|
|
31619
|
+
buildTags(properties) {
|
|
31620
|
+
if (!properties["Tags"])
|
|
31621
|
+
return [];
|
|
31622
|
+
return properties["Tags"];
|
|
31623
|
+
}
|
|
31624
|
+
isNotFoundError(error, faultName) {
|
|
31625
|
+
if (!(error instanceof Error))
|
|
31626
|
+
return false;
|
|
31627
|
+
const name = error.name ?? "";
|
|
31628
|
+
const message = error.message.toLowerCase();
|
|
31629
|
+
return name === faultName || message.includes("not found") || message.includes("does not exist");
|
|
31630
|
+
}
|
|
31631
|
+
async describeDBCluster(dbClusterIdentifier) {
|
|
31632
|
+
const response = await this.getClient().send(
|
|
31633
|
+
new DescribeDBClustersCommand3({
|
|
31634
|
+
DBClusterIdentifier: dbClusterIdentifier
|
|
31635
|
+
})
|
|
31636
|
+
);
|
|
31637
|
+
return response.DBClusters?.[0];
|
|
31638
|
+
}
|
|
31639
|
+
async describeDBInstance(dbInstanceIdentifier) {
|
|
31640
|
+
const response = await this.getClient().send(
|
|
31641
|
+
new DescribeDBInstancesCommand3({
|
|
31642
|
+
DBInstanceIdentifier: dbInstanceIdentifier
|
|
31643
|
+
})
|
|
31644
|
+
);
|
|
31645
|
+
return response.DBInstances?.[0];
|
|
31646
|
+
}
|
|
31647
|
+
/**
|
|
31648
|
+
* Wait for a DBCluster to become available (no SDK waiter — manual poll).
|
|
31649
|
+
*/
|
|
31650
|
+
async waitForClusterAvailable(dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
31651
|
+
const startTime = Date.now();
|
|
31652
|
+
let delay = 5e3;
|
|
31653
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
31654
|
+
const cluster = await this.describeDBCluster(dbClusterIdentifier);
|
|
31655
|
+
const status = cluster?.Status;
|
|
31656
|
+
this.logger.debug(`Neptune DBCluster ${dbClusterIdentifier} status: ${status}`);
|
|
31657
|
+
if (status === "available")
|
|
31658
|
+
return;
|
|
31659
|
+
await this.sleep(delay);
|
|
31660
|
+
delay = Math.min(delay * 2, 3e4);
|
|
31661
|
+
}
|
|
31662
|
+
throw new Error(
|
|
31663
|
+
`Timed out waiting for Neptune DBCluster ${dbClusterIdentifier} to become available`
|
|
31664
|
+
);
|
|
31665
|
+
}
|
|
31666
|
+
/**
|
|
31667
|
+
* Wait for a DBCluster to be deleted (no SDK waiter — manual poll).
|
|
31668
|
+
*/
|
|
31669
|
+
async waitForClusterDeleted(dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
31670
|
+
const startTime = Date.now();
|
|
31671
|
+
let delay = 5e3;
|
|
31672
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
31673
|
+
try {
|
|
31674
|
+
const cluster = await this.describeDBCluster(dbClusterIdentifier);
|
|
31675
|
+
const status = cluster?.Status;
|
|
31676
|
+
this.logger.debug(`Neptune DBCluster ${dbClusterIdentifier} status: ${status}`);
|
|
31677
|
+
if (!cluster)
|
|
31678
|
+
return;
|
|
31679
|
+
} catch (error) {
|
|
31680
|
+
if (this.isNotFoundError(error, "DBClusterNotFoundFault")) {
|
|
31681
|
+
return;
|
|
31682
|
+
}
|
|
31683
|
+
throw error;
|
|
31684
|
+
}
|
|
31685
|
+
await this.sleep(delay);
|
|
31686
|
+
delay = Math.min(delay * 2, 3e4);
|
|
31687
|
+
}
|
|
31688
|
+
throw new Error(`Timed out waiting for Neptune DBCluster ${dbClusterIdentifier} to be deleted`);
|
|
31689
|
+
}
|
|
31690
|
+
/**
|
|
31691
|
+
* Wait for a DBInstance to become available (manual poll).
|
|
31692
|
+
*/
|
|
31693
|
+
async waitForInstanceAvailable(dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
31694
|
+
const startTime = Date.now();
|
|
31695
|
+
let delay = 1e4;
|
|
31696
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
31697
|
+
const instance = await this.describeDBInstance(dbInstanceIdentifier);
|
|
31698
|
+
const status = instance?.DBInstanceStatus;
|
|
31699
|
+
this.logger.debug(`Neptune DBInstance ${dbInstanceIdentifier} status: ${status}`);
|
|
31700
|
+
if (status === "available")
|
|
31701
|
+
return;
|
|
31702
|
+
await this.sleep(delay);
|
|
31703
|
+
delay = Math.min(delay * 2, 3e4);
|
|
31704
|
+
}
|
|
31705
|
+
throw new Error(
|
|
31706
|
+
`Timed out waiting for Neptune DBInstance ${dbInstanceIdentifier} to become available`
|
|
31707
|
+
);
|
|
31708
|
+
}
|
|
31709
|
+
async waitForInstanceDeleted(dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
31710
|
+
const startTime = Date.now();
|
|
31711
|
+
let delay = 1e4;
|
|
31712
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
31713
|
+
try {
|
|
31714
|
+
const instance = await this.describeDBInstance(dbInstanceIdentifier);
|
|
31715
|
+
const status = instance?.DBInstanceStatus;
|
|
31716
|
+
this.logger.debug(`Neptune DBInstance ${dbInstanceIdentifier} status: ${status}`);
|
|
31717
|
+
if (!instance)
|
|
31718
|
+
return;
|
|
31719
|
+
} catch (error) {
|
|
31720
|
+
if (this.isNotFoundError(error, "DBInstanceNotFoundFault")) {
|
|
31721
|
+
return;
|
|
31722
|
+
}
|
|
31723
|
+
throw error;
|
|
31724
|
+
}
|
|
31725
|
+
await this.sleep(delay);
|
|
31726
|
+
delay = Math.min(delay * 2, 3e4);
|
|
31727
|
+
}
|
|
31728
|
+
throw new Error(
|
|
31729
|
+
`Timed out waiting for Neptune DBInstance ${dbInstanceIdentifier} to be deleted`
|
|
31730
|
+
);
|
|
31731
|
+
}
|
|
31732
|
+
sleep(ms) {
|
|
31733
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
31734
|
+
}
|
|
31735
|
+
/**
|
|
31736
|
+
* Adopt an existing Neptune resource into cdkd state.
|
|
31737
|
+
*/
|
|
31738
|
+
async import(input) {
|
|
31739
|
+
switch (input.resourceType) {
|
|
31740
|
+
case "AWS::Neptune::DBInstance":
|
|
31741
|
+
return this.importDBInstance(input);
|
|
31742
|
+
case "AWS::Neptune::DBCluster":
|
|
31743
|
+
return this.importDBCluster(input);
|
|
31744
|
+
case "AWS::Neptune::DBSubnetGroup":
|
|
31745
|
+
return this.importDBSubnetGroup(input);
|
|
31746
|
+
default:
|
|
31747
|
+
return null;
|
|
31748
|
+
}
|
|
31749
|
+
}
|
|
31750
|
+
/**
|
|
31751
|
+
* Read the AWS-current Neptune resource configuration in CFn-property
|
|
31752
|
+
* shape. Each branch surfaces only the keys cdkd's `create()` accepts.
|
|
31753
|
+
* Sensitive fields are NEVER surfaced. `Tags` are surfaced via a
|
|
31754
|
+
* follow-up `ListTagsForResource(ResourceName=arn)` call.
|
|
31755
|
+
*/
|
|
31756
|
+
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
31757
|
+
switch (resourceType) {
|
|
31758
|
+
case "AWS::Neptune::DBInstance":
|
|
31759
|
+
return this.readCurrentStateDBInstance(physicalId);
|
|
31760
|
+
case "AWS::Neptune::DBCluster":
|
|
31761
|
+
return this.readCurrentStateDBCluster(physicalId);
|
|
31762
|
+
case "AWS::Neptune::DBSubnetGroup":
|
|
31763
|
+
return this.readCurrentStateDBSubnetGroup(physicalId);
|
|
31764
|
+
default:
|
|
31765
|
+
return void 0;
|
|
31766
|
+
}
|
|
31767
|
+
}
|
|
31768
|
+
async readCurrentStateDBInstance(physicalId) {
|
|
31769
|
+
let inst;
|
|
31770
|
+
try {
|
|
31771
|
+
inst = await this.describeDBInstance(physicalId);
|
|
31772
|
+
} catch (err) {
|
|
31773
|
+
if (this.isNotFoundError(err, "DBInstanceNotFoundFault"))
|
|
31774
|
+
return void 0;
|
|
31775
|
+
throw err;
|
|
31776
|
+
}
|
|
31777
|
+
if (!inst)
|
|
31778
|
+
return void 0;
|
|
31779
|
+
const result = {};
|
|
31780
|
+
if (inst.DBInstanceIdentifier !== void 0) {
|
|
31781
|
+
result["DBInstanceIdentifier"] = inst.DBInstanceIdentifier;
|
|
31782
|
+
}
|
|
31783
|
+
if (inst.DBInstanceClass !== void 0)
|
|
31784
|
+
result["DBInstanceClass"] = inst.DBInstanceClass;
|
|
31785
|
+
if (inst.DBClusterIdentifier !== void 0) {
|
|
31786
|
+
result["DBClusterIdentifier"] = inst.DBClusterIdentifier;
|
|
31787
|
+
}
|
|
31788
|
+
if (inst.DBSubnetGroup?.DBSubnetGroupName !== void 0) {
|
|
31789
|
+
result["DBSubnetGroupName"] = inst.DBSubnetGroup.DBSubnetGroupName;
|
|
31790
|
+
}
|
|
31791
|
+
if (inst.AvailabilityZone !== void 0)
|
|
31792
|
+
result["AvailabilityZone"] = inst.AvailabilityZone;
|
|
31793
|
+
if (inst.PreferredMaintenanceWindow !== void 0) {
|
|
31794
|
+
result["PreferredMaintenanceWindow"] = inst.PreferredMaintenanceWindow;
|
|
31795
|
+
}
|
|
31796
|
+
if (inst.AutoMinorVersionUpgrade !== void 0) {
|
|
31797
|
+
result["AutoMinorVersionUpgrade"] = inst.AutoMinorVersionUpgrade;
|
|
31798
|
+
}
|
|
31799
|
+
if (inst.DeletionProtection !== void 0) {
|
|
31800
|
+
result["DeletionProtection"] = inst.DeletionProtection;
|
|
31801
|
+
}
|
|
31802
|
+
const pg = inst.DBParameterGroups?.[0]?.DBParameterGroupName;
|
|
31803
|
+
if (pg !== void 0)
|
|
31804
|
+
result["DBParameterGroupName"] = pg;
|
|
31805
|
+
if (inst.DBInstanceArn)
|
|
31806
|
+
await this.attachTags(result, inst.DBInstanceArn);
|
|
31807
|
+
return result;
|
|
31808
|
+
}
|
|
31809
|
+
async readCurrentStateDBCluster(physicalId) {
|
|
31810
|
+
let cluster;
|
|
31811
|
+
try {
|
|
31812
|
+
cluster = await this.describeDBCluster(physicalId);
|
|
31813
|
+
} catch (err) {
|
|
31814
|
+
if (this.isNotFoundError(err, "DBClusterNotFoundFault"))
|
|
31815
|
+
return void 0;
|
|
31816
|
+
throw err;
|
|
31817
|
+
}
|
|
31818
|
+
if (!cluster)
|
|
31819
|
+
return void 0;
|
|
31820
|
+
const result = {};
|
|
31821
|
+
if (cluster.DBClusterIdentifier !== void 0) {
|
|
31822
|
+
result["DBClusterIdentifier"] = cluster.DBClusterIdentifier;
|
|
31823
|
+
}
|
|
31824
|
+
if (cluster.EngineVersion !== void 0)
|
|
31825
|
+
result["EngineVersion"] = cluster.EngineVersion;
|
|
31826
|
+
if (cluster.Port !== void 0)
|
|
31827
|
+
result["Port"] = cluster.Port;
|
|
31828
|
+
result["VpcSecurityGroupIds"] = (cluster.VpcSecurityGroups ?? []).map((sg) => sg.VpcSecurityGroupId).filter((id) => !!id);
|
|
31829
|
+
if (cluster.DBSubnetGroup !== void 0)
|
|
31830
|
+
result["DBSubnetGroupName"] = cluster.DBSubnetGroup;
|
|
31831
|
+
if (cluster.StorageEncrypted !== void 0) {
|
|
31832
|
+
result["StorageEncrypted"] = cluster.StorageEncrypted;
|
|
31833
|
+
}
|
|
31834
|
+
if (cluster.KmsKeyId !== void 0)
|
|
31835
|
+
result["KmsKeyId"] = cluster.KmsKeyId;
|
|
31836
|
+
if (cluster.BackupRetentionPeriod !== void 0) {
|
|
31837
|
+
result["BackupRetentionPeriod"] = cluster.BackupRetentionPeriod;
|
|
31838
|
+
}
|
|
31839
|
+
if (cluster.PreferredBackupWindow !== void 0) {
|
|
31840
|
+
result["PreferredBackupWindow"] = cluster.PreferredBackupWindow;
|
|
31841
|
+
}
|
|
31842
|
+
if (cluster.PreferredMaintenanceWindow !== void 0) {
|
|
31843
|
+
result["PreferredMaintenanceWindow"] = cluster.PreferredMaintenanceWindow;
|
|
31844
|
+
}
|
|
31845
|
+
if (cluster.DBClusterParameterGroup !== void 0) {
|
|
31846
|
+
result["DBClusterParameterGroupName"] = cluster.DBClusterParameterGroup;
|
|
31847
|
+
}
|
|
31848
|
+
if (cluster.IAMDatabaseAuthenticationEnabled !== void 0) {
|
|
31849
|
+
result["IamAuthEnabled"] = cluster.IAMDatabaseAuthenticationEnabled;
|
|
31850
|
+
}
|
|
31851
|
+
if (cluster.DeletionProtection !== void 0) {
|
|
31852
|
+
result["DeletionProtection"] = cluster.DeletionProtection;
|
|
31853
|
+
}
|
|
31854
|
+
if (cluster.DBClusterArn)
|
|
31855
|
+
await this.attachTags(result, cluster.DBClusterArn);
|
|
31856
|
+
return result;
|
|
31857
|
+
}
|
|
31858
|
+
async readCurrentStateDBSubnetGroup(physicalId) {
|
|
31859
|
+
let resp;
|
|
31860
|
+
try {
|
|
31861
|
+
resp = await this.getClient().send(
|
|
31862
|
+
new DescribeDBSubnetGroupsCommand3({ DBSubnetGroupName: physicalId })
|
|
31863
|
+
);
|
|
31864
|
+
} catch (err) {
|
|
31865
|
+
if (this.isNotFoundError(err, "DBSubnetGroupNotFoundFault"))
|
|
31866
|
+
return void 0;
|
|
31867
|
+
throw err;
|
|
31868
|
+
}
|
|
31869
|
+
const sg = resp.DBSubnetGroups?.[0];
|
|
31870
|
+
if (!sg)
|
|
31871
|
+
return void 0;
|
|
31872
|
+
const result = {};
|
|
31873
|
+
if (sg.DBSubnetGroupName !== void 0)
|
|
31874
|
+
result["DBSubnetGroupName"] = sg.DBSubnetGroupName;
|
|
31875
|
+
if (sg.DBSubnetGroupDescription !== void 0) {
|
|
31876
|
+
result["DBSubnetGroupDescription"] = sg.DBSubnetGroupDescription;
|
|
31877
|
+
}
|
|
31878
|
+
result["SubnetIds"] = (sg.Subnets ?? []).map((s) => s.SubnetIdentifier).filter((id) => !!id);
|
|
31879
|
+
if (sg.DBSubnetGroupArn)
|
|
31880
|
+
await this.attachTags(result, sg.DBSubnetGroupArn);
|
|
31881
|
+
return result;
|
|
31882
|
+
}
|
|
31883
|
+
/**
|
|
31884
|
+
* Fetch tags via `ListTagsForResource` and merge them into the result
|
|
31885
|
+
* under `Tags` (CFn shape). Best-effort.
|
|
31886
|
+
*/
|
|
31887
|
+
async attachTags(result, arn) {
|
|
31888
|
+
try {
|
|
31889
|
+
const tagsResp = await this.getClient().send(
|
|
31890
|
+
new ListTagsForResourceCommand12({ ResourceName: arn })
|
|
31891
|
+
);
|
|
31892
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
31893
|
+
result["Tags"] = tags;
|
|
31894
|
+
} catch (err) {
|
|
31895
|
+
this.logger.debug(
|
|
31896
|
+
`Neptune ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
31897
|
+
);
|
|
31898
|
+
}
|
|
31899
|
+
}
|
|
31900
|
+
async importDBInstance(input) {
|
|
31901
|
+
const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
|
|
31902
|
+
if (explicit) {
|
|
31903
|
+
try {
|
|
31904
|
+
await this.getClient().send(
|
|
31905
|
+
new DescribeDBInstancesCommand3({ DBInstanceIdentifier: explicit })
|
|
31906
|
+
);
|
|
31907
|
+
return { physicalId: explicit, attributes: {} };
|
|
31908
|
+
} catch (err) {
|
|
31909
|
+
if (err.name === "DBInstanceNotFoundFault")
|
|
31910
|
+
return null;
|
|
31911
|
+
throw err;
|
|
31912
|
+
}
|
|
31913
|
+
}
|
|
31914
|
+
if (!input.cdkPath)
|
|
31915
|
+
return null;
|
|
31916
|
+
let marker;
|
|
31917
|
+
do {
|
|
31918
|
+
const list = await this.getClient().send(
|
|
31919
|
+
new DescribeDBInstancesCommand3({ ...marker && { Marker: marker } })
|
|
31920
|
+
);
|
|
31921
|
+
for (const inst of list.DBInstances ?? []) {
|
|
31922
|
+
if (!inst.DBInstanceIdentifier || !inst.DBInstanceArn)
|
|
31923
|
+
continue;
|
|
31924
|
+
const tagsResp = await this.getClient().send(
|
|
31925
|
+
new ListTagsForResourceCommand12({ ResourceName: inst.DBInstanceArn })
|
|
31926
|
+
);
|
|
31927
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
31928
|
+
return { physicalId: inst.DBInstanceIdentifier, attributes: {} };
|
|
31929
|
+
}
|
|
31930
|
+
}
|
|
31931
|
+
marker = list.Marker;
|
|
31932
|
+
} while (marker);
|
|
31933
|
+
return null;
|
|
31934
|
+
}
|
|
31935
|
+
async importDBCluster(input) {
|
|
31936
|
+
const explicit = resolveExplicitPhysicalId(input, "DBClusterIdentifier");
|
|
31937
|
+
if (explicit) {
|
|
31938
|
+
try {
|
|
31939
|
+
await this.getClient().send(
|
|
31940
|
+
new DescribeDBClustersCommand3({ DBClusterIdentifier: explicit })
|
|
31941
|
+
);
|
|
31942
|
+
return { physicalId: explicit, attributes: {} };
|
|
31943
|
+
} catch (err) {
|
|
31944
|
+
if (err.name === "DBClusterNotFoundFault")
|
|
31945
|
+
return null;
|
|
31946
|
+
throw err;
|
|
31947
|
+
}
|
|
31948
|
+
}
|
|
31949
|
+
if (!input.cdkPath)
|
|
31950
|
+
return null;
|
|
31951
|
+
let marker;
|
|
31952
|
+
do {
|
|
31953
|
+
const list = await this.getClient().send(
|
|
31954
|
+
new DescribeDBClustersCommand3({ ...marker && { Marker: marker } })
|
|
31955
|
+
);
|
|
31956
|
+
for (const c of list.DBClusters ?? []) {
|
|
31957
|
+
if (!c.DBClusterIdentifier || !c.DBClusterArn)
|
|
31958
|
+
continue;
|
|
31959
|
+
const tagsResp = await this.getClient().send(
|
|
31960
|
+
new ListTagsForResourceCommand12({ ResourceName: c.DBClusterArn })
|
|
31961
|
+
);
|
|
31962
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
31963
|
+
return { physicalId: c.DBClusterIdentifier, attributes: {} };
|
|
31964
|
+
}
|
|
31965
|
+
}
|
|
31966
|
+
marker = list.Marker;
|
|
31967
|
+
} while (marker);
|
|
31968
|
+
return null;
|
|
31969
|
+
}
|
|
31970
|
+
async importDBSubnetGroup(input) {
|
|
31971
|
+
const explicit = resolveExplicitPhysicalId(input, "DBSubnetGroupName");
|
|
31972
|
+
if (explicit) {
|
|
31973
|
+
try {
|
|
31974
|
+
await this.getClient().send(
|
|
31975
|
+
new DescribeDBSubnetGroupsCommand3({ DBSubnetGroupName: explicit })
|
|
31976
|
+
);
|
|
31977
|
+
return { physicalId: explicit, attributes: {} };
|
|
31978
|
+
} catch (err) {
|
|
31979
|
+
if (err.name === "DBSubnetGroupNotFoundFault")
|
|
31980
|
+
return null;
|
|
31981
|
+
throw err;
|
|
31982
|
+
}
|
|
31983
|
+
}
|
|
31984
|
+
if (!input.cdkPath)
|
|
31985
|
+
return null;
|
|
31986
|
+
let marker;
|
|
31987
|
+
do {
|
|
31988
|
+
const list = await this.getClient().send(
|
|
31989
|
+
new DescribeDBSubnetGroupsCommand3({ ...marker && { Marker: marker } })
|
|
31990
|
+
);
|
|
31991
|
+
for (const sg of list.DBSubnetGroups ?? []) {
|
|
31992
|
+
if (!sg.DBSubnetGroupName || !sg.DBSubnetGroupArn)
|
|
31993
|
+
continue;
|
|
31994
|
+
const tagsResp = await this.getClient().send(
|
|
31995
|
+
new ListTagsForResourceCommand12({ ResourceName: sg.DBSubnetGroupArn })
|
|
31996
|
+
);
|
|
31997
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
31998
|
+
return { physicalId: sg.DBSubnetGroupName, attributes: {} };
|
|
31999
|
+
}
|
|
32000
|
+
}
|
|
32001
|
+
marker = list.Marker;
|
|
32002
|
+
} while (marker);
|
|
32003
|
+
return null;
|
|
32004
|
+
}
|
|
32005
|
+
};
|
|
32006
|
+
|
|
32007
|
+
// src/provisioning/providers/route53-provider.ts
|
|
32008
|
+
import {
|
|
32009
|
+
Route53Client as Route53Client2,
|
|
32010
|
+
CreateHostedZoneCommand,
|
|
32011
|
+
DeleteHostedZoneCommand,
|
|
32012
|
+
GetHostedZoneCommand as GetHostedZoneCommand2,
|
|
32013
|
+
ChangeResourceRecordSetsCommand,
|
|
32014
|
+
UpdateHostedZoneCommentCommand,
|
|
32015
|
+
ChangeTagsForResourceCommand,
|
|
32016
|
+
AssociateVPCWithHostedZoneCommand,
|
|
32017
|
+
DisassociateVPCFromHostedZoneCommand,
|
|
32018
|
+
CreateQueryLoggingConfigCommand,
|
|
32019
|
+
DeleteQueryLoggingConfigCommand,
|
|
32020
|
+
ListQueryLoggingConfigsCommand,
|
|
32021
|
+
ListHostedZonesByNameCommand as ListHostedZonesByNameCommand2,
|
|
32022
|
+
ListHostedZonesCommand,
|
|
32023
|
+
ListResourceRecordSetsCommand,
|
|
32024
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand13
|
|
32025
|
+
} from "@aws-sdk/client-route-53";
|
|
32026
|
+
var Route53Provider = class {
|
|
32027
|
+
route53Client;
|
|
32028
|
+
providerRegion = process.env["AWS_REGION"];
|
|
32029
|
+
logger = getLogger().child("Route53Provider");
|
|
32030
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
32031
|
+
[
|
|
32032
|
+
"AWS::Route53::HostedZone",
|
|
32033
|
+
/* @__PURE__ */ new Set(["Name", "HostedZoneConfig", "HostedZoneTags", "VPCs", "QueryLoggingConfig"])
|
|
32034
|
+
],
|
|
32035
|
+
[
|
|
32036
|
+
"AWS::Route53::RecordSet",
|
|
32037
|
+
/* @__PURE__ */ new Set([
|
|
32038
|
+
"HostedZoneId",
|
|
32039
|
+
"HostedZoneName",
|
|
32040
|
+
"Name",
|
|
32041
|
+
"Type",
|
|
32042
|
+
"TTL",
|
|
32043
|
+
"ResourceRecords",
|
|
32044
|
+
"AliasTarget",
|
|
32045
|
+
"SetIdentifier",
|
|
32046
|
+
"Weight",
|
|
32047
|
+
"Region",
|
|
32048
|
+
"Failover",
|
|
32049
|
+
"MultiValueAnswer",
|
|
32050
|
+
"HealthCheckId",
|
|
32051
|
+
"Comment",
|
|
32052
|
+
"GeoLocation"
|
|
32053
|
+
])
|
|
32054
|
+
]
|
|
32055
|
+
]);
|
|
32056
|
+
getClient() {
|
|
32057
|
+
if (!this.route53Client) {
|
|
32058
|
+
this.route53Client = new Route53Client2(
|
|
32059
|
+
this.providerRegion ? { region: this.providerRegion } : {}
|
|
32060
|
+
);
|
|
32061
|
+
}
|
|
32062
|
+
return this.route53Client;
|
|
32063
|
+
}
|
|
32064
|
+
// ─── Dispatch ─────────────────────────────────────────────────────
|
|
32065
|
+
async create(logicalId, resourceType, properties) {
|
|
32066
|
+
switch (resourceType) {
|
|
32067
|
+
case "AWS::Route53::HostedZone":
|
|
32068
|
+
return this.createHostedZone(logicalId, resourceType, properties);
|
|
32069
|
+
case "AWS::Route53::RecordSet":
|
|
32070
|
+
return this.createRecordSet(logicalId, resourceType, properties);
|
|
32071
|
+
default:
|
|
32072
|
+
throw new ProvisioningError(
|
|
32073
|
+
`Unsupported resource type: ${resourceType}`,
|
|
32074
|
+
resourceType,
|
|
32075
|
+
logicalId
|
|
32076
|
+
);
|
|
32077
|
+
}
|
|
32078
|
+
}
|
|
32079
|
+
async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
32080
|
+
switch (resourceType) {
|
|
32081
|
+
case "AWS::Route53::HostedZone":
|
|
32082
|
+
return this.updateHostedZone(logicalId, physicalId, resourceType, properties);
|
|
32083
|
+
case "AWS::Route53::RecordSet":
|
|
32084
|
+
return this.updateRecordSet(logicalId, physicalId, resourceType, properties);
|
|
32085
|
+
default:
|
|
32086
|
+
throw new ProvisioningError(
|
|
32087
|
+
`Unsupported resource type: ${resourceType}`,
|
|
32088
|
+
resourceType,
|
|
32089
|
+
logicalId,
|
|
32090
|
+
physicalId
|
|
32091
|
+
);
|
|
32092
|
+
}
|
|
32093
|
+
}
|
|
32094
|
+
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
32095
|
+
switch (resourceType) {
|
|
32096
|
+
case "AWS::Route53::HostedZone":
|
|
32097
|
+
return this.deleteHostedZone(logicalId, physicalId, resourceType, context);
|
|
32098
|
+
case "AWS::Route53::RecordSet":
|
|
32099
|
+
return this.deleteRecordSet(logicalId, physicalId, resourceType, properties, context);
|
|
32100
|
+
default:
|
|
32101
|
+
throw new ProvisioningError(
|
|
32102
|
+
`Unsupported resource type: ${resourceType}`,
|
|
32103
|
+
resourceType,
|
|
32104
|
+
logicalId,
|
|
32105
|
+
physicalId
|
|
32106
|
+
);
|
|
32107
|
+
}
|
|
32108
|
+
}
|
|
32109
|
+
async getAttribute(physicalId, resourceType, attributeName) {
|
|
32110
|
+
switch (resourceType) {
|
|
32111
|
+
case "AWS::Route53::HostedZone":
|
|
32112
|
+
return this.getHostedZoneAttribute(physicalId, attributeName);
|
|
32113
|
+
default:
|
|
32114
|
+
return void 0;
|
|
32115
|
+
}
|
|
32116
|
+
}
|
|
32117
|
+
// ─── AWS::Route53::HostedZone ──────────────────────────────────────
|
|
32118
|
+
async createHostedZone(logicalId, resourceType, properties) {
|
|
32119
|
+
this.logger.debug(`Creating Route 53 hosted zone ${logicalId}`);
|
|
32120
|
+
const name = properties["Name"];
|
|
32121
|
+
if (!name) {
|
|
32122
|
+
throw new ProvisioningError(
|
|
32123
|
+
`Name is required for hosted zone ${logicalId}`,
|
|
32124
|
+
resourceType,
|
|
32125
|
+
logicalId
|
|
32126
|
+
);
|
|
32127
|
+
}
|
|
32128
|
+
try {
|
|
32129
|
+
const hostedZoneConfig = properties["HostedZoneConfig"];
|
|
32130
|
+
const vpcs = properties["VPCs"];
|
|
32131
|
+
const firstVpc = vpcs && vpcs.length > 0 ? vpcs[0] : void 0;
|
|
32132
|
+
const response = await this.getClient().send(
|
|
32133
|
+
new CreateHostedZoneCommand({
|
|
32134
|
+
Name: name,
|
|
32135
|
+
CallerReference: `${logicalId}-${Date.now()}`,
|
|
32136
|
+
...hostedZoneConfig && hostedZoneConfig["Comment"] ? {
|
|
32137
|
+
HostedZoneConfig: {
|
|
32138
|
+
Comment: hostedZoneConfig["Comment"],
|
|
32139
|
+
// When VPCs are specified, this is a private hosted zone
|
|
32140
|
+
...firstVpc ? { PrivateZone: true } : {}
|
|
32141
|
+
}
|
|
32142
|
+
} : firstVpc ? { HostedZoneConfig: { PrivateZone: true } } : {},
|
|
32143
|
+
...firstVpc ? {
|
|
32144
|
+
VPC: {
|
|
32145
|
+
VPCId: firstVpc["VPCId"],
|
|
32146
|
+
VPCRegion: firstVpc["VPCRegion"]
|
|
32147
|
+
}
|
|
32148
|
+
} : {}
|
|
32149
|
+
})
|
|
32150
|
+
);
|
|
32151
|
+
const hostedZone = response.HostedZone;
|
|
32152
|
+
if (!hostedZone?.Id) {
|
|
32153
|
+
throw new Error("CreateHostedZone did not return HostedZone.Id");
|
|
32154
|
+
}
|
|
32155
|
+
const zoneId = hostedZone.Id.replace("/hostedzone/", "");
|
|
32156
|
+
if (vpcs && vpcs.length > 1) {
|
|
32157
|
+
for (let i = 1; i < vpcs.length; i++) {
|
|
32158
|
+
const additionalVpc = vpcs[i];
|
|
32159
|
+
this.logger.debug(
|
|
32160
|
+
`Associating additional VPC ${String(additionalVpc["VPCId"])} with hosted zone ${zoneId}`
|
|
32161
|
+
);
|
|
32162
|
+
await this.getClient().send(
|
|
32163
|
+
new AssociateVPCWithHostedZoneCommand({
|
|
32164
|
+
HostedZoneId: zoneId,
|
|
32165
|
+
VPC: {
|
|
32166
|
+
VPCId: additionalVpc["VPCId"],
|
|
32167
|
+
VPCRegion: additionalVpc["VPCRegion"]
|
|
32168
|
+
}
|
|
32169
|
+
})
|
|
32170
|
+
);
|
|
32171
|
+
}
|
|
32172
|
+
}
|
|
32173
|
+
await this.applyHostedZoneTags(zoneId, properties, logicalId);
|
|
32174
|
+
await this.applyQueryLoggingConfig(zoneId, properties, logicalId);
|
|
32175
|
+
const nameServers = response.DelegationSet?.NameServers ?? [];
|
|
32176
|
+
this.logger.debug(`Successfully created hosted zone ${logicalId}: ${zoneId}`);
|
|
32177
|
+
return {
|
|
32178
|
+
physicalId: zoneId,
|
|
32179
|
+
attributes: {
|
|
32180
|
+
Id: zoneId,
|
|
32181
|
+
NameServers: nameServers.join(",")
|
|
32182
|
+
}
|
|
32183
|
+
};
|
|
32184
|
+
} catch (error) {
|
|
32185
|
+
if (error instanceof ProvisioningError)
|
|
32186
|
+
throw error;
|
|
32187
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32188
|
+
throw new ProvisioningError(
|
|
32189
|
+
`Failed to create hosted zone ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32190
|
+
resourceType,
|
|
32191
|
+
logicalId,
|
|
32192
|
+
void 0,
|
|
32193
|
+
cause
|
|
32194
|
+
);
|
|
32195
|
+
}
|
|
32196
|
+
}
|
|
32197
|
+
async updateHostedZone(logicalId, physicalId, resourceType, properties) {
|
|
32198
|
+
this.logger.debug(`Updating Route 53 hosted zone ${logicalId}: ${physicalId}`);
|
|
32199
|
+
try {
|
|
32200
|
+
const hostedZoneConfig = properties["HostedZoneConfig"];
|
|
32201
|
+
const comment = hostedZoneConfig?.["Comment"] ?? "";
|
|
32202
|
+
await this.getClient().send(
|
|
32203
|
+
new UpdateHostedZoneCommentCommand({
|
|
32204
|
+
Id: physicalId,
|
|
32205
|
+
Comment: comment
|
|
32206
|
+
})
|
|
32207
|
+
);
|
|
32208
|
+
await this.applyHostedZoneTags(physicalId, properties, logicalId);
|
|
32209
|
+
await this.applyQueryLoggingConfig(physicalId, properties, logicalId);
|
|
32210
|
+
await this.syncVPCAssociations(physicalId, properties, logicalId);
|
|
32211
|
+
const getResponse = await this.getClient().send(new GetHostedZoneCommand2({ Id: physicalId }));
|
|
32212
|
+
const nameServers = getResponse.DelegationSet?.NameServers ?? [];
|
|
32213
|
+
this.logger.debug(`Successfully updated hosted zone ${logicalId}`);
|
|
32214
|
+
return {
|
|
32215
|
+
physicalId,
|
|
32216
|
+
wasReplaced: false,
|
|
32217
|
+
attributes: {
|
|
32218
|
+
Id: physicalId,
|
|
32219
|
+
NameServers: nameServers.join(",")
|
|
32220
|
+
}
|
|
32221
|
+
};
|
|
32222
|
+
} catch (error) {
|
|
32223
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32224
|
+
throw new ProvisioningError(
|
|
32225
|
+
`Failed to update hosted zone ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32226
|
+
resourceType,
|
|
32227
|
+
logicalId,
|
|
32228
|
+
physicalId,
|
|
32229
|
+
cause
|
|
32230
|
+
);
|
|
32231
|
+
}
|
|
32232
|
+
}
|
|
32233
|
+
async deleteHostedZone(logicalId, physicalId, resourceType, context) {
|
|
32234
|
+
this.logger.debug(`Deleting Route 53 hosted zone ${logicalId}: ${physicalId}`);
|
|
32235
|
+
try {
|
|
32236
|
+
await this.deleteQueryLoggingConfigForZone(physicalId, logicalId);
|
|
32237
|
+
await this.getClient().send(new DeleteHostedZoneCommand({ Id: physicalId }));
|
|
32238
|
+
this.logger.debug(`Successfully deleted hosted zone ${logicalId}`);
|
|
32239
|
+
} catch (error) {
|
|
32240
|
+
if (error instanceof Error && error.name === "NoSuchHostedZone") {
|
|
32241
|
+
const clientRegion = await this.getClient().config.region();
|
|
32242
|
+
assertRegionMatch(
|
|
32243
|
+
clientRegion,
|
|
32244
|
+
context?.expectedRegion,
|
|
32245
|
+
resourceType,
|
|
32246
|
+
logicalId,
|
|
32247
|
+
physicalId
|
|
32248
|
+
);
|
|
32249
|
+
this.logger.debug(`Hosted zone ${physicalId} does not exist, skipping deletion`);
|
|
32250
|
+
return;
|
|
32251
|
+
}
|
|
32252
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32253
|
+
throw new ProvisioningError(
|
|
32254
|
+
`Failed to delete hosted zone ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32255
|
+
resourceType,
|
|
32256
|
+
logicalId,
|
|
32257
|
+
physicalId,
|
|
32258
|
+
cause
|
|
32259
|
+
);
|
|
32260
|
+
}
|
|
32261
|
+
}
|
|
32262
|
+
async getHostedZoneAttribute(physicalId, attributeName) {
|
|
32263
|
+
switch (attributeName) {
|
|
32264
|
+
case "Id":
|
|
32265
|
+
return physicalId;
|
|
32266
|
+
case "NameServers": {
|
|
32267
|
+
const response = await this.getClient().send(new GetHostedZoneCommand2({ Id: physicalId }));
|
|
32268
|
+
return (response.DelegationSet?.NameServers ?? []).join(",");
|
|
32269
|
+
}
|
|
32270
|
+
default:
|
|
32271
|
+
return void 0;
|
|
32272
|
+
}
|
|
32273
|
+
}
|
|
32274
|
+
// ─── AWS::Route53::RecordSet ───────────────────────────────────────
|
|
32275
|
+
async createRecordSet(logicalId, resourceType, properties) {
|
|
32276
|
+
this.logger.debug(`Creating Route 53 record set ${logicalId}`);
|
|
32277
|
+
const hostedZoneId = await this.resolveHostedZoneId(properties, logicalId, resourceType);
|
|
32278
|
+
const recordName = properties["Name"];
|
|
32279
|
+
const recordType = properties["Type"];
|
|
32280
|
+
try {
|
|
32281
|
+
const resourceRecordSet = this.buildResourceRecordSet(properties);
|
|
32282
|
+
const comment = properties["Comment"];
|
|
32283
|
+
await this.getClient().send(
|
|
32284
|
+
new ChangeResourceRecordSetsCommand({
|
|
32285
|
+
HostedZoneId: hostedZoneId,
|
|
32286
|
+
ChangeBatch: {
|
|
32287
|
+
...comment ? { Comment: comment } : {},
|
|
32288
|
+
Changes: [
|
|
32289
|
+
{
|
|
32290
|
+
Action: "CREATE",
|
|
32291
|
+
ResourceRecordSet: resourceRecordSet
|
|
32292
|
+
}
|
|
32293
|
+
]
|
|
32294
|
+
}
|
|
32295
|
+
})
|
|
32296
|
+
);
|
|
32297
|
+
const compositeId = `${hostedZoneId}|${recordName}|${recordType}`;
|
|
32298
|
+
this.logger.debug(`Successfully created record set ${logicalId}: ${compositeId}`);
|
|
32299
|
+
return {
|
|
32300
|
+
physicalId: compositeId,
|
|
32301
|
+
attributes: {}
|
|
32302
|
+
};
|
|
32303
|
+
} catch (error) {
|
|
32304
|
+
if (error instanceof ProvisioningError)
|
|
32305
|
+
throw error;
|
|
32306
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32307
|
+
throw new ProvisioningError(
|
|
32308
|
+
`Failed to create record set ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32309
|
+
resourceType,
|
|
32310
|
+
logicalId,
|
|
32311
|
+
void 0,
|
|
32312
|
+
cause
|
|
32313
|
+
);
|
|
32314
|
+
}
|
|
32315
|
+
}
|
|
32316
|
+
async updateRecordSet(logicalId, physicalId, resourceType, properties) {
|
|
32317
|
+
this.logger.debug(`Updating Route 53 record set ${logicalId}: ${physicalId}`);
|
|
32318
|
+
const hostedZoneId = await this.resolveHostedZoneId(
|
|
32319
|
+
properties,
|
|
32320
|
+
logicalId,
|
|
32321
|
+
resourceType,
|
|
32322
|
+
physicalId
|
|
32323
|
+
);
|
|
32324
|
+
const recordName = properties["Name"];
|
|
32325
|
+
const recordType = properties["Type"];
|
|
32326
|
+
try {
|
|
32327
|
+
const resourceRecordSet = this.buildResourceRecordSet(properties);
|
|
32328
|
+
const comment = properties["Comment"];
|
|
32329
|
+
await this.getClient().send(
|
|
32330
|
+
new ChangeResourceRecordSetsCommand({
|
|
32331
|
+
HostedZoneId: hostedZoneId,
|
|
32332
|
+
ChangeBatch: {
|
|
32333
|
+
...comment ? { Comment: comment } : {},
|
|
32334
|
+
Changes: [
|
|
32335
|
+
{
|
|
32336
|
+
Action: "UPSERT",
|
|
32337
|
+
ResourceRecordSet: resourceRecordSet
|
|
32338
|
+
}
|
|
32339
|
+
]
|
|
32340
|
+
}
|
|
32341
|
+
})
|
|
32342
|
+
);
|
|
32343
|
+
const compositeId = `${hostedZoneId}|${recordName}|${recordType}`;
|
|
32344
|
+
this.logger.debug(`Successfully updated record set ${logicalId}`);
|
|
32345
|
+
return {
|
|
32346
|
+
physicalId: compositeId,
|
|
32347
|
+
wasReplaced: false,
|
|
32348
|
+
attributes: {}
|
|
32349
|
+
};
|
|
32350
|
+
} catch (error) {
|
|
32351
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32352
|
+
throw new ProvisioningError(
|
|
32353
|
+
`Failed to update record set ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32354
|
+
resourceType,
|
|
32355
|
+
logicalId,
|
|
32356
|
+
physicalId,
|
|
32357
|
+
cause
|
|
32358
|
+
);
|
|
32359
|
+
}
|
|
32360
|
+
}
|
|
32361
|
+
async deleteRecordSet(logicalId, physicalId, resourceType, properties, context) {
|
|
32362
|
+
this.logger.debug(`Deleting Route 53 record set ${logicalId}: ${physicalId}`);
|
|
32363
|
+
const parts = physicalId.split("|");
|
|
32364
|
+
if (parts.length !== 3) {
|
|
32365
|
+
throw new ProvisioningError(
|
|
32366
|
+
`Invalid record set physical ID format: ${physicalId}`,
|
|
32367
|
+
resourceType,
|
|
32368
|
+
logicalId,
|
|
32369
|
+
physicalId
|
|
32370
|
+
);
|
|
32371
|
+
}
|
|
32372
|
+
const [hostedZoneId] = parts;
|
|
32373
|
+
if (!properties) {
|
|
32374
|
+
throw new ProvisioningError(
|
|
32375
|
+
`Properties required to delete record set ${logicalId}`,
|
|
32376
|
+
resourceType,
|
|
32377
|
+
logicalId,
|
|
32378
|
+
physicalId
|
|
32379
|
+
);
|
|
32380
|
+
}
|
|
32381
|
+
try {
|
|
32382
|
+
const resourceRecordSet = this.buildResourceRecordSet(properties);
|
|
32383
|
+
await this.getClient().send(
|
|
32384
|
+
new ChangeResourceRecordSetsCommand({
|
|
32385
|
+
HostedZoneId: hostedZoneId,
|
|
32386
|
+
ChangeBatch: {
|
|
32387
|
+
Changes: [
|
|
32388
|
+
{
|
|
32389
|
+
Action: "DELETE",
|
|
32390
|
+
ResourceRecordSet: resourceRecordSet
|
|
32391
|
+
}
|
|
32392
|
+
]
|
|
32393
|
+
}
|
|
32394
|
+
})
|
|
32395
|
+
);
|
|
32396
|
+
this.logger.debug(`Successfully deleted record set ${logicalId}`);
|
|
32397
|
+
} catch (error) {
|
|
32398
|
+
if (error instanceof Error && (error.name === "InvalidChangeBatch" || error.message.includes("it was not found"))) {
|
|
32399
|
+
const clientRegion = await this.getClient().config.region();
|
|
32400
|
+
assertRegionMatch(
|
|
32401
|
+
clientRegion,
|
|
32402
|
+
context?.expectedRegion,
|
|
32403
|
+
resourceType,
|
|
32404
|
+
logicalId,
|
|
32405
|
+
physicalId
|
|
32406
|
+
);
|
|
32407
|
+
this.logger.debug(`Record set ${physicalId} does not exist, skipping deletion`);
|
|
32408
|
+
return;
|
|
32409
|
+
}
|
|
32410
|
+
if (error instanceof Error && error.name === "NoSuchHostedZone") {
|
|
32411
|
+
this.logger.debug(
|
|
32412
|
+
`Hosted zone for record set ${physicalId} does not exist, skipping deletion`
|
|
32413
|
+
);
|
|
32414
|
+
return;
|
|
32415
|
+
}
|
|
32416
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32417
|
+
throw new ProvisioningError(
|
|
32418
|
+
`Failed to delete record set ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32419
|
+
resourceType,
|
|
32420
|
+
logicalId,
|
|
32421
|
+
physicalId,
|
|
32422
|
+
cause
|
|
32423
|
+
);
|
|
32424
|
+
}
|
|
32425
|
+
}
|
|
32426
|
+
// ─── Helpers ───────────────────────────────────────────────────────
|
|
32427
|
+
/**
|
|
32428
|
+
* Build a ResourceRecordSet object from CDK properties.
|
|
32429
|
+
*
|
|
32430
|
+
* Handles conversion of CDK-style ResourceRecords (array of strings)
|
|
32431
|
+
* to SDK-style ResourceRecords (array of {Value}).
|
|
32432
|
+
* Also handles routing policy properties: Weight, Region, Failover,
|
|
32433
|
+
* MultiValueAnswer, GeoLocation, SetIdentifier, and HealthCheckId.
|
|
32434
|
+
*/
|
|
32435
|
+
buildResourceRecordSet(properties) {
|
|
32436
|
+
const name = properties["Name"];
|
|
32437
|
+
const type = properties["Type"];
|
|
32438
|
+
const ttl = properties["TTL"];
|
|
32439
|
+
const resourceRecords = properties["ResourceRecords"];
|
|
32440
|
+
const aliasTarget = properties["AliasTarget"];
|
|
32441
|
+
const recordSet = {
|
|
32442
|
+
Name: name,
|
|
32443
|
+
Type: type
|
|
32444
|
+
};
|
|
32445
|
+
if (aliasTarget) {
|
|
32446
|
+
recordSet.AliasTarget = {
|
|
32447
|
+
HostedZoneId: aliasTarget["HostedZoneId"],
|
|
32448
|
+
DNSName: aliasTarget["DNSName"],
|
|
32449
|
+
EvaluateTargetHealth: aliasTarget["EvaluateTargetHealth"] ?? false
|
|
32450
|
+
};
|
|
32451
|
+
} else {
|
|
32452
|
+
if (ttl !== void 0) {
|
|
32453
|
+
recordSet.TTL = Number(ttl);
|
|
32454
|
+
}
|
|
32455
|
+
if (resourceRecords) {
|
|
32456
|
+
recordSet.ResourceRecords = resourceRecords.map((record) => {
|
|
32457
|
+
if (typeof record === "string") {
|
|
32458
|
+
return { Value: record };
|
|
32459
|
+
}
|
|
32460
|
+
return record;
|
|
32461
|
+
});
|
|
32462
|
+
}
|
|
32463
|
+
}
|
|
32464
|
+
const setIdentifier = properties["SetIdentifier"];
|
|
32465
|
+
if (setIdentifier !== void 0) {
|
|
32466
|
+
recordSet.SetIdentifier = setIdentifier;
|
|
32467
|
+
}
|
|
32468
|
+
const weight = properties["Weight"];
|
|
30460
32469
|
if (weight !== void 0) {
|
|
30461
32470
|
recordSet.Weight = Number(weight);
|
|
30462
32471
|
}
|
|
@@ -30726,7 +32735,7 @@ var Route53Provider = class {
|
|
|
30726
32735
|
const idTail = physicalId.replace(/^\/hostedzone\//, "");
|
|
30727
32736
|
try {
|
|
30728
32737
|
const tagsResp = await this.getClient().send(
|
|
30729
|
-
new
|
|
32738
|
+
new ListTagsForResourceCommand13({ ResourceType: "hostedzone", ResourceId: idTail })
|
|
30730
32739
|
);
|
|
30731
32740
|
const tags = normalizeAwsTagsToCfn(tagsResp.ResourceTagSet?.Tags);
|
|
30732
32741
|
result["HostedZoneTags"] = tags;
|
|
@@ -30876,7 +32885,7 @@ var Route53Provider = class {
|
|
|
30876
32885
|
const zoneId = zone.Id.replace("/hostedzone/", "");
|
|
30877
32886
|
try {
|
|
30878
32887
|
const tagsResp = await this.getClient().send(
|
|
30879
|
-
new
|
|
32888
|
+
new ListTagsForResourceCommand13({
|
|
30880
32889
|
ResourceType: "hostedzone",
|
|
30881
32890
|
ResourceId: zoneId
|
|
30882
32891
|
})
|
|
@@ -30904,7 +32913,7 @@ import {
|
|
|
30904
32913
|
DeleteWebACLCommand,
|
|
30905
32914
|
GetWebACLCommand,
|
|
30906
32915
|
ListWebACLsCommand,
|
|
30907
|
-
ListTagsForResourceCommand as
|
|
32916
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand14,
|
|
30908
32917
|
TagResourceCommand as TagResourceCommand13,
|
|
30909
32918
|
UntagResourceCommand as UntagResourceCommand13,
|
|
30910
32919
|
WAFNonexistentItemException
|
|
@@ -31232,7 +33241,7 @@ var WAFv2WebACLProvider = class {
|
|
|
31232
33241
|
}
|
|
31233
33242
|
try {
|
|
31234
33243
|
const tagsResp = await this.getClient().send(
|
|
31235
|
-
new
|
|
33244
|
+
new ListTagsForResourceCommand14({ ResourceARN: physicalId })
|
|
31236
33245
|
);
|
|
31237
33246
|
const tags = normalizeAwsTagsToCfn(tagsResp.TagInfoForResource?.TagList);
|
|
31238
33247
|
result["Tags"] = tags;
|
|
@@ -31280,7 +33289,7 @@ var WAFv2WebACLProvider = class {
|
|
|
31280
33289
|
if (!item.ARN)
|
|
31281
33290
|
continue;
|
|
31282
33291
|
const tagsResp = await this.getClient().send(
|
|
31283
|
-
new
|
|
33292
|
+
new ListTagsForResourceCommand14({ ResourceARN: item.ARN })
|
|
31284
33293
|
);
|
|
31285
33294
|
const tagList = tagsResp.TagInfoForResource?.TagList;
|
|
31286
33295
|
if (matchesCdkPath(tagList, input.cdkPath)) {
|
|
@@ -31301,7 +33310,7 @@ import {
|
|
|
31301
33310
|
UpdateUserPoolCommand,
|
|
31302
33311
|
DescribeUserPoolCommand,
|
|
31303
33312
|
ListUserPoolsCommand,
|
|
31304
|
-
ListTagsForResourceCommand as
|
|
33313
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand15,
|
|
31305
33314
|
ResourceNotFoundException as ResourceNotFoundException12
|
|
31306
33315
|
} from "@aws-sdk/client-cognito-identity-provider";
|
|
31307
33316
|
function isEmptyObjectPlaceholder(value) {
|
|
@@ -31770,7 +33779,7 @@ var CognitoUserPoolProvider = class {
|
|
|
31770
33779
|
if (!arn)
|
|
31771
33780
|
continue;
|
|
31772
33781
|
const tagsResp = await this.getClient().send(
|
|
31773
|
-
new
|
|
33782
|
+
new ListTagsForResourceCommand15({ ResourceArn: arn })
|
|
31774
33783
|
);
|
|
31775
33784
|
if (tagsResp.Tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
31776
33785
|
return { physicalId: pool.Id, attributes: {} };
|
|
@@ -31799,9 +33808,9 @@ import {
|
|
|
31799
33808
|
DeleteCacheSubnetGroupCommand,
|
|
31800
33809
|
ModifyCacheSubnetGroupCommand,
|
|
31801
33810
|
ModifyCacheClusterCommand,
|
|
31802
|
-
ListTagsForResourceCommand as
|
|
31803
|
-
AddTagsToResourceCommand as
|
|
31804
|
-
RemoveTagsFromResourceCommand as
|
|
33811
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand16,
|
|
33812
|
+
AddTagsToResourceCommand as AddTagsToResourceCommand5,
|
|
33813
|
+
RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand5
|
|
31805
33814
|
} from "@aws-sdk/client-elasticache";
|
|
31806
33815
|
import { STSClient as STSClient6, GetCallerIdentityCommand as GetCallerIdentityCommand6 } from "@aws-sdk/client-sts";
|
|
31807
33816
|
var ElastiCacheProvider = class {
|
|
@@ -32187,13 +34196,13 @@ var ElastiCacheProvider = class {
|
|
|
32187
34196
|
}
|
|
32188
34197
|
if (tagsToRemove.length > 0) {
|
|
32189
34198
|
await this.getClient().send(
|
|
32190
|
-
new
|
|
34199
|
+
new RemoveTagsFromResourceCommand5({ ResourceName: arn, TagKeys: tagsToRemove })
|
|
32191
34200
|
);
|
|
32192
34201
|
this.logger.debug(`Removed ${tagsToRemove.length} tag(s) from ElastiCache resource ${arn}`);
|
|
32193
34202
|
}
|
|
32194
34203
|
if (tagsToAdd.length > 0) {
|
|
32195
34204
|
await this.getClient().send(
|
|
32196
|
-
new
|
|
34205
|
+
new AddTagsToResourceCommand5({ ResourceName: arn, Tags: tagsToAdd })
|
|
32197
34206
|
);
|
|
32198
34207
|
this.logger.debug(`Added/updated ${tagsToAdd.length} tag(s) on ElastiCache resource ${arn}`);
|
|
32199
34208
|
}
|
|
@@ -32393,7 +34402,7 @@ var ElastiCacheProvider = class {
|
|
|
32393
34402
|
async attachTags(result, arn) {
|
|
32394
34403
|
try {
|
|
32395
34404
|
const tagsResp = await this.getClient().send(
|
|
32396
|
-
new
|
|
34405
|
+
new ListTagsForResourceCommand16({ ResourceName: arn })
|
|
32397
34406
|
);
|
|
32398
34407
|
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
32399
34408
|
result["Tags"] = tags;
|
|
@@ -32455,7 +34464,7 @@ var ElastiCacheProvider = class {
|
|
|
32455
34464
|
continue;
|
|
32456
34465
|
const arn = c.ARN ?? await this.buildClusterArn(c.CacheClusterId);
|
|
32457
34466
|
const tagsResp = await this.getClient().send(
|
|
32458
|
-
new
|
|
34467
|
+
new ListTagsForResourceCommand16({ ResourceName: arn })
|
|
32459
34468
|
);
|
|
32460
34469
|
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
32461
34470
|
return { physicalId: c.CacheClusterId, attributes: {} };
|
|
@@ -32492,7 +34501,7 @@ var ElastiCacheProvider = class {
|
|
|
32492
34501
|
continue;
|
|
32493
34502
|
const arn = g.ARN ?? await this.buildSubnetGroupArn(g.CacheSubnetGroupName);
|
|
32494
34503
|
const tagsResp = await this.getClient().send(
|
|
32495
|
-
new
|
|
34504
|
+
new ListTagsForResourceCommand16({ ResourceName: arn })
|
|
32496
34505
|
);
|
|
32497
34506
|
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
32498
34507
|
return { physicalId: g.CacheSubnetGroupName, attributes: {} };
|
|
@@ -32545,7 +34554,7 @@ import {
|
|
|
32545
34554
|
GetServiceCommand,
|
|
32546
34555
|
ListNamespacesCommand,
|
|
32547
34556
|
ListServicesCommand as ListServicesCommand2,
|
|
32548
|
-
ListTagsForResourceCommand as
|
|
34557
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand17,
|
|
32549
34558
|
NamespaceNotFound,
|
|
32550
34559
|
ServiceNotFound
|
|
32551
34560
|
} from "@aws-sdk/client-servicediscovery";
|
|
@@ -33109,7 +35118,7 @@ var ServiceDiscoveryProvider = class {
|
|
|
33109
35118
|
async attachTags(result, arn) {
|
|
33110
35119
|
try {
|
|
33111
35120
|
const tagsResp = await this.getClient().send(
|
|
33112
|
-
new
|
|
35121
|
+
new ListTagsForResourceCommand17({ ResourceARN: arn })
|
|
33113
35122
|
);
|
|
33114
35123
|
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
33115
35124
|
result["Tags"] = tags;
|
|
@@ -33155,7 +35164,7 @@ var ServiceDiscoveryProvider = class {
|
|
|
33155
35164
|
if (input.cdkPath) {
|
|
33156
35165
|
try {
|
|
33157
35166
|
const tagsResp = await this.getClient().send(
|
|
33158
|
-
new
|
|
35167
|
+
new ListTagsForResourceCommand17({ ResourceARN: ns.Arn })
|
|
33159
35168
|
);
|
|
33160
35169
|
if (matchesCdkPath(tagsResp.Tags, input.cdkPath)) {
|
|
33161
35170
|
return { physicalId: ns.Id, attributes: {} };
|
|
@@ -33194,7 +35203,7 @@ var ServiceDiscoveryProvider = class {
|
|
|
33194
35203
|
continue;
|
|
33195
35204
|
try {
|
|
33196
35205
|
const tagsResp = await this.getClient().send(
|
|
33197
|
-
new
|
|
35206
|
+
new ListTagsForResourceCommand17({ ResourceARN: svc.Arn })
|
|
33198
35207
|
);
|
|
33199
35208
|
if (matchesCdkPath(tagsResp.Tags, input.cdkPath)) {
|
|
33200
35209
|
return { physicalId: svc.Id, attributes: {} };
|
|
@@ -38392,7 +40401,7 @@ import {
|
|
|
38392
40401
|
GetVectorBucketCommand,
|
|
38393
40402
|
ListIndexesCommand,
|
|
38394
40403
|
ListVectorBucketsCommand,
|
|
38395
|
-
ListTagsForResourceCommand as
|
|
40404
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand18,
|
|
38396
40405
|
DeleteIndexCommand
|
|
38397
40406
|
} from "@aws-sdk/client-s3vectors";
|
|
38398
40407
|
var S3VectorsProvider = class {
|
|
@@ -38626,7 +40635,7 @@ var S3VectorsProvider = class {
|
|
|
38626
40635
|
continue;
|
|
38627
40636
|
try {
|
|
38628
40637
|
const tagsResp = await this.getClient().send(
|
|
38629
|
-
new
|
|
40638
|
+
new ListTagsForResourceCommand18({ resourceArn: bucket.vectorBucketArn })
|
|
38630
40639
|
);
|
|
38631
40640
|
if (tagsResp.tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
38632
40641
|
return { physicalId: bucket.vectorBucketName, attributes: {} };
|
|
@@ -38970,7 +40979,7 @@ import {
|
|
|
38970
40979
|
ListNamespacesCommand as ListNamespacesCommand2,
|
|
38971
40980
|
ListTablesCommand as ListTablesCommand2,
|
|
38972
40981
|
ListTableBucketsCommand,
|
|
38973
|
-
ListTagsForResourceCommand as
|
|
40982
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand19,
|
|
38974
40983
|
NotFoundException as NotFoundException6
|
|
38975
40984
|
} from "@aws-sdk/client-s3tables";
|
|
38976
40985
|
var S3TablesProvider = class {
|
|
@@ -39454,7 +41463,7 @@ var S3TablesProvider = class {
|
|
|
39454
41463
|
if (input.cdkPath) {
|
|
39455
41464
|
try {
|
|
39456
41465
|
const tagsResp = await this.getClient().send(
|
|
39457
|
-
new
|
|
41466
|
+
new ListTagsForResourceCommand19({ resourceArn: bucket.arn })
|
|
39458
41467
|
);
|
|
39459
41468
|
if (tagsResp.tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
39460
41469
|
return { physicalId: bucket.arn, attributes: {} };
|
|
@@ -39534,7 +41543,7 @@ var S3TablesProvider = class {
|
|
|
39534
41543
|
continue;
|
|
39535
41544
|
try {
|
|
39536
41545
|
const tagsResp = await this.getClient().send(
|
|
39537
|
-
new
|
|
41546
|
+
new ListTagsForResourceCommand19({ resourceArn: table.tableARN })
|
|
39538
41547
|
);
|
|
39539
41548
|
if (tagsResp.tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
39540
41549
|
return {
|
|
@@ -39620,7 +41629,7 @@ import {
|
|
|
39620
41629
|
PutImageScanningConfigurationCommand,
|
|
39621
41630
|
PutImageTagMutabilityCommand,
|
|
39622
41631
|
TagResourceCommand as TagResourceCommand15,
|
|
39623
|
-
ListTagsForResourceCommand as
|
|
41632
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand20,
|
|
39624
41633
|
LifecyclePolicyNotFoundException,
|
|
39625
41634
|
RepositoryNotFoundException
|
|
39626
41635
|
} from "@aws-sdk/client-ecr";
|
|
@@ -39950,7 +41959,7 @@ var ECRProvider = class {
|
|
|
39950
41959
|
if (r.repositoryArn) {
|
|
39951
41960
|
try {
|
|
39952
41961
|
const tagsResp = await this.getClient().send(
|
|
39953
|
-
new
|
|
41962
|
+
new ListTagsForResourceCommand20({ resourceArn: r.repositoryArn })
|
|
39954
41963
|
);
|
|
39955
41964
|
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
39956
41965
|
result["Tags"] = tags;
|
|
@@ -39996,7 +42005,7 @@ var ECRProvider = class {
|
|
|
39996
42005
|
continue;
|
|
39997
42006
|
try {
|
|
39998
42007
|
const tagsResp = await this.getClient().send(
|
|
39999
|
-
new
|
|
42008
|
+
new ListTagsForResourceCommand20({ resourceArn: repo.repositoryArn })
|
|
40000
42009
|
);
|
|
40001
42010
|
if (matchesCdkPath(tagsResp.tags, input.cdkPath)) {
|
|
40002
42011
|
return { physicalId: repo.repositoryName, attributes: {} };
|
|
@@ -40559,8 +42568,9 @@ var ASGProvider = class {
|
|
|
40559
42568
|
out.LaunchTemplateId = lt.LaunchTemplateId;
|
|
40560
42569
|
if (lt.LaunchTemplateName !== void 0)
|
|
40561
42570
|
out.LaunchTemplateName = lt.LaunchTemplateName;
|
|
40562
|
-
if (lt.Version !== void 0)
|
|
40563
|
-
out.Version = lt.Version;
|
|
42571
|
+
if (lt.Version !== void 0) {
|
|
42572
|
+
out.Version = String(lt.Version);
|
|
42573
|
+
}
|
|
40564
42574
|
if (out.LaunchTemplateId === void 0 && out.LaunchTemplateName === void 0) {
|
|
40565
42575
|
return void 0;
|
|
40566
42576
|
}
|
|
@@ -40724,6 +42734,14 @@ function registerAllProviders(registry) {
|
|
|
40724
42734
|
registry.register("AWS::RDS::DBSubnetGroup", rdsProvider);
|
|
40725
42735
|
registry.register("AWS::RDS::DBCluster", rdsProvider);
|
|
40726
42736
|
registry.register("AWS::RDS::DBInstance", rdsProvider);
|
|
42737
|
+
const docdbProvider = new DocDBProvider();
|
|
42738
|
+
registry.register("AWS::DocDB::DBSubnetGroup", docdbProvider);
|
|
42739
|
+
registry.register("AWS::DocDB::DBCluster", docdbProvider);
|
|
42740
|
+
registry.register("AWS::DocDB::DBInstance", docdbProvider);
|
|
42741
|
+
const neptuneProvider = new NeptuneProvider();
|
|
42742
|
+
registry.register("AWS::Neptune::DBSubnetGroup", neptuneProvider);
|
|
42743
|
+
registry.register("AWS::Neptune::DBCluster", neptuneProvider);
|
|
42744
|
+
registry.register("AWS::Neptune::DBInstance", neptuneProvider);
|
|
40727
42745
|
const route53Provider = new Route53Provider();
|
|
40728
42746
|
registry.register("AWS::Route53::HostedZone", route53Provider);
|
|
40729
42747
|
registry.register("AWS::Route53::RecordSet", route53Provider);
|
|
@@ -43725,6 +45743,14 @@ var PROTECTION_PROPERTY_BY_TYPE = {
|
|
|
43725
45743
|
"AWS::Logs::LogGroup": "DeletionProtectionEnabled",
|
|
43726
45744
|
"AWS::RDS::DBInstance": "DeletionProtection",
|
|
43727
45745
|
"AWS::RDS::DBCluster": "DeletionProtection",
|
|
45746
|
+
// DocDB: cluster-level only. The DocDB DBInstance shape does NOT
|
|
45747
|
+
// expose a DeletionProtection field (verified against the
|
|
45748
|
+
// @aws-sdk/client-docdb CreateDBInstanceMessage type — the field is
|
|
45749
|
+
// absent), so there is nothing to flip on destroy of an instance.
|
|
45750
|
+
"AWS::DocDB::DBCluster": "DeletionProtection",
|
|
45751
|
+
// Neptune: both cluster and instance expose DeletionProtection.
|
|
45752
|
+
"AWS::Neptune::DBCluster": "DeletionProtection",
|
|
45753
|
+
"AWS::Neptune::DBInstance": "DeletionProtection",
|
|
43728
45754
|
"AWS::DynamoDB::Table": "DeletionProtectionEnabled",
|
|
43729
45755
|
"AWS::EC2::Instance": "DisableApiTermination",
|
|
43730
45756
|
"AWS::Cognito::UserPool": "DeletionProtection",
|
|
@@ -46045,7 +48071,7 @@ function createStateDestroyCommand() {
|
|
|
46045
48071
|
"Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'."
|
|
46046
48072
|
).argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).option(
|
|
46047
48073
|
"--remove-protection",
|
|
46048
|
-
"Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DynamoDB::Table, AWS::EC2::Instance, and AWS::ElasticLoadBalancingV2::LoadBalancer.",
|
|
48074
|
+
"Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, and AWS::ElasticLoadBalancingV2::LoadBalancer.",
|
|
46049
48075
|
false
|
|
46050
48076
|
).addOption(stackRegionOption2()).addHelpText(
|
|
46051
48077
|
"after",
|
|
@@ -47187,7 +49213,7 @@ function reorderArgs(argv) {
|
|
|
47187
49213
|
}
|
|
47188
49214
|
async function main() {
|
|
47189
49215
|
const program = new Command14();
|
|
47190
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
49216
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.60.0");
|
|
47191
49217
|
program.addCommand(createBootstrapCommand());
|
|
47192
49218
|
program.addCommand(createSynthCommand());
|
|
47193
49219
|
program.addCommand(createListCommand());
|