@go-to-k/cdkd 0.301.15 → 0.302.1
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-ClDYCUia.js → asg-provider-BpRcm_UB.js} +5 -5
- package/dist/asg-provider-BpRcm_UB.js.map +1 -0
- package/dist/{aws-failure-text-CdgZn80O.js → aws-failure-text-e_ddrDDo.js} +313 -35
- package/dist/aws-failure-text-e_ddrDDo.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-Dy7N7-Il.js → deploy-engine-CYVt2NQR.js} +2189 -1104
- package/dist/deploy-engine-CYVt2NQR.js.map +1 -0
- package/dist/{iam-policy-targets-Dap4bLyq.js → iam-policy-targets-CmHNH1DY.js} +17 -4
- package/dist/iam-policy-targets-CmHNH1DY.js.map +1 -0
- package/dist/{iam-role-provider-C8Icvrf7.js → iam-role-provider-R1GC6KcT.js} +14 -5
- package/dist/iam-role-provider-R1GC6KcT.js.map +1 -0
- package/dist/index.d.ts +32 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/{neptune-provider-CtnwSAGM.js → neptune-provider-DzTl6-74.js} +7 -16
- package/dist/neptune-provider-DzTl6-74.js.map +1 -0
- package/dist/{program-CXvao3wc.js → program-CvRs5pV_.js} +172 -30
- package/dist/program-CvRs5pV_.js.map +1 -0
- package/dist/{provider-classes-CBbWGsK0.js → provider-classes-B2_u4Fg0.js} +268 -150
- package/dist/provider-classes-B2_u4Fg0.js.map +1 -0
- package/dist/{rds-provider-BMQvQTTS.js → rds-provider-CmKbYAvr.js} +7 -16
- package/dist/rds-provider-CmKbYAvr.js.map +1 -0
- package/dist/{version-DadUoJjK.js → version-CaejipV3.js} +2 -2
- package/dist/{version-DadUoJjK.js.map → version-CaejipV3.js.map} +1 -1
- package/package.json +1 -1
- package/dist/asg-provider-ClDYCUia.js.map +0 -1
- package/dist/aws-failure-text-CdgZn80O.js.map +0 -1
- package/dist/deploy-engine-Dy7N7-Il.js.map +0 -1
- package/dist/iam-policy-targets-Dap4bLyq.js.map +0 -1
- package/dist/iam-role-provider-C8Icvrf7.js.map +0 -1
- package/dist/neptune-provider-CtnwSAGM.js.map +0 -1
- package/dist/program-CXvao3wc.js.map +0 -1
- package/dist/provider-classes-CBbWGsK0.js.map +0 -1
- package/dist/rds-provider-BMQvQTTS.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { r as getAwsClients, s as __exportAll } from "./aws-clients-B_CEQGE1.js";
|
|
2
|
-
import { A as
|
|
3
|
-
import { $ as protectedReplacementAdvice, $n as
|
|
2
|
+
import { A as isNameGeneration, B as SECRET_REF_MAX_CODE_POINTS, D as getCurrentStackInstanceId, E as getCurrentSkipPrefix, F as withSkipPrefix, G as displayAwsMessage, H as UNRENDERABLE, I as withStackScope, J as displayStackName, K as displayIdent, L as withStackScopeBeforeStateRead, N as stackInstanceNameSuffix, O as getCurrentStackName, P as withNameGeneration, Q as safeMsg, R as withoutGeneratedFallbackName, S as fallbackNamePropertyFor, T as generatedNameFor, U as asIsMessage, V as STACK_REF_MAX_CODE_POINTS, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify$1, c as isStdoutReservedForPayload, et as terminalSafe, f as currentLogLineMasker, j as looksLikeCdkdGeneratedName, m as getLiveRenderer, n as describeAwsFailure, p as installLogLineMaskerSource, q as displaySafe, s as getLogger, t as VERBOSE_POINTER, tt as truncateCodePoints, v as applyDefaultNameForFallback, w as generateResourceNameWithFallback, x as explicitNamePropertyFor, y as currentNameGeneration, z as SAFE_MSG_ALTERED_CHAR } from "./aws-failure-text-e_ddrDDo.js";
|
|
3
|
+
import { $ as protectedReplacementAdvice, $n as isReplayedNameCollisionFrom, $t as ambientCredentialConfig, A as isQuotableImportValue, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as plainOrDescribed, Bt as formatLockOperation, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as commandHole, Ft as UNREPRODUCIBLE_LOCK_CLAUSE, G as runDeleteAttempt, Gt as DEFAULT_STATE_PREFIX, H as observeThenDisableProtection, Hn as shellBoundedDisplay, Ht as recoveryCommandFlags, It as buildForceUnlockCommand, J as DELETION_PROTECTION_DOC_POINTER, Jn as hasReplayMayCollide, Kt as injectiveKey, L as ProtectionFlipRegistry, Ln as isInertUnquoted, M as quotedRemedyLogicalId, Mn as SHELL_ACTIVE, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as SHELL_ACTIVE_WHY, On as isSoftAbort, Ot as hasCreatedBeforeFailure, Pn as UNSHOWABLE_VALUE, Pt as replayMadeAnotherResource, Q as pasteableAwsCommand, Qn as isRecreateRetryableError, Qt as ambientClientDefaults, R as compensateProtectionFlip, Rn as pasteableCommand, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as SynthesisError, U as protectionFlipKey, Un as shellQuote, Ut as sanitizeRecoveryValue, Vn as quotedOrDescribed, Vt as formatLockOwner, Wn as withheldTargetClause, Wt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xn as isNameCollisionErrorFrom, Yt as producerRecordKey, Zn as isNameCooldownError, Zt as withPasteableAwsProfile, _r as isThrottlingError, _t as createMaskedLogSinks, at as startInterruptWatch, bn as ResourceTimeoutError, br as wrapMaskedAwsError, bt as maskDeep, cr as isAmbiguousCcHandlerErrorCode, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as IntrinsicResolutionRefusalError, dr as isIamPropagationError, en as clientDefaultsFor, f as removalWarning, fr as isRetryableTransientError, ft as logicalIdShown, gn as MalformedProducerRecordRefusalError, gr as isMarkedNonRetryable, gt as stateOrphanRecordRemedy, hn as MacroExpansionError, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CdkdError, ir as stripControlChars, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jt as markAuxiliaryFailure, kn as normalizeAwsError, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, ln as DeploymentNotApprovedError, lr as isAmbiguousOutcomeError, m as withoutInjectedRemovals, mn as LockError, mr as retryClassificationText, mt as resourceTypeShown, nn as AccountIdUnavailableError, nr as relayedNameCollision, on as CrossAccountSecretRefusalError, ot as ElapsedBudgetRegistry, pr as isTransientServerError, qn as isUpdateUnsupportedError, rn as AssetError, rr as escapeRegExp$3, sn as DependencyError, sr as formatRetryClassificationSignals, st as monotonicNowMs, tn as credentialFingerprint, tr as markReplayMayCollide, un as DynamicReferenceRegionAmbiguousError, ut as compositeIdSeparatorRefusal, vr as markNonRetryable, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wn as StateError, wt as carryCreatedBeforeFailure, xn as ResourceUpdateNotSupportedError, xt as maskerOrIdentity, yn as ProvisioningError, yr as markRedactedCause, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as physicalIdShownBesideCommand, zt as formatLockExpiry } from "./iam-policy-targets-CmHNH1DY.js";
|
|
4
4
|
import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, s as ambientRegion, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-DBXBcg0J.js";
|
|
5
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
+
import { t as getCdkdVersion } from "./version-CaejipV3.js";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketLifecycleConfigurationCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -4577,7 +4577,8 @@ var WorkGraph = class {
|
|
|
4577
4577
|
nodeId: node.id,
|
|
4578
4578
|
error
|
|
4579
4579
|
});
|
|
4580
|
-
this.logger.
|
|
4580
|
+
if (isSoftAbort(error)) this.logger.debug(safeMsg`Not approved: ${node.id}`);
|
|
4581
|
+
else this.logger.error(`Failed: ${node.id}: ${describeAwsFailure(error).detail}`);
|
|
4581
4582
|
}).finally(() => {
|
|
4582
4583
|
active[node.type]--;
|
|
4583
4584
|
dispatch();
|
|
@@ -4591,6 +4592,12 @@ var WorkGraph = class {
|
|
|
4591
4592
|
}
|
|
4592
4593
|
if (errors.length > 0) {
|
|
4593
4594
|
const skippedCount = [...this.nodes.values()].filter((n) => n.state === "skipped").length;
|
|
4595
|
+
if (errors.every((e) => isSoftAbort(e.error))) {
|
|
4596
|
+
const lines = errors.map((e) => e.error.message);
|
|
4597
|
+
if (skippedCount > 0) lines.push(`${skippedCount} node(s) depending on a declined stack were skipped.`);
|
|
4598
|
+
reject(errors.length === 1 && skippedCount === 0 ? errors[0].error : new DeploymentNotApprovedError(lines.join("\n")));
|
|
4599
|
+
return;
|
|
4600
|
+
}
|
|
4594
4601
|
const msg = errors.map((e) => ` - ${e.nodeId}: ${describeAwsFailure(e.error).detail}`).join("\n");
|
|
4595
4602
|
reject(/* @__PURE__ */ new Error(`${errors.length} node(s) failed${skippedCount > 0 ? `, ${skippedCount} skipped` : ""}:\n${msg}`));
|
|
4596
4603
|
return;
|
|
@@ -4803,7 +4810,8 @@ const STATE_SCHEMA_VERSIONS_READABLE = [
|
|
|
4803
4810
|
9,
|
|
4804
4811
|
10,
|
|
4805
4812
|
11,
|
|
4806
|
-
12
|
|
4813
|
+
12,
|
|
4814
|
+
13
|
|
4807
4815
|
];
|
|
4808
4816
|
function hasUnverifiableParameterRefusal(record) {
|
|
4809
4817
|
return record?.observedBaselineRefused === true && record.observedBaselineRefusalReason === "unverifiable-parameter";
|
|
@@ -4851,6 +4859,13 @@ function importableOutputs(state) {
|
|
|
4851
4859
|
function exportNamesCarriedFrom(previous) {
|
|
4852
4860
|
return previous.exportNames === void 0 ? {} : { exportNames: previous.exportNames };
|
|
4853
4861
|
}
|
|
4862
|
+
function stackInstanceIdCarriedFrom(previous) {
|
|
4863
|
+
return {
|
|
4864
|
+
...previous?.stackInstanceId !== void 0 && { stackInstanceId: previous.stackInstanceId },
|
|
4865
|
+
...previous?.retiredNameGenerations !== void 0 && { retiredNameGenerations: previous.retiredNameGenerations },
|
|
4866
|
+
...previous?.supersededResources !== void 0 && { supersededResources: previous.supersededResources }
|
|
4867
|
+
};
|
|
4868
|
+
}
|
|
4854
4869
|
function skippedOutputsCarriedFrom(previous) {
|
|
4855
4870
|
return previous.skippedOutputs === void 0 ? {} : { skippedOutputs: previous.skippedOutputs };
|
|
4856
4871
|
}
|
|
@@ -4942,6 +4957,7 @@ function refuseMalformedOperation(shownStack, where, op) {
|
|
|
4942
4957
|
if (o["changeType"] !== "UPDATE") refuseMalformed(shownStack, `${where}.replacementOrphaned is only valid on an UPDATE.`);
|
|
4943
4958
|
}
|
|
4944
4959
|
if (o["wasReplaced"] !== void 0 && typeof o["wasReplaced"] !== "boolean") fail("wasReplaced", o["wasReplaced"], "a boolean when present");
|
|
4960
|
+
if (o["nameGeneration"] !== void 0 && !(typeof o["nameGeneration"] === "number" && Number.isSafeInteger(o["nameGeneration"]) && o["nameGeneration"] >= 0)) fail("nameGeneration", o["nameGeneration"], "a non-negative integer when present");
|
|
4945
4961
|
if (o["oldDeletedBeforeCreate"] !== void 0 && typeof o["oldDeletedBeforeCreate"] !== "boolean") fail("oldDeletedBeforeCreate", o["oldDeletedBeforeCreate"], "a boolean when present");
|
|
4946
4962
|
if (o["oldResourceMaySurvive"] !== void 0 && !["kept", "unconfirmed"].includes(o["oldResourceMaySurvive"])) fail("oldResourceMaySurvive", o["oldResourceMaySurvive"], "kept or unconfirmed when present");
|
|
4947
4963
|
if (o["physicalIdRecoveredFromError"] !== void 0 && typeof o["physicalIdRecoveredFromError"] !== "boolean") fail("physicalIdRecoveredFromError", o["physicalIdRecoveredFromError"], "a boolean when present");
|
|
@@ -5099,6 +5115,53 @@ async function notifyStateSaved(stackName, region) {
|
|
|
5099
5115
|
await stateSavedObserver.getStore()?.(stackName, region);
|
|
5100
5116
|
}
|
|
5101
5117
|
|
|
5118
|
+
//#endregion
|
|
5119
|
+
//#region src/state/stack-instance-id.ts
|
|
5120
|
+
const STACK_INSTANCE_SIBLING_VERSION = 1;
|
|
5121
|
+
const STACK_INSTANCE_SIBLING_FILE = "stack-instance.json";
|
|
5122
|
+
const STACK_INSTANCE_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
5123
|
+
function isStackInstanceId(value) {
|
|
5124
|
+
return typeof value === "string" && STACK_INSTANCE_ID_PATTERN.test(value);
|
|
5125
|
+
}
|
|
5126
|
+
function stackInstanceSiblingBody(id) {
|
|
5127
|
+
return JSON.stringify({
|
|
5128
|
+
stackInstanceVersion: 1,
|
|
5129
|
+
stackInstanceId: id
|
|
5130
|
+
}, null, 2);
|
|
5131
|
+
}
|
|
5132
|
+
function parseStackInstanceSibling(body) {
|
|
5133
|
+
let raw;
|
|
5134
|
+
try {
|
|
5135
|
+
raw = JSON.parse(body);
|
|
5136
|
+
} catch {
|
|
5137
|
+
return null;
|
|
5138
|
+
}
|
|
5139
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
5140
|
+
const doc = raw;
|
|
5141
|
+
if (doc["stackInstanceVersion"] !== 1) return null;
|
|
5142
|
+
return isStackInstanceId(doc["stackInstanceId"]) ? doc["stackInstanceId"] : null;
|
|
5143
|
+
}
|
|
5144
|
+
var MalformedStackInstanceIdError = class extends Error {
|
|
5145
|
+
constructor(stackLabel) {
|
|
5146
|
+
super(`The state record of ${stackLabel} holds a stackInstanceId that is not a well-formed id. cdkd does not guess which lifetime of the stack it names, since names derive from it; restore the field from an earlier version of state.json.`);
|
|
5147
|
+
this.name = "MalformedStackInstanceIdError";
|
|
5148
|
+
}
|
|
5149
|
+
};
|
|
5150
|
+
function stackInstanceIdOf(state, stackLabel) {
|
|
5151
|
+
const value = state?.stackInstanceId;
|
|
5152
|
+
if (value === void 0) return void 0;
|
|
5153
|
+
if (!isStackInstanceId(value)) throw new MalformedStackInstanceIdError(stackLabel);
|
|
5154
|
+
return value;
|
|
5155
|
+
}
|
|
5156
|
+
const STACK_INSTANCE_ID_WITHHELD = "<withheld>";
|
|
5157
|
+
function withStackInstanceIdWithheld(state) {
|
|
5158
|
+
if (state === null || typeof state !== "object" || state.stackInstanceId === void 0) return state;
|
|
5159
|
+
return {
|
|
5160
|
+
...state,
|
|
5161
|
+
stackInstanceId: STACK_INSTANCE_ID_WITHHELD
|
|
5162
|
+
};
|
|
5163
|
+
}
|
|
5164
|
+
|
|
5102
5165
|
//#endregion
|
|
5103
5166
|
//#region src/state/cross-prefix-stack-scan.ts
|
|
5104
5167
|
function journalCanOwnResources(journal) {
|
|
@@ -5110,6 +5173,8 @@ function recordCanOwnResources(record, journal) {
|
|
|
5110
5173
|
if (Object.keys(resources).length > 0) return true;
|
|
5111
5174
|
const orphans = record.orphans;
|
|
5112
5175
|
if (orphans !== void 0 && (!Array.isArray(orphans) || orphans.length > 0)) return true;
|
|
5176
|
+
const superseded = record.supersededResources;
|
|
5177
|
+
if (superseded !== void 0 && (!Array.isArray(superseded) || superseded.length > 0)) return true;
|
|
5113
5178
|
if (journal === null) return false;
|
|
5114
5179
|
const segments = journal.segments;
|
|
5115
5180
|
if (!Array.isArray(segments)) return true;
|
|
@@ -5616,6 +5681,7 @@ function legacyProbeBelongsTo(probe, region) {
|
|
|
5616
5681
|
}
|
|
5617
5682
|
const KEPT_AT_CLOCK_TOLERANCE_MS = 2e3;
|
|
5618
5683
|
const ROLLBACK_JOURNAL_OBJECT_DESCRIPTION = "the rollback journal, whose `failedOperations[].attemptedProperties` records the properties of the failed write verbatim";
|
|
5684
|
+
const STACK_INSTANCE_OBJECT_DESCRIPTION = "the write-ahead stack instance id, from which a stack's generated resource names derive";
|
|
5619
5685
|
const STATE_RECORD_OBJECT_DESCRIPTION = "the stack's state record, which carries every resource's recorded properties and attributes";
|
|
5620
5686
|
var S3StateBackend = class S3StateBackend {
|
|
5621
5687
|
logger = getLogger().child("S3StateBackend");
|
|
@@ -5627,6 +5693,7 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5627
5693
|
resolveInFlight = null;
|
|
5628
5694
|
journalsReadAbsent = /* @__PURE__ */ new Set();
|
|
5629
5695
|
journalTouches = /* @__PURE__ */ new Map();
|
|
5696
|
+
pendingStackInstanceSiblings = /* @__PURE__ */ new Map();
|
|
5630
5697
|
constructor(s3Client, config, clientOpts = {}) {
|
|
5631
5698
|
this.s3Client = s3Client;
|
|
5632
5699
|
this.config = config;
|
|
@@ -5684,6 +5751,9 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5684
5751
|
async purgeRollbackJournalVersions(stackName, region) {
|
|
5685
5752
|
await this.purgeNoncurrentVersions([this.rollbackJournalKey(stackName, region)], { objectDescription: ROLLBACK_JOURNAL_OBJECT_DESCRIPTION });
|
|
5686
5753
|
}
|
|
5754
|
+
getStackInstanceKey(stackName, region) {
|
|
5755
|
+
return `${this.config.prefix}/${stackName}/${region}/${STACK_INSTANCE_SIBLING_FILE}`;
|
|
5756
|
+
}
|
|
5687
5757
|
getCreateTokenLedgerKey(stackName, region) {
|
|
5688
5758
|
return `${this.config.prefix}/${stackName}/${region}/create-tokens.json`;
|
|
5689
5759
|
}
|
|
@@ -5798,7 +5868,8 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5798
5868
|
const { expectedEtag, migrateLegacy } = options;
|
|
5799
5869
|
const body = {
|
|
5800
5870
|
...state,
|
|
5801
|
-
|
|
5871
|
+
...stackInstanceIdCarriedFrom(state),
|
|
5872
|
+
version: 13,
|
|
5802
5873
|
stackName,
|
|
5803
5874
|
region
|
|
5804
5875
|
};
|
|
@@ -5827,6 +5898,12 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5827
5898
|
this.logger.warn(`Migrated stack ${this.displayName(stackName)} to new key, but failed to delete legacy key: ${errorDetail$2(deleteError)}`);
|
|
5828
5899
|
}
|
|
5829
5900
|
await notifyStateSaved(stackName, region);
|
|
5901
|
+
const siblingKey = this.getStackInstanceKey(stackName, region);
|
|
5902
|
+
const pendingId = this.pendingStackInstanceSiblings.get(siblingKey);
|
|
5903
|
+
if (pendingId !== void 0 && body.stackInstanceId === pendingId) {
|
|
5904
|
+
this.pendingStackInstanceSiblings.delete(siblingKey);
|
|
5905
|
+
await this.dropStackInstanceSiblingAfterSave(stackName, region);
|
|
5906
|
+
}
|
|
5830
5907
|
return response.ETag;
|
|
5831
5908
|
} catch (error) {
|
|
5832
5909
|
if (error.name === "PreconditionFailed") throw new StateError(`State has been modified by another process. Expected ETag: ${expectedEtag}, but state has changed.`, error instanceof Error ? error : void 0);
|
|
@@ -5840,6 +5917,7 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5840
5917
|
async deleteState(stackName, region) {
|
|
5841
5918
|
await this.ensureClientForBucket();
|
|
5842
5919
|
await this.deleteCreateTokenLedger(stackName, region);
|
|
5920
|
+
await this.deleteStackInstanceSibling(stackName, region);
|
|
5843
5921
|
try {
|
|
5844
5922
|
this.logger.debug(`Deleting state: ${this.stackRef(stackName, region)}`);
|
|
5845
5923
|
await this.s3Client.send(new DeleteObjectCommand({
|
|
@@ -5868,7 +5946,7 @@ var S3StateBackend = class S3StateBackend {
|
|
|
5868
5946
|
});
|
|
5869
5947
|
throw new StateError(`Failed to delete state for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}`, normalized);
|
|
5870
5948
|
} finally {
|
|
5871
|
-
await this.deleteRollbackJournal(stackName, region);
|
|
5949
|
+
await Promise.all([this.deleteRollbackJournal(stackName, region), this.purgeNoncurrentVersions([this.getStackInstanceKey(stackName, region)], { objectDescription: STACK_INSTANCE_OBJECT_DESCRIPTION })]);
|
|
5872
5950
|
}
|
|
5873
5951
|
}
|
|
5874
5952
|
async purgeDeletedStateHistory(stackName, region) {
|
|
@@ -6413,6 +6491,102 @@ var S3StateBackend = class S3StateBackend {
|
|
|
6413
6491
|
throw new StateError(`Failed to delete the create-token ledger for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}. The state record was left in place; re-run once the ledger can be deleted.`, normalized);
|
|
6414
6492
|
}
|
|
6415
6493
|
}
|
|
6494
|
+
async stackInstanceIdForFirstWrite(stackName, region, options) {
|
|
6495
|
+
const key = this.getStackInstanceKey(stackName, region);
|
|
6496
|
+
const read = async () => this.readSiblingId(key, stackName, region);
|
|
6497
|
+
try {
|
|
6498
|
+
const existing = await read();
|
|
6499
|
+
if (existing !== null) {
|
|
6500
|
+
this.pendingStackInstanceSiblings.set(key, existing);
|
|
6501
|
+
this.logger.debug(safeMsg`Reusing the write-ahead stack instance id of ${displayStackName(stackName)}`);
|
|
6502
|
+
return existing;
|
|
6503
|
+
}
|
|
6504
|
+
const minted = randomUUID();
|
|
6505
|
+
if (!options.writeAhead) return minted;
|
|
6506
|
+
await this.ensureClientForBucket();
|
|
6507
|
+
const body = stackInstanceSiblingBody(minted);
|
|
6508
|
+
const put = async () => this.s3Client.send(new PutObjectCommand({
|
|
6509
|
+
Bucket: this.config.bucket,
|
|
6510
|
+
...await this.ownerParam(),
|
|
6511
|
+
Key: key,
|
|
6512
|
+
Body: body,
|
|
6513
|
+
ContentLength: Buffer.byteLength(body),
|
|
6514
|
+
ContentType: "application/json",
|
|
6515
|
+
IfNoneMatch: "*"
|
|
6516
|
+
}));
|
|
6517
|
+
try {
|
|
6518
|
+
try {
|
|
6519
|
+
await put();
|
|
6520
|
+
} catch (error) {
|
|
6521
|
+
if (!isConditionalConflict(error)) throw error;
|
|
6522
|
+
await put();
|
|
6523
|
+
}
|
|
6524
|
+
} catch (error) {
|
|
6525
|
+
if (isNotImplemented(error)) {
|
|
6526
|
+
await this.putRawObject(key, body);
|
|
6527
|
+
this.pendingStackInstanceSiblings.set(key, minted);
|
|
6528
|
+
return minted;
|
|
6529
|
+
}
|
|
6530
|
+
if (!isConditionFailure(error)) throw error;
|
|
6531
|
+
const winner = await read();
|
|
6532
|
+
if (winner === null) throw error;
|
|
6533
|
+
this.pendingStackInstanceSiblings.set(key, winner);
|
|
6534
|
+
return winner;
|
|
6535
|
+
}
|
|
6536
|
+
this.pendingStackInstanceSiblings.set(key, minted);
|
|
6537
|
+
return minted;
|
|
6538
|
+
} catch (error) {
|
|
6539
|
+
if (error instanceof StateError) throw error;
|
|
6540
|
+
throw this.stackInstanceSiblingError(stackName, region, error, "write");
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
stackInstanceSiblingError(stackName, region, error, access) {
|
|
6544
|
+
const normalized = normalizeAwsError(error, { bucket: this.config.bucket });
|
|
6545
|
+
return new StateError(`Failed to ${access === "write" ? "read or write" : "read"} the write-ahead stack instance id of stack ${this.stackRef(stackName, region)} (${STACK_INSTANCE_SIBLING_FILE} beside its state.json): ${errorDetail$2(normalized)}. ` + (access === "write" ? "Nothing was created; re-run once the state bucket can be written." : "Nothing was changed; re-run once the state bucket can be read."), normalized);
|
|
6546
|
+
}
|
|
6547
|
+
async readSiblingId(key, stackName, region) {
|
|
6548
|
+
const body = await this.getRawObject(key);
|
|
6549
|
+
if (body === null) return null;
|
|
6550
|
+
const id = parseStackInstanceSibling(body);
|
|
6551
|
+
if (id === null) throw new StateError(`The write-ahead stack instance id of stack ${this.stackRef(stackName, region)} (${STACK_INSTANCE_SIBLING_FILE} beside its state.json) is in a format this cdkd version cannot read; upgrade cdkd, or delete that object if it is damaged`);
|
|
6552
|
+
return id;
|
|
6553
|
+
}
|
|
6554
|
+
async readStackInstanceSibling(stackName, region) {
|
|
6555
|
+
try {
|
|
6556
|
+
return await this.readSiblingId(this.getStackInstanceKey(stackName, region), stackName, region) ?? void 0;
|
|
6557
|
+
} catch (error) {
|
|
6558
|
+
if (error instanceof StateError) throw error;
|
|
6559
|
+
throw this.stackInstanceSiblingError(stackName, region, error, "read");
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
async deleteStackInstanceSibling(stackName, region) {
|
|
6563
|
+
await this.ensureClientForBucket();
|
|
6564
|
+
const key = this.getStackInstanceKey(stackName, region);
|
|
6565
|
+
this.pendingStackInstanceSiblings.delete(key);
|
|
6566
|
+
try {
|
|
6567
|
+
await this.s3Client.send(new DeleteObjectCommand({
|
|
6568
|
+
Bucket: this.config.bucket,
|
|
6569
|
+
...await this.ownerParam(),
|
|
6570
|
+
Key: key
|
|
6571
|
+
}));
|
|
6572
|
+
} catch (error) {
|
|
6573
|
+
if (isNoSuchKey(error) || error.name === "NotFound") return;
|
|
6574
|
+
const normalized = normalizeAwsError(error, {
|
|
6575
|
+
bucket: this.config.bucket,
|
|
6576
|
+
operation: "DeleteObject"
|
|
6577
|
+
});
|
|
6578
|
+
throw new StateError(`Failed to delete the write-ahead stack instance id for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}. The state record was left in place; re-run once that object can be deleted.`, normalized);
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6581
|
+
async dropStackInstanceSiblingAfterSave(stackName, region) {
|
|
6582
|
+
try {
|
|
6583
|
+
await this.deleteStackInstanceSibling(stackName, region);
|
|
6584
|
+
} catch (error) {
|
|
6585
|
+
this.logger.debug(safeMsg`Could not delete the write-ahead stack instance id of ${displayStackName(stackName)}: ${describeAwsFailure(error).summary}`);
|
|
6586
|
+
return;
|
|
6587
|
+
}
|
|
6588
|
+
await this.purgeNoncurrentVersions([this.getStackInstanceKey(stackName, region)], { objectDescription: STACK_INSTANCE_OBJECT_DESCRIPTION });
|
|
6589
|
+
}
|
|
6416
6590
|
async loadRollbackJournal(stackName, region) {
|
|
6417
6591
|
const key = this.rollbackJournalKey(stackName, region);
|
|
6418
6592
|
const touches = this.journalTouches.get(key) ?? 0;
|
|
@@ -6611,6 +6785,7 @@ var S3StateBackend = class S3StateBackend {
|
|
|
6611
6785
|
if (raw === region) return { state };
|
|
6612
6786
|
if (raw === void 0) return { state: {
|
|
6613
6787
|
...state,
|
|
6788
|
+
...stackInstanceIdCarriedFrom(state),
|
|
6614
6789
|
region
|
|
6615
6790
|
} };
|
|
6616
6791
|
const kind = describeRegionValueKind(raw);
|
|
@@ -6619,6 +6794,7 @@ var S3StateBackend = class S3StateBackend {
|
|
|
6619
6794
|
return {
|
|
6620
6795
|
state: {
|
|
6621
6796
|
...state,
|
|
6797
|
+
...stackInstanceIdCarriedFrom(state),
|
|
6622
6798
|
region
|
|
6623
6799
|
},
|
|
6624
6800
|
divergentBodyRegion: raw
|
|
@@ -13577,62 +13753,21 @@ function sentIdentifierIs(requested, recorded, observed, physicalId) {
|
|
|
13577
13753
|
return sent !== void 0 && heldAt(recorded, observed, [key]).value === sent;
|
|
13578
13754
|
});
|
|
13579
13755
|
}
|
|
13756
|
+
const derivedEntry = (resourceType, file) => ({
|
|
13757
|
+
file,
|
|
13758
|
+
source: `generatedNameFor('${resourceType}', logicalId)`,
|
|
13759
|
+
derive: (id) => generatedNameFor(resourceType, id)
|
|
13760
|
+
});
|
|
13580
13761
|
const DERIVED_GENERATED_NAMES = {
|
|
13581
|
-
"AWS::AutoScaling::AutoScalingGroup":
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
"AWS::
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
},
|
|
13591
|
-
"AWS::DynamoDB::GlobalTable": {
|
|
13592
|
-
file: "dynamodb-globaltable-provider.ts",
|
|
13593
|
-
source: "generateResourceName(logicalId, { maxLength: 255 })",
|
|
13594
|
-
derive: (id) => generateResourceName(id, { maxLength: 255 })
|
|
13595
|
-
},
|
|
13596
|
-
"AWS::Logs::LogGroup": {
|
|
13597
|
-
file: "logs-loggroup-provider.ts",
|
|
13598
|
-
source: "`/cdkd/${generateResourceName(logicalId, { maxLength: 506, allowedPattern: /[^a-zA-Z0-9-/_]/g })}`",
|
|
13599
|
-
derive: (id) => `/cdkd/${generateResourceName(id, {
|
|
13600
|
-
maxLength: 506,
|
|
13601
|
-
allowedPattern: /[^a-zA-Z0-9-/_]/g
|
|
13602
|
-
})}`
|
|
13603
|
-
},
|
|
13604
|
-
"AWS::RDS::DBProxy": {
|
|
13605
|
-
file: "rds-dbproxy-provider.ts",
|
|
13606
|
-
source: "generateResourceName(logicalId, { maxLength: 64 })",
|
|
13607
|
-
derive: (id) => generateResourceName(id, { maxLength: 64 })
|
|
13608
|
-
},
|
|
13609
|
-
"AWS::RDS::DBProxyEndpoint": {
|
|
13610
|
-
file: "rds-dbproxy-endpoint-provider.ts",
|
|
13611
|
-
source: "generateResourceName(logicalId, { maxLength: 64 })",
|
|
13612
|
-
derive: (id) => generateResourceName(id, { maxLength: 64 })
|
|
13613
|
-
},
|
|
13614
|
-
"AWS::S3::Bucket": {
|
|
13615
|
-
file: "s3-bucket-provider.ts",
|
|
13616
|
-
source: "generateResourceName(logicalId, {\n maxLength: 63,\n lowercase: true,\n allowedPattern: /[^a-z0-9.-]/g,\n })",
|
|
13617
|
-
derive: (id) => generateResourceName(id, {
|
|
13618
|
-
maxLength: 63,
|
|
13619
|
-
lowercase: true,
|
|
13620
|
-
allowedPattern: /[^a-z0-9.-]/g
|
|
13621
|
-
})
|
|
13622
|
-
},
|
|
13623
|
-
"AWS::Scheduler::Schedule": {
|
|
13624
|
-
file: "scheduler-schedule-provider.ts",
|
|
13625
|
-
source: "generateResourceName(logicalId, { maxLength: 64 })",
|
|
13626
|
-
derive: (id) => generateResourceName(id, { maxLength: 64 })
|
|
13627
|
-
},
|
|
13628
|
-
"AWS::SSM::Parameter": {
|
|
13629
|
-
file: "ssm-parameter-provider.ts",
|
|
13630
|
-
source: "`/${generateResourceName(logicalId, { maxLength: 1023, allowedPattern: /[^a-zA-Z0-9-/_]/g })}`",
|
|
13631
|
-
derive: (id) => `/${generateResourceName(id, {
|
|
13632
|
-
maxLength: 1023,
|
|
13633
|
-
allowedPattern: /[^a-zA-Z0-9-/_]/g
|
|
13634
|
-
})}`
|
|
13635
|
-
}
|
|
13762
|
+
"AWS::AutoScaling::AutoScalingGroup": derivedEntry("AWS::AutoScaling::AutoScalingGroup", "asg-provider.ts"),
|
|
13763
|
+
"AWS::CodeCommit::Repository": derivedEntry("AWS::CodeCommit::Repository", "codecommit-repository-provider.ts"),
|
|
13764
|
+
"AWS::DynamoDB::GlobalTable": derivedEntry("AWS::DynamoDB::GlobalTable", "dynamodb-globaltable-provider.ts"),
|
|
13765
|
+
"AWS::Logs::LogGroup": derivedEntry("AWS::Logs::LogGroup", "logs-loggroup-provider.ts"),
|
|
13766
|
+
"AWS::RDS::DBProxy": derivedEntry("AWS::RDS::DBProxy", "rds-dbproxy-provider.ts"),
|
|
13767
|
+
"AWS::RDS::DBProxyEndpoint": derivedEntry("AWS::RDS::DBProxyEndpoint", "rds-dbproxy-endpoint-provider.ts"),
|
|
13768
|
+
"AWS::S3::Bucket": derivedEntry("AWS::S3::Bucket", "s3-bucket-provider.ts"),
|
|
13769
|
+
"AWS::Scheduler::Schedule": derivedEntry("AWS::Scheduler::Schedule", "scheduler-schedule-provider.ts"),
|
|
13770
|
+
"AWS::SSM::Parameter": derivedEntry("AWS::SSM::Parameter", "ssm-parameter-provider.ts")
|
|
13636
13771
|
};
|
|
13637
13772
|
|
|
13638
13773
|
//#endregion
|
|
@@ -13720,6 +13855,52 @@ function replacementSentNameMoves(input) {
|
|
|
13720
13855
|
physicalId: input.physicalId
|
|
13721
13856
|
};
|
|
13722
13857
|
}
|
|
13858
|
+
function generatedReplacementName(resourceType, createdVia, desired, logicalId) {
|
|
13859
|
+
const declared = (property) => {
|
|
13860
|
+
const value = desired?.[property];
|
|
13861
|
+
return value !== void 0 && value !== null && value !== "";
|
|
13862
|
+
};
|
|
13863
|
+
const fallbackProperty = fallbackNamePropertyFor(resourceType);
|
|
13864
|
+
if (createdVia === "cc-api" || GENERATED_NAME_VERBATIM.has(resourceType)) {
|
|
13865
|
+
if (fallbackProperty === void 0 || declared(fallbackProperty)) return void 0;
|
|
13866
|
+
const name = applyDefaultNameForFallback(logicalId, resourceType, desired ?? {}, "omit")[fallbackProperty];
|
|
13867
|
+
return typeof name === "string" ? {
|
|
13868
|
+
property: fallbackProperty,
|
|
13869
|
+
name
|
|
13870
|
+
} : void 0;
|
|
13871
|
+
}
|
|
13872
|
+
const rewrite = ownEntry$1(SENT_NAME_REWRITTEN, resourceType);
|
|
13873
|
+
if (rewrite !== void 0) {
|
|
13874
|
+
if (declared(rewrite.property)) return void 0;
|
|
13875
|
+
return {
|
|
13876
|
+
property: rewrite.property,
|
|
13877
|
+
name: generateResourceNameWithFallback(void 0, logicalId, { maxLength: rewrite.maxLength })
|
|
13878
|
+
};
|
|
13879
|
+
}
|
|
13880
|
+
const derived = ownEntry$1(DERIVED_GENERATED_NAMES, resourceType);
|
|
13881
|
+
const property = explicitNamePropertyFor(resourceType);
|
|
13882
|
+
if (derived === void 0 || property === void 0 || declared(property)) return void 0;
|
|
13883
|
+
return {
|
|
13884
|
+
property,
|
|
13885
|
+
name: derived.derive(logicalId)
|
|
13886
|
+
};
|
|
13887
|
+
}
|
|
13888
|
+
function replacementGeneratedNameMoves(input) {
|
|
13889
|
+
if (getCurrentStackInstanceId() === void 0) return void 0;
|
|
13890
|
+
if (input.oldResourceType !== input.newResourceType) return void 0;
|
|
13891
|
+
const generated = generatedReplacementName(input.newResourceType, input.createdVia, input.desiredProperties, input.logicalId);
|
|
13892
|
+
if (generated === void 0 || generated.name === "") return void 0;
|
|
13893
|
+
const fold = CASE_INSENSITIVE_NAME_TYPES.has(input.newResourceType) ? (value) => value.toLowerCase() : (value) => value;
|
|
13894
|
+
if (input.physicalId === "" || holderIdNames(fold(input.physicalId), fold(generated.name))) return;
|
|
13895
|
+
return {
|
|
13896
|
+
property: generated.property,
|
|
13897
|
+
desiredName: generated.name,
|
|
13898
|
+
heldName: void 0,
|
|
13899
|
+
heldProperty: void 0,
|
|
13900
|
+
physicalId: input.physicalId,
|
|
13901
|
+
generated: true
|
|
13902
|
+
};
|
|
13903
|
+
}
|
|
13723
13904
|
function maskRewrittenSentName(resourceType, properties, logicalId, base) {
|
|
13724
13905
|
const sent = sentRewrittenName(resourceType, properties, logicalId);
|
|
13725
13906
|
if (sent === void 0) return base;
|
|
@@ -27247,7 +27428,7 @@ var CloudControlProvider = class {
|
|
|
27247
27428
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
27248
27429
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
27249
27430
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
27250
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
27431
|
+
const { ASGProvider } = await import("./asg-provider-BpRcm_UB.js");
|
|
27251
27432
|
const delegateRegion = ambientRegion();
|
|
27252
27433
|
let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
|
|
27253
27434
|
if (asgProvider === void 0) {
|
|
@@ -27353,7 +27534,7 @@ var CloudControlProvider = class {
|
|
|
27353
27534
|
const family = SDK_DELETE_FAMILIES.get(resourceType);
|
|
27354
27535
|
const cached = this.sdkDeleteDelegates.get(family);
|
|
27355
27536
|
if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
|
|
27356
|
-
const provider = family === "rds" ? new (await (import("./rds-provider-
|
|
27537
|
+
const provider = family === "rds" ? new (await (import("./rds-provider-CmKbYAvr.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-DzTl6-74.js"))).NeptuneProvider({ region: ccRegion });
|
|
27357
27538
|
this.sdkDeleteDelegates.set(family, {
|
|
27358
27539
|
region: ccRegion,
|
|
27359
27540
|
provider
|
|
@@ -32050,245 +32231,682 @@ function isRefusedByName(error) {
|
|
|
32050
32231
|
}
|
|
32051
32232
|
|
|
32052
32233
|
//#endregion
|
|
32053
|
-
//#region src/
|
|
32054
|
-
|
|
32055
|
-
|
|
32056
|
-
|
|
32057
|
-
|
|
32058
|
-
const tokenKey = (scope, logicalId, maxLength, charset) => injectiveKey(scope, ambientRegion() ?? "", getCurrentStackName() ?? "", logicalId, maxLength, charset);
|
|
32059
|
-
const derive = (key, generation, maxLength, charset) => {
|
|
32060
|
-
const digest = createHash("sha256").update(`${PROCESS_NONCE}\u0000${key}\u0000${generation}`).digest("hex");
|
|
32061
|
-
return `cdkd${charset === "alphanumeric" ? "" : "-"}${digest}`.slice(0, maxLength);
|
|
32062
|
-
};
|
|
32063
|
-
function acquireIdempotencyToken(options) {
|
|
32064
|
-
const { scope, logicalId, maxLength = 64, charset = "default" } = options;
|
|
32065
|
-
const key = tokenKey(scope, logicalId, maxLength, charset);
|
|
32066
|
-
const existing = inFlight$1.get(key);
|
|
32067
|
-
const value = existing ?? derive(key, generations.get(key) ?? 0, maxLength, charset);
|
|
32068
|
-
if (existing === void 0) inFlight$1.set(key, value);
|
|
32069
|
-
return {
|
|
32070
|
-
value,
|
|
32071
|
-
release: () => {
|
|
32072
|
-
if (!inFlight$1.has(key)) return;
|
|
32073
|
-
inFlight$1.delete(key);
|
|
32074
|
-
const generation = (generations.get(key) ?? 0) + 1;
|
|
32075
|
-
if (!generations.has(key) && generations.size >= MAX_TRACKED_GENERATIONS) {
|
|
32076
|
-
const oldest = generations.keys().next();
|
|
32077
|
-
if (!oldest.done) generations.delete(oldest.value);
|
|
32078
|
-
}
|
|
32079
|
-
generations.set(key, generation);
|
|
32080
|
-
}
|
|
32234
|
+
//#region src/types/deployment-events.ts
|
|
32235
|
+
function extractDeploymentEventError(err) {
|
|
32236
|
+
if (!(err instanceof Error)) return {
|
|
32237
|
+
name: "UnknownError",
|
|
32238
|
+
message: safeStringify$1(err)
|
|
32081
32239
|
};
|
|
32082
|
-
|
|
32083
|
-
|
|
32084
|
-
|
|
32085
|
-
|
|
32086
|
-
|
|
32087
|
-
|
|
32088
|
-
|
|
32089
|
-
|
|
32090
|
-
|
|
32091
|
-
|
|
32240
|
+
const result = {
|
|
32241
|
+
name: err.name || "Error",
|
|
32242
|
+
message: err.message
|
|
32243
|
+
};
|
|
32244
|
+
let current = err;
|
|
32245
|
+
for (let depth = 0; depth < 10 && current instanceof Error; depth++) {
|
|
32246
|
+
const maybeAws = current;
|
|
32247
|
+
if (maybeAws.$metadata !== void 0) {
|
|
32248
|
+
const code = maybeAws.Code ?? maybeAws.name;
|
|
32249
|
+
if (code) result.awsErrorCode = code;
|
|
32250
|
+
if (maybeAws.$metadata.requestId) result.requestId = maybeAws.$metadata.requestId;
|
|
32251
|
+
}
|
|
32252
|
+
current = current.cause;
|
|
32253
|
+
}
|
|
32254
|
+
return result;
|
|
32092
32255
|
}
|
|
32093
32256
|
|
|
32094
32257
|
//#endregion
|
|
32095
|
-
//#region src/
|
|
32096
|
-
|
|
32097
|
-
|
|
32098
|
-
|
|
32099
|
-
|
|
32100
|
-
|
|
32101
|
-
|
|
32102
|
-
|
|
32103
|
-
|
|
32104
|
-
|
|
32105
|
-
|
|
32106
|
-
|
|
32107
|
-
|
|
32108
|
-
|
|
32109
|
-
|
|
32110
|
-
|
|
32111
|
-
|
|
32258
|
+
//#region src/state/deployment-events-store.ts
|
|
32259
|
+
const DEPLOYMENT_EVENTS_MAX_INDEX_RUNS = 20;
|
|
32260
|
+
const FLUSH_INTERVAL_MS = 2e3;
|
|
32261
|
+
const FLUSH_EVENT_THRESHOLD = 50;
|
|
32262
|
+
function newDeploymentRunId(now = /* @__PURE__ */ new Date()) {
|
|
32263
|
+
return `${now.toISOString().replace(/[-:.]/g, "")}-${randomUUID().slice(0, 8)}`;
|
|
32264
|
+
}
|
|
32265
|
+
function deploymentEventsKey(prefix, stackName, region, runId) {
|
|
32266
|
+
return `${prefix}/${stackName}/${region}/deployments/${runId}.jsonl`;
|
|
32267
|
+
}
|
|
32268
|
+
function deploymentEventsIndexKey(prefix, stackName, region) {
|
|
32269
|
+
return `${prefix}/${stackName}/${region}/deployments/index.json`;
|
|
32270
|
+
}
|
|
32271
|
+
function deploymentsDirPrefix(prefix, stackName, region) {
|
|
32272
|
+
return `${prefix}/${stackName}/${region}/deployments/`;
|
|
32273
|
+
}
|
|
32274
|
+
const DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION = "deployment-event streams and their index, whose recorded error messages can quote values the secret mask does not catch";
|
|
32275
|
+
async function deleteAndPurgeEventObjects(backend, keys, dirPrefix, scope = "deleted-keys") {
|
|
32276
|
+
if (keys.length === 0) return void 0;
|
|
32277
|
+
let swept;
|
|
32278
|
+
try {
|
|
32279
|
+
await backend.deleteRawObjects(keys);
|
|
32280
|
+
} finally {
|
|
32281
|
+
if (scope === "whole-dir") swept = await backend.purgeNoncurrentVersionsUnderPrefix(dirPrefix, { objectDescription: DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION });
|
|
32282
|
+
else await backend.purgeNoncurrentVersions(keys, {
|
|
32283
|
+
...keys.length > 1 && { listPrefix: dirPrefix },
|
|
32284
|
+
objectDescription: DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION
|
|
32285
|
+
});
|
|
32112
32286
|
}
|
|
32113
|
-
|
|
32114
|
-
|
|
32115
|
-
|
|
32116
|
-
|
|
32287
|
+
return swept;
|
|
32288
|
+
}
|
|
32289
|
+
function runIdTimestampMs(runId) {
|
|
32290
|
+
const m = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z/.exec(runId);
|
|
32291
|
+
if (!m) return null;
|
|
32292
|
+
const iso = `${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}.${m[7]}Z`;
|
|
32293
|
+
const ms = Date.parse(iso);
|
|
32294
|
+
return Number.isNaN(ms) ? null : ms;
|
|
32295
|
+
}
|
|
32296
|
+
function runIdFromJsonlKey(key, dirPrefix) {
|
|
32297
|
+
if (!key.startsWith(dirPrefix) || !key.endsWith(".jsonl")) return null;
|
|
32298
|
+
return key.slice(dirPrefix.length, -6);
|
|
32299
|
+
}
|
|
32300
|
+
var DeploymentEventsStore = class {
|
|
32301
|
+
logger = getLogger().child("DeploymentEvents");
|
|
32302
|
+
backend;
|
|
32303
|
+
stackName;
|
|
32304
|
+
region;
|
|
32305
|
+
command;
|
|
32306
|
+
runId;
|
|
32307
|
+
cdkdVersion;
|
|
32308
|
+
startedAt;
|
|
32309
|
+
events = [];
|
|
32310
|
+
persistedCount = 0;
|
|
32311
|
+
flushTimer;
|
|
32312
|
+
writeChain = Promise.resolve();
|
|
32313
|
+
warnedOnce = false;
|
|
32314
|
+
finalized = false;
|
|
32315
|
+
constructor(backend, options) {
|
|
32316
|
+
this.backend = backend;
|
|
32317
|
+
this.stackName = options.stackName;
|
|
32318
|
+
this.region = options.region;
|
|
32319
|
+
this.command = options.command;
|
|
32320
|
+
this.runId = options.runId ?? newDeploymentRunId();
|
|
32321
|
+
this.cdkdVersion = options.cdkdVersion ?? getCdkdVersion();
|
|
32322
|
+
this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
32117
32323
|
}
|
|
32118
|
-
|
|
32119
|
-
|
|
32120
|
-
|
|
32324
|
+
record(event) {
|
|
32325
|
+
try {
|
|
32326
|
+
if (this.finalized) return;
|
|
32327
|
+
this.events.push({
|
|
32328
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32329
|
+
...event
|
|
32330
|
+
});
|
|
32331
|
+
if (this.events.length - this.persistedCount >= FLUSH_EVENT_THRESHOLD) this.scheduleFlush(0);
|
|
32332
|
+
else this.scheduleFlush(FLUSH_INTERVAL_MS);
|
|
32333
|
+
} catch {}
|
|
32121
32334
|
}
|
|
32122
|
-
async
|
|
32123
|
-
if (this.
|
|
32124
|
-
|
|
32125
|
-
|
|
32126
|
-
|
|
32127
|
-
|
|
32128
|
-
if (loaded !== null && this.replaceRecordedLedger && loaded.stateRecorded === true) {
|
|
32129
|
-
this.logger.info("This stack has no state record but its create-token ledger outlived an earlier one; starting a fresh ledger, so this deploy does not take over resources that deployment left.");
|
|
32130
|
-
this.doc = emptyCreateTokenLedger(randomUUID());
|
|
32131
|
-
this.startedThisDeploy = true;
|
|
32132
|
-
return this.doc;
|
|
32335
|
+
async finalize(result) {
|
|
32336
|
+
if (this.finalized) return;
|
|
32337
|
+
this.finalized = true;
|
|
32338
|
+
if (this.flushTimer) {
|
|
32339
|
+
clearTimeout(this.flushTimer);
|
|
32340
|
+
this.flushTimer = void 0;
|
|
32133
32341
|
}
|
|
32134
|
-
this.
|
|
32135
|
-
|
|
32342
|
+
if (this.events.length === 0) return;
|
|
32343
|
+
await this.enqueueWrite(async () => {
|
|
32344
|
+
const indexRead = this.readIndexRuns();
|
|
32345
|
+
indexRead.catch(() => {});
|
|
32346
|
+
await this.doFlush();
|
|
32347
|
+
await this.writeIndexAndPrune(result, await indexRead);
|
|
32348
|
+
});
|
|
32136
32349
|
}
|
|
32137
|
-
async
|
|
32138
|
-
|
|
32139
|
-
|
|
32140
|
-
|
|
32141
|
-
|
|
32350
|
+
async writeIndexAndPrune(result, existingRuns) {
|
|
32351
|
+
const { key, file, runs } = this.buildIndexUpdate(result, existingRuns);
|
|
32352
|
+
const keptRunIds = runs.map((r) => r.runId);
|
|
32353
|
+
const willPrune = keptRunIds.length >= 20;
|
|
32354
|
+
const dirPrefix = deploymentsDirPrefix(this.backend.prefix, this.stackName, this.region);
|
|
32355
|
+
const staleKeysRead = willPrune ? this.backend.listRawKeys(dirPrefix) : void 0;
|
|
32356
|
+
staleKeysRead?.catch(() => {});
|
|
32357
|
+
await this.backend.putRawObject(key, JSON.stringify(file, null, 2));
|
|
32358
|
+
if (!staleKeysRead) return;
|
|
32359
|
+
await this.pruneSupersededRunFiles(keptRunIds, dirPrefix, await staleKeysRead);
|
|
32142
32360
|
}
|
|
32143
|
-
|
|
32144
|
-
|
|
32145
|
-
if (this.unrecordedLetGo.has(logicalId)) throw this.wrapLedgerError(logicalId, this.unrecordedLetGo.get(logicalId));
|
|
32146
|
-
const earlier = this.doc?.sent[logicalId];
|
|
32147
|
-
if (earlier !== void 0 && earlier.base === base) return {
|
|
32148
|
-
value: earlier.token,
|
|
32149
|
-
earlierFirstSentAt: earlier.firstSentAt,
|
|
32150
|
-
ledgerStartedThisDeploy: false
|
|
32151
|
-
};
|
|
32152
|
-
let doc;
|
|
32153
|
-
try {
|
|
32154
|
-
const loaded = await this.current();
|
|
32155
|
-
if (loaded === null) {
|
|
32156
|
-
doc = emptyCreateTokenLedger(randomUUID());
|
|
32157
|
-
this.doc = doc;
|
|
32158
|
-
this.startedThisDeploy = true;
|
|
32159
|
-
} else {
|
|
32160
|
-
doc = loaded;
|
|
32161
|
-
const recorded = doc.sent[logicalId];
|
|
32162
|
-
if (recorded !== void 0 && recorded.base === base) return {
|
|
32163
|
-
value: recorded.token,
|
|
32164
|
-
earlierFirstSentAt: recorded.firstSentAt,
|
|
32165
|
-
ledgerStartedThisDeploy: false
|
|
32166
|
-
};
|
|
32167
|
-
}
|
|
32168
|
-
} catch (error) {
|
|
32169
|
-
this.stale = true;
|
|
32170
|
-
throw this.wrapLedgerError(logicalId, error);
|
|
32171
|
-
}
|
|
32172
|
-
const value = derive(doc.nonce);
|
|
32173
|
-
const previous = doc.sent[logicalId];
|
|
32174
|
-
doc.sent[logicalId] = {
|
|
32175
|
-
base,
|
|
32176
|
-
token: value,
|
|
32177
|
-
firstSentAt
|
|
32178
|
-
};
|
|
32179
|
-
try {
|
|
32180
|
-
await this.persist(doc);
|
|
32181
|
-
} catch (error) {
|
|
32182
|
-
if (previous === void 0) delete doc.sent[logicalId];
|
|
32183
|
-
else doc.sent[logicalId] = previous;
|
|
32184
|
-
this.stale = true;
|
|
32185
|
-
throw this.wrapLedgerError(logicalId, error);
|
|
32186
|
-
}
|
|
32187
|
-
return {
|
|
32188
|
-
value,
|
|
32189
|
-
earlierFirstSentAt: void 0,
|
|
32190
|
-
ledgerStartedThisDeploy: this.startedThisDeploy
|
|
32191
|
-
};
|
|
32192
|
-
});
|
|
32361
|
+
async drain() {
|
|
32362
|
+
await this.writeChain;
|
|
32193
32363
|
}
|
|
32194
|
-
|
|
32195
|
-
|
|
32196
|
-
|
|
32364
|
+
scheduleFlush(delayMs) {
|
|
32365
|
+
if (this.flushTimer) {
|
|
32366
|
+
if (delayMs > 0) return;
|
|
32367
|
+
clearTimeout(this.flushTimer);
|
|
32368
|
+
}
|
|
32369
|
+
this.flushTimer = setTimeout(() => {
|
|
32370
|
+
this.flushTimer = void 0;
|
|
32371
|
+
this.enqueueWrite(() => this.doFlush());
|
|
32372
|
+
}, delayMs);
|
|
32373
|
+
this.flushTimer.unref?.();
|
|
32197
32374
|
}
|
|
32198
|
-
|
|
32199
|
-
|
|
32200
|
-
|
|
32201
|
-
const doc = await this.current();
|
|
32202
|
-
if (doc === null) return;
|
|
32203
|
-
doc.nonce = randomUUID();
|
|
32204
|
-
delete doc.sent[logicalId];
|
|
32205
|
-
await this.persist(doc);
|
|
32206
|
-
this.unrecordedLetGo.delete(logicalId);
|
|
32207
|
-
} catch (error) {
|
|
32208
|
-
this.stale = true;
|
|
32209
|
-
this.unrecordedLetGo.set(logicalId, error);
|
|
32210
|
-
this.logger.warn(safeMsg`Could not record in this stack's create-token ledger that ${logicalId} was kept (${describeAwsFailure(error).summary}). A create of ${logicalId} in this deploy is refused; a later deploy's create of it may be handed the kept resource back, so check the resource it records against the one this deploy kept.`);
|
|
32211
|
-
}
|
|
32375
|
+
enqueueWrite(op) {
|
|
32376
|
+
const next = this.writeChain.then(op).catch((err) => {
|
|
32377
|
+
this.warnOnce(`Failed to persist deployment events for run ${this.runId}: ${describeAwsFailure(err).detail}`);
|
|
32212
32378
|
});
|
|
32379
|
+
this.writeChain = next;
|
|
32380
|
+
return next;
|
|
32213
32381
|
}
|
|
32214
|
-
|
|
32215
|
-
|
|
32216
|
-
|
|
32217
|
-
|
|
32218
|
-
|
|
32219
|
-
|
|
32220
|
-
throw error;
|
|
32221
|
-
}
|
|
32222
|
-
});
|
|
32382
|
+
async doFlush() {
|
|
32383
|
+
if (this.events.length === 0 || this.events.length === this.persistedCount) return;
|
|
32384
|
+
const snapshotCount = this.events.length;
|
|
32385
|
+
const body = this.events.slice(0, snapshotCount).map((e) => JSON.stringify(e)).join("\n");
|
|
32386
|
+
await this.backend.putRawObject(deploymentEventsKey(this.backend.prefix, this.stackName, this.region, this.runId), body + "\n", "application/x-ndjson");
|
|
32387
|
+
this.persistedCount = snapshotCount;
|
|
32223
32388
|
}
|
|
32224
|
-
|
|
32225
|
-
|
|
32226
|
-
|
|
32227
|
-
|
|
32228
|
-
|
|
32229
|
-
|
|
32230
|
-
|
|
32231
|
-
this.startedThisDeploy = true;
|
|
32232
|
-
}
|
|
32233
|
-
let changed = false;
|
|
32234
|
-
for (const entry of entries) {
|
|
32235
|
-
const recorded = doc.sent[entry.logicalId];
|
|
32236
|
-
if (recorded?.base === entry.base && recorded.token === entry.token) continue;
|
|
32237
|
-
doc.sent[entry.logicalId] = {
|
|
32238
|
-
base: entry.base,
|
|
32239
|
-
token: entry.token,
|
|
32240
|
-
firstSentAt
|
|
32241
|
-
};
|
|
32242
|
-
changed = true;
|
|
32243
|
-
}
|
|
32244
|
-
if (changed) await this.persist(doc);
|
|
32245
|
-
} catch (error) {
|
|
32246
|
-
this.stale = true;
|
|
32247
|
-
throw error;
|
|
32389
|
+
async readIndexRuns() {
|
|
32390
|
+
const key = deploymentEventsIndexKey(this.backend.prefix, this.stackName, this.region);
|
|
32391
|
+
try {
|
|
32392
|
+
const raw = await this.backend.getRawObject(key);
|
|
32393
|
+
if (raw !== null) {
|
|
32394
|
+
const parsed = JSON.parse(raw);
|
|
32395
|
+
if (Array.isArray(parsed.runs)) return parsed.runs;
|
|
32248
32396
|
}
|
|
32249
|
-
})
|
|
32397
|
+
} catch (err) {
|
|
32398
|
+
this.logger.debug(`Deployment-events index unreadable, rewriting: ${describeAwsFailure(err).detail}`);
|
|
32399
|
+
}
|
|
32400
|
+
return [];
|
|
32250
32401
|
}
|
|
32251
|
-
|
|
32252
|
-
|
|
32402
|
+
buildIndexUpdate(result, existingRuns) {
|
|
32403
|
+
const key = deploymentEventsIndexKey(this.backend.prefix, this.stackName, this.region);
|
|
32404
|
+
const runs = [{
|
|
32405
|
+
runId: this.runId,
|
|
32406
|
+
command: this.command,
|
|
32407
|
+
cdkdVersion: this.cdkdVersion,
|
|
32408
|
+
startedAt: this.startedAt,
|
|
32409
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32410
|
+
result,
|
|
32411
|
+
eventCount: this.persistedCount
|
|
32412
|
+
}, ...existingRuns.filter((r) => r.runId !== this.runId)].slice(0, 20);
|
|
32413
|
+
return {
|
|
32414
|
+
key,
|
|
32415
|
+
file: {
|
|
32416
|
+
indexVersion: 1,
|
|
32417
|
+
stackName: this.stackName,
|
|
32418
|
+
region: this.region,
|
|
32419
|
+
runs,
|
|
32420
|
+
lastModified: Date.now()
|
|
32421
|
+
},
|
|
32422
|
+
runs
|
|
32423
|
+
};
|
|
32253
32424
|
}
|
|
32254
|
-
|
|
32255
|
-
|
|
32256
|
-
|
|
32257
|
-
|
|
32258
|
-
|
|
32259
|
-
|
|
32260
|
-
doc.abandonedAt = at;
|
|
32261
|
-
await this.persist(doc);
|
|
32262
|
-
} catch (error) {
|
|
32263
|
-
this.stale = true;
|
|
32264
|
-
throw error;
|
|
32265
|
-
}
|
|
32425
|
+
async pruneSupersededRunFiles(keptRunIds, dirPrefix, keys) {
|
|
32426
|
+
if (keptRunIds.length < 20) return;
|
|
32427
|
+
const cutoff = keptRunIds.reduce((min, id) => id < min ? id : min, keptRunIds[0]);
|
|
32428
|
+
const stale = keys.filter((k) => {
|
|
32429
|
+
const runId = runIdFromJsonlKey(k, dirPrefix);
|
|
32430
|
+
return runId !== null && runId < cutoff;
|
|
32266
32431
|
});
|
|
32432
|
+
if (stale.length === 0) return;
|
|
32433
|
+
await deleteAndPurgeEventObjects(this.backend, stale, dirPrefix);
|
|
32434
|
+
this.logger.debug(`Pruned ${stale.length} superseded deployment-event stream(s) for ${this.stackName} (${this.region})`);
|
|
32267
32435
|
}
|
|
32268
|
-
|
|
32269
|
-
|
|
32270
|
-
|
|
32271
|
-
|
|
32272
|
-
|
|
32273
|
-
|
|
32274
|
-
|
|
32275
|
-
|
|
32276
|
-
|
|
32277
|
-
|
|
32278
|
-
|
|
32279
|
-
|
|
32280
|
-
|
|
32281
|
-
|
|
32282
|
-
|
|
32283
|
-
|
|
32284
|
-
|
|
32285
|
-
|
|
32286
|
-
|
|
32287
|
-
|
|
32288
|
-
|
|
32289
|
-
|
|
32290
|
-
|
|
32291
|
-
|
|
32436
|
+
warnOnce(message) {
|
|
32437
|
+
if (this.warnedOnce) {
|
|
32438
|
+
this.logger.debug(message);
|
|
32439
|
+
return;
|
|
32440
|
+
}
|
|
32441
|
+
this.warnedOnce = true;
|
|
32442
|
+
this.logger.warn(`${message} — continuing; deployment events are best-effort and never block the run.`);
|
|
32443
|
+
}
|
|
32444
|
+
};
|
|
32445
|
+
var DeploymentEventsReader = class {
|
|
32446
|
+
backend;
|
|
32447
|
+
constructor(backend) {
|
|
32448
|
+
this.backend = backend;
|
|
32449
|
+
}
|
|
32450
|
+
async listRegions(stackName) {
|
|
32451
|
+
const prefix = `${this.backend.prefix}/${stackName}/`;
|
|
32452
|
+
const keys = await this.backend.listRawKeys(prefix);
|
|
32453
|
+
const regions = /* @__PURE__ */ new Set();
|
|
32454
|
+
for (const key of keys) {
|
|
32455
|
+
const segments = key.slice(prefix.length).split("/");
|
|
32456
|
+
if (segments.length === 3 && segments[1] === "deployments" && segments[0]) regions.add(segments[0]);
|
|
32457
|
+
}
|
|
32458
|
+
return [...regions].sort();
|
|
32459
|
+
}
|
|
32460
|
+
async listRuns(stackName, region) {
|
|
32461
|
+
const key = deploymentEventsIndexKey(this.backend.prefix, stackName, region);
|
|
32462
|
+
try {
|
|
32463
|
+
const raw = await this.backend.getRawObject(key);
|
|
32464
|
+
if (raw !== null) {
|
|
32465
|
+
const parsed = JSON.parse(raw);
|
|
32466
|
+
if (Array.isArray(parsed.runs)) return parsed.runs;
|
|
32467
|
+
}
|
|
32468
|
+
} catch {}
|
|
32469
|
+
const dirPrefix = `${this.backend.prefix}/${stackName}/${region}/deployments/`;
|
|
32470
|
+
const runIds = (await this.backend.listRawKeys(dirPrefix)).filter((k) => k.endsWith(".jsonl")).map((k) => k.slice(dirPrefix.length, -6)).sort().reverse();
|
|
32471
|
+
return Promise.all(runIds.map((runId) => this.summarizeRunFromJsonl(stackName, region, runId)));
|
|
32472
|
+
}
|
|
32473
|
+
async summarizeRunFromJsonl(stackName, region, runId) {
|
|
32474
|
+
const fallback = {
|
|
32475
|
+
runId,
|
|
32476
|
+
command: "deploy",
|
|
32477
|
+
cdkdVersion: "unknown",
|
|
32478
|
+
startedAt: "",
|
|
32479
|
+
finishedAt: "",
|
|
32480
|
+
result: "UNKNOWN",
|
|
32481
|
+
eventCount: 0
|
|
32482
|
+
};
|
|
32483
|
+
let events = null;
|
|
32484
|
+
try {
|
|
32485
|
+
events = await this.readRunEvents(stackName, region, runId);
|
|
32486
|
+
} catch {
|
|
32487
|
+
return fallback;
|
|
32488
|
+
}
|
|
32489
|
+
if (events === null || events.length === 0) return fallback;
|
|
32490
|
+
const started = events.find((e) => e.eventType === "RUN_STARTED");
|
|
32491
|
+
let finished;
|
|
32492
|
+
for (const e of events) if (e.eventType === "RUN_FINISHED") finished = e;
|
|
32493
|
+
return {
|
|
32494
|
+
runId,
|
|
32495
|
+
command: started?.command ?? fallback.command,
|
|
32496
|
+
cdkdVersion: started?.cdkdVersion ?? fallback.cdkdVersion,
|
|
32497
|
+
startedAt: started?.timestamp ?? fallback.startedAt,
|
|
32498
|
+
finishedAt: finished?.timestamp ?? fallback.finishedAt,
|
|
32499
|
+
result: finished?.result ?? "UNKNOWN",
|
|
32500
|
+
eventCount: events.length
|
|
32501
|
+
};
|
|
32502
|
+
}
|
|
32503
|
+
async readRunEvents(stackName, region, runId) {
|
|
32504
|
+
const key = deploymentEventsKey(this.backend.prefix, stackName, region, runId);
|
|
32505
|
+
const raw = await this.backend.getRawObject(key);
|
|
32506
|
+
if (raw === null) return null;
|
|
32507
|
+
const events = [];
|
|
32508
|
+
for (const line of raw.split("\n")) {
|
|
32509
|
+
const trimmed = line.trim();
|
|
32510
|
+
if (!trimmed) continue;
|
|
32511
|
+
try {
|
|
32512
|
+
events.push(JSON.parse(trimmed));
|
|
32513
|
+
} catch {}
|
|
32514
|
+
}
|
|
32515
|
+
return events;
|
|
32516
|
+
}
|
|
32517
|
+
async pruneRuns(stackName, region, opts = {}) {
|
|
32518
|
+
const dirPrefix = deploymentsDirPrefix(this.backend.prefix, stackName, region);
|
|
32519
|
+
const keys = await this.backend.listRawKeys(dirPrefix);
|
|
32520
|
+
const runIdsDesc = keys.map((k) => runIdFromJsonlKey(k, dirPrefix)).filter((id) => id !== null).sort().reverse();
|
|
32521
|
+
const indexKey = deploymentEventsIndexKey(this.backend.prefix, stackName, region);
|
|
32522
|
+
const indexExisted = keys.includes(indexKey);
|
|
32523
|
+
if (opts.all === true) {
|
|
32524
|
+
const toDelete = runIdsDesc.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
|
|
32525
|
+
const earlierVersions = await deleteAndPurgeEventObjects(this.backend, [...toDelete, indexKey], dirPrefix, "whole-dir");
|
|
32526
|
+
return {
|
|
32527
|
+
deletedRunIds: runIdsDesc,
|
|
32528
|
+
remainingRunIds: [],
|
|
32529
|
+
indexDeleted: indexExisted,
|
|
32530
|
+
...earlierVersions !== void 0 && { earlierVersions }
|
|
32531
|
+
};
|
|
32532
|
+
}
|
|
32533
|
+
const noGuards = opts.keep === void 0 && opts.olderThanMs === void 0;
|
|
32534
|
+
const keep = opts.keep ?? (noGuards ? 20 : void 0);
|
|
32535
|
+
const protectedByCount = keep === void 0 ? /* @__PURE__ */ new Set() : new Set(runIdsDesc.slice(0, keep));
|
|
32536
|
+
let candidates = runIdsDesc.filter((id) => !protectedByCount.has(id));
|
|
32537
|
+
if (opts.olderThanMs !== void 0) {
|
|
32538
|
+
const cutoff = (opts.now ?? /* @__PURE__ */ new Date()).getTime() - opts.olderThanMs;
|
|
32539
|
+
candidates = candidates.filter((id) => {
|
|
32540
|
+
const t = runIdTimestampMs(id);
|
|
32541
|
+
return t !== null && t < cutoff;
|
|
32542
|
+
});
|
|
32543
|
+
}
|
|
32544
|
+
if (candidates.length === 0) return {
|
|
32545
|
+
deletedRunIds: [],
|
|
32546
|
+
remainingRunIds: runIdsDesc,
|
|
32547
|
+
indexDeleted: false
|
|
32548
|
+
};
|
|
32549
|
+
const deletedSet = new Set(candidates);
|
|
32550
|
+
const deleteKeys = candidates.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
|
|
32551
|
+
const remainingRunIds = runIdsDesc.filter((id) => !deletedSet.has(id));
|
|
32552
|
+
if (remainingRunIds.length === 0) {
|
|
32553
|
+
await deleteAndPurgeEventObjects(this.backend, [...deleteKeys, indexKey], dirPrefix);
|
|
32554
|
+
return {
|
|
32555
|
+
deletedRunIds: candidates,
|
|
32556
|
+
remainingRunIds,
|
|
32557
|
+
indexDeleted: indexExisted
|
|
32558
|
+
};
|
|
32559
|
+
}
|
|
32560
|
+
await this.rewriteIndexAfterPrune(indexKey, stackName, region, deletedSet);
|
|
32561
|
+
await deleteAndPurgeEventObjects(this.backend, deleteKeys, dirPrefix);
|
|
32562
|
+
return {
|
|
32563
|
+
deletedRunIds: candidates,
|
|
32564
|
+
remainingRunIds,
|
|
32565
|
+
indexDeleted: false
|
|
32566
|
+
};
|
|
32567
|
+
}
|
|
32568
|
+
async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds) {
|
|
32569
|
+
let raw;
|
|
32570
|
+
try {
|
|
32571
|
+
raw = await this.backend.getRawObject(indexKey);
|
|
32572
|
+
} catch {
|
|
32573
|
+
return;
|
|
32574
|
+
}
|
|
32575
|
+
if (raw === null) return;
|
|
32576
|
+
let parsed;
|
|
32577
|
+
try {
|
|
32578
|
+
parsed = JSON.parse(raw);
|
|
32579
|
+
} catch {
|
|
32580
|
+
return;
|
|
32581
|
+
}
|
|
32582
|
+
if (!Array.isArray(parsed.runs)) return;
|
|
32583
|
+
const remaining = parsed.runs.filter((r) => !deletedRunIds.has(r.runId));
|
|
32584
|
+
if (remaining.length === parsed.runs.length) return;
|
|
32585
|
+
const file = {
|
|
32586
|
+
indexVersion: 1,
|
|
32587
|
+
stackName,
|
|
32588
|
+
region,
|
|
32589
|
+
runs: remaining,
|
|
32590
|
+
lastModified: Date.now()
|
|
32591
|
+
};
|
|
32592
|
+
await this.backend.putRawObject(indexKey, JSON.stringify(file, null, 2));
|
|
32593
|
+
}
|
|
32594
|
+
};
|
|
32595
|
+
|
|
32596
|
+
//#endregion
|
|
32597
|
+
//#region src/deployment/kept-in-history.ts
|
|
32598
|
+
function keptInEarlierRecords(records) {
|
|
32599
|
+
const out = [];
|
|
32600
|
+
for (const record of records) for (const [logicalId, raw] of Object.entries(record.resources)) {
|
|
32601
|
+
if (raw === null || typeof raw !== "object") continue;
|
|
32602
|
+
const r = raw;
|
|
32603
|
+
if (typeof r.resourceType !== "string" || typeof r.physicalId !== "string") continue;
|
|
32604
|
+
if (r.physicalId === "") continue;
|
|
32605
|
+
if (!shouldRetainResource(r.deletionPolicy)) continue;
|
|
32606
|
+
out.push({
|
|
32607
|
+
logicalId,
|
|
32608
|
+
resourceType: r.resourceType,
|
|
32609
|
+
physicalId: r.physicalId,
|
|
32610
|
+
...record.writtenAt !== void 0 && { keptAt: record.writtenAt }
|
|
32611
|
+
});
|
|
32612
|
+
}
|
|
32613
|
+
return out;
|
|
32614
|
+
}
|
|
32615
|
+
function keptInEventHistory(runs, stackName) {
|
|
32616
|
+
const made = /* @__PURE__ */ new Map();
|
|
32617
|
+
const out = [];
|
|
32618
|
+
for (const events of runs) for (const e of events) {
|
|
32619
|
+
if (e.stackName !== stackName || typeof e.logicalId !== "string") continue;
|
|
32620
|
+
if (typeof e.resourceType !== "string") continue;
|
|
32621
|
+
if (e.eventType === "RESOURCE_SUCCEEDED" && (e.operation === "CREATE" || e.operation === "UPDATE") && typeof e.physicalId === "string" && e.physicalId !== "") made.set(e.logicalId, {
|
|
32622
|
+
resourceType: e.resourceType,
|
|
32623
|
+
physicalId: e.physicalId
|
|
32624
|
+
});
|
|
32625
|
+
else if (e.eventType === "RESOURCE_RETAINED") {
|
|
32626
|
+
const m = made.get(e.logicalId);
|
|
32627
|
+
if (m !== void 0 && m.resourceType === e.resourceType) {
|
|
32628
|
+
const keptAt = Date.parse(e.timestamp);
|
|
32629
|
+
out.push({
|
|
32630
|
+
logicalId: e.logicalId,
|
|
32631
|
+
...m,
|
|
32632
|
+
...Number.isFinite(keptAt) && { keptAt }
|
|
32633
|
+
});
|
|
32634
|
+
}
|
|
32635
|
+
}
|
|
32636
|
+
}
|
|
32637
|
+
return out;
|
|
32638
|
+
}
|
|
32639
|
+
async function loadKeptInHistory(sources, stackName, region) {
|
|
32640
|
+
const [records, runs] = await Promise.all([sources.earlierStateResources(stackName, region).catch(() => []), readRecentRuns(sources, stackName, region)]);
|
|
32641
|
+
return [...keptInEarlierRecords(records), ...keptInEventHistory(runs, stackName)];
|
|
32642
|
+
}
|
|
32643
|
+
async function readRecentRuns(sources, stackName, region) {
|
|
32644
|
+
const runsOf = stackName.split("~")[0];
|
|
32645
|
+
return (async () => {
|
|
32646
|
+
const listed = (await sources.listRuns(runsOf, region)).slice(0, 20);
|
|
32647
|
+
return (await Promise.all(listed.map((r) => sources.readRunEvents(runsOf, region, r.runId).catch(() => null)))).filter((e) => e !== null).reverse();
|
|
32648
|
+
})().catch(() => []);
|
|
32649
|
+
}
|
|
32650
|
+
const RETAINED_SURVIVOR_REASON_PREFIX = "UpdateReplacePolicy: Retain kept the replacement's new";
|
|
32651
|
+
function rollbackRetainedInEventHistory(runs, stackName) {
|
|
32652
|
+
const out = [];
|
|
32653
|
+
for (const events of runs) for (const e of events) {
|
|
32654
|
+
if (e.stackName !== stackName || e.eventType !== "ROLLBACK_RESOURCE_SUCCEEDED") continue;
|
|
32655
|
+
if (typeof e.logicalId !== "string" || typeof e.resourceType !== "string") continue;
|
|
32656
|
+
if (typeof e.physicalId !== "string" || e.physicalId === "") continue;
|
|
32657
|
+
if (typeof e.reason !== "string" || !e.reason.startsWith("UpdateReplacePolicy: Retain kept the replacement's new")) continue;
|
|
32658
|
+
out.push({
|
|
32659
|
+
logicalId: e.logicalId,
|
|
32660
|
+
resourceType: e.resourceType,
|
|
32661
|
+
physicalId: e.physicalId
|
|
32662
|
+
});
|
|
32663
|
+
}
|
|
32664
|
+
return out;
|
|
32665
|
+
}
|
|
32666
|
+
async function loadRollbackRetainedCopies(sources, stackName, region) {
|
|
32667
|
+
return rollbackRetainedInEventHistory(await readRecentRuns(sources, stackName, region), stackName);
|
|
32668
|
+
}
|
|
32669
|
+
|
|
32670
|
+
//#endregion
|
|
32671
|
+
//#region src/provisioning/providers/idempotency-token.ts
|
|
32672
|
+
const PROCESS_NONCE = randomUUID();
|
|
32673
|
+
const inFlight$1 = /* @__PURE__ */ new Map();
|
|
32674
|
+
const generations = /* @__PURE__ */ new Map();
|
|
32675
|
+
const MAX_TRACKED_GENERATIONS = 1e5;
|
|
32676
|
+
const tokenKey = (scope, logicalId, maxLength, charset) => injectiveKey(scope, ambientRegion() ?? "", getCurrentStackName() ?? "", logicalId, maxLength, charset);
|
|
32677
|
+
const derive = (key, generation, maxLength, charset) => {
|
|
32678
|
+
const digest = createHash("sha256").update(`${PROCESS_NONCE}\u0000${key}\u0000${generation}`).digest("hex");
|
|
32679
|
+
return `cdkd${charset === "alphanumeric" ? "" : "-"}${digest}`.slice(0, maxLength);
|
|
32680
|
+
};
|
|
32681
|
+
function acquireIdempotencyToken(options) {
|
|
32682
|
+
const { scope, logicalId, maxLength = 64, charset = "default" } = options;
|
|
32683
|
+
const key = tokenKey(scope, logicalId, maxLength, charset);
|
|
32684
|
+
const existing = inFlight$1.get(key);
|
|
32685
|
+
const value = existing ?? derive(key, generations.get(key) ?? 0, maxLength, charset);
|
|
32686
|
+
if (existing === void 0) inFlight$1.set(key, value);
|
|
32687
|
+
return {
|
|
32688
|
+
value,
|
|
32689
|
+
release: () => {
|
|
32690
|
+
if (!inFlight$1.has(key)) return;
|
|
32691
|
+
inFlight$1.delete(key);
|
|
32692
|
+
const generation = (generations.get(key) ?? 0) + 1;
|
|
32693
|
+
if (!generations.has(key) && generations.size >= MAX_TRACKED_GENERATIONS) {
|
|
32694
|
+
const oldest = generations.keys().next();
|
|
32695
|
+
if (!oldest.done) generations.delete(oldest.value);
|
|
32696
|
+
}
|
|
32697
|
+
generations.set(key, generation);
|
|
32698
|
+
}
|
|
32699
|
+
};
|
|
32700
|
+
}
|
|
32701
|
+
let unscopedCreateTokensAllowed = false;
|
|
32702
|
+
const STACK_SCOPED_DIGEST_LENGTH = 12;
|
|
32703
|
+
function stackScopedCreateToken(options) {
|
|
32704
|
+
const { logicalId, immutableInputs, maxLength } = options;
|
|
32705
|
+
const stackName = getCurrentStackName();
|
|
32706
|
+
if (stackName === void 0 && !unscopedCreateTokensAllowed) throw new Error(`cdkd internal error: a create token for ${logicalId} was requested outside a stack scope (withStackScope), so it cannot be scoped to its stack`);
|
|
32707
|
+
const digest = createHash("sha256").update(injectiveKey(stackName ?? "", ambientRegion() ?? "", logicalId, ...immutableInputs.map((v) => JSON.stringify(v ?? null)))).digest("hex").slice(0, STACK_SCOPED_DIGEST_LENGTH);
|
|
32708
|
+
const prefixLength = maxLength - 5 - 1 - STACK_SCOPED_DIGEST_LENGTH;
|
|
32709
|
+
return `cdkd-${logicalId.slice(0, prefixLength)}-${digest}`;
|
|
32710
|
+
}
|
|
32711
|
+
|
|
32712
|
+
//#endregion
|
|
32713
|
+
//#region src/provisioning/providers/create-token-ledger.ts
|
|
32714
|
+
var CreateTokenLedger = class {
|
|
32715
|
+
doc;
|
|
32716
|
+
loadedAbsent = false;
|
|
32717
|
+
stale = false;
|
|
32718
|
+
startedThisDeploy = false;
|
|
32719
|
+
replaceRecordedLedger = false;
|
|
32720
|
+
stateRecorded = false;
|
|
32721
|
+
stateRecordedPersisted = false;
|
|
32722
|
+
unrecordedLetGo = /* @__PURE__ */ new Map();
|
|
32723
|
+
chain = Promise.resolve();
|
|
32724
|
+
logger = getLogger().child("CreateTokenLedger");
|
|
32725
|
+
store;
|
|
32726
|
+
stack;
|
|
32727
|
+
constructor(store, stack) {
|
|
32728
|
+
this.store = store;
|
|
32729
|
+
this.stack = stack;
|
|
32730
|
+
}
|
|
32731
|
+
serialized(fn) {
|
|
32732
|
+
const next = this.chain.then(fn, fn);
|
|
32733
|
+
this.chain = next.catch(() => void 0);
|
|
32734
|
+
return next;
|
|
32735
|
+
}
|
|
32736
|
+
beginDeploy(exists) {
|
|
32737
|
+
this.stateRecorded = exists;
|
|
32738
|
+
this.replaceRecordedLedger = !exists;
|
|
32739
|
+
}
|
|
32740
|
+
async current() {
|
|
32741
|
+
if (this.doc !== void 0 && !this.stale) return this.doc;
|
|
32742
|
+
if (this.loadedAbsent && !this.stale) return null;
|
|
32743
|
+
const loaded = await this.store.load();
|
|
32744
|
+
this.stale = false;
|
|
32745
|
+
this.loadedAbsent = loaded === null;
|
|
32746
|
+
if (loaded !== null && this.replaceRecordedLedger && loaded.stateRecorded === true) {
|
|
32747
|
+
this.logger.info("This stack has no state record but its create-token ledger outlived an earlier one; starting a fresh ledger, so this deploy does not take over resources that deployment left.");
|
|
32748
|
+
this.doc = emptyCreateTokenLedger(randomUUID());
|
|
32749
|
+
this.startedThisDeploy = true;
|
|
32750
|
+
return this.doc;
|
|
32751
|
+
}
|
|
32752
|
+
this.doc = loaded ?? void 0;
|
|
32753
|
+
return loaded;
|
|
32754
|
+
}
|
|
32755
|
+
async persist(doc) {
|
|
32756
|
+
if (this.stateRecorded) doc.stateRecorded = true;
|
|
32757
|
+
await this.store.save(doc);
|
|
32758
|
+
this.replaceRecordedLedger = false;
|
|
32759
|
+
if (doc.stateRecorded === true) this.stateRecordedPersisted = true;
|
|
32760
|
+
}
|
|
32761
|
+
reserve(logicalId, base, derive, firstSentAt) {
|
|
32762
|
+
return this.serialized(async () => {
|
|
32763
|
+
if (this.unrecordedLetGo.has(logicalId)) throw this.wrapLedgerError(logicalId, this.unrecordedLetGo.get(logicalId));
|
|
32764
|
+
const earlier = this.doc?.sent[logicalId];
|
|
32765
|
+
if (earlier !== void 0 && earlier.base === base) return {
|
|
32766
|
+
value: earlier.token,
|
|
32767
|
+
earlierFirstSentAt: earlier.firstSentAt,
|
|
32768
|
+
ledgerStartedThisDeploy: false
|
|
32769
|
+
};
|
|
32770
|
+
let doc;
|
|
32771
|
+
try {
|
|
32772
|
+
const loaded = await this.current();
|
|
32773
|
+
if (loaded === null) {
|
|
32774
|
+
doc = emptyCreateTokenLedger(randomUUID());
|
|
32775
|
+
this.doc = doc;
|
|
32776
|
+
this.startedThisDeploy = true;
|
|
32777
|
+
} else {
|
|
32778
|
+
doc = loaded;
|
|
32779
|
+
const recorded = doc.sent[logicalId];
|
|
32780
|
+
if (recorded !== void 0 && recorded.base === base) return {
|
|
32781
|
+
value: recorded.token,
|
|
32782
|
+
earlierFirstSentAt: recorded.firstSentAt,
|
|
32783
|
+
ledgerStartedThisDeploy: false
|
|
32784
|
+
};
|
|
32785
|
+
}
|
|
32786
|
+
} catch (error) {
|
|
32787
|
+
this.stale = true;
|
|
32788
|
+
throw this.wrapLedgerError(logicalId, error);
|
|
32789
|
+
}
|
|
32790
|
+
const value = derive(doc.nonce);
|
|
32791
|
+
const previous = doc.sent[logicalId];
|
|
32792
|
+
doc.sent[logicalId] = {
|
|
32793
|
+
base,
|
|
32794
|
+
token: value,
|
|
32795
|
+
firstSentAt
|
|
32796
|
+
};
|
|
32797
|
+
try {
|
|
32798
|
+
await this.persist(doc);
|
|
32799
|
+
} catch (error) {
|
|
32800
|
+
if (previous === void 0) delete doc.sent[logicalId];
|
|
32801
|
+
else doc.sent[logicalId] = previous;
|
|
32802
|
+
this.stale = true;
|
|
32803
|
+
throw this.wrapLedgerError(logicalId, error);
|
|
32804
|
+
}
|
|
32805
|
+
return {
|
|
32806
|
+
value,
|
|
32807
|
+
earlierFirstSentAt: void 0,
|
|
32808
|
+
ledgerStartedThisDeploy: this.startedThisDeploy
|
|
32809
|
+
};
|
|
32810
|
+
});
|
|
32811
|
+
}
|
|
32812
|
+
wrapLedgerError(logicalId, error) {
|
|
32813
|
+
const stack = this.stack === void 0 ? "this stack" : `stack ${displayStackName(this.stack.stackName)} (${displayIdent(this.stack.region)})`;
|
|
32814
|
+
return new Error(safeMsg`Could not read or write the create-token ledger of ${stack} (${describeAwsFailure(error).summary}), so the create of ${logicalId} was not sent: the token it would send without the ledger is not the one a later deploy would send, and the resource could leak. Re-run the deploy once the ledger can be read and written.`, { cause: error });
|
|
32815
|
+
}
|
|
32816
|
+
rotate(logicalId) {
|
|
32817
|
+
return this.serialized(async () => {
|
|
32818
|
+
try {
|
|
32819
|
+
const doc = await this.current();
|
|
32820
|
+
if (doc === null) return;
|
|
32821
|
+
doc.nonce = randomUUID();
|
|
32822
|
+
delete doc.sent[logicalId];
|
|
32823
|
+
await this.persist(doc);
|
|
32824
|
+
this.unrecordedLetGo.delete(logicalId);
|
|
32825
|
+
} catch (error) {
|
|
32826
|
+
this.stale = true;
|
|
32827
|
+
this.unrecordedLetGo.set(logicalId, error);
|
|
32828
|
+
this.logger.warn(safeMsg`Could not record in this stack's create-token ledger that ${logicalId} was kept (${describeAwsFailure(error).summary}). A create of ${logicalId} in this deploy is refused; a later deploy's create of it may be handed the kept resource back, so check the resource it records against the one this deploy kept.`);
|
|
32829
|
+
}
|
|
32830
|
+
});
|
|
32831
|
+
}
|
|
32832
|
+
sentEntries() {
|
|
32833
|
+
return this.serialized(async () => {
|
|
32834
|
+
try {
|
|
32835
|
+
return { ...(await this.current())?.sent ?? {} };
|
|
32836
|
+
} catch (error) {
|
|
32837
|
+
this.stale = true;
|
|
32838
|
+
throw error;
|
|
32839
|
+
}
|
|
32840
|
+
});
|
|
32841
|
+
}
|
|
32842
|
+
recordSent(entries, firstSentAt) {
|
|
32843
|
+
return this.serialized(async () => {
|
|
32844
|
+
try {
|
|
32845
|
+
let doc = await this.current();
|
|
32846
|
+
if (doc === null) {
|
|
32847
|
+
doc = emptyCreateTokenLedger(randomUUID());
|
|
32848
|
+
this.doc = doc;
|
|
32849
|
+
this.startedThisDeploy = true;
|
|
32850
|
+
}
|
|
32851
|
+
let changed = false;
|
|
32852
|
+
for (const entry of entries) {
|
|
32853
|
+
const recorded = doc.sent[entry.logicalId];
|
|
32854
|
+
if (recorded?.base === entry.base && recorded.token === entry.token) continue;
|
|
32855
|
+
doc.sent[entry.logicalId] = {
|
|
32856
|
+
base: entry.base,
|
|
32857
|
+
token: entry.token,
|
|
32858
|
+
firstSentAt
|
|
32859
|
+
};
|
|
32860
|
+
changed = true;
|
|
32861
|
+
}
|
|
32862
|
+
if (changed) await this.persist(doc);
|
|
32863
|
+
} catch (error) {
|
|
32864
|
+
this.stale = true;
|
|
32865
|
+
throw error;
|
|
32866
|
+
}
|
|
32867
|
+
});
|
|
32868
|
+
}
|
|
32869
|
+
abandonedAt() {
|
|
32870
|
+
return this.serialized(async () => (await this.current())?.abandonedAt);
|
|
32871
|
+
}
|
|
32872
|
+
noteAbandoned(at) {
|
|
32873
|
+
return this.serialized(async () => {
|
|
32874
|
+
try {
|
|
32875
|
+
const doc = await this.current();
|
|
32876
|
+
if (doc === null) return;
|
|
32877
|
+
if (!Object.values(doc.sent).some((e) => e.base.startsWith("adopt-by-name:")) || doc.abandonedAt !== void 0 && doc.abandonedAt >= at) return;
|
|
32878
|
+
doc.abandonedAt = at;
|
|
32879
|
+
await this.persist(doc);
|
|
32880
|
+
} catch (error) {
|
|
32881
|
+
this.stale = true;
|
|
32882
|
+
throw error;
|
|
32883
|
+
}
|
|
32884
|
+
});
|
|
32885
|
+
}
|
|
32886
|
+
settleAdoptingCreates(drop, failedAt) {
|
|
32887
|
+
return this.serialized(async () => {
|
|
32888
|
+
try {
|
|
32889
|
+
const doc = await this.current();
|
|
32890
|
+
if (doc === null) return;
|
|
32891
|
+
const adopting = (id) => doc.sent[id]?.base.startsWith(ADOPTING_CREATE_BASE) === true;
|
|
32892
|
+
let changed = false;
|
|
32893
|
+
for (const id of drop) {
|
|
32894
|
+
if (!adopting(id)) continue;
|
|
32895
|
+
delete doc.sent[id];
|
|
32896
|
+
changed = true;
|
|
32897
|
+
}
|
|
32898
|
+
for (const [id, at] of failedAt) {
|
|
32899
|
+
const entry = adopting(id) ? doc.sent[id] : void 0;
|
|
32900
|
+
if (entry === void 0 || entry.failedAt !== void 0) continue;
|
|
32901
|
+
entry.failedAt = at;
|
|
32902
|
+
changed = true;
|
|
32903
|
+
}
|
|
32904
|
+
if (changed) await this.persist(doc);
|
|
32905
|
+
} catch (error) {
|
|
32906
|
+
this.stale = true;
|
|
32907
|
+
throw error;
|
|
32908
|
+
}
|
|
32909
|
+
});
|
|
32292
32910
|
}
|
|
32293
32911
|
prefetch() {
|
|
32294
32912
|
return this.serialized(async () => {
|
|
@@ -32914,30 +33532,6 @@ async function createReplicationGroupFinalSnapshot(client, replicationGroupId, l
|
|
|
32914
33532
|
});
|
|
32915
33533
|
}
|
|
32916
33534
|
|
|
32917
|
-
//#endregion
|
|
32918
|
-
//#region src/types/deployment-events.ts
|
|
32919
|
-
function extractDeploymentEventError(err) {
|
|
32920
|
-
if (!(err instanceof Error)) return {
|
|
32921
|
-
name: "UnknownError",
|
|
32922
|
-
message: safeStringify$1(err)
|
|
32923
|
-
};
|
|
32924
|
-
const result = {
|
|
32925
|
-
name: err.name || "Error",
|
|
32926
|
-
message: err.message
|
|
32927
|
-
};
|
|
32928
|
-
let current = err;
|
|
32929
|
-
for (let depth = 0; depth < 10 && current instanceof Error; depth++) {
|
|
32930
|
-
const maybeAws = current;
|
|
32931
|
-
if (maybeAws.$metadata !== void 0) {
|
|
32932
|
-
const code = maybeAws.Code ?? maybeAws.name;
|
|
32933
|
-
if (code) result.awsErrorCode = code;
|
|
32934
|
-
if (maybeAws.$metadata.requestId) result.requestId = maybeAws.$metadata.requestId;
|
|
32935
|
-
}
|
|
32936
|
-
current = current.cause;
|
|
32937
|
-
}
|
|
32938
|
-
return result;
|
|
32939
|
-
}
|
|
32940
|
-
|
|
32941
33535
|
//#endregion
|
|
32942
33536
|
//#region src/deployment/rollback-executor/types.ts
|
|
32943
33537
|
const NESTED_STACK_RESOURCE_TYPE$1 = "AWS::CloudFormation::Stack";
|
|
@@ -33133,15 +33727,20 @@ function retainedSurvivorMessages(logicalId, resourceType, survivorPhysicalId, s
|
|
|
33133
33727
|
const clause = mask(stateClause);
|
|
33134
33728
|
return {
|
|
33135
33729
|
warn: ` ⚠ ${safe(logicalId)} (${safe(resourceType)}) has UpdateReplacePolicy: Retain — the replacement's new physical resource (${displaySafe(survivorId)}) is RETAINED by this rollback and is no longer tracked by cdkd: it keeps running and incurring cost, and destroying the stack will not remove it. Delete it yourself once you no longer need it. ${displaySafe(clause)}`,
|
|
33136
|
-
reason:
|
|
33730
|
+
reason: `${RETAINED_SURVIVOR_REASON_PREFIX} ${resourceType} (${survivorId}); it is live, still billing, and no longer tracked by cdkd. ${clause}`
|
|
33137
33731
|
};
|
|
33138
33732
|
}
|
|
33139
33733
|
|
|
33140
33734
|
//#endregion
|
|
33141
33735
|
//#region src/deployment/rollback-executor/names.ts
|
|
33142
33736
|
function replayPrefixScope(input, logger, mask, restoring) {
|
|
33737
|
+
const generation = input.nameGeneration;
|
|
33738
|
+
const inGeneration = (fn) => generation === void 0 ? fn() : withNameGeneration({
|
|
33739
|
+
logicalId: input.logicalId,
|
|
33740
|
+
generation
|
|
33741
|
+
}, fn);
|
|
33143
33742
|
const choice = replayPrefixChoice(input);
|
|
33144
|
-
if (choice.kind === "not-applicable") return (fn) => fn
|
|
33743
|
+
if (choice.kind === "not-applicable") return (fn) => inGeneration(fn);
|
|
33145
33744
|
const setting = (skip) => skip ? "SKIPPED" : "KEPT";
|
|
33146
33745
|
const subject = `${safe(input.logicalId)} (${safe(input.resourceType)})`;
|
|
33147
33746
|
const declared = choice.declared;
|
|
@@ -33161,7 +33760,7 @@ function replayPrefixScope(input, logger, mask, restoring) {
|
|
|
33161
33760
|
logger.warn(mask(` ⚠ ${subject}: cdkd cannot tell which user-supplied-name prefix setting created the old resource (` + (withheld ? `its physical id is withheld, as its name is secret-derived or unreadable` : shown(input.physicalId)) + `) — ` + (choice.names === void 0 ? unreadable !== void 0 ? `cdkd cannot read ${unreadable} to compare` : `cdkd cannot derive the names its ${prop} takes to compare` : secretDerived ? `its ${prop} is secret-derived, and neither name it derives matches` : `its ${prop} derives to ${quoted(choice.names.skipped)} (prefix skipped) or ${quoted(choice.names.kept)} (prefix kept), and it is neither`) + `; re-creating it with the stack-name prefix ${setting(choice.skipPrefix)}, as the failed deploy ran, so it may come back under a different physical name.`));
|
|
33162
33761
|
}
|
|
33163
33762
|
const skip = choice.skipPrefix;
|
|
33164
|
-
return (fn) => withSkipPrefix(skip, fn);
|
|
33763
|
+
return (fn) => withSkipPrefix(skip, () => inGeneration(fn));
|
|
33165
33764
|
}
|
|
33166
33765
|
function createOpMasker(logger, secrets, deployBag) {
|
|
33167
33766
|
const base = createMaskedLogSinks(logger, deployBag === void 0 ? (text) => maskSecretsInText(text, secrets) : createUnionSecretMasker([secrets, deployBag]));
|
|
@@ -34257,6 +34856,149 @@ function maskedRecordRemedyFor(reads, resources, causeScoped = false) {
|
|
|
34257
34856
|
return [parts.join(" "), ...commandLines].join("\n");
|
|
34258
34857
|
}
|
|
34259
34858
|
|
|
34859
|
+
//#endregion
|
|
34860
|
+
//#region src/deployment/delete-guard-scope.ts
|
|
34861
|
+
const storage$1 = new AsyncLocalStorage();
|
|
34862
|
+
function collectDeleteGuards(sink, fn) {
|
|
34863
|
+
return storage$1.run(sink, fn);
|
|
34864
|
+
}
|
|
34865
|
+
function reportDeleteGuards(result, target) {
|
|
34866
|
+
const sink = storage$1.getStore();
|
|
34867
|
+
if (!sink) return;
|
|
34868
|
+
for (const guard of deleteIndeterminateGuards(result)) sink.push({
|
|
34869
|
+
guard: guard.guard,
|
|
34870
|
+
reason: guard.reason,
|
|
34871
|
+
physicalId: target.physicalId,
|
|
34872
|
+
resourceType: target.resourceType,
|
|
34873
|
+
...target.provisionedBy && { provisionedBy: target.provisionedBy }
|
|
34874
|
+
});
|
|
34875
|
+
}
|
|
34876
|
+
|
|
34877
|
+
//#endregion
|
|
34878
|
+
//#region src/deployment/superseded-resources.ts
|
|
34879
|
+
function supersededResourcesOf(state) {
|
|
34880
|
+
const rows = state?.supersededResources;
|
|
34881
|
+
if (!Array.isArray(rows)) return [];
|
|
34882
|
+
return rows.filter(isSupersededResourceRecord);
|
|
34883
|
+
}
|
|
34884
|
+
function isSupersededResourceRecord(row) {
|
|
34885
|
+
if (typeof row !== "object" || row === null) return false;
|
|
34886
|
+
const entry = row;
|
|
34887
|
+
const record = entry["state"];
|
|
34888
|
+
if (typeof entry["logicalId"] !== "string") return false;
|
|
34889
|
+
if (typeof record !== "object" || record === null) return false;
|
|
34890
|
+
const { physicalId, resourceType, properties } = record;
|
|
34891
|
+
return typeof physicalId === "string" && physicalId !== "" && typeof resourceType === "string" && resourceType !== "" && typeof properties === "object" && properties !== null && !Array.isArray(properties);
|
|
34892
|
+
}
|
|
34893
|
+
function supersededHolderOf(entry, resources) {
|
|
34894
|
+
const holders = Object.values(resources).filter((record) => typeof record === "object" && record !== null && record.physicalId === entry.state.physicalId);
|
|
34895
|
+
return holders.find((record) => record.resourceType === entry.state.resourceType) ?? holders[0];
|
|
34896
|
+
}
|
|
34897
|
+
function isSupersededHeldBySameType(entry, resources) {
|
|
34898
|
+
return Object.values(resources).some((record) => typeof record === "object" && record !== null && record.physicalId === entry.state.physicalId && record.resourceType === entry.state.resourceType);
|
|
34899
|
+
}
|
|
34900
|
+
function supersededHeldByOtherTypeWarning(entry, holderType) {
|
|
34901
|
+
return `the superseded ${entry.state.resourceType} of ${entry.logicalId} (${entry.state.physicalId}) was not deleted: a ${holderType} record of this stack has the same physical id, and cdkd never deletes an id a record names. If the ${entry.state.resourceType} still exists, delete it by hand; it is no longer tracked in state.`;
|
|
34902
|
+
}
|
|
34903
|
+
function addSuperseded(host, entry) {
|
|
34904
|
+
host.supersededResources = [...(Array.isArray(host.supersededResources) ? host.supersededResources : []).filter((row) => !isSupersededResourceRecord(row) || row.state.physicalId !== entry.state.physicalId || row.state.resourceType !== entry.state.resourceType), entry];
|
|
34905
|
+
}
|
|
34906
|
+
function canRecordSuperseded(record, deleteContext) {
|
|
34907
|
+
if (deleteContext.noEchoDeleteValues !== void 0) return false;
|
|
34908
|
+
if (deleteContext.inlinePolicyClaimed !== void 0) return false;
|
|
34909
|
+
if (Array.isArray(record.noEchoLeaves) && record.noEchoLeaves.length > 0) return false;
|
|
34910
|
+
return !INLINE_POLICY_TYPES.has(record.resourceType);
|
|
34911
|
+
}
|
|
34912
|
+
const INLINE_POLICY_TYPES = /* @__PURE__ */ new Set([
|
|
34913
|
+
"AWS::IAM::Policy",
|
|
34914
|
+
"AWS::IAM::RolePolicy",
|
|
34915
|
+
"AWS::IAM::UserPolicy",
|
|
34916
|
+
"AWS::IAM::GroupPolicy"
|
|
34917
|
+
]);
|
|
34918
|
+
function removeSuperseded(host, entry) {
|
|
34919
|
+
if (!Array.isArray(host.supersededResources)) return;
|
|
34920
|
+
const remaining = host.supersededResources.filter((row) => row !== entry);
|
|
34921
|
+
if (remaining.length === 0) delete host.supersededResources;
|
|
34922
|
+
else host.supersededResources = remaining;
|
|
34923
|
+
}
|
|
34924
|
+
function supersededAfterRollback(base, pending) {
|
|
34925
|
+
const added = Array.isArray(pending.supersededResources) ? pending.supersededResources : [];
|
|
34926
|
+
if (added.length === 0) return {};
|
|
34927
|
+
return { supersededResources: [...Array.isArray(base.supersededResources) ? base.supersededResources : [], ...added] };
|
|
34928
|
+
}
|
|
34929
|
+
const SUPERSEDED_KEPT_REMEDY = "cdkd keeps it in state: the next `cdkd deploy` of this stack retries the delete, and `cdkd destroy` deletes it";
|
|
34930
|
+
function withoutSuperseded(state) {
|
|
34931
|
+
const { supersededResources: _dropped, ...rest } = state;
|
|
34932
|
+
return rest;
|
|
34933
|
+
}
|
|
34934
|
+
async function deleteSupersededEntry(entry, input) {
|
|
34935
|
+
const record = entry.state;
|
|
34936
|
+
let result;
|
|
34937
|
+
try {
|
|
34938
|
+
const send = () => input.provider.delete(entry.logicalId, record.physicalId, record.resourceType, record.properties, {
|
|
34939
|
+
expectedRegion: input.region,
|
|
34940
|
+
...entry.forceDataDelete === true && { forceDataDelete: true },
|
|
34941
|
+
...entry.finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier: entry.finalSnapshotIdentifier },
|
|
34942
|
+
deletionPolicy: replacementDeletePolicy(entry.updateReplacePolicy),
|
|
34943
|
+
...entry.skipFinalSnapshot === true && { skipFinalSnapshot: true },
|
|
34944
|
+
...input.removeProtection === true && { removeProtection: true },
|
|
34945
|
+
...input.stackDestroy === true && { stackDestroy: true },
|
|
34946
|
+
recordedAttributes: record.attributes,
|
|
34947
|
+
recordedNoEchoLeaves: record.noEchoLeaves,
|
|
34948
|
+
maskSecrets: input.maskSecrets
|
|
34949
|
+
});
|
|
34950
|
+
result = input.once === true ? await send() : await retryWhileInUse(send, input.stop);
|
|
34951
|
+
} catch (error) {
|
|
34952
|
+
return {
|
|
34953
|
+
kind: "failed",
|
|
34954
|
+
error
|
|
34955
|
+
};
|
|
34956
|
+
}
|
|
34957
|
+
reportDeleteGuards(result, {
|
|
34958
|
+
physicalId: record.physicalId,
|
|
34959
|
+
resourceType: record.resourceType,
|
|
34960
|
+
provisionedBy: record.provisionedBy
|
|
34961
|
+
});
|
|
34962
|
+
const reason = deleteSkipReason(result);
|
|
34963
|
+
return reason === void 0 ? { kind: "deleted" } : {
|
|
34964
|
+
kind: "notDeleted",
|
|
34965
|
+
reason
|
|
34966
|
+
};
|
|
34967
|
+
}
|
|
34968
|
+
const supersededInUseRetry = {
|
|
34969
|
+
attempts: 6,
|
|
34970
|
+
delayMs: 1e4
|
|
34971
|
+
};
|
|
34972
|
+
const IN_USE_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
34973
|
+
"ResourceInUseException",
|
|
34974
|
+
"ResourceInUse",
|
|
34975
|
+
"DependencyViolation"
|
|
34976
|
+
]);
|
|
34977
|
+
const IN_USE_CONFLICT = /\bare using it\b/;
|
|
34978
|
+
function isInUseRefusal(error) {
|
|
34979
|
+
for (let current = error, depth = 0; current !== void 0 && depth < 8; depth++) {
|
|
34980
|
+
if (typeof current !== "object" || current === null) return false;
|
|
34981
|
+
const { name, message } = current;
|
|
34982
|
+
if (typeof name === "string" && IN_USE_ERROR_NAMES.has(name)) return true;
|
|
34983
|
+
if (name === "ConflictException" && typeof message === "string" && IN_USE_CONFLICT.test(message)) return true;
|
|
34984
|
+
current = current.cause;
|
|
34985
|
+
}
|
|
34986
|
+
return false;
|
|
34987
|
+
}
|
|
34988
|
+
async function retryWhileInUse(send, stop) {
|
|
34989
|
+
for (let attempt = 1;; attempt++) try {
|
|
34990
|
+
return await send();
|
|
34991
|
+
} catch (error) {
|
|
34992
|
+
if (attempt >= supersededInUseRetry.attempts || stop() || !isInUseRefusal(error)) throw error;
|
|
34993
|
+
await new Promise((resolve) => setTimeout(resolve, supersededInUseRetry.delayMs));
|
|
34994
|
+
if (stop()) throw error;
|
|
34995
|
+
}
|
|
34996
|
+
}
|
|
34997
|
+
function holdsSupersededResources(record) {
|
|
34998
|
+
const rows = record.supersededResources;
|
|
34999
|
+
return rows !== void 0 && (!Array.isArray(rows) || rows.length > 0);
|
|
35000
|
+
}
|
|
35001
|
+
|
|
34260
35002
|
//#endregion
|
|
34261
35003
|
//#region src/utils/colors.ts
|
|
34262
35004
|
const codes = {
|
|
@@ -34283,6 +35025,16 @@ function withReplayDeletePrinting(scope, fn) {
|
|
|
34283
35025
|
const deployBag = scope.ctx.logOnlyNeedlesFor?.(scope.op.logicalId);
|
|
34284
35026
|
return withPrintingSecrets(scope.secrets, () => deployBag === void 0 ? fn() : withPrintingSecrets(deployBag, fn));
|
|
34285
35027
|
}
|
|
35028
|
+
function noteRolledBackCreate(scope, op, record) {
|
|
35029
|
+
if (op.changeType !== "CREATE") return;
|
|
35030
|
+
const create = {
|
|
35031
|
+
logicalId: op.logicalId,
|
|
35032
|
+
record,
|
|
35033
|
+
...op.nameGeneration !== void 0 && { nameGeneration: op.nameGeneration }
|
|
35034
|
+
};
|
|
35035
|
+
scope.result.rolledBackCreates.push(create);
|
|
35036
|
+
scope.onRolledBackCreate?.(create);
|
|
35037
|
+
}
|
|
34286
35038
|
|
|
34287
35039
|
//#endregion
|
|
34288
35040
|
//#region src/deployment/rollback-executor/replaced-survivor.ts
|
|
@@ -34332,24 +35084,6 @@ async function readSurvivor(s, oldType) {
|
|
|
34332
35084
|
}
|
|
34333
35085
|
}
|
|
34334
35086
|
|
|
34335
|
-
//#endregion
|
|
34336
|
-
//#region src/deployment/delete-guard-scope.ts
|
|
34337
|
-
const storage$1 = new AsyncLocalStorage();
|
|
34338
|
-
function collectDeleteGuards(sink, fn) {
|
|
34339
|
-
return storage$1.run(sink, fn);
|
|
34340
|
-
}
|
|
34341
|
-
function reportDeleteGuards(result, target) {
|
|
34342
|
-
const sink = storage$1.getStore();
|
|
34343
|
-
if (!sink) return;
|
|
34344
|
-
for (const guard of deleteIndeterminateGuards(result)) sink.push({
|
|
34345
|
-
guard: guard.guard,
|
|
34346
|
-
reason: guard.reason,
|
|
34347
|
-
physicalId: target.physicalId,
|
|
34348
|
-
resourceType: target.resourceType,
|
|
34349
|
-
...target.provisionedBy && { provisionedBy: target.provisionedBy }
|
|
34350
|
-
});
|
|
34351
|
-
}
|
|
34352
|
-
|
|
34353
35087
|
//#endregion
|
|
34354
35088
|
//#region src/deployment/stack-records-scope.ts
|
|
34355
35089
|
async function awaitInFlightSibling(view, self, sibling) {
|
|
@@ -34394,11 +35128,92 @@ function replayStackRecordsView(records, orphanLogicalIds = /* @__PURE__ */ new
|
|
|
34394
35128
|
};
|
|
34395
35129
|
}
|
|
34396
35130
|
|
|
35131
|
+
//#endregion
|
|
35132
|
+
//#region src/deployment/deploy-engine/name-collision.ts
|
|
35133
|
+
function replacementNameOrigin(logicalId, physicalId) {
|
|
35134
|
+
if (looksLikeCdkdGeneratedName(physicalId, logicalId, getCurrentStackName(), getCurrentStackInstanceId())) return {
|
|
35135
|
+
descriptor: `The physical name (${physicalId}) was GENERATED by cdkd from the construct's logical id rather than declared in your template, and that derivation has no random component — so the new resource asks for exactly the name the existing one still holds`,
|
|
35136
|
+
remedy: "Either give the resource an explicit physical name in your CDK code, or rename the CONSTRUCT (its id feeds the generated name — note that this replaces the resource rather than renaming it in place)"
|
|
35137
|
+
};
|
|
35138
|
+
return {
|
|
35139
|
+
descriptor: `The resource has a user-supplied physical name (${physicalId})`,
|
|
35140
|
+
remedy: "Either rename the resource in your CDK code (a fresh name lets the safe create-first order proceed)"
|
|
35141
|
+
};
|
|
35142
|
+
}
|
|
35143
|
+
function generatedReplacementHolderAdvice(input) {
|
|
35144
|
+
if (input.change?.generated !== true) return "";
|
|
35145
|
+
const name = displaySafe(input.mask(input.change.desiredName), { asciiOnly: true });
|
|
35146
|
+
const old = displaySafe(input.mask(input.oldPhysicalId), { asciiOnly: true });
|
|
35147
|
+
const lead = ` The colliding name ${isInertUnquoted(name) ? name : "the generated name"} is the one this replacement generates for its next name generation, so its holder is most likely the new resource an interrupted earlier attempt of this replacement created. If it is, `;
|
|
35148
|
+
const tail = `, or delete it and re-run the deploy.`;
|
|
35149
|
+
if (input.stackName.includes("~")) return lead + `adopt it through the top-level stack with \`cdkd import\` (then delete ${old} by hand)` + tail;
|
|
35150
|
+
const adopt = pasteableCommand("cdkd import", [{
|
|
35151
|
+
value: input.stackName,
|
|
35152
|
+
hole: "stack"
|
|
35153
|
+
}, {
|
|
35154
|
+
flag: "--resource",
|
|
35155
|
+
value: `${input.logicalId}=${input.change.desiredName}`,
|
|
35156
|
+
hole: "logicalId=physicalId"
|
|
35157
|
+
}]);
|
|
35158
|
+
const command = input.mask(adopt.command) === adopt.command ? adopt.command : void 0;
|
|
35159
|
+
return lead + (command === void 0 ? `adopt it with \`cdkd import\`` : `adopt it with \`${command}\` (using its physical id where the type records another)`) + ` and then delete ${old} by hand` + tail;
|
|
35160
|
+
}
|
|
35161
|
+
function orphanedNameCollisionAdvice(providerRegistry, changeType, logicalId, error) {
|
|
35162
|
+
if (changeType !== "CREATE") return void 0;
|
|
35163
|
+
if (!(error instanceof ProvisioningError)) return void 0;
|
|
35164
|
+
const physicalId = error.physicalId;
|
|
35165
|
+
if (!physicalId) return void 0;
|
|
35166
|
+
const replayed = isReplayedNameCollisionFrom(error, logicalId, (link) => isAuxiliaryMarkOf(link, RETRY_AUXILIARY_OWNER));
|
|
35167
|
+
if (!replayed && !isNameCollisionErrorFrom(error, logicalId)) return void 0;
|
|
35168
|
+
const stackName = getCurrentStackName();
|
|
35169
|
+
if (!looksLikeCdkdGeneratedName(physicalId, logicalId, stackName, getCurrentStackInstanceId())) return;
|
|
35170
|
+
if (!stackName) return void 0;
|
|
35171
|
+
const safeId = displaySafe(physicalId, { asciiOnly: true });
|
|
35172
|
+
const safeStack = displaySafe(stackName, { asciiOnly: true });
|
|
35173
|
+
const safeLogicalId = displaySafe(logicalId, { asciiOnly: true });
|
|
35174
|
+
const idShown = isInertUnquoted(safeId);
|
|
35175
|
+
const shownId = idShown ? safeId : "a name that cannot be shown safely here";
|
|
35176
|
+
const shownLogicalId = isInertUnquoted(safeLogicalId) ? safeLogicalId : "A resource whose logical id cannot be shown safely here";
|
|
35177
|
+
const diagnosis = replayed ? `${shownLogicalId}: the name AWS reports as taken (${shownId}) is most likely held by a resource THIS create made. An earlier attempt of it ended without a clear verdict (a server error, a dropped connection or a timeout, or a failure after the create call itself may have succeeded), and the retry then found the name taken. A dropped connection can also happen before the request reached AWS, so the holder may be another resource: confirm it is yours before deleting or importing it. cdkd records a resource only once its create succeeds, so this one is in no state file: no rollback or cdkd destroy will remove it, and re-running collides with it again.` : `${shownLogicalId}: the name AWS reports as taken (${shownId}) is one cdkd DERIVED from the logical id, and that derivation has no random component — so this is most likely a resource an earlier cdkd run left behind. A rollback leaves a resource carrying DeletionPolicy: Retain in AWS and drops it from state, as CloudFormation does; what differs is the name. CloudFormation would generate a fresh one for an unnamed resource and redeploy clean, whereas cdkd asks again for the name the orphan still holds — so re-running does not clear this.`;
|
|
35178
|
+
const deleteArm = `If it is not a resource you want to keep, delete ${idShown ? safeId : "it"} in AWS — after confirming it holds nothing you need${replayed ? "" : ", since Retain is what kept it"} — and re-deploy.`;
|
|
35179
|
+
let canImport;
|
|
35180
|
+
try {
|
|
35181
|
+
canImport = typeof providerRegistry.getProvider(error.resourceType).import === "function";
|
|
35182
|
+
} catch {
|
|
35183
|
+
canImport = false;
|
|
35184
|
+
}
|
|
35185
|
+
const commandNamesTheRightResource = safeId === physicalId && safeStack === stackName && safeLogicalId === logicalId;
|
|
35186
|
+
const importableTarget = !stackName.includes("~");
|
|
35187
|
+
if (!canImport || !commandNamesTheRightResource || !importableTarget) return `${diagnosis} ${!canImport ? `cdkd cannot adopt ${displaySafe(error.resourceType, { asciiOnly: true })} back into state (its provider implements no import)` : !importableTarget ? `this is a nested-stack child, whose stack name cdkd import cannot resolve` : `cdkd cannot render an import command that provably names this resource`}, so the way forward is to delete it. ${deleteArm}`;
|
|
35188
|
+
const adopt = pasteableCommand("cdkd import", [{
|
|
35189
|
+
value: stackName,
|
|
35190
|
+
hole: "stack"
|
|
35191
|
+
}, {
|
|
35192
|
+
flag: "--resource",
|
|
35193
|
+
value: `${logicalId}=${physicalId}`,
|
|
35194
|
+
hole: "logicalId=physicalId"
|
|
35195
|
+
}]);
|
|
35196
|
+
return `${diagnosis} To recover, adopt it back into state instead of re-creating it, with the command below (a selective import merges into existing state and needs no --force while the resource is absent from it). CONFIRM IT IS YOURS FIRST — a name cdkd derives is predictable, so for a globally-namespaced type it can belong to another account, and the same stack deployed in another region derives the same name. ${deleteArm}${adopt.withheld.length === 0 ? "" : " The command below prints a quoted hole in place of a value cdkd will not name on a command line; replace it whole, quotes included, with your stack name or '<logicalId>=<name>', shell-quoted."}\nAdopt with: ${adopt.command}`;
|
|
35197
|
+
}
|
|
35198
|
+
function isReplacementNameRefusal(error, logicalId) {
|
|
35199
|
+
let current = error;
|
|
35200
|
+
for (let depth = 0; depth < 10 && current != null; depth++) {
|
|
35201
|
+
if (typeof current !== "object") return false;
|
|
35202
|
+
const linkId = current.logicalId;
|
|
35203
|
+
if (typeof linkId === "string" && linkId !== logicalId) return false;
|
|
35204
|
+
if (current instanceof CdkdError && current.code === "NAMED_REPLACEMENT_COLLISION") return true;
|
|
35205
|
+
current = current.cause;
|
|
35206
|
+
}
|
|
35207
|
+
return false;
|
|
35208
|
+
}
|
|
35209
|
+
|
|
34397
35210
|
//#endregion
|
|
34398
35211
|
//#region src/deployment/deploy-engine/replacement.ts
|
|
34399
35212
|
var ReplacementRunState = class {
|
|
34400
35213
|
replacedDeleteSkips = /* @__PURE__ */ new Map();
|
|
34401
35214
|
deferredReplacedDeletes = void 0;
|
|
35215
|
+
supersededHost = void 0;
|
|
35216
|
+
supersededEntries = /* @__PURE__ */ new Map();
|
|
34402
35217
|
retainedOldOnReplacement = /* @__PURE__ */ new Set();
|
|
34403
35218
|
replacedOldMaySurvive = /* @__PURE__ */ new Map();
|
|
34404
35219
|
recreatedUnderSameId = /* @__PURE__ */ new Set();
|
|
@@ -34407,6 +35222,7 @@ var ReplacementRunState = class {
|
|
|
34407
35222
|
updateWasReplaced = /* @__PURE__ */ new Map();
|
|
34408
35223
|
inPlaceCreateOnlyPaths = /* @__PURE__ */ new Map();
|
|
34409
35224
|
oldDeletedBeforeCreate = /* @__PURE__ */ new Set();
|
|
35225
|
+
attemptedNameGeneration = /* @__PURE__ */ new Map();
|
|
34410
35226
|
};
|
|
34411
35227
|
function replacementDeleteContext(deps, updateReplacePolicy) {
|
|
34412
35228
|
return {
|
|
@@ -34452,15 +35268,19 @@ async function replaceDeleteFirstAndRecreate(run, deps, logicalId, resourceType,
|
|
|
34452
35268
|
if (replaceSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, replaceSkipReason, "during the --replace delete-first fallback"));
|
|
34453
35269
|
deps.logger.info(safeMsg` ${green("✓")} Old resource deleted`);
|
|
34454
35270
|
run.oldDeletedBeforeCreate.add(logicalId);
|
|
35271
|
+
await oldDeleteProvider.waitForNameReleased?.(logicalId, currentResource.physicalId, oldResourceType, {
|
|
35272
|
+
isInterrupted: () => deps.userInterrupted(),
|
|
35273
|
+
maskSecrets: (text) => maskSecretsInText(text, secrets)
|
|
35274
|
+
});
|
|
34455
35275
|
deps.logger.info(safeMsg` Re-creating ${logicalId}...`);
|
|
34456
35276
|
try {
|
|
34457
|
-
return await withRetry(() => deps.withRetry(() => withCurrentResourceSecrets(secrets, () => replaceProvider.create(logicalId, resourceType, replaceProps, createContext)), logicalId, void 0, void 0, replaceProvider), logicalId, {
|
|
35277
|
+
return await withRetry(() => deps.withRetry(() => withCurrentResourceSecrets(secrets, () => replaceProvider.create(logicalId, resourceType, replaceProps, createContext)), logicalId, void 0, void 0, replaceProvider, true), logicalId, {
|
|
34458
35278
|
maxRetries: 8,
|
|
34459
35279
|
initialDelayMs: 2e3,
|
|
34460
35280
|
maxDelayMs: 1e4,
|
|
34461
35281
|
logger: deps.maskingRetryLoggerFor(secrets),
|
|
34462
|
-
isInterrupted: () => deps.
|
|
34463
|
-
onInterrupted: () => new InterruptedError(
|
|
35282
|
+
isInterrupted: () => deps.userInterrupted(),
|
|
35283
|
+
onInterrupted: () => new InterruptedError("user"),
|
|
34464
35284
|
isRetryable: isRecreateRetryableError
|
|
34465
35285
|
});
|
|
34466
35286
|
} catch (recreateError) {
|
|
@@ -34494,6 +35314,14 @@ async function checkedReplacementNameChange(deps, input) {
|
|
|
34494
35314
|
};
|
|
34495
35315
|
const adopts = replacementCreateAdoptsName(resourceType, input.createdVia);
|
|
34496
35316
|
const typeChanged = input.oldResourceType !== resourceType;
|
|
35317
|
+
const generatedMove = replacementGeneratedNameMoves({
|
|
35318
|
+
oldResourceType: input.oldResourceType,
|
|
35319
|
+
newResourceType: resourceType,
|
|
35320
|
+
createdVia: input.createdVia,
|
|
35321
|
+
desiredProperties: input.desiredProperties,
|
|
35322
|
+
physicalId: currentResource.physicalId,
|
|
35323
|
+
logicalId
|
|
35324
|
+
});
|
|
34497
35325
|
const change = replacementRequestsDifferentName(question) ?? (adopts || replacementOrderIsCaseSensitive(resourceType) ? replacementRequestsDifferentName({
|
|
34498
35326
|
...question,
|
|
34499
35327
|
caseSensitive: true
|
|
@@ -34504,8 +35332,9 @@ async function checkedReplacementNameChange(deps, input) {
|
|
|
34504
35332
|
desiredProperties: input.desiredProperties,
|
|
34505
35333
|
physicalId: currentResource.physicalId,
|
|
34506
35334
|
logicalId
|
|
34507
|
-
}) ?? (adopts && typeChanged ? typeChangeNameQuestion(resourceType, input) : void 0);
|
|
35335
|
+
}) ?? (adopts && typeChanged ? typeChangeNameQuestion(resourceType, input) : void 0) ?? generatedMove;
|
|
34508
35336
|
if (change === void 0) return void 0;
|
|
35337
|
+
if (change === generatedMove && deps.generatedNameGuarded(logicalId)) return change;
|
|
34509
35338
|
const probe = replacementNameProbe({
|
|
34510
35339
|
resourceType,
|
|
34511
35340
|
createdVia: input.createdVia,
|
|
@@ -34535,7 +35364,8 @@ async function checkedReplacementNameChange(deps, input) {
|
|
|
34535
35364
|
}
|
|
34536
35365
|
if (found === null) return change;
|
|
34537
35366
|
if (!typeChanged && probeFoundSameId(resourceType, found.physicalId, currentResource.physicalId)) return;
|
|
34538
|
-
|
|
35367
|
+
const remedy = (await deps.rollbackRetainedCopies?.(input.stackName).catch(() => []) ?? []).some((copy) => copy.logicalId === logicalId && copy.resourceType === resourceType && probeFoundSameId(resourceType, copy.physicalId, found.physicalId)) ? `This stack's event history records that a rolled-back deploy kept ${displaySafe(logicalId)}'s replacement under this name because of UpdateReplacePolicy: Retain, as CloudFormation also does, untracked by cdkd. If the holder is that copy and you no longer need it, delete it; otherwise choose another name.` : `Choose a name no other resource holds, or delete the resource holding it if it is yours.`;
|
|
35368
|
+
throw markNonRetryable(new CdkdError(maskName(`${subject} requires replacement, and another existing resource (${displaySafe(found.physicalId)}) already holds the name it asks for. ${renderReplacementNameChange(change, input.createProps)}. Since ${adoptsText}, creating the replacement would take that resource over and record it as this stack's. Nothing was created or deleted. ${remedy}`), "NAMED_REPLACEMENT_COLLISION"));
|
|
34539
35369
|
}
|
|
34540
35370
|
async function createFirstThenDeleteOld(run, deps, input) {
|
|
34541
35371
|
const { logicalId, resourceType, currentResource, secrets } = input;
|
|
@@ -34545,11 +35375,23 @@ async function createFirstThenDeleteOld(run, deps, input) {
|
|
|
34545
35375
|
const maskName = maskRewrittenSentName(resourceType, input.createProps, logicalId, (text) => maskSecretsInText(text, secrets));
|
|
34546
35376
|
let createResult;
|
|
34547
35377
|
try {
|
|
34548
|
-
createResult = await deps.
|
|
35378
|
+
createResult = await deps.guardedReplacementCreate({
|
|
35379
|
+
logicalId,
|
|
35380
|
+
resourceType,
|
|
35381
|
+
stackName: input.stackName,
|
|
35382
|
+
createdVia: input.createdVia,
|
|
35383
|
+
resolvedProps: input.resolvedProps
|
|
35384
|
+
}, () => deps.withRetry(() => withCurrentResourceSecrets(secrets, () => input.createProvider.create(logicalId, resourceType, input.createProps, { maskSecrets: createSecretMasker(secrets) })), logicalId, void 0, void 0, input.createProvider));
|
|
34549
35385
|
} catch (createError) {
|
|
34550
35386
|
if (!isNameCollisionErrorFrom(createError, logicalId)) throw createError;
|
|
34551
35387
|
const createMsg = displayAwsMessage(maskName(describeAwsFailure(createError).detail));
|
|
34552
|
-
throw markNonRetryable(new CdkdError(maskName(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement (${input.trigger}), and cdkd created the new resource first because its name differs, but the create collided: ${createMsg}. If the collision is on the requested name: ${renderReplacementNameChange(input.change, input.createProps)}. Nothing was deleted` + (retainOld ? ` (UpdateReplacePolicy: Retain keeps the old resource in place)` : "") + ". Choose a name no other resource holds, or delete the resource holding it if it is yours."
|
|
35388
|
+
throw markNonRetryable(new CdkdError(maskName(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement (${input.trigger}), and cdkd created the new resource first because its name differs, but the create collided: ${createMsg}. If the collision is on the requested name: ${renderReplacementNameChange(input.change, input.createProps)}. Nothing was deleted` + (retainOld ? ` (UpdateReplacePolicy: Retain keeps the old resource in place)` : "") + ". Choose a name no other resource holds, or delete the resource holding it if it is yours." + generatedReplacementHolderAdvice({
|
|
35389
|
+
stackName: input.stackName,
|
|
35390
|
+
logicalId,
|
|
35391
|
+
change: input.change,
|
|
35392
|
+
oldPhysicalId: currentResource.physicalId,
|
|
35393
|
+
mask: (text) => maskName(maskSecretsInText(text, unionOfSecretBags([secrets, printingSecretsFor(deps.secretsRun(), logicalId)])))
|
|
35394
|
+
})), "NAMED_REPLACEMENT_COLLISION", createError instanceof Error ? createError : void 0));
|
|
34553
35395
|
}
|
|
34554
35396
|
if (input.equalIdIsSameResource && createResult.physicalId === currentResource.physicalId) throw markNonRetryable(new CdkdError(maskName(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement (${input.trigger}) under a new name, but the create returned the resource being replaced (${displaySafe(currentResource.physicalId)}) instead of a new one, so cdkd cannot tell which name it holds. Nothing was deleted. Delete that resource by hand if it is yours, then re-run the deploy.`), "NAMED_REPLACEMENT_IDEMPOTENT_CREATE"));
|
|
34555
35397
|
if (retainOld) return createResult;
|
|
@@ -34562,7 +35404,7 @@ async function deleteReplacedAfterCreate(run, deps, logicalId, oldResourceType,
|
|
|
34562
35404
|
let deleteFailed = false;
|
|
34563
35405
|
const inlinePolicyClaimed = isStandaloneInlinePolicyType(oldResourceType) ? deps.inlinePolicyClaimedFor(oldResourceType, logicalId, deps.deployStateResources()) : void 0;
|
|
34564
35406
|
try {
|
|
34565
|
-
|
|
35407
|
+
const sendDelete = () => deleteProvider.delete(logicalId, currentResource.physicalId, oldResourceType, deleteProperties, {
|
|
34566
35408
|
expectedRegion: deps.stackRegion,
|
|
34567
35409
|
forceDataDelete: deps.options.forceStatefulRecreation === true,
|
|
34568
35410
|
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier },
|
|
@@ -34572,7 +35414,8 @@ async function deleteReplacedAfterCreate(run, deps, logicalId, oldResourceType,
|
|
|
34572
35414
|
...noEchoDeleteValues !== void 0 && { noEchoDeleteValues },
|
|
34573
35415
|
...inlinePolicyClaimed && { inlinePolicyClaimed },
|
|
34574
35416
|
maskSecrets: createUnionSecretMasker([secrets, secretNameBagFor(deps.secretsRun(), logicalId)])
|
|
34575
|
-
})
|
|
35417
|
+
});
|
|
35418
|
+
deleteResult = await withPrintingSecrets(secrets, () => isRetry ? retryWhileInUse(sendDelete, () => deps.interrupted()) : sendDelete());
|
|
34576
35419
|
} catch (deleteError) {
|
|
34577
35420
|
const deleteMsg = maskSecretsInText(describeAwsFailure(deleteError).detail, secrets);
|
|
34578
35421
|
deleteFailed = true;
|
|
@@ -34580,6 +35423,23 @@ async function deleteReplacedAfterCreate(run, deps, logicalId, oldResourceType,
|
|
|
34580
35423
|
const deferred = run.deferredReplacedDeletes;
|
|
34581
35424
|
if (!isRetry && deferred !== void 0) {
|
|
34582
35425
|
deps.logger.info(safeMsg` Could not delete old ${logicalId} (${currentResource.physicalId}) yet: ${deleteMsg}. Retrying after the rest of the deploy.`);
|
|
35426
|
+
const host = run.supersededHost;
|
|
35427
|
+
if (host !== void 0 && canRecordSuperseded(currentResource, {
|
|
35428
|
+
noEchoDeleteValues,
|
|
35429
|
+
inlinePolicyClaimed
|
|
35430
|
+
}) && !Object.entries(deps.deployStateResources()).some(([id, record]) => id !== logicalId && record?.physicalId === currentResource.physicalId)) {
|
|
35431
|
+
const entry = {
|
|
35432
|
+
logicalId,
|
|
35433
|
+
supersededAt: Date.now(),
|
|
35434
|
+
state: currentResource,
|
|
35435
|
+
...updateReplacePolicy !== void 0 && { updateReplacePolicy },
|
|
35436
|
+
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier },
|
|
35437
|
+
...deps.options.forceStatefulRecreation === true && { forceDataDelete: true },
|
|
35438
|
+
...deps.options.skipFinalSnapshot === true && { skipFinalSnapshot: true }
|
|
35439
|
+
};
|
|
35440
|
+
addSuperseded(host, entry);
|
|
35441
|
+
run.supersededEntries.set(logicalId, entry);
|
|
35442
|
+
}
|
|
34583
35443
|
deferred.set(logicalId, {
|
|
34584
35444
|
physicalId: currentResource.physicalId,
|
|
34585
35445
|
resourceType: oldResourceType,
|
|
@@ -34589,7 +35449,13 @@ async function deleteReplacedAfterCreate(run, deps, logicalId, oldResourceType,
|
|
|
34589
35449
|
});
|
|
34590
35450
|
return;
|
|
34591
35451
|
}
|
|
34592
|
-
|
|
35452
|
+
const kept = isRetry && run.supersededEntries.has(logicalId);
|
|
35453
|
+
deps.logger.warn(kept ? safeMsg` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteMsg}. ${SUPERSEDED_KEPT_REMEDY}.` : safeMsg` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteMsg}`);
|
|
35454
|
+
}
|
|
35455
|
+
const recorded = isRetry ? run.supersededEntries.get(logicalId) : void 0;
|
|
35456
|
+
if (recorded !== void 0 && !deleteFailed && run.supersededHost !== void 0) {
|
|
35457
|
+
removeSuperseded(run.supersededHost, recorded);
|
|
35458
|
+
run.supersededEntries.delete(logicalId);
|
|
34593
35459
|
}
|
|
34594
35460
|
reportDeleteGuards(deleteResult, {
|
|
34595
35461
|
physicalId: currentResource.physicalId,
|
|
@@ -34662,8 +35528,9 @@ async function retryDeferredReplacedDeletes(run, deps, stackName, counts) {
|
|
|
34662
35528
|
function warnUnretriedReplacedDeletes(run, deps, why) {
|
|
34663
35529
|
const deferred = run.deferredReplacedDeletes;
|
|
34664
35530
|
run.deferredReplacedDeletes = void 0;
|
|
34665
|
-
const
|
|
34666
|
-
|
|
35531
|
+
const cause = why === "failed" ? "the deploy failed first" : "the deploy was interrupted";
|
|
35532
|
+
const noteFor = (logicalId) => run.supersededEntries.has(logicalId) ? `not retried: ${cause}; cdkd keeps it in state, and the next deploy retries the delete` : `not retried: ${cause}; it is no longer tracked in state, so delete it manually`;
|
|
35533
|
+
for (const [logicalId, entry] of deferred ?? []) withPrintingSecrets(secretNameBagFor(deps.secretsRun(), logicalId), () => deps.logger.warn(safeMsg` ⚠ Failed to delete old resource ${logicalId} (${entry.physicalId}): ${entry.failureMessage} (${noteFor(logicalId)})`));
|
|
34667
35534
|
}
|
|
34668
35535
|
|
|
34669
35536
|
//#endregion
|
|
@@ -35556,6 +36423,136 @@ function recaptureMaskedBaseline(args) {
|
|
|
35556
36423
|
return changed ? result : void 0;
|
|
35557
36424
|
}
|
|
35558
36425
|
|
|
36426
|
+
//#endregion
|
|
36427
|
+
//#region src/state/name-generation.ts
|
|
36428
|
+
var MalformedNameGenerationError = class extends Error {
|
|
36429
|
+
constructor(where, reason = "malformed") {
|
|
36430
|
+
super(`The state record holds a name generation for ${displayIdent(where)} that is ` + (reason === "exhausted" ? "too large to derive the next one from (the next is not a safe integer). " : "not a non-negative integer. ") + "cdkd does not guess which name the resource was given, since the next replacement's name derives from it; restore the field from an earlier version of state.json.");
|
|
36431
|
+
this.name = "MalformedNameGenerationError";
|
|
36432
|
+
}
|
|
36433
|
+
};
|
|
36434
|
+
function generationAfter(generation, logicalId) {
|
|
36435
|
+
const next = generation + 1;
|
|
36436
|
+
if (!isNameGeneration(next)) throw new MalformedNameGenerationError(logicalId, "exhausted");
|
|
36437
|
+
return next;
|
|
36438
|
+
}
|
|
36439
|
+
function nameGenerationOf(record, logicalId) {
|
|
36440
|
+
const value = record.nameGeneration;
|
|
36441
|
+
if (value === void 0) return 0;
|
|
36442
|
+
if (!isNameGeneration(value)) throw new MalformedNameGenerationError(logicalId);
|
|
36443
|
+
return value;
|
|
36444
|
+
}
|
|
36445
|
+
function nameGenerationHighWaterOf(record, logicalId) {
|
|
36446
|
+
const generation = nameGenerationOf(record, logicalId);
|
|
36447
|
+
const high = record.nameGenerationHigh;
|
|
36448
|
+
if (high === void 0) return generation;
|
|
36449
|
+
if (!isNameGeneration(high)) throw new MalformedNameGenerationError(logicalId);
|
|
36450
|
+
return Math.max(generation, high);
|
|
36451
|
+
}
|
|
36452
|
+
function retiredNameGenerationsOf(state) {
|
|
36453
|
+
const raw = state.retiredNameGenerations;
|
|
36454
|
+
const out = /* @__PURE__ */ new Map();
|
|
36455
|
+
if (raw === void 0) return out;
|
|
36456
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new MalformedNameGenerationError("retiredNameGenerations");
|
|
36457
|
+
for (const [logicalId, value] of Object.entries(raw)) {
|
|
36458
|
+
if (!isNameGeneration(value)) throw new MalformedNameGenerationError(logicalId);
|
|
36459
|
+
out.set(logicalId, value);
|
|
36460
|
+
}
|
|
36461
|
+
return out;
|
|
36462
|
+
}
|
|
36463
|
+
function nameGenerationsOf(state) {
|
|
36464
|
+
const out = /* @__PURE__ */ new Map();
|
|
36465
|
+
for (const [logicalId, retired] of retiredNameGenerationsOf(state)) out.set(logicalId, generationAfter(retired, logicalId));
|
|
36466
|
+
for (const [logicalId, record] of Object.entries(state.resources ?? {})) {
|
|
36467
|
+
if (record === null || typeof record !== "object") continue;
|
|
36468
|
+
out.set(logicalId, nameGenerationOf(record, logicalId));
|
|
36469
|
+
}
|
|
36470
|
+
return out;
|
|
36471
|
+
}
|
|
36472
|
+
function nextNameGeneration(record, logicalId, stackInstanceId) {
|
|
36473
|
+
let next = generationAfter(nameGenerationHighWaterOf(record, logicalId), logicalId);
|
|
36474
|
+
const physicalId = typeof record.physicalId === "string" ? record.physicalId.toLowerCase() : "";
|
|
36475
|
+
while (physicalId.includes(stackInstanceNameSuffix(stackInstanceId, logicalId, next))) next = generationAfter(next, logicalId);
|
|
36476
|
+
return next;
|
|
36477
|
+
}
|
|
36478
|
+
function replacementNameGeneration(record, logicalId, stackInstanceId, keepsName) {
|
|
36479
|
+
if (stackInstanceId === void 0 || keepsName) return {
|
|
36480
|
+
generation: void 0,
|
|
36481
|
+
fields: nameGenerationCarriedFrom(record)
|
|
36482
|
+
};
|
|
36483
|
+
const generation = nextNameGeneration(record, logicalId, stackInstanceId);
|
|
36484
|
+
return {
|
|
36485
|
+
generation,
|
|
36486
|
+
fields: nameGenerationField(generation)
|
|
36487
|
+
};
|
|
36488
|
+
}
|
|
36489
|
+
function nameGenerationField(generation) {
|
|
36490
|
+
return generation === 0 ? {} : { nameGeneration: generation };
|
|
36491
|
+
}
|
|
36492
|
+
function nameGenerationCarriedFrom(previous) {
|
|
36493
|
+
return {
|
|
36494
|
+
...previous?.nameGeneration !== void 0 && { nameGeneration: previous.nameGeneration },
|
|
36495
|
+
...previous?.nameGenerationHigh !== void 0 && { nameGenerationHigh: previous.nameGenerationHigh }
|
|
36496
|
+
};
|
|
36497
|
+
}
|
|
36498
|
+
function withNameGenerationReached(record, logicalId, reached) {
|
|
36499
|
+
if (reached === void 0 || !isNameGeneration(reached)) return record;
|
|
36500
|
+
if (reached <= nameGenerationHighWaterOf(record, logicalId)) return record;
|
|
36501
|
+
return {
|
|
36502
|
+
...record,
|
|
36503
|
+
nameGenerationHigh: reached
|
|
36504
|
+
};
|
|
36505
|
+
}
|
|
36506
|
+
function retiredNameGenerationsAfter(state, leaving) {
|
|
36507
|
+
if (state.stackInstanceId === void 0) return {};
|
|
36508
|
+
const retired = new Map(retiredNameGenerationsOf(state));
|
|
36509
|
+
let changed = false;
|
|
36510
|
+
for (const { logicalId, record } of leaving) {
|
|
36511
|
+
const reached = nameGenerationHighWaterOf(record, logicalId);
|
|
36512
|
+
const before = retired.get(logicalId);
|
|
36513
|
+
if (before !== void 0 && before >= reached) continue;
|
|
36514
|
+
retired.set(logicalId, reached);
|
|
36515
|
+
changed = true;
|
|
36516
|
+
}
|
|
36517
|
+
if (!changed) return state.retiredNameGenerations === void 0 ? {} : { retiredNameGenerations: state.retiredNameGenerations };
|
|
36518
|
+
return { retiredNameGenerations: Object.fromEntries(retired) };
|
|
36519
|
+
}
|
|
36520
|
+
function nameScopeOf(stackName, stackInstanceId, state) {
|
|
36521
|
+
return {
|
|
36522
|
+
stackName,
|
|
36523
|
+
stackInstanceId,
|
|
36524
|
+
nameGenerations: stackInstanceId === void 0 ? void 0 : nameGenerationsOf(state ?? { resources: {} })
|
|
36525
|
+
};
|
|
36526
|
+
}
|
|
36527
|
+
function rolledBackCreateReached(create) {
|
|
36528
|
+
let reached = 0;
|
|
36529
|
+
for (const value of [
|
|
36530
|
+
create.record?.nameGeneration,
|
|
36531
|
+
create.record?.nameGenerationHigh,
|
|
36532
|
+
create.nameGeneration
|
|
36533
|
+
]) if (isNameGeneration(value)) reached = Math.max(reached, value);
|
|
36534
|
+
return reached;
|
|
36535
|
+
}
|
|
36536
|
+
function retiredAfterRollback(state, orphaned, rolledBackCreates = []) {
|
|
36537
|
+
return retiredNameGenerationsAfter(state, [...orphaned.map((o) => ({
|
|
36538
|
+
logicalId: o.logicalId,
|
|
36539
|
+
record: o.state
|
|
36540
|
+
})), ...rolledBackCreates.map((c) => ({
|
|
36541
|
+
logicalId: c.logicalId,
|
|
36542
|
+
record: { nameGenerationHigh: rolledBackCreateReached(c) }
|
|
36543
|
+
}))]);
|
|
36544
|
+
}
|
|
36545
|
+
function retiredNameGenerationsLeaving(state, remaining) {
|
|
36546
|
+
try {
|
|
36547
|
+
return retiredNameGenerationsAfter(state, Object.entries(state.resources ?? {}).filter(([logicalId, record]) => !Object.hasOwn(remaining, logicalId) && record !== null && typeof record === "object").map(([logicalId, record]) => ({
|
|
36548
|
+
logicalId,
|
|
36549
|
+
record
|
|
36550
|
+
})));
|
|
36551
|
+
} catch {
|
|
36552
|
+
return state.retiredNameGenerations === void 0 ? {} : { retiredNameGenerations: state.retiredNameGenerations };
|
|
36553
|
+
}
|
|
36554
|
+
}
|
|
36555
|
+
|
|
35559
36556
|
//#endregion
|
|
35560
36557
|
//#region src/deployment/update-outcome.ts
|
|
35561
36558
|
function updatePartialReason(result) {
|
|
@@ -35816,6 +36813,7 @@ function isPlainRecord$1(value) {
|
|
|
35816
36813
|
//#endregion
|
|
35817
36814
|
//#region src/deployment/type-change-guard.ts
|
|
35818
36815
|
function equalIdNamesDifferentResources(input) {
|
|
36816
|
+
if (input.resourceType === "AWS::Lambda::Permission") return permissionsOnDifferentFunctions(input.oldProperties, input.newProperties);
|
|
35819
36817
|
if (input.resourceType !== "AWS::Glue::Table" || input.physicalId === void 0) return false;
|
|
35820
36818
|
const oldDb = input.oldProperties?.["DatabaseName"];
|
|
35821
36819
|
const newDb = input.newProperties?.["DatabaseName"];
|
|
@@ -35824,6 +36822,15 @@ function equalIdNamesDifferentResources(input) {
|
|
|
35824
36822
|
if (segmentAfterAnchor(input.physicalId, oldDb) === void 0 || segmentAfterAnchor(input.physicalId, newDb) === void 0) return false;
|
|
35825
36823
|
return oldDb !== newDb;
|
|
35826
36824
|
}
|
|
36825
|
+
function permissionsOnDifferentFunctions(oldProperties, newProperties) {
|
|
36826
|
+
const oldFn = oldProperties?.["FunctionName"];
|
|
36827
|
+
const newFn = newProperties?.["FunctionName"];
|
|
36828
|
+
if (typeof oldFn !== "string" || typeof newFn !== "string") return false;
|
|
36829
|
+
if (carriesSecretMask(oldFn) || carriesSecretMask(newFn)) return false;
|
|
36830
|
+
const oldName = parseLambdaFunctionAddress(oldFn)?.name;
|
|
36831
|
+
const newName = parseLambdaFunctionAddress(newFn)?.name;
|
|
36832
|
+
return oldName !== void 0 && newName !== void 0 && oldName !== newName;
|
|
36833
|
+
}
|
|
35827
36834
|
function equalIdNamesSameResource(input) {
|
|
35828
36835
|
if (input.oldType === input.newType) return !equalIdNamesDifferentResources({
|
|
35829
36836
|
resourceType: input.oldType,
|
|
@@ -36243,6 +37250,30 @@ function planRollback(operations, stateResources, orphanLogicalIds = /* @__PURE_
|
|
|
36243
37250
|
};
|
|
36244
37251
|
});
|
|
36245
37252
|
}
|
|
37253
|
+
function renamedReverseReplacement(op, stateResources, orphanLogicalIds, pendingNewIds = /* @__PURE__ */ new Set()) {
|
|
37254
|
+
if (op.changeType !== "UPDATE") return false;
|
|
37255
|
+
if (op.oldDeletedBeforeCreate === true || op.oldResourceMaySurvive !== void 0) return false;
|
|
37256
|
+
const current = Object.hasOwn(stateResources, op.logicalId) ? stateResources[op.logicalId] : void 0;
|
|
37257
|
+
const oldId = op.previousState?.physicalId;
|
|
37258
|
+
if (typeof oldId !== "string" || typeof current?.physicalId !== "string") return false;
|
|
37259
|
+
if (current.physicalId === oldId) return false;
|
|
37260
|
+
if (pendingNewIds.has(oldId)) return false;
|
|
37261
|
+
const oldType = op.previousState?.resourceType ?? op.resourceType;
|
|
37262
|
+
for (const [logicalId, other] of Object.entries(stateResources)) {
|
|
37263
|
+
if (logicalId === op.logicalId || typeof other?.physicalId !== "string") continue;
|
|
37264
|
+
if (other.physicalId === oldId || other.resourceType === oldType && samePhysicalId(oldType, other.physicalId, oldId)) return false;
|
|
37265
|
+
}
|
|
37266
|
+
return classifyRollbackOp(op, stateResources, orphanLogicalIds) === "reverse-replacement";
|
|
37267
|
+
}
|
|
37268
|
+
function revertReferences(op, stateResources) {
|
|
37269
|
+
const current = Object.hasOwn(stateResources, op.logicalId) ? stateResources[op.logicalId] : void 0;
|
|
37270
|
+
const refs = /* @__PURE__ */ new Set();
|
|
37271
|
+
for (const record of [op.previousState, current]) {
|
|
37272
|
+
if (!Array.isArray(record?.dependencies)) continue;
|
|
37273
|
+
for (const id of record.dependencies) if (typeof id === "string") refs.add(id);
|
|
37274
|
+
}
|
|
37275
|
+
return refs;
|
|
37276
|
+
}
|
|
36246
37277
|
function partitionOps(operations) {
|
|
36247
37278
|
const createOps = [];
|
|
36248
37279
|
const otherOps = [];
|
|
@@ -36706,6 +37737,7 @@ async function replayOrphanFlag(s) {
|
|
|
36706
37737
|
const orphanFlagProvisionedBy = effectiveProvisionedBy(record, op.provisionedBy);
|
|
36707
37738
|
s.createRollbackRoute = orphanFlagProvisionedBy;
|
|
36708
37739
|
delete stateResources[op.logicalId];
|
|
37740
|
+
if (record) noteRolledBackCreate(s, op, record);
|
|
36709
37741
|
await noteRetainedResource(op.resourceType, op.logicalId);
|
|
36710
37742
|
logger.info(` Rollback: Orphaning created resource ${safe(op.logicalId)} (--orphan)`);
|
|
36711
37743
|
await afterOp?.(op.logicalId);
|
|
@@ -36738,6 +37770,7 @@ async function replayOrphanRetain(s) {
|
|
|
36738
37770
|
onOrphan?.(orphaned);
|
|
36739
37771
|
}
|
|
36740
37772
|
delete stateResources[op.logicalId];
|
|
37773
|
+
noteRolledBackCreate(s, op, record);
|
|
36741
37774
|
await noteRetainedResource(op.resourceType, op.logicalId);
|
|
36742
37775
|
logger.info(` Rollback: Leaving ${safe(op.logicalId)} (${safe(op.resourceType)}) in AWS (DeletionPolicy: Retain) — removed from state`);
|
|
36743
37776
|
await afterOp?.(op.logicalId);
|
|
@@ -36799,7 +37832,9 @@ async function replayDelete(s) {
|
|
|
36799
37832
|
provisionedBy: deleteRoutedVia,
|
|
36800
37833
|
mask
|
|
36801
37834
|
});
|
|
37835
|
+
const deletedRecord = stateResources[op.logicalId];
|
|
36802
37836
|
delete stateResources[op.logicalId];
|
|
37837
|
+
noteRolledBackCreate(s, op, deletedRecord);
|
|
36803
37838
|
logger.info(` Rollback: ${safe(op.logicalId)} deleted successfully`);
|
|
36804
37839
|
await afterOp?.(op.logicalId);
|
|
36805
37840
|
ctx.recordEvent?.({
|
|
@@ -36864,7 +37899,7 @@ async function replayReadopt(s, survivor) {
|
|
|
36864
37899
|
mask
|
|
36865
37900
|
});
|
|
36866
37901
|
}
|
|
36867
|
-
stateResources[op.logicalId] = prev;
|
|
37902
|
+
stateResources[op.logicalId] = withNameGenerationReached(prev, op.logicalId, op.nameGeneration);
|
|
36868
37903
|
logger.info(` Rollback: ${safe(op.logicalId)} restored to the ${oldKind} old resource`);
|
|
36869
37904
|
await afterOp?.(op.logicalId);
|
|
36870
37905
|
const survivorProvisionedBy = current.provisionedBy;
|
|
@@ -36947,7 +37982,8 @@ async function replayRevert(s) {
|
|
|
36947
37982
|
properties: desiredProps,
|
|
36948
37983
|
logicalId: op.logicalId,
|
|
36949
37984
|
physicalId: current.physicalId,
|
|
36950
|
-
via: revertVia
|
|
37985
|
+
via: revertVia,
|
|
37986
|
+
nameGeneration: nameGenerationOf(current, op.logicalId)
|
|
36951
37987
|
}, logger, mask, false)(() => updateWithRollbackRetry(provider, [
|
|
36952
37988
|
op.logicalId,
|
|
36953
37989
|
current.physicalId,
|
|
@@ -37059,7 +38095,8 @@ async function replayReverseReplacement(s) {
|
|
|
37059
38095
|
properties: resolvedPrevProps,
|
|
37060
38096
|
logicalId: op.logicalId,
|
|
37061
38097
|
physicalId: prev.physicalId,
|
|
37062
|
-
via: createProvisionedBy
|
|
38098
|
+
via: createProvisionedBy,
|
|
38099
|
+
nameGeneration: nameGenerationOf(prev, op.logicalId)
|
|
37063
38100
|
}, logger, mask, true);
|
|
37064
38101
|
const resolveNewDeleteRoute = () => ctx.providerRegistry.getProviderFor({
|
|
37065
38102
|
resourceType: op.resourceType,
|
|
@@ -37101,6 +38138,10 @@ async function replayReverseReplacement(s) {
|
|
|
37101
38138
|
throwIfDeleteSkipped(deleteNewFirst, op.logicalId, current.physicalId, purpose, newDeleteGuardScope(deleteNewFirstRoute.provisionedBy));
|
|
37102
38139
|
delete stateResources[op.logicalId];
|
|
37103
38140
|
await afterOp?.(op.logicalId);
|
|
38141
|
+
await deleteNewFirstRoute.provider.waitForNameReleased?.(op.logicalId, current.physicalId, current.resourceType, {
|
|
38142
|
+
isInterrupted: () => isInterrupted?.() === true,
|
|
38143
|
+
maskSecrets: mask
|
|
38144
|
+
});
|
|
37104
38145
|
};
|
|
37105
38146
|
const recreateAfterNewDeleted = async () => {
|
|
37106
38147
|
try {
|
|
@@ -37133,7 +38174,7 @@ async function replayReverseReplacement(s) {
|
|
|
37133
38174
|
oldResourceType: oldType,
|
|
37134
38175
|
newResourceType: op.resourceType,
|
|
37135
38176
|
requested: replayCreateProps(),
|
|
37136
|
-
generated: typeof op.logicalId === "string" ? applyDefaultNameForFallback(op.logicalId, oldType, resolvedPrevProps) : void 0,
|
|
38177
|
+
generated: typeof op.logicalId === "string" ? applyDefaultNameForFallback(op.logicalId, oldType, resolvedPrevProps, "omit") : void 0,
|
|
37137
38178
|
logicalId: op.logicalId,
|
|
37138
38179
|
createdVia: createProvisionedBy,
|
|
37139
38180
|
mask,
|
|
@@ -37192,56 +38233,125 @@ async function replayReverseReplacement(s) {
|
|
|
37192
38233
|
const { observedProperties: _staleObserved, ...prevRecord } = prev;
|
|
37193
38234
|
recordNoEchoAttributeValues(createResult, secrets, resolvedPrevProps);
|
|
37194
38235
|
stateResources[op.logicalId] = redactRollbackRecord({
|
|
37195
|
-
...prevRecord,
|
|
38236
|
+
...withNameGenerationReached(prevRecord, op.logicalId, op.nameGeneration),
|
|
37196
38237
|
physicalId: createResult.physicalId,
|
|
37197
38238
|
attributes: createResult.attributes ?? {},
|
|
37198
38239
|
properties: recordedPropertiesAfterReplayCreate(prevRecord, createResult)
|
|
37199
38240
|
}, secrets, prevRecord.properties, prevRecord.attributes);
|
|
37200
38241
|
if (!adoptedLiveNewResource) inlinePolicyWriters.record(op.logicalId, "create", stateResources[op.logicalId], false, createProvisionedBy);
|
|
38242
|
+
const deferral = s.deferral !== void 0 && !deletedNewFirst && !adoptedLiveNewResource && !rollbackRetainsNewResource(current) ? s.deferral : void 0;
|
|
38243
|
+
const supersededFinalSnapshot = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
|
|
38244
|
+
const supersededPolicy = current.updateReplacePolicy;
|
|
38245
|
+
const superseded = {
|
|
38246
|
+
logicalId: op.logicalId,
|
|
38247
|
+
supersededAt: Date.now(),
|
|
38248
|
+
state: current,
|
|
38249
|
+
...(supersededPolicy === "Delete" || supersededPolicy === "Snapshot" || supersededPolicy === "RetainExceptOnCreate") && { updateReplacePolicy: supersededPolicy },
|
|
38250
|
+
...supersededFinalSnapshot !== void 0 && { finalSnapshotIdentifier: supersededFinalSnapshot }
|
|
38251
|
+
};
|
|
38252
|
+
const recordSuperseded = deferral?.onSuperseded !== void 0 && canRecordSuperseded(current, {});
|
|
38253
|
+
if (recordSuperseded) deferral?.onSuperseded?.(superseded);
|
|
37201
38254
|
await afterOp?.(op.logicalId);
|
|
37202
|
-
|
|
37203
|
-
|
|
37204
|
-
|
|
37205
|
-
|
|
37206
|
-
|
|
37207
|
-
|
|
37208
|
-
|
|
37209
|
-
|
|
37210
|
-
|
|
37211
|
-
|
|
37212
|
-
|
|
37213
|
-
|
|
37214
|
-
|
|
37215
|
-
|
|
37216
|
-
|
|
37217
|
-
|
|
37218
|
-
|
|
37219
|
-
|
|
37220
|
-
|
|
37221
|
-
|
|
37222
|
-
|
|
37223
|
-
|
|
37224
|
-
|
|
37225
|
-
|
|
38255
|
+
const finish = async () => {
|
|
38256
|
+
let survivorReason;
|
|
38257
|
+
const survivorId = retainedSurvivorId(current, op);
|
|
38258
|
+
if (!deletedNewFirst && !adoptedLiveNewResource && rollbackRetainsNewResource(current)) {
|
|
38259
|
+
const survivorMessages = retainedSurvivorMessages(op.logicalId, op.resourceType, survivorId ?? "no recorded id", `State records the re-created old resource (${stateResources[op.logicalId]?.physicalId ?? prev.physicalId}).`, mask);
|
|
38260
|
+
logger.warn(survivorMessages.warn);
|
|
38261
|
+
survivorReason = survivorMessages.reason;
|
|
38262
|
+
result.warnings++;
|
|
38263
|
+
await noteRetainedResource(op.resourceType, op.logicalId);
|
|
38264
|
+
} else if (!deletedNewFirst && !adoptedLiveNewResource) try {
|
|
38265
|
+
const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
|
|
38266
|
+
const deleteNewAfterRecreateRoute = resolveNewDeleteRoute();
|
|
38267
|
+
const deleteNewAfterRecreate = await withReplayDeletePrinting(s, () => deleteNewAfterRecreateRoute.provider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
|
|
38268
|
+
expectedRegion: ctx.region,
|
|
38269
|
+
...newCopyClaimed && { inlinePolicyClaimed: newCopyClaimed },
|
|
38270
|
+
...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier },
|
|
38271
|
+
deletionPolicy: replacementDeletePolicy(current.updateReplacePolicy),
|
|
38272
|
+
recordedAttributes: current.attributes,
|
|
38273
|
+
recordedNoEchoLeaves: current.noEchoLeaves,
|
|
38274
|
+
maskSecrets: mask
|
|
38275
|
+
}));
|
|
38276
|
+
throwIfDeleteSkipped(deleteNewAfterRecreate, op.logicalId, current.physicalId, "while deleting the new resource after re-creating the old one", newDeleteGuardScope(deleteNewAfterRecreateRoute.provisionedBy));
|
|
38277
|
+
} catch (deleteError) {
|
|
38278
|
+
logger.warn(mask(` Rollback: old ${safe(op.logicalId)} re-created, but deleting the new resource (${displaySafe(mask(current.physicalId))}) failed: ${displaySafe(describeAwsFailure(deleteError).detail)}. ` + (recordSuperseded ? `${SUPERSEDED_KEPT_REMEDY}.` : `Delete it manually — it is no longer tracked in state.`)));
|
|
38279
|
+
survivorReason = `The replacement's new ${op.resourceType} (${current.physicalId}) could not be deleted after the old resource was re-created: ${describeAwsFailure(deleteError).detail}. ` + (recordSuperseded ? `It is live and still billing; ${SUPERSEDED_KEPT_REMEDY}.` : `It is live, still billing, and no longer tracked by cdkd — delete it yourself.`);
|
|
38280
|
+
result.warnings++;
|
|
38281
|
+
}
|
|
38282
|
+
const recreatedId = displaySafe(mask(String(createResult.physicalId)));
|
|
38283
|
+
logger.info(mask(adoptedLiveNewResource ? ` Rollback: ${safe(op.logicalId)} adopted the live resource (${recreatedId}) — replacement NOT fully reversed (name-idempotent Create API)` : ` Rollback: ${safe(op.logicalId)} replacement reversed (old resource re-created as ${recreatedId})`));
|
|
38284
|
+
const survivorProvisionedBy = current.provisionedBy;
|
|
38285
|
+
ctx.recordEvent?.({
|
|
38286
|
+
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
38287
|
+
stackName,
|
|
38288
|
+
operation: "UPDATE",
|
|
38289
|
+
logicalId: op.logicalId,
|
|
38290
|
+
resourceType: op.resourceType,
|
|
38291
|
+
...op.provisionedBy && { provisionedBy: op.provisionedBy },
|
|
38292
|
+
...survivorReason !== void 0 && {
|
|
38293
|
+
...survivorId !== void 0 && { physicalId: survivorId },
|
|
38294
|
+
reason: mask(survivorReason),
|
|
38295
|
+
...survivorProvisionedBy && { provisionedBy: survivorProvisionedBy }
|
|
38296
|
+
},
|
|
38297
|
+
...adoptedLiveNewResource && { reason: mask("The re-create returned the live new resource instead of re-creating the old one (its Create API is name-idempotent), so the replacement was NOT fully reversed: the old resource's original properties may not have been re-applied. Inspect it with `cdkd drift` and run `cdkd deploy` to reconcile.") }
|
|
38298
|
+
});
|
|
38299
|
+
return survivorReason === void 0;
|
|
38300
|
+
};
|
|
38301
|
+
const keep = (reason) => {
|
|
38302
|
+
logger.warn(mask(` Rollback: old ${safe(op.logicalId)} re-created, but the new resource (${displaySafe(mask(current.physicalId))}) was not deleted: ${reason}. ${SUPERSEDED_KEPT_REMEDY}.`));
|
|
37226
38303
|
result.warnings++;
|
|
38304
|
+
ctx.recordEvent?.({
|
|
38305
|
+
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
38306
|
+
stackName,
|
|
38307
|
+
operation: "UPDATE",
|
|
38308
|
+
logicalId: op.logicalId,
|
|
38309
|
+
resourceType: op.resourceType,
|
|
38310
|
+
...current.provisionedBy && { provisionedBy: current.provisionedBy },
|
|
38311
|
+
physicalId: current.physicalId,
|
|
38312
|
+
reason: mask(`The old resource was re-created; the new one (${current.physicalId}) was not deleted: ${reason}. ${SUPERSEDED_KEPT_REMEDY}.`)
|
|
38313
|
+
});
|
|
38314
|
+
};
|
|
38315
|
+
if (deferral !== void 0) {
|
|
38316
|
+
logger.info(safeMsg` Rollback: old ${safe(op.logicalId)} re-created first; the new resource ` + safeMsg`(${mask(current.physicalId)}) is deleted once the resources that reference it ` + `are reverted`);
|
|
38317
|
+
deferral.defer(async () => {
|
|
38318
|
+
let gone = false;
|
|
38319
|
+
try {
|
|
38320
|
+
if (supersededHolderOf(superseded, stateResources) !== void 0) {
|
|
38321
|
+
logger.warn(safeMsg` Rollback: not deleting the new ${shownLogicalId(op.logicalId)} ` + safeMsg`(${mask(current.physicalId)}): a record of this stack now holds its ` + `physical id. Check it with cdkd drift.`);
|
|
38322
|
+
result.warnings++;
|
|
38323
|
+
ctx.recordEvent?.({
|
|
38324
|
+
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
38325
|
+
stackName,
|
|
38326
|
+
operation: "UPDATE",
|
|
38327
|
+
logicalId: op.logicalId,
|
|
38328
|
+
resourceType: op.resourceType,
|
|
38329
|
+
...op.provisionedBy && { provisionedBy: op.provisionedBy },
|
|
38330
|
+
reason: mask(`The old resource was re-created; the new one (${current.physicalId}) was not deleted because a record of this stack now holds its physical id.`)
|
|
38331
|
+
});
|
|
38332
|
+
gone = true;
|
|
38333
|
+
} else gone = await finish();
|
|
38334
|
+
} catch (finishError) {
|
|
38335
|
+
logger.warn(maskedFailureText(` Rollback failed for ${shownLogicalId(op.logicalId)} (UPDATE): `, finishError, mask));
|
|
38336
|
+
result.failures++;
|
|
38337
|
+
ctx.recordEvent?.({
|
|
38338
|
+
eventType: "ROLLBACK_RESOURCE_FAILED",
|
|
38339
|
+
stackName,
|
|
38340
|
+
operation: op.changeType,
|
|
38341
|
+
logicalId: op.logicalId,
|
|
38342
|
+
resourceType: op.resourceType,
|
|
38343
|
+
...op.provisionedBy && { provisionedBy: op.provisionedBy },
|
|
38344
|
+
error: maskedRollbackEventError(finishError, mask)
|
|
38345
|
+
});
|
|
38346
|
+
}
|
|
38347
|
+
if (recordSuperseded && gone) {
|
|
38348
|
+
deferral.onSupersededSettled?.(superseded);
|
|
38349
|
+
await afterOp?.(op.logicalId);
|
|
38350
|
+
}
|
|
38351
|
+
}, recordSuperseded ? keep : void 0);
|
|
38352
|
+
return;
|
|
37227
38353
|
}
|
|
37228
|
-
|
|
37229
|
-
logger.info(mask(adoptedLiveNewResource ? ` Rollback: ${safe(op.logicalId)} adopted the live resource (${recreatedId}) — replacement NOT fully reversed (name-idempotent Create API)` : ` Rollback: ${safe(op.logicalId)} replacement reversed (old resource re-created as ${recreatedId})`));
|
|
37230
|
-
const survivorProvisionedBy = current.provisionedBy;
|
|
37231
|
-
ctx.recordEvent?.({
|
|
37232
|
-
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
37233
|
-
stackName,
|
|
37234
|
-
operation: "UPDATE",
|
|
37235
|
-
logicalId: op.logicalId,
|
|
37236
|
-
resourceType: op.resourceType,
|
|
37237
|
-
...op.provisionedBy && { provisionedBy: op.provisionedBy },
|
|
37238
|
-
...survivorReason !== void 0 && {
|
|
37239
|
-
...survivorId !== void 0 && { physicalId: survivorId },
|
|
37240
|
-
reason: mask(survivorReason),
|
|
37241
|
-
...survivorProvisionedBy && { provisionedBy: survivorProvisionedBy }
|
|
37242
|
-
},
|
|
37243
|
-
...adoptedLiveNewResource && { reason: mask("The re-create returned the live new resource instead of re-creating the old one (its Create API is name-idempotent), so the replacement was NOT fully reversed: the old resource's original properties may not have been re-applied. Inspect it with `cdkd drift` and run `cdkd deploy` to reconcile.") }
|
|
37244
|
-
});
|
|
38354
|
+
await finish();
|
|
37245
38355
|
}
|
|
37246
38356
|
async function deleteMarkedRecreate(error, s) {
|
|
37247
38357
|
const madeId = createdBeforeFailure(error, s.op.logicalId, s.oldType);
|
|
@@ -37318,7 +38428,8 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
|
|
|
37318
38428
|
warnings: 0,
|
|
37319
38429
|
skipped: 0,
|
|
37320
38430
|
interrupted: false,
|
|
37321
|
-
orphaned: []
|
|
38431
|
+
orphaned: [],
|
|
38432
|
+
rolledBackCreates: []
|
|
37322
38433
|
};
|
|
37323
38434
|
if (operations.length === 0) {
|
|
37324
38435
|
ctx.logger.info("No completed operations to roll back.");
|
|
@@ -37335,13 +38446,77 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
|
|
|
37335
38446
|
markDeleteFirstBlocked(operations, options.failedOperations);
|
|
37336
38447
|
const { createOps, otherOps } = partitionOps(operations);
|
|
37337
38448
|
const createdInSegment = new Set(createOps.map((o) => o.logicalId));
|
|
37338
|
-
|
|
38449
|
+
const stepOne = orderInlinePolicyReversals([...otherOps].reverse(), stateResources);
|
|
38450
|
+
const stepOneIds = /* @__PURE__ */ new Map();
|
|
38451
|
+
const stepOneIndex = /* @__PURE__ */ new Map();
|
|
38452
|
+
stepOne.forEach((op, at) => {
|
|
38453
|
+
if (!stepOneIds.has(op.logicalId)) stepOneIds.set(op.logicalId, op);
|
|
38454
|
+
stepOneIndex.set(op, at);
|
|
38455
|
+
});
|
|
38456
|
+
const started = /* @__PURE__ */ new Set();
|
|
38457
|
+
const pendingNewDeletes = /* @__PURE__ */ new Map();
|
|
38458
|
+
const failedOps = /* @__PURE__ */ new Set();
|
|
38459
|
+
const usedByFailedRevert = (target) => [...failedOps].some((failed) => failed !== target && revertReferences(failed, stateResources).has(target.logicalId));
|
|
38460
|
+
const pendingNewIds = /* @__PURE__ */ new Set();
|
|
38461
|
+
const runOp = async (op, deferral) => {
|
|
38462
|
+
const failuresBefore = result.failures;
|
|
38463
|
+
const skippedBefore = result.skipped;
|
|
38464
|
+
await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted, createdInSegment, options.onRolledBackCreate, deferral);
|
|
38465
|
+
if (result.failures > failuresBefore || result.skipped > skippedBefore) failedOps.add(op);
|
|
38466
|
+
};
|
|
38467
|
+
const recreateAhead = async (refs) => {
|
|
38468
|
+
for (const target of [...refs].map((id) => stepOneIds.get(id))) {
|
|
38469
|
+
if (target === void 0 || started.has(target)) continue;
|
|
38470
|
+
if (!renamedReverseReplacement(target, stateResources, orphanLogicalIds, pendingNewIds)) continue;
|
|
38471
|
+
const ownRefs = revertReferences(target, stateResources);
|
|
38472
|
+
if ([...ownRefs].some((id) => {
|
|
38473
|
+
const named = stepOneIds.get(id);
|
|
38474
|
+
return named !== void 0 && !started.has(named) && stepOneIndex.get(named) < stepOneIndex.get(target) && !renamedReverseReplacement(named, stateResources, orphanLogicalIds, pendingNewIds);
|
|
38475
|
+
})) continue;
|
|
38476
|
+
if (options.isInterrupted?.()) return;
|
|
38477
|
+
started.add(target);
|
|
38478
|
+
await recreateAhead(ownRefs);
|
|
38479
|
+
if (options.isInterrupted?.()) return;
|
|
38480
|
+
const newId = stateResources[target.logicalId]?.physicalId;
|
|
38481
|
+
await runOp(target, {
|
|
38482
|
+
defer: (finish, keep) => {
|
|
38483
|
+
pendingNewDeletes.set(target, {
|
|
38484
|
+
finish: async () => {
|
|
38485
|
+
await finish();
|
|
38486
|
+
if (typeof newId === "string") pendingNewIds.delete(newId);
|
|
38487
|
+
},
|
|
38488
|
+
keep
|
|
38489
|
+
});
|
|
38490
|
+
if (typeof newId === "string") pendingNewIds.add(newId);
|
|
38491
|
+
},
|
|
38492
|
+
onSuperseded: options.onSuperseded,
|
|
38493
|
+
onSupersededSettled: options.onSupersededSettled
|
|
38494
|
+
});
|
|
38495
|
+
}
|
|
38496
|
+
};
|
|
38497
|
+
for (const op of stepOne) {
|
|
37339
38498
|
if (options.isInterrupted?.()) {
|
|
37340
38499
|
result.interrupted = true;
|
|
37341
38500
|
break;
|
|
37342
38501
|
}
|
|
37343
|
-
await
|
|
38502
|
+
if (!started.has(op)) await recreateAhead(revertReferences(op, stateResources));
|
|
38503
|
+
if (options.isInterrupted?.()) {
|
|
38504
|
+
result.interrupted = true;
|
|
38505
|
+
break;
|
|
38506
|
+
}
|
|
38507
|
+
if (started.has(op)) {
|
|
38508
|
+
const pending = pendingNewDeletes.get(op);
|
|
38509
|
+
pendingNewDeletes.delete(op);
|
|
38510
|
+
if (pending?.keep !== void 0 && usedByFailedRevert(op)) pending.keep("a resource that references it did not revert");
|
|
38511
|
+
else await pending?.finish();
|
|
38512
|
+
continue;
|
|
38513
|
+
}
|
|
38514
|
+
started.add(op);
|
|
38515
|
+
await runOp(op);
|
|
37344
38516
|
}
|
|
38517
|
+
for (const pending of pendingNewDeletes.values()) if (pending.keep !== void 0) pending.keep("the rollback was interrupted");
|
|
38518
|
+
else await pending.finish();
|
|
38519
|
+
pendingNewDeletes.clear();
|
|
37345
38520
|
if (!result.interrupted && createOps.length > 0) {
|
|
37346
38521
|
const sorted = sortRollbackCreates(createOps, stateResources);
|
|
37347
38522
|
for (const op of sorted) {
|
|
@@ -37349,7 +38524,7 @@ async function replayRollbackUnbound(operations, stateResources, stackName, ctx,
|
|
|
37349
38524
|
result.interrupted = true;
|
|
37350
38525
|
break;
|
|
37351
38526
|
}
|
|
37352
|
-
await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted, createdInSegment);
|
|
38527
|
+
await replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, options.onOrphan, inlinePolicyWriters, options.afterOp, options.isInterrupted, createdInSegment, options.onRolledBackCreate);
|
|
37353
38528
|
}
|
|
37354
38529
|
}
|
|
37355
38530
|
await restoreHeldInlinePolicies(inlinePolicyWriters, stateResources, stackName, ctx, result);
|
|
@@ -37379,7 +38554,7 @@ async function journaledOrphanKeepReason(op, foreignHolder, ctx) {
|
|
|
37379
38554
|
return typeof journaled === "string" && journaled !== "" ? { retry: "its live identity could not be read, so nothing proves the resource now under that id is the one it created" } : { keep: "nothing proves the resource now under that id is the one it created (the journal recorded no identity for it; it may have been deleted and its name reused)" };
|
|
37380
38555
|
}
|
|
37381
38556
|
}
|
|
37382
|
-
async function replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, onOrphan, inlinePolicyWriters, afterOp, isInterrupted, createdInSegment = /* @__PURE__ */ new Set()) {
|
|
38557
|
+
async function replaySingle(op, stateResources, stackName, ctx, resolver, orphanLogicalIds, result, onOrphan, inlinePolicyWriters, afterOp, isInterrupted, createdInSegment = /* @__PURE__ */ new Set(), onRolledBackCreate, deferral) {
|
|
37383
38558
|
const action = classifyRollbackOp(op, stateResources, orphanLogicalIds);
|
|
37384
38559
|
const { logger } = ctx;
|
|
37385
38560
|
const secrets = /* @__PURE__ */ new Map();
|
|
@@ -37396,6 +38571,7 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
|
|
|
37396
38571
|
orphanLogicalIds,
|
|
37397
38572
|
result,
|
|
37398
38573
|
onOrphan,
|
|
38574
|
+
onRolledBackCreate,
|
|
37399
38575
|
inlinePolicyWriters,
|
|
37400
38576
|
afterOp,
|
|
37401
38577
|
isInterrupted,
|
|
@@ -37405,7 +38581,8 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
|
|
|
37405
38581
|
opMasker,
|
|
37406
38582
|
mask,
|
|
37407
38583
|
createdInSegment,
|
|
37408
|
-
createRollbackRoute: void 0
|
|
38584
|
+
createRollbackRoute: void 0,
|
|
38585
|
+
deferral
|
|
37409
38586
|
};
|
|
37410
38587
|
const recordBefore = ownRecord(stateResources, op.logicalId);
|
|
37411
38588
|
try {
|
|
@@ -37469,9 +38646,14 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37469
38646
|
remainingFailedOps: [],
|
|
37470
38647
|
skippedOps: [],
|
|
37471
38648
|
orphaned: [],
|
|
38649
|
+
rolledBackCreates: [],
|
|
37472
38650
|
leftInPlace: 0
|
|
37473
38651
|
};
|
|
37474
38652
|
const { logger } = ctx;
|
|
38653
|
+
const rolledBack = {
|
|
38654
|
+
result,
|
|
38655
|
+
onRolledBackCreate: options.onRolledBackCreate
|
|
38656
|
+
};
|
|
37475
38657
|
const resolver = new ReplayResolvers(ctx.region);
|
|
37476
38658
|
const emitEnvelope = options.emitEnvelope === true && failedOps.length > 0;
|
|
37477
38659
|
if (emitEnvelope) ctx.recordEvent?.({
|
|
@@ -37548,7 +38730,10 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37548
38730
|
result.orphaned.push(orphaned);
|
|
37549
38731
|
options.onOrphan?.(orphaned);
|
|
37550
38732
|
}
|
|
37551
|
-
if (!recordUnderIdIsNotOwn(op, stateResources))
|
|
38733
|
+
if (!recordUnderIdIsNotOwn(op, stateResources)) {
|
|
38734
|
+
delete stateResources[op.logicalId];
|
|
38735
|
+
noteRolledBackCreate(rolledBack, op, failedCreateRecord);
|
|
38736
|
+
}
|
|
37552
38737
|
await noteRetainedResource(op.resourceType, op.logicalId);
|
|
37553
38738
|
logger.info(` Rollback: leaving partially-created ${safe(op.logicalId)} (${safe(op.resourceType)}) in AWS (DeletionPolicy: Retain)` + (failedCreateRecord ? " — removed from state" : " — it was never in state"));
|
|
37554
38739
|
await options.afterOp?.(op.logicalId);
|
|
@@ -37582,7 +38767,10 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37582
38767
|
}, ctx.foreignHolder, ctx);
|
|
37583
38768
|
if (verdict === "gone") {
|
|
37584
38769
|
logger.info(safeMsg` Rollback: partially-created ${shownLogicalId(op.logicalId)} (${refusalResourceType(op.resourceType)}) is already gone — nothing to delete`);
|
|
37585
|
-
if (!recordUnderIdIsNotOwn(op, stateResources))
|
|
38770
|
+
if (!recordUnderIdIsNotOwn(op, stateResources)) {
|
|
38771
|
+
delete stateResources[op.logicalId];
|
|
38772
|
+
noteRolledBackCreate(rolledBack, op, failedCreateRecord);
|
|
38773
|
+
}
|
|
37586
38774
|
await options.afterOp?.(op.logicalId);
|
|
37587
38775
|
ctx.recordEvent?.({
|
|
37588
38776
|
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
@@ -37649,7 +38837,10 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37649
38837
|
result.warnings++;
|
|
37650
38838
|
result.leftInPlace++;
|
|
37651
38839
|
}
|
|
37652
|
-
if (!recordUnderIdIsNotOwn(op, stateResources))
|
|
38840
|
+
if (!recordUnderIdIsNotOwn(op, stateResources)) {
|
|
38841
|
+
delete stateResources[op.logicalId];
|
|
38842
|
+
noteRolledBackCreate(rolledBack, op, failedCreateRecord);
|
|
38843
|
+
}
|
|
37653
38844
|
await options.afterOp?.(op.logicalId);
|
|
37654
38845
|
ctx.recordEvent?.({
|
|
37655
38846
|
eventType: "ROLLBACK_RESOURCE_SUCCEEDED",
|
|
@@ -37714,7 +38905,8 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37714
38905
|
properties: desiredProps,
|
|
37715
38906
|
logicalId: op.logicalId,
|
|
37716
38907
|
physicalId: current.physicalId,
|
|
37717
|
-
via: revertVia
|
|
38908
|
+
via: revertVia,
|
|
38909
|
+
nameGeneration: nameGenerationOf(current, op.logicalId)
|
|
37718
38910
|
}, logger, mask, false)(() => updateWithRollbackRetry(provider, [
|
|
37719
38911
|
op.logicalId,
|
|
37720
38912
|
current.physicalId,
|
|
@@ -37730,7 +38922,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
|
|
|
37730
38922
|
}
|
|
37731
38923
|
], op.logicalId, logger, options.isInterrupted, secrets, mask));
|
|
37732
38924
|
if (revertFailedResult) recordNoEchoAttributeValues(revertFailedResult, secrets, desiredProps);
|
|
37733
|
-
stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(recordAfterRollbackUpdate(prev, revertFailedResult), secrets, prev.properties, prev.attributes), prev, noEcho.substituted);
|
|
38925
|
+
stateResources[op.logicalId] = maskRestoredNoEchoRecord(redactRollbackRecord(withNameGenerationReached(recordAfterRollbackUpdate(prev, revertFailedResult), op.logicalId, op.nameGeneration), secrets, prev.properties, prev.attributes), prev, noEcho.substituted);
|
|
37734
38926
|
if (updatePartialReason(revertFailedResult) === void 0) inlinePolicyWriters.record(op.logicalId, "update", stateResources[op.logicalId], !deepEqual$1(prev.properties?.["Policies"], (op.attemptedProperties ?? current.properties)?.["Policies"]), revertVia);
|
|
37735
38927
|
const revertFailedPartial = updatePartialReason(revertFailedResult);
|
|
37736
38928
|
if (revertFailedPartial !== void 0) logger.warn(mask(` Rollback: ${safe(op.logicalId)} reverted, ${updatePartialMessage(revertFailedPartial)}`));
|
|
@@ -38095,6 +39287,69 @@ function healPrintingBag(baseline, logicalId, resource, namingSecrets) {
|
|
|
38095
39287
|
return hit.judge(logicalId);
|
|
38096
39288
|
}
|
|
38097
39289
|
|
|
39290
|
+
//#endregion
|
|
39291
|
+
//#region src/deployment/deploy-engine/superseded-retry.ts
|
|
39292
|
+
async function retryCarriedSupersededResources(engine, host, carried, resources, options = {}) {
|
|
39293
|
+
let changed = false;
|
|
39294
|
+
if (carried.length === 0) return changed;
|
|
39295
|
+
const view = {
|
|
39296
|
+
live: () => Object.entries(resources),
|
|
39297
|
+
survivors: () => Object.entries(resources)
|
|
39298
|
+
};
|
|
39299
|
+
for (const entry of carried) {
|
|
39300
|
+
if (engine.interrupted) break;
|
|
39301
|
+
const { logicalId } = entry;
|
|
39302
|
+
const { physicalId, resourceType } = entry.state;
|
|
39303
|
+
const bag = unionOfSecretBags([secretNameBagFor(engine.secretsRun, logicalId), orphanRecordsPrintingBag([entry])]);
|
|
39304
|
+
const holder = supersededHolderOf(entry, resources);
|
|
39305
|
+
if (holder !== void 0) {
|
|
39306
|
+
removeSuperseded(host, entry);
|
|
39307
|
+
changed = true;
|
|
39308
|
+
if (holder.resourceType !== resourceType) {
|
|
39309
|
+
withPrintingSecrets(bag, () => engine.logger.warn(safeMsg` ⚠ ${supersededHeldByOtherTypeWarning(entry, holder.resourceType)}`));
|
|
39310
|
+
continue;
|
|
39311
|
+
}
|
|
39312
|
+
withPrintingSecrets(bag, () => engine.logger.debug(safeMsg`Superseded ${logicalId} (${physicalId}) is held by a record again; not deleting it`));
|
|
39313
|
+
continue;
|
|
39314
|
+
}
|
|
39315
|
+
await withPrintingSecrets(bag, () => withStackRecords(view, async () => {
|
|
39316
|
+
engine.logger.info(safeMsg` Deleting old ${logicalId} (${physicalId}), superseded by an earlier deploy...`);
|
|
39317
|
+
let outcome;
|
|
39318
|
+
try {
|
|
39319
|
+
const route = engine.providerRegistry.getProviderFor({
|
|
39320
|
+
resourceType,
|
|
39321
|
+
...entry.state.provisionedBy !== void 0 && { provisionedBy: entry.state.provisionedBy }
|
|
39322
|
+
});
|
|
39323
|
+
outcome = await deleteSupersededEntry(entry, {
|
|
39324
|
+
provider: route.provider,
|
|
39325
|
+
region: engine.stackRegion,
|
|
39326
|
+
maskSecrets: createSecretMasker(bag),
|
|
39327
|
+
stop: () => engine.interrupted,
|
|
39328
|
+
once: options.waitInUse !== true
|
|
39329
|
+
});
|
|
39330
|
+
} catch (error) {
|
|
39331
|
+
outcome = {
|
|
39332
|
+
kind: "failed",
|
|
39333
|
+
error
|
|
39334
|
+
};
|
|
39335
|
+
}
|
|
39336
|
+
if (outcome.kind === "failed") {
|
|
39337
|
+
const detail = maskSecretsInText(describeAwsFailure(outcome.error).detail, bag);
|
|
39338
|
+
engine.logger.warn(safeMsg` ⚠ Failed to delete old resource ${logicalId} (${physicalId}): ${detail}. ${SUPERSEDED_KEPT_REMEDY}.`);
|
|
39339
|
+
return;
|
|
39340
|
+
}
|
|
39341
|
+
removeSuperseded(host, entry);
|
|
39342
|
+
changed = true;
|
|
39343
|
+
if (outcome.kind === "notDeleted") {
|
|
39344
|
+
engine.logger.warn(safeMsg` ⚠ ${deleteSkippedMessage(logicalId, physicalId, outcome.reason, "while cleaning up the superseded resource", { commandFreeLine: true })}. Delete it manually — it is no longer tracked in state.`);
|
|
39345
|
+
return;
|
|
39346
|
+
}
|
|
39347
|
+
engine.logger.info(safeMsg` ${green("✓")} Old ${logicalId} (${physicalId}) deleted`);
|
|
39348
|
+
}));
|
|
39349
|
+
}
|
|
39350
|
+
return changed;
|
|
39351
|
+
}
|
|
39352
|
+
|
|
38098
39353
|
//#endregion
|
|
38099
39354
|
//#region src/provisioning/name-lookup.ts
|
|
38100
39355
|
const inFlight = /* @__PURE__ */ new Map();
|
|
@@ -38193,7 +39448,8 @@ var GeneratedNameGuard = class GeneratedNameGuard {
|
|
|
38193
39448
|
static start(input) {
|
|
38194
39449
|
const candidates = [];
|
|
38195
39450
|
for (const change of input.changes) {
|
|
38196
|
-
|
|
39451
|
+
const generation = change.changeType === "UPDATE" ? input.replacementGeneration?.(change) : void 0;
|
|
39452
|
+
if (change.changeType !== "CREATE" && generation === void 0) continue;
|
|
38197
39453
|
const properties = change.desiredProperties ?? {};
|
|
38198
39454
|
let decision;
|
|
38199
39455
|
let name;
|
|
@@ -38204,7 +39460,11 @@ var GeneratedNameGuard = class GeneratedNameGuard {
|
|
|
38204
39460
|
properties
|
|
38205
39461
|
});
|
|
38206
39462
|
if (!replacementCreateAdoptsName(change.resourceType, decision.provisionedBy)) continue;
|
|
38207
|
-
|
|
39463
|
+
const derive = () => decision.provider.generatedCreateName?.(change.resourceType, change.logicalId, properties);
|
|
39464
|
+
name = generation === void 0 ? derive() : withNameGeneration({
|
|
39465
|
+
logicalId: change.logicalId,
|
|
39466
|
+
generation
|
|
39467
|
+
}, derive);
|
|
38208
39468
|
deferred = decision.provider.lookupNeedsResolvedProperties?.(change.resourceType, properties) === true;
|
|
38209
39469
|
} catch {
|
|
38210
39470
|
continue;
|
|
@@ -38504,7 +39764,7 @@ var GeneratedNameGuard = class GeneratedNameGuard {
|
|
|
38504
39764
|
});
|
|
38505
39765
|
unlicensed.push(c);
|
|
38506
39766
|
}
|
|
38507
|
-
if (unlicensed.length > 0 && input.loadKeptInHistory !== void 0 && evidence !== void 0 && !("error" in evidence) && evidence.retainedAbsent) {
|
|
39767
|
+
if (unlicensed.length > 0 && input.newScheme !== true && input.loadKeptInHistory !== void 0 && evidence !== void 0 && !("error" in evidence) && evidence.retainedAbsent) {
|
|
38508
39768
|
let kept;
|
|
38509
39769
|
try {
|
|
38510
39770
|
this.historyRead ??= input.loadKeptInHistory();
|
|
@@ -38667,14 +39927,15 @@ async function lookupAll(input, candidates) {
|
|
|
38667
39927
|
};
|
|
38668
39928
|
}
|
|
38669
39929
|
async function loadEvidence(input) {
|
|
38670
|
-
const
|
|
39930
|
+
const kept = input.newScheme !== true;
|
|
39931
|
+
const [journal, retained] = await Promise.all([input.loadJournal(), kept ? input.loadRetained() : Promise.resolve([])]);
|
|
38671
39932
|
const sources = [];
|
|
38672
39933
|
for (const record of Object.values(input.records)) if (typeof record?.physicalId === "string") sources.push({
|
|
38673
39934
|
via: "record",
|
|
38674
39935
|
type: record.resourceType,
|
|
38675
39936
|
id: record.physicalId
|
|
38676
39937
|
});
|
|
38677
|
-
for (const orphan of input.orphans ?? []) {
|
|
39938
|
+
for (const orphan of kept ? input.orphans ?? [] : []) {
|
|
38678
39939
|
const s = orphan.state;
|
|
38679
39940
|
if (typeof s?.physicalId === "string") sources.push({
|
|
38680
39941
|
via: "orphan",
|
|
@@ -38853,7 +40114,7 @@ function warnDropFailed(logger, stackName, region, logicalIds) {
|
|
|
38853
40114
|
logger.warn(safeMsg`${hint.intro}`);
|
|
38854
40115
|
for (const command of hint.commands) logger.warn(safeMsg`Drop with: ${command}`);
|
|
38855
40116
|
}
|
|
38856
|
-
async function deleteJournaledOrphans(orphans, stateResources, stackName, ctx, options = {}) {
|
|
40117
|
+
async function deleteJournaledOrphans(orphans, stateResources, stackName, stackInstanceId, ctx, options = {}) {
|
|
38857
40118
|
const total = {
|
|
38858
40119
|
failures: 0,
|
|
38859
40120
|
warnings: 0,
|
|
@@ -38877,7 +40138,10 @@ async function deleteJournaledOrphans(orphans, stateResources, stackName, ctx, o
|
|
|
38877
40138
|
break;
|
|
38878
40139
|
}
|
|
38879
40140
|
const ops = [...companions ?? [], ...orphanOps];
|
|
38880
|
-
const replay = () => withPrintingSecrets(printing, () =>
|
|
40141
|
+
const replay = () => withPrintingSecrets(printing, () => withStackScope(nameScopeOf(stackName, stackInstanceId, {
|
|
40142
|
+
resources: stateResources,
|
|
40143
|
+
...options.retiredNameGenerations !== void 0 && { retiredNameGenerations: options.retiredNameGenerations }
|
|
40144
|
+
}), () => replayFailedOperations(ops, stateResources, stackName, maskedCtx, {
|
|
38881
40145
|
emitEnvelope: false,
|
|
38882
40146
|
inlinePolicyWriters,
|
|
38883
40147
|
forDestroy: true,
|
|
@@ -38963,14 +40227,15 @@ async function settleJournaledOrphansOnSuccess(args) {
|
|
|
38963
40227
|
count: orphans.count - unreadable.size - tracked.size
|
|
38964
40228
|
};
|
|
38965
40229
|
const writtenThisRun = [...orphans.deployLogicalIds ?? []].filter((id) => Object.prototype.hasOwnProperty.call(stateResources, id)).map((id) => stateResources[id]).filter((r) => r !== void 0 && r !== null && typeof r === "object");
|
|
38966
|
-
const outcome = await deleteJournaledOrphans(acting, { ...stateResources }, stackName, {
|
|
40230
|
+
const outcome = await deleteJournaledOrphans(acting, { ...stateResources }, stackName, args.stackInstanceId, {
|
|
38967
40231
|
...ctx,
|
|
38968
40232
|
writtenThisRun,
|
|
38969
40233
|
foreignHolder: args.foreignHolder,
|
|
38970
40234
|
orphanDeleteProven: proven
|
|
38971
40235
|
}, {
|
|
38972
40236
|
pointAtDrop: false,
|
|
38973
|
-
...args.isInterrupted && { isInterrupted: args.isInterrupted }
|
|
40237
|
+
...args.isInterrupted && { isInterrupted: args.isInterrupted },
|
|
40238
|
+
retiredNameGenerations: args.retiredNameGenerations
|
|
38974
40239
|
});
|
|
38975
40240
|
leftInPlace = outcome.leftInPlace;
|
|
38976
40241
|
failedDeletes = outcome.failedLogicalIds;
|
|
@@ -39425,10 +40690,13 @@ async function revertNestedChildFromJournal(args) {
|
|
|
39425
40690
|
refuseMalformedState(base, childStackName, region, refusalRecovery);
|
|
39426
40691
|
refuseMalformedOrphans(base, childStackName, region, refusalRecovery);
|
|
39427
40692
|
refuseMalformedOrphanRecords(base, childStackName, region, refusalRecovery);
|
|
40693
|
+
const childNamingScope = nameScopeOf(childStackName, stackInstanceIdOf(base, displayStackName(childStackName)), base);
|
|
39428
40694
|
const segments = ((await ctx.stateBackend.loadRollbackJournal(childStackName, region))?.segments ?? []).filter((segment) => segment.runId === runId);
|
|
39429
40695
|
if (segments.length === 0) refuse("its rollback journal holds no segment for this deploy run, so there is no record of what it held before.");
|
|
39430
40696
|
const stateResources = { ...base.resources };
|
|
39431
40697
|
const mintedOrphans = [];
|
|
40698
|
+
const rolledBackCreates = [];
|
|
40699
|
+
const supersededHost = {};
|
|
39432
40700
|
const restoredOutputs = segments.find((s) => s.previousOutputs)?.previousOutputs;
|
|
39433
40701
|
const restoredReads = segments.find((s) => s.previousCrossStackReads)?.previousCrossStackReads;
|
|
39434
40702
|
let currentEtag = stateData.etag;
|
|
@@ -39437,10 +40705,13 @@ async function revertNestedChildFromJournal(args) {
|
|
|
39437
40705
|
const { skippedOutputs: _dropped, ...carried } = base;
|
|
39438
40706
|
const next = () => ({
|
|
39439
40707
|
...carried,
|
|
39440
|
-
|
|
40708
|
+
...stackInstanceIdCarriedFrom(base),
|
|
40709
|
+
...supersededAfterRollback(base, supersededHost),
|
|
40710
|
+
version: 13,
|
|
39441
40711
|
region,
|
|
39442
40712
|
resources: { ...stateResources },
|
|
39443
40713
|
...orphansAfterRollback(base, mintedOrphans),
|
|
40714
|
+
...retiredAfterRollback(base, mintedOrphans, rolledBackCreates),
|
|
39444
40715
|
...restoring && restoredOutputs && { outputs: { ...restoredOutputs.outputs } },
|
|
39445
40716
|
...restoring && restoredReads && {
|
|
39446
40717
|
...restoredReads.imports && { imports: [...restoredReads.imports] },
|
|
@@ -39509,12 +40780,15 @@ async function revertNestedChildFromJournal(args) {
|
|
|
39509
40780
|
const segment = segments[s];
|
|
39510
40781
|
const skipPrefix = segment.skipPrefix ?? getCurrentSkipPrefix();
|
|
39511
40782
|
const split = splitImportedOps(segment.operations, segment);
|
|
39512
|
-
const result = await withNestedStackContext(childCtx, () => withSkipPrefix(skipPrefix, () =>
|
|
40783
|
+
const result = await withNestedStackContext(childCtx, () => withSkipPrefix(skipPrefix, () => withStackScope(childNamingScope, () => withCreateTokenLedger(ledgerForStack(ctx.stateBackend, childStackName, region), () => withNestedRevertRun(runId, async (inner) => {
|
|
39513
40784
|
const replayed = await withPrintingSecrets(journaledOrphanPrintingBag(completedReplayEntries(split.replay), stateResources), () => replayRollback(split.replay, stateResources, childStackName, execCtx, {
|
|
39514
40785
|
afterOp: save,
|
|
39515
40786
|
onOrphan: (record) => mintedOrphans.push(record),
|
|
40787
|
+
onRolledBackCreate: (create) => rolledBackCreates.push(create),
|
|
39516
40788
|
inlinePolicyWriters,
|
|
39517
|
-
failedOperations: segment.failedOperations
|
|
40789
|
+
failedOperations: segment.failedOperations,
|
|
40790
|
+
onSuperseded: (entry) => addSuperseded(supersededHost, entry),
|
|
40791
|
+
onSupersededSettled: (entry) => removeSuperseded(supersededHost, entry)
|
|
39518
40792
|
}));
|
|
39519
40793
|
for (const [id, below] of inner.settled) settledBelow.set(id, below);
|
|
39520
40794
|
return {
|
|
@@ -39544,13 +40818,18 @@ async function revertNestedChildFromJournal(args) {
|
|
|
39544
40818
|
|
|
39545
40819
|
//#endregion
|
|
39546
40820
|
//#region src/deployment/retained-readoption.ts
|
|
39547
|
-
function
|
|
39548
|
-
if (!replacementCreateAdoptsName(resource.resourceType, resource.provisionedBy)) return false;
|
|
40821
|
+
function keptUnderGeneratedName(resource) {
|
|
39549
40822
|
if (typeof resource.physicalId !== "string" || resource.physicalId === "") return false;
|
|
39550
40823
|
const property = explicitNamePropertyFor(resource.resourceType);
|
|
39551
40824
|
const properties = resource.properties;
|
|
39552
40825
|
return property === void 0 || !properties?.[property];
|
|
39553
40826
|
}
|
|
40827
|
+
function keptForRetainedRecord(resource) {
|
|
40828
|
+
return replacementCreateAdoptsName(resource.resourceType, "sdk") ? keptForReadoption(resource) : keptUnderGeneratedName(resource);
|
|
40829
|
+
}
|
|
40830
|
+
function keptForReadoption(resource) {
|
|
40831
|
+
return replacementCreateAdoptsName(resource.resourceType, resource.provisionedBy) && keptUnderGeneratedName(resource);
|
|
40832
|
+
}
|
|
39554
40833
|
async function recordRetainedForReadoption(backend, stackName, region, kept, logger, earlier) {
|
|
39555
40834
|
if (kept.length === 0) {
|
|
39556
40835
|
try {
|
|
@@ -39566,10 +40845,10 @@ async function recordRetainedForReadoption(backend, stackName, region, kept, log
|
|
|
39566
40845
|
await backend.saveRetainedResources(stackName, region, [...before.filter((e) => !keptIds.has(e.logicalId)), ...kept]);
|
|
39567
40846
|
} catch (error) {
|
|
39568
40847
|
if (error instanceof RetainedTimeUnconfirmedError) {
|
|
39569
|
-
logger.warn(safeMsg`Recorded the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)} ` + safeMsg`
|
|
40848
|
+
logger.warn(safeMsg`Recorded the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)}, ` + safeMsg`but their time could not be confirmed from S3 ` + safeMsg`(${describeAwsFailure(error.cause).summary}); they carry this machine's clock instead.`);
|
|
39570
40849
|
return;
|
|
39571
40850
|
}
|
|
39572
|
-
logger.warn(safeMsg`Could not record the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)} ` + safeMsg`
|
|
40851
|
+
logger.warn(safeMsg`Could not record the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). A later deploy may refuse to create one over ` + `its kept copy, or not name them; adopt a kept one with 'cdkd import'.`);
|
|
39573
40852
|
}
|
|
39574
40853
|
}
|
|
39575
40854
|
var KeptForReadoption = class {
|
|
@@ -39630,7 +40909,7 @@ async function provisionDelete(deps, logicalId, change, stateResources, stackNam
|
|
|
39630
40909
|
deps.logger.info(safeMsg`Retaining ${logicalId} (${resourceType}) - DeletionPolicy: ${deletionPolicy}`);
|
|
39631
40910
|
delete stateResources[logicalId];
|
|
39632
40911
|
await noteRetainedResource(resourceType, logicalId);
|
|
39633
|
-
if (keptForReadoption(currentResource)) {
|
|
40912
|
+
if (getCurrentStackInstanceId() !== void 0 ? keptForRetainedRecord(currentResource) : keptForReadoption(currentResource)) {
|
|
39634
40913
|
let kept = keptByEngine.get(deps.owner);
|
|
39635
40914
|
if (kept === void 0) {
|
|
39636
40915
|
kept = new KeptForReadoption(deps.stateBackend, stackName, deps.stackRegion, deps.logger);
|
|
@@ -39809,6 +41088,9 @@ async function settlePending(params, pending) {
|
|
|
39809
41088
|
const reader = params.reader();
|
|
39810
41089
|
const isUnique = params.identifierUnique ?? ccIdentifierIsUnique;
|
|
39811
41090
|
const stackShown = displayStackName(stackName);
|
|
41091
|
+
const source = params.stackInstanceId;
|
|
41092
|
+
let resolvedId;
|
|
41093
|
+
const stackInstanceId = () => resolvedId ??= typeof source === "function" ? source() : Promise.resolve(source);
|
|
39812
41094
|
const settlements = /* @__PURE__ */ new Map();
|
|
39813
41095
|
const unresolved = [];
|
|
39814
41096
|
for (const [token, op] of pending) {
|
|
@@ -39840,7 +41122,9 @@ async function settlePending(params, pending) {
|
|
|
39840
41122
|
identifier: made,
|
|
39841
41123
|
attemptedProperties: op.attemptedProperties,
|
|
39842
41124
|
logicalId: op.logicalId,
|
|
39843
|
-
stackName
|
|
41125
|
+
stackName,
|
|
41126
|
+
stackInstanceId: await stackInstanceId(),
|
|
41127
|
+
nameGenerationsThrough: generationsThrough(op, held)
|
|
39844
41128
|
});
|
|
39845
41129
|
const ended = outcome.status === "succeeded" ? "completed" : outcome.status === "cancelled" ? "was cancelled" : "failed";
|
|
39846
41130
|
if (outcome.status === "succeeded" && unique && held === void 0 && params.resume?.(op, made)) {
|
|
@@ -39894,7 +41178,7 @@ function holdsSecretReference(properties) {
|
|
|
39894
41178
|
if (properties === void 0) return false;
|
|
39895
41179
|
return carriesSecretMask(properties) || JSON.stringify(properties).includes("{{resolve:");
|
|
39896
41180
|
}
|
|
39897
|
-
const ccIdentifierIsUnique = async ({ resourceType, identifier, attemptedProperties, logicalId, stackName }) => {
|
|
41181
|
+
const ccIdentifierIsUnique = async ({ resourceType, identifier, attemptedProperties, logicalId, stackName, stackInstanceId, nameGenerationsThrough }) => {
|
|
39898
41182
|
if (attemptedProperties === void 0 || holdsSecretReference(attemptedProperties)) return false;
|
|
39899
41183
|
const [fields, readOnly] = await Promise.all([getPrimaryIdentifierFields(resourceType), getTopLevelReadOnlyProperties(resourceType)]);
|
|
39900
41184
|
if (fields === void 0 || readOnly === void 0) return false;
|
|
@@ -39909,9 +41193,15 @@ const ccIdentifierIsUnique = async ({ resourceType, identifier, attemptedPropert
|
|
|
39909
41193
|
collect(attemptedProperties);
|
|
39910
41194
|
return parts.some((part, i) => {
|
|
39911
41195
|
if (part === "" || !readOnly.has(fields[i])) return false;
|
|
39912
|
-
return !nameSegments(part).some((segment) => sent.has(segment) || looksLikeCdkdGeneratedName(segment, logicalId, stackName));
|
|
41196
|
+
return !nameSegments(part).some((segment) => sent.has(segment) || looksLikeCdkdGeneratedName(segment, logicalId, stackName, stackInstanceId, nameGenerationsThrough === void 0 ? void 0 : { through: nameGenerationsThrough }));
|
|
39913
41197
|
});
|
|
39914
41198
|
};
|
|
41199
|
+
function generationsThrough(op, held) {
|
|
41200
|
+
const own = isNameGeneration(op.nameGeneration) ? op.nameGeneration : 0;
|
|
41201
|
+
let recorded = 0;
|
|
41202
|
+
for (const value of [held?.nameGeneration, held?.nameGenerationHigh]) if (isNameGeneration(value)) recorded = Math.max(recorded, value);
|
|
41203
|
+
return Math.max(own, recorded) + 1;
|
|
41204
|
+
}
|
|
39915
41205
|
function nameSegments(value) {
|
|
39916
41206
|
const text = value.toLowerCase();
|
|
39917
41207
|
const arn = /^arn:[^:]*:[^:]*:[^:]*:[^:]*:(.*)$/.exec(text);
|
|
@@ -39927,345 +41217,6 @@ function withoutPendingRequest(op) {
|
|
|
39927
41217
|
return rest;
|
|
39928
41218
|
}
|
|
39929
41219
|
|
|
39930
|
-
//#endregion
|
|
39931
|
-
//#region src/state/deployment-events-store.ts
|
|
39932
|
-
const DEPLOYMENT_EVENTS_MAX_INDEX_RUNS = 20;
|
|
39933
|
-
const FLUSH_INTERVAL_MS = 2e3;
|
|
39934
|
-
const FLUSH_EVENT_THRESHOLD = 50;
|
|
39935
|
-
function newDeploymentRunId(now = /* @__PURE__ */ new Date()) {
|
|
39936
|
-
return `${now.toISOString().replace(/[-:.]/g, "")}-${randomUUID().slice(0, 8)}`;
|
|
39937
|
-
}
|
|
39938
|
-
function deploymentEventsKey(prefix, stackName, region, runId) {
|
|
39939
|
-
return `${prefix}/${stackName}/${region}/deployments/${runId}.jsonl`;
|
|
39940
|
-
}
|
|
39941
|
-
function deploymentEventsIndexKey(prefix, stackName, region) {
|
|
39942
|
-
return `${prefix}/${stackName}/${region}/deployments/index.json`;
|
|
39943
|
-
}
|
|
39944
|
-
function deploymentsDirPrefix(prefix, stackName, region) {
|
|
39945
|
-
return `${prefix}/${stackName}/${region}/deployments/`;
|
|
39946
|
-
}
|
|
39947
|
-
const DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION = "deployment-event streams and their index, whose recorded error messages can quote values the secret mask does not catch";
|
|
39948
|
-
async function deleteAndPurgeEventObjects(backend, keys, dirPrefix, scope = "deleted-keys") {
|
|
39949
|
-
if (keys.length === 0) return void 0;
|
|
39950
|
-
let swept;
|
|
39951
|
-
try {
|
|
39952
|
-
await backend.deleteRawObjects(keys);
|
|
39953
|
-
} finally {
|
|
39954
|
-
if (scope === "whole-dir") swept = await backend.purgeNoncurrentVersionsUnderPrefix(dirPrefix, { objectDescription: DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION });
|
|
39955
|
-
else await backend.purgeNoncurrentVersions(keys, {
|
|
39956
|
-
...keys.length > 1 && { listPrefix: dirPrefix },
|
|
39957
|
-
objectDescription: DEPLOYMENT_EVENTS_OBJECT_DESCRIPTION
|
|
39958
|
-
});
|
|
39959
|
-
}
|
|
39960
|
-
return swept;
|
|
39961
|
-
}
|
|
39962
|
-
function runIdTimestampMs(runId) {
|
|
39963
|
-
const m = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z/.exec(runId);
|
|
39964
|
-
if (!m) return null;
|
|
39965
|
-
const iso = `${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}.${m[7]}Z`;
|
|
39966
|
-
const ms = Date.parse(iso);
|
|
39967
|
-
return Number.isNaN(ms) ? null : ms;
|
|
39968
|
-
}
|
|
39969
|
-
function runIdFromJsonlKey(key, dirPrefix) {
|
|
39970
|
-
if (!key.startsWith(dirPrefix) || !key.endsWith(".jsonl")) return null;
|
|
39971
|
-
return key.slice(dirPrefix.length, -6);
|
|
39972
|
-
}
|
|
39973
|
-
var DeploymentEventsStore = class {
|
|
39974
|
-
logger = getLogger().child("DeploymentEvents");
|
|
39975
|
-
backend;
|
|
39976
|
-
stackName;
|
|
39977
|
-
region;
|
|
39978
|
-
command;
|
|
39979
|
-
runId;
|
|
39980
|
-
cdkdVersion;
|
|
39981
|
-
startedAt;
|
|
39982
|
-
events = [];
|
|
39983
|
-
persistedCount = 0;
|
|
39984
|
-
flushTimer;
|
|
39985
|
-
writeChain = Promise.resolve();
|
|
39986
|
-
warnedOnce = false;
|
|
39987
|
-
finalized = false;
|
|
39988
|
-
constructor(backend, options) {
|
|
39989
|
-
this.backend = backend;
|
|
39990
|
-
this.stackName = options.stackName;
|
|
39991
|
-
this.region = options.region;
|
|
39992
|
-
this.command = options.command;
|
|
39993
|
-
this.runId = options.runId ?? newDeploymentRunId();
|
|
39994
|
-
this.cdkdVersion = options.cdkdVersion ?? getCdkdVersion();
|
|
39995
|
-
this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39996
|
-
}
|
|
39997
|
-
record(event) {
|
|
39998
|
-
try {
|
|
39999
|
-
if (this.finalized) return;
|
|
40000
|
-
this.events.push({
|
|
40001
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40002
|
-
...event
|
|
40003
|
-
});
|
|
40004
|
-
if (this.events.length - this.persistedCount >= FLUSH_EVENT_THRESHOLD) this.scheduleFlush(0);
|
|
40005
|
-
else this.scheduleFlush(FLUSH_INTERVAL_MS);
|
|
40006
|
-
} catch {}
|
|
40007
|
-
}
|
|
40008
|
-
async finalize(result) {
|
|
40009
|
-
if (this.finalized) return;
|
|
40010
|
-
this.finalized = true;
|
|
40011
|
-
if (this.flushTimer) {
|
|
40012
|
-
clearTimeout(this.flushTimer);
|
|
40013
|
-
this.flushTimer = void 0;
|
|
40014
|
-
}
|
|
40015
|
-
if (this.events.length === 0) return;
|
|
40016
|
-
await this.enqueueWrite(async () => {
|
|
40017
|
-
const indexRead = this.readIndexRuns();
|
|
40018
|
-
indexRead.catch(() => {});
|
|
40019
|
-
await this.doFlush();
|
|
40020
|
-
await this.writeIndexAndPrune(result, await indexRead);
|
|
40021
|
-
});
|
|
40022
|
-
}
|
|
40023
|
-
async writeIndexAndPrune(result, existingRuns) {
|
|
40024
|
-
const { key, file, runs } = this.buildIndexUpdate(result, existingRuns);
|
|
40025
|
-
const keptRunIds = runs.map((r) => r.runId);
|
|
40026
|
-
const willPrune = keptRunIds.length >= 20;
|
|
40027
|
-
const dirPrefix = deploymentsDirPrefix(this.backend.prefix, this.stackName, this.region);
|
|
40028
|
-
const staleKeysRead = willPrune ? this.backend.listRawKeys(dirPrefix) : void 0;
|
|
40029
|
-
staleKeysRead?.catch(() => {});
|
|
40030
|
-
await this.backend.putRawObject(key, JSON.stringify(file, null, 2));
|
|
40031
|
-
if (!staleKeysRead) return;
|
|
40032
|
-
await this.pruneSupersededRunFiles(keptRunIds, dirPrefix, await staleKeysRead);
|
|
40033
|
-
}
|
|
40034
|
-
async drain() {
|
|
40035
|
-
await this.writeChain;
|
|
40036
|
-
}
|
|
40037
|
-
scheduleFlush(delayMs) {
|
|
40038
|
-
if (this.flushTimer) {
|
|
40039
|
-
if (delayMs > 0) return;
|
|
40040
|
-
clearTimeout(this.flushTimer);
|
|
40041
|
-
}
|
|
40042
|
-
this.flushTimer = setTimeout(() => {
|
|
40043
|
-
this.flushTimer = void 0;
|
|
40044
|
-
this.enqueueWrite(() => this.doFlush());
|
|
40045
|
-
}, delayMs);
|
|
40046
|
-
this.flushTimer.unref?.();
|
|
40047
|
-
}
|
|
40048
|
-
enqueueWrite(op) {
|
|
40049
|
-
const next = this.writeChain.then(op).catch((err) => {
|
|
40050
|
-
this.warnOnce(`Failed to persist deployment events for run ${this.runId}: ${describeAwsFailure(err).detail}`);
|
|
40051
|
-
});
|
|
40052
|
-
this.writeChain = next;
|
|
40053
|
-
return next;
|
|
40054
|
-
}
|
|
40055
|
-
async doFlush() {
|
|
40056
|
-
if (this.events.length === 0 || this.events.length === this.persistedCount) return;
|
|
40057
|
-
const snapshotCount = this.events.length;
|
|
40058
|
-
const body = this.events.slice(0, snapshotCount).map((e) => JSON.stringify(e)).join("\n");
|
|
40059
|
-
await this.backend.putRawObject(deploymentEventsKey(this.backend.prefix, this.stackName, this.region, this.runId), body + "\n", "application/x-ndjson");
|
|
40060
|
-
this.persistedCount = snapshotCount;
|
|
40061
|
-
}
|
|
40062
|
-
async readIndexRuns() {
|
|
40063
|
-
const key = deploymentEventsIndexKey(this.backend.prefix, this.stackName, this.region);
|
|
40064
|
-
try {
|
|
40065
|
-
const raw = await this.backend.getRawObject(key);
|
|
40066
|
-
if (raw !== null) {
|
|
40067
|
-
const parsed = JSON.parse(raw);
|
|
40068
|
-
if (Array.isArray(parsed.runs)) return parsed.runs;
|
|
40069
|
-
}
|
|
40070
|
-
} catch (err) {
|
|
40071
|
-
this.logger.debug(`Deployment-events index unreadable, rewriting: ${describeAwsFailure(err).detail}`);
|
|
40072
|
-
}
|
|
40073
|
-
return [];
|
|
40074
|
-
}
|
|
40075
|
-
buildIndexUpdate(result, existingRuns) {
|
|
40076
|
-
const key = deploymentEventsIndexKey(this.backend.prefix, this.stackName, this.region);
|
|
40077
|
-
const runs = [{
|
|
40078
|
-
runId: this.runId,
|
|
40079
|
-
command: this.command,
|
|
40080
|
-
cdkdVersion: this.cdkdVersion,
|
|
40081
|
-
startedAt: this.startedAt,
|
|
40082
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40083
|
-
result,
|
|
40084
|
-
eventCount: this.persistedCount
|
|
40085
|
-
}, ...existingRuns.filter((r) => r.runId !== this.runId)].slice(0, 20);
|
|
40086
|
-
return {
|
|
40087
|
-
key,
|
|
40088
|
-
file: {
|
|
40089
|
-
indexVersion: 1,
|
|
40090
|
-
stackName: this.stackName,
|
|
40091
|
-
region: this.region,
|
|
40092
|
-
runs,
|
|
40093
|
-
lastModified: Date.now()
|
|
40094
|
-
},
|
|
40095
|
-
runs
|
|
40096
|
-
};
|
|
40097
|
-
}
|
|
40098
|
-
async pruneSupersededRunFiles(keptRunIds, dirPrefix, keys) {
|
|
40099
|
-
if (keptRunIds.length < 20) return;
|
|
40100
|
-
const cutoff = keptRunIds.reduce((min, id) => id < min ? id : min, keptRunIds[0]);
|
|
40101
|
-
const stale = keys.filter((k) => {
|
|
40102
|
-
const runId = runIdFromJsonlKey(k, dirPrefix);
|
|
40103
|
-
return runId !== null && runId < cutoff;
|
|
40104
|
-
});
|
|
40105
|
-
if (stale.length === 0) return;
|
|
40106
|
-
await deleteAndPurgeEventObjects(this.backend, stale, dirPrefix);
|
|
40107
|
-
this.logger.debug(`Pruned ${stale.length} superseded deployment-event stream(s) for ${this.stackName} (${this.region})`);
|
|
40108
|
-
}
|
|
40109
|
-
warnOnce(message) {
|
|
40110
|
-
if (this.warnedOnce) {
|
|
40111
|
-
this.logger.debug(message);
|
|
40112
|
-
return;
|
|
40113
|
-
}
|
|
40114
|
-
this.warnedOnce = true;
|
|
40115
|
-
this.logger.warn(`${message} — continuing; deployment events are best-effort and never block the run.`);
|
|
40116
|
-
}
|
|
40117
|
-
};
|
|
40118
|
-
var DeploymentEventsReader = class {
|
|
40119
|
-
backend;
|
|
40120
|
-
constructor(backend) {
|
|
40121
|
-
this.backend = backend;
|
|
40122
|
-
}
|
|
40123
|
-
async listRegions(stackName) {
|
|
40124
|
-
const prefix = `${this.backend.prefix}/${stackName}/`;
|
|
40125
|
-
const keys = await this.backend.listRawKeys(prefix);
|
|
40126
|
-
const regions = /* @__PURE__ */ new Set();
|
|
40127
|
-
for (const key of keys) {
|
|
40128
|
-
const segments = key.slice(prefix.length).split("/");
|
|
40129
|
-
if (segments.length === 3 && segments[1] === "deployments" && segments[0]) regions.add(segments[0]);
|
|
40130
|
-
}
|
|
40131
|
-
return [...regions].sort();
|
|
40132
|
-
}
|
|
40133
|
-
async listRuns(stackName, region) {
|
|
40134
|
-
const key = deploymentEventsIndexKey(this.backend.prefix, stackName, region);
|
|
40135
|
-
try {
|
|
40136
|
-
const raw = await this.backend.getRawObject(key);
|
|
40137
|
-
if (raw !== null) {
|
|
40138
|
-
const parsed = JSON.parse(raw);
|
|
40139
|
-
if (Array.isArray(parsed.runs)) return parsed.runs;
|
|
40140
|
-
}
|
|
40141
|
-
} catch {}
|
|
40142
|
-
const dirPrefix = `${this.backend.prefix}/${stackName}/${region}/deployments/`;
|
|
40143
|
-
const runIds = (await this.backend.listRawKeys(dirPrefix)).filter((k) => k.endsWith(".jsonl")).map((k) => k.slice(dirPrefix.length, -6)).sort().reverse();
|
|
40144
|
-
return Promise.all(runIds.map((runId) => this.summarizeRunFromJsonl(stackName, region, runId)));
|
|
40145
|
-
}
|
|
40146
|
-
async summarizeRunFromJsonl(stackName, region, runId) {
|
|
40147
|
-
const fallback = {
|
|
40148
|
-
runId,
|
|
40149
|
-
command: "deploy",
|
|
40150
|
-
cdkdVersion: "unknown",
|
|
40151
|
-
startedAt: "",
|
|
40152
|
-
finishedAt: "",
|
|
40153
|
-
result: "UNKNOWN",
|
|
40154
|
-
eventCount: 0
|
|
40155
|
-
};
|
|
40156
|
-
let events = null;
|
|
40157
|
-
try {
|
|
40158
|
-
events = await this.readRunEvents(stackName, region, runId);
|
|
40159
|
-
} catch {
|
|
40160
|
-
return fallback;
|
|
40161
|
-
}
|
|
40162
|
-
if (events === null || events.length === 0) return fallback;
|
|
40163
|
-
const started = events.find((e) => e.eventType === "RUN_STARTED");
|
|
40164
|
-
let finished;
|
|
40165
|
-
for (const e of events) if (e.eventType === "RUN_FINISHED") finished = e;
|
|
40166
|
-
return {
|
|
40167
|
-
runId,
|
|
40168
|
-
command: started?.command ?? fallback.command,
|
|
40169
|
-
cdkdVersion: started?.cdkdVersion ?? fallback.cdkdVersion,
|
|
40170
|
-
startedAt: started?.timestamp ?? fallback.startedAt,
|
|
40171
|
-
finishedAt: finished?.timestamp ?? fallback.finishedAt,
|
|
40172
|
-
result: finished?.result ?? "UNKNOWN",
|
|
40173
|
-
eventCount: events.length
|
|
40174
|
-
};
|
|
40175
|
-
}
|
|
40176
|
-
async readRunEvents(stackName, region, runId) {
|
|
40177
|
-
const key = deploymentEventsKey(this.backend.prefix, stackName, region, runId);
|
|
40178
|
-
const raw = await this.backend.getRawObject(key);
|
|
40179
|
-
if (raw === null) return null;
|
|
40180
|
-
const events = [];
|
|
40181
|
-
for (const line of raw.split("\n")) {
|
|
40182
|
-
const trimmed = line.trim();
|
|
40183
|
-
if (!trimmed) continue;
|
|
40184
|
-
try {
|
|
40185
|
-
events.push(JSON.parse(trimmed));
|
|
40186
|
-
} catch {}
|
|
40187
|
-
}
|
|
40188
|
-
return events;
|
|
40189
|
-
}
|
|
40190
|
-
async pruneRuns(stackName, region, opts = {}) {
|
|
40191
|
-
const dirPrefix = deploymentsDirPrefix(this.backend.prefix, stackName, region);
|
|
40192
|
-
const keys = await this.backend.listRawKeys(dirPrefix);
|
|
40193
|
-
const runIdsDesc = keys.map((k) => runIdFromJsonlKey(k, dirPrefix)).filter((id) => id !== null).sort().reverse();
|
|
40194
|
-
const indexKey = deploymentEventsIndexKey(this.backend.prefix, stackName, region);
|
|
40195
|
-
const indexExisted = keys.includes(indexKey);
|
|
40196
|
-
if (opts.all === true) {
|
|
40197
|
-
const toDelete = runIdsDesc.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
|
|
40198
|
-
const earlierVersions = await deleteAndPurgeEventObjects(this.backend, [...toDelete, indexKey], dirPrefix, "whole-dir");
|
|
40199
|
-
return {
|
|
40200
|
-
deletedRunIds: runIdsDesc,
|
|
40201
|
-
remainingRunIds: [],
|
|
40202
|
-
indexDeleted: indexExisted,
|
|
40203
|
-
...earlierVersions !== void 0 && { earlierVersions }
|
|
40204
|
-
};
|
|
40205
|
-
}
|
|
40206
|
-
const noGuards = opts.keep === void 0 && opts.olderThanMs === void 0;
|
|
40207
|
-
const keep = opts.keep ?? (noGuards ? 20 : void 0);
|
|
40208
|
-
const protectedByCount = keep === void 0 ? /* @__PURE__ */ new Set() : new Set(runIdsDesc.slice(0, keep));
|
|
40209
|
-
let candidates = runIdsDesc.filter((id) => !protectedByCount.has(id));
|
|
40210
|
-
if (opts.olderThanMs !== void 0) {
|
|
40211
|
-
const cutoff = (opts.now ?? /* @__PURE__ */ new Date()).getTime() - opts.olderThanMs;
|
|
40212
|
-
candidates = candidates.filter((id) => {
|
|
40213
|
-
const t = runIdTimestampMs(id);
|
|
40214
|
-
return t !== null && t < cutoff;
|
|
40215
|
-
});
|
|
40216
|
-
}
|
|
40217
|
-
if (candidates.length === 0) return {
|
|
40218
|
-
deletedRunIds: [],
|
|
40219
|
-
remainingRunIds: runIdsDesc,
|
|
40220
|
-
indexDeleted: false
|
|
40221
|
-
};
|
|
40222
|
-
const deletedSet = new Set(candidates);
|
|
40223
|
-
const deleteKeys = candidates.map((id) => deploymentEventsKey(this.backend.prefix, stackName, region, id));
|
|
40224
|
-
const remainingRunIds = runIdsDesc.filter((id) => !deletedSet.has(id));
|
|
40225
|
-
if (remainingRunIds.length === 0) {
|
|
40226
|
-
await deleteAndPurgeEventObjects(this.backend, [...deleteKeys, indexKey], dirPrefix);
|
|
40227
|
-
return {
|
|
40228
|
-
deletedRunIds: candidates,
|
|
40229
|
-
remainingRunIds,
|
|
40230
|
-
indexDeleted: indexExisted
|
|
40231
|
-
};
|
|
40232
|
-
}
|
|
40233
|
-
await this.rewriteIndexAfterPrune(indexKey, stackName, region, deletedSet);
|
|
40234
|
-
await deleteAndPurgeEventObjects(this.backend, deleteKeys, dirPrefix);
|
|
40235
|
-
return {
|
|
40236
|
-
deletedRunIds: candidates,
|
|
40237
|
-
remainingRunIds,
|
|
40238
|
-
indexDeleted: false
|
|
40239
|
-
};
|
|
40240
|
-
}
|
|
40241
|
-
async rewriteIndexAfterPrune(indexKey, stackName, region, deletedRunIds) {
|
|
40242
|
-
let raw;
|
|
40243
|
-
try {
|
|
40244
|
-
raw = await this.backend.getRawObject(indexKey);
|
|
40245
|
-
} catch {
|
|
40246
|
-
return;
|
|
40247
|
-
}
|
|
40248
|
-
if (raw === null) return;
|
|
40249
|
-
let parsed;
|
|
40250
|
-
try {
|
|
40251
|
-
parsed = JSON.parse(raw);
|
|
40252
|
-
} catch {
|
|
40253
|
-
return;
|
|
40254
|
-
}
|
|
40255
|
-
if (!Array.isArray(parsed.runs)) return;
|
|
40256
|
-
const remaining = parsed.runs.filter((r) => !deletedRunIds.has(r.runId));
|
|
40257
|
-
if (remaining.length === parsed.runs.length) return;
|
|
40258
|
-
const file = {
|
|
40259
|
-
indexVersion: 1,
|
|
40260
|
-
stackName,
|
|
40261
|
-
region,
|
|
40262
|
-
runs: remaining,
|
|
40263
|
-
lastModified: Date.now()
|
|
40264
|
-
};
|
|
40265
|
-
await this.backend.putRawObject(indexKey, JSON.stringify(file, null, 2));
|
|
40266
|
-
}
|
|
40267
|
-
};
|
|
40268
|
-
|
|
40269
41220
|
//#endregion
|
|
40270
41221
|
//#region src/deployment/orphan-adoption.ts
|
|
40271
41222
|
function templateStillDeclares(template, record, nameProperties) {
|
|
@@ -40281,9 +41232,19 @@ async function planOrphanAdoption(params) {
|
|
|
40281
41232
|
adopted: {},
|
|
40282
41233
|
remaining: [],
|
|
40283
41234
|
refusals: [],
|
|
40284
|
-
notices: []
|
|
41235
|
+
notices: [],
|
|
41236
|
+
warnings: []
|
|
40285
41237
|
};
|
|
40286
41238
|
if (params.records.length === 0) return outcome;
|
|
41239
|
+
if (params.newScheme === true) {
|
|
41240
|
+
for (const record of params.records) {
|
|
41241
|
+
if (params.managedLogicalIds.has(record.logicalId)) continue;
|
|
41242
|
+
outcome.remaining.push(record);
|
|
41243
|
+
if ((params.template.Resources?.[record.logicalId])?.Type !== record.state.resourceType) continue;
|
|
41244
|
+
outcome.warnings.push(`${displayIdent(record.logicalId)} (${displayIdent(record.state.resourceType)}) was left in AWS by an earlier rollback as ${displaySafe(record.state.physicalId)} (DeletionPolicy: Retain). This deploy does not take it back: it creates a new resource under a new name, as CloudFormation does. To manage the kept resource again, adopt it with 'cdkd import'.`);
|
|
41245
|
+
}
|
|
41246
|
+
return outcome;
|
|
41247
|
+
}
|
|
40287
41248
|
let siblingClaims;
|
|
40288
41249
|
const claims = async () => siblingClaims ??= await params.readSiblingClaims();
|
|
40289
41250
|
for (const record of params.records) {
|
|
@@ -40473,9 +41434,11 @@ async function adoptRollbackOrphans(deps, currentState, effectiveTemplate) {
|
|
|
40473
41434
|
selfRegion: deps.stackRegion,
|
|
40474
41435
|
logger: deps.logger
|
|
40475
41436
|
}),
|
|
40476
|
-
logger: { debug: (m) => deps.logger.debug(m) }
|
|
41437
|
+
logger: { debug: (m) => deps.logger.debug(m) },
|
|
41438
|
+
newScheme: currentState.stackInstanceId !== void 0
|
|
40477
41439
|
}));
|
|
40478
41440
|
for (const notice of plan.notices) deps.logger.info(maskSecretsInText(notice, named));
|
|
41441
|
+
for (const warning of plan.warnings) deps.logger.warn(maskSecretsInText(warning, named));
|
|
40479
41442
|
const adoptedFrom = /* @__PURE__ */ new Map();
|
|
40480
41443
|
adoptedOrphanRecords.set(deps.owner, adoptedFrom);
|
|
40481
41444
|
if (plan.refusals.length > 0) throw new Error(safeMsg`Deploy refused — cdkd left ${plan.refusals.length} resource(s) in AWS that it cannot ` + "safely re-adopt:" + plan.refusals.map((r) => safeMsg`\n ${maskSecretsInText(r, named)}`).join(""));
|
|
@@ -40534,6 +41497,7 @@ async function performRollback(deps, completedOperations, stateResources, stackN
|
|
|
40534
41497
|
createdResourceHolder: crossPrefixHolder === void 0 ? void 0 : () => crossPrefixAnswer ??= crossPrefixHolder(stackName)
|
|
40535
41498
|
};
|
|
40536
41499
|
const inlinePolicyWriters = new RollbackInlinePolicyWriters();
|
|
41500
|
+
const supersededHost = {};
|
|
40537
41501
|
const runId = deps.options.eventRecorder?.runId;
|
|
40538
41502
|
const { result, failed, run } = await withNestedRevertRun(runId, async (scope) => {
|
|
40539
41503
|
return {
|
|
@@ -40546,7 +41510,10 @@ async function performRollback(deps, completedOperations, stateResources, stackN
|
|
|
40546
41510
|
})) : void 0,
|
|
40547
41511
|
result: await withPrintingSecrets(replayPrintingBag(deps, completedReplayEntries(completedOperations), stateResources), () => replayRollback(completedOperations, stateResources, stackName, ctx, {
|
|
40548
41512
|
inlinePolicyWriters,
|
|
40549
|
-
failedOperations
|
|
41513
|
+
failedOperations,
|
|
41514
|
+
isInterrupted: () => deps.userInterrupted(),
|
|
41515
|
+
onSuperseded: (entry) => addSuperseded(supersededHost, entry),
|
|
41516
|
+
onSupersededSettled: (entry) => removeSuperseded(supersededHost, entry)
|
|
40550
41517
|
})),
|
|
40551
41518
|
run: scope
|
|
40552
41519
|
};
|
|
@@ -40557,7 +41524,10 @@ async function performRollback(deps, completedOperations, stateResources, stackN
|
|
|
40557
41524
|
failures: result.failures + (failed?.failures ?? 0),
|
|
40558
41525
|
warnings: result.warnings + run.warnings + (failed?.warnings ?? 0),
|
|
40559
41526
|
skipped: result.skipped + (failed?.skipped ?? 0),
|
|
41527
|
+
interrupted: result.interrupted,
|
|
40560
41528
|
orphaned: [...failed?.orphaned ?? [], ...result.orphaned],
|
|
41529
|
+
rolledBackCreates: [...failed?.rolledBackCreates ?? [], ...result.rolledBackCreates],
|
|
41530
|
+
superseded: supersededHost.supersededResources ?? [],
|
|
40561
41531
|
settledNested: run.settled,
|
|
40562
41532
|
remainingFailedOps: failedOperations.filter((_, i) => !handled.has(i))
|
|
40563
41533
|
};
|
|
@@ -40600,9 +41570,11 @@ async function settleJournalAfterSuccess(deps, stackName, completedOperations, p
|
|
|
40600
41570
|
const own = await settleJournaledOrphansOnSuccess({
|
|
40601
41571
|
stateBackend: deps.stateBackend,
|
|
40602
41572
|
stackName,
|
|
41573
|
+
stackInstanceId: stackInstanceIdOf(previousState, displayStackName(stackName)),
|
|
40603
41574
|
region: deps.stackRegion,
|
|
40604
41575
|
stateResources: finalResources,
|
|
40605
41576
|
rollbackOrphans: previousState.orphans,
|
|
41577
|
+
retiredNameGenerations: previousState.retiredNameGenerations,
|
|
40606
41578
|
newerOperations: completedOperations,
|
|
40607
41579
|
...deployRunId !== void 0 && { deployRunId },
|
|
40608
41580
|
foreignHolder: foreignHolderFor({
|
|
@@ -40628,9 +41600,11 @@ async function settleJournalAfterSuccess(deps, stackName, completedOperations, p
|
|
|
40628
41600
|
const settled = await settleJournaledOrphansOnSuccess({
|
|
40629
41601
|
stateBackend: deps.stateBackend,
|
|
40630
41602
|
stackName: child,
|
|
41603
|
+
stackInstanceId: stackInstanceIdOf(childState, displayStackName(child)),
|
|
40631
41604
|
region: deps.stackRegion,
|
|
40632
41605
|
stateResources: childState?.resources,
|
|
40633
41606
|
rollbackOrphans: childState?.orphans,
|
|
41607
|
+
retiredNameGenerations: childState?.retiredNameGenerations,
|
|
40634
41608
|
newerOperations: [],
|
|
40635
41609
|
...deployRunId !== void 0 && { deployRunId },
|
|
40636
41610
|
foreignHolder: foreignHolderFor({
|
|
@@ -40786,58 +41760,6 @@ async function orphanUntakenResumes(deps, stackName, finalResources) {
|
|
|
40786
41760
|
}
|
|
40787
41761
|
}
|
|
40788
41762
|
|
|
40789
|
-
//#endregion
|
|
40790
|
-
//#region src/deployment/kept-in-history.ts
|
|
40791
|
-
function keptInEarlierRecords(records) {
|
|
40792
|
-
const out = [];
|
|
40793
|
-
for (const record of records) for (const [logicalId, raw] of Object.entries(record.resources)) {
|
|
40794
|
-
if (raw === null || typeof raw !== "object") continue;
|
|
40795
|
-
const r = raw;
|
|
40796
|
-
if (typeof r.resourceType !== "string" || typeof r.physicalId !== "string") continue;
|
|
40797
|
-
if (r.physicalId === "") continue;
|
|
40798
|
-
if (!shouldRetainResource(r.deletionPolicy)) continue;
|
|
40799
|
-
out.push({
|
|
40800
|
-
logicalId,
|
|
40801
|
-
resourceType: r.resourceType,
|
|
40802
|
-
physicalId: r.physicalId,
|
|
40803
|
-
...record.writtenAt !== void 0 && { keptAt: record.writtenAt }
|
|
40804
|
-
});
|
|
40805
|
-
}
|
|
40806
|
-
return out;
|
|
40807
|
-
}
|
|
40808
|
-
function keptInEventHistory(runs, stackName) {
|
|
40809
|
-
const made = /* @__PURE__ */ new Map();
|
|
40810
|
-
const out = [];
|
|
40811
|
-
for (const events of runs) for (const e of events) {
|
|
40812
|
-
if (e.stackName !== stackName || typeof e.logicalId !== "string") continue;
|
|
40813
|
-
if (typeof e.resourceType !== "string") continue;
|
|
40814
|
-
if (e.eventType === "RESOURCE_SUCCEEDED" && (e.operation === "CREATE" || e.operation === "UPDATE") && typeof e.physicalId === "string" && e.physicalId !== "") made.set(e.logicalId, {
|
|
40815
|
-
resourceType: e.resourceType,
|
|
40816
|
-
physicalId: e.physicalId
|
|
40817
|
-
});
|
|
40818
|
-
else if (e.eventType === "RESOURCE_RETAINED") {
|
|
40819
|
-
const m = made.get(e.logicalId);
|
|
40820
|
-
if (m !== void 0 && m.resourceType === e.resourceType) {
|
|
40821
|
-
const keptAt = Date.parse(e.timestamp);
|
|
40822
|
-
out.push({
|
|
40823
|
-
logicalId: e.logicalId,
|
|
40824
|
-
...m,
|
|
40825
|
-
...Number.isFinite(keptAt) && { keptAt }
|
|
40826
|
-
});
|
|
40827
|
-
}
|
|
40828
|
-
}
|
|
40829
|
-
}
|
|
40830
|
-
return out;
|
|
40831
|
-
}
|
|
40832
|
-
async function loadKeptInHistory(sources, stackName, region) {
|
|
40833
|
-
const runsOf = stackName.split("~")[0];
|
|
40834
|
-
const [records, runs] = await Promise.all([sources.earlierStateResources(stackName, region).catch(() => []), (async () => {
|
|
40835
|
-
const listed = (await sources.listRuns(runsOf, region)).slice(0, 20);
|
|
40836
|
-
return (await Promise.all(listed.map((r) => sources.readRunEvents(runsOf, region, r.runId).catch(() => null)))).filter((e) => e !== null).reverse();
|
|
40837
|
-
})().catch(() => [])]);
|
|
40838
|
-
return [...keptInEarlierRecords(records), ...keptInEventHistory(runs, stackName)];
|
|
40839
|
-
}
|
|
40840
|
-
|
|
40841
41763
|
//#endregion
|
|
40842
41764
|
//#region src/provisioning/canonicalize-properties.ts
|
|
40843
41765
|
function makeCanonicalizePropertiesFn(registry) {
|
|
@@ -42219,7 +43141,7 @@ async function requireDeploymentApproval(args) {
|
|
|
42219
43141
|
} catch (error) {
|
|
42220
43142
|
throw error instanceof Error ? markNonRetryable(error) : error;
|
|
42221
43143
|
}
|
|
42222
|
-
if (!approved) throw markNonRetryable(new
|
|
43144
|
+
if (!approved) throw markNonRetryable(new DeploymentNotApprovedError(safeMsg`Deployment of stack ${args.stackName} was not approved (--require-approval=${level}). Nothing was changed.`));
|
|
42223
43145
|
return approve.autoApproves !== true;
|
|
42224
43146
|
}
|
|
42225
43147
|
async function checkDestructivePlan(args) {
|
|
@@ -42276,7 +43198,7 @@ async function requireOutputsOnlyApproval(args) {
|
|
|
42276
43198
|
} catch (error) {
|
|
42277
43199
|
throw error instanceof Error ? markNonRetryable(error) : error;
|
|
42278
43200
|
}
|
|
42279
|
-
if (!approved) throw markNonRetryable(new
|
|
43201
|
+
if (!approved) throw markNonRetryable(new DeploymentNotApprovedError(safeMsg`Deployment of stack ${args.stackName} was not approved (--require-approval=any-change). Nothing was changed.`));
|
|
42280
43202
|
}
|
|
42281
43203
|
function isNoEchoPromotionOnly(change) {
|
|
42282
43204
|
return change.changeType === "UPDATE" && (change.attributeChanges?.length ?? 0) === 0 && (change.propertyChanges?.length ?? 0) > 0 && change.propertyChanges.every((pc) => pc.noEchoPromoted === true);
|
|
@@ -43280,60 +44202,10 @@ function peekRoutingForLabel(providerRegistry, options, change, existingState, s
|
|
|
43280
44202
|
}
|
|
43281
44203
|
return deriveLabelRouting(change, existingState, providerRegistry, isPinnedToCcApi(options, stackName, logicalId));
|
|
43282
44204
|
}
|
|
43283
|
-
function preparePropertiesForCcApi(providerRegistry, resourceType, resolvedProps, logicalId) {
|
|
44205
|
+
function preparePropertiesForCcApi(providerRegistry, resourceType, resolvedProps, logicalId, underivable = "refuse") {
|
|
43284
44206
|
const sdkProvider = providerRegistry.getRegisteredTypes().includes(resourceType) ? providerRegistry.getProvider(resourceType) : void 0;
|
|
43285
44207
|
if (sdkProvider?.preparePropertiesForFallback) return sdkProvider.preparePropertiesForFallback(logicalId, resourceType, resolvedProps);
|
|
43286
|
-
return applyDefaultNameForFallback(logicalId, resourceType, resolvedProps);
|
|
43287
|
-
}
|
|
43288
|
-
|
|
43289
|
-
//#endregion
|
|
43290
|
-
//#region src/deployment/deploy-engine/name-collision.ts
|
|
43291
|
-
function replacementNameOrigin(logicalId, physicalId) {
|
|
43292
|
-
if (looksLikeCdkdGeneratedName(physicalId, logicalId, getCurrentStackName())) return {
|
|
43293
|
-
descriptor: `The physical name (${physicalId}) was GENERATED by cdkd from the construct's logical id rather than declared in your template, and that derivation has no random component — so the new resource asks for exactly the name the existing one still holds`,
|
|
43294
|
-
remedy: "Either give the resource an explicit physical name in your CDK code, or rename the CONSTRUCT (its id feeds the generated name — note that this replaces the resource rather than renaming it in place)"
|
|
43295
|
-
};
|
|
43296
|
-
return {
|
|
43297
|
-
descriptor: `The resource has a user-supplied physical name (${physicalId})`,
|
|
43298
|
-
remedy: "Either rename the resource in your CDK code (a fresh name lets the safe create-first order proceed)"
|
|
43299
|
-
};
|
|
43300
|
-
}
|
|
43301
|
-
function orphanedNameCollisionAdvice(providerRegistry, changeType, logicalId, error) {
|
|
43302
|
-
if (changeType !== "CREATE") return void 0;
|
|
43303
|
-
if (!(error instanceof ProvisioningError)) return void 0;
|
|
43304
|
-
const physicalId = error.physicalId;
|
|
43305
|
-
if (!physicalId) return void 0;
|
|
43306
|
-
const replayed = isReplayedNameCollisionFrom(error, logicalId, (link) => isAuxiliaryMarkOf(link, RETRY_AUXILIARY_OWNER));
|
|
43307
|
-
if (!replayed && !isNameCollisionErrorFrom(error, logicalId)) return void 0;
|
|
43308
|
-
const stackName = getCurrentStackName();
|
|
43309
|
-
if (!looksLikeCdkdGeneratedName(physicalId, logicalId, stackName)) return void 0;
|
|
43310
|
-
if (!stackName) return void 0;
|
|
43311
|
-
const safeId = displaySafe(physicalId, { asciiOnly: true });
|
|
43312
|
-
const safeStack = displaySafe(stackName, { asciiOnly: true });
|
|
43313
|
-
const safeLogicalId = displaySafe(logicalId, { asciiOnly: true });
|
|
43314
|
-
const idShown = isInertUnquoted(safeId);
|
|
43315
|
-
const shownId = idShown ? safeId : "a name that cannot be shown safely here";
|
|
43316
|
-
const shownLogicalId = isInertUnquoted(safeLogicalId) ? safeLogicalId : "A resource whose logical id cannot be shown safely here";
|
|
43317
|
-
const diagnosis = replayed ? `${shownLogicalId}: the name AWS reports as taken (${shownId}) is most likely held by a resource THIS create made. An earlier attempt of it ended without a clear verdict (a server error, a dropped connection or a timeout, or a failure after the create call itself may have succeeded), and the retry then found the name taken. A dropped connection can also happen before the request reached AWS, so the holder may be another resource: confirm it is yours before deleting or importing it. cdkd records a resource only once its create succeeds, so this one is in no state file: no rollback or cdkd destroy will remove it, and re-running collides with it again.` : `${shownLogicalId}: the name AWS reports as taken (${shownId}) is one cdkd DERIVED from the logical id, and that derivation has no random component — so this is most likely a resource an earlier cdkd run left behind. A rollback leaves a resource carrying DeletionPolicy: Retain in AWS and drops it from state, as CloudFormation does; what differs is the name. CloudFormation would generate a fresh one for an unnamed resource and redeploy clean, whereas cdkd asks again for the name the orphan still holds — so re-running does not clear this.`;
|
|
43318
|
-
const deleteArm = `If it is not a resource you want to keep, delete ${idShown ? safeId : "it"} in AWS — after confirming it holds nothing you need${replayed ? "" : ", since Retain is what kept it"} — and re-deploy.`;
|
|
43319
|
-
let canImport;
|
|
43320
|
-
try {
|
|
43321
|
-
canImport = typeof providerRegistry.getProvider(error.resourceType).import === "function";
|
|
43322
|
-
} catch {
|
|
43323
|
-
canImport = false;
|
|
43324
|
-
}
|
|
43325
|
-
const commandNamesTheRightResource = safeId === physicalId && safeStack === stackName && safeLogicalId === logicalId;
|
|
43326
|
-
const importableTarget = !stackName.includes("~");
|
|
43327
|
-
if (!canImport || !commandNamesTheRightResource || !importableTarget) return `${diagnosis} ${!canImport ? `cdkd cannot adopt ${displaySafe(error.resourceType, { asciiOnly: true })} back into state (its provider implements no import)` : !importableTarget ? `this is a nested-stack child, whose stack name cdkd import cannot resolve` : `cdkd cannot render an import command that provably names this resource`}, so the way forward is to delete it. ${deleteArm}`;
|
|
43328
|
-
const adopt = pasteableCommand("cdkd import", [{
|
|
43329
|
-
value: stackName,
|
|
43330
|
-
hole: "stack"
|
|
43331
|
-
}, {
|
|
43332
|
-
flag: "--resource",
|
|
43333
|
-
value: `${logicalId}=${physicalId}`,
|
|
43334
|
-
hole: "logicalId=physicalId"
|
|
43335
|
-
}]);
|
|
43336
|
-
return `${diagnosis} To recover, adopt it back into state instead of re-creating it, with the command below (a selective import merges into existing state and needs no --force while the resource is absent from it). CONFIRM IT IS YOURS FIRST — a name cdkd derives is predictable, so for a globally-namespaced type it can belong to another account, and the same stack deployed in another region derives the same name. ${deleteArm}${adopt.withheld.length === 0 ? "" : " The command below prints a quoted hole in place of a value cdkd will not name on a command line; replace it whole, quotes included, with your stack name or '<logicalId>=<name>', shell-quoted."}\nAdopt with: ${adopt.command}`;
|
|
44208
|
+
return applyDefaultNameForFallback(logicalId, resourceType, resolvedProps, underivable);
|
|
43337
44209
|
}
|
|
43338
44210
|
|
|
43339
44211
|
//#endregion
|
|
@@ -43510,6 +44382,7 @@ async function provisionCreate(engine, logicalId, change, stateResources, stackN
|
|
|
43510
44382
|
const recordedProperties = propertiesToRecord(resolvedProps, result, resourceType, createDecision.provisionedBy);
|
|
43511
44383
|
stateResources[logicalId] = {
|
|
43512
44384
|
physicalId: result.physicalId,
|
|
44385
|
+
...getCurrentStackInstanceId() !== void 0 && nameGenerationField(currentNameGeneration(logicalId) ?? 0),
|
|
43513
44386
|
resourceType,
|
|
43514
44387
|
properties: recordedProperties,
|
|
43515
44388
|
...acceptedCreateOnlyDropsField(recordedProperties, resourceType, createDecision.provisionedBy, "new-resource"),
|
|
@@ -43536,6 +44409,21 @@ async function provisionCreate(engine, logicalId, change, stateResources, stackN
|
|
|
43536
44409
|
renderer.removeTask(logicalId);
|
|
43537
44410
|
engine.logger.info(safeMsg`${createPrefix}${formatResourceLine("created", logicalId, resourceType)}`);
|
|
43538
44411
|
}
|
|
44412
|
+
async function guardedReplacementCreate(engine, input, create) {
|
|
44413
|
+
const guard = engine.generatedNameGuard;
|
|
44414
|
+
if (input.keepsName === true || guard?.candidate(input.logicalId) === void 0) return create();
|
|
44415
|
+
await refuseUnlicensedGeneratedName(engine, input);
|
|
44416
|
+
guard.noteSent(input.logicalId);
|
|
44417
|
+
let result;
|
|
44418
|
+
try {
|
|
44419
|
+
result = await create();
|
|
44420
|
+
} catch (error) {
|
|
44421
|
+
guard.noteFailed(input.logicalId, error);
|
|
44422
|
+
throw error;
|
|
44423
|
+
}
|
|
44424
|
+
guard.noteReturned(input.logicalId);
|
|
44425
|
+
return result;
|
|
44426
|
+
}
|
|
43539
44427
|
async function refuseUnlicensedGeneratedName(engine, input) {
|
|
43540
44428
|
const { logicalId, resourceType } = input;
|
|
43541
44429
|
const asked = engine.generatedNameGuard?.candidate(logicalId);
|
|
@@ -44021,7 +44909,7 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
44021
44909
|
const warn = log.warn;
|
|
44022
44910
|
log.debug(`Creating DynamoDB GlobalTable ${logicalId}`);
|
|
44023
44911
|
const desiredReplicaTags = refuseMalformedReplicaTags(properties, resourceType, logicalId);
|
|
44024
|
-
const tableName = properties["TableName"] ||
|
|
44912
|
+
const tableName = properties["TableName"] || generatedNameFor("AWS::DynamoDB::GlobalTable", logicalId);
|
|
44025
44913
|
const keySchema = properties["KeySchema"];
|
|
44026
44914
|
const attributeDefinitions = properties["AttributeDefinitions"];
|
|
44027
44915
|
if (!keySchema) throw new ProvisioningError(`KeySchema is required for DynamoDB GlobalTable ${logicalId}`, resourceType, logicalId);
|
|
@@ -46465,7 +47353,7 @@ function recordedProtectionNote(evidence, flags) {
|
|
|
46465
47353
|
|
|
46466
47354
|
//#endregion
|
|
46467
47355
|
//#region src/deployment/deploy-engine/update-replace.ts
|
|
46468
|
-
async function updateByReplacement(engine, { change, counts, currentProps, currentResource, dependencies, logicalId, oldResourceType, progress, propertyDrivenReplacement, recreateFlagged, recreateViaCcApi, recreateViaSdkProvider, renderer, resolvedProps, resourceType, stackName, stateResources, template, typeChanged, updateReplacePolicy, updateSecrets, lostWithParent }) {
|
|
47356
|
+
async function updateByReplacement(engine, { change, counts, currentProps, currentResource, dependencies, logicalId, oldResourceType, progress, propertyDrivenReplacement, recreateFlagged, recreateViaCcApi, recreateViaSdkProvider, renderer, resolvedProps, resourceType, stackName, stateResources, template, typeChanged, updateReplacePolicy, updateSecrets, lostWithParent, nameGenerationFields }) {
|
|
46469
47357
|
const noEchoDeleteValues = await noEchoDeleteValuesFromResolved({
|
|
46470
47358
|
record: currentResource,
|
|
46471
47359
|
templateResource: template?.Resources?.[logicalId],
|
|
@@ -46540,6 +47428,9 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46540
47428
|
}
|
|
46541
47429
|
createResult = await createFirstThenDeleteOld(engine.replacementRun, engine.replacementDeps(), {
|
|
46542
47430
|
retainOld,
|
|
47431
|
+
stackName,
|
|
47432
|
+
createdVia: replaceDecision.provisionedBy,
|
|
47433
|
+
resolvedProps,
|
|
46543
47434
|
logicalId,
|
|
46544
47435
|
resourceType,
|
|
46545
47436
|
oldResourceType,
|
|
@@ -46591,17 +47482,27 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46591
47482
|
if (recreateSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, recreateSkipReason, `during ${recreateFlagName}`));
|
|
46592
47483
|
engine.logger.info(safeMsg` ${green("✓")} Old resource deleted`);
|
|
46593
47484
|
engine.replacementRun.oldDeletedBeforeCreate.add(logicalId);
|
|
47485
|
+
await oldDeleteProvider.waitForNameReleased?.(logicalId, currentResource.physicalId, oldResourceType, {
|
|
47486
|
+
isInterrupted: () => engine.userInterrupted,
|
|
47487
|
+
maskSecrets: createSecretMasker(updateSecrets)
|
|
47488
|
+
});
|
|
46594
47489
|
}
|
|
46595
47490
|
engine.logger.info(safeMsg` Creating new ${logicalId}...`);
|
|
46596
|
-
createResult = await
|
|
47491
|
+
createResult = await guardedReplacementCreate(engine, {
|
|
47492
|
+
logicalId,
|
|
47493
|
+
resourceType,
|
|
47494
|
+
stackName,
|
|
47495
|
+
createdVia: replaceDecision.provisionedBy,
|
|
47496
|
+
resolvedProps
|
|
47497
|
+
}, () => withRetry(() => engine.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => replaceProvider.create(logicalId, resourceType, replaceProps, { maskSecrets: createSecretMasker(updateSecrets) })), logicalId, void 0, void 0, replaceProvider, true), logicalId, {
|
|
46597
47498
|
maxRetries: 8,
|
|
46598
47499
|
initialDelayMs: 2e3,
|
|
46599
47500
|
maxDelayMs: 1e4,
|
|
46600
47501
|
logger: engine.maskingRetryLoggerFor(updateSecrets),
|
|
46601
|
-
isInterrupted: () => engine.
|
|
46602
|
-
onInterrupted: () => new InterruptedError(
|
|
47502
|
+
isInterrupted: () => engine.userInterrupted,
|
|
47503
|
+
onInterrupted: () => new InterruptedError("user"),
|
|
46603
47504
|
isRetryable: isRecreateRetryableError
|
|
46604
|
-
});
|
|
47505
|
+
}));
|
|
46605
47506
|
if (equalIdIsSameResource && updateReplacePolicy === "Retain" && createResult.physicalId === currentResource.physicalId) throw new CdkdError(safeMsg`${logicalId} (${resourceType}) recreate returned the existing resource ` + safeMsg`(${currentResource.physicalId}) instead of creating a new one — its Create ` + "API is name-idempotent — and UpdateReplacePolicy: Retain means the old resource was never destroyed, so the new properties were not applied. Rename the resource in your CDK code (or remove the explicit physical name) so the recreate can produce a genuinely new resource.", "NAMED_REPLACEMENT_IDEMPOTENT_CREATE");
|
|
46606
47507
|
} else {
|
|
46607
47508
|
engine.logger.info(safeMsg` Creating new ${logicalId}...`);
|
|
@@ -46611,7 +47512,14 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46611
47512
|
engine.logger.info(safeMsg` ${logicalId} went with ${lostWithParent}, which was destroyed and re-created under the same id: re-creating it`);
|
|
46612
47513
|
}
|
|
46613
47514
|
try {
|
|
46614
|
-
createResult = await engine
|
|
47515
|
+
createResult = await guardedReplacementCreate(engine, {
|
|
47516
|
+
logicalId,
|
|
47517
|
+
resourceType,
|
|
47518
|
+
stackName,
|
|
47519
|
+
createdVia: replaceDecision.provisionedBy,
|
|
47520
|
+
resolvedProps,
|
|
47521
|
+
keepsName: lostWithParent !== void 0
|
|
47522
|
+
}, () => engine.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => replaceProvider.create(logicalId, resourceType, replaceProps, { maskSecrets: createSecretMasker(updateSecrets) })), logicalId, void 0, void 0, replaceProvider, lostWithParent !== void 0));
|
|
46615
47523
|
} catch (createError) {
|
|
46616
47524
|
const createMsg = displayAwsMessage(maskSecretsInText(describeAwsFailure(createError).detail, updateSecrets));
|
|
46617
47525
|
const createSentence = createMsg.endsWith(".") ? createMsg.slice(0, -1) : createMsg;
|
|
@@ -46630,7 +47538,7 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46630
47538
|
createType: resourceType,
|
|
46631
47539
|
holderType: oldResourceType,
|
|
46632
47540
|
requested: replaceProps,
|
|
46633
|
-
generated: applyDefaultNameForFallback(logicalId, resourceType, resolvedProps),
|
|
47541
|
+
generated: applyDefaultNameForFallback(logicalId, resourceType, resolvedProps, "omit"),
|
|
46634
47542
|
recorded: currentResource.properties,
|
|
46635
47543
|
observed: currentResource.observedProperties,
|
|
46636
47544
|
physicalId: currentResource.physicalId,
|
|
@@ -46641,7 +47549,13 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46641
47549
|
});
|
|
46642
47550
|
if (!holder.holds) {
|
|
46643
47551
|
const flagClause = engine.options.replace === true ? ` --replace was NOT applied and nothing was deleted.` : updateReplacePolicy === "Retain" ? " Nothing was deleted. UpdateReplacePolicy: Retain keeps the resource being replaced in place; removing it and re-running with `cdkd deploy --replace` would refuse the same way rather than delete it." : " Nothing was deleted, and `cdkd deploy --replace` would refuse the same way rather than delete it.";
|
|
46644
|
-
throw markNonRetryable(new CdkdError(maskSecretsInText(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement, but the create-first attempt collided: ${holder.diagnosis} — ` + (holder.known ? "so another resource holds the colliding name (an orphan of an earlier attempt, or one made outside this stack), and deleting the resource being replaced would destroy it and collide again." + flagClause + " Remove or rename the resource holding that name if it is yours, then re-run the deploy." : "so if another resource holds it (an orphan of an earlier attempt, or one made outside this stack), deleting the resource being replaced would destroy it and collide again." + flagClause + " Remove or rename whatever holds that name if it is yours — if that is the resource being replaced itself, delete it by hand — then re-run the deploy.") +
|
|
47552
|
+
throw markNonRetryable(new CdkdError(maskSecretsInText(`${displaySafe(logicalId)} (${displaySafe(resourceType)}) requires replacement, but the create-first attempt collided: ${holder.diagnosis} — ` + (holder.known ? "so another resource holds the colliding name (an orphan of an earlier attempt, or one made outside this stack), and deleting the resource being replaced would destroy it and collide again." + flagClause + " Remove or rename the resource holding that name if it is yours, then re-run the deploy." : "so if another resource holds it (an orphan of an earlier attempt, or one made outside this stack), deleting the resource being replaced would destroy it and collide again." + flagClause + " Remove or rename whatever holds that name if it is yours — if that is the resource being replaced itself, delete it by hand — then re-run the deploy.") + generatedReplacementHolderAdvice({
|
|
47553
|
+
stackName,
|
|
47554
|
+
logicalId,
|
|
47555
|
+
change: nameChange,
|
|
47556
|
+
oldPhysicalId: currentResource.physicalId,
|
|
47557
|
+
mask: (value) => maskSecretsInText(value, unionOfSecretBags([updateSecrets, printingSecretsFor(engine.secretsRun, logicalId)]))
|
|
47558
|
+
}) + ` Underlying collision: ${createMsg}`, updateSecrets), "NAMED_REPLACEMENT_COLLISION", createError instanceof Error ? createError : void 0));
|
|
46645
47559
|
}
|
|
46646
47560
|
if (updateReplacePolicy === "Retain") throw new CdkdError(safeMsg`${logicalId} (${resourceType}) requires replacement, but its physical name ` + `is still held by the existing resource AND UpdateReplacePolicy: Retain ` + safeMsg`pins that resource in place. ${nameOrigin.descriptor}. ` + safeMsg`${nameOrigin.remedy} — with Retain, the old resource keeps the name, so a ` + `same-name replacement can never proceed.`, "NAMED_REPLACEMENT_COLLISION");
|
|
46647
47561
|
if (engine.options.replace !== true) throw new CdkdError(safeMsg`${logicalId} (${resourceType}) requires replacement, but the create-first ` + safeMsg`attempt collided with the existing resource: ${createSentence}. ` + safeMsg`${nameOrigin.descriptor}, so the CloudFormation-style safe replacement ` + "order (create the new resource before deleting the old) cannot reuse the occupied name — CloudFormation refuses this shape with \"cannot update a stack when a custom-named resource requires replacing\". " + safeMsg`${nameOrigin.remedy}, or re-run with \`cdkd deploy --replace\` to delete ` + "the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated).", "NAMED_REPLACEMENT_COLLISION");
|
|
@@ -46681,6 +47595,7 @@ async function updateByReplacement(engine, { change, counts, currentProps, curre
|
|
|
46681
47595
|
const recordedReplacementProperties = propertiesToRecord(resolvedProps, createResult, resourceType, replaceDecision.provisionedBy);
|
|
46682
47596
|
stateResources[logicalId] = {
|
|
46683
47597
|
physicalId: createResult.physicalId,
|
|
47598
|
+
...nameGenerationFields,
|
|
46684
47599
|
resourceType,
|
|
46685
47600
|
properties: recordedReplacementProperties,
|
|
46686
47601
|
...acceptedCreateOnlyDropsField(recordedReplacementProperties, resourceType, replaceDecision.provisionedBy, "new-resource"),
|
|
@@ -46724,7 +47639,7 @@ function ccAutoRouteUpdateFailureRemedy(logicalId, resourceType, autoRoutedPrope
|
|
|
46724
47639
|
|
|
46725
47640
|
//#endregion
|
|
46726
47641
|
//#region src/deployment/deploy-engine/update-in-place.ts
|
|
46727
|
-
async function updateInPlace(engine, { conditions, counts, currentProps, currentPropsAsWritten, currentResource, dependencies, desiredForSkipCheckAsWritten, logicalId, noEchoHeldPaths, parameterValues, progress, renderer, resolvedProps, resourceType, stackName, stateResources, template, updateReplacePolicy, updateSecrets, reattach }) {
|
|
47642
|
+
async function updateInPlace(engine, { changedProperties, conditions, counts, currentProps, currentPropsAsWritten, currentResource, dependencies, desiredForSkipCheckAsWritten, logicalId, noEchoHeldPaths, parameterValues, progress, renderer, resolvedProps, resourceType, stackName, stateResources, template, updateReplacePolicy, updateSecrets, reattach }) {
|
|
46728
47643
|
engine.logger.debug(safeMsg`Updating ${logicalId} (${resourceType})`);
|
|
46729
47644
|
const updateDecision = engine.providerRegistry.getProviderFor({
|
|
46730
47645
|
resourceType,
|
|
@@ -46749,11 +47664,12 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46749
47664
|
engine.logger.info(message);
|
|
46750
47665
|
}
|
|
46751
47666
|
const updateProvider = updateDecision.provider;
|
|
46752
|
-
const updateProps = updateDecision.provisionedBy === "cc-api" ? withoutGeneratedFallbackName(resourceType, resolvedProps, preparePropertiesForCcApi(engine.providerRegistry, resourceType, resolvedProps, logicalId)) : resolvedProps;
|
|
46753
|
-
const
|
|
47667
|
+
const updateProps = updateDecision.provisionedBy === "cc-api" ? withoutGeneratedFallbackName(resourceType, resolvedProps, preparePropertiesForCcApi(engine.providerRegistry, resourceType, resolvedProps, logicalId, "omit")) : resolvedProps;
|
|
47668
|
+
const previousWithNoEchoHeld = noEchoHeldPaths.size === 0 ? currentPropsAsWritten : {
|
|
46754
47669
|
...currentPropsAsWritten,
|
|
46755
47670
|
...Object.fromEntries([...noEchoHeldPaths].filter((path) => Object.prototype.hasOwnProperty.call(updateProps, path)).map((path) => [path, updateProps[path]]))
|
|
46756
|
-
}
|
|
47671
|
+
};
|
|
47672
|
+
const { previous: previousWithSecretsDropped, dropped: droppedPrincipalKinds } = withUnchangedSecretPrincipalLists(resourceType, currentResource.physicalId, previousWithNoEchoHeld, desiredForSkipCheckAsWritten);
|
|
46757
47673
|
const reattached = reattach === true ? withRecreatedAttachmentsDropped({
|
|
46758
47674
|
resourceType,
|
|
46759
47675
|
templateProperties: template?.Resources?.[logicalId]?.Properties,
|
|
@@ -46763,6 +47679,9 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46763
47679
|
conditions
|
|
46764
47680
|
}) : void 0;
|
|
46765
47681
|
const previousForUpdate = reattached?.previous ?? previousWithSecretsDropped;
|
|
47682
|
+
const changedForProvider = new Set(changedProperties);
|
|
47683
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(previousWithNoEchoHeld), ...Object.keys(previousForUpdate)])) if (keyOrderFreeJson(previousForUpdate[key]) !== keyOrderFreeJson(previousWithNoEchoHeld[key])) changedForProvider.add(key);
|
|
47684
|
+
if (changedForProvider.size === 0) for (const key of /* @__PURE__ */ new Set([...Object.keys(updateProps), ...Object.keys(previousForUpdate)])) changedForProvider.add(key);
|
|
46766
47685
|
if (reattached !== void 0) engine.logger.info(safeMsg` ${logicalId} (${resourceType}) lost its attachment to ${reattached.parents.join(", ")}, which this deploy re-created under the same name: attaching it again`);
|
|
46767
47686
|
if (droppedPrincipalKinds.length > 0) {
|
|
46768
47687
|
const kinds = droppedPrincipalKinds.join(" / ");
|
|
@@ -46772,6 +47691,7 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46772
47691
|
let result;
|
|
46773
47692
|
let resultProvisionedBy = updateDecision.provisionedBy;
|
|
46774
47693
|
let captureProvider = updateProvider;
|
|
47694
|
+
let replacedAtGeneration;
|
|
46775
47695
|
const inlinePolicyClaimed = engine.inlinePolicyClaimedFor(resourceType, logicalId, stateResources);
|
|
46776
47696
|
try {
|
|
46777
47697
|
result = await engine.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => updateProvider.update(logicalId, currentResource.physicalId, resourceType, removal.properties, previousForUpdate, {
|
|
@@ -46779,7 +47699,8 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46779
47699
|
expectedRegion: engine.stackRegion,
|
|
46780
47700
|
recordedAttributes: currentResource.attributes,
|
|
46781
47701
|
...inlinePolicyClaimed && { inlinePolicyClaimed },
|
|
46782
|
-
...removal.context
|
|
47702
|
+
...removal.context,
|
|
47703
|
+
changedProperties: changedForProvider
|
|
46783
47704
|
})), logicalId, void 0, void 0, updateProvider);
|
|
46784
47705
|
if (result.sentNothing === true) engine.replacementRun.updatesThatSentNothing.add(logicalId);
|
|
46785
47706
|
if (result.wasReplaced === true && result.outcome === "partial") engine.replacementRun.replacedOldMaySurvive.set(logicalId, result.oldResourceSurvivor === "kept" ? "kept" : "unconfirmed");
|
|
@@ -46789,153 +47710,181 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46789
47710
|
const ccUnsupported = isUpdateUnsupportedError(updateError, logicalId);
|
|
46790
47711
|
const replaceOptIn = updateError instanceof ResourceUpdateNotSupportedError && engine.options.replace === true;
|
|
46791
47712
|
if (ccUnsupported || replaceOptIn) {
|
|
46792
|
-
const
|
|
46793
|
-
const
|
|
46794
|
-
if (
|
|
46795
|
-
|
|
46796
|
-
|
|
46797
|
-
|
|
46798
|
-
|
|
46799
|
-
|
|
46800
|
-
|
|
46801
|
-
previousProperties: currentResource.properties
|
|
46802
|
-
});
|
|
46803
|
-
const replProvider = replDecision.provider;
|
|
46804
|
-
const replProps = replDecision.provisionedBy === "cc-api" ? preparePropertiesForCcApi(engine.providerRegistry, resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
46805
|
-
const fallbackNameChange = await checkedReplacementNameChange(engine.replacementDeps(), {
|
|
46806
|
-
logicalId,
|
|
46807
|
-
resourceType,
|
|
46808
|
-
oldResourceType: resourceType,
|
|
46809
|
-
stackName,
|
|
46810
|
-
currentResource,
|
|
46811
|
-
desiredProperties: resolvedProps,
|
|
46812
|
-
createProvider: replProvider,
|
|
46813
|
-
createdVia: replDecision.provisionedBy,
|
|
46814
|
-
createProps: replProps,
|
|
46815
|
-
secrets: updateSecrets
|
|
46816
|
-
});
|
|
46817
|
-
const createFirst = !retainOldOnReplace && fallbackNameChange !== void 0;
|
|
46818
|
-
const noEchoDeleteValues = await noEchoDeleteValuesFromResolved({
|
|
46819
|
-
record: currentResource,
|
|
46820
|
-
templateResource: template?.Resources?.[logicalId],
|
|
46821
|
-
resolvedProperties: resolvedProps,
|
|
46822
|
-
noEchoParameters: noEchoPositionSources(engine.noEchoRun, stateResources, template)?.parameters ?? /* @__PURE__ */ new Set(),
|
|
46823
|
-
conditions: engine.noEchoRun.noEchoConditions,
|
|
46824
|
-
secrets: updateSecrets,
|
|
46825
|
-
inputSources: template && maskedInputSources(engine.resolverContextDeps(), template, stateResources, engine.noEchoRun.noEchoConditions, stackName)
|
|
46826
|
-
});
|
|
46827
|
-
engine.logger.info(retainOldOnReplace ? safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing ` + `(CREATE only — UpdateReplacePolicy: Retain keeps the old resource)` : createFirst ? safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing (CREATE → DELETE — the new name differs from the old resource's)` : safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing (DELETE → CREATE)`);
|
|
46828
|
-
if (retainOldOnReplace) await noteRetainedResource(resourceType, logicalId);
|
|
46829
|
-
if (!retainOldOnReplace && !createFirst) {
|
|
46830
|
-
const fallbackUpdateReplacePolicy = template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy;
|
|
46831
|
-
const fallbackFinalSnapshotId = await prepareFinalSnapshotForDelete(engine.replacementDeps(), logicalId, resourceType, currentResource, fallbackUpdateReplacePolicy);
|
|
46832
|
-
let fallbackDeleteResult = void 0;
|
|
46833
|
-
try {
|
|
46834
|
-
fallbackDeleteResult = await withPrintingSecrets(updateSecrets, () => updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
|
|
46835
|
-
expectedRegion: engine.stackRegion,
|
|
46836
|
-
forceDataDelete: engine.options.forceStatefulRecreation === true,
|
|
46837
|
-
...fallbackFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: fallbackFinalSnapshotId },
|
|
46838
|
-
...replacementDeleteContext(engine.replacementDeps(), fallbackUpdateReplacePolicy),
|
|
46839
|
-
recordedAttributes: currentResource.attributes,
|
|
46840
|
-
recordedNoEchoLeaves: currentResource.noEchoLeaves,
|
|
46841
|
-
...noEchoDeleteValues !== void 0 && { noEchoDeleteValues },
|
|
46842
|
-
maskSecrets: createUnionSecretMasker([updateSecrets, secretNameBagFor(engine.secretsRun, logicalId)])
|
|
46843
|
-
}));
|
|
46844
|
-
} catch (deleteError) {
|
|
46845
|
-
const deleteMsg = describeAwsFailure(deleteError).detail;
|
|
46846
|
-
if (!isWaitAbandonedError(deleteError) && !isInterruptedWaitError(deleteError) && !isMarkedNonRetryable(deleteError) && (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound"))) engine.logger.debug(safeMsg`Old resource ${logicalId} already gone, proceeding with CREATE`);
|
|
46847
|
-
else throw deleteError;
|
|
47713
|
+
const fallbackStackInstanceId = getCurrentStackInstanceId();
|
|
47714
|
+
const fallbackGeneration = fallbackStackInstanceId === void 0 ? void 0 : nextNameGeneration(currentResource, logicalId, fallbackStackInstanceId);
|
|
47715
|
+
if (fallbackGeneration !== void 0) engine.replacementRun.attemptedNameGeneration.set(logicalId, fallbackGeneration);
|
|
47716
|
+
const replaceFallback = async () => {
|
|
47717
|
+
const retainOldOnReplace = updateReplacePolicy === "Retain";
|
|
47718
|
+
const statefulReason = retainOldOnReplace ? null : isStatefulRecreateTargetForReplace(resourceType, currentProps, currentResource.observedProperties);
|
|
47719
|
+
if (statefulReason && engine.options.forceStatefulRecreation !== true) {
|
|
47720
|
+
const protection = recordedProtectionEvidence(resourceType, currentProps, currentResource.observedProperties, engine.stackRegion);
|
|
47721
|
+
throw markNonRetryable(new CdkdError(replaceOptIn ? safeMsg`--replace would DELETE + CREATE the stateful resource ${logicalId} ` + safeMsg`(${resourceType}) — ${renderStatefulReason(statefulReason)}. ` + (protection ? safeMsg`${recordedProtectionNote(protection, "--replace --force-stateful-recreation")} ` + `Or change the resource's definition to avoid the immutable-property change.` : "Re-run with --force-stateful-recreation to confirm the data loss, or change the resource definition to avoid the immutable-property change.") : safeMsg`${logicalId} (${resourceType}) cannot be updated in place by the ` + "provisioning layer it routes through, so applying this change would DELETE + CREATE it — but it is a stateful resource: " + safeMsg`${renderStatefulReason(statefulReason)}. ` + (protection ? safeMsg`${recordedProtectionNote(protection, "--force-stateful-recreation")} ` + `Or change the resource's definition to avoid the update.` : "Re-run with --force-stateful-recreation to confirm the data loss, or change the resource definition to avoid the update."), "STATEFUL_REPLACE_BLOCKED", updateError instanceof Error ? updateError : void 0));
|
|
46848
47722
|
}
|
|
46849
|
-
|
|
46850
|
-
physicalId: currentResource.physicalId,
|
|
47723
|
+
const replDecision = engine.providerRegistry.getProviderFor({
|
|
46851
47724
|
resourceType,
|
|
46852
|
-
|
|
47725
|
+
properties: resolvedProps,
|
|
47726
|
+
previousProperties: currentResource.properties
|
|
46853
47727
|
});
|
|
46854
|
-
const
|
|
46855
|
-
|
|
46856
|
-
engine.
|
|
46857
|
-
}
|
|
46858
|
-
let retainedSurvivorReason;
|
|
46859
|
-
let createResult;
|
|
46860
|
-
try {
|
|
46861
|
-
createResult = createFirst && fallbackNameChange !== void 0 ? await createFirstThenDeleteOld(engine.replacementRun, engine.replacementDeps(), {
|
|
47728
|
+
const replProvider = replDecision.provider;
|
|
47729
|
+
const replProps = replDecision.provisionedBy === "cc-api" ? preparePropertiesForCcApi(engine.providerRegistry, resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
47730
|
+
const fallbackNameChange = await checkedReplacementNameChange(engine.replacementDeps(), {
|
|
46862
47731
|
logicalId,
|
|
46863
47732
|
resourceType,
|
|
46864
47733
|
oldResourceType: resourceType,
|
|
47734
|
+
stackName,
|
|
46865
47735
|
currentResource,
|
|
47736
|
+
desiredProperties: resolvedProps,
|
|
46866
47737
|
createProvider: replProvider,
|
|
47738
|
+
createdVia: replDecision.provisionedBy,
|
|
46867
47739
|
createProps: replProps,
|
|
46868
|
-
|
|
46869
|
-
|
|
46870
|
-
|
|
47740
|
+
secrets: updateSecrets
|
|
47741
|
+
});
|
|
47742
|
+
const createFirst = !retainOldOnReplace && fallbackNameChange !== void 0;
|
|
47743
|
+
const noEchoDeleteValues = await noEchoDeleteValuesFromResolved({
|
|
47744
|
+
record: currentResource,
|
|
47745
|
+
templateResource: template?.Resources?.[logicalId],
|
|
47746
|
+
resolvedProperties: resolvedProps,
|
|
47747
|
+
noEchoParameters: noEchoPositionSources(engine.noEchoRun, stateResources, template)?.parameters ?? /* @__PURE__ */ new Set(),
|
|
47748
|
+
conditions: engine.noEchoRun.noEchoConditions,
|
|
46871
47749
|
secrets: updateSecrets,
|
|
46872
|
-
|
|
46873
|
-
|
|
46874
|
-
|
|
47750
|
+
inputSources: template && maskedInputSources(engine.resolverContextDeps(), template, stateResources, engine.noEchoRun.noEchoConditions, stackName)
|
|
47751
|
+
});
|
|
47752
|
+
engine.logger.info(retainOldOnReplace ? safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing ` + `(CREATE only — UpdateReplacePolicy: Retain keeps the old resource)` : createFirst ? safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing (CREATE → DELETE — the new name differs from the old resource's)` : safeMsg`UPDATE not supported for ${logicalId} (${resourceType}), replacing (DELETE → CREATE)`);
|
|
47753
|
+
if (retainOldOnReplace) await noteRetainedResource(resourceType, logicalId);
|
|
47754
|
+
if (!retainOldOnReplace && !createFirst) {
|
|
47755
|
+
const fallbackUpdateReplacePolicy = template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy;
|
|
47756
|
+
const fallbackFinalSnapshotId = await prepareFinalSnapshotForDelete(engine.replacementDeps(), logicalId, resourceType, currentResource, fallbackUpdateReplacePolicy);
|
|
47757
|
+
let fallbackDeleteResult = void 0;
|
|
47758
|
+
try {
|
|
47759
|
+
fallbackDeleteResult = await withPrintingSecrets(updateSecrets, () => updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
|
|
47760
|
+
expectedRegion: engine.stackRegion,
|
|
47761
|
+
forceDataDelete: engine.options.forceStatefulRecreation === true,
|
|
47762
|
+
...fallbackFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: fallbackFinalSnapshotId },
|
|
47763
|
+
...replacementDeleteContext(engine.replacementDeps(), fallbackUpdateReplacePolicy),
|
|
47764
|
+
recordedAttributes: currentResource.attributes,
|
|
47765
|
+
recordedNoEchoLeaves: currentResource.noEchoLeaves,
|
|
47766
|
+
...noEchoDeleteValues !== void 0 && { noEchoDeleteValues },
|
|
47767
|
+
maskSecrets: createUnionSecretMasker([updateSecrets, secretNameBagFor(engine.secretsRun, logicalId)])
|
|
47768
|
+
}));
|
|
47769
|
+
} catch (deleteError) {
|
|
47770
|
+
const deleteMsg = describeAwsFailure(deleteError).detail;
|
|
47771
|
+
if (!isWaitAbandonedError(deleteError) && !isInterruptedWaitError(deleteError) && !isMarkedNonRetryable(deleteError) && (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound"))) engine.logger.debug(safeMsg`Old resource ${logicalId} already gone, proceeding with CREATE`);
|
|
47772
|
+
else throw deleteError;
|
|
47773
|
+
}
|
|
47774
|
+
reportDeleteGuards(fallbackDeleteResult, {
|
|
46875
47775
|
physicalId: currentResource.physicalId,
|
|
46876
|
-
|
|
46877
|
-
|
|
46878
|
-
})
|
|
46879
|
-
|
|
46880
|
-
|
|
46881
|
-
|
|
46882
|
-
|
|
46883
|
-
|
|
46884
|
-
|
|
46885
|
-
|
|
46886
|
-
if (!retainOldOnReplace) {
|
|
46887
|
-
const shownSecrets = unionOfSecretBags([updateSecrets, printingSecretsFor(engine.secretsRun, logicalId)]);
|
|
46888
|
-
throw new Error(safeMsg`Failed to create ${maskSecretsInText(logicalId, shownSecrets)} after the ` + safeMsg`UPDATE-not-supported replacement: the old resource (${maskSecretsInText(currentResource.physicalId, shownSecrets)}) ` + safeMsg`is now gone. Re-run the deploy to create it fresh. Cause: ${asIsMessage(maskSecretsInText(describeAwsFailure(createError).detail, shownSecrets))}`, { cause: createError instanceof Error ? createError : void 0 });
|
|
47776
|
+
resourceType,
|
|
47777
|
+
provisionedBy: updateDecision.provisionedBy
|
|
47778
|
+
});
|
|
47779
|
+
const fallbackSkipReason = deleteSkipReason(fallbackDeleteResult);
|
|
47780
|
+
if (fallbackSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, fallbackSkipReason, "during the UPDATE-not-supported replacement"));
|
|
47781
|
+
engine.replacementRun.oldDeletedBeforeCreate.add(logicalId);
|
|
47782
|
+
await updateProvider.waitForNameReleased?.(logicalId, currentResource.physicalId, resourceType, {
|
|
47783
|
+
isInterrupted: () => engine.userInterrupted,
|
|
47784
|
+
maskSecrets: createSecretMasker(updateSecrets)
|
|
47785
|
+
});
|
|
46889
47786
|
}
|
|
46890
|
-
|
|
46891
|
-
|
|
46892
|
-
|
|
46893
|
-
|
|
46894
|
-
|
|
46895
|
-
|
|
46896
|
-
|
|
46897
|
-
|
|
46898
|
-
|
|
46899
|
-
|
|
46900
|
-
|
|
46901
|
-
|
|
46902
|
-
|
|
46903
|
-
|
|
46904
|
-
|
|
46905
|
-
|
|
46906
|
-
|
|
46907
|
-
|
|
46908
|
-
|
|
46909
|
-
|
|
46910
|
-
|
|
47787
|
+
let retainedSurvivorReason;
|
|
47788
|
+
let createResult;
|
|
47789
|
+
try {
|
|
47790
|
+
createResult = createFirst && fallbackNameChange !== void 0 ? await createFirstThenDeleteOld(engine.replacementRun, engine.replacementDeps(), {
|
|
47791
|
+
stackName,
|
|
47792
|
+
createdVia: replDecision.provisionedBy,
|
|
47793
|
+
resolvedProps,
|
|
47794
|
+
logicalId,
|
|
47795
|
+
resourceType,
|
|
47796
|
+
oldResourceType: resourceType,
|
|
47797
|
+
currentResource,
|
|
47798
|
+
createProvider: replProvider,
|
|
47799
|
+
createProps: replProps,
|
|
47800
|
+
deleteProvider: updateProvider,
|
|
47801
|
+
deleteProvisionedBy: updateDecision.provisionedBy,
|
|
47802
|
+
deleteProperties: currentProps,
|
|
47803
|
+
secrets: updateSecrets,
|
|
47804
|
+
change: fallbackNameChange,
|
|
47805
|
+
equalIdIsSameResource: !equalIdNamesDifferentResources({
|
|
47806
|
+
resourceType,
|
|
47807
|
+
physicalId: currentResource.physicalId,
|
|
47808
|
+
oldProperties: currentResource.properties,
|
|
47809
|
+
newProperties: resolvedProps
|
|
47810
|
+
}),
|
|
47811
|
+
snapshotPolicy: template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy,
|
|
47812
|
+
deletePolicy: template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy,
|
|
47813
|
+
trigger: "the provisioning layer cannot update it in place",
|
|
47814
|
+
noEchoDeleteValues
|
|
47815
|
+
}) : await guardedReplacementCreate(engine, {
|
|
47816
|
+
logicalId,
|
|
47817
|
+
resourceType,
|
|
47818
|
+
stackName,
|
|
47819
|
+
createdVia: replDecision.provisionedBy,
|
|
47820
|
+
resolvedProps
|
|
47821
|
+
}, () => engine.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => replProvider.create(logicalId, resourceType, replProps, { maskSecrets: createSecretMasker(updateSecrets) })), logicalId, void 0, void 0, replProvider, !retainOldOnReplace));
|
|
47822
|
+
} catch (createError) {
|
|
47823
|
+
if (createFirst) throw createError;
|
|
47824
|
+
if (!retainOldOnReplace) {
|
|
47825
|
+
const shownSecrets = unionOfSecretBags([updateSecrets, printingSecretsFor(engine.secretsRun, logicalId)]);
|
|
47826
|
+
throw new Error(safeMsg`Failed to create ${maskSecretsInText(logicalId, shownSecrets)} after the ` + safeMsg`UPDATE-not-supported replacement: the old resource (${maskSecretsInText(currentResource.physicalId, shownSecrets)}) ` + safeMsg`is now gone. Re-run the deploy to create it fresh. Cause: ${asIsMessage(maskSecretsInText(describeAwsFailure(createError).detail, shownSecrets))}`, { cause: createError instanceof Error ? createError : void 0 });
|
|
47827
|
+
}
|
|
47828
|
+
if (!isNameCollisionErrorFrom(createError, logicalId)) throw createError;
|
|
47829
|
+
const nameHeldElsewhere = replacementRequestsDifferentName({
|
|
47830
|
+
oldResourceType: resourceType,
|
|
47831
|
+
newResourceType: resourceType,
|
|
47832
|
+
desiredProperties: resolvedProps,
|
|
47833
|
+
recorded: currentResource.properties,
|
|
47834
|
+
observed: currentResource.observedProperties,
|
|
47835
|
+
physicalId: currentResource.physicalId
|
|
47836
|
+
});
|
|
47837
|
+
if (nameHeldElsewhere !== void 0) throw markNonRetryable(new CdkdError(safeMsg`${logicalId} (${resourceType}) requires replacement because the ` + `provisioning layer cannot update it in place, but the create collided. ` + safeMsg`${renderNameHeldElsewhere(nameHeldElsewhere)} — so removing ` + "UpdateReplacePolicy: Retain would delete this resource and still collide. Choose a name no other resource holds, or delete the resource holding it if it is yours.", "NAMED_REPLACEMENT_COLLISION", createError instanceof Error ? createError : void 0));
|
|
47838
|
+
const nameOrigin = replacementNameOrigin(logicalId, currentResource.physicalId);
|
|
47839
|
+
throw markNonRetryable(new CdkdError(safeMsg`${logicalId} (${resourceType}) requires replacement because the ` + "provisioning layer cannot update it in place — but its physical name is still held by the existing resource AND UpdateReplacePolicy: Retain pins that resource in place. " + safeMsg`${nameOrigin.descriptor}. ${nameOrigin.remedy} — with Retain, the old ` + "resource keeps the name, so a same-name replacement can never proceed. Removing UpdateReplacePolicy: Retain lets cdkd delete the old resource first, which destroys it and any data it holds.", "NAMED_REPLACEMENT_COLLISION", createError instanceof Error ? createError : void 0));
|
|
47840
|
+
}
|
|
47841
|
+
if (!retainOldOnReplace && !createFirst && createResult.physicalId === currentResource.physicalId && !equalIdNamesDifferentResources({
|
|
46911
47842
|
resourceType,
|
|
46912
47843
|
physicalId: currentResource.physicalId,
|
|
46913
47844
|
oldProperties: currentResource.properties,
|
|
46914
47845
|
newProperties: resolvedProps
|
|
46915
|
-
}))
|
|
46916
|
-
|
|
46917
|
-
|
|
47846
|
+
})) engine.replacementRun.recreatedUnderSameId.add(logicalId);
|
|
47847
|
+
if (retainOldOnReplace) {
|
|
47848
|
+
if (createResult.physicalId === currentResource.physicalId && !equalIdNamesDifferentResources({
|
|
47849
|
+
resourceType,
|
|
47850
|
+
physicalId: currentResource.physicalId,
|
|
47851
|
+
oldProperties: currentResource.properties,
|
|
47852
|
+
newProperties: resolvedProps
|
|
47853
|
+
})) {
|
|
47854
|
+
const idempotentNameOrigin = replacementNameOrigin(logicalId, currentResource.physicalId);
|
|
47855
|
+
throw markNonRetryable(new CdkdError(safeMsg`${logicalId} (${resourceType}) requires replacement, but its Create ` + `API is name-idempotent: the create returned the existing resource ` + safeMsg`(${currentResource.physicalId}) instead of creating a new one, and ` + `UpdateReplacePolicy: Retain pins that resource in place, so the new ` + safeMsg`properties were not applied. ${idempotentNameOrigin.descriptor}. ` + safeMsg`${idempotentNameOrigin.remedy} — with Retain, the old resource keeps ` + `the name, so a same-name replacement can never proceed.`, "NAMED_REPLACEMENT_IDEMPOTENT_CREATE"));
|
|
47856
|
+
}
|
|
47857
|
+
engine.replacementRun.retainedOldOnReplacement.add(logicalId);
|
|
47858
|
+
engine.logger.warn(safeMsg` ⚠ ${logicalId} has UpdateReplacePolicy: Retain — the old physical ` + safeMsg`resource (${currentResource.physicalId}) is RETAINED and is no longer ` + "tracked by cdkd: it keeps running and incurring cost, and `cdkd destroy` will not remove it. Delete it yourself once you no longer need its data.");
|
|
47859
|
+
retainedSurvivorReason = `UpdateReplacePolicy: Retain kept the old ${resourceType} (${currentResource.physicalId}), now untracked by cdkd`;
|
|
46918
47860
|
}
|
|
46919
|
-
|
|
46920
|
-
|
|
46921
|
-
|
|
46922
|
-
|
|
46923
|
-
|
|
46924
|
-
|
|
46925
|
-
|
|
46926
|
-
|
|
46927
|
-
|
|
46928
|
-
|
|
46929
|
-
|
|
46930
|
-
|
|
46931
|
-
|
|
46932
|
-
|
|
46933
|
-
|
|
47861
|
+
const replacementResult = {
|
|
47862
|
+
physicalId: createResult.physicalId,
|
|
47863
|
+
wasReplaced: true,
|
|
47864
|
+
...createResult.attributes && { attributes: createResult.attributes },
|
|
47865
|
+
...createResult.noEchoAttributes === true && { noEchoAttributes: true },
|
|
47866
|
+
...createResult.noEchoAttributeNames && { noEchoAttributeNames: createResult.noEchoAttributeNames },
|
|
47867
|
+
...createResult.secretNamedAttributeNames && { secretNamedAttributeNames: createResult.secretNamedAttributeNames },
|
|
47868
|
+
...retainedSurvivorReason !== void 0 ? {
|
|
47869
|
+
outcome: "partial",
|
|
47870
|
+
reason: retainedSurvivorReason
|
|
47871
|
+
} : { outcome: "updated" }
|
|
47872
|
+
};
|
|
47873
|
+
if (createResult.effectiveProperties) replacementResult.effectiveProperties = createResult.effectiveProperties;
|
|
47874
|
+
return {
|
|
47875
|
+
result: replacementResult,
|
|
47876
|
+
provisionedBy: replDecision.provisionedBy,
|
|
47877
|
+
captureProvider: replProvider
|
|
47878
|
+
};
|
|
46934
47879
|
};
|
|
46935
|
-
|
|
46936
|
-
|
|
46937
|
-
|
|
46938
|
-
|
|
47880
|
+
const fallbackOutcome = await (fallbackGeneration === void 0 ? replaceFallback() : withNameGeneration({
|
|
47881
|
+
logicalId,
|
|
47882
|
+
generation: fallbackGeneration
|
|
47883
|
+
}, replaceFallback));
|
|
47884
|
+
result = fallbackOutcome.result;
|
|
47885
|
+
resultProvisionedBy = fallbackOutcome.provisionedBy;
|
|
47886
|
+
captureProvider = fallbackOutcome.captureProvider;
|
|
47887
|
+
replacedAtGeneration = fallbackGeneration;
|
|
46939
47888
|
} else {
|
|
46940
47889
|
if (currentResource.provisionedBy !== "cc-api" && updateDecision.ccRouteReason !== void 0 && updateError instanceof Error && !isInterruptedWaitError(updateError) && !isWaitAbandonedError(updateError)) updateError.message += ccAutoRouteUpdateFailureRemedy(logicalId, resourceType, updateDecision.ccRouteReason.properties, engine.options.parentStackInfo !== void 0);
|
|
46941
47890
|
throw updateError;
|
|
@@ -46966,6 +47915,7 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
46966
47915
|
if (result.wasReplaced) engine.noEchoRun.noEchoExactEchoes.delete(logicalId);
|
|
46967
47916
|
stateResources[logicalId] = {
|
|
46968
47917
|
physicalId: result.physicalId,
|
|
47918
|
+
...replacedAtGeneration === void 0 ? nameGenerationCarriedFrom(currentResource) : nameGenerationField(replacedAtGeneration),
|
|
46969
47919
|
resourceType,
|
|
46970
47920
|
properties: recordedProperties,
|
|
46971
47921
|
...acceptedCreateOnlyDropsField(recordedProperties, resourceType, resultProvisionedBy, dischargedByReplacement ? "new-resource" : "in-place", currentResource),
|
|
@@ -47010,6 +47960,10 @@ async function updateInPlace(engine, { conditions, counts, currentProps, current
|
|
|
47010
47960
|
engine.logger.info(safeMsg`${updatePrefix}${formatResourceLine("updated", logicalId, resourceType)}`);
|
|
47011
47961
|
}
|
|
47012
47962
|
|
|
47963
|
+
//#endregion
|
|
47964
|
+
//#region src/provisioning/changed-properties-consumers.ts
|
|
47965
|
+
const CHANGED_PROPERTIES_CONSUMER_TYPES = /* @__PURE__ */ new Set(["AWS::ServiceDiscovery::Service"]);
|
|
47966
|
+
|
|
47013
47967
|
//#endregion
|
|
47014
47968
|
//#region src/deployment/deploy-engine/read-provenance-moved.ts
|
|
47015
47969
|
function occurrences(value, token) {
|
|
@@ -47380,6 +48334,7 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47380
48334
|
for (const path of provenanceMoved.paths) rewrittenPaths.add(path);
|
|
47381
48335
|
if (provenanceMoved.paths.size > 0) engine.logger.info(safeMsg`${logicalId} is sent: ${[...provenanceMoved.paths].sort().join(", ")} read a secret-derived value at a newer version than ${logicalId} was deployed with (its upstream changed since then)`);
|
|
47382
48336
|
const recordMatchesDesired = movedMasked.size === 0 && rewrittenPaths.size === 0 && keyOrderFreeJson(desiredForSkipCheckAsWritten) === keyOrderFreeJson(currentPropsAsWritten);
|
|
48337
|
+
const movedAsWritten = (key) => movedMasked.has(key) || rewrittenPaths.has(key) || keyOrderFreeJson(desiredForSkipCheckAsWritten[key]) !== keyOrderFreeJson(currentPropsAsWritten[key]);
|
|
47383
48338
|
const applyAttributeOnlyUpdate = (attributeChanges) => {
|
|
47384
48339
|
const attrSummary = attributeChanges.map((a) => `${a.attribute}: ${a.oldValue ?? "(unset)"} → ${a.newValue ?? "(unset)"}`).join(", ");
|
|
47385
48340
|
engine.logger.info(safeMsg` ↻ ${logicalId} (${resourceType}) attribute update: ${attrSummary}`);
|
|
@@ -47484,7 +48439,7 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47484
48439
|
lowered.push(pc);
|
|
47485
48440
|
continue;
|
|
47486
48441
|
}
|
|
47487
|
-
const moved =
|
|
48442
|
+
const moved = movedAsWritten(pc.path);
|
|
47488
48443
|
const conditionalVerdict = moved && !typeChanged && isReplacementCeiling(pc) ? engine.diffCalculator.conditionalReplacementVerdict?.(resourceType, pc.path, currentPropsAsWritten[pc.path], desiredForSkipCheckAsWritten[pc.path]) : void 0;
|
|
47489
48444
|
if (moved && conditionalVerdict !== false) {
|
|
47490
48445
|
warnWitnessReplacement(pc.path);
|
|
@@ -47530,7 +48485,8 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47530
48485
|
const parameterHeldKeys = /* @__PURE__ */ new Set();
|
|
47531
48486
|
const parameterUnreadablePaths = [];
|
|
47532
48487
|
if (pendingParameterLeaves.size > 0 && !typeChanged) {
|
|
47533
|
-
const
|
|
48488
|
+
const consumerReadsBack = CHANGED_PROPERTIES_CONSUMER_TYPES.has(resourceType) && currentResource.provisionedBy !== "cc-api" && [...pendingParameterLeaves.keys()].some((key) => !parameterCreateOnlyPaths.has(key) && otherFreshAt(key).length === 0);
|
|
48489
|
+
const read = parameterCreateOnlyPaths.size > 0 || recordMatchesDesired || consumerReadsBack ? await readOnce() : void 0;
|
|
47534
48490
|
const verdictAt = (key) => {
|
|
47535
48491
|
if (read === void 0) return "not-readable";
|
|
47536
48492
|
if ("failure" in read) return read.failure;
|
|
@@ -47538,14 +48494,13 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47538
48494
|
return liveHoldsFreshLeaves(read.live[key], pendingParameterLeaves.get(key) ?? []) ? "held" : "differs";
|
|
47539
48495
|
};
|
|
47540
48496
|
const lowered = [];
|
|
47541
|
-
|
|
47542
|
-
replacedAnyway = recreateDirectionFor(engine.options, stackName, logicalId) !== void 0 || lostWithParent !== void 0 || (change.propertyChanges ?? []).some((other) => other.requiresReplacement && (!parameterCreateOnlyPaths.has(other.path) || movedAt(other.path)));
|
|
48497
|
+
replacedAnyway = recreateDirectionFor(engine.options, stackName, logicalId) !== void 0 || lostWithParent !== void 0 || (change.propertyChanges ?? []).some((other) => other.requiresReplacement && (!parameterCreateOnlyPaths.has(other.path) || movedAsWritten(other.path)));
|
|
47543
48498
|
for (const pc of change.propertyChanges ?? []) {
|
|
47544
48499
|
if (!parameterCreateOnlyPaths.has(pc.path)) {
|
|
47545
48500
|
lowered.push(pc);
|
|
47546
48501
|
continue;
|
|
47547
48502
|
}
|
|
47548
|
-
if (
|
|
48503
|
+
if (movedAsWritten(pc.path)) {
|
|
47549
48504
|
if (pc.requiresReplacement) warnWitnessReplacement(pc.path);
|
|
47550
48505
|
lowered.push(pc);
|
|
47551
48506
|
continue;
|
|
@@ -47656,30 +48611,39 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47656
48611
|
engine.replacementRun.restoredLostChildren.add(logicalId);
|
|
47657
48612
|
return outcome;
|
|
47658
48613
|
};
|
|
47659
|
-
if (needsReplacement)
|
|
47660
|
-
|
|
47661
|
-
|
|
47662
|
-
|
|
47663
|
-
|
|
47664
|
-
|
|
47665
|
-
|
|
47666
|
-
|
|
47667
|
-
|
|
47668
|
-
|
|
47669
|
-
|
|
47670
|
-
|
|
47671
|
-
|
|
47672
|
-
|
|
47673
|
-
|
|
47674
|
-
|
|
47675
|
-
|
|
47676
|
-
|
|
47677
|
-
|
|
47678
|
-
|
|
47679
|
-
|
|
47680
|
-
|
|
47681
|
-
|
|
47682
|
-
|
|
48614
|
+
if (needsReplacement) {
|
|
48615
|
+
const { generation: nextGeneration, fields: nameGenerationFields } = replacementNameGeneration(currentResource, logicalId, getCurrentStackInstanceId(), lostWithParent !== void 0);
|
|
48616
|
+
if (nextGeneration !== void 0) engine.replacementRun.attemptedNameGeneration.set(logicalId, nextGeneration);
|
|
48617
|
+
const replace = () => updateByReplacement(engine, {
|
|
48618
|
+
change,
|
|
48619
|
+
counts,
|
|
48620
|
+
currentProps,
|
|
48621
|
+
currentResource,
|
|
48622
|
+
dependencies,
|
|
48623
|
+
logicalId,
|
|
48624
|
+
oldResourceType,
|
|
48625
|
+
progress,
|
|
48626
|
+
propertyDrivenReplacement,
|
|
48627
|
+
recreateFlagged,
|
|
48628
|
+
recreateViaCcApi,
|
|
48629
|
+
recreateViaSdkProvider,
|
|
48630
|
+
renderer,
|
|
48631
|
+
resolvedProps,
|
|
48632
|
+
resourceType,
|
|
48633
|
+
stackName,
|
|
48634
|
+
stateResources,
|
|
48635
|
+
template,
|
|
48636
|
+
typeChanged,
|
|
48637
|
+
updateReplacePolicy,
|
|
48638
|
+
updateSecrets,
|
|
48639
|
+
lostWithParent,
|
|
48640
|
+
nameGenerationFields
|
|
48641
|
+
});
|
|
48642
|
+
return markRestored(await (nextGeneration === void 0 ? replace() : withNameGeneration({
|
|
48643
|
+
logicalId,
|
|
48644
|
+
generation: nextGeneration
|
|
48645
|
+
}, replace)));
|
|
48646
|
+
}
|
|
47683
48647
|
const serviceTokenRefusal = serviceTokenUpdateRefusal({
|
|
47684
48648
|
logicalId,
|
|
47685
48649
|
resourceType,
|
|
@@ -47689,6 +48653,11 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47689
48653
|
diffSawTokenChange: diffMovedServiceToken(change)
|
|
47690
48654
|
});
|
|
47691
48655
|
if (serviceTokenRefusal !== void 0) throw markRefusedBeforeApplying(markNonRetryable(new CdkdError(renderServiceTokenRefusal([serviceTokenRefusal], stackName, createSecretMasker(updateSecrets)), SERVICE_TOKEN_CHANGE_REFUSED)));
|
|
48656
|
+
const changedProperties = new Set([.../* @__PURE__ */ new Set([
|
|
48657
|
+
...Object.keys(desiredForSkipCheckAsWritten),
|
|
48658
|
+
...Object.keys(currentPropsAsWritten),
|
|
48659
|
+
...Object.keys(resolvedProps)
|
|
48660
|
+
])].filter((key) => movedAsWritten(key) || !confirmedPaths.has(key) && (pendingParameterLeaves.has(key) || otherFreshAt(key).length > 0)));
|
|
47692
48661
|
let previousForProvider = currentPropsAsWritten;
|
|
47693
48662
|
for (const coordinate of witness?.confirmed ?? []) {
|
|
47694
48663
|
const value = valueAtCoordinate(resolvedProps, coordinate);
|
|
@@ -47699,6 +48668,7 @@ async function provisionUpdate(engine, logicalId, change, stateResources, stackN
|
|
|
47699
48668
|
counts,
|
|
47700
48669
|
currentProps,
|
|
47701
48670
|
currentPropsAsWritten: previousForProvider,
|
|
48671
|
+
changedProperties,
|
|
47702
48672
|
currentResource,
|
|
47703
48673
|
dependencies,
|
|
47704
48674
|
desiredForSkipCheckAsWritten,
|
|
@@ -47963,7 +48933,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
47963
48933
|
saveChain = saveChain.then(async () => {
|
|
47964
48934
|
try {
|
|
47965
48935
|
const partialState = {
|
|
47966
|
-
version:
|
|
48936
|
+
version: 13,
|
|
47967
48937
|
region: engine.stackRegion,
|
|
47968
48938
|
stackName: currentState.stackName,
|
|
47969
48939
|
resources: newResources,
|
|
@@ -47971,6 +48941,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
47971
48941
|
...exportNamesCarriedFrom(currentState),
|
|
47972
48942
|
...skippedOutputsCarriedFrom(currentState),
|
|
47973
48943
|
...orphansCarriedFrom(currentState),
|
|
48944
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
47974
48945
|
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
47975
48946
|
lastModified: Date.now()
|
|
47976
48947
|
};
|
|
@@ -47993,6 +48964,12 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
47993
48964
|
const inFlightWrites = /* @__PURE__ */ new Map();
|
|
47994
48965
|
engine.stackRecordsView = deployStackRecordsView(newResources, currentState.resources, deleteChanges, (logicalId) => startedUpdates.has(logicalId) && !settledUpdates.has(logicalId), () => [...inFlightWrites.values()].map(({ write }) => write));
|
|
47995
48966
|
engine.replacementRun.deferredReplacedDeletes = /* @__PURE__ */ new Map();
|
|
48967
|
+
engine.replacementRun.supersededHost = currentState;
|
|
48968
|
+
const carriedSuperseded = supersededResourcesOf(currentState).filter((entry) => {
|
|
48969
|
+
if (!isSupersededHeldBySameType(entry, currentState.resources)) return true;
|
|
48970
|
+
removeSuperseded(currentState, entry);
|
|
48971
|
+
return false;
|
|
48972
|
+
});
|
|
47996
48973
|
try {
|
|
47997
48974
|
const createUpdateIds = [];
|
|
47998
48975
|
for (const [id, change] of changes.entries()) {
|
|
@@ -48086,6 +49063,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48086
49063
|
engine.interrupted = true;
|
|
48087
49064
|
engine.interruptCause ??= "sibling-failure";
|
|
48088
49065
|
const refused = isRefusedBeforeApplying(provisionError, logicalId);
|
|
49066
|
+
const attemptedGeneration = change.changeType === "UPDATE" && !refused && !isReplacementNameRefusal(provisionError, logicalId) ? engine.replacementRun.attemptedNameGeneration.get(logicalId) : void 0;
|
|
48089
49067
|
const statePhysicalId = newResources[logicalId]?.physicalId ?? previousState?.physicalId;
|
|
48090
49068
|
if (refused && change.changeType === "CREATE" && statePhysicalId === void 0) throw provisionError;
|
|
48091
49069
|
const createdId = change.changeType === "CREATE" && statePhysicalId === void 0 ? createdBeforeFailure(provisionError, logicalId, change.resourceType) : void 0;
|
|
@@ -48117,10 +49095,14 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48117
49095
|
deletionPolicy: journaledOrphanPolicy(extractTemplateAttributes(template, logicalId).deletionPolicy)
|
|
48118
49096
|
},
|
|
48119
49097
|
...change.changeType === "UPDATE" && engine.replacementRun.oldDeletedBeforeCreate.has(logicalId) && { oldDeletedBeforeCreate: true },
|
|
49098
|
+
...attemptedGeneration !== void 0 && { nameGeneration: attemptedGeneration },
|
|
49099
|
+
...change.changeType === "CREATE" && getCurrentStackInstanceId() !== void 0 && { nameGeneration: currentNameGeneration(logicalId) ?? 0 },
|
|
48120
49100
|
...orphanedBy !== void 0 && { replacementOrphaned: engine.replacementRun.oldDeletedBeforeCreate.has(logicalId) ? "delete-first" : "create-first" },
|
|
48121
49101
|
...!refused && { attemptedProperties: engine.attemptedResolvedProps.get(logicalId) }
|
|
48122
49102
|
};
|
|
48123
49103
|
failedOperations.push(failedOp);
|
|
49104
|
+
const heldNow = newResources[logicalId];
|
|
49105
|
+
if (attemptedGeneration !== void 0 && heldNow !== void 0) newResources[logicalId] = withNameGenerationReached(heldNow, logicalId, attemptedGeneration);
|
|
48124
49106
|
let replacementOrphanOp;
|
|
48125
49107
|
if (orphanedBy !== void 0) {
|
|
48126
49108
|
replacementOrphanOp = {
|
|
@@ -48167,7 +49149,8 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48167
49149
|
},
|
|
48168
49150
|
...change.changeType === "UPDATE" && engine.replacementRun.replacedOldMaySurvive.has(logicalId) && { oldResourceMaySurvive: engine.replacementRun.replacedOldMaySurvive.get(logicalId) },
|
|
48169
49151
|
...change.changeType === "UPDATE" && engine.replacementRun.updateWasReplaced.has(logicalId) && { wasReplaced: engine.replacementRun.updateWasReplaced.get(logicalId) },
|
|
48170
|
-
...change.changeType === "UPDATE" && previousState !== void 0 && { previousResourceType: previousState.resourceType }
|
|
49152
|
+
...change.changeType === "UPDATE" && previousState !== void 0 && { previousResourceType: previousState.resourceType },
|
|
49153
|
+
...change.changeType === "UPDATE" && engine.replacementRun.attemptedNameGeneration.has(logicalId) && newResources[logicalId]?.nameGeneration !== void 0 && { nameGeneration: newResources[logicalId].nameGeneration }
|
|
48171
49154
|
});
|
|
48172
49155
|
saveStateAfterResource(logicalId);
|
|
48173
49156
|
if (engine.replacementRun.recreatedUnderSameId.has(logicalId)) enqueueLostChildren(createUpdateExecutor);
|
|
@@ -48218,6 +49201,10 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48218
49201
|
provisionedBy: previousState?.provisionedBy,
|
|
48219
49202
|
previousState
|
|
48220
49203
|
});
|
|
49204
|
+
if (previousState !== void 0 && newResources[logicalId] === void 0) Object.assign(currentState, retiredNameGenerationsAfter(currentState, [{
|
|
49205
|
+
logicalId,
|
|
49206
|
+
record: previousState
|
|
49207
|
+
}]));
|
|
48221
49208
|
saveStateAfterResource(logicalId);
|
|
48222
49209
|
}, () => engine.interrupted);
|
|
48223
49210
|
} finally {
|
|
@@ -48226,15 +49213,19 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48226
49213
|
if (engine.interrupted && hasPending(deleteExecutor)) throw new InterruptedError(engine.interruptCause ?? "user");
|
|
48227
49214
|
}
|
|
48228
49215
|
if (engine.interrupted) warnUnretriedReplacedDeletes(engine.replacementRun, engine.replacementDeps(), "interrupted");
|
|
48229
|
-
else
|
|
48230
|
-
|
|
48231
|
-
|
|
48232
|
-
|
|
48233
|
-
|
|
48234
|
-
|
|
48235
|
-
|
|
48236
|
-
|
|
49216
|
+
else {
|
|
49217
|
+
try {
|
|
49218
|
+
await retryDeferredReplacedDeletes(engine.replacementRun, engine.replacementDeps(), stackName, actualCounts);
|
|
49219
|
+
} finally {
|
|
49220
|
+
for (const op of completedOperations) {
|
|
49221
|
+
if (op.changeType !== "UPDATE") continue;
|
|
49222
|
+
const verdict = engine.replacementRun.replacedOldMaySurvive.get(op.logicalId);
|
|
49223
|
+
if (verdict !== void 0) op.oldResourceMaySurvive = verdict;
|
|
49224
|
+
else delete op.oldResourceMaySurvive;
|
|
49225
|
+
}
|
|
48237
49226
|
}
|
|
49227
|
+
const releasedSomething = deleteChanges.size > 0 || completedOperations.some((op) => op.changeType === "UPDATE" && op.previousState !== void 0 && op.physicalId !== void 0 && op.physicalId !== op.previousState.physicalId);
|
|
49228
|
+
await retryCarriedSupersededResources(engine, currentState, carriedSuperseded, newResources, { waitInUse: releasedSomething });
|
|
48238
49229
|
}
|
|
48239
49230
|
} catch (error) {
|
|
48240
49231
|
warnUnretriedReplacedDeletes(engine.replacementRun, engine.replacementDeps(), engine.interruptCause === "user" ? "interrupted" : "failed");
|
|
@@ -48293,7 +49284,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48293
49284
|
}
|
|
48294
49285
|
try {
|
|
48295
49286
|
const preRollbackState = {
|
|
48296
|
-
version:
|
|
49287
|
+
version: 13,
|
|
48297
49288
|
region: engine.stackRegion,
|
|
48298
49289
|
stackName: currentState.stackName,
|
|
48299
49290
|
resources: newResources,
|
|
@@ -48301,6 +49292,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48301
49292
|
...exportNamesCarriedFrom(currentState),
|
|
48302
49293
|
...skippedOutputsCarriedFrom(currentState),
|
|
48303
49294
|
...orphansCarriedFrom(currentState),
|
|
49295
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
48304
49296
|
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
48305
49297
|
lastModified: Date.now()
|
|
48306
49298
|
};
|
|
@@ -48318,6 +49310,8 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48318
49310
|
let autoRollbackClean = false;
|
|
48319
49311
|
let autoRollbackJournaled = false;
|
|
48320
49312
|
let rollbackOrphans = [];
|
|
49313
|
+
let rollbackCreates = [];
|
|
49314
|
+
let rollbackSuperseded = [];
|
|
48321
49315
|
let rollbackSettledNested = /* @__PURE__ */ new Map();
|
|
48322
49316
|
let rollbackRemainingFailedOps = failedOperations;
|
|
48323
49317
|
if (error instanceof InterruptedError || isInterruptedWaitError(error) || engine.interruptCause === "user") {
|
|
@@ -48332,7 +49326,14 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48332
49326
|
} else {
|
|
48333
49327
|
autoRollbackJournaled = await writeRollbackJournalSegment(engine.rollbackDeps(), stackName, completedOperations, failedOperations, "auto-rollback-started", initialDeploy);
|
|
48334
49328
|
const rollbackResult = await performRollback(engine.rollbackDeps(), completedOperations, newResources, stackName, currentState, failedOperations, currentState.orphans ?? []);
|
|
48335
|
-
autoRollbackClean = autoRollbackJournaled && rollbackResult.failures === 0 && rollbackResult.skipped === 0;
|
|
49329
|
+
autoRollbackClean = autoRollbackJournaled && rollbackResult.failures === 0 && rollbackResult.skipped === 0 && !rollbackResult.interrupted;
|
|
49330
|
+
if (rollbackResult.interrupted && rollbackResult.failures === 0 && rollbackResult.skipped === 0) {
|
|
49331
|
+
const remedy = autoRollbackJournaled ? recoveryHint(engine.rollbackDeps(), "The rollback journal keeps them; finish the rollback with: " + pasteableCommand("cdkd rollback", [{
|
|
49332
|
+
value: stackName,
|
|
49333
|
+
hole: "stack"
|
|
49334
|
+
}]).command) : "";
|
|
49335
|
+
engine.logger.warn(safeMsg`The automatic rollback was interrupted before it reverted every operation. ${remedy}`);
|
|
49336
|
+
}
|
|
48336
49337
|
if (rollbackResult.failures === 0 && rollbackResult.skipped > 0) {
|
|
48337
49338
|
engine.logger.warn(safeMsg`The automatic rollback could not revert ${rollbackResult.skipped} operation(s) ` + `(see the warnings above; each is recorded as a ROLLBACK_RESOURCE_SKIPPED event).` + (autoRollbackJournaled ? ` The rollback journal keeps them.` : ""));
|
|
48338
49339
|
if (autoRollbackJournaled && engine.options.parentStackInfo === void 0 && rollbackResult.remainingFailedOps.some((op) => op.changeType !== "DELETE")) engine.logger.warn(safeMsg`The record of the operation that failed is kept too. Revert it with: ${pasteableCommand("cdkd rollback", [{
|
|
@@ -48341,12 +49342,14 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48341
49342
|
}, { literal: "--revert-failed" }]).command}`);
|
|
48342
49343
|
}
|
|
48343
49344
|
rollbackOrphans = rollbackResult.orphaned;
|
|
49345
|
+
rollbackCreates = rollbackResult.rolledBackCreates;
|
|
49346
|
+
rollbackSuperseded = rollbackResult.superseded;
|
|
48344
49347
|
rollbackSettledNested = rollbackResult.settledNested;
|
|
48345
49348
|
rollbackRemainingFailedOps = rollbackResult.remainingFailedOps;
|
|
48346
49349
|
}
|
|
48347
49350
|
try {
|
|
48348
49351
|
const postRollbackState = {
|
|
48349
|
-
version:
|
|
49352
|
+
version: 13,
|
|
48350
49353
|
region: engine.stackRegion,
|
|
48351
49354
|
stackName: currentState.stackName,
|
|
48352
49355
|
resources: newResources,
|
|
@@ -48354,6 +49357,9 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48354
49357
|
...exportNamesCarriedFrom(currentState),
|
|
48355
49358
|
...skippedOutputsCarriedFrom(currentState),
|
|
48356
49359
|
...orphansAfterRollback(currentState, rollbackOrphans),
|
|
49360
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
49361
|
+
...supersededAfterRollback(currentState, { supersededResources: rollbackSuperseded }),
|
|
49362
|
+
...retiredAfterRollback(currentState, rollbackOrphans, rollbackCreates),
|
|
48357
49363
|
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
48358
49364
|
lastModified: Date.now()
|
|
48359
49365
|
};
|
|
@@ -48365,7 +49371,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48365
49371
|
try {
|
|
48366
49372
|
const freshEtag = (await engine.stateBackend.getState(stackName, engine.stackRegion))?.etag;
|
|
48367
49373
|
const postRollbackState = {
|
|
48368
|
-
version:
|
|
49374
|
+
version: 13,
|
|
48369
49375
|
region: engine.stackRegion,
|
|
48370
49376
|
stackName: currentState.stackName,
|
|
48371
49377
|
resources: newResources,
|
|
@@ -48373,6 +49379,9 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48373
49379
|
...exportNamesCarriedFrom(currentState),
|
|
48374
49380
|
...skippedOutputsCarriedFrom(currentState),
|
|
48375
49381
|
...orphansAfterRollback(currentState, rollbackOrphans),
|
|
49382
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
49383
|
+
...supersededAfterRollback(currentState, { supersededResources: rollbackSuperseded }),
|
|
49384
|
+
...retiredAfterRollback(currentState, rollbackOrphans, rollbackCreates),
|
|
48376
49385
|
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
48377
49386
|
lastModified: Date.now()
|
|
48378
49387
|
};
|
|
@@ -48381,6 +49390,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48381
49390
|
if (autoRollbackClean) await settleNestedChildrenAfterCleanRollback(engine.rollbackDeps(), stackName, rollbackSettledNested, await settleJournalAfterCleanRollback(engine.rollbackDeps(), stackName, rollbackRemainingFailedOps, initialDeploy));
|
|
48382
49391
|
} catch (retryError) {
|
|
48383
49392
|
engine.logger.warn(safeMsg`Failed to save state after rollback: ${asIsMessage(describeAwsFailure(retryError).detail)}`);
|
|
49393
|
+
for (const entry of rollbackSuperseded) withPrintingSecrets(unionOfSecretBags([secretNameBagFor(engine.secretsRun, entry.logicalId), orphanRecordsPrintingBag([entry])]), () => engine.logger.warn(safeMsg` ${entry.logicalId}'s new ${entry.state.resourceType} ` + safeMsg`(${entry.state.physicalId}) the rollback left to delete is NOT recorded: ` + "delete it manually."));
|
|
48384
49394
|
}
|
|
48385
49395
|
}
|
|
48386
49396
|
throw error;
|
|
@@ -48398,11 +49408,12 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48398
49408
|
}
|
|
48399
49409
|
return {
|
|
48400
49410
|
state: {
|
|
48401
|
-
version:
|
|
49411
|
+
version: 13,
|
|
48402
49412
|
region: engine.stackRegion,
|
|
48403
49413
|
stackName: currentState.stackName,
|
|
48404
49414
|
resources: newResources,
|
|
48405
49415
|
...orphansCarriedFrom(currentState),
|
|
49416
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
48406
49417
|
outputs,
|
|
48407
49418
|
exportNames: [...engine.outputsRun.resolvedExportNames],
|
|
48408
49419
|
...engine.outputsRun.skippedOutputs && { skippedOutputs: { ...engine.outputsRun.skippedOutputs } },
|
|
@@ -48416,7 +49427,7 @@ async function executeDeployment(engine, template, currentState, changes, dag, e
|
|
|
48416
49427
|
}
|
|
48417
49428
|
async function persistStateAfterOutputFailure(engine, stackName, currentState, newResources, currentEtag, pendingMigration) {
|
|
48418
49429
|
const buildState = () => ({
|
|
48419
|
-
version:
|
|
49430
|
+
version: 13,
|
|
48420
49431
|
region: engine.stackRegion,
|
|
48421
49432
|
stackName: currentState.stackName,
|
|
48422
49433
|
resources: newResources,
|
|
@@ -48424,6 +49435,7 @@ async function persistStateAfterOutputFailure(engine, stackName, currentState, n
|
|
|
48424
49435
|
...exportNamesCarriedFrom(currentState),
|
|
48425
49436
|
...skippedOutputsCarriedFrom(currentState),
|
|
48426
49437
|
...orphansCarriedFrom(currentState),
|
|
49438
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
48427
49439
|
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
48428
49440
|
lastModified: Date.now()
|
|
48429
49441
|
});
|
|
@@ -48459,12 +49471,14 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48459
49471
|
const renderer = getLiveRenderer();
|
|
48460
49472
|
engine.interrupted = false;
|
|
48461
49473
|
engine.interruptCause = null;
|
|
49474
|
+
engine.userInterrupted = false;
|
|
48462
49475
|
const sigintHandler = () => {
|
|
48463
49476
|
renderer.printAbove(() => {
|
|
48464
49477
|
process.stderr.write("\nInterrupted — saving partial state after current operations complete...\n");
|
|
48465
49478
|
});
|
|
48466
49479
|
engine.interrupted = true;
|
|
48467
49480
|
engine.interruptCause ??= "user";
|
|
49481
|
+
engine.userInterrupted = true;
|
|
48468
49482
|
};
|
|
48469
49483
|
process.on("SIGINT", sigintHandler);
|
|
48470
49484
|
try {
|
|
@@ -48482,7 +49496,7 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48482
49496
|
const currentStateData = await engine.stateBackend.getState(stackName, engine.stackRegion);
|
|
48483
49497
|
noteDeployStateRecord(currentStateData?.state !== void 0);
|
|
48484
49498
|
const currentState = currentStateData?.state ?? {
|
|
48485
|
-
version:
|
|
49499
|
+
version: 13,
|
|
48486
49500
|
region: engine.stackRegion,
|
|
48487
49501
|
stackName,
|
|
48488
49502
|
resources: {},
|
|
@@ -48491,6 +49505,19 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48491
49505
|
lastModified: Date.now()
|
|
48492
49506
|
};
|
|
48493
49507
|
const currentEtag = currentStateData?.etag;
|
|
49508
|
+
stackInstanceIdOf(currentState, displayStackName(stackName));
|
|
49509
|
+
const loadedNameGenerations = nameGenerationsOf(currentState);
|
|
49510
|
+
const nameScope = () => {
|
|
49511
|
+
const stackInstanceId = stackInstanceIdOf(currentState, displayStackName(stackName));
|
|
49512
|
+
return {
|
|
49513
|
+
stackName,
|
|
49514
|
+
stackInstanceId,
|
|
49515
|
+
nameGenerations: stackInstanceId === void 0 ? void 0 : loadedNameGenerations
|
|
49516
|
+
};
|
|
49517
|
+
};
|
|
49518
|
+
const idArrivesLater = (currentStateData === null || currentStateData === void 0) && currentState.stackInstanceId === void 0;
|
|
49519
|
+
const retainedAtFirstDeploy = idArrivesLater && !engine.options.dryRun ? Promise.resolve().then(() => engine.stateBackend.loadRetainedRecord(stackName, engine.stackRegion)) : void 0;
|
|
49520
|
+
const retainedForWarning = retainedAtFirstDeploy?.catch(() => null);
|
|
48494
49521
|
engine.rebaseline(currentState.resources ?? {});
|
|
48495
49522
|
engine.runProducerRegionEvidence = () => producerRegionEvidence(engine.rollbackDeps(), currentState);
|
|
48496
49523
|
refuseMalformedOutputs(currentState, stackName, engine.stackRegion, engine.options.refusalRecovery);
|
|
@@ -48534,6 +49561,7 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48534
49561
|
command: "deploy",
|
|
48535
49562
|
logger: engine.logger,
|
|
48536
49563
|
stateResources: currentState.resources,
|
|
49564
|
+
stackInstanceId: currentStateData?.state === void 0 ? () => engine.stateBackend.readStackInstanceSibling(stackName, engine.stackRegion) : nameScope().stackInstanceId,
|
|
48537
49565
|
resume: (op, identifier) => {
|
|
48538
49566
|
const attempted = op.attemptedProperties;
|
|
48539
49567
|
if (template.Resources?.[op.logicalId]?.Type !== op.resourceType || attempted === void 0 || carriesSecretMask(attempted) || op.pendingCloudControlRequest === void 0 || Object.values(currentState.resources).some((r) => r.physicalId === identifier && r.resourceType === op.resourceType)) return false;
|
|
@@ -48695,6 +49723,11 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48695
49723
|
firstDeployStateGate = void 0;
|
|
48696
49724
|
await gate;
|
|
48697
49725
|
}
|
|
49726
|
+
const resolveStackInstanceId = async () => {
|
|
49727
|
+
if (currentStateData !== null && currentStateData !== void 0) return;
|
|
49728
|
+
if (engine.options.dryRun || currentState.stackInstanceId !== void 0) return;
|
|
49729
|
+
currentState.stackInstanceId = await engine.stateBackend.stackInstanceIdForFirstWrite(stackName, engine.stackRegion, { writeAhead: true });
|
|
49730
|
+
};
|
|
48698
49731
|
const startProvenanceCapture = () => {
|
|
48699
49732
|
if (engine.options.dryRun || isKnownTokenFreeState(currentStateData?.state)) return;
|
|
48700
49733
|
engine.provenanceCapture.kickOffProvenanceCapture({
|
|
@@ -48709,6 +49742,7 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48709
49742
|
if (!engine.diffCalculator.hasChanges(changes)) {
|
|
48710
49743
|
engine.logger.info("No changes detected. Stack is up to date.");
|
|
48711
49744
|
startProvenanceCapture();
|
|
49745
|
+
const supersededChanged = engine.options.dryRun ? false : await retryCarriedSupersededResources(engine, currentState, supersededResourcesOf(currentState), currentState.resources);
|
|
48712
49746
|
let persistedOutputs = currentState.outputs ?? {};
|
|
48713
49747
|
if (!engine.options.dryRun) {
|
|
48714
49748
|
const resolvedOutputs = redactOutputs(engine.maskingDeps(), await withSharedDrainBudget(() => resolveOutputs(engine.outputsRun, engine.outputsDeps(), effectiveTemplate, currentState.resources, stackName, outputsDigestSource, parameterValues, conditions)));
|
|
@@ -48747,37 +49781,41 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48747
49781
|
stackName
|
|
48748
49782
|
});
|
|
48749
49783
|
const outputProvenanceBackfill = !outputsChanged && currentState.outputReferenceProvenance === void 0 && engine.provenanceBaseline?.tokenFree === false && engine.outputReferenceProvenanceFor(persistedOutputs, redactOutputs(engine.maskingDeps(), persistedOutputs)) !== void 0;
|
|
48750
|
-
if (observedRefresh || outputProvenanceBackfill || maskedFingerprintsBackfilled || conditionVerdictsChanged || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged || healedAttributesPending)
|
|
48751
|
-
|
|
48752
|
-
|
|
48753
|
-
|
|
48754
|
-
|
|
48755
|
-
|
|
48756
|
-
|
|
48757
|
-
|
|
48758
|
-
|
|
48759
|
-
|
|
48760
|
-
|
|
48761
|
-
|
|
48762
|
-
|
|
48763
|
-
|
|
48764
|
-
|
|
48765
|
-
|
|
48766
|
-
|
|
48767
|
-
|
|
48768
|
-
|
|
48769
|
-
|
|
48770
|
-
|
|
48771
|
-
|
|
48772
|
-
|
|
48773
|
-
|
|
48774
|
-
|
|
48775
|
-
|
|
48776
|
-
|
|
48777
|
-
|
|
48778
|
-
|
|
48779
|
-
|
|
48780
|
-
|
|
49784
|
+
if (observedRefresh || outputProvenanceBackfill || maskedFingerprintsBackfilled || conditionVerdictsChanged || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged || supersededChanged || healedAttributesPending) {
|
|
49785
|
+
await resolveStackInstanceId();
|
|
49786
|
+
try {
|
|
49787
|
+
const refreshedState = {
|
|
49788
|
+
version: 13,
|
|
49789
|
+
region: engine.stackRegion,
|
|
49790
|
+
stackName: currentState.stackName,
|
|
49791
|
+
resources: currentState.resources,
|
|
49792
|
+
...orphansCarriedFrom(currentState),
|
|
49793
|
+
...stackInstanceIdCarriedFrom(currentState),
|
|
49794
|
+
outputs: outputsChanged ? outputsToPersist : persistedOutputs,
|
|
49795
|
+
...exportNamesToPersist === void 0 ? exportNamesCarriedFrom(currentState) : { exportNames: [...exportNamesToPersist] },
|
|
49796
|
+
...engine.outputsRun.skippedOutputs && { skippedOutputs: { ...engine.outputsRun.skippedOutputs } },
|
|
49797
|
+
...crossStackReadsForPartialSave(currentState, engine.recordedImports, engine.recordedOutputReads, engine.crossStackReadKeyNormalizer()),
|
|
49798
|
+
...conditionVerdicts && { conditionVerdicts },
|
|
49799
|
+
lastModified: Date.now()
|
|
49800
|
+
};
|
|
49801
|
+
const saveOptions = {};
|
|
49802
|
+
if (currentEtag !== void 0) saveOptions.expectedEtag = currentEtag;
|
|
49803
|
+
if (migrationPending) saveOptions.migrateLegacy = true;
|
|
49804
|
+
await engine.stateBackend.saveState(stackName, engine.stackRegion, engine.withParentInfo(refreshedState), saveOptions);
|
|
49805
|
+
if (outputsChanged || exportSetChanged) {
|
|
49806
|
+
persistedOutputs = refreshedState.outputs;
|
|
49807
|
+
if (outputsChanged) engine.logger.info("Persisted Outputs-only change (no resource diff).");
|
|
49808
|
+
else engine.logger.debug("Persisted export-set change (no outputs-value diff, no-change path)");
|
|
49809
|
+
if (engine.exportIndexStore) await engine.exportIndexStore.updateForStack(stackName, engine.stackRegion, importableOutputs({
|
|
49810
|
+
...refreshedState,
|
|
49811
|
+
outputs: redactOutputs(engine.maskingDeps(), refreshedState.outputs)
|
|
49812
|
+
}));
|
|
49813
|
+
} else if (observedRefresh) engine.logger.debug("Persisted refreshed observedProperties (no-change path)");
|
|
49814
|
+
else if (healedAttributesPending) engine.logger.debug("Persisted attributes re-read from AWS for a stale record (no-change path)");
|
|
49815
|
+
else engine.logger.debug("Persisted skipped-outputs record (no outputs-value diff, no-change path)");
|
|
49816
|
+
} catch (saveError) {
|
|
49817
|
+
engine.logger.warn(safeMsg`Failed to persist no-change state update: ${asIsMessage(describeAwsFailure(saveError).detail)} — drift baseline / outputs will be re-resolved on next deploy.`);
|
|
49818
|
+
}
|
|
48781
49819
|
}
|
|
48782
49820
|
}
|
|
48783
49821
|
return {
|
|
@@ -48817,7 +49855,7 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48817
49855
|
}
|
|
48818
49856
|
const abandonedRunAt = engine.lockManager.abandonedRunEndedBy?.(stackName, engine.stackRegion);
|
|
48819
49857
|
if (abandonedRunAt !== void 0) await noteAbandonedRun(abandonedRunAt);
|
|
48820
|
-
|
|
49858
|
+
const generatedNameGuardInput = {
|
|
48821
49859
|
stackName,
|
|
48822
49860
|
region: engine.stackRegion,
|
|
48823
49861
|
changes: changes.values(),
|
|
@@ -48828,7 +49866,7 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48828
49866
|
records: currentState.resources,
|
|
48829
49867
|
orphans: currentState.orphans,
|
|
48830
49868
|
loadJournal: () => engine.stateBackend.loadRollbackJournal(stackName, engine.stackRegion),
|
|
48831
|
-
loadRetained: () => engine.stateBackend.loadRetainedRecord(stackName, engine.stackRegion),
|
|
49869
|
+
loadRetained: () => retainedAtFirstDeploy ?? engine.stateBackend.loadRetainedRecord(stackName, engine.stackRegion),
|
|
48832
49870
|
loadKeptInHistory: () => {
|
|
48833
49871
|
const reader = new DeploymentEventsReader(engine.stateBackend);
|
|
48834
49872
|
return loadKeptInHistory({
|
|
@@ -48840,8 +49878,24 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48840
49878
|
accountInfo: () => getAccountInfo(engine.stackRegion),
|
|
48841
49879
|
warn: (message) => engine.logger.warn(message),
|
|
48842
49880
|
...abandonedRunAt !== void 0 && { abandonedRunAt }
|
|
48843
|
-
}
|
|
48844
|
-
|
|
49881
|
+
};
|
|
49882
|
+
const startGeneratedNameGuard = () => {
|
|
49883
|
+
const scope = nameScope();
|
|
49884
|
+
const lifetimeId = scope.stackInstanceId;
|
|
49885
|
+
engine.generatedNameGuard = withStackScope(scope, () => GeneratedNameGuard.start({
|
|
49886
|
+
...generatedNameGuardInput,
|
|
49887
|
+
...lifetimeId !== void 0 && {
|
|
49888
|
+
newScheme: true,
|
|
49889
|
+
replacementGeneration: (change) => {
|
|
49890
|
+
const record = currentState.resources[change.logicalId];
|
|
49891
|
+
if (record === void 0 || record.resourceType !== change.resourceType || !((change.propertyChanges ?? []).some((pc) => pc.requiresReplacement) || recreateTargetIdsFor(engine.options.recreateTargets, stackName)?.has(change.logicalId) === true)) return;
|
|
49892
|
+
return nextNameGeneration(record, change.logicalId, lifetimeId);
|
|
49893
|
+
}
|
|
49894
|
+
}
|
|
49895
|
+
}));
|
|
49896
|
+
if (engine.generatedNameGuard !== void 0) engine.logger.debug(safeMsg`Generated-name check: looking up ${String(engine.generatedNameGuard.size)} planned create(s)`);
|
|
49897
|
+
};
|
|
49898
|
+
if (!idArrivesLater) startGeneratedNameGuard();
|
|
48845
49899
|
await checkDestructivePlan({
|
|
48846
49900
|
options: engine.options,
|
|
48847
49901
|
stackName,
|
|
@@ -48860,13 +49914,19 @@ async function doDeployWithPrefetch(engine, stackName, template, createOnlyPrefe
|
|
|
48860
49914
|
secretMask: () => diffLogMasker(engine.secretsRun, engine.maskingDeps(), diffResolverContext.recordedSecretValues, effectiveTemplate, parameterValues, currentState.resources)
|
|
48861
49915
|
})) engine.generatedNameGuard?.noteApprovalPrompted();
|
|
48862
49916
|
startProvenanceCapture();
|
|
48863
|
-
engine.generatedNameGuard?.recordPlannedIntents();
|
|
48864
49917
|
engine.resolver.resetPhysicalIdFallbackCount();
|
|
49918
|
+
await resolveStackInstanceId();
|
|
49919
|
+
if (idArrivesLater) {
|
|
49920
|
+
startGeneratedNameGuard();
|
|
49921
|
+
const kept = await retainedForWarning ?? [];
|
|
49922
|
+
if (kept.length > 0) engine.logger.warn(safeMsg`An earlier deployment of ${displayStackName(stackName)} kept ${String(kept.length)} ` + "resource(s) here (DeletionPolicy: Retain). This deploy does not take them back: it creates new resources under new names, as CloudFormation does. To manage a kept resource again, adopt it with 'cdkd import'.");
|
|
49923
|
+
}
|
|
49924
|
+
engine.generatedNameGuard?.recordPlannedIntents();
|
|
48865
49925
|
const progress = {
|
|
48866
49926
|
current: 0,
|
|
48867
49927
|
total: createChanges.length + updateChanges.length + deleteChanges.length
|
|
48868
49928
|
};
|
|
48869
|
-
const { state: newState, actualCounts, completedOperations } = await withProducerRegions(() => producerRegionEvidence(engine.rollbackDeps(), currentState), () => executeDeployment(engine, effectiveTemplate, currentState, changes, dag, executionLevels, stackName, outputsDigestSource, parameterValues, conditions, currentEtag, progress, migrationPending));
|
|
49929
|
+
const { state: newState, actualCounts, completedOperations } = await withProducerRegions(() => producerRegionEvidence(engine.rollbackDeps(), currentState), () => withStackScope(nameScope(), () => executeDeployment(engine, effectiveTemplate, currentState, changes, dag, executionLevels, stackName, outputsDigestSource, parameterValues, conditions, currentEtag, progress, migrationPending)));
|
|
48870
49930
|
try {
|
|
48871
49931
|
engine.stateBackend.warmConnections(stackName, engine.stackRegion, TAIL_WARM_CONNECTIONS);
|
|
48872
49932
|
} catch {}
|
|
@@ -48977,6 +50037,7 @@ var DeployEngine = class {
|
|
|
48977
50037
|
resolver;
|
|
48978
50038
|
interrupted = false;
|
|
48979
50039
|
interruptCause = null;
|
|
50040
|
+
userInterrupted = false;
|
|
48980
50041
|
absentJournalVersionPurge;
|
|
48981
50042
|
noEchoCeilingReadbackTimeoutMs = 3e4;
|
|
48982
50043
|
observedCapture;
|
|
@@ -49109,10 +50170,20 @@ var DeployEngine = class {
|
|
|
49109
50170
|
deployStateResources: () => this.deployStateResources,
|
|
49110
50171
|
interrupted: () => this.interrupted,
|
|
49111
50172
|
interruptCause: () => this.interruptCause,
|
|
50173
|
+
userInterrupted: () => this.userInterrupted,
|
|
49112
50174
|
withRetry: (...args) => this.withRetry(...args),
|
|
49113
50175
|
maskingRetryLoggerFor: (...args) => this.maskingRetryLoggerFor(...args),
|
|
49114
50176
|
inlinePolicyClaimedFor: (...args) => this.inlinePolicyClaimedFor(...args),
|
|
49115
|
-
recordEvent: (...args) => this.recordEvent(...args)
|
|
50177
|
+
recordEvent: (...args) => this.recordEvent(...args),
|
|
50178
|
+
guardedReplacementCreate: (input, create) => guardedReplacementCreate(this, input, create),
|
|
50179
|
+
generatedNameGuarded: (logicalId) => this.generatedNameGuard?.candidate(logicalId) !== void 0,
|
|
50180
|
+
rollbackRetainedCopies: (stackName) => {
|
|
50181
|
+
const reader = new DeploymentEventsReader(this.stateBackend);
|
|
50182
|
+
return loadRollbackRetainedCopies({
|
|
50183
|
+
listRuns: (s, r) => reader.listRuns(s, r),
|
|
50184
|
+
readRunEvents: (s, r, id) => reader.readRunEvents(s, r, id)
|
|
50185
|
+
}, stackName, this.stackRegion);
|
|
50186
|
+
}
|
|
49116
50187
|
};
|
|
49117
50188
|
}
|
|
49118
50189
|
resolverContextDeps() {
|
|
@@ -49164,6 +50235,7 @@ var DeployEngine = class {
|
|
|
49164
50235
|
},
|
|
49165
50236
|
absentJournalVersionPurge: () => this.absentJournalVersionPurge,
|
|
49166
50237
|
interrupted: () => this.interrupted,
|
|
50238
|
+
userInterrupted: () => this.userInterrupted,
|
|
49167
50239
|
noEchoDeps: () => this.noEchoDeps(),
|
|
49168
50240
|
recordEvent: (...args) => this.recordEvent(...args),
|
|
49169
50241
|
crossStackReadKeyNormalizer: (...args) => this.crossStackReadKeyNormalizer(...args)
|
|
@@ -49190,7 +50262,7 @@ var DeployEngine = class {
|
|
|
49190
50262
|
this.inlinePolicyWriters = /* @__PURE__ */ new Map();
|
|
49191
50263
|
this.resolver.resetPhysicalIdFallbackCount();
|
|
49192
50264
|
const ledger = ledgerForStack(this.stateBackend, stackName, this.stackRegion);
|
|
49193
|
-
return
|
|
50265
|
+
return withStackScopeBeforeStateRead(stackName, () => this.options.dryRun ? this.doDeploy(stackName, template) : withCreateTokenLedger(ledger, () => this.doDeploy(stackName, template)));
|
|
49194
50266
|
}
|
|
49195
50267
|
static maskedRecordRemedyFor = maskedRecordRemedyFor;
|
|
49196
50268
|
redactStateForPersist(state) {
|
|
@@ -49203,23 +50275,35 @@ var DeployEngine = class {
|
|
|
49203
50275
|
const noEchoScrubbed = applyNoEchoPersist(this.noEchoRun, this.noEchoDeps(), logicalId, record, withNoEchoExactEchoes(this.noEchoRun, logicalId, scrubbed), templateProps, state.resources, secrets);
|
|
49204
50276
|
resources[logicalId] = withReferenceProvenance(withConstructPath(withMaskedPropertyFingerprints(noEchoScrubbed, record.properties, templateProps, secrets, this.secretsRun.fingerprintNoEchoValues, this.secretsRun.perResourceInputFingerprints.get(logicalId)), constructPathOf(this.noEchoRun.constructPathTemplate, logicalId)), this.referenceProvenanceToPersist(logicalId, record, noEchoScrubbed, secrets));
|
|
49205
50277
|
}
|
|
49206
|
-
const
|
|
50278
|
+
const orphanEntries = state.orphans;
|
|
50279
|
+
const scrubDroppedRecord = (entry) => {
|
|
49207
50280
|
const sameResource = this.secretsRun.perResourceResolvedType.get(entry.logicalId) === entry.state.resourceType;
|
|
49208
50281
|
const orphanTemplateProps = sameResource ? this.secretsRun.perResourceTemplateProps.get(entry.logicalId) : void 0;
|
|
49209
|
-
return
|
|
50282
|
+
return withMaskedPropertyFingerprints(applyNoEchoPersist(this.noEchoRun, this.noEchoDeps(), entry.logicalId, entry.state, scrubResourceRecord(entry.state, (sameResource ? this.secretsRun.perResourceSecrets.get(entry.logicalId) : void 0) ?? /* @__PURE__ */ new Map(), orphanTemplateProps, void 0, sameGenerationClaimsOf(entry.state)), orphanTemplateProps, state.resources), entry.state.properties, orphanTemplateProps, sameResource ? this.secretsRun.perResourceSecrets.get(entry.logicalId) : void 0, sameResource ? this.secretsRun.fingerprintNoEchoValues : void 0, sameResource ? this.secretsRun.perResourceInputFingerprints.get(entry.logicalId) : void 0);
|
|
50283
|
+
};
|
|
50284
|
+
const orphans = orphanEntries?.map((entry) => ({
|
|
50285
|
+
...entry,
|
|
50286
|
+
state: scrubDroppedRecord(entry)
|
|
50287
|
+
}));
|
|
50288
|
+
const superseded = Array.isArray(state.supersededResources) ? state.supersededResources.flatMap((entry) => {
|
|
50289
|
+
if (!isSupersededResourceRecord(entry)) return [entry];
|
|
50290
|
+
if (isSupersededHeldBySameType(entry, state.resources)) return [];
|
|
50291
|
+
return [{
|
|
49210
50292
|
...entry,
|
|
49211
|
-
state:
|
|
49212
|
-
};
|
|
49213
|
-
});
|
|
50293
|
+
state: scrubDroppedRecord(entry)
|
|
50294
|
+
}];
|
|
50295
|
+
}) : void 0;
|
|
49214
50296
|
const outputs = redactOutputs(this.maskingDeps(), state.outputs);
|
|
49215
50297
|
const crossStackReads = this.redactCrossStackReads(state);
|
|
49216
|
-
const { outputReferenceProvenance: _incoming, ...rest } = state;
|
|
50298
|
+
const { outputReferenceProvenance: _incoming, supersededResources: _superseded, ...rest } = state;
|
|
49217
50299
|
const outputReferenceProvenance = this.outputReferenceProvenanceFor(state.outputs, outputs);
|
|
49218
50300
|
return {
|
|
49219
50301
|
...rest,
|
|
50302
|
+
...stackInstanceIdCarriedFrom(withoutSuperseded(state)),
|
|
49220
50303
|
resources,
|
|
49221
50304
|
outputs,
|
|
49222
50305
|
...orphans === void 0 ? {} : { orphans },
|
|
50306
|
+
...superseded === void 0 ? _superseded !== void 0 && { supersededResources: _superseded } : superseded.length > 0 && { supersededResources: superseded },
|
|
49223
50307
|
...crossStackReads,
|
|
49224
50308
|
...outputReferenceProvenance !== void 0 && { outputReferenceProvenance }
|
|
49225
50309
|
};
|
|
@@ -49292,6 +50376,7 @@ var DeployEngine = class {
|
|
|
49292
50376
|
const { parentStack, parentLogicalId, parentRegion } = this.options.parentStackInfo;
|
|
49293
50377
|
return {
|
|
49294
50378
|
...redacted,
|
|
50379
|
+
...stackInstanceIdCarriedFrom(redacted),
|
|
49295
50380
|
parentStack,
|
|
49296
50381
|
parentLogicalId,
|
|
49297
50382
|
parentRegion
|
|
@@ -49339,14 +50424,14 @@ var DeployEngine = class {
|
|
|
49339
50424
|
}
|
|
49340
50425
|
};
|
|
49341
50426
|
}
|
|
49342
|
-
async withRetry(operation, logicalId, maxRetries, initialDelayMs, provider) {
|
|
50427
|
+
async withRetry(operation, logicalId, maxRetries, initialDelayMs, provider, interruptOnlyByUser) {
|
|
49343
50428
|
if (provider?.disableOuterRetry) return operation();
|
|
49344
50429
|
return withRetry(operation, logicalId, {
|
|
49345
50430
|
...maxRetries !== void 0 && { maxRetries },
|
|
49346
50431
|
...initialDelayMs !== void 0 && { initialDelayMs },
|
|
49347
50432
|
logger: this.maskingRetryLogger(logicalId),
|
|
49348
|
-
isInterrupted: () => this.interrupted,
|
|
49349
|
-
onInterrupted: () => new InterruptedError(this.interruptCause ?? "user")
|
|
50433
|
+
isInterrupted: () => interruptOnlyByUser === true ? this.userInterrupted : this.interrupted,
|
|
50434
|
+
onInterrupted: () => new InterruptedError(interruptOnlyByUser === true ? "user" : this.interruptCause ?? "user")
|
|
49350
50435
|
});
|
|
49351
50436
|
}
|
|
49352
50437
|
maskingRetryLogger(logicalId) {
|
|
@@ -49367,5 +50452,5 @@ function sameGenerationClaimsOf(record) {
|
|
|
49367
50452
|
}
|
|
49368
50453
|
|
|
49369
50454
|
//#endregion
|
|
49370
|
-
export { DeploymentEventsStore as $, repairMalformedOrphanRecordsForReadOnly as $a, runDockerStreaming as $c, UNREADABLE_ORPHANS_CONTAINER_ROW as $i, ATOMIC_FINAL_SNAPSHOT_TYPES as $n, noEchoOutputsComparison as $o, reDisableInstanceApiTermination as $r, CrossPrefixReadError as $s, updatePartialReason as $t, inheritedProvenanceForChildDiff as A, refuseMalformedNestedChildOutputs as Aa, getBootstrapMarkerKey as Ac, producerRegionsFromState as Ai, StageLoadError as Al, bold as An, configStringRefusal as Ao, TemplateNoEchoReresolver as Ar, pathCrossesDottedKey as As, replayFailedOperations as At, conditionFingerprint as B, refuseMalformedResourceEntriesForDeploy as Ba, describeDockerExecFailure as Bc, keepsSecretReferenceToken as Bi, renderAssemblyPathEscape as Bl, createReadOnlyAttributeHealerFactory as Bn, canonicalLambdaFunctionName as Bo, unchangedBehindSecretReference as Br, provenPublicValue as Bs, recordUnderIdIsNotOwn as Bt, hasCdkAutoDeleteTag as C, malformedResourceEntriesWarning as Ca, createAssetRedirectResolver as Cc, sendableAssumeRoleCommand as Ci, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Cl, findDestructiveChanges as Cn, isWarmThroughputDecrease as Co, stringifyIfAssigned as Cr, maskSecretsInText as Cs, makeForeignHolderScan as Ct, IMPLICIT_DELETE_DEPENDENCIES as D, malformedStateRefusalMessage as Da, BOOTSTRAP_MARKER_PREFIX as Dc, envCredentialsAreAssumedRole as Di, canonicalizeRegion as Dl, getStackRecords as Dn, coerceCfnInteger as Do, isCustomResource as Dr, DYNAMIC_REFERENCE_TOKEN_SCAN as Ds, isAccessDeniedError as Dt, markRefusedBeforeApplying as E, malformedScrubResourceEntriesRefusalMessage as Ea, AssetModeResolver as Ec, callerEnvCredentials as Ei, PARTITION_TABLE as El, destroyStackRecordsView as En, coerceCfnBoolean as Eo, ccBrokenReason as Er, withoutPhysicalNameCopies as Es, chunks as Et, findNestedTemplateTreeDefect as F, refuseMalformedOrphansForOrphan as Fa, validateContainerRepoName as Fc, getAccountInfo as Fi, nullPrototypeRecord as Fl, yellow as Fn, requireConfigString as Fo, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as Fr, physicalNameCopiesOf as Fs, isJournaledOrphan as Ft, diffSecurity as G, refuseMalformedResourcePropertiesForDestroy as Ga, getDockerCmd as Gc, parseWebACLArn as Gi, resolveBucketRegion as Gl, orphanRecordsPrintingBag as Gn, canonicalCoordinates as Go, deleteSkipReason as Gr, recordProvenPublicExpression as Gs, findNestedStackTypeChanges as Gt, parentSuppliedValues as H, refuseMalformedResourceEntriesForImport as Ha, dockerSpawnEnvWithSensitive as Hc, cfnRefValueFromPhysicalId as Hi, injectAwsRegion as Hl, journaledOrphanPrintingBag as Hn, sameLambdaFunctionAddress as Ho, UNSPECIFIED_SKIP_REASON as Hr, recordMaskOnlyValuesIn as Hs, resolveReplacementOldType as Ht, isAbsoluteAssetPath as I, refuseMalformedOutputs as Ia, buildDenyExternalAccessPolicy as Ic, isImpossibleEmptyStoredAttribute as Ii, ownValue as Il, noEchoAttributeNamesOf as In, prefetchCreateOnlyPropertyPaths as Io, applyCustomResourceResponseExpiration as Ir, recordAttributeIdCopy as Is, isReplacementOrphan as It, mergeNoChangeOutputs as J, refuseMalformedResourcePropertiesForOrphan as Ja, partitionSensitiveEnv as Jc, passedParameterClassesOf as Ji, secretNamedAttributeNamesOf as Jn, maskReadbackAtCoordinates as Jo, markWaitAbandoned as Jr, isSingleDynamicReferenceToken as Js, REDACTED_DELETE_ADDRESS_SKIP_REASON as Jt, isSecretBearingReferenceString as K, refuseMalformedResourcePropertiesForDrift as Ka, isDockerClientEnvKey as Kc, withSharedDrainBudget as Ki, secretNamePrintingBag as Kn, isMarkedCoordinate as Ko, withIndeterminateGuard as Kr, wholeStringLeavesOf as Ks, getCurrentProducerRegions as Kt, listNestedTemplateRows as L, refuseMalformedOutputsForDestroy as La, buildDockerImage as Lc, carriesDynamicReference as Li, absoluteAssemblyPathEscape as Ll, noEchoComparisonForTemplate as Ln, templateResourceTypes as Lo, customResourceResponseExpirationWarning as Lr, recordPhysicalNameCopy as Ls, planFailedOps as Lt, findServiceTokenRefusals as M, refuseMalformedOrphanRecordsForDestroy as Ma, parseBootstrapMarker as Mc, coerceParameterTypedValue as Mi, defineOwnKey as Ml, gray as Mn, replayWarn as Mo, isCustomResourceType as Mr, inheritNestedStackParameterAssociations as Ms, removeProtectionTypeList as Mt, serviceTokenBlockingReason as N, refuseMalformedOrphans as Na, readBootstrapMarkerBody as Nc, isUnboundTemplateParameter as Ni, hasOwnKey as Nl, green as Nn, requireConfigArray as No, getCurrentResourceSecrets as Nr, recordNestedStackParameterExpressions as Ns, recordAfterRollbackUpdate as Nt, computeImplicitDeleteEdges as O, previewableOrphanRecords as Oa, assertAssetBucketRegion as Oc, classifyRecordedSecretRegion as Oi, derivePartitionAndUrlSuffix as Ol, withStackRecords as On, configBooleanRefusal as Oo, wouldReturnToSdkProvider as Or, dynamicReferenceTokens as Os, lookupEachName as Ot, childTemplateLoader as P, refuseMalformedOrphansForDestroy as Pa, validateAssetBucketName as Pc, parameterTypeMayLoseSecretIdentity as Pi, hasPlainPrototype$1 as Pl, red as Pn, requireConfigObject as Po, withPrintingSecrets as Pr, recoverMaskedOutput as Ps, demoteSupersededOrphans as Pt, DeploymentEventsReader as Q, refuseMalformedState as Qa, runDockerForeground as Qc, STATE_RESOURCES_MALFORMED as Qi, extractDeploymentEventError as Qn, noEchoLeavesOf as Qo, observeThenDisableInstanceApiTermination as Qr, rebuildClientForBucketRegion as Qs, updatePartialMessage as Qt, renderNestedTemplateTreeDefect as R, refuseMalformedResourceAttributesForOrphan as Ra, resolveDockerContextDirectory as Rc, carriesFetchableDynamicReference as Ri, describeFileReadFailure as Rl, noEchoExactEchoLeavesOf as Rn, describeTypeWithThrottleRetry as Ro, CloudControlProvider as Rr, splitGetAttStringForm as Rs, planRollback as Rt, S3_AUTO_DELETE_OBJECTS_TAG as S, malformedRenderedContainersWarning as Sa, buildAssetRedirectMap as Sc, isIamRoleArn as Si, uploadCfnTemplate as Sl, constructPathOf as Sn, coerceWarmThroughput as So, definedAttributes as Sr, maskSecretsInError as Ss, loadJournaledOrphans as St, getPriorAttempts as T, malformedResourcesWarning as Ta, rewriteTemplateAssetReferences as Tc, applyCallerIdentityCredentials as Ti, expectedOwnerParam as Tl, awaitInFlightSibling as Tn, toFiniteNumber as To, ProviderRegistry as Tr, withPhysicalNameCopies as Ts, formatResourceLine as Tt, readRecordedConditionVerdicts as U, refuseMalformedResourceEntriesForImportSave as Ua, finchSecretArgvRefusal as Uc, isStalePlaceholderArnAttribute as Ui, injectedAwsRegionValue as Ul, maskEventTextWithBoundBags as Un, DagBuilder as Uo, deleteIndeterminateGuards as Ur, recordNoEchoAttributeValues as Us, seedsDeleteFirstGuard as Ut, conditionInputsFrom as V, refuseMalformedResourceEntriesForDestroy as Va, describeDockerFailure as Vc, AWS_NO_VALUE as Vi, resolveAssemblyPath as Vl, completedReplayEntries as Vn, lambdaFunctionNameForMask as Vo, RollbackInlinePolicyWriters as Vr, recordMaskOnlyValue as Vs, replacementNeverSwapped as Vt, withResourceDeadline as W, refuseMalformedResourceEntriesForOrphan as Wa, formatDockerLoginError as Wc, refStateLookupFromResource as Wi, clearBucketRegionCache as Wl, namingSecretsWithRecordedNoEcho as Wn, TemplateParser as Wo, deleteLeftInPlace as Wr, recordNoEchoParameterFreshValue as Ws, orphanNeedsIdentity as Wt, makeSiblingClaimReader as X, refuseMalformedResourcesForDestroy as Xa, redactedCause as Xc, JSON_LISTING_HOLE_VALUE as Xi, stateSecretNameNeedles as Xn, maskedLeafCoordinatesOf as Xo, ec2InstanceProtectionSite as Xr, isLockInfoExpired as Xs, redactedDeleteAddressFields as Xt, makeCanonicalizePropertiesFn as Y, refuseMalformedResourcesForDeploy as Ya, redactDockerArgvValues as Yc, declaresNoEcho as Yi, secretNamedRecordNeedles as Yn, maskWholeValue as Yo, disableInstanceApiTermination as Yr, LockManager as Ys, isRedactedRecordedValue as Yt, planOrphanAdoption as Z, refuseMalformedResourcesForExport as Za, redactedDockerCause as Zc, STATE_REGION_DIVERGED as Zi, storedSecretNameNeedles as Zn, noEchoCoordinatesOf as Zo, isTerminationProtectionPropagationError as Zr, S3StateBackend as Zs, redactedDeleteAddressSkip as Zt, deleteTableWithIndexBusyRetry as _, malformedOrphanRowsKeptWarning as _a, shouldRetainResource as _c, recordedReferenceRegions as _i, ssmResolvedValueType as _l, isExportAliasCollision as _n, MULTI_REGION_RECREATE_BLOCKED_TYPES as _o, planTagDiff as _r, recordLogOnlyValue as _s, deleteJournaledOrphans as _t, isProtectionValueActive as a, hasReadableOutputs as aa, splitImportedOps as ac, isSettledInstanceState as ai, getDefaultStateBucketName as al, displayTextOrWithheld as an, unpreviewableOrphanRecords as ao, isFinalSnapshotError as ar, liveMatchesUnresolvedTokenFrame as as, displacedOpClause as at, waitForIndexesSettled as b, malformedOutputsRefusalMessage as ba, stringifyValue as bc, assertSendableRoleArn as bi, MIGRATE_TMP_PREFIX as bl, DEFAULT_RESOURCE_WARN_AFTER_MS as bn, renderStatefulReason as bo, tagMapAsList as br, createSecretMasker as bs, isHandledOrphan as bt, DynamoDBGlobalTableProvider as c, isReadableResourceEntry as ca, exportNamesCarriedFrom as cc, s3BucketDualStackDomainName as ci, resolveApp as cl, secretBearingStateKeyWarning as cn, withheldAccountClause as co, earliestDefined as cr, recordReferenceProvenanceEntry as cs, getNestedRevertRun as ct, compensateRemovedDeletionProtection as d, malformedExportSourceWarning as da, hasUnverifiableParameterRefusal as dc, resolveDynamicReferences as di, resolveSkipPrefix as dl, exportNameNoEchoParameters as dn, unwrittenCreateOnlyReplacement as do, withCreateTokenLedger as dr, createUnionSecretMasker as ds, revertNestedChildFromJournal as dt, UNREADABLE_RESOURCES_MAP_ROW as ea, CrossPrefixScanCache as ec, reEnableInstanceApiTermination as ei, warnFinchArgvExposure as el, computeParameterTaint as en, repairMalformedOrphansForReadOnly as eo, PRE_DELETE_SNAPSHOT_TYPES as er, passedNoEchoParametersOf as es, pendingRequestCount as et, deleteBudgetKey as f, malformedLocalOutputsWarning as fa, importableOutputKeys as fc, producerLookupOver as fi, resolveStateBucketWithDefault as fl, exportNameSecretExposure as fn, withoutSilentDropProperties as fo, acquireIdempotencyToken as fr, hasMaskableValues as fs, revertedNestedRowIds as ft, INDEX_SETTLE_POLL_INTERVAL_MS as g, malformedOrphanRecordsWarning as ga, orphansCarriedFrom as gc, recordedOutputReferenceRegions as gi, warnDeprecatedNoPrefixCliFlag as gl, collectPublishedOutputNames as gn, shownType as go, DBPROXY_TAG_OPTIONS as gr, recordLogOnlyParameterValue as gs, withNestedStackContext as gt, DELETE_INDEX_WAIT_PROCEED_NOTE as h, malformedOrphanRecordsRefusalMessage as ha, orphansAfterRollback as hc, outputReferenceProvenanceOf as hi, stateBucketExistenceConfirmed as hl, collectDeclaredOutputNames as hn, findReplacedReadersOfRecreateTargets as ho, DBPROXY_TAGS_WHAT as hr, printingCorpusOf as hs, getCurrentNestedStackContext as ht, PROTECTION_PROPERTY_BY_TYPE as i, hasReadableOrphans as ia, isNotImplemented as ic, poisonRenderedSpellingsCollidingIn as ii, synthesisStatusMessage as il, WITHHELD_NAME_DISPLAY as in, repairMalformedResourcesForReadOnly as io, effectiveDeletionPolicy as ir, valueAtCoordinate as is, NESTED_PENDING_PARENT_REASON as it, deferredServiceTokenWarning as j, refuseMalformedOrphanRecords as ja, isCrossRegionRedirect as jc, regionLessSecretName as ji, processStackMessages as jl, cyan as jn, readConfigString as jo, readsNoEchoDeleteValues as jr, identityKeyFor as js, replayRollback as jt, crossStackOutputProvenanceSource as k, refuseDivergentRecordRegionForDestroy as ka, ensureAssetStorage as kc, classifyReplaySecretRegion as ki, AssemblyReader as kl, replacedDeleteFailureVerdict as kn, configIntegerRefusal as ko, waitForLambdaFunctionActive as kr, isUncertifiedBaselineMaskPosition as ks, withApiLimit as kt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as l, malformedDriftResourcePropertiesWarning as la, hasReadableExportSet as lc, s3BucketRegionalDomainName as li, resolveAutoAssetStorage as ll, secretSafeKeyDisplay as ln, findActionableSilentDrops as lo, ledgerForStack as lr, snapshotPassProvenance as ls, nestedChildStackName as lt, resolveDynamoDbDeleteBudgetMs as m, malformedLocalResourcesWarning as ma, isReadableBag as mc, keepHeldTokenProvenance as mi, resolveUseCdkBootstrapAssets as ml, noEchoParameterValueSeed as mn, hasNoCloudControlHandlers as mo, markDeleteStarted as mr, logOnlyValueCount as ms, collectNestedChildUnaddressed as mt, recordedProtectionEvidence as n, deployRefusesOrphanRowsReason as na, crossPrefixDeniedWarning as nc, INTRINSIC_KEYS as ni, getDockerImageBySourceHash as nl, reachableDivergentParameters as nn, repairMalformedResourceEntriesForReadOnly as no, ccRoutedFinalSnapshotError as nr, readsNoEchoSource as ns, keptForReadoption as nt, perType as o, hasReadableResources as oa, acceptedCreateOnlyDropsOf as oc, s3BucketArn as oi, getLegacyStateBucketName as ol, exportAliasCollisionScrubWarning as on, unreadableOrphanRecords as oo, refusesFinalSnapshot as or, markSameGenerationBag as os, displacedPhysicalIdShown as ot, resolveDynamoDbDeleteBudgetClock as p, malformedLocalResourceEntriesWarning as pa, importableOutputs as pc, refuseUnreadableCdkCrossAccountRefs as pi, resolveStateBucketWithDefaultAndSource as pl, isWholeDynamicReferenceValue as pn, NO_CC_HANDLERS_REASON as po, isRefusedByName as pr, literalSplitDelimitersOf as ps, withNestedRevertRun as pt, keptWholeReasonText as q, refuseMalformedResourcePropertiesForExport as qa, isMalformedEnvKey as qc, parameterInputsFor as qi, secretNamePrintingBags as qn, maskAtCoordinates as qo, isWaitAbandonedError as qr, WHOLE_DYNAMIC_REFERENCE_PATTERN as qs, inheritProducerRegions as qt, recordedProtectionNote as r, displayLogicalId as ra, isAccessDenied$1 as rc, IntrinsicFunctionResolver as ri, Synthesizer as rl, resourcesNamingDeclaredParameter as rn, repairMalformedResourcePropertiesForReadOnly as ro, createPreDeleteFinalSnapshot as rr, recordedNoEchoValuesOf as rs, recordRetainedForReadoption as rt, readProtection as s, isReadableOrphanRecord as sa, describeRegionValueKind as sc, s3BucketDomainName as si, loadCdkJson as sl, secretBearing as sn, unreadableResourceEntries as so, unsupportedFinalSnapshotError as sr, redactForState as ss, dropSettledNestedJournals as st, DeployEngine as t, accountArgs as ta, applyCrossPrefixScan as tc, DiffCalculator as ti, AssetManifestLoader as tl, namesAnyDeclaredParameter as tn, repairMalformedOutputsForReadOnly as to, buildFinalSnapshotIdentifier as tr, readbackPathFor as ts, resolvePendingCloudControlRequests as tt, beginDeleteWait as u, malformedExportNamesWarning as ua, hasReasonlessBaselineRefusal as uc, s3BucketWebsiteUrl as ui, resolveCaptureObservedState as ul, carriedExportAliasExposure as un, findSilentDropProperties as uo, reserveStackCreateToken as ur, carryLogOnlyValues as us, recordDisplacedSkips as ut, maskedLogger as v, malformedOrphansRefusalMessage as va, AssetPublisher as vc, applyRoleArnIfSet as vi, CFN_TEMPLATE_BODY_LIMIT as vl, bindingSkippedOutputs as vn, isStatefulRecreateTargetForReplace as vo, readTagList as vr, shareLogOnlyValues as vs, dropFailedCommands as vt, isTruthyCfnBoolean as w, malformedResourcePropertiesWarning as wa, loadPublishableAssetManifest as wc, AWS_CREDENTIAL_ENV_KEYS as wi, decodeListingKey as wl, formatDestructiveChange as wn, toCfnInteger as wo, CC_BROKEN_REASON as wr, scrubResourceRecord as ws, sameJournaledOrphans as wt, ECR_AUTO_DELETE_IMAGES_TAG as x, malformedOutputsWarning as xa, WorkGraph as xc, explicitRoleArnOrThrow as xi, findLargeInlineResources as xl, maskingRetryLogger as xn, WARM_THROUGHPUT_MEMBERS as xo, tagPlanWarning as xr, errorCauseChain as xs, journaledOrphanLines as xt, relayedIndexBusyDelete as y, malformedOrphansWarning as ya, isSensitiveAttributeName as yc, assertFlagRoleArn as yi, CFN_TEMPLATE_URL_LIMIT as yl, DEFAULT_RESOURCE_TIMEOUT_MS as yn, isStatefulRecreateTargetSync as yo, refuseMalformedDesiredTags as yr, unionOfSecretBags as ys, dropFailedHint as yt, templateIdentity as z, refuseMalformedResourceEntries as za, describeDockerCapturedOutput as zc, isNamelessDynamicReferenceError as zi, displayAssemblyPath as zl, noEchoParameterNamesOf as zn, withRetry as zo, slowCcOperationTimeoutMs as zr, carriesSecretMask as zs, recheckFailedPlan as zt };
|
|
49371
|
-
//# sourceMappingURL=deploy-engine-
|
|
50455
|
+
export { resolvePendingCloudControlRequests as $, refuseMalformedOutputsForDestroy as $a, validateAssetBucketName as $c, carriesDynamicReference as $i, hasPlainPrototype$1 as $l, noEchoParameterNamesOf as $n, templateResourceTypes as $o, customResourceResponseExpirationWarning as $r, recordPhysicalNameCopy as $s, nameGenerationHighWaterOf as $t, inheritedProvenanceForChildDiff as A, malformedLocalResourcesWarning as Aa, importableOutputKeys as Ac, keepHeldTokenProvenance as Ai, resolveSkipPrefix as Al, destroyStackRecordsView as An, hasNoCloudControlHandlers as Ao, markDeleteStarted as Ar, logOnlyValueCount as As, removeProtectionTypeList as At, conditionFingerprint as B, malformedResourcePropertiesWarning as Ba, WorkGraph as Bc, AWS_CREDENTIAL_ENV_KEYS as Bi, findLargeInlineResources as Bl, addSuperseded as Bn, toCfnInteger as Bo, CC_BROKEN_REASON as Br, scrubResourceRecord as Bs, resolveReplacementOldType as Bt, hasCdkAutoDeleteTag as C, isReadableOrphanRecord as Ca, splitImportedOps as Cc, s3BucketDomainName as Ci, synthesisStatusMessage as Cl, DEFAULT_RESOURCE_TIMEOUT_MS as Cn, unreadableResourceEntries as Co, reserveStackCreateToken as Cr, redactForState as Cs, formatResourceLine as Ct, IMPLICIT_DELETE_DEPENDENCIES as D, malformedExportSourceWarning as Da, hasReadableExportSet as Dc, resolveDynamicReferences as Di, resolveApp as Dl, findDestructiveChanges as Dn, unwrittenCreateOnlyReplacement as Do, DeploymentEventsStore as Dr, createUnionSecretMasker as Ds, withApiLimit as Dt, markRefusedBeforeApplying as E, malformedExportNamesWarning as Ea, exportNamesCarriedFrom as Ec, s3BucketWebsiteUrl as Ei, loadCdkJson as El, constructPathOf as En, findSilentDropProperties as Eo, DeploymentEventsReader as Er, carryLogOnlyValues as Es, lookupEachName as Et, findNestedTemplateTreeDefect as F, malformedOrphansWarning as Fa, shouldRetainResource as Fc, assertFlagRoleArn as Fi, warnDeprecatedNoPrefixCliFlag as Fl, cyan as Fn, isStatefulRecreateTargetSync as Fo, refuseMalformedDesiredTags as Fr, unionOfSecretBags as Fs, planFailedOps as Ft, diffSecurity as G, refuseDivergentRecordRegionForDestroy as Ga, AssetModeResolver as Gc, classifyReplaySecretRegion as Gi, PARTITION_TABLE as Gl, supersededAfterRollback as Gn, configIntegerRefusal as Go, waitForLambdaFunctionActive as Gr, isUncertifiedBaselineMaskPosition as Gs, inheritProducerRegions as Gt, parentSuppliedValues as H, malformedScrubResourceEntriesRefusalMessage as Ha, createAssetRedirectResolver as Hc, callerEnvCredentials as Hi, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Hl, holdsSupersededResources as Hn, coerceCfnBoolean as Ho, ccBrokenReason as Hr, withoutPhysicalNameCopies as Hs, orphanNeedsIdentity as Ht, isAbsoluteAssetPath as I, malformedOutputsRefusalMessage as Ia, stackInstanceIdCarriedFrom as Ic, assertSendableRoleArn as Ii, ssmResolvedValueType as Il, gray as In, renderStatefulReason as Io, tagMapAsList as Ir, createSecretMasker as Is, planRollback as It, mergeNoChangeOutputs as J, refuseMalformedOrphanRecordsForDestroy as Ja, ensureAssetStorage as Jc, coerceParameterTypedValue as Ji, AssemblyReader as Jl, supersededResourcesOf as Jn, replayWarn as Jo, isCustomResourceType as Jr, inheritNestedStackParameterAssociations as Js, redactedDeleteAddressFields as Jt, isSecretBearingReferenceString as K, refuseMalformedNestedChildOutputs as Ka, BOOTSTRAP_MARKER_PREFIX as Kc, producerRegionsFromState as Ki, canonicalizeRegion as Kl, supersededHeldByOtherTypeWarning as Kn, configStringRefusal as Ko, TemplateNoEchoReresolver as Kr, pathCrossesDottedKey as Ks, REDACTED_DELETE_ADDRESS_SKIP_REASON as Kt, listNestedTemplateRows as L, malformedOutputsWarning as La, AssetPublisher as Lc, explicitRoleArnOrThrow as Li, CFN_TEMPLATE_BODY_LIMIT as Ll, green as Ln, WARM_THROUGHPUT_MEMBERS as Lo, tagPlanWarning as Lr, errorCauseChain as Ls, recheckFailedPlan as Lt, findServiceTokenRefusals as M, malformedOrphanRecordsWarning as Ma, isReadableBag as Mc, recordedOutputReferenceRegions as Mi, resolveStateBucketWithDefaultAndSource as Ml, withStackRecords as Mn, shownType as Mo, DBPROXY_TAG_OPTIONS as Mr, recordLogOnlyParameterValue as Ms, demoteSupersededOrphans as Mt, serviceTokenBlockingReason as N, malformedOrphanRowsKeptWarning as Na, orphansAfterRollback as Nc, recordedReferenceRegions as Ni, resolveUseCdkBootstrapAssets as Nl, replacedDeleteFailureVerdict as Nn, MULTI_REGION_RECREATE_BLOCKED_TYPES as No, planTagDiff as Nr, recordLogOnlyValue as Ns, isJournaledOrphan as Nt, computeImplicitDeleteEdges as O, malformedLocalOutputsWarning as Oa, hasReasonlessBaselineRefusal as Oc, producerLookupOver as Oi, resolveAutoAssetStorage as Ol, formatDestructiveChange as On, withoutSilentDropProperties as Oo, extractDeploymentEventError as Or, hasMaskableValues as Os, replayFailedOperations as Ot, childTemplateLoader as P, malformedOrphansRefusalMessage as Pa, orphansCarriedFrom as Pc, applyRoleArnIfSet as Pi, stateBucketExistenceConfirmed as Pl, bold as Pn, isStatefulRecreateTargetForReplace as Po, readTagList as Pr, shareLogOnlyValues as Ps, isReplacementOrphan as Pt, pendingRequestCount as Q, refuseMalformedOutputs as Qa, readBootstrapMarkerBody as Qc, isImpossibleEmptyStoredAttribute as Qi, hasOwnKey as Ql, noEchoExactEchoLeavesOf as Qn, prefetchCreateOnlyPropertyPaths as Qo, applyCustomResourceResponseExpiration as Qr, recordAttributeIdCopy as Qs, nameGenerationCarriedFrom as Qt, renderNestedTemplateTreeDefect as R, malformedRenderedContainersWarning as Ra, isSensitiveAttributeName as Rc, isIamRoleArn as Ri, CFN_TEMPLATE_URL_LIMIT as Rl, red as Rn, coerceWarmThroughput as Ro, definedAttributes as Rr, maskSecretsInError as Rs, recordUnderIdIsNotOwn as Rt, S3_AUTO_DELETE_OBJECTS_TAG as S, hasReadableResources as Sa, withStackInstanceIdWithheld as Sc, s3BucketArn as Si, Synthesizer as Sl, bindingSkippedOutputs as Sn, unreadableOrphanRecords as So, ledgerForStack as Sr, markSameGenerationBag as Ss, sameJournaledOrphans as St, getPriorAttempts as T, malformedDriftResourcePropertiesWarning as Ta, describeRegionValueKind as Tc, s3BucketRegionalDomainName as Ti, getLegacyStateBucketName as Tl, maskingRetryLogger as Tn, findActionableSilentDrops as To, acquireIdempotencyToken as Tr, snapshotPassProvenance as Ts, isAccessDeniedError as Tt, readRecordedConditionVerdicts as U, malformedStateRefusalMessage as Ua, loadPublishableAssetManifest as Uc, envCredentialsAreAssumedRole as Ui, decodeListingKey as Ul, isSupersededResourceRecord as Un, coerceCfnInteger as Uo, isCustomResource as Ur, DYNAMIC_REFERENCE_TOKEN_SCAN as Us, findNestedStackTypeChanges as Ut, conditionInputsFrom as V, malformedResourcesWarning as Va, buildAssetRedirectMap as Vc, applyCallerIdentityCredentials as Vi, uploadCfnTemplate as Vl, deleteSupersededEntry as Vn, toFiniteNumber as Vo, ProviderRegistry as Vr, withPhysicalNameCopies as Vs, seedsDeleteFirstGuard as Vt, withResourceDeadline as W, previewableOrphanRecords as Wa, rewriteTemplateAssetReferences as Wc, classifyRecordedSecretRegion as Wi, expectedOwnerParam as Wl, removeSuperseded as Wn, configBooleanRefusal as Wo, wouldReturnToSdkProvider as Wr, dynamicReferenceTokens as Ws, getCurrentProducerRegions as Wt, makeSiblingClaimReader as X, refuseMalformedOrphansForDestroy as Xa, isCrossRegionRedirect as Xc, parameterTypeMayLoseSecretIdentity as Xi, processStackMessages as Xl, noEchoAttributeNamesOf as Xn, requireConfigObject as Xo, withPrintingSecrets as Xr, recoverMaskedOutput as Xs, updatePartialMessage as Xt, makeCanonicalizePropertiesFn as Y, refuseMalformedOrphans as Ya, getBootstrapMarkerKey as Yc, isUnboundTemplateParameter as Yi, StageLoadError as Yl, withoutSuperseded as Yn, requireConfigArray as Yo, getCurrentResourceSecrets as Yr, recordNestedStackParameterExpressions as Ys, redactedDeleteAddressSkip as Yt, planOrphanAdoption as Z, refuseMalformedOrphansForOrphan as Za, parseBootstrapMarker as Zc, getAccountInfo as Zi, defineOwnKey as Zl, noEchoComparisonForTemplate as Zn, requireConfigString as Zo, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as Zr, physicalNameCopiesOf as Zs, updatePartialReason as Zt, deleteTableWithIndexBusyRetry as _, accountArgs as _a, applyCrossPrefixScan as _c, DiffCalculator as _i, runDockerForeground as _l, isWholeDynamicReferenceValue as _n, repairMalformedOutputsForReadOnly as _o, effectiveDeletionPolicy as _r, readbackPathFor as _s, dropFailedHint as _t, isProtectionValueActive as a, isStalePlaceholderArnAttribute as aa, recordNoEchoAttributeValues as ac, deleteIndeterminateGuards as ai, describeDockerExecFailure as al, namesAnyDeclaredParameter as an, refuseMalformedResourceEntriesForImportSave as ao, orphanRecordsPrintingBag as ar, DagBuilder as as, dropSettledNestedJournals as at, renderAssemblyPathEscape as au, waitForIndexesSettled as b, hasReadableOrphans as ba, isNotImplemented as bc, poisonRenderedSpellingsCollidingIn as bi, AssetManifestLoader as bl, collectPublishedOutputNames as bn, repairMalformedResourcesForReadOnly as bo, unsupportedFinalSnapshotError as br, valueAtCoordinate as bs, loadJournaledOrphans as bt, DynamoDBGlobalTableProvider as c, withSharedDrainBudget as ca, wholeStringLeavesOf as cc, withIndeterminateGuard as ci, finchSecretArgvRefusal as cl, WITHHELD_NAME_DISPLAY as cn, refuseMalformedResourcePropertiesForDrift as co, secretNamedAttributeNamesOf as cr, isMarkedCoordinate as cs, recordDisplacedSkips as ct, injectedAwsRegionValue as cu, compensateRemovedDeletionProtection as d, declaresNoEcho as da, LockManager as dc, disableInstanceApiTermination as di, isDockerClientEnvKey as dl, secretBearing as dn, refuseMalformedResourcesForDeploy as do, storedSecretNameNeedles as dr, maskWholeValue as ds, withNestedRevertRun as dt, carriesFetchableDynamicReference as ea, splitGetAttStringForm as ec, CloudControlProvider as ei, validateContainerRepoName as el, nameScopeOf as en, refuseMalformedResourceAttributesForOrphan as eo, createReadOnlyAttributeHealerFactory as er, describeTypeWithThrottleRetry as es, keptForRetainedRecord as et, nullPrototypeRecord as eu, deleteBudgetKey as f, JSON_LISTING_HOLE_VALUE as fa, isLockInfoExpired as fc, ec2InstanceProtectionSite as fi, isMalformedEnvKey as fl, secretBearingStateKeyWarning as fn, refuseMalformedResourcesForDestroy as fo, ATOMIC_FINAL_SNAPSHOT_TYPES as fr, maskedLeafCoordinatesOf as fs, collectNestedChildUnaddressed as ft, INDEX_SETTLE_POLL_INTERVAL_MS as g, UNREADABLE_RESOURCES_MAP_ROW as ga, CrossPrefixScanCache as gc, reEnableInstanceApiTermination as gi, redactedDockerCause as gl, exportNameSecretExposure as gn, repairMalformedOrphansForReadOnly as go, createPreDeleteFinalSnapshot as gr, passedNoEchoParametersOf as gs, dropFailedCommands as gt, DELETE_INDEX_WAIT_PROCEED_NOTE as h, UNREADABLE_ORPHANS_CONTAINER_ROW as ha, CrossPrefixReadError as hc, reDisableInstanceApiTermination as hi, redactedCause as hl, exportNameNoEchoParameters as hn, repairMalformedOrphanRecordsForReadOnly as ho, ccRoutedFinalSnapshotError as hr, noEchoOutputsComparison as hs, deleteJournaledOrphans as ht, PROTECTION_PROPERTY_BY_TYPE as i, cfnRefValueFromPhysicalId as ia, recordMaskOnlyValuesIn as ic, UNSPECIFIED_SKIP_REASON as ii, describeDockerCapturedOutput as il, computeParameterTaint as in, refuseMalformedResourceEntriesForImport as io, namingSecretsWithRecordedNoEcho as ir, sameLambdaFunctionAddress as is, displacedPhysicalIdShown as it, displayAssemblyPath as iu, deferredServiceTokenWarning as j, malformedOrphanRecordsRefusalMessage as ja, importableOutputs as jc, outputReferenceProvenanceOf as ji, resolveStateBucketWithDefault as jl, getStackRecords as jn, findReplacedReadersOfRecreateTargets as jo, DBPROXY_TAGS_WHAT as jr, printingCorpusOf as js, recordAfterRollbackUpdate as jt, crossStackOutputProvenanceSource as k, malformedLocalResourceEntriesWarning as ka, hasUnverifiableParameterRefusal as kc, refuseUnreadableCdkCrossAccountRefs as ki, resolveCaptureObservedState as kl, awaitInFlightSibling as kn, NO_CC_HANDLERS_REASON as ko, isRefusedByName as kr, literalSplitDelimitersOf as ks, replayRollback as kt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as l, parameterInputsFor as la, WHOLE_DYNAMIC_REFERENCE_PATTERN as lc, isWaitAbandonedError as li, formatDockerLoginError as ll, displayTextOrWithheld as ln, refuseMalformedResourcePropertiesForExport as lo, secretNamedRecordNeedles as lr, maskAtCoordinates as ls, revertNestedChildFromJournal as lt, clearBucketRegionCache as lu, resolveDynamoDbDeleteBudgetMs as m, STATE_RESOURCES_MALFORMED as ma, rebuildClientForBucketRegion as mc, observeThenDisableInstanceApiTermination as mi, redactDockerArgvValues as ml, carriedExportAliasExposure as mn, refuseMalformedState as mo, buildFinalSnapshotIdentifier as mr, noEchoLeavesOf as ms, withNestedStackContext as mt, recordedProtectionEvidence as n, keepsSecretReferenceToken as na, provenPublicValue as nc, unchangedBehindSecretReference as ni, buildDockerImage as nl, retiredNameGenerationsAfter as nn, refuseMalformedResourceEntriesForDeploy as no, journaledOrphanPrintingBag as nr, canonicalLambdaFunctionName as ns, NESTED_PENDING_PARENT_REASON as nt, absoluteAssemblyPathEscape as nu, perType as o, refStateLookupFromResource as oa, recordNoEchoParameterFreshValue as oc, deleteLeftInPlace as oi, describeDockerFailure as ol, reachableDivergentParameters as on, refuseMalformedResourceEntriesForOrphan as oo, secretNamePrintingBag as or, TemplateParser as os, getNestedRevertRun as ot, resolveAssemblyPath as ou, resolveDynamoDbDeleteBudgetClock as p, STATE_REGION_DIVERGED as pa, S3StateBackend as pc, isTerminationProtectionPropagationError as pi, partitionSensitiveEnv as pl, secretSafeKeyDisplay as pn, refuseMalformedResourcesForExport as po, PRE_DELETE_SNAPSHOT_TYPES as pr, noEchoCoordinatesOf as ps, getCurrentNestedStackContext as pt, keptWholeReasonText as q, refuseMalformedOrphanRecords as qa, assertAssetBucketRegion as qc, regionLessSecretName as qi, derivePartitionAndUrlSuffix as ql, supersededHolderOf as qn, readConfigString as qo, readsNoEchoDeleteValues as qr, identityKeyFor as qs, isRedactedRecordedValue as qt, recordedProtectionNote as r, AWS_NO_VALUE as ra, recordMaskOnlyValue as rc, RollbackInlinePolicyWriters as ri, resolveDockerContextDirectory as rl, retiredNameGenerationsLeaving as rn, refuseMalformedResourceEntriesForDestroy as ro, maskEventTextWithBoundBags as rr, lambdaFunctionNameForMask as rs, displacedOpClause as rt, describeFileReadFailure as ru, readProtection as s, parseWebACLArn as sa, recordProvenPublicExpression as sc, deleteSkipReason as si, dockerSpawnEnvWithSensitive as sl, resourcesNamingDeclaredParameter as sn, refuseMalformedResourcePropertiesForDestroy as so, secretNamePrintingBags as sr, canonicalCoordinates as ss, nestedChildStackName as st, injectAwsRegion as su, DeployEngine as t, isNamelessDynamicReferenceError as ta, carriesSecretMask as tc, slowCcOperationTimeoutMs as ti, buildDenyExternalAccessPolicy as tl, retiredAfterRollback as tn, refuseMalformedResourceEntries as to, completedReplayEntries as tr, withRetry as ts, recordRetainedForReadoption as tt, ownValue as tu, beginDeleteWait as u, passedParameterClassesOf as ua, isSingleDynamicReferenceToken as uc, markWaitAbandoned as ui, getDockerCmd as ul, exportAliasCollisionScrubWarning as un, refuseMalformedResourcePropertiesForOrphan as uo, stateSecretNameNeedles as ur, maskReadbackAtCoordinates as us, revertedNestedRowIds as ut, resolveBucketRegion as uu, maskedLogger as v, deployRefusesOrphanRowsReason as va, crossPrefixDeniedWarning as vc, INTRINSIC_KEYS as vi, runDockerStreaming as vl, noEchoParameterValueSeed as vn, repairMalformedResourceEntriesForReadOnly as vo, isFinalSnapshotError as vr, readsNoEchoSource as vs, isHandledOrphan as vt, isTruthyCfnBoolean as w, isReadableResourceEntry as wa, acceptedCreateOnlyDropsOf as wc, s3BucketDualStackDomainName as wi, getDefaultStateBucketName as wl, DEFAULT_RESOURCE_WARN_AFTER_MS as wn, withheldAccountClause as wo, withCreateTokenLedger as wr, recordReferenceProvenanceEntry as ws, chunks as wt, ECR_AUTO_DELETE_IMAGES_TAG as x, hasReadableOutputs as xa, stackInstanceIdOf as xc, isSettledInstanceState as xi, getDockerImageBySourceHash as xl, isExportAliasCollision as xn, unpreviewableOrphanRecords as xo, earliestDefined as xr, liveMatchesUnresolvedTokenFrame as xs, makeForeignHolderScan as xt, relayedIndexBusyDelete as y, displayLogicalId as ya, isAccessDenied$1 as yc, IntrinsicFunctionResolver as yi, warnFinchArgvExposure as yl, collectDeclaredOutputNames as yn, repairMalformedResourcePropertiesForReadOnly as yo, refusesFinalSnapshot as yr, recordedNoEchoValuesOf as ys, journaledOrphanLines as yt, templateIdentity as z, malformedResourceEntriesWarning as za, stringifyValue as zc, sendableAssumeRoleCommand as zi, MIGRATE_TMP_PREFIX as zl, yellow as zn, isWarmThroughputDecrease as zo, stringifyIfAssigned as zr, maskSecretsInText as zs, replacementNeverSwapped as zt };
|
|
50456
|
+
//# sourceMappingURL=deploy-engine-CYVt2NQR.js.map
|