@go-to-k/cdkd 0.283.6 → 0.283.8
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-BA2wc324.js → asg-provider-Tu4sDbhu.js} +2 -2
- package/dist/{asg-provider-BA2wc324.js.map → asg-provider-Tu4sDbhu.js.map} +1 -1
- package/dist/cli.js +28 -24
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DaEsg4mn.js → deploy-engine-D95wmKN8.js} +208 -36
- package/dist/deploy-engine-D95wmKN8.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DaEsg4mn.js.map +0 -1
|
@@ -9850,6 +9850,40 @@ function s3BucketWebsiteUrl(bucketName, region) {
|
|
|
9850
9850
|
* but a downstream refusal can still leave earlier sub-config PUTs applied —
|
|
9851
9851
|
* the same exposure the pre-existing `applyOwnershipControls` throw has, and
|
|
9852
9852
|
* still strictly better than a silent wrong-direction PUT.
|
|
9853
|
+
*
|
|
9854
|
+
* ## Every `onUnusable` message is a SENTENCE, and describes the READ only
|
|
9855
|
+
*
|
|
9856
|
+
* Issue #1735. Callers compose these as `${message} <their sentence>` — the
|
|
9857
|
+
* `.claude/rules/providers.md` per-site clause ("keep the PREVIOUS value" /
|
|
9858
|
+
* "SKIP the block" / "SUPPRESS the diff") is prescribed, so the appending set
|
|
9859
|
+
* GROWS. Two defects lived in that seam, and both are fixed HERE rather than
|
|
9860
|
+
* at the callers, so a future appender inherits the fix instead of repeating
|
|
9861
|
+
* the bug:
|
|
9862
|
+
*
|
|
9863
|
+
* 1. **Terminal punctuation.** Every message ended bare, so the composition
|
|
9864
|
+
* ran two sentences together (`...template-path create The mode this
|
|
9865
|
+
* update...`). Each `onUnusable` message now ends with a period. The
|
|
9866
|
+
* `throw` arms deliberately do NOT — nothing composes onto those.
|
|
9867
|
+
* 2. **The message must not claim an OUTCOME the caller overrides.**
|
|
9868
|
+
* `requireConfigString` said "Ignoring it and using the default
|
|
9869
|
+
* (PROVISIONED)" while `DynamoDBTableProvider`'s clause said the compared
|
|
9870
|
+
* mode (PAY_PER_REQUEST) "is kept" — both true of different things (what
|
|
9871
|
+
* the HELPER returned vs what the provider SENDS), but read as one sentence
|
|
9872
|
+
* the user could not tell which value reached AWS, which is the only
|
|
9873
|
+
* question the warning exists to answer. The helper now describes its own
|
|
9874
|
+
* READ ("This read falls back to the default (X)") and leaves the outcome
|
|
9875
|
+
* entirely to the caller. For a caller that appends NOTHING the read IS the
|
|
9876
|
+
* outcome, so nothing is lost there.
|
|
9877
|
+
*
|
|
9878
|
+
* `requireConfigArray` / `requireConfigObject` take (1) but NOT (2): they
|
|
9879
|
+
* return `undefined` and every caller SKIPS, so "Leaving this configuration
|
|
9880
|
+
* unapplied" is what actually happens on all of them and no caller's clause
|
|
9881
|
+
* contradicts it.
|
|
9882
|
+
*
|
|
9883
|
+
* Every existing assertion in this family uses `stringContaining`, so none of
|
|
9884
|
+
* them ever rendered the COMPOSED sentence — which is why a live run was what
|
|
9885
|
+
* surfaced this. `config-shape.test.ts` carries a composition block that
|
|
9886
|
+
* asserts the joined string directly.
|
|
9853
9887
|
*/
|
|
9854
9888
|
/**
|
|
9855
9889
|
* Read an optional string field out of a nested CFn config block, refusing a
|
|
@@ -9881,7 +9915,7 @@ function readConfigString(container, key, fallback, containerPath, options) {
|
|
|
9881
9915
|
const detail = malformedShapeDetail(container);
|
|
9882
9916
|
if (options?.onUnusable) {
|
|
9883
9917
|
const named = fallback === "" ? "" : ` (${fallback})`;
|
|
9884
|
-
options.onUnusable(`${containerPath} must be an object ${detail}. Treating the block as empty, so ${containerPath}.${key}
|
|
9918
|
+
options.onUnusable(`${containerPath} must be an object ${detail}. Treating the block as empty, so this read of ${containerPath}.${key} falls back to its default${named}; the same value is REFUSED on a template-path create.`);
|
|
9885
9919
|
return fallback;
|
|
9886
9920
|
}
|
|
9887
9921
|
throw new Error(`${containerPath} must be an object ${detail}`);
|
|
@@ -9919,7 +9953,7 @@ function requireConfigString(value, fallback, path, options) {
|
|
|
9919
9953
|
}
|
|
9920
9954
|
const named = fallback === "" ? "" : ` (${fallback})`;
|
|
9921
9955
|
if (options?.onUnusable) {
|
|
9922
|
-
options.onUnusable(`${refusal}.
|
|
9956
|
+
options.onUnusable(`${refusal}. This read falls back to the default${named}; the same value is REFUSED on a template-path create.`);
|
|
9923
9957
|
return fallback;
|
|
9924
9958
|
}
|
|
9925
9959
|
throw new Error(`${refusal}. Omit the field entirely to use the default${named}`);
|
|
@@ -9949,7 +9983,7 @@ function requireConfigArray(value, path, options) {
|
|
|
9949
9983
|
if (!Array.isArray(value)) {
|
|
9950
9984
|
const detail = malformedShapeDetail(value);
|
|
9951
9985
|
if (options?.onUnusable) {
|
|
9952
|
-
options.onUnusable(`${path} must be an array ${detail}. Leaving this configuration unapplied here; the same value is REFUSED on a template-path create
|
|
9986
|
+
options.onUnusable(`${path} must be an array ${detail}. Leaving this configuration unapplied here; the same value is REFUSED on a template-path create.`);
|
|
9953
9987
|
return;
|
|
9954
9988
|
}
|
|
9955
9989
|
throw new Error(`${path} must be an array ${detail}`);
|
|
@@ -9960,7 +9994,7 @@ function requireConfigObject(value, path, options) {
|
|
|
9960
9994
|
if (!isPlainObject$1(value)) {
|
|
9961
9995
|
const detail = malformedShapeDetail(value);
|
|
9962
9996
|
if (options?.onUnusable) {
|
|
9963
|
-
options.onUnusable(`${path} must be an object ${detail}. Leaving this configuration unapplied here; the same value is REFUSED on a template-path create
|
|
9997
|
+
options.onUnusable(`${path} must be an object ${detail}. Leaving this configuration unapplied here; the same value is REFUSED on a template-path create.`);
|
|
9964
9998
|
return;
|
|
9965
9999
|
}
|
|
9966
10000
|
throw new Error(`${path} must be an object ${detail}`);
|
|
@@ -13937,7 +13971,7 @@ var CloudControlProvider = class {
|
|
|
13937
13971
|
if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
|
|
13938
13972
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
13939
13973
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
13940
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
13974
|
+
const { ASGProvider } = await import("./asg-provider-Tu4sDbhu.js").then((n) => n.n);
|
|
13941
13975
|
return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
|
|
13942
13976
|
}
|
|
13943
13977
|
const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
|
|
@@ -14621,7 +14655,7 @@ const CR_NO_SERVICE_TOKEN_SKIP_REASON = "no ServiceToken in state — Delete han
|
|
|
14621
14655
|
* torn down by hand. Mirrors the caveat `compositeIdFormatMessage` already
|
|
14622
14656
|
* carries for the composite-id family.
|
|
14623
14657
|
*/
|
|
14624
|
-
const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy
|
|
14658
|
+
const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy. Since issue 1762 the DELETE of a resource removed from the template behaves like destroy — the record is KEPT and the next deploy re-attempts it — but a REPLACEMENT / rollback delete FAILS the resource instead (https://github.com/go-to-k/cdkd/issues/1762), leaving the old one untracked; there, tear the resource down by hand.";
|
|
14625
14659
|
/**
|
|
14626
14660
|
* Type guard to validate Lambda response payload structure
|
|
14627
14661
|
*/
|
|
@@ -20052,8 +20086,98 @@ async function withResourceDeadline(operation, opts) {
|
|
|
20052
20086
|
});
|
|
20053
20087
|
}
|
|
20054
20088
|
|
|
20089
|
+
//#endregion
|
|
20090
|
+
//#region src/deployment/delete-outcome.ts
|
|
20091
|
+
/**
|
|
20092
|
+
* Deploy-side consumption of {@link ResourceDeleteResult} (issue
|
|
20093
|
+
* [#1762](https://github.com/go-to-k/cdkd/issues/1762)) — the twin of what
|
|
20094
|
+
* `src/cli/commands/destroy-runner.ts` does for `cdkd destroy`.
|
|
20095
|
+
*
|
|
20096
|
+
* Issue [#1752](https://github.com/go-to-k/cdkd/issues/1752) gave
|
|
20097
|
+
* `ResourceProvider.delete` an optional return value whose `'skipped'` arm
|
|
20098
|
+
* means **the resource this result names was NOT destroyed and may still be
|
|
20099
|
+
* ALIVE**, and taught the destroy runner to report it. Every OTHER
|
|
20100
|
+
* `provider.delete(...)` call site — the deploy engine's template-DELETE
|
|
20101
|
+
* branch, its four replacement / recreate delete sites, and the five
|
|
20102
|
+
* `rollback-executor.ts` delete arms — discarded the value, so the same skip
|
|
20103
|
+
* printed as `deleted`, counted as `deleted`, and dropped the state record.
|
|
20104
|
+
*
|
|
20105
|
+
* **The module must stay a LEAF — no imports beyond the type, ever.** Same
|
|
20106
|
+
* reason as `src/provisioning/nested-stack-messages.ts`: both the deploy
|
|
20107
|
+
* engine and the rollback executor consume it, and those two already sit on a
|
|
20108
|
+
* dense import ring (engine -> executor -> provider registry -> every
|
|
20109
|
+
* provider). A helper that pulled anything else in would close it.
|
|
20110
|
+
*/
|
|
20111
|
+
/**
|
|
20112
|
+
* The `reason` of a `'skipped'` delete outcome, or `undefined` when the
|
|
20113
|
+
* provider reported a delete (`{ outcome: 'deleted' }` or the back-compat
|
|
20114
|
+
* `void` return ~80 providers still use).
|
|
20115
|
+
*
|
|
20116
|
+
* A function rather than an inline `result?.outcome === 'skipped'` test at
|
|
20117
|
+
* ten call sites so the back-compat `void` reading lives in ONE place: the
|
|
20118
|
+
* signature is `Promise<void | ResourceDeleteResult>`, so a caller that awaits
|
|
20119
|
+
* it holds `void | ResourceDeleteResult`, which TypeScript will happily let
|
|
20120
|
+
* you compare against nothing useful.
|
|
20121
|
+
*/
|
|
20122
|
+
function deleteSkipReason(result) {
|
|
20123
|
+
if (!result || result.outcome !== "skipped") return void 0;
|
|
20124
|
+
if (typeof result.reason !== "string") return UNSPECIFIED_SKIP_REASON;
|
|
20125
|
+
const trimmed = result.reason.trim();
|
|
20126
|
+
return trimmed === "" ? UNSPECIFIED_SKIP_REASON : trimmed;
|
|
20127
|
+
}
|
|
20128
|
+
/**
|
|
20129
|
+
* Stand-in for a `'skipped'` outcome whose producer supplied no `reason`.
|
|
20130
|
+
*
|
|
20131
|
+
* Deliberately says the cause is unknown rather than inventing one: the line
|
|
20132
|
+
* it renders on is the user's only signal that the resource survived, and a
|
|
20133
|
+
* fabricated cause would send them looking in the wrong place.
|
|
20134
|
+
*/
|
|
20135
|
+
const UNSPECIFIED_SKIP_REASON = "no reason reported by the provider";
|
|
20136
|
+
/**
|
|
20137
|
+
* The sentence every deploy-side skip renders, in the log line AND in the
|
|
20138
|
+
* `Error` the sites that must FAIL the resource throw.
|
|
20139
|
+
*
|
|
20140
|
+
* Wording rules, both load-bearing:
|
|
20141
|
+
*
|
|
20142
|
+
* 1. It says the resource was NOT deleted and MAY STILL EXIST. A skip issued
|
|
20143
|
+
* no AWS call at every producer but `NestedStackProvider.delete`, so the
|
|
20144
|
+
* old resource is presumed alive — which is the whole reason a replacement
|
|
20145
|
+
* site cannot proceed to create its replacement beside it.
|
|
20146
|
+
* 2. It must NOT contain any phrase the callers' already-deleted classifiers
|
|
20147
|
+
* substring-match (`does not exist` / `was not found` / `not found` /
|
|
20148
|
+
* `No policy found` / `NoSuchEntity` / `NotFoundException` /
|
|
20149
|
+
* `ResourceNotFoundException`). Reading a skip as "already gone" is exactly
|
|
20150
|
+
* the mis-accounting this change exists to remove, and the deploy engine's
|
|
20151
|
+
* DELETE branch and its update-not-supported fallback each carry such a
|
|
20152
|
+
* classifier. The call sites additionally handle the skip OUTSIDE their
|
|
20153
|
+
* `catch`, so a future `reason` carrying one of those phrases still cannot
|
|
20154
|
+
* reach a classifier — belt and braces, because `reason` is provider text.
|
|
20155
|
+
*/
|
|
20156
|
+
function deleteSkippedMessage(logicalId, physicalId, reason, duringClause) {
|
|
20157
|
+
return `cdkd could not address ${logicalId} (${physicalId}) ${duringClause}, so it was NOT deleted and may still exist: ${reason}`;
|
|
20158
|
+
}
|
|
20159
|
+
|
|
20055
20160
|
//#endregion
|
|
20056
20161
|
//#region src/deployment/rollback-executor.ts
|
|
20162
|
+
/**
|
|
20163
|
+
* Issue [#1762](https://github.com/go-to-k/cdkd/issues/1762): turn a
|
|
20164
|
+
* `{ outcome: 'skipped' }` delete into a thrown error at every rollback delete
|
|
20165
|
+
* arm.
|
|
20166
|
+
*
|
|
20167
|
+
* A skip means the resource was NOT deleted, so the rollback op did not
|
|
20168
|
+
* happen. Throwing routes it into the per-op accounting each arm already has —
|
|
20169
|
+
* `result.failures++` plus a `ROLLBACK_RESOURCE_FAILED` event and a kept
|
|
20170
|
+
* journal segment for the shared catch, or the local warn + `result.warnings++`
|
|
20171
|
+
* at the one arm whose delete is already best-effort. Both are correct and
|
|
20172
|
+
* neither needs a second code path; what is NOT correct is the pre-#1762
|
|
20173
|
+
* behavior, where every arm read a skip as a successful revert, dropped the
|
|
20174
|
+
* state record, and popped the segment.
|
|
20175
|
+
*/
|
|
20176
|
+
function throwIfDeleteSkipped(result, logicalId, physicalId, duringClause) {
|
|
20177
|
+
const reason = deleteSkipReason(result);
|
|
20178
|
+
if (reason === void 0) return;
|
|
20179
|
+
throw new Error(deleteSkippedMessage(logicalId, physicalId, reason, duringClause));
|
|
20180
|
+
}
|
|
20057
20181
|
/** The `--skip-final-snapshot` flag name cited by every refusal below. */
|
|
20058
20182
|
const SKIP_FINAL_SNAPSHOT_FLAG = "--skip-final-snapshot";
|
|
20059
20183
|
/**
|
|
@@ -20483,10 +20607,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
|
|
|
20483
20607
|
resourceType: op.resourceType,
|
|
20484
20608
|
provisionedBy: deleteProvisionedBy
|
|
20485
20609
|
});
|
|
20486
|
-
await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.properties, {
|
|
20610
|
+
throwIfDeleteSkipped(await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.properties, {
|
|
20487
20611
|
expectedRegion: ctx.region,
|
|
20488
20612
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
20489
|
-
});
|
|
20613
|
+
}), op.logicalId, op.physicalId, "while rolling back its CREATE");
|
|
20490
20614
|
delete stateResources[op.logicalId];
|
|
20491
20615
|
logger.info(` Rollback: ${op.logicalId} deleted successfully`);
|
|
20492
20616
|
await afterOp?.(op.logicalId);
|
|
@@ -20510,10 +20634,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
|
|
|
20510
20634
|
});
|
|
20511
20635
|
{
|
|
20512
20636
|
const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
|
|
20513
|
-
await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20637
|
+
throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20514
20638
|
expectedRegion: ctx.region,
|
|
20515
20639
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
20516
|
-
});
|
|
20640
|
+
}), op.logicalId, current.physicalId, "while reversing its replacement (re-adopting the retained old resource)");
|
|
20517
20641
|
}
|
|
20518
20642
|
stateResources[op.logicalId] = prev;
|
|
20519
20643
|
logger.info(` Rollback: ${op.logicalId} restored to the retained old resource`);
|
|
@@ -20558,10 +20682,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
|
|
|
20558
20682
|
logger.info(` Rollback: re-create collided with the new resource's name — deleting the new resource (${current.physicalId}) first...`);
|
|
20559
20683
|
{
|
|
20560
20684
|
const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
|
|
20561
|
-
await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20685
|
+
throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20562
20686
|
expectedRegion: ctx.region,
|
|
20563
20687
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
20564
|
-
});
|
|
20688
|
+
}), op.logicalId, current.physicalId, "while clearing the new resource so the old one could be re-created");
|
|
20565
20689
|
}
|
|
20566
20690
|
deletedNewFirst = true;
|
|
20567
20691
|
delete stateResources[op.logicalId];
|
|
@@ -20595,10 +20719,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
|
|
|
20595
20719
|
await afterOp?.(op.logicalId);
|
|
20596
20720
|
if (!deletedNewFirst && !adoptedLiveNewResource) try {
|
|
20597
20721
|
const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
|
|
20598
|
-
await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20722
|
+
throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
20599
20723
|
expectedRegion: ctx.region,
|
|
20600
20724
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
20601
|
-
});
|
|
20725
|
+
}), op.logicalId, current.physicalId, "while deleting the new resource after re-creating the old one");
|
|
20602
20726
|
} catch (deleteError) {
|
|
20603
20727
|
logger.warn(` Rollback: old ${op.logicalId} re-created, but deleting the new resource (${current.physicalId}) failed: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}. Delete it manually — it is no longer tracked in state.`);
|
|
20604
20728
|
result.warnings++;
|
|
@@ -20744,10 +20868,10 @@ async function replayFailedOperations(failedOps, stateResources, stackName, ctx,
|
|
|
20744
20868
|
resourceType: op.resourceType,
|
|
20745
20869
|
provisionedBy: deleteProvisionedBy
|
|
20746
20870
|
});
|
|
20747
|
-
await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.attemptedProperties, {
|
|
20871
|
+
throwIfDeleteSkipped(await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.attemptedProperties, {
|
|
20748
20872
|
expectedRegion: ctx.region,
|
|
20749
20873
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
20750
|
-
});
|
|
20874
|
+
}), op.logicalId, op.physicalId, "while deleting the partially-created resource (--revert-failed)");
|
|
20751
20875
|
delete stateResources[op.logicalId];
|
|
20752
20876
|
await options.afterOp?.(op.logicalId);
|
|
20753
20877
|
ctx.recordEvent?.({
|
|
@@ -20901,7 +21025,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
20901
21025
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
20902
21026
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
20903
21027
|
function getCdkdVersion() {
|
|
20904
|
-
return "0.283.
|
|
21028
|
+
return "0.283.8";
|
|
20905
21029
|
}
|
|
20906
21030
|
/**
|
|
20907
21031
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -21868,6 +21992,7 @@ var DeployEngine = class {
|
|
|
21868
21992
|
created: 0,
|
|
21869
21993
|
updated: 0,
|
|
21870
21994
|
deleted: 0,
|
|
21995
|
+
deleteSkipped: 0,
|
|
21871
21996
|
unchanged: Object.keys(currentState.resources).length,
|
|
21872
21997
|
durationMs: Date.now() - startTime,
|
|
21873
21998
|
outputs: this.buildDisplayOutputs(template, persistedOutputs),
|
|
@@ -21885,6 +22010,7 @@ var DeployEngine = class {
|
|
|
21885
22010
|
created: createChanges.length,
|
|
21886
22011
|
updated: updateChanges.length,
|
|
21887
22012
|
deleted: deleteChanges.length,
|
|
22013
|
+
deleteSkipped: 0,
|
|
21888
22014
|
unchanged: this.diffCalculator.filterByType(changes, "NO_CHANGE").length,
|
|
21889
22015
|
durationMs: Date.now() - startTime,
|
|
21890
22016
|
attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
|
|
@@ -21907,6 +22033,7 @@ var DeployEngine = class {
|
|
|
21907
22033
|
created: actualCounts.created,
|
|
21908
22034
|
updated: actualCounts.updated,
|
|
21909
22035
|
deleted: actualCounts.deleted,
|
|
22036
|
+
deleteSkipped: actualCounts.deleteSkipped,
|
|
21910
22037
|
unchanged: unchangedCount,
|
|
21911
22038
|
durationMs,
|
|
21912
22039
|
outputs: this.buildDisplayOutputs(template, newState.outputs ?? {}),
|
|
@@ -21940,7 +22067,8 @@ var DeployEngine = class {
|
|
|
21940
22067
|
created: 0,
|
|
21941
22068
|
updated: 0,
|
|
21942
22069
|
deleted: 0,
|
|
21943
|
-
skipped: 0
|
|
22070
|
+
skipped: 0,
|
|
22071
|
+
deleteSkipped: 0
|
|
21944
22072
|
};
|
|
21945
22073
|
const completedOperations = [];
|
|
21946
22074
|
const failedOperations = [];
|
|
@@ -22047,8 +22175,9 @@ var DeployEngine = class {
|
|
|
22047
22175
|
const logicalId = node.id;
|
|
22048
22176
|
const change = node.data;
|
|
22049
22177
|
const previousState = currentState.resources[logicalId] ? { ...currentState.resources[logicalId] } : void 0;
|
|
22178
|
+
let deleteOutcome;
|
|
22050
22179
|
try {
|
|
22051
|
-
await this.provisionResource(logicalId, change, newResources, stackName, template, parameterValues, conditions, actualCounts, progress);
|
|
22180
|
+
deleteOutcome = await this.provisionResource(logicalId, change, newResources, stackName, template, parameterValues, conditions, actualCounts, progress);
|
|
22052
22181
|
} catch (provisionError) {
|
|
22053
22182
|
this.interrupted = true;
|
|
22054
22183
|
this.interruptCause ??= "sibling-failure";
|
|
@@ -22062,6 +22191,7 @@ var DeployEngine = class {
|
|
|
22062
22191
|
});
|
|
22063
22192
|
throw provisionError;
|
|
22064
22193
|
}
|
|
22194
|
+
if (deleteOutcome) return;
|
|
22065
22195
|
completedOperations.push({
|
|
22066
22196
|
logicalId,
|
|
22067
22197
|
changeType: "DELETE",
|
|
@@ -22353,9 +22483,10 @@ var DeployEngine = class {
|
|
|
22353
22483
|
resourceType,
|
|
22354
22484
|
...labelRouting && { provisionedBy: labelRouting }
|
|
22355
22485
|
});
|
|
22486
|
+
let deleteSkipped;
|
|
22356
22487
|
try {
|
|
22357
22488
|
await withResourceDeadline(async () => {
|
|
22358
|
-
await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress);
|
|
22489
|
+
deleteSkipped = (await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress))?.deleteSkipped;
|
|
22359
22490
|
}, {
|
|
22360
22491
|
warnAfterMs,
|
|
22361
22492
|
timeoutMs,
|
|
@@ -22369,6 +22500,20 @@ var DeployEngine = class {
|
|
|
22369
22500
|
},
|
|
22370
22501
|
onTimeout: (elapsedMs) => new ResourceTimeoutError(logicalId, resourceType, this.stackRegion, elapsedMs, operationKind, timeoutMs)
|
|
22371
22502
|
});
|
|
22503
|
+
if (deleteSkipped !== void 0) {
|
|
22504
|
+
this.recordEvent({
|
|
22505
|
+
eventType: "RESOURCE_SKIPPED",
|
|
22506
|
+
stackName,
|
|
22507
|
+
operation: eventOp,
|
|
22508
|
+
logicalId,
|
|
22509
|
+
resourceType,
|
|
22510
|
+
...stateResources[logicalId]?.provisionedBy ? { provisionedBy: stateResources[logicalId]?.provisionedBy } : labelRouting && { provisionedBy: labelRouting },
|
|
22511
|
+
...stateResources[logicalId]?.physicalId && { physicalId: stateResources[logicalId]?.physicalId },
|
|
22512
|
+
reason: deleteSkipped,
|
|
22513
|
+
durationMs: Date.now() - resourceStartedAt
|
|
22514
|
+
});
|
|
22515
|
+
return { deleteSkipped };
|
|
22516
|
+
}
|
|
22372
22517
|
this.recordEvent({
|
|
22373
22518
|
eventType: "RESOURCE_SUCCEEDED",
|
|
22374
22519
|
stackName,
|
|
@@ -22465,8 +22610,9 @@ var DeployEngine = class {
|
|
|
22465
22610
|
*/
|
|
22466
22611
|
async replaceDeleteFirstAndRecreate(logicalId, resourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateReplacePolicy) {
|
|
22467
22612
|
const finalSnapshotIdentifier = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, updateReplacePolicy);
|
|
22613
|
+
let deleteResult;
|
|
22468
22614
|
try {
|
|
22469
|
-
await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22615
|
+
deleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22470
22616
|
expectedRegion: this.stackRegion,
|
|
22471
22617
|
forceDataDelete: this.options.forceStatefulRecreation === true,
|
|
22472
22618
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
@@ -22474,6 +22620,8 @@ var DeployEngine = class {
|
|
|
22474
22620
|
} catch (deleteError) {
|
|
22475
22621
|
throw new Error(`Failed to delete old resource ${logicalId} (${currentResource.physicalId}) during the --replace delete-first fallback: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
|
|
22476
22622
|
}
|
|
22623
|
+
const replaceSkipReason = deleteSkipReason(deleteResult);
|
|
22624
|
+
if (replaceSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, replaceSkipReason, "during the --replace delete-first fallback"));
|
|
22477
22625
|
this.logger.info(` ${green("✓")} Old resource deleted`);
|
|
22478
22626
|
this.logger.info(` Re-creating ${logicalId}...`);
|
|
22479
22627
|
try {
|
|
@@ -22611,16 +22759,19 @@ var DeployEngine = class {
|
|
|
22611
22759
|
else {
|
|
22612
22760
|
this.logger.info(` Destroying old ${logicalId} (${currentResource.physicalId}) before recreate...`);
|
|
22613
22761
|
const recreateFinalSnapshotId = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, updateReplacePolicy);
|
|
22762
|
+
let recreateDeleteResult;
|
|
22614
22763
|
try {
|
|
22615
|
-
await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22764
|
+
recreateDeleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22616
22765
|
expectedRegion: this.stackRegion,
|
|
22617
22766
|
forceDataDelete: this.options.forceStatefulRecreation === true,
|
|
22618
22767
|
...recreateFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: recreateFinalSnapshotId }
|
|
22619
22768
|
});
|
|
22620
|
-
this.logger.info(` ${green("✓")} Old resource deleted`);
|
|
22621
22769
|
} catch (deleteError) {
|
|
22622
22770
|
throw new Error(`Failed to destroy old resource ${logicalId} (${currentResource.physicalId}) during ${recreateFlagName}: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
|
|
22623
22771
|
}
|
|
22772
|
+
const recreateSkipReason = deleteSkipReason(recreateDeleteResult);
|
|
22773
|
+
if (recreateSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, recreateSkipReason, `during ${recreateFlagName}`));
|
|
22774
|
+
this.logger.info(` ${green("✓")} Old resource deleted`);
|
|
22624
22775
|
}
|
|
22625
22776
|
this.logger.info(` Creating new ${logicalId}...`);
|
|
22626
22777
|
createResult = await withRetry(() => this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider), logicalId, {
|
|
@@ -22668,15 +22819,22 @@ var DeployEngine = class {
|
|
|
22668
22819
|
snapshotBlockedDelete = true;
|
|
22669
22820
|
this.logger.warn(` ⚠ Final snapshot for old ${logicalId} (${currentResource.physicalId}) failed: ${snapshotError instanceof Error ? snapshotError.message : String(snapshotError)}. The old resource was NOT deleted (UpdateReplacePolicy: Snapshot) — delete it manually once you have a snapshot; it is no longer tracked in state.`);
|
|
22670
22821
|
}
|
|
22671
|
-
if (!snapshotBlockedDelete)
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
22822
|
+
if (!snapshotBlockedDelete) {
|
|
22823
|
+
let cleanupDeleteResult = void 0;
|
|
22824
|
+
let cleanupDeleteFailed = false;
|
|
22825
|
+
try {
|
|
22826
|
+
cleanupDeleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22827
|
+
expectedRegion: this.stackRegion,
|
|
22828
|
+
forceDataDelete: this.options.forceStatefulRecreation === true,
|
|
22829
|
+
...cleanupFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: cleanupFinalSnapshotId }
|
|
22830
|
+
});
|
|
22831
|
+
} catch (deleteError) {
|
|
22832
|
+
this.logger.warn(` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
|
|
22833
|
+
cleanupDeleteFailed = true;
|
|
22834
|
+
}
|
|
22835
|
+
const cleanupSkipReason = deleteSkipReason(cleanupDeleteResult);
|
|
22836
|
+
if (cleanupSkipReason !== void 0) this.logger.warn(` ⚠ ${deleteSkippedMessage(logicalId, currentResource.physicalId, cleanupSkipReason, "while cleaning up the replaced resource")}. Delete it manually — it is no longer tracked in state.`);
|
|
22837
|
+
else if (!cleanupDeleteFailed) this.logger.info(` ${green("✓")} Old resource deleted`);
|
|
22680
22838
|
}
|
|
22681
22839
|
}
|
|
22682
22840
|
}
|
|
@@ -22719,8 +22877,9 @@ var DeployEngine = class {
|
|
|
22719
22877
|
}
|
|
22720
22878
|
this.logger.info(`UPDATE not supported for ${logicalId} (${resourceType}), replacing (DELETE → CREATE)`);
|
|
22721
22879
|
const fallbackFinalSnapshotId = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy);
|
|
22880
|
+
let fallbackDeleteResult = void 0;
|
|
22722
22881
|
try {
|
|
22723
|
-
await updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
|
|
22882
|
+
fallbackDeleteResult = await updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
|
|
22724
22883
|
expectedRegion: this.stackRegion,
|
|
22725
22884
|
forceDataDelete: this.options.forceStatefulRecreation === true,
|
|
22726
22885
|
...fallbackFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: fallbackFinalSnapshotId }
|
|
@@ -22730,6 +22889,8 @@ var DeployEngine = class {
|
|
|
22730
22889
|
if (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound")) this.logger.debug(`Old resource ${logicalId} already gone, proceeding with CREATE`);
|
|
22731
22890
|
else throw deleteError;
|
|
22732
22891
|
}
|
|
22892
|
+
const fallbackSkipReason = deleteSkipReason(fallbackDeleteResult);
|
|
22893
|
+
if (fallbackSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, fallbackSkipReason, "during the UPDATE-not-supported replacement"));
|
|
22733
22894
|
const replDecision = this.providerRegistry.getProviderFor({
|
|
22734
22895
|
resourceType,
|
|
22735
22896
|
properties: resolvedProps
|
|
@@ -22783,8 +22944,9 @@ var DeployEngine = class {
|
|
|
22783
22944
|
provisionedBy: currentResource.provisionedBy
|
|
22784
22945
|
}).provider;
|
|
22785
22946
|
this.logger.debug(`Deleting ${logicalId} (${resourceType})`);
|
|
22947
|
+
let deleteResult = void 0;
|
|
22786
22948
|
try {
|
|
22787
|
-
await this.withRetry(() => deleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22949
|
+
deleteResult = await this.withRetry(() => deleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
|
|
22788
22950
|
expectedRegion: this.stackRegion,
|
|
22789
22951
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
|
|
22790
22952
|
}), logicalId, 3, 5e3, deleteProvider);
|
|
@@ -22793,6 +22955,16 @@ var DeployEngine = class {
|
|
|
22793
22955
|
if (msg.includes("does not exist") || msg.includes("was not found") || msg.includes("not found") || msg.includes("No policy found") || msg.includes("NoSuchEntity") || msg.includes("NotFoundException") || msg.includes("ResourceNotFoundException")) this.logger.debug(`Resource ${logicalId} already deleted (${msg}), removing from state`);
|
|
22794
22956
|
else throw deleteError;
|
|
22795
22957
|
}
|
|
22958
|
+
const deleteSkipped = deleteSkipReason(deleteResult);
|
|
22959
|
+
if (deleteSkipped !== void 0) {
|
|
22960
|
+
if (progress) progress.current++;
|
|
22961
|
+
const skipPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
22962
|
+
renderer.removeTask(logicalId);
|
|
22963
|
+
this.logger.info(`${skipPrefix}${formatResourceLine("skipped", logicalId, resourceType, `skipped (${deleteSkipped})`)}`);
|
|
22964
|
+
this.logger.warn(deleteSkippedMessage(logicalId, currentResource.physicalId, deleteSkipped, "while removing it from the template") + `. Its cdkd state record was KEPT, so the next 'cdkd deploy' re-attempts the delete. Repair the record first ('cdkd state show ${stackName}' to inspect; for a nested stack it is the CHILD's own state, whose other resources may already be gone), or delete the resource by hand and drop the record with 'cdkd state orphan ${stackName}'.`);
|
|
22965
|
+
if (counts) counts.deleteSkipped++;
|
|
22966
|
+
return { deleteSkipped };
|
|
22967
|
+
}
|
|
22796
22968
|
delete stateResources[logicalId];
|
|
22797
22969
|
if (counts) counts.deleted++;
|
|
22798
22970
|
if (progress) progress.current++;
|
|
@@ -23069,5 +23241,5 @@ var DeployEngine = class {
|
|
|
23069
23241
|
};
|
|
23070
23242
|
|
|
23071
23243
|
//#endregion
|
|
23072
|
-
export {
|
|
23073
|
-
//# sourceMappingURL=deploy-engine-
|
|
23244
|
+
export { coerceCfnBoolean as $, resolveAutoAssetStorage as $t, cyan as A, LocalMigrateError as An, createAssetRedirectResolver as At, findSilentDropProperties as B, StackTerminationProtectionError as Bn, buildDenyExternalAccessPolicy as Bt, makeCanonicalizePropertiesFn as C, setAwsClients as Cn, S3StateBackend as Ct, renderStatefulReason as D, DependencyError as Dn, stringifyValue as Dt, isStatefulRecreateTargetSync as E, ConfigError as En, AssetPublisher as Et, IAMRoleProvider as F, PartialFailureError as Fn, ensureAssetStorage as Ft, IntrinsicFunctionResolver as G, normalizeAwsError as Gn, runDockerStreaming as Gt, slowCcOperationTimeoutMs as H, SynthesisError as Hn, formatDockerLoginError as Ht, collectInlinePolicyNamesManagedBySiblings as I, ProvisioningError as In, getBootstrapMarkerKey as It, refStateLookupFromResource as J, Synthesizer as Jt, cfnRefValueFromPhysicalId as K, withErrorHandling as Kn, AssetManifestLoader as Kt, clearOnUpdateRemoval as L, ResourceTimeoutError as Ln, parseBootstrapMarker as Lt, green as M, LockError as Mn, rewriteTemplateAssetReferences as Mt, red as N, MissingCdkCliError as Nn, AssetModeResolver as Nt, formatResourceLine as O, DeployCancelledError as On, WorkGraph as Ot, yellow as P, NestedStackChildDirectDestroyError as Pn, BOOTSTRAP_MARKER_PREFIX as Pt, assertRegionMatch as Q, resolveApp as Qt, ProviderRegistry as R, ResourceUpdateNotSupportedError as Rn, validateAssetBucketName as Rt, unsupportedFinalSnapshotError as S, resetAwsClients as Sn, LockManager as St, MULTI_REGION_RECREATE_BLOCKED_TYPES as T, CdkdError as Tn, shouldRetainResource as Tt, disableInstanceApiTermination as U, formatError as Un, getDockerCmd as Ut, CloudControlProvider as V, StateError as Vn, buildDockerImage as Vt, isTerminationProtectionPropagationError as W, isCdkdError as Wn, runDockerForeground as Wt, normalizeAwsTagsToCfn as X, getDefaultStateBucketName as Xt, WAFv2WebACLProvider as Y, synthesisStatusMessage as Yt, resolveExplicitPhysicalId as Z, getLegacyStateBucketName as Zt, buildFinalSnapshotIdentifier as _, processStackMessages as _n, isRetryableTransientError as _t, DeploymentEventsStore as a, stateBucketExistenceConfirmed as an, requireConfigObject as at, isFinalSnapshotError as b, AwsClients as bn, DagBuilder as bt, replayFailedOperations as c, CFN_TEMPLATE_URL_LIMIT as cn, s3BucketDomainName as ct, deleteSkipReason as d, uploadCfnTemplate as dn, s3BucketWebsiteUrl as dt, resolveCaptureObservedState as en, configBooleanRefusal as et, withResourceDeadline as f, expectedOwnerParam as fn, applyRoleArnIfSet as ft, PRE_DELETE_SNAPSHOT_TYPES as g, AssemblyReader as gn, isMarkedNonRetryable as gt, ATOMIC_FINAL_SNAPSHOT_TYPES as h, derivePartitionAndUrlSuffix as hn, withRetry as ht, DeploymentEventsReader as i, resolveUseCdkBootstrapAssets as in, requireConfigArray as it, gray as j, LocalStartServiceError as jn, loadPublishableAssetManifest as jt, bold as k, LocalInvokeBuildError as kn, buildAssetRedirectMap as kt, replayRollback as l, MIGRATE_TMP_PREFIX as ln, s3BucketDualStackDomainName as lt, computeImplicitDeleteEdges as m, canonicalizeRegion as mn, describeTypeWithThrottleRetry as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, resolveStateBucketWithDefault as nn, readConfigString as nt, planFailedOps as o, warnDeprecatedNoPrefixCliFlag as on, requireConfigString as ot, IMPLICIT_DELETE_DEPENDENCIES as p, PARTITION_TABLE as pn, DiffCalculator as pt, getAccountInfo as q, __exportAll as qn, getDockerImageBySourceHash as qt, DeployEngine as r, resolveStateBucketWithDefaultAndSource as rn, replayWarn as rt, planRollback as s, CFN_TEMPLATE_BODY_LIMIT as sn, s3BucketArn as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, resolveSkipPrefix as tn, configStringRefusal as tt, UNSPECIFIED_SKIP_REASON as u, findLargeInlineResources as un, s3BucketRegionalDomainName as ut, ccRoutedFinalSnapshotError as v, clearBucketRegionCache as vn, isThrottlingError as vt, extractDeploymentEventError as w, AssetError as wn, rebuildClientForBucketRegion as wt, refusesFinalSnapshot as x, getAwsClients as xn, TemplateParser as xt, createPreDeleteFinalSnapshot as y, resolveBucketRegion as yn, markNonRetryable as yt, findActionableSilentDrops as z, StackHasActiveImportsError as zn, validateContainerRepoName as zt };
|
|
23245
|
+
//# sourceMappingURL=deploy-engine-D95wmKN8.js.map
|