@go-to-k/cdkd 0.255.0 → 0.256.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/dist/{asg-provider-BPtdM67j.js → asg-provider-DbIC4hWG.js} +2 -2
- package/dist/{asg-provider-BPtdM67j.js.map → asg-provider-DbIC4hWG.js.map} +1 -1
- package/dist/cli.js +17 -4
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-CFUNbwD1.js → deploy-engine-vUgwldVH.js} +184 -44
- package/dist/deploy-engine-vUgwldVH.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-CFUNbwD1.js.map +0 -1
|
@@ -8917,8 +8917,37 @@ function collectReferencedParameterNames(template) {
|
|
|
8917
8917
|
var IntrinsicFunctionResolver = class {
|
|
8918
8918
|
logger = getLogger().child("IntrinsicFunctionResolver");
|
|
8919
8919
|
resolverRegion;
|
|
8920
|
-
|
|
8920
|
+
strictGetAtt;
|
|
8921
|
+
/**
|
|
8922
|
+
* Number of unknown-attribute resolutions that fell back to the physical
|
|
8923
|
+
* ID (the warn path) since construction / the last
|
|
8924
|
+
* {@link resetPhysicalIdFallbackCount}. Counting semantics (issue #1111
|
|
8925
|
+
* item 3): the deploy engine resets this at the start of each `deploy()`
|
|
8926
|
+
* run AND again right before provisioning on the change path — the diff
|
|
8927
|
+
* phase resolves through this same counted resolver, so without the
|
|
8928
|
+
* second reset a fallback site on a to-be-updated resource would count
|
|
8929
|
+
* once during diff and again during provisioning (~2x distinct sites in
|
|
8930
|
+
* the summary). Each distinct fallback site therefore counts once per
|
|
8931
|
+
* run: the surfaced summary covers provisioning + output resolution on
|
|
8932
|
+
* the change path, diff + output resolution on the no-change path, and
|
|
8933
|
+
* diff only under --dry-run. Instance-scoped, so parallel stacks (each
|
|
8934
|
+
* with their own engine + resolver) never share a counter; for the same
|
|
8935
|
+
* reason a nested-stack CHILD engine's fallbacks are counted by the
|
|
8936
|
+
* child's own resolver and are NOT aggregated into the parent stack's
|
|
8937
|
+
* deploy summary.
|
|
8938
|
+
*/
|
|
8939
|
+
physicalIdFallbackCount = 0;
|
|
8940
|
+
constructor(region, options) {
|
|
8921
8941
|
this.resolverRegion = region || process.env["AWS_REGION"] || "us-east-1";
|
|
8942
|
+
this.strictGetAtt = options?.strictGetAtt ?? false;
|
|
8943
|
+
}
|
|
8944
|
+
/** Unknown-attribute physicalId fallbacks recorded since the last reset. */
|
|
8945
|
+
getPhysicalIdFallbackCount() {
|
|
8946
|
+
return this.physicalIdFallbackCount;
|
|
8947
|
+
}
|
|
8948
|
+
/** Reset the per-run fallback counter (called at the start of each deploy). */
|
|
8949
|
+
resetPhysicalIdFallbackCount() {
|
|
8950
|
+
this.physicalIdFallbackCount = 0;
|
|
8922
8951
|
}
|
|
8923
8952
|
/**
|
|
8924
8953
|
* Resolve parameter values from template Parameters section
|
|
@@ -9210,19 +9239,19 @@ var IntrinsicFunctionResolver = class {
|
|
|
9210
9239
|
if (resourceType === "AWS::DynamoDB::Table" || resourceType === "AWS::DynamoDB::GlobalTable") switch (attributeName) {
|
|
9211
9240
|
case "Arn": return `arn:${partition}:dynamodb:${region}:${accountId}:table/${physicalId}`;
|
|
9212
9241
|
case "StreamArn": return;
|
|
9213
|
-
default: return physicalId;
|
|
9242
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9214
9243
|
}
|
|
9215
9244
|
if (resourceType === "AWS::S3::Bucket") switch (attributeName) {
|
|
9216
9245
|
case "Arn": return `arn:${partition}:s3:::${physicalId}`;
|
|
9217
9246
|
case "DomainName": return `${physicalId}.s3.amazonaws.com`;
|
|
9218
9247
|
case "RegionalDomainName": return `${physicalId}.s3.${region}.amazonaws.com`;
|
|
9219
9248
|
case "WebsiteURL": return `http://${physicalId}.s3-website-${region}.amazonaws.com`;
|
|
9220
|
-
default: return physicalId;
|
|
9249
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9221
9250
|
}
|
|
9222
9251
|
if (resourceType === "AWS::IAM::Role") switch (attributeName) {
|
|
9223
9252
|
case "Arn": return `arn:${partition}:iam::${accountId}:role/${physicalId}`;
|
|
9224
9253
|
case "RoleId": return;
|
|
9225
|
-
default: return physicalId;
|
|
9254
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9226
9255
|
}
|
|
9227
9256
|
if (resourceType === "AWS::EC2::VPC") switch (attributeName) {
|
|
9228
9257
|
case "VpcId": return physicalId;
|
|
@@ -9252,37 +9281,38 @@ var IntrinsicFunctionResolver = class {
|
|
|
9252
9281
|
return [];
|
|
9253
9282
|
}
|
|
9254
9283
|
case "DefaultSecurityGroup": return resource.attributes?.["DefaultSecurityGroup"] || physicalId;
|
|
9255
|
-
default: return physicalId;
|
|
9284
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9256
9285
|
}
|
|
9257
9286
|
if (resourceType === "AWS::IAM::Policy") switch (attributeName) {
|
|
9258
9287
|
case "Arn": return `arn:${partition}:iam::${accountId}:policy/${physicalId}`;
|
|
9259
9288
|
case "PolicyId": return;
|
|
9260
|
-
default: return physicalId;
|
|
9289
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9261
9290
|
}
|
|
9262
9291
|
if (resourceType === "AWS::IAM::User") switch (attributeName) {
|
|
9263
9292
|
case "Arn": return `arn:${partition}:iam::${accountId}:user/${physicalId}`;
|
|
9264
|
-
default: return physicalId;
|
|
9293
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9265
9294
|
}
|
|
9266
9295
|
if (resourceType === "AWS::IAM::Group") switch (attributeName) {
|
|
9267
9296
|
case "Arn": return `arn:${partition}:iam::${accountId}:group/${physicalId}`;
|
|
9268
|
-
default: return physicalId;
|
|
9297
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9269
9298
|
}
|
|
9270
9299
|
if (resourceType === "AWS::IAM::InstanceProfile") switch (attributeName) {
|
|
9271
9300
|
case "Arn": return `arn:${partition}:iam::${accountId}:instance-profile/${physicalId}`;
|
|
9272
|
-
default: return physicalId;
|
|
9301
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9273
9302
|
}
|
|
9274
9303
|
if (resourceType === "AWS::KMS::Key") switch (attributeName) {
|
|
9275
9304
|
case "Arn": return `arn:${partition}:kms:${region}:${accountId}:key/${physicalId}`;
|
|
9276
9305
|
case "KeyId": return physicalId;
|
|
9277
|
-
default: return physicalId;
|
|
9306
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9278
9307
|
}
|
|
9279
9308
|
if (resourceType === "AWS::Cognito::UserPool") switch (attributeName) {
|
|
9280
9309
|
case "Arn": return `arn:${partition}:cognito-idp:${region}:${accountId}:userpool/${physicalId}`;
|
|
9281
|
-
|
|
9310
|
+
case "UserPoolId": return physicalId;
|
|
9311
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9282
9312
|
}
|
|
9283
9313
|
if (resourceType === "AWS::Kinesis::Stream") switch (attributeName) {
|
|
9284
9314
|
case "Arn": return `arn:${partition}:kinesis:${region}:${accountId}:stream/${physicalId}`;
|
|
9285
|
-
default: return physicalId;
|
|
9315
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9286
9316
|
}
|
|
9287
9317
|
if (resourceType === "AWS::Events::Rule") switch (attributeName) {
|
|
9288
9318
|
case "Arn": {
|
|
@@ -9292,36 +9322,36 @@ var IntrinsicFunctionResolver = class {
|
|
|
9292
9322
|
const busName = bus.startsWith("arn:") ? bus.split("/").pop() || "" : bus;
|
|
9293
9323
|
return busName ? `arn:${partition}:events:${region}:${accountId}:rule/${busName}/${physicalId}` : `arn:${partition}:events:${region}:${accountId}:rule/${physicalId}`;
|
|
9294
9324
|
}
|
|
9295
|
-
default: return physicalId;
|
|
9325
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9296
9326
|
}
|
|
9297
9327
|
if (resourceType === "AWS::Events::EventBus") switch (attributeName) {
|
|
9298
9328
|
case "Arn": return `arn:${partition}:events:${region}:${accountId}:event-bus/${physicalId}`;
|
|
9299
9329
|
case "Name": return physicalId;
|
|
9300
|
-
default: return physicalId;
|
|
9330
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9301
9331
|
}
|
|
9302
9332
|
if (resourceType === "AWS::EFS::FileSystem") switch (attributeName) {
|
|
9303
9333
|
case "Arn": return `arn:${partition}:elasticfilesystem:${region}:${accountId}:file-system/${physicalId}`;
|
|
9304
9334
|
case "FileSystemId": return physicalId;
|
|
9305
|
-
default: return physicalId;
|
|
9335
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9306
9336
|
}
|
|
9307
9337
|
if (resourceType === "AWS::KinesisFirehose::DeliveryStream") switch (attributeName) {
|
|
9308
9338
|
case "Arn": return `arn:${partition}:firehose:${region}:${accountId}:deliverystream/${physicalId}`;
|
|
9309
|
-
default: return physicalId;
|
|
9339
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9310
9340
|
}
|
|
9311
9341
|
if (resourceType === "AWS::CodeBuild::Project") switch (attributeName) {
|
|
9312
9342
|
case "Arn": return `arn:${partition}:codebuild:${region}:${accountId}:project/${physicalId}`;
|
|
9313
|
-
default: return physicalId;
|
|
9343
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9314
9344
|
}
|
|
9315
9345
|
if (resourceType === "AWS::CloudTrail::Trail") switch (attributeName) {
|
|
9316
9346
|
case "Arn":
|
|
9317
9347
|
if (physicalId.startsWith("arn:")) return physicalId;
|
|
9318
9348
|
return `arn:${partition}:cloudtrail:${region}:${accountId}:trail/${physicalId}`;
|
|
9319
|
-
default: return physicalId;
|
|
9349
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9320
9350
|
}
|
|
9321
9351
|
if (resourceType === "AWS::AppSync::GraphQLApi") switch (attributeName) {
|
|
9322
9352
|
case "Arn": return `arn:${partition}:appsync:${region}:${accountId}:apis/${physicalId}`;
|
|
9323
9353
|
case "ApiId": return physicalId;
|
|
9324
|
-
default: return physicalId;
|
|
9354
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9325
9355
|
}
|
|
9326
9356
|
if (resourceType === "AWS::ServiceDiscovery::PrivateDnsNamespace" || resourceType === "AWS::ServiceDiscovery::HttpNamespace" || resourceType === "AWS::ServiceDiscovery::PublicDnsNamespace") switch (attributeName) {
|
|
9327
9357
|
case "Arn": return `arn:${partition}:servicediscovery:${region}:${accountId}:namespace/${physicalId}`;
|
|
@@ -9333,38 +9363,38 @@ var IntrinsicFunctionResolver = class {
|
|
|
9333
9363
|
this.logger.warn(`Failed to fetch HostedZoneId for namespace ${physicalId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
9334
9364
|
return;
|
|
9335
9365
|
}
|
|
9336
|
-
default: return physicalId;
|
|
9366
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9337
9367
|
}
|
|
9338
9368
|
if (resourceType === "AWS::ServiceDiscovery::Service") switch (attributeName) {
|
|
9339
9369
|
case "Arn": return `arn:${partition}:servicediscovery:${region}:${accountId}:service/${physicalId}`;
|
|
9340
9370
|
case "Id": return physicalId;
|
|
9341
|
-
default: return physicalId;
|
|
9371
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9342
9372
|
}
|
|
9343
9373
|
if (resourceType === "AWS::CloudWatch::Alarm") switch (attributeName) {
|
|
9344
9374
|
case "Arn": return `arn:${partition}:cloudwatch:${region}:${accountId}:alarm:${physicalId}`;
|
|
9345
|
-
default: return physicalId;
|
|
9375
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9346
9376
|
}
|
|
9347
9377
|
if (resourceType === "AWS::CloudWatch::CompositeAlarm") switch (attributeName) {
|
|
9348
9378
|
case "Arn": return `arn:${partition}:cloudwatch:${region}:${accountId}:alarm:${physicalId}`;
|
|
9349
|
-
default: return physicalId;
|
|
9379
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9350
9380
|
}
|
|
9351
9381
|
if (resourceType === "AWS::RDS::DBInstance" || resourceType === "AWS::DocDB::DBInstance" || resourceType === "AWS::Neptune::DBInstance") switch (attributeName) {
|
|
9352
9382
|
case "DBInstanceArn":
|
|
9353
9383
|
case "Arn": return `arn:${partition}:rds:${region}:${accountId}:db:${physicalId}`;
|
|
9354
|
-
default: return physicalId;
|
|
9384
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9355
9385
|
}
|
|
9356
9386
|
if (resourceType === "AWS::RDS::DBCluster" || resourceType === "AWS::DocDB::DBCluster" || resourceType === "AWS::Neptune::DBCluster") switch (attributeName) {
|
|
9357
9387
|
case "DBClusterArn":
|
|
9358
9388
|
case "Arn": return `arn:${partition}:rds:${region}:${accountId}:cluster:${physicalId}`;
|
|
9359
|
-
default: return physicalId;
|
|
9389
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9360
9390
|
}
|
|
9361
9391
|
if (resourceType === "AWS::S3Express::DirectoryBucket") switch (attributeName) {
|
|
9362
9392
|
case "Arn": return `arn:${partition}:s3express:${region}:${accountId}:bucket/${physicalId}`;
|
|
9363
|
-
default: return physicalId;
|
|
9393
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9364
9394
|
}
|
|
9365
9395
|
if (resourceType === "AWS::Lambda::Function") switch (attributeName) {
|
|
9366
9396
|
case "Arn": return `arn:${partition}:lambda:${region}:${accountId}:function:${physicalId}`;
|
|
9367
|
-
default: return physicalId;
|
|
9397
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9368
9398
|
}
|
|
9369
9399
|
if (resourceType === "AWS::SQS::Queue") {
|
|
9370
9400
|
let queueName = physicalId;
|
|
@@ -9376,25 +9406,26 @@ var IntrinsicFunctionResolver = class {
|
|
|
9376
9406
|
case "Arn": return `arn:${partition}:sqs:${region}:${accountId}:${queueName}`;
|
|
9377
9407
|
case "QueueUrl": return physicalId;
|
|
9378
9408
|
case "QueueName": return queueName;
|
|
9379
|
-
default: return physicalId;
|
|
9409
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9380
9410
|
}
|
|
9381
9411
|
}
|
|
9382
9412
|
if (resourceType === "AWS::SNS::Topic") switch (attributeName) {
|
|
9383
9413
|
case "TopicArn": return `arn:${partition}:sns:${region}:${accountId}:${physicalId}`;
|
|
9384
|
-
|
|
9414
|
+
case "TopicName": return physicalId;
|
|
9415
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9385
9416
|
}
|
|
9386
9417
|
if (resourceType === "AWS::Logs::LogGroup") switch (attributeName) {
|
|
9387
9418
|
case "Arn": return `arn:${partition}:logs:${region}:${accountId}:log-group:${physicalId}:*`;
|
|
9388
|
-
default: return physicalId;
|
|
9419
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9389
9420
|
}
|
|
9390
9421
|
if (resourceType === "AWS::ECR::Repository") switch (attributeName) {
|
|
9391
9422
|
case "Arn": return `arn:${partition}:ecr:${region}:${accountId}:repository/${physicalId}`;
|
|
9392
9423
|
case "RepositoryUri": return `${accountId}.dkr.ecr.${region}.amazonaws.com/${physicalId}`;
|
|
9393
|
-
default: return physicalId;
|
|
9424
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9394
9425
|
}
|
|
9395
9426
|
if (resourceType === "AWS::ECS::Cluster") switch (attributeName) {
|
|
9396
9427
|
case "Arn": return `arn:${partition}:ecs:${region}:${accountId}:cluster/${physicalId}`;
|
|
9397
|
-
default: return physicalId;
|
|
9428
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9398
9429
|
}
|
|
9399
9430
|
if (resourceType === "AWS::ECS::Service") switch (attributeName) {
|
|
9400
9431
|
case "Name": {
|
|
@@ -9407,18 +9438,30 @@ var IntrinsicFunctionResolver = class {
|
|
|
9407
9438
|
if (pipeIdx >= 0) return physicalId.substring(pipeIdx + 1);
|
|
9408
9439
|
return physicalId;
|
|
9409
9440
|
}
|
|
9410
|
-
|
|
9441
|
+
case "ServiceArn": {
|
|
9442
|
+
const pipeIdx = physicalId.indexOf("|");
|
|
9443
|
+
if (pipeIdx < 0) return physicalId;
|
|
9444
|
+
const left = physicalId.substring(0, pipeIdx);
|
|
9445
|
+
if (left.includes(":service/")) return left;
|
|
9446
|
+
const clusterIdx = left.indexOf(":cluster/");
|
|
9447
|
+
if (clusterIdx < 0) return physicalId;
|
|
9448
|
+
const clusterName = left.substring(clusterIdx + 9);
|
|
9449
|
+
const serviceName = physicalId.substring(pipeIdx + 1);
|
|
9450
|
+
return `${left.substring(0, clusterIdx)}:service/${clusterName}/${serviceName}`;
|
|
9451
|
+
}
|
|
9452
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9411
9453
|
}
|
|
9412
9454
|
if (resourceType === "AWS::EC2::SecurityGroup") switch (attributeName) {
|
|
9413
9455
|
case "GroupId": return physicalId;
|
|
9414
9456
|
case "VpcId": return;
|
|
9415
|
-
default: return physicalId;
|
|
9457
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9416
9458
|
}
|
|
9417
9459
|
if (resourceType === "AWS::EC2::Subnet") switch (attributeName) {
|
|
9418
9460
|
case "SubnetId": return physicalId;
|
|
9419
|
-
default: return physicalId;
|
|
9461
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9420
9462
|
}
|
|
9421
9463
|
if (resourceType === "AWS::EC2::Instance") switch (attributeName) {
|
|
9464
|
+
case "InstanceId": return physicalId;
|
|
9422
9465
|
case "PrivateIp":
|
|
9423
9466
|
case "PublicIp":
|
|
9424
9467
|
case "PrivateDnsName":
|
|
@@ -9457,7 +9500,7 @@ var IntrinsicFunctionResolver = class {
|
|
|
9457
9500
|
}
|
|
9458
9501
|
return physicalId;
|
|
9459
9502
|
}
|
|
9460
|
-
default: return physicalId;
|
|
9503
|
+
default: return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9461
9504
|
}
|
|
9462
9505
|
if (resourceType === "AWS::EC2::LaunchTemplate") {
|
|
9463
9506
|
if (attributeName === "LatestVersionNumber" || attributeName === "DefaultVersionNumber") {
|
|
@@ -9470,11 +9513,44 @@ var IntrinsicFunctionResolver = class {
|
|
|
9470
9513
|
}
|
|
9471
9514
|
return attributeName === "LatestVersionNumber" ? "$Latest" : "$Default";
|
|
9472
9515
|
}
|
|
9473
|
-
return physicalId;
|
|
9516
|
+
if (attributeName === "LaunchTemplateId") return physicalId;
|
|
9517
|
+
return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9474
9518
|
}
|
|
9519
|
+
return this.guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId);
|
|
9520
|
+
}
|
|
9521
|
+
/**
|
|
9522
|
+
* Shared unknown-attribute physicalId fallback (issues #1106 / #1111).
|
|
9523
|
+
*
|
|
9524
|
+
* Applied by BOTH the final unknown-type fallback of
|
|
9525
|
+
* {@link constructAttribute} and every per-type handler's
|
|
9526
|
+
* `default:`-for-an-unknown-attribute branch:
|
|
9527
|
+
*
|
|
9528
|
+
* - An attribute name ending in `Arn` whose fallback value is not
|
|
9529
|
+
* ARN-shaped (or ending in `Url` whose fallback is not an http(s) URL)
|
|
9530
|
+
* cannot be what CloudFormation would return — hard-fail. The #1103
|
|
9531
|
+
* incident shipped four resource NAMES into stack Outputs where ARNs
|
|
9532
|
+
* were requested, with a green deploy. A physicalId that already IS an
|
|
9533
|
+
* ARN / URL passes the shape check and remains a valid fallback.
|
|
9534
|
+
* - Under `--strict-getatt`, EVERY unknown-attribute fallback (any
|
|
9535
|
+
* suffix) is a hard error.
|
|
9536
|
+
* - Otherwise: `Alias` / `Endpoint` and every other suffix keep the
|
|
9537
|
+
* warn-and-return behavior (an alias or endpoint is
|
|
9538
|
+
* shape-indistinguishable from a plain name, so a hard-fail there
|
|
9539
|
+
* would risk failing correct deploys — false positives are
|
|
9540
|
+
* unacceptable). Each warn-and-return increments the per-run fallback
|
|
9541
|
+
* counter surfaced in the deploy summary.
|
|
9542
|
+
*
|
|
9543
|
+
* A `return physicalId` that is the CORRECT value for a KNOWN attribute
|
|
9544
|
+
* (e.g. `AWS::KMS::Key.KeyId`, `AWS::SNS::Topic.TopicName`) must NOT
|
|
9545
|
+
* route through this helper — those are explicit `case`s in the
|
|
9546
|
+
* per-type handlers.
|
|
9547
|
+
*/
|
|
9548
|
+
guardedPhysicalIdFallback(logicalId, attributeName, resourceType, physicalId) {
|
|
9475
9549
|
const expectsArnShape = attributeName.endsWith("Arn") && !physicalId.startsWith("arn:");
|
|
9476
9550
|
const expectsUrlShape = attributeName.endsWith("Url") && !/^https?:\/\//.test(physicalId);
|
|
9477
9551
|
if (expectsArnShape || expectsUrlShape) throw new Error(`Cannot resolve Fn::GetAtt [${logicalId}, ${attributeName}] for ${resourceType}: attributes are not enriched for this resource type, and the physical ID fallback "${physicalId}" is not ${expectsArnShape ? "an ARN (arn:...)" : "a URL (http(s)://...)"}. CloudFormation would return a different value here, so falling back to the physical ID would silently produce a wrong value (e.g. in stack Outputs). Avoid this Fn::GetAtt, or file an issue at https://github.com/go-to-k/cdkd/issues so cdkd can enrich ${resourceType}.${attributeName}.`);
|
|
9552
|
+
if (this.strictGetAtt) throw new Error(`Cannot resolve Fn::GetAtt [${logicalId}, ${attributeName}] for ${resourceType}: attributes are not enriched for this resource type, and --strict-getatt rejects the physical ID fallback "${physicalId}" (which may not be the value CloudFormation would return). Drop --strict-getatt to fall back with a warning, avoid this Fn::GetAtt, or file an issue at https://github.com/go-to-k/cdkd/issues so cdkd can enrich ${resourceType}.${attributeName}.`);
|
|
9553
|
+
this.physicalIdFallbackCount++;
|
|
9478
9554
|
this.logger.warn(`Unknown attribute ${attributeName} for resource type ${resourceType}, returning physical ID`);
|
|
9479
9555
|
return physicalId;
|
|
9480
9556
|
}
|
|
@@ -10878,7 +10954,7 @@ var CloudControlProvider = class {
|
|
|
10878
10954
|
this.logger.debug(`Deleting resource ${logicalId} (${resourceType}), physical ID: ${physicalId}`);
|
|
10879
10955
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
10880
10956
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
10881
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
10957
|
+
const { ASGProvider } = await import("./asg-provider-DbIC4hWG.js").then((n) => n.n);
|
|
10882
10958
|
await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
|
|
10883
10959
|
return;
|
|
10884
10960
|
}
|
|
@@ -16280,7 +16356,7 @@ var DeployEngine = class {
|
|
|
16280
16356
|
this.options = options;
|
|
16281
16357
|
this.stackRegion = stackRegion;
|
|
16282
16358
|
this.exportIndexStore = exportIndexStore;
|
|
16283
|
-
this.resolver = new IntrinsicFunctionResolver(stackRegion);
|
|
16359
|
+
this.resolver = new IntrinsicFunctionResolver(stackRegion, { strictGetAtt: options.strictGetAtt ?? false });
|
|
16284
16360
|
this.options.concurrency = options.concurrency ?? 10;
|
|
16285
16361
|
this.options.dryRun = options.dryRun ?? false;
|
|
16286
16362
|
this.options.lockTimeout = options.lockTimeout ?? 300 * 1e3;
|
|
@@ -16295,6 +16371,7 @@ var DeployEngine = class {
|
|
|
16295
16371
|
async deploy(stackName, template) {
|
|
16296
16372
|
this.recordedImports = [];
|
|
16297
16373
|
this.recordedOutputReads = [];
|
|
16374
|
+
this.resolver.resetPhysicalIdFallbackCount();
|
|
16298
16375
|
return withStackName(stackName, () => this.doDeploy(stackName, template));
|
|
16299
16376
|
}
|
|
16300
16377
|
/**
|
|
@@ -16611,7 +16688,8 @@ var DeployEngine = class {
|
|
|
16611
16688
|
deleted: 0,
|
|
16612
16689
|
unchanged: Object.keys(currentState.resources).length,
|
|
16613
16690
|
durationMs: Date.now() - startTime,
|
|
16614
|
-
outputs: this.buildDisplayOutputs(template, persistedOutputs)
|
|
16691
|
+
outputs: this.buildDisplayOutputs(template, persistedOutputs),
|
|
16692
|
+
attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
|
|
16615
16693
|
};
|
|
16616
16694
|
}
|
|
16617
16695
|
const createChanges = this.diffCalculator.filterByType(changes, "CREATE");
|
|
@@ -16626,9 +16704,11 @@ var DeployEngine = class {
|
|
|
16626
16704
|
updated: updateChanges.length,
|
|
16627
16705
|
deleted: deleteChanges.length,
|
|
16628
16706
|
unchanged: this.diffCalculator.filterByType(changes, "NO_CHANGE").length,
|
|
16629
|
-
durationMs: Date.now() - startTime
|
|
16707
|
+
durationMs: Date.now() - startTime,
|
|
16708
|
+
attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
|
|
16630
16709
|
};
|
|
16631
16710
|
}
|
|
16711
|
+
this.resolver.resetPhysicalIdFallbackCount();
|
|
16632
16712
|
const progress = {
|
|
16633
16713
|
current: 0,
|
|
16634
16714
|
total: createChanges.length + updateChanges.length + deleteChanges.length
|
|
@@ -16647,7 +16727,8 @@ var DeployEngine = class {
|
|
|
16647
16727
|
deleted: actualCounts.deleted,
|
|
16648
16728
|
unchanged: unchangedCount,
|
|
16649
16729
|
durationMs,
|
|
16650
|
-
outputs: this.buildDisplayOutputs(template, newState.outputs ?? {})
|
|
16730
|
+
outputs: this.buildDisplayOutputs(template, newState.outputs ?? {}),
|
|
16731
|
+
attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
|
|
16651
16732
|
};
|
|
16652
16733
|
} finally {
|
|
16653
16734
|
renderer.stop();
|
|
@@ -16861,7 +16942,13 @@ var DeployEngine = class {
|
|
|
16861
16942
|
}
|
|
16862
16943
|
throw error;
|
|
16863
16944
|
}
|
|
16864
|
-
|
|
16945
|
+
let outputs;
|
|
16946
|
+
try {
|
|
16947
|
+
outputs = await this.resolveOutputs(template, newResources, stackName, parameterValues, conditions);
|
|
16948
|
+
} catch (outputError) {
|
|
16949
|
+
await this.persistStateAfterOutputFailure(stackName, currentState, newResources, currentEtag, pendingMigration);
|
|
16950
|
+
throw outputError;
|
|
16951
|
+
}
|
|
16865
16952
|
return {
|
|
16866
16953
|
state: {
|
|
16867
16954
|
version: 8,
|
|
@@ -16877,6 +16964,58 @@ var DeployEngine = class {
|
|
|
16877
16964
|
};
|
|
16878
16965
|
}
|
|
16879
16966
|
/**
|
|
16967
|
+
* Persist state after provisioning fully succeeded but output resolution
|
|
16968
|
+
* threw (only reachable under `--strict-getatt`, whose promotion fires
|
|
16969
|
+
* AFTER the rollback catch block). The persisted shape mirrors the
|
|
16970
|
+
* success-path state EXCEPT for outputs:
|
|
16971
|
+
*
|
|
16972
|
+
* - `resources`: this run's provisioning result (`newResources`) — every
|
|
16973
|
+
* create/update/delete landed in AWS, so state must record it.
|
|
16974
|
+
* - `imports` / `outputReads`: this run's `recordedImports` /
|
|
16975
|
+
* `recordedOutputReads` (the provisioning that produced them succeeded;
|
|
16976
|
+
* dropping them would desync the strong-reference records from AWS —
|
|
16977
|
+
* matters on the update-deploy path where the pre-deploy snapshot may
|
|
16978
|
+
* be stale).
|
|
16979
|
+
* - `outputs`: the PREVIOUSLY persisted map — resolveOutputs threw before
|
|
16980
|
+
* producing a new one, mirroring what a resource-failure persist keeps.
|
|
16981
|
+
* The exports index is deliberately NOT updated (it stays consistent
|
|
16982
|
+
* with the old outputs that remain in state).
|
|
16983
|
+
*
|
|
16984
|
+
* ETag handling mirrors the post-rollback save: expected-ETag first (or
|
|
16985
|
+
* unconditional when `pendingMigration` — same as the per-resource save),
|
|
16986
|
+
* then a fresh-ETag retry, then warn. Best-effort: the deploy error being
|
|
16987
|
+
* rethrown is the primary signal; a failed save only warns.
|
|
16988
|
+
*/
|
|
16989
|
+
async persistStateAfterOutputFailure(stackName, currentState, newResources, currentEtag, pendingMigration) {
|
|
16990
|
+
const buildState = () => ({
|
|
16991
|
+
version: 8,
|
|
16992
|
+
region: this.stackRegion,
|
|
16993
|
+
stackName: currentState.stackName,
|
|
16994
|
+
resources: newResources,
|
|
16995
|
+
outputs: currentState.outputs,
|
|
16996
|
+
...this.recordedImports.length > 0 && { imports: [...this.recordedImports] },
|
|
16997
|
+
...this.recordedOutputReads.length > 0 && { outputReads: [...this.recordedOutputReads] },
|
|
16998
|
+
lastModified: Date.now()
|
|
16999
|
+
});
|
|
17000
|
+
try {
|
|
17001
|
+
const expectedEtag = pendingMigration ? void 0 : currentEtag;
|
|
17002
|
+
await this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(buildState()), {
|
|
17003
|
+
...expectedEtag !== void 0 && { expectedEtag },
|
|
17004
|
+
migrateLegacy: pendingMigration
|
|
17005
|
+
});
|
|
17006
|
+
this.logger.debug("State saved after output resolution failure");
|
|
17007
|
+
} catch (saveError) {
|
|
17008
|
+
this.logger.debug(`Retrying state save after output resolution failure (ETag mismatch): ${saveError instanceof Error ? saveError.message : String(saveError)}`);
|
|
17009
|
+
try {
|
|
17010
|
+
const freshEtag = (await this.stateBackend.getState(stackName, this.stackRegion))?.etag;
|
|
17011
|
+
await this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(buildState()), { ...freshEtag !== void 0 && { expectedEtag: freshEtag } });
|
|
17012
|
+
this.logger.debug("State saved after output resolution failure (retry succeeded)");
|
|
17013
|
+
} catch (retryError) {
|
|
17014
|
+
this.logger.warn(`Failed to save state after output resolution failure: ${retryError instanceof Error ? retryError.message : String(retryError)} — resources were provisioned but not recorded; run deploy again to reconcile.`);
|
|
17015
|
+
}
|
|
17016
|
+
}
|
|
17017
|
+
}
|
|
17018
|
+
/**
|
|
16880
17019
|
* Perform best-effort rollback of completed operations respecting dependencies
|
|
16881
17020
|
*
|
|
16882
17021
|
* - CREATE → delete the newly created resource (in reverse dependency order)
|
|
@@ -17624,6 +17763,7 @@ var DeployEngine = class {
|
|
|
17624
17763
|
if (typeof exportName === "string") outputs[exportName] = value;
|
|
17625
17764
|
}
|
|
17626
17765
|
} catch (error) {
|
|
17766
|
+
if (this.options.strictGetAtt) throw new Error(`Failed to resolve output ${outputKey}: ${error instanceof Error ? error.message : String(error)} (--strict-getatt promotes output resolution failures to deploy errors; drop the flag to warn and skip the output instead)`);
|
|
17627
17767
|
this.logger.warn(`Failed to resolve output ${outputKey}: ${String(error)}`);
|
|
17628
17768
|
outputs[outputKey] = void 0;
|
|
17629
17769
|
}
|
|
@@ -17643,4 +17783,4 @@ var DeployEngine = class {
|
|
|
17643
17783
|
|
|
17644
17784
|
//#endregion
|
|
17645
17785
|
export { BOOTSTRAP_MARKER_PREFIX as $, StateError as $t, refStateLookupFromResource as A, AssemblyReader as At, TemplateParser as B, DependencyError as Bt, ProviderRegistry as C, warnDeprecatedNoPrefixCliFlag as Ct, isTerminationProtectionPropagationError as D, findLargeInlineResources as Dt, disableInstanceApiTermination as E, MIGRATE_TMP_PREFIX as Et, resolveExplicitPhysicalId as F, resetAwsClients as Ft, AssetPublisher as G, MissingCdkCliError as Gt, S3StateBackend as H, LocalMigrateError as Ht, assertRegionMatch as I, setAwsClients as It, buildAssetRedirectMap as J, ProvisioningError as Jt, stringifyValue as K, NestedStackChildDirectDestroyError as Kt, applyRoleArnIfSet as L, AssetError as Lt, CDK_PATH_TAG as M, resolveBucketRegion as Mt, matchesCdkPath as N, AwsClients as Nt, IntrinsicFunctionResolver as O, uploadCfnTemplate as Ot, normalizeAwsTagsToCfn as P, getAwsClients as Pt, AssetModeResolver as Q, StackTerminationProtectionError as Qt, DiffCalculator as R, CdkdError as Rt, isRetryableTransientError as S, resolveUseCdkBootstrapAssets as St, CloudControlProvider as T, CFN_TEMPLATE_URL_LIMIT as Tt, rebuildClientForBucketRegion as U, LocalStartServiceError as Ut, LockManager as V, LocalInvokeBuildError as Vt, shouldRetainResource as W, LockError as Wt, loadPublishableAssetManifest as X, ResourceUpdateNotSupportedError as Xt, createAssetRedirectResolver as Y, ResourceTimeoutError as Yt, rewriteTemplateAssetReferences as Z, StackHasActiveImportsError as Zt, yellow as _, resolveAutoAssetStorage as _t, IMPLICIT_DELETE_DEPENDENCIES as a, __exportAll as an, buildDockerImage as at, importTagWalk as b, resolveStateBucketWithDefault as bt, MULTI_REGION_RECREATE_BLOCKED_TYPES as c, runDockerForeground as ct, formatResourceLine as d, getDockerImageBySourceHash as dt, SynthesisError as en, ensureAssetStorage as et, bold as f, Synthesizer as ft, red as g, resolveApp as gt, green as h, getLegacyStateBucketName as ht, withResourceDeadline as i, withErrorHandling as in, validateContainerRepoName as it, WAFv2WebACLProvider as j, clearBucketRegionCache as jt, cfnRefValueFromPhysicalId as k, expectedOwnerParam as kt, isStatefulRecreateTargetSync as l, runDockerStreaming as lt, gray as m, getDefaultStateBucketName as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, isCdkdError as nn, parseBootstrapMarker as nt, computeImplicitDeleteEdges as o, formatDockerLoginError as ot, cyan as p, synthesisStatusMessage as pt, WorkGraph as q, PartialFailureError as qt, DeployEngine as r, normalizeAwsError as rn, validateAssetBucketName as rt, extractDeploymentEventError as s, getDockerCmd as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, formatError as tn, getBootstrapMarkerKey as tt, renderStatefulReason as u, AssetManifestLoader as ut, IAMRoleProvider as v, resolveCaptureObservedState as vt, findActionableSilentDrops as w, CFN_TEMPLATE_BODY_LIMIT as wt, withRetry as x, resolveStateBucketWithDefaultAndSource as xt, collectInlinePolicyNamesManagedBySiblings as y, resolveSkipPrefix as yt, DagBuilder as z, ConfigError as zt };
|
|
17646
|
-
//# sourceMappingURL=deploy-engine-
|
|
17786
|
+
//# sourceMappingURL=deploy-engine-vUgwldVH.js.map
|